<commit_before>/*
 * BackwardChainer.cc
 *
 * Copyright (C) 2014-2017 OpenCog Foundation
 *
 * Authors: Misgana Bayetta <misgana.bayetta@gmail.com>  October 2014
 *          William Ma <https://github.com/williampma>
 *          Nil Geisweiller 2016-2017
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <random>

#include <boost/range/algorithm/lower_bound.hpp>

#include <opencog/util/random.h>

#include <opencog/atomutils/FindUtils.h>
#include <opencog/atomutils/Substitutor.h>
#include <opencog/atomutils/Unify.h>
#include <opencog/atomutils/TypeUtils.h>
#include <opencog/atoms/pattern/PatternLink.h>
#include <opencog/atoms/pattern/BindLink.h>

#include <opencog/query/BindLinkAPI.h>

#include "BackwardChainer.h"
#include "BackwardChainerPMCB.h"
#include "../URELogger.h"

using namespace opencog;

BackwardChainer::BackwardChainer(AtomSpace& as, const Handle& rbs,
                                 const Handle& target,
                                 const Handle& vardecl,
                                 AtomSpace* trace_as,
                                 AtomSpace* control_as,
                                 const Handle& focus_set, // TODO:
                                                          // support
                                                          // focus_set
                                 const BITNodeFitness& bitnode_fitness,
                                 const AndBITFitness& andbit_fitness)
	: _as(as), _configReader(as, rbs),
	  _bit(as, target, vardecl, bitnode_fitness),
	  _andbit_fitness(andbit_fitness),
	  _trace_recorder(trace_as),
	  _control(_configReader.get_rules(), _bit, control_as),
	  _rules(_control.rules),
	  _iteration(0), _last_expansion_andbit(nullptr)
{
	// Record the target in the trace atomspace
	_trace_recorder.target(target);
}

UREConfigReader& BackwardChainer::get_config()
{
	return _configReader;
}

const UREConfigReader& BackwardChainer::get_config() const
{
	return _configReader;
}

void BackwardChainer::do_chain()
{
	ure_logger().debug("Start Backward Chaining");
	LAZY_URE_LOG_DEBUG << "With rule set:" << std::endl << oc_to_string(_rules);

	while (not termination())
	{
		do_step();
	}

	LAZY_URE_LOG_DEBUG << "Finished Backward Chaining with solutions:"
	                   << std::endl << get_results()->toString();
}

void BackwardChainer::do_step()
{
	ure_logger().debug("Iteration %d", _iteration);
	_iteration++;

	expand_bit();
	fulfill_bit();
	reduce_bit();
}

bool BackwardChainer::termination()
{
	return _configReader.get_maximum_iterations() <= _iteration;
}

Handle BackwardChainer::get_results() const
{
	HandleSeq results(_results.begin(), _results.end());
	return _as.add_link(SET_LINK, results);
}

void BackwardChainer::expand_meta_rules()
{
	// This is kinda of hack before meta rules are fully supported by
	// the Rule class.
	size_t rules_size = _rules.size();
	_rules.expand_meta_rules(_as);

	// If the rule set has changed we need to reset the exhausted
	// flags.
	if (rules_size != _rules.size()) {
		_bit.reset_exhausted_flags();
		ure_logger().debug() << "The rule set has gone from "
		                     << rules_size << " rules to " << _rules.size()
		                     << ". All exhausted flags have been reset.";
	}
}

void BackwardChainer::expand_bit()
{
	// Expand meta rules, before they are fully supported
	expand_meta_rules();

	// Reset _last_expansion_fcs
	_last_expansion_andbit = nullptr;

	if (_bit.empty()) {
		_last_expansion_andbit = _bit.init();
		// Record the initial and-BIT in the trace atomspace
		_trace_recorder.andbit(*_last_expansion_andbit);
	} else {
		// Select an FCS (i.e. and-BIT) and expand it
		AndBIT* andbit = select_expansion_andbit();
		LAZY_URE_LOG_DEBUG << "Selected and-BIT for expansion:" << std::endl
		                   << andbit->to_string();
		expand_bit(*andbit);
	}
}

void BackwardChainer::expand_bit(AndBIT& andbit)
{
	// Select leaf
	BITNode* bitleaf = andbit.select_leaf();
	if (bitleaf) {
		LAZY_URE_LOG_DEBUG << "Selected BIT-node for expansion:" << std::endl
		                   << bitleaf->to_string();
	} else {
		ure_logger().debug() << "All BIT-nodes of this and-BIT are exhausted "
		                     << "(or possibly fulfilled). Abort expansion.";
		andbit.exhausted = true;
		return;
	}

	// Select rule for expansion
	RuleSelection rule_sel = _control.select_rule(andbit, *bitleaf);
	Rule rule(rule_sel.first.first);
	Unify::TypedSubstitution ts(rule_sel.first.second);
	double prob(rule_sel.second);

	// Add the rule in the _bit.bit_as to make comparing atoms easier
	// as well as logging more consistent.
	rule.add(_bit.bit_as);

	// Abort expansion if ill rule
	if (not rule.is_valid()) {
		ure_logger().debug("No valid rule for the selected BIT-node, "
		                   "abort expansion");
		return;
	} else if (rule.has_cycle()) {
		LAZY_URE_LOG_DEBUG << "The following rule has cycle (some premise "
		                   << "equals to conclusion), abort expansion"
		                   << rule.to_string();
		return;
	}

	// Rule seems well, expand
	LAZY_URE_LOG_DEBUG << "Selected rule for BIT expansion:" << std::endl
	                   << rule.to_string();

	// Expand andbit. Warning: after this call the reference on andbit
	// and bitleaf may no longer be valid because the container of
	// and-BITs might have been resorted. so we keep track of their
	// bodies for future use.
	Handle andbit_fcs = andbit.fcs;
	Handle bitleaf_body = bitleaf->body;
	_last_expansion_andbit = _bit.expand(andbit, *bitleaf, {rule, ts}, prob);

	// Record the expansion in the trace atomspace
	if (_last_expansion_andbit) {
		_trace_recorder.andbit(*_last_expansion_andbit);
		_trace_recorder.expansion(andbit_fcs, bitleaf_body,
		                          rule, *_last_expansion_andbit);
	}
}

void BackwardChainer::fulfill_bit()
{
	if (_bit.empty()) {
		ure_logger().warn("Cannot fulfill an empty BIT!");
		return;
	}

	// Select an and-BIT for fulfillment
	const AndBIT* andbit = select_fulfillment_andbit();
	if (andbit == nullptr) {
		ure_logger().debug() << "Cannot fulfill an empty and-BIT. "
		                    << "Abort BIT fulfillment";
		return;
	}
	LAZY_URE_LOG_DEBUG << "Selected and-BIT for fulfillment (fcs value):"
	                   << std::endl << andbit->fcs->idToString();
	fulfill_fcs(andbit->fcs);
}

void BackwardChainer::fulfill_fcs(const Handle& fcs)
{
	// Temporary atomspace to not pollute _as with intermediary
	// results
	AtomSpace tmp_as(&_as);

	// Run the FCS and add the results, if any, in _as.
	//
	// Warning: since tmp_as is a child of _as, TVs of existing atoms
	// in _as, that are modified by running fcs will be modified on
	// _as as well. This can create involontary TVs changes, hopefully
	// mitigated by the merging the TVs properly (for now the one with
	// the highest confidence wins). To avoid that side effect, we
	// could operate on a copy the atomspace, of its zone of focus. Or
	// alternatively modify some HypotheticalLink wrapping the atoms
	// of concerns instead of the atoms themselves, and only modify
	// the atoms if there are existing results to copy back to _as.
	Handle hresult = bindlink(&tmp_as, fcs);
	HandleSeq results;
	for (const Handle& result : hresult->getOutgoingSet())
		results.push_back(_as.add_atom(result));
	LAZY_URE_LOG_DEBUG << "Results:" << std::endl << results;
	_results.insert(results.begin(), results.end());

	// Record the results in _trace_as
	for (const Handle& result : results)
		_trace_recorder.proof(fcs, result);
}

std::vector<double> BackwardChainer::expansion_anbit_weights()
{
	std::vector<double> weights;
	for (const AndBIT& andbit : _bit.andbits)
		weights.push_back(operator()(andbit));
	return weights;
}

AndBIT* BackwardChainer::select_expansion_andbit()
{
	std::vector<double> weights = expansion_anbit_weights();

	// Debug log
	if (ure_logger().is_debug_enabled()) {
		OC_ASSERT(weights.size() == _bit.andbits.size());
		std::stringstream ss;
		ss << "Weighted and-BITs:";
		for (size_t i = 0; i < weights.size(); i++)
			ss << std::endl << weights[i] << " "
			   << _bit.andbits[i].fcs->idToString();
		ure_logger().debug() << ss.str();
	}

	// Sample andbits according to this distribution
	std::discrete_distribution<size_t> dist(weights.begin(), weights.end());
	return &rand_element(_bit.andbits, dist);
}

const AndBIT* BackwardChainer::select_fulfillment_andbit() const
{
	return _last_expansion_andbit;
}

void BackwardChainer::reduce_bit()
{
	if (0 < _configReader.get_max_bit_size()) {
		// If the BIT size has reached its maximum, randomly remove
		// and-BITs so that the BIT size gets back below or equal to
		// its maximum.
		while (_configReader.get_max_bit_size() < _bit.size()) {
			// Randomly select an and-BIT that is unlikely to be used
			// for the remaining of the inferenceThe and-BITs to remove are
			// selected so that the least likely and-BITs to be
			// selected for expansion are removed first.
			remove_unlikely_expandable_andbit();
		}
	}
}

void BackwardChainer::remove_unlikely_expandable_andbit()
{
	std::vector<double> weights = expansion_anbit_weights();
	std::discrete_distribution<size_t> dist(weights.begin(), weights.end());
	std::vector<double> never_expand_probs;

	// Calculate the probability of never being expanded for the
	// remainder of the inference, thus (1-p) raised to the power of
	// _configReader.get_maximum_iterations() - _iteration. This makes
	// the assumption that the BIT (i.e. its and-BIT population) is
	// not gonna change from this point on, a false but OK assumption
	// for now.
	for (double p : dist.probabilities()) {
		double remaining_iterations =
			_configReader.get_maximum_iterations() - _iteration;
		double nep = std::pow(1 - p, remaining_iterations);
		never_expand_probs.push_back(nep);
	}

	// Fine log
	if (ure_logger().is_fine_enabled()) {
		OC_ASSERT(never_expand_probs.size() == _bit.andbits.size());
		std::stringstream ss;
		ss << "Never expand probs and-BITs:";
		for (size_t i = 0; i < never_expand_probs.size(); i++)
			ss << std::endl << never_expand_probs[i] << " "
			   << _bit.andbits[i].fcs->idToString();
		ure_logger().fine() << ss.str();
	}

	std::discrete_distribution<size_t>
		never_expand_dist(never_expand_probs.begin(), never_expand_probs.end());

	// Pick the and-BIT, remove it from the BIT and remove its
	// FCS from the bit atomspace.
	auto it = std::next(_bit.andbits.begin(), never_expand_dist(randGen()));
	LAZY_URE_LOG_DEBUG << "Remove " << it->fcs->idToString()
	                   << " from the BIT";
	_bit.erase(it);
}

double BackwardChainer::complexity_factor(const AndBIT& andbit) const
{
	return exp(-_configReader.get_complexity_penalty() * andbit.complexity);
}

double BackwardChainer::operator()(const AndBIT& andbit) const
{
	return (andbit.exhausted ? 0.0 : 1.0)
		* _andbit_fitness(andbit)
		* complexity_factor(andbit);
}
<commit_msg>Improve logging<commit_after>/*
 * BackwardChainer.cc
 *
 * Copyright (C) 2014-2017 OpenCog Foundation
 *
 * Authors: Misgana Bayetta <misgana.bayetta@gmail.com>  October 2014
 *          William Ma <https://github.com/williampma>
 *          Nil Geisweiller 2016-2017
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <random>

#include <boost/range/algorithm/lower_bound.hpp>

#include <opencog/util/random.h>

#include <opencog/atomutils/FindUtils.h>
#include <opencog/atomutils/Substitutor.h>
#include <opencog/atomutils/Unify.h>
#include <opencog/atomutils/TypeUtils.h>
#include <opencog/atoms/pattern/PatternLink.h>
#include <opencog/atoms/pattern/BindLink.h>

#include <opencog/query/BindLinkAPI.h>

#include "BackwardChainer.h"
#include "BackwardChainerPMCB.h"
#include "../URELogger.h"

using namespace opencog;

BackwardChainer::BackwardChainer(AtomSpace& as, const Handle& rbs,
                                 const Handle& target,
                                 const Handle& vardecl,
                                 AtomSpace* trace_as,
                                 AtomSpace* control_as,
                                 const Handle& focus_set, // TODO:
                                                          // support
                                                          // focus_set
                                 const BITNodeFitness& bitnode_fitness,
                                 const AndBITFitness& andbit_fitness)
	: _as(as), _configReader(as, rbs),
	  _bit(as, target, vardecl, bitnode_fitness),
	  _andbit_fitness(andbit_fitness),
	  _trace_recorder(trace_as),
	  _control(_configReader.get_rules(), _bit, control_as),
	  _rules(_control.rules),
	  _iteration(0), _last_expansion_andbit(nullptr)
{
	// Record the target in the trace atomspace
	_trace_recorder.target(target);
}

UREConfigReader& BackwardChainer::get_config()
{
	return _configReader;
}

const UREConfigReader& BackwardChainer::get_config() const
{
	return _configReader;
}

void BackwardChainer::do_chain()
{
	ure_logger().debug("Start Backward Chaining");
	LAZY_URE_LOG_DEBUG << "With rule set:" << std::endl << oc_to_string(_rules);

	while (not termination())
	{
		do_step();
	}

	LAZY_URE_LOG_DEBUG << "Finished Backward Chaining with solutions:"
	                   << std::endl << get_results()->toString();
}

void BackwardChainer::do_step()
{
	ure_logger().debug("Iteration %d", _iteration);
	_iteration++;

	expand_bit();
	fulfill_bit();
	reduce_bit();
}

bool BackwardChainer::termination()
{
	return _configReader.get_maximum_iterations() <= _iteration;
}

Handle BackwardChainer::get_results() const
{
	HandleSeq results(_results.begin(), _results.end());
	return _as.add_link(SET_LINK, results);
}

void BackwardChainer::expand_meta_rules()
{
	// This is kinda of hack before meta rules are fully supported by
	// the Rule class.
	size_t rules_size = _rules.size();
	_rules.expand_meta_rules(_as);

	// If the rule set has changed we need to reset the exhausted
	// flags.
	if (rules_size != _rules.size()) {
		_bit.reset_exhausted_flags();
		ure_logger().debug() << "The rule set has gone from "
		                     << rules_size << " rules to " << _rules.size()
		                     << ". All exhausted flags have been reset.";
	}
}

void BackwardChainer::expand_bit()
{
	// Expand meta rules, before they are fully supported
	expand_meta_rules();

	// Reset _last_expansion_fcs
	_last_expansion_andbit = nullptr;

	if (_bit.empty()) {
		_last_expansion_andbit = _bit.init();
		// Record the initial and-BIT in the trace atomspace
		_trace_recorder.andbit(*_last_expansion_andbit);
	} else {
		// Select an FCS (i.e. and-BIT) and expand it
		AndBIT* andbit = select_expansion_andbit();
		LAZY_URE_LOG_DEBUG << "Selected and-BIT for expansion:" << std::endl
		                   << andbit->to_string();
		expand_bit(*andbit);
	}
}

void BackwardChainer::expand_bit(AndBIT& andbit)
{
	// Select leaf
	BITNode* bitleaf = andbit.select_leaf();
	if (bitleaf) {
		LAZY_URE_LOG_DEBUG << "Selected BIT-node for expansion:" << std::endl
		                   << bitleaf->to_string();
	} else {
		ure_logger().debug() << "All BIT-nodes of this and-BIT are exhausted "
		                     << "(or possibly fulfilled). Abort expansion.";
		andbit.exhausted = true;
		return;
	}

	// Select rule for expansion
	RuleSelection rule_sel = _control.select_rule(andbit, *bitleaf);
	Rule rule(rule_sel.first.first);
	Unify::TypedSubstitution ts(rule_sel.first.second);
	double prob(rule_sel.second);

	// Add the rule in the _bit.bit_as to make comparing atoms easier
	// as well as logging more consistent.
	rule.add(_bit.bit_as);

	// Abort expansion if ill rule
	if (not rule.is_valid()) {
		ure_logger().debug("No valid rule for the selected BIT-node, "
		                   "abort expansion");
		return;
	} else if (rule.has_cycle()) {
		LAZY_URE_LOG_DEBUG << "The following rule has cycle (some premise "
		                   << "equals to conclusion), abort expansion"
		                   << rule.to_string();
		return;
	}

	// Rule seems well, expand
	LAZY_URE_LOG_DEBUG << "Selected rule, with probability " << prob
	                   << ", for BIT expansion:" << std::endl
	                   << rule.to_string();

	// Expand andbit. Warning: after this call the reference on andbit
	// and bitleaf may no longer be valid because the container of
	// and-BITs might have been resorted. so we keep track of their
	// bodies for future use.
	Handle andbit_fcs = andbit.fcs;
	Handle bitleaf_body = bitleaf->body;
	_last_expansion_andbit = _bit.expand(andbit, *bitleaf, {rule, ts}, prob);

	// Record the expansion in the trace atomspace
	if (_last_expansion_andbit) {
		_trace_recorder.andbit(*_last_expansion_andbit);
		_trace_recorder.expansion(andbit_fcs, bitleaf_body,
		                          rule, *_last_expansion_andbit);
	}
}

void BackwardChainer::fulfill_bit()
{
	if (_bit.empty()) {
		ure_logger().warn("Cannot fulfill an empty BIT!");
		return;
	}

	// Select an and-BIT for fulfillment
	const AndBIT* andbit = select_fulfillment_andbit();
	if (andbit == nullptr) {
		ure_logger().debug() << "Cannot fulfill an empty and-BIT. "
		                    << "Abort BIT fulfillment";
		return;
	}
	LAZY_URE_LOG_DEBUG << "Selected and-BIT for fulfillment (fcs value):"
	                   << std::endl << andbit->fcs->idToString();
	fulfill_fcs(andbit->fcs);
}

void BackwardChainer::fulfill_fcs(const Handle& fcs)
{
	// Temporary atomspace to not pollute _as with intermediary
	// results
	AtomSpace tmp_as(&_as);

	// Run the FCS and add the results, if any, in _as.
	//
	// Warning: since tmp_as is a child of _as, TVs of existing atoms
	// in _as, that are modified by running fcs will be modified on
	// _as as well. This can create involontary TVs changes, hopefully
	// mitigated by the merging the TVs properly (for now the one with
	// the highest confidence wins). To avoid that side effect, we
	// could operate on a copy the atomspace, of its zone of focus. Or
	// alternatively modify some HypotheticalLink wrapping the atoms
	// of concerns instead of the atoms themselves, and only modify
	// the atoms if there are existing results to copy back to _as.
	Handle hresult = bindlink(&tmp_as, fcs);
	HandleSeq results;
	for (const Handle& result : hresult->getOutgoingSet())
		results.push_back(_as.add_atom(result));
	LAZY_URE_LOG_DEBUG << "Results:" << std::endl << results;
	_results.insert(results.begin(), results.end());

	// Record the results in _trace_as
	for (const Handle& result : results)
		_trace_recorder.proof(fcs, result);
}

std::vector<double> BackwardChainer::expansion_anbit_weights()
{
	std::vector<double> weights;
	for (const AndBIT& andbit : _bit.andbits)
		weights.push_back(operator()(andbit));
	return weights;
}

AndBIT* BackwardChainer::select_expansion_andbit()
{
	std::vector<double> weights = expansion_anbit_weights();

	// Debug log
	if (ure_logger().is_debug_enabled()) {
		OC_ASSERT(weights.size() == _bit.andbits.size());
		std::stringstream ss;
		ss << "Weighted and-BITs:";
		for (size_t i = 0; i < weights.size(); i++)
			ss << std::endl << weights[i] << " "
			   << _bit.andbits[i].fcs->idToString();
		ure_logger().debug() << ss.str();
	}

	// Sample andbits according to this distribution
	std::discrete_distribution<size_t> dist(weights.begin(), weights.end());
	return &rand_element(_bit.andbits, dist);
}

const AndBIT* BackwardChainer::select_fulfillment_andbit() const
{
	return _last_expansion_andbit;
}

void BackwardChainer::reduce_bit()
{
	if (0 < _configReader.get_max_bit_size()) {
		// If the BIT size has reached its maximum, randomly remove
		// and-BITs so that the BIT size gets back below or equal to
		// its maximum.
		while (_configReader.get_max_bit_size() < _bit.size()) {
			// Randomly select an and-BIT that is unlikely to be used
			// for the remaining of the inferenceThe and-BITs to remove are
			// selected so that the least likely and-BITs to be
			// selected for expansion are removed first.
			remove_unlikely_expandable_andbit();
		}
	}
}

void BackwardChainer::remove_unlikely_expandable_andbit()
{
	std::vector<double> weights = expansion_anbit_weights();
	std::discrete_distribution<size_t> dist(weights.begin(), weights.end());
	std::vector<double> never_expand_probs;

	// Calculate the probability of never being expanded for the
	// remainder of the inference, thus (1-p) raised to the power of
	// _configReader.get_maximum_iterations() - _iteration. This makes
	// the assumption that the BIT (i.e. its and-BIT population) is
	// not gonna change from this point on, a false but OK assumption
	// for now.
	for (double p : dist.probabilities()) {
		double remaining_iterations =
			_configReader.get_maximum_iterations() - _iteration;
		double nep = std::pow(1 - p, remaining_iterations);
		never_expand_probs.push_back(nep);
	}

	// Fine log
	if (ure_logger().is_fine_enabled()) {
		OC_ASSERT(never_expand_probs.size() == _bit.andbits.size());
		std::stringstream ss;
		ss << "Never expand probs and-BITs:";
		for (size_t i = 0; i < never_expand_probs.size(); i++)
			ss << std::endl << never_expand_probs[i] << " "
			   << _bit.andbits[i].fcs->idToString();
		ure_logger().fine() << ss.str();
	}

	std::discrete_distribution<size_t>
		never_expand_dist(never_expand_probs.begin(), never_expand_probs.end());

	// Pick the and-BIT, remove it from the BIT and remove its
	// FCS from the bit atomspace.
	auto it = std::next(_bit.andbits.begin(), never_expand_dist(randGen()));
	LAZY_URE_LOG_DEBUG << "Remove " << it->fcs->idToString()
	                   << " from the BIT";
	_bit.erase(it);
}

double BackwardChainer::complexity_factor(const AndBIT& andbit) const
{
	return exp(-_configReader.get_complexity_penalty() * andbit.complexity);
}

double BackwardChainer::operator()(const AndBIT& andbit) const
{
	return (andbit.exhausted ? 0.0 : 1.0)
		* _andbit_fitness(andbit)
		* complexity_factor(andbit);
}
<|endoftext|>


<commit_before>//
// Created by dar on 11/25/15.
//

#include "Renderer.h"

Renderer::Renderer(Core *core) : core(core) { }

bool Renderer::init() {
    if (!this->initWindow()) {
        printf("Failed to initialize window!\n");
    } else if (!this->initGL()) {
        printf("Unable to initialize OpenGL!\n");
    } else if (!this->initTextures()) {
        printf("Unable to initialize textures!\n");
    } else {
        initRenderers();
        initTexData();
        fbo.init(0, windowWidth, windowHeight, new float[4]{0.8f, 0.8f, 0.8f, 1.0f}, "fboshader");
        return true;
    }
    return false;
}

bool Renderer::initWindow() {
    bool success = true;

    if (SDL_Init(SDL_INIT_VIDEO) < 0) { //Initialize SDL
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else {
        //Use OpenGL 3.3
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

        //Create window
        gWindow = SDL_CreateWindow("C003", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
        if (gWindow == NULL) {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else {
            gContext = SDL_GL_CreateContext(gWindow); //Create context
            if (gContext == NULL) {
                printf("OpenGL context could not be created! SDL Error: %s\n", SDL_GetError());
                success = false;
            } else {
                //Use Vsync
                if (SDL_GL_SetSwapInterval(1) < 0) {
                    printf("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());
                }
            }
        }
    }

    return success;
}

bool Renderer::initGL() {
    viewMatrix = glm::lookAt(glm::vec3(0, 0, 0.0f), glm::vec3(0, 0, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    projectionMatrix = glm::ortho(0.0f, float(windowWidth), 0.0f, float(windowHeight));
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    return true;
}

bool Renderer::initTextures() {
    bool ret = true;
    if (!textureAtlas.loadTexture2D("terrain.png", true)) ret = false;
    textureAtlas.setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);
    textureAtlas.bindTexture(10);
    return ret;
}

void Renderer::tick() {
    fbo.bind();
    glClear(GL_COLOR_BUFFER_BIT);
    for (Block *block : core->getMap()->getBlocks()) {
        getBlockRender(block)->render(block, projectionMatrix, glm::translate(viewMatrix, glm::vec3(-(signed) windowWidth / 2.0f - this->core->getCamX(), (signed) windowHeight / 2.0f - this->core->getCamY(), 0.0f)));
    }
    fbo.unbind();
    fbo.render(0);
}

void Renderer::run() {
    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
        if (e.type == SDL_QUIT) {
            this->core->stop();
        } else if (e.type == SDL_WINDOWEVENT) {
            if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
            }
        }
    }
    this->tick();
    SDL_GL_SwapWindow(gWindow);
}

void Renderer::resize(unsigned int width, unsigned int height) {
    if (width != this->windowWidth || height != this->windowHeight) {
        this->windowWidth = width;
        this->windowHeight = height;
        glViewport(0, 0, windowWidth, windowHeight);
        viewMatrix = glm::lookAt(glm::vec3(0, 0, 0.0f), glm::vec3(0, 0, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        this->projectionMatrix = glm::ortho(0.0f, float(windowWidth), 0.0f, float(windowHeight));
        this->fbo.resize(this->windowWidth, this->windowHeight);
    }
}

Renderer::~Renderer() {
    SDL_DestroyWindow(this->gWindow);
    SDL_Quit();
}
<commit_msg>Disable texture atlas mipmapping<commit_after>//
// Created by dar on 11/25/15.
//

#include "Renderer.h"

Renderer::Renderer(Core *core) : core(core) { }

bool Renderer::init() {
    if (!this->initWindow()) {
        printf("Failed to initialize window!\n");
    } else if (!this->initGL()) {
        printf("Unable to initialize OpenGL!\n");
    } else if (!this->initTextures()) {
        printf("Unable to initialize textures!\n");
    } else {
        initRenderers();
        initTexData();
        fbo.init(0, windowWidth, windowHeight, new float[4]{0.8f, 0.8f, 0.8f, 1.0f}, "fboshader");
        return true;
    }
    return false;
}

bool Renderer::initWindow() {
    bool success = true;

    if (SDL_Init(SDL_INIT_VIDEO) < 0) { //Initialize SDL
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else {
        //Use OpenGL 3.3
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

        //Create window
        gWindow = SDL_CreateWindow("C003", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
        if (gWindow == NULL) {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else {
            gContext = SDL_GL_CreateContext(gWindow); //Create context
            if (gContext == NULL) {
                printf("OpenGL context could not be created! SDL Error: %s\n", SDL_GetError());
                success = false;
            } else {
                //Use Vsync
                if (SDL_GL_SetSwapInterval(1) < 0) {
                    printf("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());
                }
            }
        }
    }

    return success;
}

bool Renderer::initGL() {
    viewMatrix = glm::lookAt(glm::vec3(0, 0, 0.0f), glm::vec3(0, 0, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    projectionMatrix = glm::ortho(0.0f, float(windowWidth), 0.0f, float(windowHeight));
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    return true;
}

bool Renderer::initTextures() {
    bool ret = true;
    if (!textureAtlas.loadTexture2D("terrain.png", false)) ret = false;
    textureAtlas.setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);
    textureAtlas.bindTexture(10);
    return ret;
}

void Renderer::tick() {
    fbo.bind();
    glClear(GL_COLOR_BUFFER_BIT);
    for (Block *block : core->getMap()->getBlocks()) {
        getBlockRender(block)->render(block, projectionMatrix, glm::translate(viewMatrix, glm::vec3(-(signed) windowWidth / 2.0f - this->core->getCamX(), (signed) windowHeight / 2.0f - this->core->getCamY(), 0.0f)));
    }
    fbo.unbind();
    fbo.render(0);
}

void Renderer::run() {
    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
        if (e.type == SDL_QUIT) {
            this->core->stop();
        } else if (e.type == SDL_WINDOWEVENT) {
            if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
            }
        }
    }
    this->tick();
    SDL_GL_SwapWindow(gWindow);
}

void Renderer::resize(unsigned int width, unsigned int height) {
    if (width != this->windowWidth || height != this->windowHeight) {
        this->windowWidth = width;
        this->windowHeight = height;
        glViewport(0, 0, windowWidth, windowHeight);
        viewMatrix = glm::lookAt(glm::vec3(0, 0, 0.0f), glm::vec3(0, 0, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        this->projectionMatrix = glm::ortho(0.0f, float(windowWidth), 0.0f, float(windowHeight));
        this->fbo.resize(this->windowWidth, this->windowHeight);
    }
}

Renderer::~Renderer() {
    SDL_DestroyWindow(this->gWindow);
    SDL_Quit();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: AccessibleDrawDocumentView.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: thb $ $Date: 2002-04-22 16:13:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX
#include "AccessibleDrawDocumentView.hxx"
#endif

#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_
#include <com/sun/star/drawing/XDrawView.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFOSUPPLIER_HPP_
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBROADCASTER_HPP_
#include <com/sun/star/document/XEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_INDEXOUTOFBOUNDSEXCEPTION_HPP_
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif
#ifndef _SFXFRAME_HXX
#include<sfx2/viewfrm.hxx>
#endif

#include <svx/AccessibleShape.hxx>

#include <svx/svdobj.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unoapi.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include "sdwindow.hxx"
#include <vcl/svapp.hxx>

#ifndef _SD_VIEWSHEL_HXX
#include "viewshel.hxx"
#endif
#ifndef _SD_SDVIEW_HXX
#include "sdview.hxx"
#endif
#include <memory>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

class SfxViewFrame;

namespace accessibility {

//=====  internal  ============================================================

AccessibleDrawDocumentView::AccessibleDrawDocumentView (
    SdWindow* pSdWindow,
    SdViewShell* pViewShell,
    const uno::Reference<frame::XController>& rxController,
    const uno::Reference<XAccessible>& rxParent)
    : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
      mpChildrenManager (NULL)
{
}

AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
{
    OSL_TRACE ("~AccessibleDrawDocumentView");

    // Unregister from the various event broadcasters.
    if (mpChildrenManager != NULL)
        delete mpChildrenManager;
}

void AccessibleDrawDocumentView::Init (void)
{
    AccessibleDocumentViewBase::Init ();

    // Determine the list of shapes on the current page.
    uno::Reference<drawing::XShapes> xShapeList;
    uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
    if (xView.is())
        xShapeList = uno::Reference<drawing::XShapes> (
            xView->getCurrentPage(), uno::UNO_QUERY);

    // Create the children manager.
    mpChildrenManager = new ChildrenManager(this, xShapeList, maShapeTreeInfo, *this);
    if (mpChildrenManager != NULL)
    {
        mpChildrenManager->AddAccessibleShape (CreateDrawPageShape());
        mpChildrenManager->Update ();
    }
}

void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType,
    const IAccessibleViewForwarder* pViewForwarder)
{
    AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);
    if (mpChildrenManager != NULL)
        mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
}

/**  The page shape is created on every call at the moment (provided that
     every thing goes well).
*/
AccessiblePageShape* AccessibleDrawDocumentView::CreateDrawPageShape (void)
{
    AccessiblePageShape* pShape = NULL;

    // Create a shape that represents the actual draw page.
    uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
    if (xView.is())
    {
        uno::Reference<beans::XPropertySet> xSet (
            uno::Reference<beans::XPropertySet> (xView->getCurrentPage(), uno::UNO_QUERY));
        if (xSet.is())
        {
            // Create a rectangle shape that will represent the draw page.
            uno::Reference<lang::XMultiServiceFactory> xFactory (mxModel, uno::UNO_QUERY);
            uno::Reference<drawing::XShape> xRectangle;
            if (xFactory.is())
                xRectangle = uno::Reference<drawing::XShape>(xFactory->createInstance (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.RectangleShape"))),
                    uno::UNO_QUERY);

            // Set the shape's size and position.
            if (xRectangle.is())
            {
                uno::Any aValue;
                awt::Point aPosition;
                awt::Size aSize;

                // Set size and position of the shape to those of the draw
                // page.
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("BorderLeft")));
                aValue >>= aPosition.X;
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("BorderTop")));
                aValue >>= aPosition.Y;
                xRectangle->setPosition (aPosition);

                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("Width")));
                aValue >>= aSize.Width;
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("Height")));
                aValue >>= aSize.Height;
                xRectangle->setSize (aSize);

                // Create the accessible object for the shape and set its
                // name and description to something more meaningfull than
                // "Rectangle..."
                pShape = new AccessiblePageShape (
                    xView->getCurrentPage(), this, maShapeTreeInfo);
            }
        }
    }
    return pShape;
}

//=====  XAccessibleContext  ==================================================

sal_Int32 SAL_CALL
    AccessibleDrawDocumentView::getAccessibleChildCount (void)
    throw (uno::RuntimeException)
{
    long mpChildCount = 0;

    // Forward request to children manager.
    if (mpChildrenManager != NULL)
        mpChildCount += mpChildrenManager->GetChildCount ();

    return mpChildCount;
}

uno::Reference<XAccessible> SAL_CALL
    AccessibleDrawDocumentView::getAccessibleChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException)
{
    if (mpChildrenManager != NULL)
    {
        // Forward request to children manager.
        return mpChildrenManager->GetChild (nIndex);
    }
    else
        throw lang::IndexOutOfBoundsException (
            ::rtl::OUString::createFromAscii ("no accessible child with index ") + nIndex,
            static_cast<uno::XWeak*>(this));
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
    AccessibleDrawDocumentView::getImplementationName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
}

//=====  XEventListener  ======================================================

void SAL_CALL
    AccessibleDrawDocumentView::disposing (const lang::EventObject& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::disposing (rEventObject);
    if (rEventObject.Source == mxModel)
    {
        ::osl::Guard< ::osl::Mutex> aGuard (::osl::Mutex::getGlobalMutex());
        // maShapeTreeInfo has been modified in base class.
        if (mpChildrenManager != NULL)
            mpChildrenManager->SetInfo (maShapeTreeInfo);
    }
}

//=====  XFrameActionListener  ================================================

void SAL_CALL
    AccessibleDrawDocumentView::frameAction (const frame::FrameActionEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::frameAction (rEventObject);

    if (rEventObject.Action == frame::FrameAction_COMPONENT_REATTACHED)
    {
        if (mpChildrenManager != NULL)
        {
            mpChildrenManager->ClearAccessibleShapeList ();
            mpChildrenManager->SetInfo (maShapeTreeInfo);
            mpChildrenManager->ViewForwarderChanged (
                IAccessibleViewForwarderListener::TRANSFORMATION,
                &maViewForwarder);

            // To properly inform the registered listeners of this we just have
            // to call the children manager and update its shape list.
            uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
            if (xView.is())
                mpChildrenManager->SetShapeList (
                    uno::Reference<drawing::XShapes> (
                        xView->getCurrentPage(), uno::UNO_QUERY));
            mpChildrenManager->AddAccessibleShape (CreateDrawPageShape ());
            mpChildrenManager->Update (false);
            OSL_TRACE ("done handling frame event for AccessibleDrawDocumentView");
        }
    }
}

//=====  XPropertyChangeListener  =============================================

void SAL_CALL
    AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::propertyChange (rEventObject);

    OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
    if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
    {
        OSL_TRACE ("    current page changed");

        // The current page changed.  Update the children manager accordingly.
        uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
        if (xView.is() && mpChildrenManager!=NULL)
        {
            // Inform the children manager to forget all children and give
            // him the new ones.
            mpChildrenManager->ClearAccessibleShapeList ();
            uno::Reference<drawing::XShapes> xShapeList (
                xView->getCurrentPage(), uno::UNO_QUERY);
            mpChildrenManager->SetShapeList (xShapeList);
            mpChildrenManager->AddAccessibleShape (CreateDrawPageShape ());
            mpChildrenManager->Update (false);
        }
        else
            OSL_TRACE ("View invalid");
    }
    else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
    {
        OSL_TRACE ("    visible area changed");
        if (mpChildrenManager != NULL)
            mpChildrenManager->ViewForwarderChanged (
                IAccessibleViewForwarderListener::VISIBLE_AREA,
                &maViewForwarder);
    }
    else
    {
        OSL_TRACE ("  unhandled");
    }
    OSL_TRACE ("  done");
}

/// Create a name for this view.
::rtl::OUString
    AccessibleDrawDocumentView::CreateAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
}

/** Create a description for this view.  Use the model's description or URL
    if a description is not available.
*/
::rtl::OUString
    AccessibleDrawDocumentView::CreateAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString sDescription;

    uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
    if (xInfo.is())
    {
        OUString sFirstService = xInfo->getSupportedServiceNames()[0];
        if (sFirstService == OUString (
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
        {
            sDescription = OUString (RTL_CONSTASCII_USTRINGPARAM("Draw Document"));
        }
        else
            sDescription = sFirstService;
    }
    else
        sDescription = OUString (
            RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document"));
    return sDescription;
}

} // end of namespace accessibility
<commit_msg>#95585# Using auto_ptr as argument of ChildrenManager::AddAccessibleShape:<commit_after>/*************************************************************************
 *
 *  $RCSfile: AccessibleDrawDocumentView.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: af $ $Date: 2002-04-29 14:07:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX
#include "AccessibleDrawDocumentView.hxx"
#endif

#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_
#include <com/sun/star/drawing/XDrawView.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFOSUPPLIER_HPP_
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBROADCASTER_HPP_
#include <com/sun/star/document/XEventBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_INDEXOUTOFBOUNDSEXCEPTION_HPP_
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif
#ifndef _SFXFRAME_HXX
#include<sfx2/viewfrm.hxx>
#endif

#include <svx/AccessibleShape.hxx>

#include <svx/svdobj.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unoapi.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include "sdwindow.hxx"
#include <vcl/svapp.hxx>

#ifndef _SD_VIEWSHEL_HXX
#include "viewshel.hxx"
#endif
#ifndef _SD_SDVIEW_HXX
#include "sdview.hxx"
#endif
#include <memory>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

class SfxViewFrame;

namespace accessibility {

//=====  internal  ============================================================

AccessibleDrawDocumentView::AccessibleDrawDocumentView (
    SdWindow* pSdWindow,
    SdViewShell* pViewShell,
    const uno::Reference<frame::XController>& rxController,
    const uno::Reference<XAccessible>& rxParent)
    : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
      mpChildrenManager (NULL)
{
}

AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
{
    OSL_TRACE ("~AccessibleDrawDocumentView");

    // Unregister from the various event broadcasters.
    if (mpChildrenManager != NULL)
        delete mpChildrenManager;
}

void AccessibleDrawDocumentView::Init (void)
{
    AccessibleDocumentViewBase::Init ();

    // Determine the list of shapes on the current page.
    uno::Reference<drawing::XShapes> xShapeList;
    uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
    if (xView.is())
        xShapeList = uno::Reference<drawing::XShapes> (
            xView->getCurrentPage(), uno::UNO_QUERY);

    // Create the children manager.
    mpChildrenManager = new ChildrenManager(this, xShapeList, maShapeTreeInfo, *this);
    if (mpChildrenManager != NULL)
    {
        mpChildrenManager->AddAccessibleShape (std::auto_ptr<AccessibleShape>(CreateDrawPageShape()));
        mpChildrenManager->Update ();
    }
}

void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType,
    const IAccessibleViewForwarder* pViewForwarder)
{
    AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);
    if (mpChildrenManager != NULL)
        mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
}

/**  The page shape is created on every call at the moment (provided that
     every thing goes well).
*/
AccessiblePageShape* AccessibleDrawDocumentView::CreateDrawPageShape (void)
{
    AccessiblePageShape* pShape = NULL;

    // Create a shape that represents the actual draw page.
    uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
    if (xView.is())
    {
        uno::Reference<beans::XPropertySet> xSet (
            uno::Reference<beans::XPropertySet> (xView->getCurrentPage(), uno::UNO_QUERY));
        if (xSet.is())
        {
            // Create a rectangle shape that will represent the draw page.
            uno::Reference<lang::XMultiServiceFactory> xFactory (mxModel, uno::UNO_QUERY);
            uno::Reference<drawing::XShape> xRectangle;
            if (xFactory.is())
                xRectangle = uno::Reference<drawing::XShape>(xFactory->createInstance (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.RectangleShape"))),
                    uno::UNO_QUERY);

            // Set the shape's size and position.
            if (xRectangle.is())
            {
                uno::Any aValue;
                awt::Point aPosition;
                awt::Size aSize;

                // Set size and position of the shape to those of the draw
                // page.
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("BorderLeft")));
                aValue >>= aPosition.X;
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("BorderTop")));
                aValue >>= aPosition.Y;
                xRectangle->setPosition (aPosition);

                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("Width")));
                aValue >>= aSize.Width;
                aValue = xSet->getPropertyValue (
                    OUString (RTL_CONSTASCII_USTRINGPARAM("Height")));
                aValue >>= aSize.Height;
                xRectangle->setSize (aSize);

                // Create the accessible object for the shape and set its
                // name and description to something more meaningfull than
                // "Rectangle..."
                pShape = new AccessiblePageShape (
                    xView->getCurrentPage(), this, maShapeTreeInfo);
            }
        }
    }
    return pShape;
}

//=====  XAccessibleContext  ==================================================

sal_Int32 SAL_CALL
    AccessibleDrawDocumentView::getAccessibleChildCount (void)
    throw (uno::RuntimeException)
{
    long mpChildCount = 0;

    // Forward request to children manager.
    if (mpChildrenManager != NULL)
        mpChildCount += mpChildrenManager->GetChildCount ();

    return mpChildCount;
}

uno::Reference<XAccessible> SAL_CALL
    AccessibleDrawDocumentView::getAccessibleChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException)
{
    if (mpChildrenManager != NULL)
    {
        // Forward request to children manager.
        return mpChildrenManager->GetChild (nIndex);
    }
    else
        throw lang::IndexOutOfBoundsException (
            ::rtl::OUString::createFromAscii ("no accessible child with index ") + nIndex,
            static_cast<uno::XWeak*>(this));
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
    AccessibleDrawDocumentView::getImplementationName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
}

//=====  XEventListener  ======================================================

void SAL_CALL
    AccessibleDrawDocumentView::disposing (const lang::EventObject& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::disposing (rEventObject);
    if (rEventObject.Source == mxModel)
    {
        ::osl::Guard< ::osl::Mutex> aGuard (::osl::Mutex::getGlobalMutex());
        // maShapeTreeInfo has been modified in base class.
        if (mpChildrenManager != NULL)
            mpChildrenManager->SetInfo (maShapeTreeInfo);
    }
}

//=====  XFrameActionListener  ================================================

void SAL_CALL
    AccessibleDrawDocumentView::frameAction (const frame::FrameActionEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::frameAction (rEventObject);

    if (rEventObject.Action == frame::FrameAction_COMPONENT_REATTACHED)
    {
        if (mpChildrenManager != NULL)
        {
            mpChildrenManager->ClearAccessibleShapeList ();
            mpChildrenManager->SetInfo (maShapeTreeInfo);
            mpChildrenManager->ViewForwarderChanged (
                IAccessibleViewForwarderListener::TRANSFORMATION,
                &maViewForwarder);

            // To properly inform the registered listeners of this we just have
            // to call the children manager and update its shape list.
            uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
            if (xView.is())
                mpChildrenManager->SetShapeList (
                    uno::Reference<drawing::XShapes> (
                        xView->getCurrentPage(), uno::UNO_QUERY));
            mpChildrenManager->AddAccessibleShape (std::auto_ptr<AccessibleShape>(CreateDrawPageShape()));
            mpChildrenManager->Update (false);
            OSL_TRACE ("done handling frame event for AccessibleDrawDocumentView");
        }
    }
}

//=====  XPropertyChangeListener  =============================================

void SAL_CALL
    AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
    throw (::com::sun::star::uno::RuntimeException)
{
    AccessibleDocumentViewBase::propertyChange (rEventObject);

    OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
    if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
    {
        OSL_TRACE ("    current page changed");

        // The current page changed.  Update the children manager accordingly.
        uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
        if (xView.is() && mpChildrenManager!=NULL)
        {
            // Inform the children manager to forget all children and give
            // him the new ones.
            mpChildrenManager->ClearAccessibleShapeList ();
            uno::Reference<drawing::XShapes> xShapeList (
                xView->getCurrentPage(), uno::UNO_QUERY);
            mpChildrenManager->SetShapeList (xShapeList);
            mpChildrenManager->AddAccessibleShape (std::auto_ptr<AccessibleShape>(CreateDrawPageShape ()));
            mpChildrenManager->Update (false);
        }
        else
            OSL_TRACE ("View invalid");
    }
    else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
    {
        OSL_TRACE ("    visible area changed");
        if (mpChildrenManager != NULL)
            mpChildrenManager->ViewForwarderChanged (
                IAccessibleViewForwarderListener::VISIBLE_AREA,
                &maViewForwarder);
    }
    else
    {
        OSL_TRACE ("  unhandled");
    }
    OSL_TRACE ("  done");
}

/// Create a name for this view.
::rtl::OUString
    AccessibleDrawDocumentView::CreateAccessibleName (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    return ::rtl::OUString (
        RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
}

/** Create a description for this view.  Use the model's description or URL
    if a description is not available.
*/
::rtl::OUString
    AccessibleDrawDocumentView::CreateAccessibleDescription (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString sDescription;

    uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
    if (xInfo.is())
    {
        OUString sFirstService = xInfo->getSupportedServiceNames()[0];
        if (sFirstService == OUString (
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
        {
            sDescription = OUString (RTL_CONSTASCII_USTRINGPARAM("Draw Document"));
        }
        else
            sDescription = sFirstService;
    }
    else
        sDescription = OUString (
            RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document"));
    return sDescription;
}

} // end of namespace accessibility
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "partialbitvector.h"

namespace search {

using vespalib::alloc::Alloc;

PartialBitVector::PartialBitVector(Index start, Index end) :
    BitVector(),
    _alloc(allocatePaddedAndAligned(start, end))
{
    init(_alloc.get(), start, end);
    clear();
}

PartialBitVector::PartialBitVector(const BitVector & org, Index start, Index end) :
    BitVector(),
    _alloc(allocatePaddedAndAligned(start, end))
{
    init(_alloc.get(), start, end);
    memcpy(_alloc.get(), org.getWordIndex(start), numActiveBytes(start, end));
    setBit(size());
}

PartialBitVector::~PartialBitVector() { }

} // namespace search
<commit_msg>Protect against copying undefined memory.<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "partialbitvector.h"

namespace search {

using vespalib::alloc::Alloc;

PartialBitVector::PartialBitVector(Index start, Index end) :
    BitVector(),
    _alloc(allocatePaddedAndAligned(start, end))
{
    init(_alloc.get(), start, end);
    clear();
}

PartialBitVector::PartialBitVector(const BitVector & org, Index start, Index end) :
    BitVector(),
    _alloc(allocatePaddedAndAligned(start, end))
{
    init(_alloc.get(), start, end);
    const Word * startWord = org.getWordIndex(start);
    size_t numBytes2Copy = numActiveBytes(start, std::min(org.size(), end));
    memcpy(_alloc.get(), startWord, numBytes2Copy);
    if (org.size() < end) {
        clearInterval(org.size(), end);
    }
    setBit(size());
}

PartialBitVector::~PartialBitVector() { }

} // namespace search
<|endoftext|>


<commit_before>//
// Stiches multiple .obj files into one .obj.
//
#include "../../tiny_obj_loader.h"
#include "obj_writer.h"

#include <cassert>
#include <iostream>
#include <cstdlib>
#include <cstdio>

typedef std::vector<tinyobj::shape_t> Shape;
typedef std::vector<tinyobj::material_t> Material;

void
StichObjs(
  std::vector<tinyobj::shape_t>& out_shape,
  std::vector<tinyobj::material_t>& out_material,
  const std::vector<Shape>& shapes,
  const std::vector<Material>& materials)
{
  int numShapes = 0;
  for (size_t i = 0; i < shapes.size(); i++) {
    numShapes += (int)shapes[i].size();
  }

  printf("Total # of shapes = %d\n", numShapes);
  int materialIdOffset = 0;

  size_t face_offset = 0;
  for (size_t i = 0; i < shapes.size(); i++) {

    for (size_t k = 0; k < shapes[i].size(); k++) {

      std::string new_name = shapes[i][k].name;
      // Add suffix
      char buf[1024];
      sprintf(buf, "_%04d", (int)i);
      new_name += std::string(buf);

      printf("shape[%ld][%ld].name = %s\n", i, k, shapes[i][k].name.c_str());
      assert((shapes[i][k].mesh.indices.size() % 3) == 0);
      assert((shapes[i][k].mesh.positions.size() % 3) == 0);

      tinyobj::shape_t new_shape = shapes[i][k];
      // Add offset.
      for (size_t f = 0; f < new_shape.mesh.material_ids.size(); f++) {
        new_shape.mesh.material_ids[f] += materialIdOffset;
      }

      new_shape.name = new_name;
      printf("shape[%ld][%ld].new_name = %s\n", i, k, new_shape.name.c_str());

      out_shape.push_back(new_shape);
    }

    materialIdOffset += materials[i].size();
  }

  for (size_t i = 0; i < materials.size(); i++) {
    for (size_t k = 0; k < materials[i].size(); k++) {
      out_material.push_back(materials[i][k]);
    }
  }

}

int
main(
  int argc,
  char **argv)
{
  if (argc < 3) {
    printf("Usage: obj_sticher input0.obj input1.obj ... output.obj\n");
    exit(1);
  }

  int num_objfiles = argc - 2;
  std::string out_filename = std::string(argv[argc-1]); // last element

  std::vector<Shape> shapes;
  std::vector<Material> materials;
  shapes.resize(num_objfiles);
  materials.resize(num_objfiles);

  for (int i = 0; i < num_objfiles; i++) {
    std::cout << "Loading " << argv[i+1] << " ... " << std::flush;

    std::string err;
    bool ret = tinyobj::LoadObj(shapes[i], materials[i], err, argv[i+1]);
    if (!err.empty()) {
      std::cerr << err << std::endl;
    }
    if (!ret) {
      exit(1);
    }

    std::cout << "DONE." << std::endl;
  }

  std::vector<tinyobj::shape_t> out_shape;
  std::vector<tinyobj::material_t> out_material;
  StichObjs(out_shape, out_material, shapes, materials);

  bool coordTransform = true;
  bool ret = WriteObj(out_filename, out_shape, out_material, coordTransform);
  assert(ret);

  return 0;
}
<commit_msg>Adapt 1.0.x datastructure<commit_after>//
// Stiches multiple .obj files into one .obj.
//

#define TINYOBJLOADER_IMPLEMENTATION
#include "../../tiny_obj_loader.h"
#include "obj_writer.h"

#include <cassert>
#include <iostream>
#include <cstdlib>
#include <cstdio>

typedef std::vector<tinyobj::shape_t> Shape;
typedef std::vector<tinyobj::material_t> Material;
typedef tinyobj::attrib_t Attribute;

void
StichObjs(
  tinyobj::attrib_t& out_attribute,
  std::vector<tinyobj::shape_t>& out_shape,
  std::vector<tinyobj::material_t>& out_material,
  const std::vector<Attribute>& attributes,
  const std::vector<Shape>& shapes,
  const std::vector<Material>& materials)
{
  // The amount of attributes, shape-vectors and material-vecotrs should be the same.
  if(attributes.size() != shapes.size() && attributes.size() != materials.size()){
    std::cerr << "Size of attributes, shapes and Materials don't fit!" << attributes.size() << " " << shapes.size() <<" " << materials.size() << std::endl;;
    exit(1);
  }
  int num_shapes = 0;
  // 4 values (vertices, normals, texcoords, colors)
  std::vector<int> num_attributes(4, 0);
  int num_materials = 0;
  for(int i = 0; i < shapes.size(); i++){
    num_shapes += shapes[i].size();
  }
  for(int i = 0; i < attributes.size(); i++){
    num_attributes[0] += attributes[i].vertices.size();
    num_attributes[1] += attributes[i].normals.size();
    num_attributes[2] += attributes[i].texcoords.size();
    num_attributes[3] += attributes[i].colors.size();
  }
  for(int i = 0; i < materials.size(); i++){
    num_materials += materials[i].size();
  }

  // More performant, than push_back
  out_attribute.vertices.resize(num_attributes[0]);
  out_attribute.normals.resize(num_attributes[1]);
  out_attribute.texcoords.resize(num_attributes[2]);
  out_attribute.colors.resize(num_attributes[3]);
  out_shape.resize(num_shapes);
  out_material.resize(num_materials);

  int material_id_offset = 0;
  int shape_id_offset = 0;
  int vertex_idx_offset = 0;
  int normal_idx_offset = 0;
  int texcoord_idx_offset = 0;
  int color_idx_offset = 0;

  // shapes.size() = attributes.size() = materials.size()
  for (size_t i = 0; i < shapes.size(); i++) {

    // Copy shapes
    for (size_t k = 0; k < shapes[i].size(); k++) {
      std::string new_name = shapes[i][k].name;
      // Add suffix
      char buf[1024];
      sprintf(buf, "_%04d", (int)i);
      new_name += std::string(buf);

      printf("shape[%ld][%ld].name = %s\n", i, k, shapes[i][k].name.c_str());

      tinyobj::shape_t new_shape = shapes[i][k];
      // Add material offset.
      for(size_t f = 0; f < new_shape.mesh.material_ids.size(); f++) {
        new_shape.mesh.material_ids[f] += material_id_offset;
      }
      // Add indices offset.
      for(size_t f = 0; f < new_shape.mesh.indices.size(); f++){
        tinyobj::index_t& ref = new_shape.mesh.indices[f];
        if(ref.vertex_index > -1){
          ref.vertex_index += vertex_idx_offset;
        }
        if(ref.normal_index > -1){
          ref.normal_index += normal_idx_offset;
        }
        if(ref.texcoord_index > -1){
          ref.texcoord_index += texcoord_idx_offset;
        }
      }

      new_shape.name = new_name;
      printf("shape[%ld][%ld].new_name = %s\n", i, k, new_shape.name.c_str());

      out_shape[shape_id_offset++] = new_shape;
    }

    // Copy materials
    for (size_t k = 0; k < materials[i].size(); k++) {
      out_material[material_id_offset++] = materials[i][k];
    }

    // Copy attributes (3 floats per vertex, 3 floats per normal, 2 floats per texture-coordinate, 3 floats per color)
    // You could also include a check here, if the sizes are dividable by 3 (resp. 2), but it's safe to simply assume, they do.
    std::copy(attributes[i].vertices.begin(), attributes[i].vertices.end(), out_attribute.vertices.begin() + vertex_idx_offset * 3);
    vertex_idx_offset += attributes[i].vertices.size() / 3;
    std::copy(attributes[i].normals.begin(), attributes[i].normals.end(), out_attribute.normals.begin() + normal_idx_offset * 3);
    normal_idx_offset += attributes[i].normals.size() / 3;
    std::copy(attributes[i].texcoords.begin(), attributes[i].texcoords.end(), out_attribute.texcoords.begin() + texcoord_idx_offset * 2);
    texcoord_idx_offset += attributes[i].texcoords.size() / 2;
    std::copy(attributes[i].colors.begin(), attributes[i].colors.end(), out_attribute.colors.begin() + color_idx_offset * 3);
    color_idx_offset += attributes[i].colors.size();
  }
}

int main(int argc, char **argv)
{
  if (argc < 3) {
    printf("Usage: obj_sticher input0.obj input1.obj ... output.obj\n");
    exit(1);
  }

  int num_objfiles = argc - 2;
  std::string out_filename = std::string(argv[argc-1]); // last element

  std::vector<Attribute> attributes(num_objfiles);
  std::vector<Shape> shapes(num_objfiles);
  std::vector<Material> materials(num_objfiles);

  for (int i = 0; i < num_objfiles; i++) {
    std::cout << "Loading " << argv[i+1] << " ... " << std::flush;

    std::string err;
    bool ret = tinyobj::LoadObj(&attributes[i], &shapes[i], &materials[i], &err, argv[i+1]);
    if (!err.empty()) {
      std::cerr << err << std::endl;
    }
    if (!ret) {
      exit(1);
    }

    std::cout << "DONE." << std::endl;
  }

  Attribute out_attribute;
  Shape out_shape;
  Material out_material;
  StichObjs(out_attribute, out_shape, out_material, attributes, shapes, materials);

  bool coordTransform = false;
  bool ret = WriteObj(out_filename, out_attribute, out_shape, out_material, coordTransform);
  assert(ret);

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "repair/repair.hh"
#include "message/messaging_service.hh"
#include "mutation_fragment.hh"
#include "xx_hasher.hh"
#include "dht/i_partitioner.hh"
#include <vector>
#include <algorithm>
#include <random>
#include <optional>

extern logging::logger rlogger;

struct shard_config {
    unsigned shard;
    unsigned shard_count;
    unsigned ignore_msb;
    sstring partitioner_name;
};

static const std::vector<row_level_diff_detect_algorithm>& suportted_diff_detect_algorithms() {
    static std::vector<row_level_diff_detect_algorithm> _algorithms = {
        row_level_diff_detect_algorithm::send_full_set,
    };
    return _algorithms;
};

static row_level_diff_detect_algorithm get_common_diff_detect_algorithm(const std::vector<gms::inet_address>& nodes) {
    std::vector<std::vector<row_level_diff_detect_algorithm>> nodes_algorithms(nodes.size());
    parallel_for_each(boost::irange(size_t(0), nodes.size()), [&nodes_algorithms, &nodes] (size_t idx) {
        return netw::get_local_messaging_service().send_repair_get_diff_algorithms(netw::messaging_service::msg_addr(nodes[idx])).then(
                [&nodes_algorithms, &nodes, idx] (std::vector<row_level_diff_detect_algorithm> algorithms) {
            std::sort(algorithms.begin(), algorithms.end());
            nodes_algorithms[idx] = std::move(algorithms);
            rlogger.trace("Got node_algorithms={}, from node={}", nodes_algorithms[idx], nodes[idx]);
        });
    }).get();

    auto common_algorithms = suportted_diff_detect_algorithms();
    for (auto& algorithms : nodes_algorithms) {
        std::sort(common_algorithms.begin(), common_algorithms.end());
        std::vector<row_level_diff_detect_algorithm> results;
        std::set_intersection(algorithms.begin(), algorithms.end(),
                common_algorithms.begin(), common_algorithms.end(),
                std::back_inserter(results));
        common_algorithms = std::move(results);
    }
    rlogger.trace("peer_algorithms={}, local_algorithms={}, common_diff_detect_algorithms={}",
            nodes_algorithms, suportted_diff_detect_algorithms(), common_algorithms);
    if (common_algorithms.empty()) {
        throw std::runtime_error("Can not find row level repair diff detect algorithm");
    }
    return common_algorithms.back();
}

static uint64_t get_random_seed() {
    static thread_local std::default_random_engine random_engine{std::random_device{}()};
    static thread_local std::uniform_int_distribution<uint64_t> random_dist{};
    return random_dist(random_engine);
}

class decorated_key_with_hash {
public:
    dht::decorated_key dk;
    repair_hash hash;
    decorated_key_with_hash(const schema& s, dht::decorated_key key, uint64_t seed)
        : dk(key) {
        xx_hasher h(seed);
        feed_hash(h, dk.key(), s);
        hash = repair_hash(h.finalize_uint64());
    }
};

class fragment_hasher {
    const schema& _schema;
    xx_hasher& _hasher;
private:
    void consume_cell(const column_definition& col, const atomic_cell_or_collection& cell) {
        feed_hash(_hasher, col.name());
        feed_hash(_hasher, col.type->name());
        feed_hash(_hasher, cell, col);
    }
public:
    explicit fragment_hasher(const schema&s, xx_hasher& h)
        : _schema(s), _hasher(h) { }

    void hash(const mutation_fragment& mf) {
        if (mf.is_static_row()) {
            consume(mf.as_static_row());
        } else if (mf.is_clustering_row()) {
            consume(mf.as_clustering_row());
        } else if (mf.is_range_tombstone()) {
            consume(mf.as_range_tombstone());
        } else if (mf.is_partition_start()) {
            consume(mf.as_partition_start());
        } else {
            throw std::runtime_error("Wrong type to consume");
        }
    }

private:

    void consume(const tombstone& t) {
        feed_hash(_hasher, t);
    }

    void consume(const static_row& sr) {
        sr.cells().for_each_cell([&] (column_id id, const atomic_cell_or_collection& cell) {
            auto&& col = _schema.static_column_at(id);
            consume_cell(col, cell);
        });
    }

    void consume(const clustering_row& cr) {
        feed_hash(_hasher, cr.key(), _schema);
        feed_hash(_hasher, cr.tomb());
        feed_hash(_hasher, cr.marker());
        cr.cells().for_each_cell([&] (column_id id, const atomic_cell_or_collection& cell) {
            auto&& col = _schema.regular_column_at(id);
            consume_cell(col, cell);
        });
    }

    void consume(const range_tombstone& rt) {
        feed_hash(_hasher, rt.start, _schema);
        feed_hash(_hasher, rt.start_kind);
        feed_hash(_hasher, rt.tomb);
        feed_hash(_hasher, rt.end, _schema);
        feed_hash(_hasher, rt.end_kind);
    }

    void consume(const partition_start& ps) {
        feed_hash(_hasher, ps.key().key(), _schema);
        if (ps.partition_tombstone()) {
            consume(ps.partition_tombstone());
        }
    }
};

class repair_row {
    frozen_mutation_fragment _fm;
    lw_shared_ptr<const decorated_key_with_hash> _dk_with_hash;
    repair_sync_boundary _boundary;
    repair_hash _hash;
    lw_shared_ptr<mutation_fragment> _mf;
public:
    repair_row() = delete;
    repair_row(frozen_mutation_fragment fm,
            position_in_partition pos,
            lw_shared_ptr<const decorated_key_with_hash> dk_with_hash,
            repair_hash hash,
            lw_shared_ptr<mutation_fragment> mf = {})
            : _fm(std::move(fm))
            , _dk_with_hash(std::move(dk_with_hash))
            , _boundary({_dk_with_hash->dk, std::move(pos)})
            , _hash(std::move(hash))
            , _mf(std::move(mf)) {
    }
    mutation_fragment& get_mutation_fragment() {
        if (!_mf) {
            throw std::runtime_error("get empty mutation_fragment");
        }
        return *_mf;
    }
    frozen_mutation_fragment& get_frozen_mutation() { return _fm; }
    const frozen_mutation_fragment& get_frozen_mutation() const { return _fm; }
    const lw_shared_ptr<const decorated_key_with_hash>& get_dk_with_hash() const {
        return _dk_with_hash;
    }
    size_t size() const {
        return _fm.representation().size();
    }
    const repair_sync_boundary& boundary() const {
        return _boundary;
    }
    const repair_hash& hash() const {
        return _hash;
    }
};
<commit_msg>repair: Add repair_reader<commit_after>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "repair/repair.hh"
#include "message/messaging_service.hh"
#include "mutation_fragment.hh"
#include "xx_hasher.hh"
#include "dht/i_partitioner.hh"
#include <vector>
#include <algorithm>
#include <random>
#include <optional>

extern logging::logger rlogger;

struct shard_config {
    unsigned shard;
    unsigned shard_count;
    unsigned ignore_msb;
    sstring partitioner_name;
};

static const std::vector<row_level_diff_detect_algorithm>& suportted_diff_detect_algorithms() {
    static std::vector<row_level_diff_detect_algorithm> _algorithms = {
        row_level_diff_detect_algorithm::send_full_set,
    };
    return _algorithms;
};

static row_level_diff_detect_algorithm get_common_diff_detect_algorithm(const std::vector<gms::inet_address>& nodes) {
    std::vector<std::vector<row_level_diff_detect_algorithm>> nodes_algorithms(nodes.size());
    parallel_for_each(boost::irange(size_t(0), nodes.size()), [&nodes_algorithms, &nodes] (size_t idx) {
        return netw::get_local_messaging_service().send_repair_get_diff_algorithms(netw::messaging_service::msg_addr(nodes[idx])).then(
                [&nodes_algorithms, &nodes, idx] (std::vector<row_level_diff_detect_algorithm> algorithms) {
            std::sort(algorithms.begin(), algorithms.end());
            nodes_algorithms[idx] = std::move(algorithms);
            rlogger.trace("Got node_algorithms={}, from node={}", nodes_algorithms[idx], nodes[idx]);
        });
    }).get();

    auto common_algorithms = suportted_diff_detect_algorithms();
    for (auto& algorithms : nodes_algorithms) {
        std::sort(common_algorithms.begin(), common_algorithms.end());
        std::vector<row_level_diff_detect_algorithm> results;
        std::set_intersection(algorithms.begin(), algorithms.end(),
                common_algorithms.begin(), common_algorithms.end(),
                std::back_inserter(results));
        common_algorithms = std::move(results);
    }
    rlogger.trace("peer_algorithms={}, local_algorithms={}, common_diff_detect_algorithms={}",
            nodes_algorithms, suportted_diff_detect_algorithms(), common_algorithms);
    if (common_algorithms.empty()) {
        throw std::runtime_error("Can not find row level repair diff detect algorithm");
    }
    return common_algorithms.back();
}

static uint64_t get_random_seed() {
    static thread_local std::default_random_engine random_engine{std::random_device{}()};
    static thread_local std::uniform_int_distribution<uint64_t> random_dist{};
    return random_dist(random_engine);
}

class decorated_key_with_hash {
public:
    dht::decorated_key dk;
    repair_hash hash;
    decorated_key_with_hash(const schema& s, dht::decorated_key key, uint64_t seed)
        : dk(key) {
        xx_hasher h(seed);
        feed_hash(h, dk.key(), s);
        hash = repair_hash(h.finalize_uint64());
    }
};

class fragment_hasher {
    const schema& _schema;
    xx_hasher& _hasher;
private:
    void consume_cell(const column_definition& col, const atomic_cell_or_collection& cell) {
        feed_hash(_hasher, col.name());
        feed_hash(_hasher, col.type->name());
        feed_hash(_hasher, cell, col);
    }
public:
    explicit fragment_hasher(const schema&s, xx_hasher& h)
        : _schema(s), _hasher(h) { }

    void hash(const mutation_fragment& mf) {
        if (mf.is_static_row()) {
            consume(mf.as_static_row());
        } else if (mf.is_clustering_row()) {
            consume(mf.as_clustering_row());
        } else if (mf.is_range_tombstone()) {
            consume(mf.as_range_tombstone());
        } else if (mf.is_partition_start()) {
            consume(mf.as_partition_start());
        } else {
            throw std::runtime_error("Wrong type to consume");
        }
    }

private:

    void consume(const tombstone& t) {
        feed_hash(_hasher, t);
    }

    void consume(const static_row& sr) {
        sr.cells().for_each_cell([&] (column_id id, const atomic_cell_or_collection& cell) {
            auto&& col = _schema.static_column_at(id);
            consume_cell(col, cell);
        });
    }

    void consume(const clustering_row& cr) {
        feed_hash(_hasher, cr.key(), _schema);
        feed_hash(_hasher, cr.tomb());
        feed_hash(_hasher, cr.marker());
        cr.cells().for_each_cell([&] (column_id id, const atomic_cell_or_collection& cell) {
            auto&& col = _schema.regular_column_at(id);
            consume_cell(col, cell);
        });
    }

    void consume(const range_tombstone& rt) {
        feed_hash(_hasher, rt.start, _schema);
        feed_hash(_hasher, rt.start_kind);
        feed_hash(_hasher, rt.tomb);
        feed_hash(_hasher, rt.end, _schema);
        feed_hash(_hasher, rt.end_kind);
    }

    void consume(const partition_start& ps) {
        feed_hash(_hasher, ps.key().key(), _schema);
        if (ps.partition_tombstone()) {
            consume(ps.partition_tombstone());
        }
    }
};

class repair_row {
    frozen_mutation_fragment _fm;
    lw_shared_ptr<const decorated_key_with_hash> _dk_with_hash;
    repair_sync_boundary _boundary;
    repair_hash _hash;
    lw_shared_ptr<mutation_fragment> _mf;
public:
    repair_row() = delete;
    repair_row(frozen_mutation_fragment fm,
            position_in_partition pos,
            lw_shared_ptr<const decorated_key_with_hash> dk_with_hash,
            repair_hash hash,
            lw_shared_ptr<mutation_fragment> mf = {})
            : _fm(std::move(fm))
            , _dk_with_hash(std::move(dk_with_hash))
            , _boundary({_dk_with_hash->dk, std::move(pos)})
            , _hash(std::move(hash))
            , _mf(std::move(mf)) {
    }
    mutation_fragment& get_mutation_fragment() {
        if (!_mf) {
            throw std::runtime_error("get empty mutation_fragment");
        }
        return *_mf;
    }
    frozen_mutation_fragment& get_frozen_mutation() { return _fm; }
    const frozen_mutation_fragment& get_frozen_mutation() const { return _fm; }
    const lw_shared_ptr<const decorated_key_with_hash>& get_dk_with_hash() const {
        return _dk_with_hash;
    }
    size_t size() const {
        return _fm.representation().size();
    }
    const repair_sync_boundary& boundary() const {
        return _boundary;
    }
    const repair_hash& hash() const {
        return _hash;
    }
};

class repair_reader {
public:
using is_local_reader = bool_class<class is_local_reader_tag>;

private:
    schema_ptr _schema;
    dht::partition_range _range;
    // Used to find the range that repair master will work on
    dht::selective_token_range_sharder _sharder;
    // Seed for the repair row hashing
    uint64_t _seed;
    // Local reader or multishard reader to read the range
    flat_mutation_reader _reader;
    // Current partition read from disk
    lw_shared_ptr<const decorated_key_with_hash> _current_dk;

public:
    repair_reader(
            seastar::sharded<database>& db,
            column_family& cf,
            dht::token_range range,
            dht::i_partitioner& local_partitioner,
            dht::i_partitioner& remote_partitioner,
            unsigned remote_shard,
            uint64_t seed,
            is_local_reader local_reader)
            : _schema(cf.schema())
            , _range(dht::to_partition_range(range))
            , _sharder(remote_partitioner, range, remote_shard)
            , _seed(seed)
            , _reader(make_reader(db, cf, local_partitioner, local_reader)) {
    }

private:
    flat_mutation_reader
    make_reader(seastar::sharded<database>& db,
            column_family& cf,
            dht::i_partitioner& local_partitioner,
            is_local_reader local_reader) {
        if (local_reader) {
            return cf.make_streaming_reader(_schema, _range);
        }
        return make_multishard_streaming_reader(db, local_partitioner, _schema, [this] {
            auto shard_range = _sharder.next();
            if (shard_range) {
                return std::optional<dht::partition_range>(dht::to_partition_range(*shard_range));
            }
            return std::optional<dht::partition_range>();
        });
    }

public:
    future<mutation_fragment_opt>
    read_mutation_fragment() {
        return _reader(db::no_timeout);
    }

    lw_shared_ptr<const decorated_key_with_hash>& get_current_dk() {
        return _current_dk;
    }

    void set_current_dk(const dht::decorated_key& key) {
        _current_dk = make_lw_shared<const decorated_key_with_hash>(*_schema, key, _seed);
    }

    void clear_current_dk() {
        _current_dk = {};
    }

    void check_current_dk() {
        if (!_current_dk) {
            throw std::runtime_error("Current partition_key is unknown");
        }
    }

};
<|endoftext|>