<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011-2012 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/Parameter.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/CrossValidationStorage.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/lib/List.h>
#include <shogun/machine/Machine.h>
#include <shogun/mathematics/Statistics.h>

using namespace shogun;

CCrossValidation::CCrossValidation() : CMachineEvaluation()
{
	init();
}

CCrossValidation::CCrossValidation(
    CMachine* machine, CFeatures* features, CLabels* labels,
    CSplittingStrategy* splitting_strategy, CEvaluation* evaluation_criterion,
    bool autolock)
    : CMachineEvaluation(
          machine, features, labels, splitting_strategy, evaluation_criterion,
          autolock)
{
	init();
}

CCrossValidation::CCrossValidation(
    CMachine* machine, CLabels* labels, CSplittingStrategy* splitting_strategy,
    CEvaluation* evaluation_criterion, bool autolock)
    : CMachineEvaluation(
          machine, labels, splitting_strategy, evaluation_criterion, autolock)
{
	init();
}

CCrossValidation::~CCrossValidation()
{
}

void CCrossValidation::init()
{
	m_num_runs = 1;

	SG_ADD(&m_num_runs, "num_runs", "Number of repetitions", MS_NOT_AVAILABLE);
}

CEvaluationResult* CCrossValidation::evaluate_impl()
{
	/* if for some reason the do_unlock_frag is set, unlock */
	if (m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock = false;
	}

	/* set labels in any case (no locking needs this) */
	m_machine->set_labels(m_labels);

	if (m_autolock)
	{
		/* if machine supports locking try to do so */
		if (m_machine->supports_locking())
		{
			/* only lock if machine is not yet locked */
			if (!m_machine->is_data_locked())
			{
				m_machine->data_lock(m_labels, m_features);
				m_do_unlock = true;
			}
		}
		else
		{
			SG_WARNING(
			    "%s does not support locking. Autolocking is skipped. "
			    "Set autolock flag to false to get rid of warning.\n",
			    m_machine->get_name());
		}
	}

	SGVector<float64_t> results(m_num_runs);

	/* perform all the x-val runs */
	SG_DEBUG("starting %d runs of cross-validation\n", m_num_runs)
	for (index_t i = 0; i < m_num_runs; ++i)
	{
		/* evtl. update xvalidation output class */
		SG_DEBUG("Creating CrossValidationStorage.\n")
		CrossValidationStorage* storage = new CrossValidationStorage();
		SG_REF(storage)
		storage->set_num_runs(m_num_runs);
		storage->set_num_folds(m_splitting_strategy->get_num_subsets());
		storage->set_expose_labels(m_labels);
		storage->post_init();
		SG_DEBUG("Ending CrossValidationStorage initilization.\n")

		SG_DEBUG("entering cross-validation run %d \n", i)
		results[i] = evaluate_one_run(i, storage);
		SG_DEBUG("result of cross-validation run %d is %f\n", i, results[i])

		/* Emit the value*/
		std::string obs_value_name{"cross_validation_run"};
		ObservedValue cv_data{i, obs_value_name, erase_type(storage),
		                      CROSSVALIDATION};
		observe(cv_data);
		SG_UNREF(storage)
	}

	/* construct evaluation result */
	CCrossValidationResult* result = new CCrossValidationResult();
	result->set_mean(CStatistics::mean(results));
	if (m_num_runs > 1)
		result->set_std_dev(CStatistics::std_deviation(results));
	else
		result->set_std_dev(0);

	/* unlock machine if it was locked in this method */
	if (m_machine->is_data_locked() && m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock = false;
	}

	SG_REF(result);
	return result;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs < 1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs)

	m_num_runs = num_runs;
}

float64_t CCrossValidation::evaluate_one_run(
    int64_t index, CrossValidationStorage* storage)
{
	SG_DEBUG("entering %s::evaluate_one_run()\n", get_name())
	index_t num_subsets = m_splitting_strategy->get_num_subsets();

	SG_DEBUG("building index sets for %d-fold cross-validation\n", num_subsets)

	/* build index sets */
	m_splitting_strategy->build_subsets();

	/* results array */
	SGVector<float64_t> results(num_subsets);

	/* different behavior whether data is locked or not */
	if (m_machine->is_data_locked())
	{
		m_machine->set_store_model_features(true);
		SG_DEBUG("starting locked evaluation\n", get_name())
		/* do actual cross-validation */
		for (index_t i = 0; i < num_subsets; ++i)
		{
			/* evtl. update xvalidation output class */
			CrossValidationFoldStorage* fold = new CrossValidationFoldStorage();
			SG_REF(fold)
			fold->set_run_index(index);
			fold->set_fold_index(i);

			/* index subset for training, will be freed below */
			SGVector<index_t> inverse_subset_indices =
			    m_splitting_strategy->generate_subset_inverse(i);

			/* train machine on training features */
			m_machine->train_locked(inverse_subset_indices);

			/* feature subset for testing */
			SGVector<index_t> subset_indices =
			    m_splitting_strategy->generate_subset_indices(i);

			/* evtl. update xvalidation output class */
			fold->set_train_indices(inverse_subset_indices);
			auto fold_machine = (CMachine*)m_machine->clone();
			fold->set_trained_machine(fold_machine);
			SG_UNREF(fold_machine)

			/* produce output for desired indices */
			CLabels* result_labels = m_machine->apply_locked(subset_indices);
			SG_REF(result_labels);

			/* set subset for testing labels */
			m_labels->add_subset(subset_indices);

			/* evaluate against own labels */
			m_evaluation_criterion->set_indices(subset_indices);
			results[i] =
			    m_evaluation_criterion->evaluate(result_labels, m_labels);

			/* evtl. update xvalidation output class */
			fold->set_test_indices(subset_indices);
			fold->set_test_result(result_labels);
			CLabels* true_labels = (CLabels*)m_labels->clone();
			fold->set_test_true_result(true_labels);
			SG_UNREF(true_labels)
			fold->post_update_results();
			fold->set_evaluation_result(results[i]);

			/* remove subset to prevent side effects */
			m_labels->remove_subset();

			/* Save fold into storage */
			storage->append_fold_result(fold);

			/* clean up */
			SG_UNREF(result_labels);
			SG_UNREF(fold);

			SG_DEBUG("done locked evaluation\n", get_name())
		}
	}
	else
	{
		SG_DEBUG("starting unlocked evaluation\n", get_name())
		/* tell machine to store model internally
		 * (otherwise changing subset of features will kaboom the classifier) */
		m_machine->set_store_model_features(true);

		/* do actual cross-validation */

		// TODO parallel xvalidation needs some serious fixing, see #3743
		//#pragma omp parallel for
		for (index_t i = 0; i < num_subsets; ++i)
		{
			CrossValidationFoldStorage* fold = new CrossValidationFoldStorage();
			SG_REF(fold)
			CMachine* machine;
			CFeatures* features;
			CLabels* labels;
			CEvaluation* evaluation_criterion;

			if (get_global_parallel()->get_num_threads() == 1)
			{
				machine = m_machine;
				features = m_features;
				evaluation_criterion = m_evaluation_criterion;
			}
			else
			{
				machine = (CMachine*)m_machine->clone();
				features = (CFeatures*)m_features->clone();
				evaluation_criterion =
				    (CEvaluation*)m_evaluation_criterion->clone();
			}

			/* evtl. update xvalidation output class */
			fold->set_run_index(index);
			fold->set_fold_index(i);

			/* set feature subset for training */
			SGVector<index_t> inverse_subset_indices =
			    m_splitting_strategy->generate_subset_inverse(i);

			features->add_subset(inverse_subset_indices);

			/* set label subset for training */
			if (get_global_parallel()->get_num_threads() == 1)
				labels = m_labels;
			else
				labels = machine->get_labels();
			labels->add_subset(inverse_subset_indices);

			SG_DEBUG("training set %d:\n", i)
			if (io->get_loglevel() == MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(
				    inverse_subset_indices.vector, inverse_subset_indices.vlen,
				    "training indices");
			}

			/* train machine on training features and remove subset */
			SG_DEBUG("starting training\n")
			machine->train(features);
			SG_DEBUG("finished training\n")

			/* evtl. update xvalidation output class */
			fold->set_train_indices(inverse_subset_indices);
			auto fold_machine = (CMachine*)machine->clone();
			fold->set_trained_machine(fold_machine);
			SG_UNREF(fold_machine)

			features->remove_subset();
			labels->remove_subset();

			/* set feature subset for testing (subset method that stores
			 * pointer) */
			SGVector<index_t> subset_indices =
			    m_splitting_strategy->generate_subset_indices(i);
			features->add_subset(subset_indices);

			/* set label subset for testing */
			labels->add_subset(subset_indices);

			SG_DEBUG("test set %d:\n", i)
			if (io->get_loglevel() == MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(
				    subset_indices.vector, subset_indices.vlen, "test indices");
			}

			/* apply machine to test features and remove subset */
			SG_DEBUG("starting evaluation\n")
			SG_DEBUG("%p\n", features)
			CLabels* result_labels = machine->apply(features);
			SG_DEBUG("finished evaluation\n")
			features->remove_subset();
			SG_REF(result_labels);

			/* evaluate */
			results[i] = evaluation_criterion->evaluate(result_labels, labels);
			SG_DEBUG("result on fold %d is %f\n", i, results[i])

			/* evtl. update xvalidation output class */
			fold->set_test_indices(subset_indices);
			fold->set_test_result(result_labels);
			CLabels* true_labels = (CLabels*)labels->clone();
			fold->set_test_true_result(true_labels);
			SG_UNREF(true_labels)
			fold->post_update_results();
			fold->set_evaluation_result(results[i]);

			storage->append_fold_result(fold);

			/* clean up, remove subsets */
			labels->remove_subset();
			if (get_global_parallel()->get_num_threads() != 1)
			{
				SG_UNREF(machine);
				SG_UNREF(features);
				SG_UNREF(labels);
				SG_UNREF(evaluation_criterion);
			}
			SG_UNREF(result_labels);
			SG_UNREF(fold)
		}

		SG_DEBUG("done unlocked evaluation\n", get_name())
	}

	/* build arithmetic mean of results */
	float64_t mean = CStatistics::mean(results);

	SG_DEBUG("leaving %s::evaluate_one_run()\n", get_name())
	return mean;
}
<commit_msg>[PrematureStopping] Add premature stopping to CrossValidation.<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011-2012 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/Parameter.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/CrossValidationStorage.h>
#include <shogun/base/progress.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/lib/List.h>
#include <shogun/machine/Machine.h>
#include <shogun/mathematics/Statistics.h>

using namespace shogun;

CCrossValidation::CCrossValidation() : CMachineEvaluation()
{
	init();
}

CCrossValidation::CCrossValidation(
    CMachine* machine, CFeatures* features, CLabels* labels,
    CSplittingStrategy* splitting_strategy, CEvaluation* evaluation_criterion,
    bool autolock)
    : CMachineEvaluation(
          machine, features, labels, splitting_strategy, evaluation_criterion,
          autolock)
{
	init();
}

CCrossValidation::CCrossValidation(
    CMachine* machine, CLabels* labels, CSplittingStrategy* splitting_strategy,
    CEvaluation* evaluation_criterion, bool autolock)
    : CMachineEvaluation(
          machine, labels, splitting_strategy, evaluation_criterion, autolock)
{
	init();
}

CCrossValidation::~CCrossValidation()
{
}

void CCrossValidation::init()
{
	m_num_runs = 1;

	SG_ADD(&m_num_runs, "num_runs", "Number of repetitions", MS_NOT_AVAILABLE);
}

CEvaluationResult* CCrossValidation::evaluate_impl()
{
	/* if for some reason the do_unlock_frag is set, unlock */
	if (m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock = false;
	}

	/* set labels in any case (no locking needs this) */
	m_machine->set_labels(m_labels);

	if (m_autolock)
	{
		/* if machine supports locking try to do so */
		if (m_machine->supports_locking())
		{
			/* only lock if machine is not yet locked */
			if (!m_machine->is_data_locked())
			{
				m_machine->data_lock(m_labels, m_features);
				m_do_unlock = true;
			}
		}
		else
		{
			SG_WARNING(
			    "%s does not support locking. Autolocking is skipped. "
			    "Set autolock flag to false to get rid of warning.\n",
			    m_machine->get_name());
		}
	}

	SGVector<float64_t> results(m_num_runs);

	/* perform all the x-val runs */
	SG_DEBUG("starting %d runs of cross-validation\n", m_num_runs)
	for (index_t i = 0; i < m_num_runs; i++)
	{
		/* evtl. update xvalidation output class */
		SG_DEBUG("Creating CrossValidationStorage.\n")
		CrossValidationStorage* storage = new CrossValidationStorage();
		SG_REF(storage)
		storage->set_num_runs(m_num_runs);
		storage->set_num_folds(m_splitting_strategy->get_num_subsets());
		storage->set_expose_labels(m_labels);
		storage->post_init();
		SG_DEBUG("Ending CrossValidationStorage initilization.\n")

		SG_DEBUG("entering cross-validation run %d \n", i)
		results[i] = evaluate_one_run(i, storage);
		SG_DEBUG("result of cross-validation run %d is %f\n", i, results[i])

		/* Emit the value*/
		std::string obs_value_name{"cross_validation_run"};
		ObservedValue cv_data{i, obs_value_name, erase_type(storage),
		                      CROSSVALIDATION};
		observe(cv_data);
		SG_UNREF(storage)
	}

	/* construct evaluation result */
	CCrossValidationResult* result = new CCrossValidationResult();
	result->set_mean(CStatistics::mean(results));
	if (m_num_runs > 1)
		result->set_std_dev(CStatistics::std_deviation(results));
	else
		result->set_std_dev(0);

	/* unlock machine if it was locked in this method */
	if (m_machine->is_data_locked() && m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock = false;
	}

	SG_REF(result);
	return result;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs < 1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs)

	m_num_runs = num_runs;
}

float64_t CCrossValidation::evaluate_one_run(
    int64_t index, CrossValidationStorage* storage)
{
	SG_DEBUG("entering %s::evaluate_one_run()\n", get_name())
	index_t num_subsets = m_splitting_strategy->get_num_subsets();

	SG_DEBUG("building index sets for %d-fold cross-validation\n", num_subsets)

	/* build index sets */
	m_splitting_strategy->build_subsets();

	/* results array */
	SGVector<float64_t> results(num_subsets);

	/* different behavior whether data is locked or not */
	if (m_machine->is_data_locked())
	{
		m_machine->set_store_model_features(true);
		SG_DEBUG("starting locked evaluation\n", get_name())
		/* do actual cross-validation */
		for (index_t i = 0; i < num_subsets; ++i)
		{
			EVALUATION_CONTROLLERS

			/* evtl. update xvalidation output class */
			CrossValidationFoldStorage* fold = new CrossValidationFoldStorage();
			SG_REF(fold)
			fold->set_run_index(index);
			fold->set_fold_index(i);

			/* index subset for training, will be freed below */
			SGVector<index_t> inverse_subset_indices =
			    m_splitting_strategy->generate_subset_inverse(i);

			/* train machine on training features */
			m_machine->train_locked(inverse_subset_indices);

			/* feature subset for testing */
			SGVector<index_t> subset_indices =
			    m_splitting_strategy->generate_subset_indices(i);

			/* evtl. update xvalidation output class */
			fold->set_train_indices(inverse_subset_indices);
			auto fold_machine = (CMachine*)m_machine->clone();
			fold->set_trained_machine(fold_machine);
			SG_UNREF(fold_machine)

			/* produce output for desired indices */
			CLabels* result_labels = m_machine->apply_locked(subset_indices);
			SG_REF(result_labels);

			/* set subset for testing labels */
			m_labels->add_subset(subset_indices);

			/* evaluate against own labels */
			m_evaluation_criterion->set_indices(subset_indices);
			results[i] =
			    m_evaluation_criterion->evaluate(result_labels, m_labels);

			/* evtl. update xvalidation output class */
			fold->set_test_indices(subset_indices);
			fold->set_test_result(result_labels);
			CLabels* true_labels = (CLabels*)m_labels->clone();
			fold->set_test_true_result(true_labels);
			SG_UNREF(true_labels)
			fold->post_update_results();
			fold->set_evaluation_result(results[i]);

			/* remove subset to prevent side effects */
			m_labels->remove_subset();

			/* Save fold into storage */
			storage->append_fold_result(fold);

			/* clean up */
			SG_UNREF(result_labels);
			SG_UNREF(fold);

			SG_DEBUG("done locked evaluation\n", get_name())
		}
	}
	else
	{
		SG_DEBUG("starting unlocked evaluation\n", get_name())
		/* tell machine to store model internally
		 * (otherwise changing subset of features will kaboom the classifier) */
		m_machine->set_store_model_features(true);

		/* do actual cross-validation */

		// TODO parallel xvalidation needs some serious fixing, see #3743
		//#pragma omp parallel for
		for (index_t i = 0; i < num_subsets; ++i)
		{
			EVALUATION_CONTROLLERS

			CrossValidationFoldStorage* fold = new CrossValidationFoldStorage();
			SG_REF(fold)

			CMachine* machine;
			CFeatures* features;
			CLabels* labels;
			CEvaluation* evaluation_criterion;

			if (get_global_parallel()->get_num_threads() == 1)
			{
				machine = m_machine;
				features = m_features;
				evaluation_criterion = m_evaluation_criterion;
			}
			else
			{
				machine = (CMachine*)m_machine->clone();
				features = (CFeatures*)m_features->clone();
				evaluation_criterion =
				    (CEvaluation*)m_evaluation_criterion->clone();
			}

			/* evtl. update xvalidation output class */
			fold->set_run_index(index);
			fold->set_fold_index(i);

			/* set feature subset for training */
			SGVector<index_t> inverse_subset_indices =
			    m_splitting_strategy->generate_subset_inverse(i);

			features->add_subset(inverse_subset_indices);

			/* set label subset for training */
			if (get_global_parallel()->get_num_threads() == 1)
				labels = m_labels;
			else
				labels = machine->get_labels();
			labels->add_subset(inverse_subset_indices);

			SG_DEBUG("training set %d:\n", i)
			if (io->get_loglevel() == MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(
				    inverse_subset_indices.vector, inverse_subset_indices.vlen,
				    "training indices");
			}

			/* train machine on training features and remove subset */
			SG_DEBUG("starting training\n")
			machine->train(features);
			SG_DEBUG("finished training\n")

			/* evtl. update xvalidation output class */
			fold->set_train_indices(inverse_subset_indices);
			auto fold_machine = (CMachine*)machine->clone();
			fold->set_trained_machine(fold_machine);
			SG_UNREF(fold_machine)

			features->remove_subset();
			labels->remove_subset();

			/* set feature subset for testing (subset method that stores
			 * pointer) */
			SGVector<index_t> subset_indices =
			    m_splitting_strategy->generate_subset_indices(i);
			features->add_subset(subset_indices);

			/* set label subset for testing */
			labels->add_subset(subset_indices);

			SG_DEBUG("test set %d:\n", i)
			if (io->get_loglevel() == MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(
				    subset_indices.vector, subset_indices.vlen, "test indices");
			}

			/* apply machine to test features and remove subset */
			SG_DEBUG("starting evaluation\n")
			SG_DEBUG("%p\n", features)
			CLabels* result_labels = machine->apply(features);
			SG_DEBUG("finished evaluation\n")
			features->remove_subset();
			SG_REF(result_labels);

			/* evaluate */
			results[i] = evaluation_criterion->evaluate(result_labels, labels);
			SG_DEBUG("result on fold %d is %f\n", i, results[i])

			/* evtl. update xvalidation output class */
			fold->set_test_indices(subset_indices);
			fold->set_test_result(result_labels);
			CLabels* true_labels = (CLabels*)labels->clone();
			fold->set_test_true_result(true_labels);
			SG_UNREF(true_labels)
			fold->post_update_results();
			fold->set_evaluation_result(results[i]);

			storage->append_fold_result(fold);

			/* clean up, remove subsets */
			labels->remove_subset();
			if (get_global_parallel()->get_num_threads() != 1)
			{
				SG_UNREF(machine);
				SG_UNREF(features);
				SG_UNREF(labels);
				SG_UNREF(evaluation_criterion);
			}
			SG_UNREF(result_labels);
			SG_UNREF(fold)
		}

		SG_DEBUG("done unlocked evaluation\n", get_name())
	}

	/* build arithmetic mean of results */
	float64_t mean = CStatistics::mean(results);

	SG_DEBUG("leaving %s::evaluate_one_run()\n", get_name())
	return mean;
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/evaluation/CrossValidation.h>
#include <shogun/machine/Machine.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/base/Parameter.h>

using namespace shogun;

CCrossValidation::CCrossValidation()
{
	init();
}

CCrossValidation::~CCrossValidation()
{
	SG_UNREF(m_machine);
	SG_UNREF(m_features);
	SG_UNREF(m_labels);
	SG_UNREF(m_splitting_strategy);
	SG_UNREF(m_evaluation_criterium);
}

CCrossValidation::CCrossValidation(CMachine* machine, CFeatures* features,
		CLabels* labels, CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterium)
{
	init();

	m_machine=machine;
	m_features=features;
	m_labels=labels;
	m_splitting_strategy=splitting_strategy;
	m_evaluation_criterium=evaluation_criterium;

	SG_REF(m_machine);
	SG_REF(m_features);
	SG_REF(m_labels);
	SG_REF(m_splitting_strategy);
	SG_REF(m_evaluation_criterium);
}

void CCrossValidation::init()
{
	m_machine=NULL;
	m_features=NULL;
	m_labels=NULL;
	m_splitting_strategy=NULL;
	m_evaluation_criterium=NULL;
	m_num_runs=1;
	m_conf_int_p=0;

	m_parameters->add((CSGObject**) &m_machine, "machine",
			"Used learning machine");
	m_parameters->add((CSGObject**) &m_features, "features", "Used features");
	m_parameters->add((CSGObject**) &m_labels, "labels", "Used labels");
	m_parameters->add((CSGObject**) &m_splitting_strategy,
			"splitting_strategy", "Used splitting strategy");
	m_parameters->add((CSGObject**) &m_evaluation_criterium,
			"evaluation_criterium", "Used evaluation criterium");
	m_parameters->add(&m_num_runs, "num_runs", "Number of repetitions");
	m_parameters->add(&m_conf_int_p, "conf_int_p", "p-value of confidence "
			"interval");
}

Parameter* CCrossValidation::get_machine_parameters() const
{
	return m_machine->m_parameters;
}

CrossValidationResult CCrossValidation::evaluate()
{
	float64_t* results=new float64_t[m_num_runs];

	for (index_t i=0; i<m_num_runs; ++i)
		results[i]=evaluate_one_run();

	/* construct evaluation result */
	CrossValidationResult result;
	result.value=CMath::mean(results, m_num_runs);
	result.has_conf_int=m_conf_int_p!=0;
	result.conf_int_p=m_conf_int_p;

	if (result.has_conf_int)
	{
		/* TODO: calculate confidence interval, maybe put this into CMath? */
		SG_NOTIMPLEMENTED;
	}
	else
	{
		result.conf_int_low=0;
		result.conf_int_up=0;
	}

	delete[] results;

	return result;
}

void CCrossValidation::set_conf_int_p(float64_t conf_int_p)
{
	if (conf_int_p<0||conf_int_p>=1)
	{
		SG_ERROR("%f is an illegal p-value for confidence interval of "
				"cross-validation\n", conf_int_p);
	}

	m_conf_int_p=conf_int_p;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs<1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs);

	m_num_runs=num_runs;
}

float64_t CCrossValidation::evaluate_one_run()
{
	index_t num_subsets=m_splitting_strategy->get_num_subsets();
	float64_t* results=new float64_t[num_subsets];

	/* set labels to machine */
	m_machine->set_labels(m_labels);

	/* do actual cross-validation */
	for (index_t i=0; i<num_subsets; ++i)
	{
		/* set feature subset for training */
		SGVector<index_t> inverse_subset_indices=
				m_splitting_strategy->generate_subset_inverse(i);
		m_features->set_subset(new CSubset(inverse_subset_indices));

		/* set label subset for training (copy data before) */
		SGVector<index_t> inverse_subset_indices_copy(
				inverse_subset_indices.vlen);
		memcpy(inverse_subset_indices_copy.vector,
				inverse_subset_indices.vector,
				inverse_subset_indices.vlen*sizeof(index_t));
		m_labels->set_subset(new CSubset(inverse_subset_indices_copy));

		/* train machine on training features */
		m_machine->train(m_features);

		/* set feature subset for testing (subset method that stores pointer) */
		SGVector<index_t> subset_indices=
				m_splitting_strategy->generate_subset_indices(i);
		m_features->set_subset(new CSubset(subset_indices));

		/* apply machine to test features */
		CLabels* result_labels=m_machine->apply(m_features);
		SG_REF(result_labels);

		/* set label subset for testing (copy data before) */
		SGVector<index_t> subset_indices_copy(
				new index_t[subset_indices.vlen], subset_indices.vlen);
		memcpy(subset_indices_copy.vector, subset_indices.vector,
				subset_indices.vlen*sizeof(index_t));
		m_labels->set_subset(new CSubset(subset_indices_copy));

		/* evaluate */
		results[i]=m_evaluation_criterium->evaluate(result_labels, m_labels);

		/* clean up, reset subsets */
		SG_UNREF(result_labels);
		m_features->remove_subset();
		m_labels->remove_subset();
	}

	/* build arithmetic mean of results */
	float64_t mean=CMath::mean(results, num_subsets);

	/* clean up */
	delete[] results;

	return mean;
}
<commit_msg>usage of mean method of CStatistics instead of CMath<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/evaluation/CrossValidation.h>
#include <shogun/machine/Machine.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/base/Parameter.h>
#include <shogun/mathematics/Statistics.h>

using namespace shogun;

CCrossValidation::CCrossValidation()
{
	init();
}

CCrossValidation::~CCrossValidation()
{
	SG_UNREF(m_machine);
	SG_UNREF(m_features);
	SG_UNREF(m_labels);
	SG_UNREF(m_splitting_strategy);
	SG_UNREF(m_evaluation_criterium);
}

CCrossValidation::CCrossValidation(CMachine* machine, CFeatures* features,
		CLabels* labels, CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterium)
{
	init();

	m_machine=machine;
	m_features=features;
	m_labels=labels;
	m_splitting_strategy=splitting_strategy;
	m_evaluation_criterium=evaluation_criterium;

	SG_REF(m_machine);
	SG_REF(m_features);
	SG_REF(m_labels);
	SG_REF(m_splitting_strategy);
	SG_REF(m_evaluation_criterium);
}

void CCrossValidation::init()
{
	m_machine=NULL;
	m_features=NULL;
	m_labels=NULL;
	m_splitting_strategy=NULL;
	m_evaluation_criterium=NULL;
	m_num_runs=1;
	m_conf_int_p=0;

	m_parameters->add((CSGObject**) &m_machine, "machine",
			"Used learning machine");
	m_parameters->add((CSGObject**) &m_features, "features", "Used features");
	m_parameters->add((CSGObject**) &m_labels, "labels", "Used labels");
	m_parameters->add((CSGObject**) &m_splitting_strategy,
			"splitting_strategy", "Used splitting strategy");
	m_parameters->add((CSGObject**) &m_evaluation_criterium,
			"evaluation_criterium", "Used evaluation criterium");
	m_parameters->add(&m_num_runs, "num_runs", "Number of repetitions");
	m_parameters->add(&m_conf_int_p, "conf_int_p", "p-value of confidence "
			"interval");
}

Parameter* CCrossValidation::get_machine_parameters() const
{
	return m_machine->m_parameters;
}

CrossValidationResult CCrossValidation::evaluate()
{
	float64_t* results=new float64_t[m_num_runs];

	for (index_t i=0; i<m_num_runs; ++i)
		results[i]=evaluate_one_run();

	/* construct evaluation result */
	CrossValidationResult result;
	result.value=CMath::mean(results, m_num_runs);
	result.has_conf_int=m_conf_int_p!=0;
	result.conf_int_p=m_conf_int_p;

	if (result.has_conf_int)
	{
		/* TODO: calculate confidence interval, maybe put this into CMath? */
		SG_NOTIMPLEMENTED;
	}
	else
	{
		result.conf_int_low=0;
		result.conf_int_up=0;
	}

	delete[] results;

	return result;
}

void CCrossValidation::set_conf_int_p(float64_t conf_int_p)
{
	if (conf_int_p<0||conf_int_p>=1)
	{
		SG_ERROR("%f is an illegal p-value for confidence interval of "
				"cross-validation\n", conf_int_p);
	}

	m_conf_int_p=conf_int_p;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs<1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs);

	m_num_runs=num_runs;
}

float64_t CCrossValidation::evaluate_one_run()
{
	index_t num_subsets=m_splitting_strategy->get_num_subsets();
	float64_t* results=new float64_t[num_subsets];

	/* set labels to machine */
	m_machine->set_labels(m_labels);

	/* do actual cross-validation */
	for (index_t i=0; i<num_subsets; ++i)
	{
		/* set feature subset for training */
		SGVector<index_t> inverse_subset_indices=
				m_splitting_strategy->generate_subset_inverse(i);
		m_features->set_subset(new CSubset(inverse_subset_indices));

		/* set label subset for training (copy data before) */
		SGVector<index_t> inverse_subset_indices_copy(
				inverse_subset_indices.vlen);
		memcpy(inverse_subset_indices_copy.vector,
				inverse_subset_indices.vector,
				inverse_subset_indices.vlen*sizeof(index_t));
		m_labels->set_subset(new CSubset(inverse_subset_indices_copy));

		/* train machine on training features */
		m_machine->train(m_features);

		/* set feature subset for testing (subset method that stores pointer) */
		SGVector<index_t> subset_indices=
				m_splitting_strategy->generate_subset_indices(i);
		m_features->set_subset(new CSubset(subset_indices));

		/* apply machine to test features */
		CLabels* result_labels=m_machine->apply(m_features);
		SG_REF(result_labels);

		/* set label subset for testing (copy data before) */
		SGVector<index_t> subset_indices_copy(
				new index_t[subset_indices.vlen], subset_indices.vlen);
		memcpy(subset_indices_copy.vector, subset_indices.vector,
				subset_indices.vlen*sizeof(index_t));
		m_labels->set_subset(new CSubset(subset_indices_copy));

		/* evaluate */
		results[i]=m_evaluation_criterium->evaluate(result_labels, m_labels);

		/* clean up, reset subsets */
		SG_UNREF(result_labels);
		m_features->remove_subset();
		m_labels->remove_subset();
	}

	/* build arithmetic mean of results */
	float64_t mean=CStatistics::mean(SGVector<float64_t>(results, num_subsets));

	/* clean up */
	delete[] results;

	return mean;
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "saxendanalyzer.h"
#include "streamindexer.h"
#include "inputstreamreader.h"
#include "indexwriter.h"
#include <expat.h>
using namespace jstreams;
using namespace std;

class SaxEndAnalyzer::Private {
public:
    enum FieldType { NONE, TEXT, TITLE };
    string fieldvalue;
    FieldType fieldtype;
    XML_Parser parser;
    Indexable* idx;
    int chars;
    int depth;
    bool stop;
    bool error;
    bool welformed;
    bool html;
    string errorstring;

    static void charactersSAXFunc(void* ctx, const char * ch, int len);
    static void startElementSAXFunc(void * ctx, const char * name,
        const char ** atts);
    static void endElementSAXFunc(void * ctx, const char * name);

    Private() {
        idx = 0;
        parser = XML_ParserCreate(NULL);
    }
    ~Private() {
        XML_ParserFree(parser);
    }
    void reset() {
        XML_ParserReset(parser, 0);
        XML_SetElementHandler(this->parser,
            startElementSAXFunc, endElementSAXFunc);
        XML_SetCharacterDataHandler(this->parser, charactersSAXFunc);
        XML_SetUserData(parser, this);
        error = stop = false;
        chars = 0;
        stop = false;
        error = false;
        html = false;
        welformed = true;
        depth = 0;
    }
    void init(Indexable*i, const char* data, int32_t len) {
        idx = i;
        reset();
        push(data, len);
    }
    void push(const char* data, int32_t len) {
        if (XML_Parse(parser, data, len, false) == 0) {
            XML_Error e = XML_GetErrorCode(parser);
            // handle the error unless it is a tag mismatch in html
            if (!(html && e == XML_ERROR_TAG_MISMATCH)) {
                errorstring = XML_ErrorString(e);
                error = stop = true;
            } else {
                welformed = false;
            }
        }
    }
    void finish() {
        XML_Parse(parser, 0, 0, false);
    }
};
void
SaxEndAnalyzer::Private::charactersSAXFunc(void* ctx, const char * ch,
        int len) {
    if (ctx == 0) return;
    Private* p = (Private*)ctx;
    if (p->idx == 0) return;

    // skip whitespace
    const char* end = ch+len;
    while (ch < end && isspace(*ch)) ch++;
    if (ch == end) return;
    len = end-ch;
    if (p->fieldtype != NONE) {
        if (p->fieldtype == TEXT) {
            p->idx->addText(ch, len);
        } else {
            p->fieldvalue += string(ch, len);
        }
    }
    p->chars += len;
    if (p->chars > 1000000) {
        p->stop = true;
    }
}
void
SaxEndAnalyzer::Private::startElementSAXFunc(void* ctx, const char* name,
        const char** atts) {
    Private* p = (Private*)ctx;
    if (p->depth++ == 0 && strcasecmp((const char*)name, "html") == 0) {
        p->html = true;
    }
    if (strcasecmp((const char*)name, "title") == 0) {
        p->fieldtype = TITLE;
        p->fieldvalue = "";
    }
}
void
SaxEndAnalyzer::Private::endElementSAXFunc(void* ctx, const char* name) {
    Private* p = (Private*)ctx;
    if (p->idx && p->fieldtype == TITLE && p->fieldvalue.size()) {
        p->idx->setField("title", p->fieldvalue);
        p->fieldvalue = "";
    }
    if (p->depth) p->depth--;
    p->fieldtype = TEXT;
}
SaxEndAnalyzer::SaxEndAnalyzer() {
    p = new Private();
}
SaxEndAnalyzer::~SaxEndAnalyzer() {
    delete p;
}

bool
SaxEndAnalyzer::checkHeader(const char* header, int32_t headersize) const {
    p->init(0, header, headersize);
    return !p->error;
}

char
SaxEndAnalyzer::analyze(std::string filename, jstreams::InputStream *in,
        int depth, StreamIndexer *indexer, Indexable* i) {

    const char* b;
    int32_t nread = in->read(b, 4, 0);
    if (nread >= 4) {
        p->init(i, b, nread);
        nread = in->read(b, 1, 0);
    }
    while (nread > 0 && !p->stop) {
        p->push(b, nread);
        nread = in->read(b, 1, 0);
    }
    p->finish();
/*    if (p->ctxt->encoding) {
        i->setField("encoding", (const char*)p->ctxt->encoding);
    }*/
    i->setMimeType("text/xml");
//    i->setField("root", p->rootelement);
    if (nread != Eof) {
        error = in->getError();
        return -1;
    }
    return 0;
}
<commit_msg>Add html mime-type.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "saxendanalyzer.h"
#include "streamindexer.h"
#include "inputstreamreader.h"
#include "indexwriter.h"
#include <expat.h>
using namespace jstreams;
using namespace std;

class SaxEndAnalyzer::Private {
public:
    enum FieldType { NONE, TEXT, TITLE };
    string fieldvalue;
    FieldType fieldtype;
    XML_Parser parser;
    Indexable* idx;
    int chars;
    int depth;
    bool stop;
    bool error;
    bool wellformed;
    bool html;
    string errorstring;

    static void charactersSAXFunc(void* ctx, const char * ch, int len);
    static void startElementSAXFunc(void * ctx, const char * name,
        const char ** atts);
    static void endElementSAXFunc(void * ctx, const char * name);

    Private() {
        idx = 0;
        parser = XML_ParserCreate(NULL);
    }
    ~Private() {
        XML_ParserFree(parser);
    }
    void reset() {
        XML_ParserReset(parser, 0);
        XML_SetElementHandler(this->parser,
            startElementSAXFunc, endElementSAXFunc);
        XML_SetCharacterDataHandler(this->parser, charactersSAXFunc);
        XML_SetUserData(parser, this);
        error = stop = false;
        chars = 0;
        stop = false;
        error = false;
        html = false;
        wellformed = true;
        depth = 0;
    }
    void init(Indexable*i, const char* data, int32_t len) {
        idx = i;
        reset();
        push(data, len);
    }
    void push(const char* data, int32_t len) {
        if (XML_Parse(parser, data, len, false) == 0) {
            XML_Error e = XML_GetErrorCode(parser);
            // handle the error unless it is a tag mismatch in html
            if (!(html && e == XML_ERROR_TAG_MISMATCH)) {
                errorstring = XML_ErrorString(e);
                error = stop = true;
            }
            wellformed = false;
        }
    }
    void finish() {
        XML_Parse(parser, 0, 0, false);
    }
};
void
SaxEndAnalyzer::Private::charactersSAXFunc(void* ctx, const char * ch,
        int len) {
    if (ctx == 0) return;
    Private* p = (Private*)ctx;
    if (p->idx == 0) return;

    // skip whitespace
    const char* end = ch+len;
    while (ch < end && isspace(*ch)) ch++;
    if (ch == end) return;
    len = end-ch;
    if (p->fieldtype != NONE) {
        if (p->fieldtype == TEXT) {
            p->idx->addText(ch, len);
        } else {
            p->fieldvalue += string(ch, len);
        }
    }
    p->chars += len;
    if (p->chars > 1000000) {
        p->stop = true;
    }
}
void
SaxEndAnalyzer::Private::startElementSAXFunc(void* ctx, const char* name,
        const char** atts) {
    Private* p = (Private*)ctx;
    if (p->depth++ == 0 && strcasecmp((const char*)name, "html") == 0) {
        p->html = true;
    }
    if (strcasecmp((const char*)name, "title") == 0) {
        p->fieldtype = TITLE;
        p->fieldvalue = "";
    }
}
void
SaxEndAnalyzer::Private::endElementSAXFunc(void* ctx, const char* name) {
    Private* p = (Private*)ctx;
    if (p->idx && p->fieldtype == TITLE && p->fieldvalue.size()) {
        p->idx->setField("title", p->fieldvalue);
        p->fieldvalue = "";
    }
    if (p->depth) p->depth--;
    p->fieldtype = TEXT;
}
SaxEndAnalyzer::SaxEndAnalyzer() {
    p = new Private();
}
SaxEndAnalyzer::~SaxEndAnalyzer() {
    delete p;
}

bool
SaxEndAnalyzer::checkHeader(const char* header, int32_t headersize) const {
    p->init(0, header, headersize);
    return !p->error;
}

char
SaxEndAnalyzer::analyze(std::string filename, jstreams::InputStream *in,
        int depth, StreamIndexer *indexer, Indexable* i) {

    const char* b;
    int32_t nread = in->read(b, 4, 0);
    if (nread >= 4) {
        p->init(i, b, nread);
        nread = in->read(b, 1, 0);
    }
    while (nread > 0 && !p->stop) {
        p->push(b, nread);
        nread = in->read(b, 1, 0);
    }
    p->finish();
/*    if (p->ctxt->encoding) {
        i->setField("encoding", (const char*)p->ctxt->encoding);
    }*/
    if (p->html) {
        i->setMimeType("text/html");
    } else if (p->wellformed) {
        i->setMimeType("text/xml");
    }
//    i->setField("root", p->rootelement);
    if (nread != Eof) {
        error = in->getError();
        return -1;
    }
    return 0;
}
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Alessandro Tasora
// =============================================================================
//
// Demonstration of using the assets system to create shapes for Irrlicht
// visualization.
// NOTE:the same assets can be used for visualization with the OpenGL module,
// postprocessing with POVray, etc.
//
// =============================================================================

#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChParticlesClones.h"
#include "chrono/physics/ChBodyEasy.h"

#include "chrono_irrlicht/ChIrrApp.h"

#include <irrlicht.h>

// Use the namespace of Chrono
using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::irrlicht;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;

int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create a Chrono::Engine physical system
    ChSystemNSC mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Assets for Irrlicht visualization", core::dimension2d<u32>(800, 600),
                         false, true);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    application.AddTypicalLogo();
    application.AddTypicalSky();
    application.AddTypicalLights();
    application.AddTypicalCamera(core::vector3df(0, 4, -6));

    //
    // EXAMPLE 1:
    //

    // Create a ChBody, and attach some 'assets'
    // that define 3D shapes. These shapes can be shown
    // by Irrlicht or POV postprocessing, etc...
    // Note: these assets are independent from collision shapes!

    // Create a rigid body as usual, and add it
    // to the physical system:
    auto mfloor = std::make_shared<ChBody>();
    mfloor->SetBodyFixed(true);

    // Define a collision shape
    mfloor->GetCollisionModel()->ClearModel();
    mfloor->GetCollisionModel()->AddBox(10, 0.5, 10, ChVector<>(0, -1, 0));
    mfloor->GetCollisionModel()->BuildModel();
    mfloor->SetCollide(true);

    // Add body to system
    application.GetSystem()->Add(mfloor);

    // ==Asset== attach a 'box' shape.
    // Note that assets are managed via shared pointer, so they
    // can also be shared). Do not forget AddAsset() at the end!
    auto mboxfloor = std::make_shared<ChBoxShape>();
    mboxfloor->GetBoxGeometry().Pos = ChVector<>(0, -1, 0);
    mboxfloor->GetBoxGeometry().Size = ChVector<>(10, 0.5, 10);
    mfloor->AddAsset(mboxfloor);

    // ==Asset== attach color asset.
    auto mfloorcolor = std::make_shared<ChColorAsset>();
    mfloorcolor->SetColor(ChColor(0.3f, 0.3f, 0.6f));
    mfloor->AddAsset(mfloorcolor);

    // ==Asset== attach a 'path' shape populated with segments and arc fillets:
    auto mpathfloor = std::make_shared<ChPathShape>();
    ChLineSegment mseg1(ChVector<>(1, 2, 0), ChVector<>(1, 3, 0));
    mpathfloor->GetPathGeometry()->AddSubLine(mseg1);
    ChLineSegment mseg2(ChVector<>(1, 3, 0), ChVector<>(2, 3, 0));
    mpathfloor->GetPathGeometry()->AddSubLine(mseg2);
    ChLineArc marc1(ChCoordsys<>(ChVector<>(2, 3.5, 0)), 0.5, -CH_C_PI_2, CH_C_PI_2);
    mpathfloor->GetPathGeometry()->AddSubLine(marc1);
    mfloor->AddAsset(mpathfloor);

    //
    // EXAMPLE 2:
    //

    // Textures, colors, asset levels with transformations.
    // This section shows how to add more advanced types of assets
    // and how to group assets in ChAssetLevel containers.

    // Create the rigid body as usual (this won't move,
    // it is only for visualization tests)
    auto mbody = std::make_shared<ChBody>();
    mbody->SetBodyFixed(true);
    application.GetSystem()->Add(mbody);

    // ==Asset== Attach a 'sphere' shape
    auto msphere = std::make_shared<ChSphereShape>();
    msphere->GetSphereGeometry().rad = 0.5;
    msphere->GetSphereGeometry().center = ChVector<>(-1, 0, 0);
    mbody->AddAsset(msphere);

    // ==Asset== Attach also a 'box' shape
    auto mbox = std::make_shared<ChBoxShape>();
    mbox->GetBoxGeometry().Pos = ChVector<>(1, 1, 0);
    mbox->GetBoxGeometry().Size = ChVector<>(0.3, 0.5, 0.1);
    mbody->AddAsset(mbox);

    // ==Asset== Attach also a 'cylinder' shape
    auto mcyl = std::make_shared<ChCylinderShape>();
    mcyl->GetCylinderGeometry().p1 = ChVector<>(2, -0.2, 0);
    mcyl->GetCylinderGeometry().p2 = ChVector<>(2.2, 0.5, 0);
    mcyl->GetCylinderGeometry().rad = 0.3;
    mbody->AddAsset(mcyl);

    // ==Asset== Attach also a 'triangle mesh' shape
    auto mmesh = std::make_shared<ChTriangleMeshShape>();
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(0, 1, 0));
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(0, 1, 0.5));
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(1, 1, 0));
    mmesh->GetMesh().getIndicesVertexes().push_back(ChVector<int>(0, 1, 2));
    mbody->AddAsset(mmesh);

    // ==Asset== Attach color. To set colors for all assets
    // in the same level, just add this:
    auto mvisual = std::make_shared<ChColorAsset>();
    mvisual->SetColor(ChColor(0.9f, 0.4f, 0.2f));
    mbody->AddAsset(mvisual);

    // ==Asset== Attach a level that contains other assets.
    // Note: a ChAssetLevel can define a rotation/translation respect to paren level,
    // Note: a ChAssetLevel can contain colors or textures: if any, they affect only objects in the level.
    auto mlevelA = std::make_shared<ChAssetLevel>();

    // ==Asset== Attach, in this level, a 'Wavefront mesh' asset,
    // referencing a .obj file:
    auto mobjmesh = std::make_shared<ChObjShapeFile>();
    mobjmesh->SetFilename(GetChronoDataFile("forklift_body.obj"));
    mlevelA->AddAsset(mobjmesh);

    // ==Asset== Attach also a texture, that will affect only the
    // assets in mlevelA:
    auto mtexture = std::make_shared<ChTexture>();
    mtexture->SetTextureFilename(GetChronoDataFile("bluwhite.png"));
    mlevelA->AddAsset(mtexture);

    // Change the position of mlevelA, thus moving also its sub-assets:
    mlevelA->GetFrame().SetPos(ChVector<>(0, 0, 2));
    mbody->AddAsset(mlevelA);

    // ==Asset== Attach sub level, then add to it an array of sub-levels,
    // each rotated, and each containing a displaced box, thus making a
    // spiral of cubes
    auto mlevelB = std::make_shared<ChAssetLevel>();
    for (int j = 0; j < 20; j++) {
        // ==Asset== the sub sub level..
        auto mlevelC = std::make_shared<ChAssetLevel>();

        // ==Asset== the contained box..
        auto msmallbox = std::make_shared<ChBoxShape>();
        msmallbox->GetBoxGeometry().Pos = ChVector<>(0.4, 0, 0);
        msmallbox->GetBoxGeometry().Size = ChVector<>(0.1, 0.1, 0.01);
        mlevelC->AddAsset(msmallbox);

        ChQuaternion<> mrot;
        mrot.Q_from_AngAxis(j * 21 * CH_C_DEG_TO_RAD, ChVector<>(0, 1, 0));
        mlevelC->GetFrame().SetRot(mrot);
        mlevelC->GetFrame().SetPos(ChVector<>(0, j * 0.02, 0));

        mlevelB->AddAsset(mlevelC);
    }

    mbody->AddAsset(mlevelB);

    // ==Asset== Attach a video camera. This will be used by Irrlicht,
    // or POVray postprocessing, etc. Note that a camera can also be
    // put in a moving object.
    auto mcamera = std::make_shared<ChCamera>();
    mcamera->SetAngle(50);
    mcamera->SetPosition(ChVector<>(-3, 4, -5));
    mcamera->SetAimPoint(ChVector<>(0, 1, 0));
    mbody->AddAsset(mcamera);

    //
    // EXAMPLE 3:
    //

    // Create a ChParticleClones cluster, and attach 'assets'
    // that define a single "sample" 3D shape. This will be shown
    // N times in Irrlicht.
    //***NOTE*** This crashes with Irrlicht 1.8 , it is ok with 1.7.x and 1.8.1 + ,

    // Create the ChParticleClones, populate it with some random particles,
    // and add it to physical system:
    auto mparticles = std::make_shared<ChParticlesClones>();

    // Note: coll. shape, if needed, must be specified before creating particles.
    // This will be shared among all particles in the ChParticlesClones.
    mparticles->GetCollisionModel()->ClearModel();
    mparticles->GetCollisionModel()->AddSphere(0.05);
    mparticles->GetCollisionModel()->BuildModel();
    mparticles->SetCollide(true);

    // Create the random particles
    for (int np = 0; np < 100; ++np)
        mparticles->AddParticle(ChCoordsys<>(ChVector<>(ChRandom() - 2, 1.5, ChRandom() + 2)));

    // Mass and inertia properties.
    // This will be shared among all particles in the ChParticlesClones.
    mparticles->SetMass(0.1);
    mparticles->SetInertiaXX(ChVector<>(0.001,0.001,0.001));

    // Do not forget to add the particle cluster to the system:
    application.GetSystem()->Add(mparticles);

    //  ==Asset== Attach a 'sphere' shape asset.. it will be used as a sample
    // shape to display all particles when rendering in 3D!
    auto mspherepart = std::make_shared<ChSphereShape>();
    mspherepart->GetSphereGeometry().rad = 0.05;
    mparticles->AddAsset(mspherepart);

    ChVector<> displ(1,0.0,0);
    std::vector< ChVector<> > mpoints;
    mpoints.push_back( ChVector<>(0.8,0.0,0.0)+displ );
    mpoints.push_back( ChVector<>(0.8,0.3,0.0)+displ );
    mpoints.push_back( ChVector<>(0.8,0.3,0.3)+displ );
    mpoints.push_back( ChVector<>(0.0,0.3,0.3)+displ );
    mpoints.push_back( ChVector<>(0.0,0.0,0.3)+displ );
    mpoints.push_back( ChVector<>(0.8,0.0,0.3)+displ );
    auto mhull = std::make_shared<ChBodyEasyConvexHullAuxRef>(mpoints, 1000, true, true);
    //mhull->SetFrame_REF_to_abs(ChFrame<>(ChVector<>(2,0.3,0)));
    //mhull->SetPos(ChVector<>(2,0.3,0));
    mhull->Move(ChVector<>(2,0.3,0));
    application.GetSystem()->Add(mhull);

    ////////////////////////

    // ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
    // in the system. These ChIrrNodeAsset assets are 'proxies' to the Irrlicht meshes.
    // If you need a finer control on which item really needs a visualization proxy in
    // Irrlicht, just use application.AssetBind(myitem); on a per-item basis.

    application.AssetBindAll();

    // ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
    // that you added to the bodies into 3D shapes, they can be visualized by Irrlicht!

    application.AssetUpdateAll();

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    application.SetStepManage(true);
    application.SetTimestep(0.01);
    application.SetTryRealtime(true);

    while (application.GetDevice()->run()) {
        application.BeginScene();

        application.DrawAll();

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
<commit_msg>Demonstrate how to use NURBS assets (both line and surface)<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Alessandro Tasora
// =============================================================================
//
// Demonstration of using the assets system to create shapes for Irrlicht
// visualization.
// NOTE:the same assets can be used for visualization with the OpenGL module,
// postprocessing with POVray, etc.
//
// =============================================================================

#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChParticlesClones.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/geometry/ChLineNurbs.h"
#include "chrono/geometry/ChSurfaceNurbs.h"
#include "chrono/assets/ChSurfaceShape.h"
#include "chrono_irrlicht/ChIrrApp.h"

#include <irrlicht.h>

// Use the namespace of Chrono
using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::irrlicht;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;

int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create a Chrono::Engine physical system
    ChSystemNSC mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Assets for Irrlicht visualization", core::dimension2d<u32>(800, 600),
                         false, true);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    application.AddTypicalLogo();
    application.AddTypicalSky();
    application.AddTypicalLights();
    application.AddTypicalCamera(core::vector3df(0, 4, -6));

    //
    // EXAMPLE 1:
    //

    // Create a ChBody, and attach some 'assets'
    // that define 3D shapes. These shapes can be shown
    // by Irrlicht or POV postprocessing, etc...
    // Note: these assets are independent from collision shapes!

    // Create a rigid body as usual, and add it
    // to the physical system:
    auto mfloor = std::make_shared<ChBody>();
    mfloor->SetBodyFixed(true);

    // Define a collision shape
    mfloor->GetCollisionModel()->ClearModel();
    mfloor->GetCollisionModel()->AddBox(10, 0.5, 10, ChVector<>(0, -1, 0));
    mfloor->GetCollisionModel()->BuildModel();
    mfloor->SetCollide(true);

    // Add body to system
    application.GetSystem()->Add(mfloor);

    // ==Asset== attach a 'box' shape.
    // Note that assets are managed via shared pointer, so they
    // can also be shared). Do not forget AddAsset() at the end!
    auto mboxfloor = std::make_shared<ChBoxShape>();
    mboxfloor->GetBoxGeometry().Pos = ChVector<>(0, -1, 0);
    mboxfloor->GetBoxGeometry().Size = ChVector<>(10, 0.5, 10);
    mfloor->AddAsset(mboxfloor);

    // ==Asset== attach color asset.
    auto mfloorcolor = std::make_shared<ChColorAsset>();
    mfloorcolor->SetColor(ChColor(0.3f, 0.3f, 0.6f));
    mfloor->AddAsset(mfloorcolor);

    // ==Asset== attach a 'path' shape populated with segments and arc fillets:
    auto mpathfloor = std::make_shared<ChPathShape>();
    ChLineSegment mseg1(ChVector<>(1, 2, 0), ChVector<>(1, 3, 0));
    mpathfloor->GetPathGeometry()->AddSubLine(mseg1);
    ChLineSegment mseg2(ChVector<>(1, 3, 0), ChVector<>(2, 3, 0));
    mpathfloor->GetPathGeometry()->AddSubLine(mseg2);
    ChLineArc marc1(ChCoordsys<>(ChVector<>(2, 3.5, 0)), 0.5, -CH_C_PI_2, CH_C_PI_2);
    mpathfloor->GetPathGeometry()->AddSubLine(marc1);
    mfloor->AddAsset(mpathfloor);

	// ==Asset== attach a 'nurbs line' shape:
	// (first you create the ChLineNurbs geometry,
	// then you put it inside a ChLineShape asset)
	auto mnurbs = std::make_shared<ChLineNurbs>();
	std::vector<ChVector<>> controlpoints = { ChVector<>(1,2,-1), ChVector<>(1,3,-1), ChVector<>(1,3,-2), ChVector<>(1,4,-2) };
	mnurbs->SetupData(3, controlpoints);

	auto mnurbsasset = std::make_shared<ChLineShape>();
	mnurbsasset->SetLineGeometry(mnurbs);
	mfloor->AddAsset(mnurbsasset);

	// ==Asset== attach a 'nurbs surface' shape:
	// (first you create the ChSurfaceNurbs geometry,
	// then you put it inside a ChSurfaceShape asset)
	auto msurf = std::make_shared<ChSurfaceNurbs>();
	ChMatrixDynamic<ChVector<>> surfpoints(4, 2); // u points, v points
	surfpoints(0, 0) = ChVector<>(1, 2, 3);
	surfpoints(1, 0) = ChVector<>(1, 3, 3);
	surfpoints(2, 0) = ChVector<>(2, 3, 3);
	surfpoints(3, 0) = ChVector<>(2, 4, 3);
	surfpoints(0, 1) = ChVector<>(1, 2, 1);
	surfpoints(1, 1) = ChVector<>(1, 3, 1);
	surfpoints(2, 1) = ChVector<>(3, 3, 1);
	surfpoints(3, 1) = ChVector<>(2, 4, 1);
	msurf->SetupData(3, 1, surfpoints);

	auto msurfasset = std::make_shared<ChSurfaceShape>();
	msurfasset->Pos = ChVector<>(3, -1, 3);
	msurfasset->SetSurfaceGeometry(msurf);
	msurfasset->SetWireframe(true);
	mfloor->AddAsset(msurfasset);

    //
    // EXAMPLE 2:
    //

    // Textures, colors, asset levels with transformations.
    // This section shows how to add more advanced types of assets
    // and how to group assets in ChAssetLevel containers.

    // Create the rigid body as usual (this won't move,
    // it is only for visualization tests)
    auto mbody = std::make_shared<ChBody>();
    mbody->SetBodyFixed(true);
    application.GetSystem()->Add(mbody);

    // ==Asset== Attach a 'sphere' shape
    auto msphere = std::make_shared<ChSphereShape>();
    msphere->GetSphereGeometry().rad = 0.5;
    msphere->GetSphereGeometry().center = ChVector<>(-1, 0, 0);
    mbody->AddAsset(msphere);

    // ==Asset== Attach also a 'box' shape
    auto mbox = std::make_shared<ChBoxShape>();
    mbox->GetBoxGeometry().Pos = ChVector<>(1, 1, 0);
    mbox->GetBoxGeometry().Size = ChVector<>(0.3, 0.5, 0.1);
    mbody->AddAsset(mbox);

    // ==Asset== Attach also a 'cylinder' shape
    auto mcyl = std::make_shared<ChCylinderShape>();
    mcyl->GetCylinderGeometry().p1 = ChVector<>(2, -0.2, 0);
    mcyl->GetCylinderGeometry().p2 = ChVector<>(2.2, 0.5, 0);
    mcyl->GetCylinderGeometry().rad = 0.3;
    mbody->AddAsset(mcyl);

    // ==Asset== Attach also a 'triangle mesh' shape
    auto mmesh = std::make_shared<ChTriangleMeshShape>();
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(0, 1, 0));
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(0, 1, 0.5));
    mmesh->GetMesh().getCoordsVertices().push_back(ChVector<>(1, 1, 0));
    mmesh->GetMesh().getIndicesVertexes().push_back(ChVector<int>(0, 1, 2));
    mbody->AddAsset(mmesh);

    // ==Asset== Attach color. To set colors for all assets
    // in the same level, just add this:
    auto mvisual = std::make_shared<ChColorAsset>();
    mvisual->SetColor(ChColor(0.9f, 0.4f, 0.2f));
    mbody->AddAsset(mvisual);

    // ==Asset== Attach a level that contains other assets.
    // Note: a ChAssetLevel can define a rotation/translation respect to paren level,
    // Note: a ChAssetLevel can contain colors or textures: if any, they affect only objects in the level.
    auto mlevelA = std::make_shared<ChAssetLevel>();

    // ==Asset== Attach, in this level, a 'Wavefront mesh' asset,
    // referencing a .obj file:
    auto mobjmesh = std::make_shared<ChObjShapeFile>();
    mobjmesh->SetFilename(GetChronoDataFile("forklift_body.obj"));
    mlevelA->AddAsset(mobjmesh);

    // ==Asset== Attach also a texture, that will affect only the
    // assets in mlevelA:
    auto mtexture = std::make_shared<ChTexture>();
    mtexture->SetTextureFilename(GetChronoDataFile("bluwhite.png"));
    mlevelA->AddAsset(mtexture);

    // Change the position of mlevelA, thus moving also its sub-assets:
    mlevelA->GetFrame().SetPos(ChVector<>(0, 0, 2));
    mbody->AddAsset(mlevelA);

    // ==Asset== Attach sub level, then add to it an array of sub-levels,
    // each rotated, and each containing a displaced box, thus making a
    // spiral of cubes
    auto mlevelB = std::make_shared<ChAssetLevel>();
    for (int j = 0; j < 20; j++) {
        // ==Asset== the sub sub level..
        auto mlevelC = std::make_shared<ChAssetLevel>();

        // ==Asset== the contained box..
        auto msmallbox = std::make_shared<ChBoxShape>();
        msmallbox->GetBoxGeometry().Pos = ChVector<>(0.4, 0, 0);
        msmallbox->GetBoxGeometry().Size = ChVector<>(0.1, 0.1, 0.01);
        mlevelC->AddAsset(msmallbox);

        ChQuaternion<> mrot;
        mrot.Q_from_AngAxis(j * 21 * CH_C_DEG_TO_RAD, ChVector<>(0, 1, 0));
        mlevelC->GetFrame().SetRot(mrot);
        mlevelC->GetFrame().SetPos(ChVector<>(0, j * 0.02, 0));

        mlevelB->AddAsset(mlevelC);
    }

    mbody->AddAsset(mlevelB);

    // ==Asset== Attach a video camera. This will be used by Irrlicht,
    // or POVray postprocessing, etc. Note that a camera can also be
    // put in a moving object.
    auto mcamera = std::make_shared<ChCamera>();
    mcamera->SetAngle(50);
    mcamera->SetPosition(ChVector<>(-3, 4, -5));
    mcamera->SetAimPoint(ChVector<>(0, 1, 0));
    mbody->AddAsset(mcamera);

    //
    // EXAMPLE 3:
    //

    // Create a ChParticleClones cluster, and attach 'assets'
    // that define a single "sample" 3D shape. This will be shown
    // N times in Irrlicht.
    //***NOTE*** This crashes with Irrlicht 1.8 , it is ok with 1.7.x and 1.8.1 + ,

    // Create the ChParticleClones, populate it with some random particles,
    // and add it to physical system:
    auto mparticles = std::make_shared<ChParticlesClones>();

    // Note: coll. shape, if needed, must be specified before creating particles.
    // This will be shared among all particles in the ChParticlesClones.
    mparticles->GetCollisionModel()->ClearModel();
    mparticles->GetCollisionModel()->AddSphere(0.05);
    mparticles->GetCollisionModel()->BuildModel();
    mparticles->SetCollide(true);

    // Create the random particles
    for (int np = 0; np < 100; ++np)
        mparticles->AddParticle(ChCoordsys<>(ChVector<>(ChRandom() - 2, 1.5, ChRandom() + 2)));

    // Mass and inertia properties.
    // This will be shared among all particles in the ChParticlesClones.
    mparticles->SetMass(0.1);
    mparticles->SetInertiaXX(ChVector<>(0.001,0.001,0.001));

    // Do not forget to add the particle cluster to the system:
    application.GetSystem()->Add(mparticles);

    //  ==Asset== Attach a 'sphere' shape asset.. it will be used as a sample
    // shape to display all particles when rendering in 3D!
    auto mspherepart = std::make_shared<ChSphereShape>();
    mspherepart->GetSphereGeometry().rad = 0.05;
    mparticles->AddAsset(mspherepart);

    ChVector<> displ(1,0.0,0);
    std::vector< ChVector<> > mpoints;
    mpoints.push_back( ChVector<>(0.8,0.0,0.0)+displ );
    mpoints.push_back( ChVector<>(0.8,0.3,0.0)+displ );
    mpoints.push_back( ChVector<>(0.8,0.3,0.3)+displ );
    mpoints.push_back( ChVector<>(0.0,0.3,0.3)+displ );
    mpoints.push_back( ChVector<>(0.0,0.0,0.3)+displ );
    mpoints.push_back( ChVector<>(0.8,0.0,0.3)+displ );
    auto mhull = std::make_shared<ChBodyEasyConvexHullAuxRef>(mpoints, 1000, true, true);
    //mhull->SetFrame_REF_to_abs(ChFrame<>(ChVector<>(2,0.3,0)));
    //mhull->SetPos(ChVector<>(2,0.3,0));
    mhull->Move(ChVector<>(2,0.3,0));
    application.GetSystem()->Add(mhull);

    ////////////////////////

    // ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
    // in the system. These ChIrrNodeAsset assets are 'proxies' to the Irrlicht meshes.
    // If you need a finer control on which item really needs a visualization proxy in
    // Irrlicht, just use application.AssetBind(myitem); on a per-item basis.

    application.AssetBindAll();

    // ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
    // that you added to the bodies into 3D shapes, they can be visualized by Irrlicht!

    application.AssetUpdateAll();

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    application.SetStepManage(true);
    application.SetTimestep(0.01);
    application.SetTryRealtime(true);

    while (application.GetDevice()->run()) {
        application.BeginScene();

        application.DrawAll();

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>

// stl
#include <ctime>

#ifndef MAPNIK_LOG_FORMAT
#define MAPNIK_LOG_FORMAT "Mapnik LOG> %Y-%m-%d %H:%M:%S:"
#endif

#ifndef MAPNIK_DEFAULT_LOG_SEVERITY
  #ifdef MAPNIK_DEBUG
    #define MAPNIK_DEFAULT_LOG_SEVERITY 0
  #else
    #define MAPNIK_DEFAULT_LOG_SEVERITY 2
  #endif
#endif

namespace mapnik {

// mutexes

#ifdef MAPNIK_THREADSAFE
boost::mutex logger::severity_mutex_;
boost::mutex logger::format_mutex_;
#endif

// first time checks

bool logger::severity_env_check_ = true;
bool logger::format_env_check_ = true;

// severity

logger::severity_type logger::severity_level_ =
    #if MAPNIK_DEFAULT_LOG_SEVERITY == 0
        logger::debug
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 1
        logger::warn
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 2
        logger::error
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 3
        logger::none
    #else
        #error "Wrong default log severity level specified!"
    #endif
;

logger::severity_map logger::object_severity_level_ = logger::severity_map();

// format

#define __xstr__(s) __str__(s)
#define __str__(s) #s
std::string logger::format_ = __xstr__(MAPNIK_LOG_FORMAT);
#undef __xstr__
#undef __str__

std::string logger::str()
{
#if 0
    // update the format from getenv if this is the first time
    if (logger::format_env_check_)
    {
        logger::format_env_check_ = false;

        const char* log_format = getenv("MAPNIK_LOG_FORMAT");
        if (log_format != NULL)
        {
            logger::format_ = log_format;
        }
    }
#endif

    char buf[256];
    const time_t tm = time(0);
    strftime(buf, sizeof(buf), logger::format_.c_str(), localtime(&tm));
    return buf;
}

// output

std::ofstream logger::file_output_;
std::string logger::file_name_;
std::streambuf* logger::saved_buf_ = 0;

void logger::use_file(std::string const& filepath)
{
    // save clog rdbuf
    if (saved_buf_ == 0)
    {
        saved_buf_ = std::clog.rdbuf();
    }

    // use a file to output as clog rdbuf
    if (file_name_ != filepath)
    {
        file_name_ = filepath;

        if (file_output_.is_open())
        {
            file_output_.close();
        }

        file_output_.open(file_name_.c_str(), std::ios::out | std::ios::app);
        if (file_output_)
        {
            std::clog.rdbuf(file_output_.rdbuf());
        }
        else
        {
            std::stringstream s;
            s << "cannot redirect log to file " << file_output_;
            throw std::runtime_error(s.str());
        }
    }
}

void logger::use_console()
{
    // save clog rdbuf
    if (saved_buf_ == 0)
    {
        saved_buf_ = std::clog.rdbuf();
    }

    // close the file to force a flush
    if (file_output_.is_open())
    {
        file_output_.close();
    }

    std::clog.rdbuf(saved_buf_);
}

} // namespace mapnik
<commit_msg>- avoid using double quotes when already escaping as string<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>

// stl
#include <ctime>

#ifndef MAPNIK_LOG_FORMAT
  #define MAPNIK_LOG_FORMAT  Mapnik LOG> %Y-%m-%d %H:%M:%S:
#endif

#ifndef MAPNIK_DEFAULT_LOG_SEVERITY
  #ifdef MAPNIK_DEBUG
    #define MAPNIK_DEFAULT_LOG_SEVERITY 0
  #else
    #define MAPNIK_DEFAULT_LOG_SEVERITY 2
  #endif
#endif

namespace mapnik {

// mutexes

#ifdef MAPNIK_THREADSAFE
boost::mutex logger::severity_mutex_;
boost::mutex logger::format_mutex_;
#endif

// first time checks

bool logger::severity_env_check_ = true;
bool logger::format_env_check_ = true;

// severity

logger::severity_type logger::severity_level_ =
    #if MAPNIK_DEFAULT_LOG_SEVERITY == 0
        logger::debug
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 1
        logger::warn
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 2
        logger::error
    #elif MAPNIK_DEFAULT_LOG_SEVERITY == 3
        logger::none
    #else
        #error "Wrong default log severity level specified!"
    #endif
;

logger::severity_map logger::object_severity_level_ = logger::severity_map();

// format

#define __xstr__(s) __str__(s)
#define __str__(s) #s
std::string logger::format_ = __xstr__(MAPNIK_LOG_FORMAT);
#undef __xstr__
#undef __str__

std::string logger::str()
{
#if 0
    // update the format from getenv if this is the first time
    if (logger::format_env_check_)
    {
        logger::format_env_check_ = false;

        const char* log_format = getenv("MAPNIK_LOG_FORMAT");
        if (log_format != NULL)
        {
            logger::format_ = log_format;
        }
    }
#endif

    char buf[256];
    const time_t tm = time(0);
    strftime(buf, sizeof(buf), logger::format_.c_str(), localtime(&tm));
    return buf;
}

// output

std::ofstream logger::file_output_;
std::string logger::file_name_;
std::streambuf* logger::saved_buf_ = 0;

void logger::use_file(std::string const& filepath)
{
    // save clog rdbuf
    if (saved_buf_ == 0)
    {
        saved_buf_ = std::clog.rdbuf();
    }

    // use a file to output as clog rdbuf
    if (file_name_ != filepath)
    {
        file_name_ = filepath;

        if (file_output_.is_open())
        {
            file_output_.close();
        }

        file_output_.open(file_name_.c_str(), std::ios::out | std::ios::app);
        if (file_output_)
        {
            std::clog.rdbuf(file_output_.rdbuf());
        }
        else
        {
            std::stringstream s;
            s << "cannot redirect log to file " << file_output_;
            throw std::runtime_error(s.str());
        }
    }
}

void logger::use_console()
{
    // save clog rdbuf
    if (saved_buf_ == 0)
    {
        saved_buf_ = std::clog.rdbuf();
    }

    // close the file to force a flush
    if (file_output_.is_open())
    {
        file_output_.close();
    }

    std::clog.rdbuf(saved_buf_);
}

} // namespace mapnik
<|endoftext|>


<commit_before>#include "dioptre/physics/bullet/physics.h"
#include "dioptre/physics/bullet/shape.h"
#include "dioptre/locator.h"

#include <iostream>

namespace dioptre {
namespace physics {
namespace bullet {

int Physics::initialize() {
  broadphase_ = std::unique_ptr<btBroadphaseInterface>(new btDbvtBroadphase());
  collisionConfiguration_ = std::unique_ptr<btDefaultCollisionConfiguration>(new btDefaultCollisionConfiguration());
  dispatcher_ = std::unique_ptr<btCollisionDispatcher>(new btCollisionDispatcher(collisionConfiguration_.get()));
  solver_ = std::unique_ptr<btSequentialImpulseConstraintSolver>(new btSequentialImpulseConstraintSolver);

  dynamicsWorld_ = std::unique_ptr<btDiscreteDynamicsWorld>(new btDiscreteDynamicsWorld(dispatcher_.get(), broadphase_.get(), solver_.get(), collisionConfiguration_.get()));

  auto gravity = world_->getGravity();
  dynamicsWorld_->setGravity(btVector3(gravity.x, gravity.y, gravity.z));

  debugDrawer_ = std::unique_ptr<DebugDrawer>(new DebugDrawer());
  debugDrawer_->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
  dynamicsWorld_->setDebugDrawer(debugDrawer_.get());

  LOG4CXX_INFO(logger_, "Bullet engine initialized.");

  return 0;
}

void Physics::initializeWorld() {
  LOG4CXX_INFO(logger_, "Initializing physics world.");
  for (auto it = world_->begin(); it != world_->end(); it++) {
    initializeRigidBody(*it);
  }
}

void Physics::initializeRigidBody(dioptre::physics::RigidBody* body) {
  auto shape = dynamic_cast<dioptre::physics::bullet::Shape*>(body->getShape());
  btCollisionShape* boxCollisionShape = shape->getCollisionShape();

  auto component = body->getComponent();
  auto object = component->getObject();
  auto transform = object->getTransform();
  auto position = transform->getPosition();
  auto orientation = body->getComponent()->getObject()->getTransform()->getOrientation();
  auto inertia = body->getInertia();
  auto mass = body->getMass();

  LOG4CXX_INFO(logger_, "Initializing rigid body." << object->getName());

  btDefaultMotionState* motionstate = new btDefaultMotionState(btTransform(
    btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w),
    btVector3(position.x, position.y, position.z)
  ));

  btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(
      mass, // mass, in kg. 0 -> Static object, will never move.
      motionstate,
      boxCollisionShape, // collision shape of body
      btVector3(inertia.x, inertia.y, inertia.z) // local inertia
      );

  btRigidBody *rigidBody = new btRigidBody(rigidBodyCI);

  rigidBodies_.push_back(rigidBody);
  dynamicsWorld_->addRigidBody(rigidBody);

  rigidBody->setUserPointer(object);
}

void ScreenPosToWorldRay(
    double mouseX, double mouseY,             // Mouse position, in pixels, from bottom-left corner of the window
    int screenWidth, int screenHeight,  // Window size, in pixels
    glm::mat4 ViewMatrix,               // Camera position and orientation
    glm::mat4 ProjectionMatrix,         // Camera parameters (ratio, field of view, near and far planes)
    glm::vec3& out_origin,              // Ouput : Origin of the ray. /!\ Starts at the near plane, so if you want the ray to start at the camera's position instead, ignore this.
    glm::vec3& out_direction            // Ouput : Direction, in world space, of the ray that goes "through" the mouse.
    ){

  // The ray Start and End positions, in Normalized Device Coordinates (Have you read Tutorial 4 ?)
  glm::vec4 lRayStart_NDC(
      ((float)mouseX/(float)screenWidth  - 0.5f) * 2.0f, // [0,1024] -> [-1,1]
      ((float)mouseY/(float)screenHeight - 0.5f) * 2.0f, // [0, 768] -> [-1,1]
      -1.0, // The near plane maps to Z=-1 in Normalized Device Coordinates
      1.0f
      );
  glm::vec4 lRayEnd_NDC(
      ((float)mouseX/(float)screenWidth  - 0.5f) * 2.0f,
      ((float)mouseY/(float)screenHeight - 0.5f) * 2.0f,
      0.0,
      1.0f
      );

  // Faster way (just one inverse)
  glm::mat4 M = glm::inverse(ProjectionMatrix * ViewMatrix);
  glm::vec4 lRayStart_world = M * lRayStart_NDC; lRayStart_world/=lRayStart_world.w;
  glm::vec4 lRayEnd_world   = M * lRayEnd_NDC  ; lRayEnd_world  /=lRayEnd_world.w;

  glm::vec3 lRayDir_world(lRayEnd_world - lRayStart_world);
  lRayDir_world = glm::normalize(lRayDir_world);

  out_origin = glm::vec3(lRayStart_world);
  out_direction = glm::normalize(lRayDir_world);
}

void Physics::castRay(dioptre::mouse::Position position) {
  LOG4CXX_INFO(logger_, "Casting ray at:" << position.x << "x" << position.y);

  auto graphics = dioptre::Locator::getInstance<dioptre::graphics::GraphicsInterface>(dioptre::Module::M_GRAPHICS);
  auto debug = graphics->getDebug();
  auto camera = graphics->getCamera();
  auto window = dioptre::Locator::getInstance<dioptre::window::WindowInterface>(dioptre::Module::M_WINDOW);
  auto size = window->getSize();

  auto view = glm::inverse(camera->getTransform()->getMatrix());
  auto projection = camera->getProjectionMatrix();

  position.y = size.height - position.y;
  glm::vec3 rayStart;
  glm::vec3 rayDirection;
  ScreenPosToWorldRay(
      position.x, position.y,
      size.width, size.height,
      view,
      projection,
      rayStart,
      rayDirection
    );

  rayDirection = rayDirection * 100000.0f;
  btCollisionWorld::ClosestRayResultCallback rayCallback(btVector3(rayStart.x, rayStart.y, rayStart.z),
                                                         btVector3(rayDirection.x, rayDirection.y, rayDirection.z));

  dynamicsWorld_->rayTest(btVector3(rayStart.x, rayStart.y, rayStart.z),
                          btVector3(rayDirection.x, rayDirection.y, rayDirection.z),
                          rayCallback);

  if (rayCallback.hasHit()) {
    LOG4CXX_INFO(logger_, "Ray hit object.");

    auto hitPoint = rayCallback.m_hitPointWorld;
    debug->addCross(glm::vec3(hitPoint.x(), hitPoint.y(), hitPoint.z()));

    dioptre::Object* object = static_cast<dioptre::Object*>(rayCallback.m_collisionObject->getUserPointer());
    std::cout << object->getName() << "; X:" << hitPoint.x() << ", Y:" << hitPoint.y() << "; Z:" << hitPoint.z() << std::endl;
  } else {
    LOG4CXX_INFO(logger_, "Ray hit background.");
  }
}

void Physics::debug() {
  auto graphics = dioptre::Locator::getInstance<dioptre::graphics::GraphicsInterface>(dioptre::Module::M_GRAPHICS);
  auto debug = graphics->getDebug();

  if (debug) {
    debug->reset();
  }

  dynamicsWorld_->debugDrawWorld();
}

void Physics::simulate() {

}

void Physics::destroy() {

}

} // bullet
} // physics
} // dioptre
<commit_msg>use ray endpoint instead of ray direction<commit_after>#include "dioptre/physics/bullet/physics.h"
#include "dioptre/physics/bullet/shape.h"
#include "dioptre/locator.h"

#include <iostream>

namespace dioptre {
namespace physics {
namespace bullet {

int Physics::initialize() {
  broadphase_ = std::unique_ptr<btBroadphaseInterface>(new btDbvtBroadphase());
  collisionConfiguration_ = std::unique_ptr<btDefaultCollisionConfiguration>(new btDefaultCollisionConfiguration());
  dispatcher_ = std::unique_ptr<btCollisionDispatcher>(new btCollisionDispatcher(collisionConfiguration_.get()));
  solver_ = std::unique_ptr<btSequentialImpulseConstraintSolver>(new btSequentialImpulseConstraintSolver);

  dynamicsWorld_ = std::unique_ptr<btDiscreteDynamicsWorld>(new btDiscreteDynamicsWorld(dispatcher_.get(), broadphase_.get(), solver_.get(), collisionConfiguration_.get()));

  auto gravity = world_->getGravity();
  dynamicsWorld_->setGravity(btVector3(gravity.x, gravity.y, gravity.z));

  debugDrawer_ = std::unique_ptr<DebugDrawer>(new DebugDrawer());
  debugDrawer_->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
  dynamicsWorld_->setDebugDrawer(debugDrawer_.get());

  LOG4CXX_INFO(logger_, "Bullet engine initialized.");

  return 0;
}

void Physics::initializeWorld() {
  LOG4CXX_INFO(logger_, "Initializing physics world.");
  for (auto it = world_->begin(); it != world_->end(); it++) {
    initializeRigidBody(*it);
  }
}

void Physics::initializeRigidBody(dioptre::physics::RigidBody* body) {
  auto shape = dynamic_cast<dioptre::physics::bullet::Shape*>(body->getShape());
  btCollisionShape* boxCollisionShape = shape->getCollisionShape();

  auto component = body->getComponent();
  auto object = component->getObject();
  auto transform = object->getTransform();
  auto position = transform->getPosition();
  auto orientation = body->getComponent()->getObject()->getTransform()->getOrientation();
  auto inertia = body->getInertia();
  auto mass = body->getMass();

  LOG4CXX_INFO(logger_, "Initializing rigid body." << object->getName());

  btDefaultMotionState* motionstate = new btDefaultMotionState(btTransform(
    btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w),
    btVector3(position.x, position.y, position.z)
  ));

  btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(
      mass, // mass, in kg. 0 -> Static object, will never move.
      motionstate,
      boxCollisionShape, // collision shape of body
      btVector3(inertia.x, inertia.y, inertia.z) // local inertia
      );

  btRigidBody *rigidBody = new btRigidBody(rigidBodyCI);

  rigidBodies_.push_back(rigidBody);
  dynamicsWorld_->addRigidBody(rigidBody);

  rigidBody->setUserPointer(object);
}

void ScreenPosToWorldRay(
    double mouseX, double mouseY,             // Mouse position, in pixels, from bottom-left corner of the window
    int screenWidth, int screenHeight,  // Window size, in pixels
    glm::mat4 ViewMatrix,               // Camera position and orientation
    glm::mat4 ProjectionMatrix,         // Camera parameters (ratio, field of view, near and far planes)
    glm::vec3& out_origin,              // Ouput : Origin of the ray. /!\ Starts at the near plane, so if you want the ray to start at the camera's position instead, ignore this.
    glm::vec3& out_direction            // Ouput : Direction, in world space, of the ray that goes "through" the mouse.
    ){

  // The ray Start and End positions, in Normalized Device Coordinates (Have you read Tutorial 4 ?)
  glm::vec4 lRayStart_NDC(
      ((float)mouseX/(float)screenWidth  - 0.5f) * 2.0f, // [0,1024] -> [-1,1]
      ((float)mouseY/(float)screenHeight - 0.5f) * 2.0f, // [0, 768] -> [-1,1]
      -1.0, // The near plane maps to Z=-1 in Normalized Device Coordinates
      1.0f
      );
  glm::vec4 lRayEnd_NDC(
      ((float)mouseX/(float)screenWidth  - 0.5f) * 2.0f,
      ((float)mouseY/(float)screenHeight - 0.5f) * 2.0f,
      0.0,
      1.0f
      );

  // Faster way (just one inverse)
  glm::mat4 M = glm::inverse(ProjectionMatrix * ViewMatrix);
  glm::vec4 lRayStart_world = M * lRayStart_NDC; lRayStart_world/=lRayStart_world.w;
  glm::vec4 lRayEnd_world   = M * lRayEnd_NDC  ; lRayEnd_world  /=lRayEnd_world.w;

  glm::vec3 lRayDir_world(lRayEnd_world - lRayStart_world);
  lRayDir_world = glm::normalize(lRayDir_world);

  out_origin = glm::vec3(lRayStart_world);
  out_direction = glm::normalize(lRayDir_world);
}

void Physics::castRay(dioptre::mouse::Position position) {
  LOG4CXX_INFO(logger_, "Casting ray at:" << position.x << "x" << position.y);

  auto graphics = dioptre::Locator::getInstance<dioptre::graphics::GraphicsInterface>(dioptre::Module::M_GRAPHICS);
  auto debug = graphics->getDebug();
  auto camera = graphics->getCamera();
  auto window = dioptre::Locator::getInstance<dioptre::window::WindowInterface>(dioptre::Module::M_WINDOW);
  auto size = window->getSize();

  auto view = glm::inverse(camera->getTransform()->getMatrix());
  auto projection = camera->getProjectionMatrix();

  position.y = size.height - position.y;
  glm::vec3 rayStart;
  glm::vec3 rayEnd;
  glm::vec3 rayDirection;
  ScreenPosToWorldRay(
      position.x, position.y,
      size.width, size.height,
      view,
      projection,
      rayStart,
      rayDirection
  );

  rayDirection = rayDirection * 1000.0f;
  rayEnd = rayStart + rayDirection;

  btCollisionWorld::ClosestRayResultCallback rayCallback(btVector3(rayStart.x, rayStart.y, rayStart.z),
                                                         btVector3(rayEnd.x, rayEnd.y, rayEnd.z));

  dynamicsWorld_->rayTest(btVector3(rayStart.x, rayStart.y, rayStart.z),
                          btVector3(rayEnd.x, rayEnd.y, rayEnd.z),
                          rayCallback);

  if (rayCallback.hasHit()) {
    LOG4CXX_INFO(logger_, "Ray hit object.");

    auto hitPoint = rayCallback.m_hitPointWorld;
    debug->addCross(glm::vec3(hitPoint.x(), hitPoint.y(), hitPoint.z()));

    dioptre::Object* object = static_cast<dioptre::Object*>(rayCallback.m_collisionObject->getUserPointer());
    std::cout << object->getName() << "; X:" << hitPoint.x() << ", Y:" << hitPoint.y() << "; Z:" << hitPoint.z() << std::endl;
  } else {
    LOG4CXX_INFO(logger_, "Ray hit background.");
  }
}

void Physics::debug() {
  auto graphics = dioptre::Locator::getInstance<dioptre::graphics::GraphicsInterface>(dioptre::Module::M_GRAPHICS);
  auto debug = graphics->getDebug();

  if (debug) {
    debug->reset();
  }

  dynamicsWorld_->debugDrawWorld();
}

void Physics::simulate() {

}

void Physics::destroy() {

}

} // bullet
} // physics
} // dioptre
<|endoftext|>