<commit_before>/*
 * Mesh3.cpp
 *
 *  Created on: Mar 1, 2016
 *      Author: lurker
 */

#include "Mesh3.h"

Mesh3::Mesh3(MatlabPtr _Vertices, MatlabPtr _PML, MatlabPtr _Vol) noexcept {
	min_vol            = *Matlab_Cast<Real_t>(_Vol);
	auto _VerticesPtr  = Matlab_Cast<Real_t>(_Vertices);
	auto _VerticesSize = mxGetN(_Vertices);

	auto _PMLPtr      = Matlab_Cast<Real_t>(_PML);
	auto _PMLSize     = mxGetN(_PML);

	tetgenio input, mid;

	input.numberofpoints = _VerticesSize;
	input.pointlist = new Real_t[_VerticesSize * 3];

	/*
	 * fill pointlist, _Vertices is column primary.
	 */
	for (int i = 0; i < _VerticesSize; i++) {
		input.pointlist[3 * i    ] = _VerticesPtr[3 * i];
		input.pointlist[3 * i + 1] = _VerticesPtr[3 * i + 1];
		input.pointlist[3 * i + 2] = _VerticesPtr[3 * i + 2];
	}

	tetrahedralize("pzcQ", &input, &mid, (tetgenio*)nullptr, (tetgenio*)nullptr);
	tetrahedralize(
			const_cast<char*>(("prq1.20/18a" + std::to_string(min_vol) + "QzenBC").c_str()),\
			&mid, &_meshdata,(tetgenio*)nullptr, (tetgenio*)nullptr);

	return;
}

Mesh3::~Mesh3() noexcept {
#if DEBUG
	cout << "3D MESH detached." <<"\n";
#endif
}

void Mesh3::Info() noexcept{
  std::cout << "Delaunay information:" << std::endl;
  std::cout << "number of points: " << _meshdata.numberofpoints << std::endl;
  std::cout << "number of edges: " << _meshdata.numberofedges << std::endl;
  std::cout << "number of trifaces: " << _meshdata.numberoftrifaces << std::endl;
  std::cout << "number of tetrahedra: " << _meshdata.numberoftetrahedra << std::endl;
  std::cout << "number of corners: " << _meshdata.numberofcorners << std::endl;

//  for (int i = 0; i < _meshdata.numberoftetrahedra; i++) {
//	  std::cout << i << ": " <<
//			  _meshdata.neighborlist[4 * i]  << ", " <<
//			  _meshdata.neighborlist[4 * i + 1] << "," <<
//			  _meshdata.neighborlist[4 * i + 2] << "," <<
//			  _meshdata.neighborlist[4 * i + 3] << std::endl;
//  }

  for (int i = 0; i < _meshdata.numberoftetrahedra; i++) {
	  std::cout <<  _meshdata.tetrahedronlist[4 * i] << " "
			  <<  _meshdata.tetrahedronlist[4 * i + 1] << " "
			  <<  _meshdata.tetrahedronlist[4 * i + 2] << " "
			  <<  _meshdata.tetrahedronlist[4 * i + 3] << std::endl;
  }

  for (int i = 0; i < _meshdata.numberofpoints; i++) {
	  std::cout << _meshdata.pointlist[3 * i] << " "
			  << _meshdata.pointlist[3 * i + 1] << " "
			  << _meshdata.pointlist[3 * i + 2] << std::endl;
  }

}

void Mesh3::Promote(int32_t _deg) noexcept{
	/*
	 * add quadrature points
	 */
}

template class mexplus::Session<Mesh3>;

namespace {

MEX_DEFINE(new) (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){
	InputArguments input(nrhs, prhs, 3);
	OutputArguments output(nlhs, plhs, 1);
	output.set(0, Session<Mesh3>::create(new Mesh3(
			const_cast<mxArray*>(input.get(0)),
			const_cast<mxArray*>(input.get(1)),
			const_cast<mxArray*>(input.get(2))
	)));
}

// Delete the instance by id
MEX_DEFINE(delete) (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 0);
	Session<Mesh3>::destroy(input.get(0));
}

MEX_DEFINE(report)(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 0);
	auto mesh3 = Session<Mesh3>::get(input.get(0));
	mesh3->Info();
}

MEX_DEFINE(meshdata)(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 2);
	auto mesh3 = Session<Mesh3>::get(input.get(0));
	/*
	 * todo: export information
	 */
	plhs[0] = mxCreateNumericMatrix(3, mesh3->_meshdata.numberofpoints, mxDOUBLE_CLASS, mxREAL);
	memcpy(mxGetPr(plhs[0]), mesh3->_meshdata.pointlist, 3 * mesh3->_meshdata.numberofpoints*sizeof(Real_t));
	plhs[1] = mxCreateNumericMatrix(4, mesh3->_meshdata.numberoftetrahedra, mxINT32_CLASS, mxREAL);
	memcpy(mxGetPr(plhs[1]), mesh3->_meshdata.tetrahedronlist, 4 * mesh3->_meshdata.numberoftetrahedra*sizeof(int32_t));
	MatlabPtr temp[] = {plhs[1], mxCreateDoubleScalar(1.0)};
	mexCallMATLAB(1, &plhs[1], 2, temp, "plus");
}

}

MEX_DISPATCH
<commit_msg>update<commit_after>/*
 * Mesh3.cpp
 *
 *  Created on: Mar 1, 2016
 *      Author: lurker
 */

#include "Mesh3.h"

Mesh3::Mesh3(MatlabPtr _Vertices, MatlabPtr _PML, MatlabPtr _Vol) noexcept {
	min_vol            = *Matlab_Cast<Real_t>(_Vol);
	auto _VerticesPtr  = Matlab_Cast<Real_t>(_Vertices);
	auto _VerticesSize = mxGetN(_Vertices);

	auto _PMLPtr      = Matlab_Cast<Real_t>(_PML);
	auto _PMLSize     = mxGetN(_PML);

	tetgenio input, mid;

	input.numberofpoints = _VerticesSize;
	input.pointlist = new Real_t[_VerticesSize * 3];

	/*
	 * fill pointlist, _Vertices is column primary.
	 */
	for (int i = 0; i < _VerticesSize; i++) {
		input.pointlist[3 * i    ] = _VerticesPtr[3 * i];
		input.pointlist[3 * i + 1] = _VerticesPtr[3 * i + 1];
		input.pointlist[3 * i + 2] = _VerticesPtr[3 * i + 2];
	}

	tetrahedralize("pzcQ", &input, &mid, (tetgenio*)nullptr, (tetgenio*)nullptr);
	tetrahedralize(
			const_cast<char*>(("prq1.20/18a" + std::to_string(min_vol) + "QzenBC").c_str()),\
			&mid, &_meshdata,(tetgenio*)nullptr, (tetgenio*)nullptr);

	return;
}

Mesh3::~Mesh3() noexcept {
#if DEBUG
	cout << "3D MESH detached." <<"\n";
#endif
}

void Mesh3::Info() noexcept{
  std::cout << "Delaunay information:" << std::endl;
  std::cout << "number of points: " << _meshdata.numberofpoints << std::endl;
  std::cout << "number of edges: " << _meshdata.numberofedges << std::endl;
  std::cout << "number of trifaces: " << _meshdata.numberoftrifaces << std::endl;
  std::cout << "number of tetrahedra: " << _meshdata.numberoftetrahedra << std::endl;
  std::cout << "number of corners: " << _meshdata.numberofcorners << std::endl;
}

void Mesh3::Promote(int32_t _deg) noexcept{
	/*
	 * add quadrature points
	 */
}

template class mexplus::Session<Mesh3>;

namespace {

MEX_DEFINE(new) (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){
	InputArguments input(nrhs, prhs, 3);
	OutputArguments output(nlhs, plhs, 1);
	output.set(0, Session<Mesh3>::create(new Mesh3(
			const_cast<mxArray*>(input.get(0)),
			const_cast<mxArray*>(input.get(1)),
			const_cast<mxArray*>(input.get(2))
	)));
}

// Delete the instance by id
MEX_DEFINE(delete) (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 0);
	Session<Mesh3>::destroy(input.get(0));
}

MEX_DEFINE(report)(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 0);
	auto mesh3 = Session<Mesh3>::get(input.get(0));
	mesh3->Info();
}

MEX_DEFINE(meshdata)(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
	InputArguments input(nrhs, prhs, 1);
	OutputArguments output(nlhs, plhs, 2);
	auto mesh3 = Session<Mesh3>::get(input.get(0));
	/*
	 * todo: export information
	 */
	plhs[0] = mxCreateNumericMatrix(3, mesh3->_meshdata.numberofpoints, mxDOUBLE_CLASS, mxREAL);
	memcpy(mxGetPr(plhs[0]), mesh3->_meshdata.pointlist, 3 * mesh3->_meshdata.numberofpoints*sizeof(Real_t));
	plhs[1] = mxCreateNumericMatrix(4, mesh3->_meshdata.numberoftetrahedra, mxINT32_CLASS, mxREAL);
	memcpy(mxGetPr(plhs[1]), mesh3->_meshdata.tetrahedronlist, 4 * mesh3->_meshdata.numberoftetrahedra*sizeof(int32_t));
	MatlabPtr temp[] = {plhs[1], mxCreateDoubleScalar(1.0)};
	mexCallMATLAB(1, &plhs[1], 2, temp, "plus");
}

}

MEX_DISPATCH
<|endoftext|>


<commit_before>#include "Halide.h"

// By convention, Generators always go in a .cpp file, usually with no
// corresponding .h file. They can be enclosed in any C++ namespaces
// you like, but the anonymous namespace is often the best choice.
//
// It's normally considered Best Practice to have exactly one Generator
// per .cpp file, and to have the .cpp file name match the generator name
// with a "_generator" suffix (e.g., Generator with name "foo" should
// live in "foo_generator.cpp"), as it tends to simplify build rules,
// but neither of these are required.

namespace {

enum class SomeEnum { Foo, Bar };

// Note the inheritance using the Curiously Recurring Template Pattern
class Example : public Halide::Generator<Example> {
public:
    // GeneratorParams, ImageParams, and Params are (by convention)
    // always public and always declared at the top of the Generator,
    // in the order
    //    GeneratorParam(s)
    //    ImageParam(s)
    //    Param(s)
    //
    // Note that the ImageParams/Params will appear in the C function
    // call in the order they are declared. (GeneratorParams are always
    // referenced by name, not position, so their order is irrelevant.)
    //
    // All Param variants declared as Generator members must have explicit
    // names, and all such names must match the regex [A-Za-z_][A-Za-z_0-9]*
    // (i.e., essentially a C/C++ variable name). (Note that autogenerated
    // Param names do not match this pattern, and thus will be rejected.)
    // By convention, the name should match the member-variable name.

    // GeneratorParams can be float or ints: {default} or {default, min, max}
    // (Note that if you want to specify min and max, you must specify both.)
    GeneratorParam<float> compiletime_factor{ "compiletime_factor", 1, 0, 100 };
    GeneratorParam<int> channels{ "channels", 3 };
    // ...or enums: {default, name->value map}
    GeneratorParam<SomeEnum> enummy{ "enummy",
                                     SomeEnum::Foo,
                                     { { "foo", SomeEnum::Foo },
                                       { "bar", SomeEnum::Bar } } };
    // ...or bools: {default}
    GeneratorParam<bool> flag{ "flag", true };

    // Halide::Type is supported as though it was an enum.
    // It's most useful for customizing the type of input or output image params.
    GeneratorParam<Halide::Type> output_type{ "output_type", Int(32) };

    // These are bad names that will produce errors at build time:
    // GeneratorParam<bool> badname{ " flag", true };
    // GeneratorParam<bool> badname{ "flag ", true };
    // GeneratorParam<bool> badname{ "0flag ", true };
    // GeneratorParam<bool> badname{ "", true };
    // GeneratorParam<bool> badname{ "\001", true };
    // GeneratorParam<bool> badname{ "a name? with! stuff*", true };

    // Note that a leading underscore is legal-but-reserved in C,
    // but it's outright forbidden here. (underscore after first char is ok.)
    // GeneratorParam<bool> badname{ "_flag", true };

    // We also forbid two underscores in a row.
    // GeneratorParam<bool> badname{ "f__lag", true };

    // Param (and ImageParam) are arguments passed to the filter when
    // it is executed (as opposed to the Generator, during compilation).
    // When jitting, there is effectively little difference between the
    // two (at least for scalar values). Note that we set a default value of
    // 1.0 so that invocations that don't set it explicitly use a predictable value.
    Param<float> runtime_factor{ "runtime_factor", 1.0 };

    Func build() override {
        Var x, y, c;
        Func f("f"), g("g");

        f(x, y) = max(x, y);
        g(x, y, c) = cast(output_type, f(x, y) * c * compiletime_factor * runtime_factor);

        g.bound(c, 0, channels).reorder(c, x, y).unroll(c);

        // Note that we can use the Generator method natural_vector_size()
        // here; this produces the width of the SIMD vector being targeted
        // divided by the width of the data type.
        g.vectorize(x, natural_vector_size(output_type));

        return g;
    }
};

// If you're only using a Generator with the JIT, you don't need to register it;
// however, registering it is needed for working seamlessly with the ahead-of-time
// compilation tools, so it's generally recommended to always register it.
// (As with Params, the name is constrained to C-like patterns.)
Halide::RegisterGenerator<Example> register_example{"example"};

}  // namespace
<commit_msg>example_generator fixes<commit_after>#include "Halide.h"

// By convention, Generators always go in a .cpp file, usually with no
// corresponding .h file. They can be enclosed in any C++ namespaces
// you like, but the anonymous namespace is often the best choice.
//
// It's normally considered Best Practice to have exactly one Generator
// per .cpp file, and to have the .cpp file name match the generator name
// with a "_generator" suffix (e.g., Generator with name "foo" should
// live in "foo_generator.cpp"), as it tends to simplify build rules,
// but neither of these are required.

namespace {

enum class SomeEnum { Foo, Bar };

// Note the inheritance using the Curiously Recurring Template Pattern
class Example : public Halide::Generator<Example> {
public:
    // GeneratorParams, ImageParams, and Params are (by convention)
    // always public and always declared at the top of the Generator,
    // in the order
    //    GeneratorParam(s)
    //    ImageParam(s)
    //    Param(s)
    //
    // Note that the ImageParams/Params will appear in the C function
    // call in the order they are declared. (GeneratorParams are always
    // referenced by name, not position, so their order is irrelevant.)
    //
    // All Param variants declared as Generator members must have explicit
    // names, and all such names must match the regex [A-Za-z_][A-Za-z_0-9]*
    // (i.e., essentially a C/C++ variable name). (Note that autogenerated
    // Param names do not match this pattern, and thus will be rejected.)
    // By convention, the name should match the member-variable name.

    // GeneratorParams can be float or ints: {default} or {default, min, max}
    // (Note that if you want to specify min and max, you must specify both.)
    GeneratorParam<float> compiletime_factor{ "compiletime_factor", 1, 0, 100 };
    GeneratorParam<int> channels{ "channels", 3 };
    // ...or enums: {default, name->value map}
    GeneratorParam<SomeEnum> enummy{ "enummy",
                                     SomeEnum::Foo,
                                     { { "foo", SomeEnum::Foo },
                                       { "bar", SomeEnum::Bar } } };
    // ...or bools: {default}
    GeneratorParam<bool> flag{ "flag", true };

    // Halide::Type is supported as though it was an enum.
    // It's most useful for customizing the type of input or output image params.
    GeneratorParam<Halide::Type> output_type{ "output_type", Int(32) };

    // These are bad names that will produce errors at build time:
    // GeneratorParam<bool> badname{ " flag", true };
    // GeneratorParam<bool> badname{ "flag ", true };
    // GeneratorParam<bool> badname{ "0flag ", true };
    // GeneratorParam<bool> badname{ "", true };
    // GeneratorParam<bool> badname{ "\001", true };
    // GeneratorParam<bool> badname{ "a name? with! stuff*", true };

    // Note that a leading underscore is legal-but-reserved in C,
    // but it's outright forbidden here. (underscore after first char is ok.)
    // GeneratorParam<bool> badname{ "_flag", true };

    // We also forbid two underscores in a row.
    // GeneratorParam<bool> badname{ "f__lag", true };

    // Param (and ImageParam) are arguments passed to the filter when
    // it is executed (as opposed to the Generator, during compilation).
    // When jitting, there is effectively little difference between the
    // two (at least for scalar values). Note that we set a default value of
    // 1.0 so that invocations that don't set it explicitly use a predictable value.
    Param<float> runtime_factor{ "runtime_factor", 1.0 };

    Func build() override {
        Var x, y, c;
        Func f("f"), g("g");

        f(x, y) = max(x, y);

        // Produce a float expression for the filter
        Expr value = f(x, y) * c * compiletime_factor * runtime_factor;

        // Float to integer conversion for unrepresentable values is undefined
        // in C++, e.g. if value is 256, it cannot be represented by a uint8_t.
        if (Type(output_type).is_uint() && Type(output_type).bits != 32) {
          Expr int_value = cast<unsigned int>(value);
          value = int_value % Type(output_type).max();
        }

        // Cast to the output type
        g(x, y, c) = cast(output_type, value);

        g.bound(c, 0, channels).reorder(c, x, y).unroll(c);

        // Note that we can use the Generator method natural_vector_size()
        // here; this produces the width of the SIMD vector being targeted
        // divided by the width of the data type.
        if (get_target().arch != Target::PNaCl) {
           g.vectorize(x, natural_vector_size(output_type));
        }

        return g;
    }
};

// If you're only using a Generator with the JIT, you don't need to register it;
// however, registering it is needed for working seamlessly with the ahead-of-time
// compilation tools, so it's generally recommended to always register it.
// (As with Params, the name is constrained to C-like patterns.)
Halide::RegisterGenerator<Example> register_example{"example"};

}  // namespace
<|endoftext|>


<commit_before>
//c++ -std=c++11 -O3 variables.cpp;./a.out

#include <iostream>
#include <vector>
#include <forward_list>
#include <unordered_map>

using namespace std;

//extern "C" int sprintf(const char* f, ...);

class variable;

typedef variable* var;
typedef vector<var> bs_list;
typedef unordered_map<string,var> bs_object;

class variables {
public:

	static forward_list<int> integers;
	static int* addInt(int* v) {
		integers.push_front(*v);
		return &integers.front();
	}

	static forward_list<string> strings;
	static string* addStr(string* v) {
		strings.push_front(*v);
		return &strings.front();
	}

	static forward_list<bs_list> lists;
	static bs_list* addLst(bs_list* v) {
		lists.push_front(*v);
		return &lists.front();
	}

	static forward_list<bs_object> objects;
	static bs_object* addObj(bs_object* v) {
		objects.push_front(*v);
		return &objects.front();
	}
};

forward_list<int> variables::integers;
forward_list<string> variables::strings;
forward_list<bs_list> variables::lists;
forward_list<bs_object> variables::objects;

class variable {
public:
	int type;
	void* value;

	variable(int* null) {
		type = 0;
	}

	int* getInt() {return (int*)value;}
	void get(int** v) {*v = (int*)value;}
	void set(int v) {*(int*)value = v;}
	variable(int v) {
		this->type = 1;
		this->value = variables::addInt(&v);
	}

	string* getStr() {return (string*)value;}
	void get(string** v) {*v = (string*)value;}
	void set(string v) {*(string*)value = v;}
	variable(string v) {
		this->type = 2;
		this->value = variables::addStr(&v);
	}

	bs_list* getLst() {return (bs_list*)value;}
	void get(bs_list** v) {*v = (bs_list*)value;}
	void set(bs_list v) {*(bs_list*)value = v;}
	variable(bs_list v) {
		this->type = 3;
		this->value = variables::addLst(&v);
	}

	bs_object* getObj() {return (bs_object*)value;}
	void get(bs_object** v) {*v = (bs_object*)value;}
	void set(bs_object v) {*(bs_object*)value = v;}
	variable(bs_object v) {
		this->type = 4;
		this->value = variables::addObj(&v);
	}

	var get(int i) {
		switch(type) {
			case 2:
				return new variable((*(string*)(value))[i]);
			break;

			case 3:
				return (*(bs_list*)value)[i];
			break;

			default:
				//err(0,"%s don't support random access",{"undefined","integers"}[type]);
			break;
		}
		return new variable(nullptr);
	}

	var get(string key) {

		switch(type) {
			case 4:
				return (*(bs_object*)value)[key];
			break;

			default:
				//err(0,"%s don't support random access",{"undefined","integers","strings"}[type]);
			break;
		}

		return new variable(nullptr);
	}

};

int main() {

	int* temp1;
	var a = new variable(15);
	a->get(&temp1);
	cout << *temp1 << endl;

	a->set(70);
	cout << *a->getInt() << endl;

	var list = new variable(bs_list({new variable("Hello "), new variable("World!")}));
	cout << *list->get(0)->getStr() << endl;

	bs_object obj;
	obj["f"] = new variable(555);
	var vobj = new variable(obj);
	cout << *vobj->get("f")->getInt() << endl;

	return 0;
}
<commit_msg>Delete variables.cpp<commit_after><|endoftext|>


<commit_before>#ifndef SENSOR_H
#define SENSOR_H
#include <string>

class Sensor{
public:
	virtual std::string read() = 0;

};

#endif
<commit_msg>started i2csensor<commit_after>#ifndef SENSOR_H
#define SENSOR_H
#include <string>

/*
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
*/
/*
oid main()

 // Create I2C bus
 int file;
 char *bus = "/dev/i2c-1";
 if ((file = open(bus, O_RDWR)) < 0)
 {
 	printf("Failed to open the bus. \n");
 	exit(1);
 }
 // Get I2C device, MCP9808 I2C address is 0x18(24)
 ioctl(file, I2C_SLAVE, 0x18);
*/

/*
class I2CSensor {
};
*/

class Sensor{
public:
	virtual std::string read() = 0;

};

#endif
<|endoftext|>


<commit_before>#include "Elk.h"

#include "KernelFactory.h"
#include "BCFactory.h"
#include "AuxFactory.h"
#include "MaterialFactory.h"

// misc
#include "CoefDiffusion.h"
#include "Convection.h"

// heat_conduction
#include "HeatConduction.h"
#include "HeatConductionImplicitEuler.h"

// navier_stokes
#include "MassInviscidFlux.h"
#include "MomentumInviscidFlux.h"
#include "MomentumViscousFlux.h"
#include "EnergyInviscidFlux.h"
#include "EnergyViscousFlux.h"
#include "GravityPower.h"
#include "GravityForce.h"
#include "PressureNeumannBC.h"
#include "ThermalBC.h"
#include "VelocityAux.h"

// linear_elasticity
#include "SolidMechX.h"
#include "SolidMechY.h"
#include "SolidMechZ.h"
#include "SolidMechImplicitEuler.h"
#include "SolidMechTempCoupleX.h"
#include "SolidMechTempCoupleY.h"
#include "SolidMechTempCoupleZ.h"

// solid_mechanics
#include "StressDivergence.h"
#include "LinearIsotropicMaterial.h"
#include "PlasticMaterial.h"
#include "DeltaGamma.h"

void
Elk::registerObjects()
{
  // misc
  KernelFactory::instance()->registerKernel<CoefDiffusion>("CoefDiffusion");
  KernelFactory::instance()->registerKernel<Convection>("Convection");

  // heat_conduction
  KernelFactory::instance()->registerKernel<HeatConduction>("HeatConduction");
  KernelFactory::instance()->registerKernel<HeatConductionImplicitEuler>("HeatConductionImplicitEuler");

  // navier_stokes
  KernelFactory::instance()->registerKernel<MassInviscidFlux>("MassInviscidFlux");
  KernelFactory::instance()->registerKernel<MomentumInviscidFlux>("MomentumInviscidFlux");
  KernelFactory::instance()->registerKernel<MomentumViscousFlux>("MomentumViscousFlux");
  KernelFactory::instance()->registerKernel<EnergyInviscidFlux>("EnergyInviscidFlux");
  KernelFactory::instance()->registerKernel<EnergyViscousFlux>("EnergyViscousFlux");
  KernelFactory::instance()->registerKernel<GravityPower>("GravityPower");
  KernelFactory::instance()->registerKernel<GravityForce>("GravityForce");
  BCFactory::instance()->registerBC<PressureNeumannBC>("PressureNeumannBC");
  BCFactory::instance()->registerBC<ThermalBC>("ThermalBC");
  AuxFactory::instance()->registerAux<VelocityAux>("VelocityAux");

  // linear_elasticity
  KernelFactory::instance()->registerKernel<SolidMechX>("SolidMechX");
  KernelFactory::instance()->registerKernel<SolidMechY>("SolidMechY");
  KernelFactory::instance()->registerKernel<SolidMechZ>("SolidMechZ");
  KernelFactory::instance()->registerKernel<SolidMechImplicitEuler>("SolidMechImplicitEuler");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleX>("SolidMechTempCoupleX");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleY>("SolidMechTempCoupleY");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleZ>("SolidMechTempCoupleZ");

  // solid_mechanics
  KernelFactory::instance()->registerKernel<StressDivergence>("StressDivergence");
  KernelFactory::instance()->registerKernel<DeltaGamma>("DeltaGamma");
  MaterialFactory::instance()->registerMaterial<LinearIsotropicMaterial>("LinearIsotropic");
  MaterialFactory::instance()->registerMaterial<PlasticMaterial>("PlasticMaterial");
}
<commit_msg>added fluxbc<commit_after>#include "Elk.h"

#include "KernelFactory.h"
#include "BCFactory.h"
#include "AuxFactory.h"
#include "MaterialFactory.h"

// misc
#include "CoefDiffusion.h"
#include "Convection.h"

// heat_conduction
#include "HeatConduction.h"
#include "HeatConductionImplicitEuler.h"
#include "FluxBC.h"

// navier_stokes
#include "MassInviscidFlux.h"
#include "MomentumInviscidFlux.h"
#include "MomentumViscousFlux.h"
#include "EnergyInviscidFlux.h"
#include "EnergyViscousFlux.h"
#include "GravityPower.h"
#include "GravityForce.h"
#include "PressureNeumannBC.h"
#include "ThermalBC.h"
#include "VelocityAux.h"

// linear_elasticity
#include "SolidMechX.h"
#include "SolidMechY.h"
#include "SolidMechZ.h"
#include "SolidMechImplicitEuler.h"
#include "SolidMechTempCoupleX.h"
#include "SolidMechTempCoupleY.h"
#include "SolidMechTempCoupleZ.h"

// solid_mechanics
#include "StressDivergence.h"
#include "LinearIsotropicMaterial.h"
#include "PlasticMaterial.h"
#include "DeltaGamma.h"

void
Elk::registerObjects()
{
  // misc
  KernelFactory::instance()->registerKernel<CoefDiffusion>("CoefDiffusion");
  KernelFactory::instance()->registerKernel<Convection>("Convection");

  // heat_conduction
  KernelFactory::instance()->registerKernel<HeatConduction>("HeatConduction");
  KernelFactory::instance()->registerKernel<HeatConductionImplicitEuler>("HeatConductionImplicitEuler");
  BCFactory::instance()->registerBC<FluxBC>("FluxBC");

  // navier_stokes
  KernelFactory::instance()->registerKernel<MassInviscidFlux>("MassInviscidFlux");
  KernelFactory::instance()->registerKernel<MomentumInviscidFlux>("MomentumInviscidFlux");
  KernelFactory::instance()->registerKernel<MomentumViscousFlux>("MomentumViscousFlux");
  KernelFactory::instance()->registerKernel<EnergyInviscidFlux>("EnergyInviscidFlux");
  KernelFactory::instance()->registerKernel<EnergyViscousFlux>("EnergyViscousFlux");
  KernelFactory::instance()->registerKernel<GravityPower>("GravityPower");
  KernelFactory::instance()->registerKernel<GravityForce>("GravityForce");
  BCFactory::instance()->registerBC<PressureNeumannBC>("PressureNeumannBC");
  BCFactory::instance()->registerBC<ThermalBC>("ThermalBC");
  AuxFactory::instance()->registerAux<VelocityAux>("VelocityAux");

  // linear_elasticity
  KernelFactory::instance()->registerKernel<SolidMechX>("SolidMechX");
  KernelFactory::instance()->registerKernel<SolidMechY>("SolidMechY");
  KernelFactory::instance()->registerKernel<SolidMechZ>("SolidMechZ");
  KernelFactory::instance()->registerKernel<SolidMechImplicitEuler>("SolidMechImplicitEuler");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleX>("SolidMechTempCoupleX");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleY>("SolidMechTempCoupleY");
  KernelFactory::instance()->registerKernel<SolidMechTempCoupleZ>("SolidMechTempCoupleZ");

  // solid_mechanics
  KernelFactory::instance()->registerKernel<StressDivergence>("StressDivergence");
  KernelFactory::instance()->registerKernel<DeltaGamma>("DeltaGamma");
  MaterialFactory::instance()->registerMaterial<LinearIsotropicMaterial>("LinearIsotropic");
  MaterialFactory::instance()->registerMaterial<PlasticMaterial>("PlasticMaterial");
}
<|endoftext|>


<commit_before>/*
  This file is part of Ingen.
  Copyright 2007-2015 David Robillard <http://drobilla.net/>

  Ingen 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 any later version.

  Ingen 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 Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <ctype.h>

#include <string>
#include <algorithm>

#include <boost/optional.hpp>

#include "raul/Path.hpp"

#include "ingen/Atom.hpp"
#include "ingen/client/GraphModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "ingen/client/PluginUI.hpp"

#include "ingen_config.h"

using namespace std;

namespace Ingen {
namespace Client {

LilvWorld*         PluginModel::_lilv_world   = NULL;
const LilvPlugins* PluginModel::_lilv_plugins = NULL;

Sord::World* PluginModel::_rdf_world = NULL;

PluginModel::PluginModel(URIs&                       uris,
                         const Raul::URI&            uri,
                         const Atom&                 type,
                         const Resource::Properties& properties)
	: Resource(uris, uri)
	, _type(type)
	, _fetched(false)
{
	if (!_type.is_valid()) {
		if (uri.find("ingen-internals") != string::npos) {
			_type = uris.ingen_Internal.urid;
		} else {
			_type = uris.lv2_Plugin.urid;  // Assume LV2 and hope for the best...
		}
	}

	add_property(uris.rdf_type, type);
	add_properties(properties);

	LilvNode* plugin_uri = lilv_new_uri(_lilv_world, uri.c_str());
	_lilv_plugin = lilv_plugins_get_by_uri(_lilv_plugins, plugin_uri);
	lilv_node_free(plugin_uri);

	if (uris.ingen_Internal == _type) {
		set_property(uris.doap_name,
		             uris.forge.alloc(uri.substr(uri.find_last_of('#') + 1)));
	}
}

static size_t
last_uri_delim(const std::string& str)
{
	for (size_t i = str.length() - 1; i > 0; --i) {
		switch (str[i]) {
		case ':': case '/': case '?': case '#':
			return i;
		}
	}
	return string::npos;
}

static bool
contains_alpha_after(const std::string& str, size_t begin)
{
	for (size_t i = begin; i < str.length(); ++i) {
		if (isalpha(str[i])) {
			return true;
		}
	}
	return false;
}

const Atom&
PluginModel::get_property(const Raul::URI& key) const
{
	static const Atom nil;
	const Atom& val = Resource::get_property(key);
	if (val.is_valid())
		return val;

	// No lv2:symbol from data or engine, invent one
	if (key == _uris.lv2_symbol) {
		string str        = this->uri();
		size_t last_delim = last_uri_delim(str);
		while (last_delim != string::npos &&
		       !contains_alpha_after(str, last_delim)) {
			str = str.substr(0, last_delim);
			last_delim = last_uri_delim(str);
		}
		str = str.substr(last_delim + 1);

		std::string symbol = Raul::Symbol::symbolify(str);
		set_property(_uris.lv2_symbol, _uris.forge.alloc(symbol));
		return get_property(key);
	}

	if (_lilv_plugin) {
		boost::optional<const Atom&> ret;
		LilvNode*  lv2_pred = lilv_new_uri(_lilv_world, key.c_str());
		LilvNodes* values   = lilv_plugin_get_value(_lilv_plugin, lv2_pred);
		lilv_node_free(lv2_pred);
		LILV_FOREACH(nodes, i, values) {
			const LilvNode* val = lilv_nodes_get(values, i);
			if (lilv_node_is_uri(val)) {
				ret = set_property(
					key, _uris.forge.alloc_uri(lilv_node_as_uri(val)));
				break;
			} else if (lilv_node_is_string(val)) {
				ret = set_property(
					key, _uris.forge.alloc(lilv_node_as_string(val)));
				break;
			} else if (lilv_node_is_float(val)) {
				ret = set_property(
					key, _uris.forge.make(lilv_node_as_float(val)));
				break;
			} else if (lilv_node_is_int(val)) {
				ret = set_property(
					key, _uris.forge.make(lilv_node_as_int(val)));
				break;
			}
		}
		lilv_nodes_free(values);

		if (ret)
			return *ret;
	}

	return nil;
}

void
PluginModel::set(SPtr<PluginModel> p)
{
	_type = p->_type;

	if (p->_lilv_plugin)
		_lilv_plugin = p->_lilv_plugin;

	for (auto v : p->properties()) {
		Resource::set_property(v.first, v.second);
		_signal_property.emit(v.first, v.second);
	}

	_signal_changed.emit();
}

void
PluginModel::add_preset(const Raul::URI& uri, const std::string& label)
{
	_presets.insert(std::make_pair(uri, label));
	_signal_preset.emit(uri, label);
}

Raul::Symbol
PluginModel::default_block_symbol() const
{
	const Atom& name_atom = get_property(_uris.lv2_symbol);
	if (name_atom.is_valid() && name_atom.type() == _uris.forge.String)
		return Raul::Symbol::symbolify(name_atom.ptr<char>());
	else
		return Raul::Symbol("_");
}

string
PluginModel::human_name() const
{
	const Atom& name_atom = get_property(_uris.doap_name);
	if (name_atom.type() == _uris.forge.String)
		return name_atom.ptr<char>();
	else
		return default_block_symbol().c_str();
}

string
PluginModel::port_human_name(uint32_t i) const
{
	if (_lilv_plugin) {
		const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, i);
		LilvNode*       name = lilv_port_get_name(_lilv_plugin, port);
		const string    ret(lilv_node_as_string(name));
		lilv_node_free(name);
		return ret;
	}
	return "";
}

PluginModel::ScalePoints
PluginModel::port_scale_points(uint32_t i) const
{
	// TODO: Non-float scale points
	ScalePoints points;
	if (_lilv_plugin) {
		const LilvPort*  port = lilv_plugin_get_port_by_index(_lilv_plugin, i);
		LilvScalePoints* sp   = lilv_port_get_scale_points(_lilv_plugin, port);
		LILV_FOREACH(scale_points, i, sp) {
			const LilvScalePoint* p = lilv_scale_points_get(sp, i);
			points.insert(
				make_pair(lilv_node_as_float(lilv_scale_point_get_value(p)),
				          lilv_node_as_string(lilv_scale_point_get_label(p))));
		}
	}
	return points;
}

bool
PluginModel::has_ui() const
{
	LilvUIs* uis = lilv_plugin_get_uis(_lilv_plugin);
	const bool ret = (lilv_nodes_size(uis) > 0);
	lilv_uis_free(uis);
	return ret;

}

SPtr<PluginUI>
PluginModel::ui(Ingen::World*          world,
                SPtr<const BlockModel> block) const
{
	if (!_lilv_plugin) {
		return SPtr<PluginUI>();
	}

	return PluginUI::create(world, block, _lilv_plugin);
}

static std::string
heading(const std::string& text, bool html, unsigned level)
{
	if (html) {
		const std::string tag = std::string("h") + std::to_string(level);
		return std::string("<") + tag + ">" + text + "</" + tag + ">\n";
	} else {
		return text + ":\n\n";
	}
}

static std::string
link(const std::string& addr, bool html)
{
	if (html) {
		return std::string("" + addr + "";
	} else {
		return addr;
	}
}

std::string
PluginModel::get_documentation(const LilvNode* subject, bool html) const
{
	std::string doc;

	LilvNode* lv2_documentation = lilv_new_uri(_lilv_world,
	                                           LV2_CORE__documentation);
	LilvNode* rdfs_comment = lilv_new_uri(_lilv_world,
	                                      LILV_NS_RDFS "comment");

	LilvNodes* vals = lilv_world_find_nodes(
		_lilv_world, subject, lv2_documentation, NULL);
	const bool doc_is_html = vals;
	if (!vals) {
		vals = lilv_world_find_nodes(
			_lilv_world, subject, rdfs_comment, NULL);
	}

	if (vals) {
		const LilvNode* val = lilv_nodes_get_first(vals);
		if (lilv_node_is_string(val)) {
			doc += lilv_node_as_string(val);
		}
	}

	if (html && !doc_is_html) {
		for (std::size_t i = 0; i < doc.size(); ++i) {
			if (doc.substr(i, 2) == "\n\n") {
				doc.replace(i, 2, "

");
				i += strlen("

");
			}
		}
	}

	lilv_node_free(rdfs_comment);
	lilv_node_free(lv2_documentation);

	return doc;
}

std::string
PluginModel::documentation(const bool html) const
{
	LilvNode* subject = (_lilv_plugin)
		? lilv_node_duplicate(lilv_plugin_get_uri(_lilv_plugin))
		: lilv_new_uri(_lilv_world, uri().c_str());

	const std::string doc(get_documentation(subject, html));

	lilv_node_free(subject);

	return (heading(human_name(), html, 2) +
	        link(uri(), html) + (html ? "

" : "\n\n") +
	        doc);
}

std::string
PluginModel::port_documentation(uint32_t index, bool html) const
{
	if (!_lilv_plugin) {
		return "";
	}

	const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, index);
	if (!port) {
		return "";
	}

	return (heading(port_human_name(index), html, 2) +
	        get_documentation(lilv_port_get_node(_lilv_plugin, port), html));
}

const LilvPort*
PluginModel::lilv_port(uint32_t index) const
{
	return lilv_plugin_get_port_by_index(_lilv_plugin, index);
}

void
PluginModel::set_lilv_world(LilvWorld* world)
{
	_lilv_world   = world;
	_lilv_plugins = lilv_world_get_all_plugins(_lilv_world);
}

} // namespace Client
} // namespace Ingen
<commit_msg>Fix checking non-LV2 'plugins' for UIs.<commit_after>/*
  This file is part of Ingen.
  Copyright 2007-2015 David Robillard <http://drobilla.net/>

  Ingen 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 any later version.

  Ingen 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 Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <ctype.h>

#include <string>
#include <algorithm>

#include <boost/optional.hpp>

#include "raul/Path.hpp"

#include "ingen/Atom.hpp"
#include "ingen/client/GraphModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "ingen/client/PluginUI.hpp"

#include "ingen_config.h"

using namespace std;

namespace Ingen {
namespace Client {

LilvWorld*         PluginModel::_lilv_world   = NULL;
const LilvPlugins* PluginModel::_lilv_plugins = NULL;

Sord::World* PluginModel::_rdf_world = NULL;

PluginModel::PluginModel(URIs&                       uris,
                         const Raul::URI&            uri,
                         const Atom&                 type,
                         const Resource::Properties& properties)
	: Resource(uris, uri)
	, _type(type)
	, _fetched(false)
{
	if (!_type.is_valid()) {
		if (uri.find("ingen-internals") != string::npos) {
			_type = uris.ingen_Internal.urid;
		} else {
			_type = uris.lv2_Plugin.urid;  // Assume LV2 and hope for the best...
		}
	}

	add_property(uris.rdf_type, type);
	add_properties(properties);

	LilvNode* plugin_uri = lilv_new_uri(_lilv_world, uri.c_str());
	_lilv_plugin = lilv_plugins_get_by_uri(_lilv_plugins, plugin_uri);
	lilv_node_free(plugin_uri);

	if (uris.ingen_Internal == _type) {
		set_property(uris.doap_name,
		             uris.forge.alloc(uri.substr(uri.find_last_of('#') + 1)));
	}
}

static size_t
last_uri_delim(const std::string& str)
{
	for (size_t i = str.length() - 1; i > 0; --i) {
		switch (str[i]) {
		case ':': case '/': case '?': case '#':
			return i;
		}
	}
	return string::npos;
}

static bool
contains_alpha_after(const std::string& str, size_t begin)
{
	for (size_t i = begin; i < str.length(); ++i) {
		if (isalpha(str[i])) {
			return true;
		}
	}
	return false;
}

const Atom&
PluginModel::get_property(const Raul::URI& key) const
{
	static const Atom nil;
	const Atom& val = Resource::get_property(key);
	if (val.is_valid())
		return val;

	// No lv2:symbol from data or engine, invent one
	if (key == _uris.lv2_symbol) {
		string str        = this->uri();
		size_t last_delim = last_uri_delim(str);
		while (last_delim != string::npos &&
		       !contains_alpha_after(str, last_delim)) {
			str = str.substr(0, last_delim);
			last_delim = last_uri_delim(str);
		}
		str = str.substr(last_delim + 1);

		std::string symbol = Raul::Symbol::symbolify(str);
		set_property(_uris.lv2_symbol, _uris.forge.alloc(symbol));
		return get_property(key);
	}

	if (_lilv_plugin) {
		boost::optional<const Atom&> ret;
		LilvNode*  lv2_pred = lilv_new_uri(_lilv_world, key.c_str());
		LilvNodes* values   = lilv_plugin_get_value(_lilv_plugin, lv2_pred);
		lilv_node_free(lv2_pred);
		LILV_FOREACH(nodes, i, values) {
			const LilvNode* val = lilv_nodes_get(values, i);
			if (lilv_node_is_uri(val)) {
				ret = set_property(
					key, _uris.forge.alloc_uri(lilv_node_as_uri(val)));
				break;
			} else if (lilv_node_is_string(val)) {
				ret = set_property(
					key, _uris.forge.alloc(lilv_node_as_string(val)));
				break;
			} else if (lilv_node_is_float(val)) {
				ret = set_property(
					key, _uris.forge.make(lilv_node_as_float(val)));
				break;
			} else if (lilv_node_is_int(val)) {
				ret = set_property(
					key, _uris.forge.make(lilv_node_as_int(val)));
				break;
			}
		}
		lilv_nodes_free(values);

		if (ret)
			return *ret;
	}

	return nil;
}

void
PluginModel::set(SPtr<PluginModel> p)
{
	_type = p->_type;

	if (p->_lilv_plugin)
		_lilv_plugin = p->_lilv_plugin;

	for (auto v : p->properties()) {
		Resource::set_property(v.first, v.second);
		_signal_property.emit(v.first, v.second);
	}

	_signal_changed.emit();
}

void
PluginModel::add_preset(const Raul::URI& uri, const std::string& label)
{
	_presets.insert(std::make_pair(uri, label));
	_signal_preset.emit(uri, label);
}

Raul::Symbol
PluginModel::default_block_symbol() const
{
	const Atom& name_atom = get_property(_uris.lv2_symbol);
	if (name_atom.is_valid() && name_atom.type() == _uris.forge.String)
		return Raul::Symbol::symbolify(name_atom.ptr<char>());
	else
		return Raul::Symbol("_");
}

string
PluginModel::human_name() const
{
	const Atom& name_atom = get_property(_uris.doap_name);
	if (name_atom.type() == _uris.forge.String)
		return name_atom.ptr<char>();
	else
		return default_block_symbol().c_str();
}

string
PluginModel::port_human_name(uint32_t i) const
{
	if (_lilv_plugin) {
		const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, i);
		LilvNode*       name = lilv_port_get_name(_lilv_plugin, port);
		const string    ret(lilv_node_as_string(name));
		lilv_node_free(name);
		return ret;
	}
	return "";
}

PluginModel::ScalePoints
PluginModel::port_scale_points(uint32_t i) const
{
	// TODO: Non-float scale points
	ScalePoints points;
	if (_lilv_plugin) {
		const LilvPort*  port = lilv_plugin_get_port_by_index(_lilv_plugin, i);
		LilvScalePoints* sp   = lilv_port_get_scale_points(_lilv_plugin, port);
		LILV_FOREACH(scale_points, i, sp) {
			const LilvScalePoint* p = lilv_scale_points_get(sp, i);
			points.insert(
				make_pair(lilv_node_as_float(lilv_scale_point_get_value(p)),
				          lilv_node_as_string(lilv_scale_point_get_label(p))));
		}
	}
	return points;
}

bool
PluginModel::has_ui() const
{
	if (_lilv_plugin) {
		LilvUIs* uis = lilv_plugin_get_uis(_lilv_plugin);
		const bool ret = (lilv_nodes_size(uis) > 0);
		lilv_uis_free(uis);
		return ret;
	}
	return false;
}

SPtr<PluginUI>
PluginModel::ui(Ingen::World*          world,
                SPtr<const BlockModel> block) const
{
	if (!_lilv_plugin) {
		return SPtr<PluginUI>();
	}

	return PluginUI::create(world, block, _lilv_plugin);
}

static std::string
heading(const std::string& text, bool html, unsigned level)
{
	if (html) {
		const std::string tag = std::string("h") + std::to_string(level);
		return std::string("<") + tag + ">" + text + "</" + tag + ">\n";
	} else {
		return text + ":\n\n";
	}
}

static std::string
link(const std::string& addr, bool html)
{
	if (html) {
		return std::string("" + addr + "";
	} else {
		return addr;
	}
}

std::string
PluginModel::get_documentation(const LilvNode* subject, bool html) const
{
	std::string doc;

	LilvNode* lv2_documentation = lilv_new_uri(_lilv_world,
	                                           LV2_CORE__documentation);
	LilvNode* rdfs_comment = lilv_new_uri(_lilv_world,
	                                      LILV_NS_RDFS "comment");

	LilvNodes* vals = lilv_world_find_nodes(
		_lilv_world, subject, lv2_documentation, NULL);
	const bool doc_is_html = vals;
	if (!vals) {
		vals = lilv_world_find_nodes(
			_lilv_world, subject, rdfs_comment, NULL);
	}

	if (vals) {
		const LilvNode* val = lilv_nodes_get_first(vals);
		if (lilv_node_is_string(val)) {
			doc += lilv_node_as_string(val);
		}
	}

	if (html && !doc_is_html) {
		for (std::size_t i = 0; i < doc.size(); ++i) {
			if (doc.substr(i, 2) == "\n\n") {
				doc.replace(i, 2, "

");
				i += strlen("

");
			}
		}
	}

	lilv_node_free(rdfs_comment);
	lilv_node_free(lv2_documentation);

	return doc;
}

std::string
PluginModel::documentation(const bool html) const
{
	LilvNode* subject = (_lilv_plugin)
		? lilv_node_duplicate(lilv_plugin_get_uri(_lilv_plugin))
		: lilv_new_uri(_lilv_world, uri().c_str());

	const std::string doc(get_documentation(subject, html));

	lilv_node_free(subject);

	return (heading(human_name(), html, 2) +
	        link(uri(), html) + (html ? "

" : "\n\n") +
	        doc);
}

std::string
PluginModel::port_documentation(uint32_t index, bool html) const
{
	if (!_lilv_plugin) {
		return "";
	}

	const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, index);
	if (!port) {
		return "";
	}

	return (heading(port_human_name(index), html, 2) +
	        get_documentation(lilv_port_get_node(_lilv_plugin, port), html));
}

const LilvPort*
PluginModel::lilv_port(uint32_t index) const
{
	return lilv_plugin_get_port_by_index(_lilv_plugin, index);
}

void
PluginModel::set_lilv_world(LilvWorld* world)
{
	_lilv_world   = world;
	_lilv_plugins = lilv_world_get_all_plugins(_lilv_world);
}

} // namespace Client
} // namespace Ingen
<|endoftext|>


<commit_before>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <vector>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"
#include "Exceptions/End_Of_File_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        if(id > -1)
        {
            throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
        }
        else
        {
            throw End_Of_File_Exception();
        }
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto positions_to_examine = genome.positions_to_examine(board, clock);
    std::string look_ahead_comment = "[" + std::to_string(positions_to_examine) + ",";
    auto time_at_start = clock.time_left(board.whose_turn());
    auto result = search_game_tree(board,
                                   positions_to_examine,
                                   clock,
                                   0);
    look_ahead_comment += std::to_string(positions_to_examine) + "] ";
    auto time_used = time_at_start - clock.time_left(board.whose_turn());
    board.add_commentary_to_next_move(look_ahead_comment
                                      + " "
                                      + std::to_string(time_used)
                                      + " "
                                      + result.commentary);
    return result.move;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   int& positions_to_examine,
                                                   const Clock& clock,
                                                   const int depth) const
{
    // Every call to search_game_tree() after the first
    // costs a position_to_examine.
    if(depth > 0 && positions_to_examine > 0)
    {
        --positions_to_examine;
    }

    auto perspective = board.whose_turn();

    std::vector<Game_Tree_Node_Result> results;

    // Moves worth examining further
    std::vector<std::tuple<Complete_Move, Board, double>> further_examine; // move, resulting board, score

    // Find moves worth examining
    for(const auto& move : board.all_legal_moves())
    {
        if(clock.time_left(clock.running_for()) < 0.0)
        {
            return {board.all_legal_moves().front(),
                    0.0,
                    perspective,
                    depth,
                    "Out of time"};
        }

        auto next_board = board;

        try
        {
            next_board.submit_move(move);

            if(next_board.all_legal_moves().size() > 1 &&
               (positions_to_examine <= 0
               || ! genome.good_enough_to_examine(board, next_board, perspective)))
            {
                // Record immediate result without looking ahead further
                results.push_back({move,
                                   genome.evaluate(next_board, perspective),
                                   perspective,
                                   depth,
                                   next_board.get_game_record().back()});
            }
            else
            {
                further_examine.push_back({move, next_board, genome.evaluate(next_board, perspective)});
            }
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();
            if(depth == 0)
            {
                comment += " (" + std::to_string(score) + ")";
            }
            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draw
            results.push_back({move,
                               genome.evaluate(next_board, perspective),
                               perspective,
                               depth,
                               next_board.get_game_record().back()});
        }
    }

    // Sort moves by score so higher scores get more moves for examination
    std::sort(further_examine.begin(),
              further_examine.end(),
              [](const auto& x, const auto& y)
              {
                  return std::get<double>(x) < std::get<double>(y);
              });

    // Look ahead through moves found above
    for(size_t i = 0; i < further_examine.size(); ++i)
    {
        int moves_left = further_examine.size() - i;
        int positions_for_this_move = positions_to_examine/moves_left;

        if(positions_for_this_move > 0 || std::get<Board>(further_examine[i]).all_legal_moves().size() == 1)
        {
            positions_to_examine -= positions_for_this_move;

            results.push_back(search_game_tree(std::get<Board>(further_examine[i]),
                                               positions_for_this_move,
                                               clock,
                                               depth + 1));
            // Update last result with this node's data
            results.back().move = std::get<Complete_Move>(further_examine[i]);
            results.back().score *= (results.back().perspective == perspective ? 1 : -1);
            results.back().commentary = std::get<Board>(further_examine[i]).get_game_record().back()
                                        + " "
                                        + results.back().commentary;

            positions_to_examine += positions_for_this_move;
        }
        else
        {
            results.push_back({std::get<Complete_Move>(further_examine[i]),
                               std::get<double>(further_examine[i]),
                               perspective,
                               depth,
                               std::get<Board>(further_examine[i]).get_game_record().back()});
        }
    }

    // Consider all results and return best
    auto best_score = -Math::infinity;
    auto best_move = board.all_legal_moves().front();
    auto best_depth = 0;
    std::string comments_on_best_move;
    std::string comments_on_all_moves; // only use when depth == 0

    for(const auto& result : results)
    {
        auto score = result.score;
        if(result.perspective != perspective)
        {
            score = -score;
        }

        // Prefer ...
        if(score > best_score // ... better score
           || (score ==  Math::infinity && result.depth < best_depth) // shortest path to victory
           || (score == -Math::infinity && result.depth > best_depth)) // longest path to defeat
        {
            best_score = score;
            best_move = result.move;
            best_depth = result.depth;
            comments_on_best_move = result.commentary;
        }

        if(depth == 0)
        {
            // build comment on all current move possibilities
            comments_on_all_moves += " " + result.commentary + " (" + std::to_string(score) + ")";
        }
    }

    return {best_move,
            best_score,
            perspective,
            best_depth,
            (depth == 0 ? comments_on_all_moves : comments_on_best_move)};
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<commit_msg>Fix incorrect commit re: propagating scores up game tree<commit_after>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <vector>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"
#include "Exceptions/End_Of_File_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        if(id > -1)
        {
            throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
        }
        else
        {
            throw End_Of_File_Exception();
        }
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto positions_to_examine = genome.positions_to_examine(board, clock);
    std::string look_ahead_comment = "[" + std::to_string(positions_to_examine) + ",";
    auto time_at_start = clock.time_left(board.whose_turn());
    auto result = search_game_tree(board,
                                   positions_to_examine,
                                   clock,
                                   0);
    look_ahead_comment += std::to_string(positions_to_examine) + "] ";
    auto time_used = time_at_start - clock.time_left(board.whose_turn());
    board.add_commentary_to_next_move(look_ahead_comment
                                      + " "
                                      + std::to_string(time_used)
                                      + " "
                                      + result.commentary);
    return result.move;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   int& positions_to_examine,
                                                   const Clock& clock,
                                                   const int depth) const
{
    // Every call to search_game_tree() after the first
    // costs a position_to_examine.
    if(depth > 0 && positions_to_examine > 0)
    {
        --positions_to_examine;
    }

    auto perspective = board.whose_turn();

    std::vector<Game_Tree_Node_Result> results;

    // Moves worth examining further
    std::vector<std::tuple<Complete_Move, Board, double>> further_examine; // move, resulting board, score

    // Find moves worth examining
    for(const auto& move : board.all_legal_moves())
    {
        if(clock.time_left(clock.running_for()) < 0.0)
        {
            return {board.all_legal_moves().front(),
                    0.0,
                    perspective,
                    depth,
                    "Out of time"};
        }

        auto next_board = board;

        try
        {
            next_board.submit_move(move);

            if(next_board.all_legal_moves().size() > 1 &&
               (positions_to_examine <= 0
               || ! genome.good_enough_to_examine(board, next_board, perspective)))
            {
                // Record immediate result without looking ahead further
                results.push_back({move,
                                   genome.evaluate(next_board, perspective),
                                   perspective,
                                   depth,
                                   next_board.get_game_record().back()});
            }
            else
            {
                further_examine.push_back({move, next_board, genome.evaluate(next_board, perspective)});
            }
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();
            if(depth == 0)
            {
                comment += " (" + std::to_string(score) + ")";
            }
            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draw
            results.push_back({move,
                               genome.evaluate(next_board, perspective),
                               perspective,
                               depth,
                               next_board.get_game_record().back()});
        }
    }

    // Sort moves by score so higher scores get more moves for examination
    std::sort(further_examine.begin(),
              further_examine.end(),
              [](const auto& x, const auto& y)
              {
                  return std::get<double>(x) < std::get<double>(y);
              });

    // Look ahead through moves found above
    for(size_t i = 0; i < further_examine.size(); ++i)
    {
        int moves_left = further_examine.size() - i;
        int positions_for_this_move = positions_to_examine/moves_left;

        if(positions_for_this_move > 0 || std::get<Board>(further_examine[i]).all_legal_moves().size() == 1)
        {
            positions_to_examine -= positions_for_this_move;

            results.push_back(search_game_tree(std::get<Board>(further_examine[i]),
                                               positions_for_this_move,
                                               clock,
                                               depth + 1));
            // Update last result with this game tree node's data
            results.back().move = std::get<Complete_Move>(further_examine[i]);
            results.back().commentary = std::get<Board>(further_examine[i]).get_game_record().back()
                                        + " "
                                        + results.back().commentary;

            positions_to_examine += positions_for_this_move;
        }
        else
        {
            results.push_back({std::get<Complete_Move>(further_examine[i]),
                               std::get<double>(further_examine[i]),
                               perspective,
                               depth,
                               std::get<Board>(further_examine[i]).get_game_record().back()});
        }
    }

    // Consider all results and return best
    auto best_score = -Math::infinity;
    auto best_move = board.all_legal_moves().front();
    auto best_depth = 0;
    std::string comments_on_best_move;
    std::string comments_on_all_moves; // only use when depth == 0

    for(const auto& result : results)
    {
        auto score = result.score;
        if(result.perspective != perspective)
        {
            score = -score;
        }

        // Prefer ...
        if(score > best_score // ... better score
           || (score ==  Math::infinity && result.depth < best_depth) // shortest path to victory
           || (score == -Math::infinity && result.depth > best_depth)) // longest path to defeat
        {
            best_score = score;
            best_move = result.move;
            best_depth = result.depth;
            comments_on_best_move = result.commentary;
        }

        if(depth == 0)
        {
            // build comment on all current move possibilities
            comments_on_all_moves += " " + result.commentary + " (" + std::to_string(score) + ")";
        }
    }

    return {best_move,
            best_score,
            perspective,
            best_depth,
            (depth == 0 ? comments_on_all_moves : comments_on_best_move)};
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/interaction/pickingcontainer.h>
#include <inviwo/core/interaction/pickingmanager.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/interaction/events/mouseevent.h>

namespace inviwo {

PickingContainer::PickingContainer()
    : src_(nullptr)
    , mousePickObj_(nullptr)
    , prevMouseCoord_(uvec2(0, 0))
    , mousePickingOngoing_(false)
    , mouseIsDown_(false)
    , touchPickingOn_(false)
{}

PickingContainer::~PickingContainer() {}

bool PickingContainer::pickingEnabled() {
    return PickingManager::getPtr()->pickingEnabled();
}

bool PickingContainer::performMousePick(MouseEvent* e) {
    if (!pickingEnabled() || e->button() == MouseEvent::MOUSE_BUTTON_NONE)
        return false;

    if (touchPickingOn_)
        return true;

    if (e->state() == MouseEvent::MOUSE_STATE_RELEASE){
        mouseIsDown_ = false;
        if (mousePickingOngoing_) {
            uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
            mousePickObj_->setPickingMove(normalizedMovement(prevMouseCoord_, coord));
            mousePickObj_->setPickingMouseEvent(*e);
            prevMouseCoord_ = coord;
            mousePickObj_->picked();
            mousePickingOngoing_ = false;
            return true;
        }
        else {
            mousePickObj_ = nullptr;
            return false;
        }
    }
    else if (!mouseIsDown_ || e->state() == MouseEvent::MOUSE_STATE_PRESS){
        mouseIsDown_ = true;

        uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
        prevMouseCoord_ = coord;

        mousePickObj_ = findPickingObject(coord);

        if (mousePickObj_) {
            mousePickingOngoing_ = true;
            mousePickObj_->setPickingPosition(normalizedCoordinates(coord));
            mousePickObj_->setPickingDepth(e->depth());
            mousePickObj_->setPickingMouseEvent(*e);

            mousePickObj_->setPickingMove(vec2(0.f, 0.f));
            mousePickObj_->picked();
            return true;
        }
        else{
            mousePickingOngoing_ = false;
            return false;
        }
    }
    else if (e->state() == MouseEvent::MOUSE_STATE_MOVE){
        if (mousePickingOngoing_){
            uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
            mousePickObj_->setPickingMove(normalizedMovement(prevMouseCoord_, coord));
            mousePickObj_->setPickingMouseEvent(*e);
            prevMouseCoord_ = coord;
            mousePickObj_->picked();
            return true;
        }
        else
            return false;
    }

    return false;
}

bool PickingContainer::performTouchPick(TouchEvent* e) {
    if (!pickingEnabled())
        return false;

    std::vector<TouchPoint>& touchPoints = e->getTouchPoints();

    // Clear the picked touch point map
    pickedTouchPoints_.clear();

    if (touchPoints.size() > 1 || touchPoints[0].state() != TouchPoint::TOUCH_STATE_ENDED)
        touchPickingOn_ = true;
    else
        touchPickingOn_ = false;

    std::unordered_map<int, PickingObject*>::iterator touchPickObjs_it;
    std::unordered_map<PickingObject*, std::vector<TouchPoint>>::iterator pickedTouchPoints_it;

    auto touchPoint = touchPoints.begin();
    while (touchPoint != touchPoints.end()) {
        bool isAssociated = false;
        if (touchPoint->state() == TouchPoint::TOUCH_STATE_STARTED) {
            // Find out if new touch point is touching inside a picking object
            uvec2 coord = clampToScreenCoords(touchPoint->getPos(), e->canvasSize());
            PickingObject* pickObj = findPickingObject(coord);

            // If it is, put it in the TouchIDPickingMap
            if (pickObj) {
                touchPickObjs_.insert(std::pair<int, PickingObject*>(touchPoint->getId(), pickObj));

                // Associate touch point with picking object
                // which can already have other associated touch points.
                pickedTouchPoints_it = pickedTouchPoints_.find(pickObj);
                if (pickedTouchPoints_it != pickedTouchPoints_.end()){
                    pickedTouchPoints_it->second.push_back(*touchPoint);
                }
                else{
                    pickedTouchPoints_.insert(std::pair<PickingObject*,
                        std::vector<TouchPoint>>(pickObj, std::vector<TouchPoint>{*touchPoint}));
                }
                isAssociated = true;
            }
        }
        else if (touchPoint->state() == TouchPoint::TOUCH_STATE_ENDED) {
            // Erase touch point from TouchIDPickingMap
            size_t numberOfErasedElements = touchPickObjs_.erase(touchPoint->getId());
            isAssociated = (numberOfErasedElements > 0);
        }
        else {
            // Find out if touch point is in the TouchIDPickingMap
            // If it exists, associate touch point with picking object
            touchPickObjs_it = touchPickObjs_.find(touchPoint->getId());
            if (touchPickObjs_it != touchPickObjs_.end()){
                // Associate touch point with picking object
                // which can already have other associated touch points.
                pickedTouchPoints_it = pickedTouchPoints_.find(touchPickObjs_it->second);
                if (pickedTouchPoints_it != pickedTouchPoints_.end()){
                    pickedTouchPoints_it->second.push_back(*touchPoint);
                }
                else{
                    pickedTouchPoints_.insert(std::pair<PickingObject*,
                        std::vector<TouchPoint>>(touchPickObjs_it->second, std::vector<TouchPoint>{*touchPoint}));
                }
                isAssociated = true;
            }
        }
        // Removed touch point from the actual event if it was associated with a picking object
        if (isAssociated)
            touchPoint = touchPoints.erase(touchPoint);
        else
            ++touchPoint;
    }

    // Build touch event for all picking objects with associated touch points
    for (pickedTouchPoints_it = pickedTouchPoints_.begin(); pickedTouchPoints_it != pickedTouchPoints_.end(); ++pickedTouchPoints_it){
        // Treat one touch point the same as mouse event, for now
        if (pickedTouchPoints_it->second.size() == 1){
            uvec2 coord = clampToScreenCoords(pickedTouchPoints_it->second[0].getPos(), e->canvasSize());
            if (pickedTouchPoints_it->second[0].state() & TouchPoint::TOUCH_STATE_STARTED){
                pickedTouchPoints_it->first->setPickingPosition(normalizedCoordinates(coord));
                pickedTouchPoints_it->first->setPickingDepth(pickedTouchPoints_it->second[0].getDepth());
                pickedTouchPoints_it->first->setPickingMove(vec2(0.f, 0.f));
            }
            else{
                uvec2 prevCoord = clampToScreenCoords(pickedTouchPoints_it->second[0].getPrevPos(), e->canvasSize());
                pickedTouchPoints_it->first->setPickingMove(normalizedMovement(prevCoord, coord));
            }
            // One touch point is currently treated as mouse event as well...
            // So prepare for that
            prevMouseCoord_ = coord;
            mousePickObj_ = pickedTouchPoints_it->first;
            mousePickingOngoing_ = true;
        }

        pickedTouchPoints_it->first->setPickingTouchEvent(TouchEvent(pickedTouchPoints_it->second, e->canvasSize()));
    }

    // One touch point is currently treated as mouse event as well...
    // So prepare for that
    if (touchPoints.size() == 1){
        prevMouseCoord_ = clampToScreenCoords(touchPoints[0].getPos(), e->canvasSize());
        touchPickingOn_ = false;
    }

    // Mark all picking objects in TouchIDPickingMap as picked.
    for (touchPickObjs_it = touchPickObjs_.begin(); touchPickObjs_it != touchPickObjs_.end(); ++touchPickObjs_it)
        touchPickObjs_it->second->picked();

    return !touchPickObjs_.empty();
}

void PickingContainer::setPickingSource(std::shared_ptr<const Image> src) {
    src_ = src;
}

PickingObject* PickingContainer::findPickingObject(const uvec2& coord){
    if (pickingEnabled() && src_) {
        const Layer* pickingLayer = src_->getPickingLayer();

        if (pickingLayer) {
            const LayerRAM* pickingLayerRAM = pickingLayer->getRepresentation<LayerRAM>();
            dvec4 value = pickingLayerRAM->getAsNormalizedDVec4(coord);
            dvec3 pickedColor = (value.a > 0.0 ? value.rgb() : dvec3(0.0));
            uvec3 color(pickedColor*255.0);
            return PickingManager::getPtr()->getPickingObjectFromColor(color);
        }
    }

    return nullptr;
}

vec2 PickingContainer::normalizedMovement(const uvec2& previous, const uvec2& current) const {
    return normalizedCoordinates(current - previous);
}

vec2 PickingContainer::normalizedCoordinates(const uvec2& coord) const {
    return vec2(coord) / vec2(src_->getDimensions());
}

uvec2 PickingContainer::clampToScreenCoords(ivec2 mpos, ivec2 dim) {
    ivec2 pos = mpos;
    pos.x = std::max(pos.x - 1, 0);
    pos.x = std::min(pos.x, dim.x - 1);

    pos.y = std::max(dim.y - pos.y - 1, 0);
    pos.y = std::min(pos.y, dim.y - 1);

    return uvec2(pos);
}

} // namespace<commit_msg>Core : Fixed broken picking movement, issue inviwo/inviwo-dev#1235<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/interaction/pickingcontainer.h>
#include <inviwo/core/interaction/pickingmanager.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/interaction/events/mouseevent.h>

namespace inviwo {

PickingContainer::PickingContainer()
    : src_(nullptr)
    , mousePickObj_(nullptr)
    , prevMouseCoord_(uvec2(0, 0))
    , mousePickingOngoing_(false)
    , mouseIsDown_(false)
    , touchPickingOn_(false)
{}

PickingContainer::~PickingContainer() {}

bool PickingContainer::pickingEnabled() {
    return PickingManager::getPtr()->pickingEnabled();
}

bool PickingContainer::performMousePick(MouseEvent* e) {
    if (!pickingEnabled() || e->button() == MouseEvent::MOUSE_BUTTON_NONE)
        return false;

    if (touchPickingOn_)
        return true;

    if (e->state() == MouseEvent::MOUSE_STATE_RELEASE){
        mouseIsDown_ = false;
        if (mousePickingOngoing_) {
            uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
            mousePickObj_->setPickingMove(normalizedMovement(prevMouseCoord_, coord));
            mousePickObj_->setPickingMouseEvent(*e);
            prevMouseCoord_ = coord;
            mousePickObj_->picked();
            mousePickingOngoing_ = false;
            return true;
        }
        else {
            mousePickObj_ = nullptr;
            return false;
        }
    }
    else if (!mouseIsDown_ || e->state() == MouseEvent::MOUSE_STATE_PRESS){
        mouseIsDown_ = true;

        uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
        prevMouseCoord_ = coord;

        mousePickObj_ = findPickingObject(coord);

        if (mousePickObj_) {
            mousePickingOngoing_ = true;
            mousePickObj_->setPickingPosition(normalizedCoordinates(coord));
            mousePickObj_->setPickingDepth(e->depth());
            mousePickObj_->setPickingMouseEvent(*e);

            mousePickObj_->setPickingMove(vec2(0.f, 0.f));
            mousePickObj_->picked();
            return true;
        }
        else{
            mousePickingOngoing_ = false;
            return false;
        }
    }
    else if (e->state() == MouseEvent::MOUSE_STATE_MOVE){
        if (mousePickingOngoing_){
            uvec2 coord = clampToScreenCoords(e->pos(), e->canvasSize());
            mousePickObj_->setPickingMove(normalizedMovement(prevMouseCoord_, coord));
            mousePickObj_->setPickingMouseEvent(*e);
            prevMouseCoord_ = coord;
            mousePickObj_->picked();
            return true;
        }
        else
            return false;
    }

    return false;
}

bool PickingContainer::performTouchPick(TouchEvent* e) {
    if (!pickingEnabled())
        return false;

    std::vector<TouchPoint>& touchPoints = e->getTouchPoints();

    // Clear the picked touch point map
    pickedTouchPoints_.clear();

    if (touchPoints.size() > 1 || touchPoints[0].state() != TouchPoint::TOUCH_STATE_ENDED)
        touchPickingOn_ = true;
    else
        touchPickingOn_ = false;

    std::unordered_map<int, PickingObject*>::iterator touchPickObjs_it;
    std::unordered_map<PickingObject*, std::vector<TouchPoint>>::iterator pickedTouchPoints_it;

    auto touchPoint = touchPoints.begin();
    while (touchPoint != touchPoints.end()) {
        bool isAssociated = false;
        if (touchPoint->state() == TouchPoint::TOUCH_STATE_STARTED) {
            // Find out if new touch point is touching inside a picking object
            uvec2 coord = clampToScreenCoords(touchPoint->getPos(), e->canvasSize());
            PickingObject* pickObj = findPickingObject(coord);

            // If it is, put it in the TouchIDPickingMap
            if (pickObj) {
                touchPickObjs_.insert(std::pair<int, PickingObject*>(touchPoint->getId(), pickObj));

                // Associate touch point with picking object
                // which can already have other associated touch points.
                pickedTouchPoints_it = pickedTouchPoints_.find(pickObj);
                if (pickedTouchPoints_it != pickedTouchPoints_.end()){
                    pickedTouchPoints_it->second.push_back(*touchPoint);
                }
                else{
                    pickedTouchPoints_.insert(std::pair<PickingObject*,
                        std::vector<TouchPoint>>(pickObj, std::vector<TouchPoint>{*touchPoint}));
                }
                isAssociated = true;
            }
        }
        else if (touchPoint->state() == TouchPoint::TOUCH_STATE_ENDED) {
            // Erase touch point from TouchIDPickingMap
            size_t numberOfErasedElements = touchPickObjs_.erase(touchPoint->getId());
            isAssociated = (numberOfErasedElements > 0);
        }
        else {
            // Find out if touch point is in the TouchIDPickingMap
            // If it exists, associate touch point with picking object
            touchPickObjs_it = touchPickObjs_.find(touchPoint->getId());
            if (touchPickObjs_it != touchPickObjs_.end()){
                // Associate touch point with picking object
                // which can already have other associated touch points.
                pickedTouchPoints_it = pickedTouchPoints_.find(touchPickObjs_it->second);
                if (pickedTouchPoints_it != pickedTouchPoints_.end()){
                    pickedTouchPoints_it->second.push_back(*touchPoint);
                }
                else{
                    pickedTouchPoints_.insert(std::pair<PickingObject*,
                        std::vector<TouchPoint>>(touchPickObjs_it->second, std::vector<TouchPoint>{*touchPoint}));
                }
                isAssociated = true;
            }
        }
        // Removed touch point from the actual event if it was associated with a picking object
        if (isAssociated)
            touchPoint = touchPoints.erase(touchPoint);
        else
            ++touchPoint;
    }

    // Build touch event for all picking objects with associated touch points
    for (pickedTouchPoints_it = pickedTouchPoints_.begin(); pickedTouchPoints_it != pickedTouchPoints_.end(); ++pickedTouchPoints_it){
        // Treat one touch point the same as mouse event, for now
        if (pickedTouchPoints_it->second.size() == 1){
            uvec2 coord = clampToScreenCoords(pickedTouchPoints_it->second[0].getPos(), e->canvasSize());
            if (pickedTouchPoints_it->second[0].state() & TouchPoint::TOUCH_STATE_STARTED){
                pickedTouchPoints_it->first->setPickingPosition(normalizedCoordinates(coord));
                pickedTouchPoints_it->first->setPickingDepth(pickedTouchPoints_it->second[0].getDepth());
                pickedTouchPoints_it->first->setPickingMove(vec2(0.f, 0.f));
            }
            else{
                uvec2 prevCoord = clampToScreenCoords(pickedTouchPoints_it->second[0].getPrevPos(), e->canvasSize());
                pickedTouchPoints_it->first->setPickingMove(normalizedMovement(prevCoord, coord));
            }
            // One touch point is currently treated as mouse event as well...
            // So prepare for that
            prevMouseCoord_ = coord;
            mousePickObj_ = pickedTouchPoints_it->first;
            mousePickingOngoing_ = true;
        }

        pickedTouchPoints_it->first->setPickingTouchEvent(TouchEvent(pickedTouchPoints_it->second, e->canvasSize()));
    }

    // One touch point is currently treated as mouse event as well...
    // So prepare for that
    if (touchPoints.size() == 1){
        prevMouseCoord_ = clampToScreenCoords(touchPoints[0].getPos(), e->canvasSize());
        touchPickingOn_ = false;
    }

    // Mark all picking objects in TouchIDPickingMap as picked.
    for (touchPickObjs_it = touchPickObjs_.begin(); touchPickObjs_it != touchPickObjs_.end(); ++touchPickObjs_it)
        touchPickObjs_it->second->picked();

    return !touchPickObjs_.empty();
}

void PickingContainer::setPickingSource(std::shared_ptr<const Image> src) {
    src_ = src;
}

PickingObject* PickingContainer::findPickingObject(const uvec2& coord){
    if (pickingEnabled() && src_) {
        const Layer* pickingLayer = src_->getPickingLayer();

        if (pickingLayer) {
            const LayerRAM* pickingLayerRAM = pickingLayer->getRepresentation<LayerRAM>();
            dvec4 value = pickingLayerRAM->getAsNormalizedDVec4(coord);
            dvec3 pickedColor = (value.a > 0.0 ? value.rgb() : dvec3(0.0));
            uvec3 color(pickedColor*255.0);
            return PickingManager::getPtr()->getPickingObjectFromColor(color);
        }
    }

    return nullptr;
}

vec2 PickingContainer::normalizedMovement(const uvec2& previous, const uvec2& current) const {
    return normalizedCoordinates(current) - normalizedCoordinates(previous);
}

vec2 PickingContainer::normalizedCoordinates(const uvec2& coord) const {
    return vec2(coord) / vec2(src_->getDimensions());
}

uvec2 PickingContainer::clampToScreenCoords(ivec2 mpos, ivec2 dim) {
    ivec2 pos = mpos;
    pos.x = std::max(pos.x - 1, 0);
    pos.x = std::min(pos.x, dim.x - 1);

    pos.y = std::max(dim.y - pos.y - 1, 0);
    pos.y = std::min(pos.y, dim.y - 1);

    return uvec2(pos);
}

} // namespace<|endoftext|>