add opendcm constraint solver

This commit is contained in:
Stefan Tröger 2013-04-25 12:14:01 +02:00 committed by Stefan Tröger
parent 474fbbcb3e
commit 952d9140d3
53 changed files with 9940 additions and 0 deletions

View File

@ -0,0 +1 @@
/usr/include/eigen3

View File

@ -0,0 +1,28 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_CORE_H
#define DCM_CORE_H
#include "core/geometry.hpp"
#include "core/kernel.hpp"
#include "core/system.hpp"
#endif //DCM_CORE_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,512 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 detemplate tails.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_CONSTRAINT_H
#define GCM_CONSTRAINT_H
#include<Eigen/StdVector>
#include <assert.h>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/size.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/size.hpp>
#include "traits.hpp"
#include "object.hpp"
#include "equations.hpp"
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
namespace detail {
//type erasure container for constraints
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
class Constraint : public Object<Sys, Derived, Signals > {
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::DynStride DS;
typedef boost::shared_ptr<Geometry> geom_ptr;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
public:
Constraint(Sys& system, geom_ptr f, geom_ptr s);
~Constraint();
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
protected:
template<typename ConstraintVector>
void initialize(typename fusion::result_of::as_vector<ConstraintVector>::type& obj);
int equationCount();
template< typename creator_type>
void resetType(creator_type& c);
void calculate(Scalar scale);
void setMaps(MES& mes);
void geometryReset(geom_ptr g) {
/* placeholder* p = content->resetConstraint(first, second);
delete content;
content = p;*/
};
void collectPseudoPoints(Vec& vec1, Vec& vec2);
//Equation is the constraint with types, the EquationSet hold all needed Maps for calculation
template<typename Equation>
struct EquationSet {
EquationSet() : m_diff_first(NULL,0,DS(0,0)), m_diff_second(NULL,0,DS(0,0)),
m_residual(NULL,0,DS(0,0)) {};
Equation m_eq;
typename Kernel::VectorMap m_diff_first; //first geometry diff
typename Kernel::VectorMap m_diff_second; //second geometry diff
typename Kernel::VectorMap m_residual;
typedef Equation eq_type;
};
struct placeholder {
virtual ~placeholder() {}
virtual placeholder* resetConstraint(geom_ptr first, geom_ptr second) const = 0;
virtual void calculate(geom_ptr first, geom_ptr second, Scalar scale) = 0;
virtual int equationCount() = 0;
virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second) = 0;
virtual void collectPseudoPoints(geom_ptr first, geom_ptr second, Vec& vec1, Vec& vec2) = 0;
virtual placeholder* clone() = 0;
};
public:
template< typename ConstraintVector, typename EquationVector>
struct holder : public placeholder {
//create a vector of EquationSets with some mpl trickery
typedef typename mpl::fold< EquationVector, mpl::vector<>,
mpl::push_back<mpl::_1, EquationSet<mpl::_2> > >::type eq_set_vector;
typedef typename fusion::result_of::as_vector<eq_set_vector>::type EquationSets;
typedef typename fusion::result_of::as_vector<ConstraintVector>::type Objects;
template<typename T>
struct has_option {
//we get the index of the eqaution in the eqaution vector, and as it is the same
//as the index of the constraint in the constraint vector we can extract the
//option type and check if it is no_option
typedef typename mpl::find<EquationVector, T>::type iterator;
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
typedef typename mpl::at<ConstraintVector, distance>::type option_type;
typedef mpl::not_<boost::is_same<option_type, no_option> > type;
};
struct OptionSetter {
Objects& objects;
OptionSetter(Objects& val);
//only set the value if the equation has a option
template< typename T >
typename boost::enable_if<typename has_option<T>::type, void>::type
operator()(EquationSet<T>& val) const;
//if the equation has no otpion we do nothing!
template< typename T >
typename boost::enable_if<mpl::not_<typename has_option<T>::type>, void>::type
operator()(EquationSet<T>& val) const;
};
struct Calculater {
geom_ptr first, second;
Scalar scale;
Calculater(geom_ptr f, geom_ptr s, Scalar sc);
template< typename T >
void operator()(T& val) const;
};
struct MapSetter {
MES& mes;
geom_ptr first, second;
MapSetter(MES& m, geom_ptr f, geom_ptr s);
template< typename T >
void operator()(T& val) const;
};
struct PseudoCollector {
Vec& points1;
Vec& points2;
geom_ptr first,second;
PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
template< typename T >
void operator()(T& val) const;
};
holder(Objects& obj);
virtual void calculate(geom_ptr first, geom_ptr second, Scalar scale);
virtual placeholder* resetConstraint(geom_ptr first, geom_ptr second) const;
virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second);
virtual void collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
virtual placeholder* clone();
virtual int equationCount() {
return mpl::size<EquationVector>::value;
};
EquationSets m_sets;
};
protected:
template< typename ConstraintVector >
struct creator : public boost::static_visitor<void> {
typedef typename fusion::result_of::as_vector<ConstraintVector>::type Objects;
Objects& objects;
creator(Objects& obj);
template<typename C, typename T1, typename T2>
struct equation {
typedef typename C::template type<Kernel, T1, T2> type;
};
template<typename T1, typename T2>
void operator()(const T1&, const T2&);
placeholder* p;
bool need_swap;
};
placeholder* content;
geom_ptr first, second;
Connection cf, cs;
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
Constraint<Sys, Derived, Signals, MES, Geometry>::Constraint(Sys& system, geom_ptr f, geom_ptr s)
: first(f), second(s), content(0) {
this->m_system = &system;
cf = first->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
cs = second->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
Constraint<Sys, Derived, Signals, MES, Geometry>::~Constraint() {
delete content;
first->template disconnectSignal<reset>(cf);
second->template disconnectSignal<reset>(cs);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
boost::shared_ptr<Derived> Constraint<Sys, Derived, Signals, MES, Geometry>::clone(Sys& newSys) {
//copy the standart stuff
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
np->m_system = &newSys;
//copy the internals
np->content = content->clone();
//and get the geometry pointers right
if(first) {
GlobalVertex v = first->template getProperty<typename Geometry::vertex_propertie>();
np->first = newSys.m_cluster->template getObject<Geometry>(v);
}
if(second) {
GlobalVertex v = second->template getProperty<typename Geometry::vertex_propertie>();
np->second = newSys.m_cluster->template getObject<Geometry>(v);
}
return np;
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector>
void Constraint<Sys, Derived, Signals, MES, Geometry>::initialize(typename fusion::result_of::as_vector<ConstraintVector>::type& obj) {
//first create the new placeholder
creator<ConstraintVector> c(obj);
boost::apply_visitor(c, first->m_geometry, second->m_geometry);
//and now store it
content = c.p;
//geometry order needs to be the one needed by equations
if(c.need_swap) first.swap(second);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
int Constraint<Sys, Derived, Signals, MES, Geometry>::equationCount() {
return content->equationCount();
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template< typename creator_type>
void Constraint<Sys, Derived, Signals, MES, Geometry>::resetType(creator_type& c) {
boost::apply_visitor(c, first->m_geometry, second->m_geometry);
content = c.p;
if(c.need_swap) first.swap(second);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
void Constraint<Sys, Derived, Signals, MES, Geometry>::calculate(Scalar scale) {
content->calculate(first, second, scale);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
void Constraint<Sys, Derived, Signals, MES, Geometry>::setMaps(MES& mes) {
content->setMaps(mes, first, second);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
void Constraint<Sys, Derived, Signals, MES, Geometry>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
content->collectPseudoPoints(first, second, vec1, vec2);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
template<typename T>
typename boost::enable_if<typename Constraint<Sys, Derived, Signals, MES, Geometry>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type, void>::type
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
//get the index of the corresbonding equation
typedef typename mpl::find<EquationVector, T>::type iterator;
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
val.m_eq.value = fusion::at<distance>(objects).value;
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
template<typename T>
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Derived, Signals, MES, Geometry>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type>, void>::type
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc) : first(f), second(s), scale(sc) {
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::Calculater::operator()(T& val) const {
val.m_eq.setScale(scale);
val.m_residual(0) = val.m_eq.calculate(first->m_parameter, second->m_parameter);
//now see which way we should calculate the gradient (may be diffrent for both geometries)
if(first->m_parameterCount) {
if(first->getClusterMode()) {
//when the cluster is fixed no maps are set as no parameters exist.
if(!first->isClusterFixed()) {
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
for(int i=0; i<6; i++) {
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, block);
}
}
} else {
//not in cluster, so allow the constraint to optimize the gradient calculation
val.m_eq.calculateGradientFirstComplete(first->m_parameter, second->m_parameter, val.m_diff_first);
}
}
if(second->m_parameterCount) {
if(second->getClusterMode()) {
if(!second->isClusterFixed()) {
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
for(int i=0; i<6; i++) {
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
second->m_parameter, block);
}
}
} else {
//not in cluster, so allow the constraint to optimize the gradient calculation
val.m_eq.calculateGradientSecondComplete(first->m_parameter, second->m_parameter, val.m_diff_second);
}
}
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
: mes(m), first(f), second(s) {
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::MapSetter::operator()(T& val) const {
//when in cluster, there are 6 clusterparameter we differentiat for, if not we differentiat
//for every parameter in the geometry;
int equation = mes.setResidualMap(val.m_residual);
if(first->getClusterMode()) {
if(!first->isClusterFixed()) {
mes.setJacobiMap(equation, first->m_offset, 6, val.m_diff_first);
}
} else mes.setJacobiMap(equation, first->m_offset, first->m_parameterCount, val.m_diff_first);
if(second->getClusterMode()) {
if(!second->isClusterFixed()) {
mes.setJacobiMap(equation, second->m_offset, 6, val.m_diff_second);
}
} else mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2)
: first(f), second(s), points1(vec1), points2(vec2) {
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::PseudoCollector::operator()(T& val) const {
if(first->m_isInCluster && second->m_isInCluster) {
val.m_eq.calculatePseudo(first->m_rotated, points1, second->m_rotated, points2);
} else if(first->m_isInCluster) {
typename Kernel::Vector sec = second->m_parameter;
val.m_eq.calculatePseudo(first->m_rotated, points1, sec, points2);
} else if(second->m_isInCluster) {
typename Kernel::Vector fir = first->m_parameter;
val.m_eq.calculatePseudo(fir, points1, second->m_rotated, points2);
}
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::holder(Objects& obj) {
//set the initial values in the equations
fusion::for_each(m_sets, OptionSetter(obj));
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::calculate(geom_ptr first, geom_ptr second, Scalar scale) {
fusion::for_each(m_sets, Calculater(first, second, scale));
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
typename Constraint<Sys, Derived, Signals, MES, Geometry>::placeholder*
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::resetConstraint(geom_ptr first, geom_ptr second) const {
//boost::apply_visitor(creator, first->m_geometry, second->m_geometry);
//if(creator.need_swap) first.swap(second);
return NULL;
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
fusion::for_each(m_sets, MapSetter(mes, first, second));
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) {
fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2));
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template<typename ConstraintVector, typename EquationVector>
typename Constraint<Sys, Derived, Signals, MES, Geometry>::placeholder*
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::clone() {
return new holder(*this);
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template< typename ConstraintVector >
Constraint<Sys, Derived, Signals, MES, Geometry>::creator<ConstraintVector>::creator(Objects& obj) : objects(obj) {
};
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
template< typename ConstraintVector >
template<typename T1, typename T2>
void Constraint<Sys, Derived, Signals, MES, Geometry>::creator<ConstraintVector>::operator()(const T1&, const T2&) {
typedef tag_order< typename geometry_traits<T1>::tag, typename geometry_traits<T2>::tag > order;
//transform the constraints into eqautions with the now known types
typedef typename mpl::fold< ConstraintVector, mpl::vector<>,
mpl::push_back<mpl::_1, equation<mpl::_2, typename order::first_tag,
typename order::second_tag> > >::type EquationVector;
//and build the placeholder
p = new holder<ConstraintVector, EquationVector>(objects);
need_swap = order::swapt::value;
};
};//detail
};//dcm
#endif //GCM_CONSTRAINT_H

View File

@ -0,0 +1,189 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 detemplate tails.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_EQUATIONS_H
#define GCM_EQUATIONS_H
#include <assert.h>
namespace dcm {
struct no_option {};
template<typename Kernel>
struct Pseudo {
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
};
template<typename Kernel>
struct Scale {
void setScale(typename Kernel::number_type scale) {};
};
template<typename Kernel>
struct PseudoScale {
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
void setScale(typename Kernel::number_type scale) {};
};
struct Distance {
typedef double option_type;
option_type value;
Distance() : value(0) {};
Distance& operator=(const option_type val) {
value = val;
return *this;
};
template< typename Kernel, typename Tag1, typename Tag2 >
struct type {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
Scalar value;
//template definition
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {
assert(false);
};
void setScale(Scalar scale) {
assert(false);
};
Scalar calculate(Vector& param1, Vector& param2) {
assert(false);
return 0;
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
assert(false);
return 0;
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
assert(false);
return 0;
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
};
};
//the possible directions
enum Direction { Same, Opposite, Both };
struct Parallel {
typedef Direction option_type;
option_type value;
Parallel() : value(Both) {};
Parallel& operator=(const option_type val) {
value = val;
return *this;
};
template< typename Kernel, typename Tag1, typename Tag2 >
struct type : public PseudoScale<Kernel> {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
option_type value;
//template definition
Scalar calculate(Vector& param1, Vector& param2) {
assert(false);
return 0;
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
assert(false);
return 0;
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
assert(false);
return 0;
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
};
};
struct Angle {
typedef double option_type;
option_type value;
Angle() : value(0) {};
Angle& operator=(const option_type val) {
value = val;
return *this;
};
template< typename Kernel, typename Tag1, typename Tag2 >
struct type : public PseudoScale<Kernel> {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
option_type value;
//template definition
Scalar calculate(Vector& param1, Vector& param2) {
assert(false);
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
assert(false);
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
assert(false);
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
};
};
//static is needed to restrain the scope of the objects to the current compilation unit. Without it
//every compiled file including this header would define these as global and the linker would find
//multiple definitions of the same objects
static Distance distance;
static Parallel parallel;
static Angle angle;
};
#endif //GCM_EQUATIONS_H

View File

@ -0,0 +1,481 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_GEOMETRY_H
#define GCM_GEOMETRY_H
#include <iostream>
#include <Eigen/Core>
#include <boost/type_traits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/set.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/map.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/concept_check.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/function.hpp>
#include <boost/variant.hpp>
#include "object.hpp"
#include "traits.hpp"
#include "logging.hpp"
#include "transformation.hpp"
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
namespace tag {
struct undefined {
typedef mpl::int_<0> parameters;
typedef mpl::int_<0> transformations;
};
//we need to order tags, this values make it easy for module tags
namespace weight {
struct direction : mpl::int_<0> {};
struct point : mpl::int_<1> {};
struct line : mpl::int_<2> {};
struct plane : mpl::int_<3> {};
struct cylinder : mpl::int_<4> {};
}
}
struct orderd_bracket_accessor {
template<typename Scalar, int ID, typename T>
Scalar get(T& t) {
return t[ID];
};
template<typename Scalar, int ID, typename T>
void set(Scalar value, T& t) {
t[ID] = value;
};
};
struct orderd_roundbracket_accessor {
template<typename Scalar, int ID, typename T>
Scalar get(T& t) {
return t(ID);
};
template<typename Scalar, int ID, typename T>
void set(Scalar value, T& t) {
t(ID) = value;
};
};
//tag ordering (smaller weight is first tag)
template<typename T1, typename T2>
struct tag_order {
BOOST_MPL_ASSERT((mpl::not_< mpl::or_<
boost::is_same< typename T1::weight, mpl::int_<0> >,
boost::is_same< typename T2::weight, mpl::int_<0> > > >));
typedef typename mpl::less<typename T2::weight, typename T1::weight>::type swapt;
typedef typename mpl::if_<swapt, T2, T1>::type first_tag;
typedef typename mpl::if_<swapt, T1, T2>::type second_tag;
};
//template<typename T1, typename T2>
//struct type_order : public tag_order< typename geometry_traits<T1>::tag, typename geometry_traits<T2>::tag > {};
template< typename T>
struct geometry_traits {
BOOST_MPL_ASSERT_MSG(false, NO_GEOMETRY_TRAITS_SPECIFIED_FOR_TYPE, (T));
};
template< typename T>
struct geometry_clone_traits {
T operator()(T& val) {
return T(val);
};
};
struct reset {}; //signal namespace
namespace detail {
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
class Geometry : public Object<Sys, Derived,
mpl::map3< mpl::pair<reset, boost::function<void (boost::shared_ptr<Derived>) > >,
mpl::pair<remove, boost::function<void (boost::shared_ptr<Derived>) > > ,
mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Derived>)> > > > {
typedef mpl::map3< mpl::pair<reset, boost::function<void (boost::shared_ptr<Derived>) > >,
mpl::pair<remove, boost::function<void (boost::shared_ptr<Derived>) > >,
mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Derived>)> > > Signals;
typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant;
typedef Object<Sys, Derived, Signals> Base;
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::DynStride DS;
typedef typename Kernel::template transform_type<Dim>::type Transform;
typedef typename Kernel::template transform_type<Dim>::diff_type DiffTransform;
struct cloner : boost::static_visitor<void> {
typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant;
Variant variant;
cloner(Variant& v) : variant(v) {};
template<typename T>
void operator()(T& t) {
variant = geometry_clone_traits<T>()(t);
};
};
#ifdef USE_LOGGING
protected:
src::logger log;
#endif
public:
typedef mpl::int_<Dim> Dimension;
template<typename T>
Geometry(T geometry, Sys& system);
template<typename T>
void set(T geometry);
template<typename Visitor>
typename Visitor::result_type apply(Visitor& vis) {
return boost::apply_visitor(vis, m_geometry);
};
//basic ation
void transform(const Transform& t);
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
//allow accessing the internal values in unittests without making them public,
//so that access control of the internal classes is not changed and can be tested
#ifdef TESTING
typename Kernel::Vector& toplocal() {
return m_toplocal;
};
typename Kernel::Vector& rotated() {
return m_rotated;
};
int& offset() {
return m_offset;
};
void clusterMode(bool iscluster, bool isFixed) {
setClusterMode(iscluster, isFixed);
};
void trans(const Transform& t) {
transform(t);
};
void recalc(DiffTransform& trans) {
recalculate(trans);
};
typename Kernel::Vector3 point() {
return getPoint();
};
int parameterCount() {
return m_parameterCount;
};
#endif
//protected would be the right way, however, visual studio 10 does not find a way to access them even when constraint::holder structs
//are declared friend
//protected:
Variant m_geometry; //Variant holding the real geometry type
int m_BaseParameterCount; //count of the parameters the variant geometry type needs
int m_parameterCount; //count of the used parameters (when in cluster:6, else m_BaseParameterCount)
int m_offset; //the starting point of our parameters in the math system parameter vector
int m_rotations; //count of rotations to be done when original vector gets rotated
int m_translations; //count of translations to be done when original vector gets rotated
bool m_isInCluster, m_clusterFixed, m_init;
typename Kernel::Vector m_toplocal; //the local value in the toplevel cluster used for cuttent solving
typename Kernel::Vector m_global; //the global value outside of all clusters
typename Kernel::Vector m_rotated; //the global value as the rotation of toplocal (used as temp)
typename Kernel::Matrix m_diffparam; //gradient vectors combined as matrix when in cluster
typename Kernel::VectorMap m_parameter; //map to the parameters in the solver
template<typename T>
void init(T& t);
void normalize();
typename Sys::Kernel::VectorMap& getParameterMap();
void initMap();
void setClusterMode(bool iscluster, bool isFixed);
bool getClusterMode() {
return m_isInCluster;
};
bool isClusterFixed() {
return m_clusterFixed;
};
void recalculate(DiffTransform& trans);
typename Kernel::Vector3 getPoint() {
return m_toplocal.template segment<Dim>(0);
};
//visitor to write the calculated value into the variant
struct apply_visitor : public boost::static_visitor<void> {
apply_visitor(typename Kernel::Vector& v) : value(v) {};
template <typename T>
void operator()(T& t) const {
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
typename geometry_traits<T>::accessor >(t, value);
}
typename Kernel::Vector& value;
};
//use m_value or parametermap as new value, dependend on the solving mode
void finishCalculation();
template<typename VectorType>
void transform(const Transform& t, VectorType& vec);
void scale(Scalar value);
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
template<typename T>
Geometry<Sys, Derived, GeometrieTypeList, Dim>::Geometry(T geometry, Sys& system)
: m_isInCluster(false), m_geometry(geometry), m_parameter(NULL,0,DS(0,0)),
m_clusterFixed(false), m_init(false) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
#endif
this->m_system = &system;
init<T>(geometry);
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
template<typename T>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::set(T geometry) {
m_geometry = geometry;
init<T>(geometry);
//Base::template emitSignal<reset>( ((Derived*)this)->shared_from_this() );
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::transform(const Transform& t) {
if(m_isInCluster)
transform(t, m_toplocal);
else if(m_init)
transform(t, m_rotated);
else
transform(t, m_global);
};
template<typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
boost::shared_ptr<Derived> Geometry<Sys, Derived, GeometrieTypeList, Dim>::clone(Sys& newSys) {
//copy the standart stuff
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
np->m_system = &newSys;
//it's possible that the variant contains pointers, so we need to clone them
cloner clone_fnc(np->m_geometry);
boost::apply_visitor(clone_fnc, m_geometry);
return np;
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
template<typename T>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::init(T& t) {
m_BaseParameterCount = geometry_traits<T>::tag::parameters::value;
m_parameterCount = m_BaseParameterCount;
m_rotations = geometry_traits<T>::tag::rotations::value;
m_translations = geometry_traits<T>::tag::translations::value;
m_toplocal.setZero(m_parameterCount);
m_global.resize(m_parameterCount);
m_rotated.resize(m_parameterCount);
m_rotated.setZero();
m_diffparam.resize(m_parameterCount,6);
m_diffparam.setZero();
(typename geometry_traits<T>::modell()).template extract<Scalar,
typename geometry_traits<T>::accessor >(t, m_global);
normalize();
//new value which is not set into parameter, so init is false
m_init = false;
#ifdef USE_LOGGING
BOOST_LOG(log) << "Init: "<<m_global.transpose();
#endif
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::normalize() {
//directions are not nessessarily normalized, but we need to ensure this in cluster mode
for(int i=m_translations; i!=m_rotations; i++)
m_global.template segment<Dim>(i*Dim).normalize();
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
typename Sys::Kernel::VectorMap& Geometry<Sys, Derived, GeometrieTypeList, Dim>::getParameterMap() {
m_isInCluster = false;
m_parameterCount = m_BaseParameterCount;
return m_parameter;
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::initMap() {
//when direct parameter solving the global value is wanted (as it's the initial rotation*toplocal)
m_parameter = m_global;
m_init = true;
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::setClusterMode(bool iscluster, bool isFixed) {
m_isInCluster = iscluster;
m_clusterFixed = isFixed;
if(iscluster) {
//we are in cluster, therfore the parameter map should not point to a solver value but to
//the rotated original value;
new(&m_parameter) typename Sys::Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1));
//the local value is the global one as no transformation was applied yet
m_toplocal = m_global;
m_rotated = m_global;
} else new(&m_parameter) typename Sys::Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::recalculate(DiffTransform& trans) {
if(!m_isInCluster) return;
for(int i=0; i!=m_rotations; i++) {
//first rotate the original to the transformed value
m_rotated.block(i*Dim,0,Dim,1) = trans.rotation()*m_toplocal.template segment<Dim>(i*Dim);
//now calculate the gradient vectors and add them to diffparam
for(int j=0; j<Dim; j++)
m_diffparam.block(i*Dim,j,Dim,1) = trans.differential().block(0,j*3,Dim,Dim) * m_toplocal.template segment<Dim>(i*Dim);
}
//after rotating the needed parameters we translate the stuff that needs to be moved
for(int i=0; i!=m_translations; i++) {
m_rotated.block(i*Dim,0,Dim,1) += trans.translation().vector();
m_rotated.block(i*Dim,0,Dim,1) *= trans.scaling().factor();
//calculate the gradient vectors and add them to diffparam
m_diffparam.block(i*Dim,Dim,Dim,Dim).setIdentity();
}
#ifdef USE_LOGGING
if(!boost::math::isnormal(m_rotated.norm()) || !boost::math::isnormal(m_diffparam.norm())) {
BOOST_LOG(log) << "Unnormal recalculated value detected: "<<m_rotated.transpose()<<std::endl
<< "or unnormal recalculated diff detected: "<<std::endl<<m_diffparam<<std::endl
<<" with Transform: "<<std::endl<<trans;
}
#endif
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::finishCalculation() {
//if fixed nothing needs to be changed
if(m_isInCluster) {
//recalculate(1.); //remove scaling to get right global value
m_global = m_rotated;
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish cluster calculation";
#endif
}
//TODO:non cluster paramter scaling
else {
m_global = m_parameter;
normalize();
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish calculation";
#endif
};
apply_visitor v(m_global);
apply(v);
m_init = false;
m_isInCluster = false;
//emit the signal for recalculation
Base::template emitSignal<recalculated>( ((Derived*)this)->shared_from_this() );
};
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
template<typename VectorType>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::transform(const Transform& t, VectorType& vec) {
//everything that needs to be translated needs to be fully transformed
for(int i=0; i!=m_translations; i++) {
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
vec.template segment<Dim>(i*Dim) = t*v;
}
for(int i=m_translations; i!=m_rotations; i++) {
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
vec.template segment<Dim>(i*Dim) = t.rotate(v);
}
#ifdef USE_LOGGING
BOOST_LOG(log) << "Transformed with cluster: "<<m_isInCluster
<< ", init: "<<m_init<<" into: "<< vec.transpose();
#endif
}
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::scale(Scalar value) {
for(int i=0; i!=m_translations; i++)
m_parameter.template segment<Dim>(i*Dim) *= 1./value;
};
}
}
#endif // GCM_GEOMETRY_H

View File

@ -0,0 +1,425 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_KERNEL_H
#define GCM_KERNEL_H
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <iostream>
#include <boost/math/special_functions/fpclassify.hpp>
#include <time.h>
#include "transformation.hpp"
#include "logging.hpp"
namespace dcm {
namespace E = Eigen;
struct nothing {
void operator()() {};
};
template<typename Kernel>
struct Dogleg {
#ifdef USE_LOGGING
src::logger log;
#endif
typedef typename Kernel::number_type number_type;
number_type tolg, tolx, tolf;
Dogleg() : tolg(1e-40), tolx(1e-20), tolf(1e-5) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
#endif
};
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
int calculateStep(const Eigen::MatrixBase<Derived>& g, const Eigen::MatrixBase<Derived3>& jacobi,
const Eigen::MatrixBase<Derived4>& residual, Eigen::MatrixBase<Derived2>& h_dl,
const double delta) {
// get the steepest descent stepsize and direction
const double alpha(g.squaredNorm()/(jacobi*g).squaredNorm());
const typename Kernel::Vector h_sd = -g;
// get the gauss-newton step
const typename Kernel::Vector h_gn = (jacobi).fullPivLu().solve(-residual);
#ifdef USE_LOGGING
if(!boost::math::isfinite(h_gn.norm())) {
BOOST_LOG(log)<< "Unnormal gauss-newton detected: "<<h_gn.norm();
}
if(!boost::math::isfinite(h_sd.norm())) {
BOOST_LOG(log)<< "Unnormal steepest descent detected: "<<h_sd.norm();
}
if(!boost::math::isfinite(alpha)) {
BOOST_LOG(log)<< "Unnormal alpha detected: "<<alpha;
}
#endif
// compute the dogleg step
if(h_gn.norm() <= delta) {
h_dl = h_gn;
} else if((alpha*h_sd).norm() >= delta) {
//h_dl = alpha*h_sd;
h_dl = (delta/(h_sd.norm()))*h_sd;
#ifdef USE_LOGGING
if(!boost::math::isfinite(h_dl.norm())) {
BOOST_LOG(log)<< "Unnormal dogleg descent detected: "<<h_dl.norm();
}
#endif
} else {
//compute beta
number_type beta = 0;
typename Kernel::Vector a = alpha*h_sd;
typename Kernel::Vector b = h_gn;
number_type c = a.transpose()*(b-a);
number_type bas = (b-a).squaredNorm(), as = a.squaredNorm();
if(c<0) {
beta = -c+std::sqrt(std::pow(c,2)+bas*(std::pow(delta,2)-as));
beta /= bas;
} else {
beta = std::pow(delta,2)-as;
beta /= c+std::sqrt(std::pow(c,2) + bas*(std::pow(delta,2)-as));
};
// and update h_dl and dL with beta
h_dl = alpha*h_sd + beta*(b-a);
#ifdef USE_LOGGING
if(!boost::math::isfinite(c)) {
BOOST_LOG(log)<< "Unnormal dogleg c detected: "<<c;
}
if(!boost::math::isfinite(bas)) {
BOOST_LOG(log)<< "Unnormal dogleg bas detected: "<<bas;
}
if(!boost::math::isfinite(beta)) {
BOOST_LOG(log)<< "Unnormal dogleg beta detected: "<<beta;
}
#endif
}
return 0;
};
int solve(typename Kernel::MappedEquationSystem& sys) {
nothing n;
return solve(sys, n);
};
template<typename Functor>
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale) {
clock_t start = clock();
clock_t inc_rec = clock();
if(!sys.isValid()) return 5;
bool translate = true;
typename Kernel::Vector h_dl, F_old(sys.m_eqns), g(sys.m_eqns);
typename Kernel::Matrix J_old(sys.m_eqns, sys.m_params);
sys.recalculate();
#ifdef USE_LOGGING
BOOST_LOG(log)<< "initial jacobi: "<<std::endl<<sys.Jacobi<<std::endl
<< "residual: "<<sys.Residual.transpose()<<std::endl
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
#endif
number_type err = sys.Residual.norm();
F_old = sys.Residual;
J_old = sys.Jacobi;
g = sys.Jacobi.transpose()*(sys.Residual);
// get the infinity norm fx_inf and g_inf
number_type g_inf = g.template lpNorm<E::Infinity>();
number_type fx_inf = sys.Residual.template lpNorm<E::Infinity>();
int maxIterNumber = 10000;//MaxIterations * xsize;
number_type diverging_lim = 1e6*err + 1e12;
number_type delta=5;
number_type nu=2.;
int iter=0, stop=0, reduce=0, unused=0, counter=0;
while(!stop) {
// check if finished
if(fx_inf <= tolf*sys.Scaling) // Success
stop = 1;
else if(g_inf <= tolg)
stop = 2;
else if(delta <= tolx)
stop = 3;
else if(iter >= maxIterNumber)
stop = 4;
else if(!boost::math::isfinite(err))
stop = 5;
else if(err > diverging_lim)
stop = 6;
// see if we are already finished
if(stop)
break;
number_type err_new;
number_type dF=0, dL=0;
number_type rho;
//get the update step
calculateStep(g, sys.Jacobi, sys.Residual, h_dl, delta);
// calculate the linear model
dL = 0.5*sys.Residual.norm() - 0.5*(sys.Residual + sys.Jacobi*h_dl).norm();
// get the new values
sys.Parameter += h_dl;
clock_t start_rec = clock();
sys.recalculate();
clock_t end_rec = clock();
inc_rec += end_rec-start_rec;
#ifdef USE_LOGGING
if(!boost::math::isfinite(sys.Residual.norm())) {
BOOST_LOG(log)<< "Unnormal residual detected: "<<sys.Residual.norm();
}
if(!boost::math::isfinite(sys.Jacobi.sum())) {
BOOST_LOG(log)<< "Unnormal jacobi detected: "<<sys.Jacobi.sum();
}
#endif
//calculate the translation update ratio
err_new = sys.Residual.norm();
dF = err - err_new;
rho = dF/dL;
if(dF<=0 || dL<=0) rho = -1;
// update delta
if(rho>0.85) {
delta = std::max(delta,2*h_dl.norm());
nu = 2;
} else if(rho < 0.25) {
delta = delta/nu;
nu = 2*nu;
}
if(dF > 0 && dL > 0) {
//see if we got too high differentials
if(sys.Jacobi.template lpNorm<Eigen::Infinity>() > 2) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "High differential detected: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>()<<" in iteration: "<<iter;
#endif
rescale();
sys.recalculate();
}
//it can also happen that the differentials get too small, however, we cant check for that
else if(iter>1 && (counter>50)) {
rescale();
sys.recalculate();
counter = 0;
}
F_old = sys.Residual;
J_old = sys.Jacobi;
err = sys.Residual.norm();
g = sys.Jacobi.transpose()*(sys.Residual);
// get infinity norms
g_inf = g.template lpNorm<E::Infinity>();
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
} else {
sys.Residual = F_old;
sys.Jacobi = J_old;
sys.Parameter -= h_dl;
unused++;
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Reject step in iter "<<iter;
#endif
}
iter++;
counter++;
}
/*
clock_t end = clock();
double ms = (double(end-start) * 1000.) / double(CLOCKS_PER_SEC);
double ms_rec = (double(inc_rec-start) * 1000.) / double(CLOCKS_PER_SEC);
*/
#ifdef USE_LOGGING
BOOST_LOG(log) <<"Done solving: "<<err<<", iter: "<<iter<<", unused: "<<unused<<", reason:"<< stop;
BOOST_LOG(log)<< "final jacobi: "<<std::endl<<sys.Jacobi;
#endif
return stop;
}
};
template<typename Scalar, template<class> class Nonlinear = Dogleg>
struct Kernel {
//basics
typedef Scalar number_type;
//linear algebra types 2D
typedef E::Matrix<Scalar, 2, 1> Vector2;
//Linear algebra types 3D
typedef E::Matrix<Scalar, 3, 1> Vector3;
typedef E::Matrix<Scalar, 1, 3> CVector3;
typedef E::Matrix<Scalar, 3, 3> Matrix3;
typedef E::Matrix<Scalar, E::Dynamic, 1> Vector;
typedef E::Matrix<Scalar, 1, E::Dynamic> CVector;
typedef E::Matrix<Scalar, E::Dynamic, E::Dynamic> Matrix;
//mapped types
typedef E::Stride<E::Dynamic, E::Dynamic> DynStride;
typedef E::Map< Vector3 > Vector3Map;
typedef E::Map< CVector3> CVector3Map;
typedef E::Map< Matrix3 > Matrix3Map;
typedef E::Map< Vector, 0, DynStride > VectorMap;
typedef E::Map< CVector, 0, DynStride > CVectorMap;
typedef E::Map< Matrix, 0, DynStride > MatrixMap;
//Special types
typedef E::Quaternion<Scalar> Quaternion;
typedef E::Matrix<Scalar, 3, 9> Matrix39;
typedef E::Map< Matrix39 > Matrix39Map;
typedef E::Block<Matrix> MatrixBlock;
typedef detail::Transform<Scalar, 3> Transform3D;
typedef detail::DiffTransform<Scalar, 3> DiffTransform3D;
typedef detail::Transform<Scalar, 2> Transform2D;
typedef detail::DiffTransform<Scalar, 2> DiffTransform2D;
typedef Nonlinear< Kernel<Scalar, Nonlinear> > NonlinearSolver;
template<int Dim>
struct transform_type {
typedef typename boost::mpl::if_c<Dim==2, Transform2D, Transform3D>::type type;
typedef typename boost::mpl::if_c<Dim==2, DiffTransform2D, DiffTransform3D>::type diff_type;
};
template<int Dim>
struct vector_type {
typedef E::Matrix<Scalar, Dim, 1> type;
};
struct MappedEquationSystem {
Matrix Jacobi;
Vector Parameter;
Vector Residual;
number_type Scaling;
int m_params, m_eqns; //total amount
int m_param_offset, m_eqn_offset; //current positions while creation
MappedEquationSystem(int params, int equations)
: Jacobi(equations, params),
Parameter(params), Residual(equations),
m_params(params), m_eqns(equations), Scaling(1.) {
m_param_offset = 0;
m_eqn_offset = 0;
Jacobi.setZero(); //important as some places are never written
};
int setParameterMap(int number, VectorMap& map) {
new(&map) VectorMap(&Parameter(m_param_offset), number, DynStride(1,1));
m_param_offset += number;
return m_param_offset-number;
};
int setParameterMap(Vector3Map& map) {
new(&map) Vector3Map(&Parameter(m_param_offset));
m_param_offset += 3;
return m_param_offset-3;
};
int setResidualMap(VectorMap& map) {
new(&map) VectorMap(&Residual(m_eqn_offset), 1, DynStride(1,1));
return m_eqn_offset++;
};
void setJacobiMap(int eqn, int offset, int number, CVectorMap& map) {
new(&map) CVectorMap(&Jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
void setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
new(&map) VectorMap(&Jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
bool isValid() {
if(!m_params || !m_eqns) return false;
return true;
};
virtual void recalculate() = 0;
};
Kernel() {};
template <typename DerivedA,typename DerivedB>
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1-p2).squaredNorm() < 0.00001);
}
static bool isSame(number_type t1, number_type t2) {
return (std::abs(t1-t2) < 0.00001);
}
template <typename DerivedA,typename DerivedB>
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1+p2).squaredNorm() < 0.00001);
}
static int solve(MappedEquationSystem& mes) {
nothing n;
return Nonlinear< Kernel<Scalar, Nonlinear> >().solve(mes, n);
};
template<typename Functor>
static int solve(MappedEquationSystem& mes, Functor& f) {
return Nonlinear< Kernel<Scalar, Nonlinear> >().solve(mes, f);
};
};
}
#endif //GCM_KERNEL_H

View File

@ -0,0 +1,94 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_LOGGING_H
#define GCM_LOGGING_H
#ifdef USE_LOGGING
#include <boost/log/core.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/attributes/attribute_def.hpp>
#include <boost/log/utility/init/to_file.hpp>
#include <boost/log/utility/init/common_attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/filters.hpp>
#include <boost/shared_ptr.hpp>
namespace logging = boost::log;
namespace sinks = boost::log::sinks;
namespace src = boost::log::sources;
namespace fmt = boost::log::formatters;
namespace flt = boost::log::filters;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
namespace dcm {
static int counter = 0;
typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;
inline boost::shared_ptr< sink_t > init_log() {
//create the filename
std::stringstream str;
str<<"openDCM_"<<counter<<"_%N.log";
counter++;
boost::shared_ptr< logging::core > core = logging::core::get();
boost::shared_ptr< sinks::text_file_backend > backend =
boost::make_shared< sinks::text_file_backend >(
keywords::file_name = str.str(), //file name pattern
keywords::rotation_size = 10 * 1024 * 1024 //Rotation size is 10MB
);
// Wrap it into the frontend and register in the core.
// The backend requires synchronization in the frontend.
boost::shared_ptr< sink_t > sink(new sink_t(backend));
sink->set_formatter(
fmt::stream <<"[" << fmt::attr<std::string>("Tag") <<"] "
<< fmt::if_(flt::has_attr<std::string>("ID")) [
fmt::stream << "["<< fmt::attr< std::string >("ID")<<"] "]
<< fmt::message()
);
core->add_sink(sink);
return sink;
};
inline void stop_log(boost::shared_ptr< sink_t >& sink) {
boost::shared_ptr< logging::core > core = logging::core::get();
// Remove the sink from the core, so that no records are passed to it
core->remove_sink(sink);
sink.reset();
};
}; //dcm
#endif //USE_LOGGING
#endif //GCM_LOGGING_H

View File

@ -0,0 +1,269 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_OBJECT_H
#define GCM_OBJECT_H
#include <iostream>
#include <list>
#include <boost/mpl/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/key_type.hpp>
#include <boost/mpl/value_type.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/any.hpp>
#include "property.hpp"
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
#define EMIT_ARGUMENTS(z, n, data) \
BOOST_PP_CAT(data, n)
#define EMIT_CALL_DEF(z, n, data) \
template < \
typename S \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
> \
void emitSignal( \
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
);
#define EMIT_CALL_DEC(z, n, data) \
template<typename Sys, typename Derived, typename Sig> \
template < \
typename S \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
> \
void Object<Sys, Derived, Sig>::emitSignal( \
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
) \
{ \
typedef typename mpl::find<sig_name, S>::type iterator; \
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance; \
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type; \
list_type& list = fusion::at<distance>(m_signals); \
for (typename list_type::iterator it=list.begin(); it != list.end(); it++) \
(*it)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
};
namespace dcm {
//few standart signal names
struct remove {};
struct recalculated {};
typedef boost::any Connection;
/**
* @brief Base class for all object types
*
* This class add's property and signal capabilitys to all deriving classes. For properties it is tigthly
* integrated with the system class: It searches systems property list for the derived class as specified by
* the second template parameter and makes it accessible via appopriate functions. Signals are speciefied by a
* mpl::map with signal name type as key and a boost::function as values.
*
* \tparam Sys class of type System of which the properties are taken
* \tparam Obj the type of the derived object
* \tparam Sig a mpl::map specifing the object's signals by (type - boost::function) pairs
**/
template<typename Sys, typename Derived, typename Sig>
struct Object : public boost::enable_shared_from_this<Derived> {
Object() {};
Object(Sys& system);
/**
* @brief Create a new object of the same type with the same values
*
* Returns a new shared_ptr for the Drived type with the same properties as the initial one. If
* the new pointer should be used in a new system the parameter \param newSys needs to be that
* new system. Overload this function if you have datamembers in any derived class wich are not
* copyconstructable.
* @tparam Prop property type which should be accessed
* @return Prop::type& a reference to the properties actual value.
**/
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
/**
* @brief Access properties
*
* Returns a reference to the propertys actual value. The property type has to be registerd to the
* System type which was given as template parameter to this object.
* @tparam Prop property type which should be accessed
* @return Prop::type& a reference to the properties actual value.
**/
template<typename Prop>
typename Prop::type& getProperty();
/**
* @brief Set properties
*
* Set'S the value of a specified property. The property type has to be registerd to the
* System type which was given as template parameter to this object. Note that setProperty(value)
* is equivalent to getProperty() = value.
* @tparam Prop property type which should be setProperty
* @param value value of type Prop::type which should be set in this object
**/
template<typename Prop>
void setProperty(typename Prop::type value);
/**
* @brief Connects a slot to a specified signal.
*
* Slots are boost::functions which get called when the signal is emitted. Any valid boost::function
* which ressembles the signal tyes signature can be registert. It is important that the signal type
* was registerd to this object on creation by the appropriate template parameter.
*
* @tparam S the signal which should be intercepted
* @param function boost::function which resembles the signal type's signature
* @return void
**/
template<typename S>
Connection connectSignal(typename mpl::at<Sig, S>::type function);
/**
* @brief Disconnects a slot for a specific signal.
*
* Disconnects a slot so that it dosn't get called at signal emittion. It's important to
* disconnect the slot by the same boost:function it was connected with.
*
* @tparam S the signal type of interest
* @param function boost::function with which the slot was connected
* @return void
**/
template<typename S>
void disconnectSignal(Connection c);
/*properties
* search the property map of the system class and get the mpl::vector of properties for the
* derived type. It's imortant to not store the properties but their types. These types are
* stored and accessed as fusion vector.
* */
typedef typename mpl::at<typename Sys::object_properties, Derived>::type Mapped;
typedef typename mpl::if_< boost::is_same<Mapped, mpl::void_ >, mpl::vector0<>, Mapped>::type Sequence;
typedef typename details::pts<Sequence>::type Properties;
Properties m_properties;
Sys* m_system;
protected:
/*signal handling
* extract all signal types to allow index search (inex search on signal functions would fail as same
* signatures are supported for multiple signals). Create std::vectors to allow multiple slots per signal
* and store these vectors in a fusion::vector for easy access.
* */
typedef typename mpl::fold< Sig, mpl::vector<>,
mpl::push_back<mpl::_1, mpl::key_type<Sig, mpl::_2> > >::type sig_name;
typedef typename mpl::fold< Sig, mpl::vector<>,
mpl::push_back<mpl::_1, mpl::value_type<Sig, mpl::_2> > >::type sig_functions;
typedef typename mpl::fold< sig_functions, mpl::vector<>,
mpl::push_back<mpl::_1, std::list<mpl::_2> > >::type sig_vectors;
typedef typename fusion::result_of::as_vector<sig_vectors>::type Signals;
Signals m_signals;
public:
//with no vararg templates before c++11 we need preprocessor to create the overloads of emit signal we need
BOOST_PP_REPEAT(5, EMIT_CALL_DEF, ~)
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys, typename Derived, typename Sig>
Object<Sys, Derived, Sig>::Object(Sys& system) : m_system(&system) {};
template<typename Sys, typename Derived, typename Sig>
boost::shared_ptr<Derived> Object<Sys, Derived, Sig>::clone(Sys& newSys) {
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
np->m_system = &newSys;
return np;
};
template<typename Sys, typename Derived, typename Sig>
template<typename Prop>
typename Prop::type& Object<Sys, Derived, Sig>::getProperty() {
typedef typename mpl::find<Sequence, Prop>::type iterator;
typedef typename mpl::distance<typename mpl::begin<Sequence>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<Sequence>::type > >));
return fusion::at<distance>(m_properties);
};
template<typename Sys, typename Derived, typename Sig>
template<typename Prop>
void Object<Sys, Derived, Sig>::setProperty(typename Prop::type value) {
typedef typename mpl::find<Sequence, Prop>::type iterator;
typedef typename mpl::distance<typename mpl::begin<Sequence>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<Sequence>::type > >));
fusion::at<distance>(m_properties) = value;
};
template<typename Sys, typename Derived, typename Sig>
template<typename S>
Connection Object<Sys, Derived, Sig>::connectSignal(typename mpl::at<Sig, S>::type function) {
typedef typename mpl::find<sig_name, S>::type iterator;
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type;
list_type& list = fusion::at<distance>(m_signals);
return list.insert(list.begin(),function);
};
template<typename Sys, typename Derived, typename Sig>
template<typename S>
void Object<Sys, Derived, Sig>::disconnectSignal(Connection c) {
typedef typename mpl::find<sig_name, S>::type iterator;
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type;
list_type& list = fusion::at<distance>(m_signals);
list.erase(boost::any_cast<typename list_type::iterator>(c));
};
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
}
#endif //GCM_OBJECT_H

View File

@ -0,0 +1,167 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_PROPERTY_H
#define GCM_PROPERTY_H
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/buffer_concepts.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/property_map/property_map.hpp>
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
struct vertex_property {};
struct edge_property {};
struct cluster_property {};
struct object_property {};
namespace details {
template<typename Graph>
struct vertex_selector {
typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
typedef typename Graph::vertex_properties sequence_type;
};
template<typename Graph>
struct edge_selector {
typedef typename boost::graph_traits<Graph>::edge_descriptor key_type;
typedef typename Graph::edge_properties sequence_type;
};
template< typename Kind, typename Graph>
struct property_selector : public mpl::if_<boost::is_same<Kind, vertex_property>,
vertex_selector<Graph>, edge_selector<Graph> >::type {};
template<typename T>
struct property_type {
typedef typename T::type type;
};
template<typename T>
struct property_kind {
typedef typename T::kind type;
};
//property vector to a fusion sequence of the propety types
template<typename T>
struct pts { //property type sequence
typedef typename mpl::transform<T, details::property_type<mpl::_1> >::type ptv;
typedef typename fusion::result_of::as_vector< ptv >::type type;
};
}
template<typename T>
struct is_edge_property : boost::is_same<typename T::kind,edge_property> {};
template<typename T>
struct is_vertex_property : boost::is_same<typename T::kind,vertex_property> {};
template<typename T>
struct is_cluster_property : boost::is_same<typename T::kind,cluster_property> {};
template<typename T>
struct is_object_property : boost::is_same<typename T::kind,object_property> {};
template <typename Property, typename Graph>
class property_map {
public:
typedef typename dcm::details::property_selector<typename Property::kind, Graph>::key_type key_type;
typedef typename Property::type value_type;
typedef typename Property::type& reference;
typedef boost::lvalue_property_map_tag category;
typedef Property property;
typedef typename dcm::details::property_selector<typename Property::kind, Graph>::sequence_type sequence;
property_map(Graph& g)
: m_graph(g) { }
Graph& m_graph;
};
template<typename P, typename G>
typename property_map<P,G>::value_type get(const property_map<P,G>& map,
typename property_map<P,G>::key_type key) {
typedef property_map<P,G> map_t;
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
return fusion::at<distance>(fusion::at_c<0>(map.m_graph[key]));
};
template <typename P, typename G>
void put(const property_map<P,G>& map,
typename property_map<P,G>::key_type key,
const typename property_map<P,G>::value_type& value) {
typedef property_map<P,G> map_t;
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
fusion::at<distance>(fusion::at_c<0>(map.m_graph[key])) = value;
};
template <typename P, typename G>
typename property_map<P,G>::reference at(const property_map<P,G>& map,
typename property_map<P,G>::key_type key) {
typedef property_map<P,G> map_t;
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
return fusion::at<distance>(fusion::at_c<0>(map.m_graph[key]));
}
//now create some standart properties
//***********************************
struct empty_prop {
typedef int kind;
typedef int type;
};
struct type_prop {
//states the type of a cluster
typedef cluster_property kind;
typedef int type;
};
struct changed_prop {
typedef cluster_property kind;
typedef bool type;
};
template<typename T>
struct id_prop {
typedef object_property kind;
typedef T type;
};
}
#endif //GCM_PROPERTY_H

View File

@ -0,0 +1,100 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_SHEDULER_H
#define GCM_SHEDULER_H
#include <set>
#include <algorithm>
namespace dcm {
template<typename Sys>
struct Job {
virtual ~Job() {};
virtual void execute(Sys& sys) = 0;
bool operator<(const Job<Sys>& j) const {
return priority < j.priority;
};
int priority;
};
template<typename functor, typename System, int prior>
struct FunctorJob : Job<System> {
FunctorJob(functor f) : m_functor(f) {
Job<System>::priority = prior;
};
virtual void execute(System& sys) {
m_functor(sys);
};
functor m_functor;
};
template<typename Sys>
class Sheduler {
public:
Sheduler() {};
~Sheduler() {
std::for_each(m_preprocess.begin(), m_preprocess.end(), Deleter());
std::for_each(m_process.begin(), m_process.end(), Deleter());
std::for_each(m_postprocess.begin(), m_postprocess.end(), Deleter());
};
void addPreprocessJob(Job<Sys>* j) {
m_preprocess.insert(j);
};
void addPostprocessJob(Job<Sys>* j) {
m_postprocess.insert(j);
};
void addProcessJob(Job<Sys>* j) {
m_process.insert(j);
};
void execute(Sys& system) {
std::for_each(m_preprocess.begin(), m_preprocess.end(), Executer(system));
std::for_each(m_process.begin(), m_process.end(), Executer(system));
std::for_each(m_postprocess.begin(), m_postprocess.end(), Executer(system));
};
protected:
struct Executer {
Executer(Sys& s) : m_system(s) {};
void operator()(Job<Sys>* j) {
j->execute(m_system);
};
Sys& m_system;
};
struct Deleter {
void operator()(Job<Sys>* j) {
delete j;
};
};
std::set< Job<Sys>* > m_preprocess, m_process, m_postprocess;
};
}
#endif //GCM_SHEDULER_H

View File

@ -0,0 +1,327 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_SYSTEM_H
#define GCM_SYSTEM_H
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector/vector0.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/count.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/less_equal.hpp>
#include <boost/mpl/print.hpp>
#include <boost/mpl/and.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include "property.hpp"
#include "clustergraph.hpp"
#include "sheduler.hpp"
#include "logging.hpp"
#include "traits.hpp"
namespace mpl = boost::mpl;
namespace dcm {
struct No_Identifier {};
struct Unspecified_Identifier {};
namespace details {
enum { subcluster = 10};
template<typename seq, typename state>
struct vector_fold : mpl::fold< seq, state,
mpl::push_back<mpl::_1,mpl::_2> > {};
template<typename seq, typename state>
struct edge_fold : mpl::fold< seq, state,
mpl::if_< is_edge_property<mpl::_2>,
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
template<typename seq, typename state>
struct vertex_fold : mpl::fold< seq, state,
mpl::if_< is_vertex_property<mpl::_2>,
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
template<typename seq, typename state>
struct cluster_fold : mpl::fold< seq, state,
mpl::if_< is_cluster_property<mpl::_2>,
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
template<typename seq, typename state, typename obj>
struct obj_fold : mpl::fold< seq, state,
mpl::if_< mpl::or_<
boost::is_same< details::property_kind<mpl::_2>, obj>, is_object_property<mpl::_2> >,
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
template<typename objects, typename properties>
struct property_map {
typedef typename mpl::fold<
objects, mpl::map<>, mpl::insert< mpl::_1, mpl::pair<
mpl::_2, details::obj_fold<properties, mpl::vector<>, mpl::_2 > > > >::type type;
};
template<typename T>
struct get_identifier {
typedef typename T::Identifier type;
};
template<typename seq, typename state>
struct map_fold : mpl::fold< seq, state, mpl::insert<mpl::_1,mpl::_2> > {};
struct nothing {};
template<int v>
struct EmptyModule {
template<typename T>
struct type {
struct inheriter {};
typedef mpl::vector<> properties;
typedef mpl::vector<> objects;
typedef Unspecified_Identifier Identifier;
static void system_init(T& sys) {};
static void system_copy(const T& from, T& into) {};
};
};
template <class T>
struct is_shared_ptr : boost::mpl::false_ {};
template <class T>
struct is_shared_ptr<boost::shared_ptr<T> > : boost::mpl::true_ {};
}
template< typename KernelType,
typename T1 = details::EmptyModule<1>,
typename T2 = details::EmptyModule<2>,
typename T3 = details::EmptyModule<3> >
class System : public T1::template type< System<KernelType,T1,T2,T3> >::inheriter,
public T2::template type< System<KernelType,T1,T2,T3> >::inheriter,
public T3::template type< System<KernelType,T1,T2,T3> >::inheriter {
typedef System<KernelType,T1,T2,T3> BaseType;
public:
typedef typename T1::template type< BaseType > Type1;
typedef typename T2::template type< BaseType > Type2;
typedef typename T3::template type< BaseType > Type3;
typedef mpl::vector3<Type1, Type2, Type3> TypeVector;
//Check if all Identifiers are the same and find out which type it is
typedef typename mpl::fold<TypeVector, mpl::vector<>,
mpl::if_<boost::is_same<details::get_identifier<mpl::_2>, Unspecified_Identifier>,
mpl::_1, mpl::push_back<mpl::_1, details::get_identifier<mpl::_2> > > >::type Identifiers;
BOOST_MPL_ASSERT((mpl::or_<
mpl::less_equal<typename mpl::size<Identifiers>::type, mpl::int_<1> >,
mpl::equal< typename mpl::count<Identifiers,
typename mpl::at_c<Identifiers,0> >::type, typename mpl::size<Identifiers>::type > >));
typedef typename mpl::if_< mpl::empty<Identifiers>,
No_Identifier, typename mpl::at_c<Identifiers, 0>::type >::type Identifier;
public:
//get all module objects and properties
typedef typename details::vector_fold<typename Type3::objects,
typename details::vector_fold<typename Type2::objects,
typename details::vector_fold<typename Type1::objects,
mpl::vector<> >::type >::type>::type objects;
typedef typename details::vector_fold<typename Type3::properties,
typename details::vector_fold<typename Type2::properties,
typename details::vector_fold<typename Type1::properties,
mpl::vector<id_prop<Identifier> > >::type >::type>::type properties;
//make the subcomponent lists of objects and properties
typedef typename details::edge_fold< properties, mpl::vector<> >::type edge_properties;
typedef typename details::vertex_fold< properties, mpl::vector<> >::type vertex_properties;
typedef typename details::cluster_fold< properties,
mpl::vector<changed_prop, type_prop> >::type cluster_properties;
typedef typename details::property_map<objects, properties>::type object_properties;
protected:
//object storage
typedef typename mpl::transform<objects, boost::shared_ptr<mpl::_1> >::type sp_objects;
typedef typename mpl::fold< sp_objects, mpl::vector<>,
mpl::push_back<mpl::_1, std::vector<mpl::_2> > >::type object_vectors;
typedef typename fusion::result_of::as_vector<object_vectors>::type Storage;
template<typename FT1, typename FT2, typename FT3>
friend struct Object;
struct clearer {
template<typename T>
void operator()(T& vector) const {
vector.clear();
};
};
#ifdef USE_LOGGING
boost::shared_ptr< sink_t > sink;
#endif
public:
typedef ClusterGraph<edge_properties, vertex_properties, cluster_properties, objects> Cluster;
typedef Sheduler< BaseType > Shedule;
typedef KernelType Kernel;
public:
System() : m_cluster(new Cluster), m_storage(new Storage)
#ifdef USE_LOGGING
, sink(init_log())
#endif
{
Type1::system_init(*this);
Type2::system_init(*this);
Type3::system_init(*this);
};
~System() {
#ifdef USE_LOGGING
stop_log(sink);
#endif
};
void clear() {
m_cluster->clearClusters();
m_cluster->clear();
fusion::for_each(*m_storage, clearer());
};
template<typename Object>
typename std::vector< boost::shared_ptr<Object> >::iterator begin() {
typedef typename mpl::find<objects, Object>::type iterator;
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
return fusion::at<distance>(*m_storage).begin();
};
template<typename Object>
typename std::vector< boost::shared_ptr<Object> >::iterator end() {
typedef typename mpl::find<objects, Object>::type iterator;
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
return fusion::at<distance>(*m_storage).end();
};
template<typename Object>
std::vector< boost::shared_ptr<Object> >& objectVector() {
typedef typename mpl::find<objects, Object>::type iterator;
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
return fusion::at<distance>(*m_storage);
};
template<typename Object>
void push_back(boost::shared_ptr<Object> ptr) {
objectVector<Object>().push_back(ptr);
};
template<typename Object>
void erase(boost::shared_ptr<Object> ptr) {
std::vector< boost::shared_ptr<Object> >& vec = objectVector<Object>();
vec.erase(std::remove(vec.begin(), vec.end(), ptr), vec.end());
};
void solve() {
clock_t start = clock();
m_sheduler.execute(*this);
clock_t end = clock();
double ms = (double(end-start)* 1000.) / double(CLOCKS_PER_SEC);
//Base::Console().Message("overall solving time in ms: %f\n", ms);
};
System* createSubsystem() {
System* s = new System();
s->m_cluster = m_cluster->createCluster().first;
s->m_storage = m_storage;
s->m_cluster->template setClusterProperty<dcm::type_prop>(details::subcluster);
return s;
};
private:
struct cloner {
System& newSys;
cloner(System& ns) : newSys(ns) {};
template<typename T>
struct test : mpl::and_<details::is_shared_ptr<T>,
mpl::not_<boost::is_same<T, boost::shared_ptr<typename System::Cluster> > > > {};
template<typename T>
typename boost::enable_if< test<T>, void>::type operator()(T& p) const {
p = p->clone(newSys);
newSys.push_back(p);
};
template<typename T>
typename boost::enable_if< mpl::not_<test<T> >, void>::type operator()(const T& p) const {};
};
public:
void copyInto(System& into) const {
//copy the clustergraph and clone all objects while at it. They are also pushed to the storage
cloner cl(into);
m_cluster->copyInto(into.m_cluster, cl);
//notify all modules that they are copied
Type1::system_copy(*this, into);
Type2::system_copy(*this, into);
Type3::system_copy(*this, into);
};
System* clone() const {
System* ns = new System();
this->copyInto(*ns);
return ns;
};
boost::shared_ptr<Cluster> m_cluster;
boost::shared_ptr<Storage> m_storage;
Shedule m_sheduler;
Kernel m_kernel;
};
}
#endif //GCM_SYSTEM_H

View File

@ -0,0 +1,101 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_TRAITS_H
#define GCM_TRAITS_H
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/void.hpp>
#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <string.h>
namespace mpl = boost::mpl;
namespace dcm {
template< typename T >
struct system_traits {
typedef typename T::Kernel Kernel;
typedef typename T::Cluster Cluster;
template<typename M>
struct getModule {
typedef typename mpl::if_< boost::is_base_of<M, typename T::Type1>, typename T::Type1, typename T::Type2 >::type test1;
typedef typename mpl::if_< boost::is_base_of<M, test1>, test1, typename T::Type3 >::type test2;
typedef typename mpl::if_< boost::is_base_of<M, test2>, test2, mpl::void_ >::type type;
typedef boost::is_same<type, mpl::void_> has_module;
};
};
template<typename T>
struct compare_traits {
BOOST_MPL_ASSERT_MSG((mpl::not_<boost::is_same<T, const char*> >::value),
YOU_SHOULD_NOT_USE_THIS_TYPE_AS_IDENTIFIER,
(const char*));
static bool compare(T& first, T& second) {
return first == second;
};
};
template<>
struct compare_traits<std::string> {
static bool compare(std::string& first, std::string& second) {
return !(first.compare(second));
};
};
template<typename seq, int size>
struct vector_shrink {
typedef typename mpl::copy< seq, mpl::back_inserter< mpl::vector<> > >::type type;
};
template<typename seq>
struct vector_shrink< seq, 0 > {
typedef mpl::vector0<> type;
};
template<typename seq>
struct vector_shrink< seq, 1 > {
typedef mpl::vector1< typename mpl::at_c< seq, 0 >::type > type;
};
#define SEQ_TYPES(z, n, data) \
typename mpl::at_c< seq, n >::type
#define VECTOR_SHRINK(z, n, data) \
template< typename seq> \
struct vector_shrink<seq, n> { \
typedef BOOST_PP_CAT(mpl::vector, n) < \
BOOST_PP_ENUM(n, SEQ_TYPES, ~) > type; \
};
BOOST_PP_REPEAT_FROM_TO(2,10, VECTOR_SHRINK, ~)
}//namespace dcm
#endif //GCM_TRAITS_H

View File

@ -0,0 +1,292 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_TRANSFORMATION_H
#define DCM_TRANSFORMATION_H
#include <cmath>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <boost/mpl/if.hpp>
namespace dcm {
namespace detail {
template<typename Scalar, int Dim>
class Transform {
public:
typedef Eigen::Matrix<Scalar, Dim, 1> Vector;
typedef typename boost::mpl::if_c< Dim == 3,
Eigen::Quaternion<Scalar>,
Eigen::Rotation2D<Scalar> >::type Rotation;
typedef Eigen::Translation<Scalar, Dim> Translation;
typedef Eigen::UniformScaling<Scalar> Scaling;
typedef typename Rotation::RotationMatrixType RotationMatrix;
protected:
Rotation m_rotation;
Translation m_translation;
Scaling m_scale;
public:
Transform() : m_rotation(Rotation::Identity()),
m_translation(Translation::Identity()),
m_scale(Scaling(1.)) { };
Transform(const Rotation& r) : m_rotation(r),
m_translation(Translation::Identity()),
m_scale(Scaling(1.)) {
m_rotation.normalize();
};
Transform(const Rotation& r, const Translation& t) : m_rotation(r),
m_translation(t),
m_scale(Scaling(1.)) {
m_rotation.normalize();
};
Transform(const Rotation& r, const Translation& t, const Scaling& s) : m_rotation(r),
m_translation(t),
m_scale(s) {
m_rotation.normalize();
};
//access the single parts and manipulate them
//***********************
const Rotation& rotation() const {
return m_rotation;
}
template<typename Derived>
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
m_rotation = rotation.derived().normalized()*m_rotation;
return *this;
}
const Translation& translation() const {
return m_translation;
}
Transform& translate(const Translation& translation) {
m_translation = m_translation*translation;
return *this;
}
const Scaling& scaling() const {
return m_scale;
}
Transform& scale(const Scalar& scaling) {
m_scale *= Scaling(scaling);
return *this;
}
Transform& scale(const Scaling& scaling) {
m_scale.factor() *= scaling.factor();
return *this;
}
Transform& invert() {
m_rotation = m_rotation.inverse();
m_translation.vector() = (m_rotation*m_translation.vector()) * (-m_scale.factor());
m_scale = Scaling(1./m_scale.factor());
return *this;
};
Transform inverse() {
Transform res(*this);
res.invert();
return res;
};
//operators for value manipulation
//********************************
inline Transform& operator=(const Translation& t) {
m_translation = t;
m_rotation = Rotation::Identity();
m_scale = Scaling(1.);
return *this;
}
inline Transform operator*(const Translation& t) const {
Transform res = *this;
res.translate(t);
return res;
}
inline Transform& operator*=(const Translation& t) {
return translate(t);
}
inline Transform& operator=(const Scaling& s) {
m_scale = s;
m_translation = Translation::Identity();
m_rotation = Rotation::Identity();
return *this;
}
inline Transform operator*(const Scaling& s) const {
Transform res = *this;
res.scale(s);
return res;
}
inline Transform& operator*=(const Scaling& s) {
return scale(s);
}
template<typename Derived>
inline Transform& operator=(const Eigen::RotationBase<Derived,Dim>& r) {
m_rotation = r.derived();
m_rotation.normalize();
m_translation = Translation::Identity();
m_scale = Scaling(1);
return *this;
}
template<typename Derived>
inline Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
Transform res = *this;
res.rotate(r.derived());
return res;
}
template<typename Derived>
inline Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
return rotate(r.derived());
}
inline Transform operator* (const Transform& other) const {
Transform res(*this);
res*= other;
return res;
}
inline Transform& operator*= (const Transform& other) {
rotate(other.rotation());
other.rotate(m_translation.vector());
m_translation.vector() += other.translation().vector()/m_scale.factor();
m_scale.factor() *= other.scaling().factor();
return *this;
}
//transform Vectors
//*****************
template<typename Derived>
inline Derived& rotate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_rotation*vec;
return vec.derived();
}
template<typename Derived>
inline Derived& translate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_translation*vec;
return vec.derived();
}
template<typename Derived>
inline Derived& scale(Eigen::MatrixBase<Derived>& vec) const {
vec*=m_scale.factor();
return vec.derived();
}
template<typename Derived>
inline Derived& transform(Eigen::MatrixBase<Derived>& vec) const {
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
return vec.derived();
}
template<typename Derived>
inline Derived operator*(const Eigen::MatrixBase<Derived>& vec) const {
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
}
template<typename Derived>
inline void operator()(Eigen::MatrixBase<Derived>& vec) const {
transform(vec);
}
//Stuff
//*****
bool isApprox(const Transform& other, Scalar prec) const {
return m_rotation.isApprox(other.rotation(), prec)
&& ((m_translation.vector()- other.translation().vector()).norm() < prec)
&& (std::abs(m_scale.factor()-other.scaling().factor()) < prec);
};
void setIdentity() {
m_rotation.setIdentity();
m_translation = Translation::Identity();
m_scale = Scaling(1.);
}
static const Transform Identity() {
return Transform(Rotation::Identity(), Translation::Identity(), Scaling(1));
}
Transform& normalize() {
m_rotation.normalize();
return *this;
}
};
template<typename Scalar, int Dim>
class DiffTransform : public Transform<Scalar, Dim> {
typedef typename Transform<Scalar, Dim>::Rotation Rotation;
typedef typename Transform<Scalar, Dim>::Translation Translation;
typedef typename Transform<Scalar, Dim>::Scaling Scaling;
typedef Eigen::Matrix<Scalar, Dim, 3*Dim> DiffMatrix;
DiffMatrix m_diffMatrix;
public:
DiffTransform() : Transform<Scalar, Dim>() { };
DiffTransform(const Rotation& r) : Transform<Scalar, Dim>(r) {};
DiffTransform(const Rotation& r, const Translation& t) : Transform<Scalar, Dim>(r,t) {};
DiffTransform(const Rotation& r, const Translation& t, const Scaling& s) : Transform<Scalar, Dim>(r,t,s) {};
DiffTransform(Transform<Scalar, Dim>& trans)
: Transform<Scalar, Dim>(trans.rotation(), trans.translation(), trans.scaling()) {
m_diffMatrix.setZero();
};
const DiffMatrix& differential() {
return m_diffMatrix;
};
inline Scalar& operator()(int f, int s) {
return m_diffMatrix(f,s);
};
inline Scalar& at(int f, int s) {
return m_diffMatrix(f,s);
};
};
}//detail
}//DCM
/*When you overload a binary operator as a member function of a class the overload is used
* when the first operand is of the class type.For stream operators, the first operand
* is the stream and not (usually) the custom class.
*/
template<typename Kernel, int Dim>
std::ostream& operator<<(std::ostream& os, const dcm::detail::Transform<Kernel, Dim>& t) {
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
<< "Translation: " << t.translation().vector().transpose() <<std::endl
<< "Scale: " << t.scaling().factor();
return os;
}
template<typename Kernel, int Dim>
std::ostream& operator<<(std::ostream& os, dcm::detail::DiffTransform<Kernel, Dim>& t) {
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
<< "Translation: " << t.translation().vector().transpose() <<std::endl
<< "Scale: " << t.scaling().factor() << std::endl
<< "Differential:" << std::endl<<t.differential();
return os;
}
#endif //DCM_TRANSFORMATION

View File

@ -0,0 +1,73 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EXTERNALIZE_H
#define DCM_EXTERNALIZE_H
#include <boost/preprocessor/list/for_each.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/list/append.hpp>
#ifdef USE_EXTERNAL
#define DCM_EXTERNAL_INCLUDE_001 <opendcm/moduleState/edge_vertex_generator_imp.hpp>
#define DCM_EXTERNAL_001( System )\
template struct dcm::details::edge_generator<System>; \
template struct dcm::details::vertex_generator<System>; \
#define DCM_EXTERNAL_INCLUDE_002 <opendcm/moduleState/object_generator_imp.hpp>
#define DCM_EXTERNAL_002( System )\
template struct dcm::details::obj_gen<System>; \
#define DCM_EXTERNAL_INCLUDE_003 <opendcm/moduleState/property_generator_imp.hpp>
#define DCM_EXTERNAL_003( System )\
template struct dcm::details::vertex_prop_gen<System>; \
template struct dcm::details::edge_prop_gen<System>; \
template struct dcm::details::cluster_prop_gen<System>;
#define DCM_EXTERNAL_INCLUDE_004 <opendcm/moduleState/generator_imp.hpp>
#define DCM_EXTERNAL_004( System )\
template struct dcm::generator<System>; \
#define DCM_EXTERNAL_INCLUDE_005 <opendcm/moduleState/property_parser_imp.hpp>
#define DCM_EXTERNAL_005( System )\
template struct dcm::details::vertex_prop_par<System>; \
template struct dcm::details::edge_prop_par<System>; \
template struct dcm::details::cluster_prop_par<System>;
#define DCM_EXTERNAL_INCLUDE_006 <opendcm/moduleState/object_parser_imp.hpp>
#define DCM_EXTERNAL_006( System )\
template struct dcm::details::obj_par<System>; \
#define DCM_EXTERNAL_INCLUDE_007 <opendcm/moduleState/edge_vertex_parser_imp.hpp>
#define DCM_EXTERNAL_007( System )\
template struct dcm::details::edge_parser<System>; \
template struct dcm::details::vertex_parser<System>; \
#define DCM_EXTERNAL_INCLUDE_008 <opendcm/moduleState/parser_imp.hpp>
#define DCM_EXTERNAL_008( System )\
template struct dcm::parser<System>; \
#else
#define DCM_EXTERNALIZE( System )
#endif
#endif //DCM_EXTERNALIZE_H

View File

@ -0,0 +1,32 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_MODULE3D_H
#define DCM_MODULE3D_H
#define DCM_USE_MODULE3D
#include "module3d/geometry.hpp"
#include "module3d/distance.hpp"
#include "module3d/parallel.hpp"
#include "module3d/angle.hpp"
#include "module3d/module.hpp"
#endif //DCM_MODULE3D_H

View File

@ -0,0 +1,149 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 detemplate tails.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_ANGLE_HPP
#define GCM_ANGLE_HPP
#include "geometry.hpp"
namespace dcm {
//the calculations( same as we always calculate directions we can outsource the work to this functions)
namespace angle_detail {
template<typename Kernel, typename T>
inline typename Kernel::number_type calc(T d1,
T d2,
typename Kernel::number_type angle) {
return d1.dot(d2) / (d1.norm()*d2.norm()) - angle;
};
template<typename Kernel, typename T>
inline typename Kernel::number_type calcGradFirst(T d1,
T d2,
T dd1) {
typename Kernel::number_type norm = d1.norm()*d2.norm();
return dd1.dot(d2)/norm - (d1.dot(d2) * (d1.dot(dd1)/d1.norm())*d2.norm()) / std::pow(norm,2);
};
template<typename Kernel, typename T>
inline typename Kernel::number_type calcGradSecond(T d1,
T d2,
T dd2) {
typename Kernel::number_type norm = d1.norm()*d2.norm();
return d1.dot(dd2)/norm - (d1.dot(d2) * (d2.dot(dd2)/d2.norm())*d1.norm()) / std::pow(norm,2);
};
template<typename Kernel, typename T>
inline void calcGradFirstComp(T d1,
T d2,
T grad) {
typename Kernel::number_type norm = d1.norm()*d2.norm();
grad = d2/norm - (d1.dot(d2)/std::pow(norm,2))*d1/d1.norm();
};
template<typename Kernel, typename T>
inline void calcGradSecondComp(T d1,
T d2,
T grad) {
typename Kernel::number_type norm = d1.norm()*d2.norm();
grad = d1/norm - (d1.dot(d2)/std::pow(norm,2))*d2/d2.norm();
};
}
/*
template< typename Kernel, typename Tag1, typename Tag2 >
struct Angle3D {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
Scalar m_angle;
Angle3D(Scalar d = 0.) : m_angle(std::cos(d)) {};
//template definition
void setScale(Scalar scale){
assert(false);
};
Scalar calculate(Vector& param1, Vector& param2) {
assert(false);
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
assert(false);
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
assert(false);
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
assert(false);
};
};
template< typename Kernel >
struct Angle3D< Kernel, tag::line3D, tag::line3D > {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
Scalar m_angle;
Angle3D(Scalar d = 0.) : m_angle(std::cos(d)) {};
Scalar getEquationScaling(typename Kernel::Vector& local1, typename Kernel::Vector& local2) {
return 1.;
}
//template definition
Scalar calculate(Vector& param1, Vector& param2) {
return angle::calc<Kernel>(param1.template tail<3>(), param2.template tail<3>(), m_angle);
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
return angle::calcGradFirst<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam1.template tail<3>());
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
return angle::calcGradSecond<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam2.template tail<3>());
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
angle::calcGradFirstComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>());
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
angle::calcGradSecondComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>());
};
};
//planes like lines have the direction as segment 3-5, so we can use the same implementations
template< typename Kernel >
struct Angle3D< Kernel, tag::plane3D, tag::plane3D > : public Angle3D<Kernel, tag::line3D, tag::line3D> {};
template< typename Kernel >
struct Angle3D< Kernel, tag::line3D, tag::plane3D > : public Angle3D<Kernel, tag::line3D, tag::line3D> {};
*/
}
#endif //GCM_ANGLE_HPP

View File

@ -0,0 +1,770 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_CLUSTERMATH_H
#define GCM_CLUSTERMATH_H
#include <vector>
#include <cmath>
#include <Eigen/StdVector>
#include <boost/noncopyable.hpp>
#include <opendcm/core/logging.hpp>
#include "defines.hpp"
#define MAXFAKTOR 1.2 //the maximal distance allowd by a point normed to the cluster size
#define MINFAKTOR 0.8 //the minimal distance allowd by a point normed to the cluster size
#define SKALEFAKTOR 1. //the faktor by which the biggest size is multiplied to get the scale value
#define NQFAKTOR 0.5 //the faktor by which the norm quaternion is multiplied with to get the RealScalar
//norm quaternion to generate the unit quaternion
namespace dcm {
namespace details {
enum Scalemode {
one,
two,
three,
multiple_inrange,
multiple_outrange
};
template<typename Sys>
struct ClusterMath {
public:
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
typedef typename module3d::Geometry3D Geometry3D;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef typename module3d::math_prop math_prop;
typedef typename module3d::fix_prop fix_prop;
typedef typename Kernel::number_type Scalar;
typename Kernel::Transform3D m_transform, m_ssrTransform, m_resetTransform;
typename Kernel::DiffTransform3D m_diffTrans;
typename Kernel::Vector3Map m_normQ;
typename Kernel::Quaternion m_resetQuaternion;
int m_offset;
bool init, fix;
std::vector<Geom> m_geometry;
typename Kernel::Vector3Map m_translation;
//shift scale stuff
typename Kernel::Vector3 midpoint, m_shift, scale_dir, maxm, minm, max, fixtrans;
Scalemode mode;
Scalar m_scale;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
Vec m_points, m_pseudo;
#ifdef USE_LOGGING
src::logger log;
#endif
public:
ClusterMath();
void setParameterOffset(int offset);
int getParameterOffset();
typename Kernel::Vector3Map& getNormQuaternionMap();
typename Kernel::Vector3Map& getTranslationMap();
void initMaps();
void initFixMaps();
typename Kernel::Transform3D& getTransform();
void mapsToTransform(typename Kernel::Transform3D& trans);
void transformToMaps(typename Kernel::Transform3D& trans);
void finishCalculation();
void finishFixCalculation();
void resetClusterRotation(typename Kernel::Transform3D& trans);
void calcDiffTransform(typename Kernel::DiffTransform3D& trans);
void recalculate();
void addGeometry(Geom g);
void clearGeometry();
std::vector<Geom>& getGeometry();
struct map_downstream {
details::ClusterMath<Sys>& m_clusterMath;
typename Kernel::Transform3D m_transform;
bool m_isFixed;
map_downstream(details::ClusterMath<Sys>& cm, bool fix);
void operator()(Geom g);
void operator()(boost::shared_ptr<Cluster> c);
};
void mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster);
//Calculate the scale of the cluster. Therefore the midpoint is calculated and the scale is
// defined as the max distance between the midpoint and the points.
Scalar calculateClusterScale();
void applyClusterScale(Scalar scale, bool isFixed);
private:
Scalar calcOnePoint(const typename Kernel::Vector3& p);
Scalar calcTwoPoints(const typename Kernel::Vector3& p1, const typename Kernel::Vector3& p2);
Scalar calcThreePoints(const typename Kernel::Vector3& p1,
const typename Kernel::Vector3& p2, const typename Kernel::Vector3& p3);
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys>
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
m_resetTransform = typename Kernel::Quaternion(1,1,1,1);
m_shift.setZero();
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Clustermath3D"));
#endif
};
template<typename Sys>
void ClusterMath<Sys>::setParameterOffset(int offset) {
m_offset = offset;
};
template<typename Sys>
int ClusterMath<Sys>::getParameterOffset() {
return m_offset;
};
template<typename Sys>
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getNormQuaternionMap() {
return m_normQ;
};
template<typename Sys>
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getTranslationMap() {
return m_translation;
};
template<typename Sys>
void ClusterMath<Sys>::initMaps() {
transformToMaps(m_transform);
init = true;
midpoint.setZero();
m_shift.setZero();
m_ssrTransform.setIdentity();
m_diffTrans = m_transform;
fix=false;
#ifdef USE_LOGGING
BOOST_LOG(log) << "Init transform: "<<m_transform;
#endif
};
template<typename Sys>
void ClusterMath<Sys>::initFixMaps() {
//when fixed no maps exist
new(&m_translation) typename Kernel::Vector3Map(&fixtrans(0));
m_translation = m_transform.translation().vector();
init = true;
midpoint.setZero();
m_shift.setZero();
m_ssrTransform.setIdentity();
m_diffTrans = m_transform;
fix=true;
#ifdef USE_LOGGING
BOOST_LOG(log) << "Init fix transform: "<<m_transform;
#endif
};
template<typename Sys>
typename ClusterMath<Sys>::Kernel::Transform3D& ClusterMath<Sys>::getTransform() {
return m_transform;
};
template<typename Sys>
void ClusterMath<Sys>::mapsToTransform(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
//add scale only after possible reset
typename Kernel::Transform3D::Scaling scale(m_transform.scaling());
trans = m_diffTrans;
trans *= scale;
};
template<typename Sys>
void ClusterMath<Sys>::transformToMaps(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
const typename Kernel::Quaternion& m_quaternion = trans.rotation();
if(m_quaternion.w() < 1.) {
Scalar s = std::acos(m_quaternion.w())/std::sin(std::acos(m_quaternion.w()));
m_normQ = m_quaternion.vec()*s;
m_normQ /= NQFAKTOR;
} else {
m_normQ.setZero();
}
m_translation = trans.translation().vector();
};
template<typename Sys>
void ClusterMath<Sys>::finishCalculation() {
mapsToTransform(m_transform);
init=false;
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish calculation";
#endif
m_transform = m_ssrTransform*m_transform;
//scale all geometries back to the original size
m_diffTrans *= typename Kernel::Transform3D::Scaling(1./m_ssrTransform.scaling().factor());
typedef typename std::vector<Geom>::iterator iter;
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
(*it)->recalculate(m_diffTrans);
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish transform:"<<std::endl<<m_transform;
#endif
};
template<typename Sys>
void ClusterMath<Sys>::finishFixCalculation() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish fix calculation";
#endif
typedef typename std::vector<Geom>::iterator iter;
m_transform *= m_ssrTransform.inverse();
typename Kernel::DiffTransform3D diff(m_transform);
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
(*it)->recalculate(diff);
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish fix transform:"<<std::endl<<m_transform;
#endif
};
template<typename Sys>
void ClusterMath<Sys>::resetClusterRotation(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Reset cluster rotation:"<<std::endl<<m_diffTrans;
#endif
trans = m_resetTransform.inverse()*trans;
m_ssrTransform *= m_resetTransform;
m_transform = m_resetTransform.inverse()*m_transform;
//apply the needed transformation to all geometries local values
typedef typename std::vector<Geom>::iterator iter;
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
(*it)->transform(m_resetTransform);
};
};
template<typename Sys>
void ClusterMath<Sys>::calcDiffTransform(typename ClusterMath<Sys>::Kernel::DiffTransform3D& trans) {
Scalar norm = m_normQ.norm();
trans.setIdentity();
if(norm < 0.1) {
if(norm == 0) {
trans *= typename Kernel::Transform3D::Translation(m_translation);
resetClusterRotation(trans);
} else {
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac,m_normQ(2)*fac);
trans *= typename Kernel::Transform3D::Translation(m_translation);
resetClusterRotation(trans);
}
transformToMaps(trans);
return;
}
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac, m_normQ(2)*fac);
trans *= typename Kernel::Transform3D::Translation(m_translation);
};
template<typename Sys>
void ClusterMath<Sys>::recalculate() {
calcDiffTransform(m_diffTrans);
const typename Kernel::Quaternion Q = m_diffTrans.rotation();
// now calculate the gradient quaternions and calculate the diff rotation matrices
// m_normQ = (a,b,c)
// n = ||m_normQ||
//
// Q = (a/n sin(n), b/n sin(n), c/n sin(n), cos(n))
//
//n=||m_normQ||, sn = sin(n)/n, sn3 = sin(n)/n^3, cn = cos(n)/n, divn = 1/n;
const Scalar n = m_normQ.norm();
const Scalar sn = std::sin(NQFAKTOR*n)/n;
const Scalar mul = (NQFAKTOR*std::cos(NQFAKTOR*n)-sn)/std::pow(n,2);
//dxa = dQx/da
const Scalar dxa = sn + std::pow(m_normQ(0),2)*mul;
const Scalar dxb = m_normQ(0)*m_normQ(1)*mul;
const Scalar dxc = m_normQ(0)*m_normQ(2)*mul;
const Scalar dya = m_normQ(1)*m_normQ(0)*mul;
const Scalar dyb = sn + std::pow(m_normQ(1),2)*mul;
const Scalar dyc = m_normQ(1)*m_normQ(2)*mul;
const Scalar dza = m_normQ(2)*m_normQ(0)*mul;
const Scalar dzb = m_normQ(2)*m_normQ(1)*mul;
const Scalar dzc = sn + std::pow(m_normQ(2),2)*mul;
const Scalar dwa = -sn*NQFAKTOR*m_normQ(0);
const Scalar dwb = -sn*NQFAKTOR*m_normQ(1);
const Scalar dwc = -sn*NQFAKTOR*m_normQ(2);
//write in the diffrot matrix, starting with dQ/dx
m_diffTrans.at(0,0) = -4.0*(Q.y()*dya+Q.z()*dza);
m_diffTrans.at(0,1) = -2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
m_diffTrans.at(0,2) = 2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
m_diffTrans.at(1,0) = 2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
m_diffTrans.at(1,1) = -4.0*(Q.x()*dxa+Q.z()*dza);
m_diffTrans.at(1,2) = -2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
m_diffTrans.at(2,0) = -2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
m_diffTrans.at(2,1) = 2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
m_diffTrans.at(2,2) = -4.0*(Q.x()*dxa+Q.y()*dya);
//dQ/dy
m_diffTrans.at(0,3) = -4.0*(Q.y()*dyb+Q.z()*dzb);
m_diffTrans.at(0,4) = -2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
m_diffTrans.at(0,5) = 2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
m_diffTrans.at(1,3) = 2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
m_diffTrans.at(1,4) = -4.0*(Q.x()*dxb+Q.z()*dzb);
m_diffTrans.at(1,5) = -2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
m_diffTrans.at(2,3) = -2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
m_diffTrans.at(2,4) = 2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
m_diffTrans.at(2,5) = -4.0*(Q.x()*dxb+Q.y()*dyb);
//dQ/dz
m_diffTrans.at(0,6) = -4.0*(Q.y()*dyc+Q.z()*dzc);
m_diffTrans.at(0,7) = -2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
m_diffTrans.at(0,8) = 2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
m_diffTrans.at(1,6) = 2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
m_diffTrans.at(1,7) = -4.0*(Q.x()*dxc+Q.z()*dzc);
m_diffTrans.at(1,8) = -2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
m_diffTrans.at(2,6) = -2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
m_diffTrans.at(2,7) = 2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
m_diffTrans.at(2,8) = -4.0*(Q.x()*dxc+Q.y()*dyc);
//recalculate all geometries
typedef typename std::vector<Geom>::iterator iter;
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
(*it)->recalculate(m_diffTrans);
};
template<typename Sys>
void ClusterMath<Sys>::addGeometry(Geom g) {
m_geometry.push_back(g);
};
template<typename Sys>
void ClusterMath<Sys>::clearGeometry() {
m_geometry.clear();
};
template<typename Sys>
std::vector<typename ClusterMath<Sys>::Geom>& ClusterMath<Sys>::getGeometry() {
return m_geometry;
};
template<typename Sys>
ClusterMath<Sys>::map_downstream::map_downstream(details::ClusterMath<Sys>& cm, bool fix)
: m_clusterMath(cm), m_isFixed(fix) {
m_transform = m_clusterMath.getTransform();
};
template<typename Sys>
void ClusterMath<Sys>::map_downstream::operator()(Geom g) {
//allow iteration over all maped geometries
m_clusterMath.addGeometry(g);
//set the offsets so that geometry knows where it is in the parameter map
g->m_offset = m_clusterMath.getParameterOffset();
//position and offset of the parameters must be set to the clusters values
g->setClusterMode(true, m_isFixed);
//calculate the appropriate local values
typename Kernel::Transform3D trans = m_transform.inverse();
g->transform(trans);
};
template<typename Sys>
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
m_transform *= c->template getClusterProperty<math_prop>().getTransform();
};
template<typename Sys>
void ClusterMath<Sys>::mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster) {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Map downstream geometry";
#endif
map_downstream down(cluster->template getClusterProperty<math_prop>(),
cluster->template getClusterProperty<fix_prop>());
cluster->template for_each<Geometry3D>(down, true);
//TODO: if one subcluster is fixed the hole cluster should be too, as there are no
// dof's remaining between parts and so nothing can be moved when one part is fixed.
};
template<typename Sys>
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calculateClusterScale() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Calculate cluster scale with transform scale: "<<m_transform.scaling().factor();
#endif
//ensure the usage of the right transformation
if(!fix)
mapsToTransform(m_transform);
#ifdef USE_LOGGING
BOOST_LOG(log) << "Calculate cluster scale sec transform scale: "<<m_transform.scaling().factor();
#endif
//collect all points together
m_points.clear();
typename Kernel::Transform3D trans(m_transform.rotation(), m_transform.translation());
trans.invert();
typedef typename Vec::iterator iter;
for(iter it = m_pseudo.begin(); it != m_pseudo.end(); it++) {
m_points.push_back(trans*(*it));
}
typedef typename std::vector<Geom>::iterator g_iter;
for(g_iter it = m_geometry.begin(); it != m_geometry.end(); it++)
m_points.push_back((*it)->getPoint());
//start scale calculation
if(m_points.empty()) assert(false); //TODO: Throw
else if(m_points.size() == 1) {
const typename Kernel::Vector3 p = m_points[0];
return calcOnePoint(p);
} else if(m_points.size() == 2) {
const typename Kernel::Vector3 p1 = m_points[0];
const typename Kernel::Vector3 p2 = m_points[1];
if(Kernel::isSame((p1-p2).norm(), 0.))
return calcOnePoint(p1);
return calcTwoPoints(p1, p2);
} else if(m_points.size() == 3) {
const typename Kernel::Vector3 p1 = m_points[0];
const typename Kernel::Vector3 p2 = m_points[1];
const typename Kernel::Vector3 p3 = m_points[2];
const typename Kernel::Vector3 d = p2-p1;
const typename Kernel::Vector3 e = p3-p1;
if(Kernel::isSame(d.norm(), 0.)) {
if(Kernel::isSame(e.norm(), 0.))
return calcOnePoint(p1);
return calcTwoPoints(p1, p3);
} else if(Kernel::isSame(e.norm(), 0.)) {
return calcTwoPoints(p1, p2);
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0.) &&
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0.)) {
return calcThreePoints(p1, p2, p3);
}
//three points on a line need to be treaded as multiple points
}
//more than 3 points dont have a exakt solution. we search for a midpoint from which all points
//are at least MAXFAKTOR*scale away, but not closer than MINFAKTOR*scale
//get the bonding box to get the center of points
Scalar xmin=1e10, xmax=1e-10, ymin=1e10, ymax=1e-10, zmin=1e10, zmax=1e-10;
for(iter it = m_points.begin(); it != m_points.end(); it++) {
typename Kernel::Vector3 v = (*it);
xmin = (v(0)<xmin) ? v(0) : xmin;
xmax = (v(0)<xmax) ? xmax : v(0);
ymin = (v(1)<ymin) ? v(1) : ymin;
ymax = (v(1)<ymax) ? ymax : v(1);
zmin = (v(2)<zmin) ? v(2) : zmin;
zmax = (v(2)<zmax) ? zmax : v(2);
};
//now calculate the midpoint
midpoint << xmin+xmax, ymin+ymax, zmin+zmax;
midpoint /= 2.;
//get the scale direction an the resulting nearest point indexes
double xh = xmax-xmin;
double yh = ymax-ymin;
double zh = zmax-zmin;
int i1, i2, i3;
if((xh<=yh) && (xh<=zh)) {
i1=1;
i2=2;
i3=0;
} else if((yh<xh) && (yh<zh)) {
i1=0;
i2=2;
i3=1;
} else {
i1=0;
i2=1;
i3=2;
}
scale_dir.setZero();
scale_dir(i3) = 1;
max = Eigen::Vector3d(xmin,ymin,zmin);
m_scale = (midpoint-max).norm()/MAXFAKTOR;
mode = multiple_inrange;
maxm = max-midpoint;
Scalar minscale = 1e10;
//get the closest point
for(iter it = m_points.begin(); it != m_points.end(); it++) {
const Eigen::Vector3d point = (*it)-midpoint;
if(point.norm()<MINFAKTOR*m_scale) {
const double h = std::abs(point(i3)-maxm(i3));
const double k = std::pow(MINFAKTOR/MAXFAKTOR,2);
double q = std::pow(point(i1),2) + std::pow(point(i2),2);
q -= (std::pow(maxm(i1),2) + std::pow(maxm(i2),2) + std::pow(h,2))*k;
q /= 1.-k;
const double p = h*k/(1.-k);
if(std::pow(p,2)<q) assert(false);
midpoint(i3) += p + std::sqrt(std::pow(p,2)-q);
maxm = max-midpoint;
m_scale = maxm.norm()/MAXFAKTOR;
mode = multiple_outrange;
minm = (*it)-midpoint;
it = m_points.begin();
} else if(point.norm()<minscale) {
minscale = point.norm();
}
}
if(mode==multiple_inrange) {
//we are in the range, let's get the perfect balanced scale value
m_scale = (minscale+maxm.norm())/2.;
}
return m_scale;
};
template<typename Sys>
void ClusterMath<Sys>::applyClusterScale(Scalar scale, bool isFixed) {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Apply cluster scale: "<<scale;
BOOST_LOG(log) << "initial transform scale: "<<m_transform.scaling().factor();
#endif
//ensure the usage of the right transform
if(!fix)
mapsToTransform(m_transform);
//when fixed, the geometries never get recalculated. therefore we have to do a calculate now
//to alow the adoption of the scale. and no shift should been set.
if(isFixed) {
m_transform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
m_ssrTransform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
typename Kernel::DiffTransform3D diff(m_transform);
//now calculate the scaled geometrys
typedef typename std::vector<Geom>::iterator iter;
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
(*it)->recalculate(diff);
#ifdef USE_LOGGING
BOOST_LOG(log) << "Fixed cluster geometry value:" << (*it)->m_rotated.transpose();
#endif
};
return;
}
//if this is our scale then just applie the midpoint as shift
if(Kernel::isSame(scale, m_scale)) {
}
//if only one point exists we extend the origin-point-line to match the scale
else if(mode==details::one) {
if(Kernel::isSame(midpoint.norm(),0))
midpoint << scale, 0, 0;
else midpoint += scale*scale_dir;
}
//two and three points form a rectangular triangle, so same procedure
else if(mode==details::two || mode==details::three) {
midpoint+= scale_dir*std::sqrt(std::pow(scale,2) - std::pow(m_scale,2));
}
//multiple points
else if(mode==details::multiple_outrange) {
if(scale_dir(0)) {
Scalar d = std::pow(maxm(1),2) + std::pow(maxm(2),2);
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
midpoint(0) += maxm(0) + h;
} else if(scale_dir(1)) {
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(2),2);
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
midpoint(1) += maxm(1) + h;
} else {
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(1),2);
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
midpoint(2) += maxm(2) + h;
}
} else {
//TODO: it's possible that for this case we get too far away from the outer points.
// The m_scale for "midpoint outside the bounding box" may be bigger than the
// scale to applie, so it results in an error.
//get the closest point
typedef typename Vec::iterator iter;
for(iter it = m_points.begin(); it != m_points.end(); it++) {
const Eigen::Vector3d point = (*it)-midpoint;
if(point.norm()<MINFAKTOR*scale) {
if(scale_dir(0)) {
Scalar d = std::pow(point(1),2) + std::pow(point(2),2);
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
midpoint(0) += point(0) + h;
} else if(scale_dir(1)) {
Scalar d = std::pow(point(0),2) + std::pow(point(2),2);
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
midpoint(1) += point(1) + h;
} else {
Scalar d = std::pow(point(0),2) + std::pow(point(1),2);
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
midpoint(2) += point(2) + h;
}
}
}
}
typename Kernel::Transform3D ssTrans;
ssTrans = typename Kernel::Transform3D::Translation(-midpoint);
ssTrans *= typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
//recalculate all geometries
typedef typename std::vector<Geom>::iterator iter;
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
(*it)->transform(ssTrans);
//set the new rotation and translation
m_transform = ssTrans.inverse()*m_transform;
m_ssrTransform *= ssTrans;
transformToMaps(m_transform);
#ifdef USE_LOGGING
BOOST_LOG(log) << "sstrans scale: "<<ssTrans.scaling().factor();
BOOST_LOG(log) << "finish transform scale: "<<m_transform.scaling().factor();
#endif
};
template<typename Sys>
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcOnePoint(const typename ClusterMath<Sys>::Kernel::Vector3& p) {
//one point can have every scale when moving the midpoint on the origin - point vector
midpoint = p;
scale_dir = -midpoint;
scale_dir.normalize();
mode = details::one;
m_scale = 0.;
return 0.;
};
template<typename Sys>
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcTwoPoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
const typename ClusterMath<Sys>::Kernel::Vector3& p2) {
//two points have their minimal scale at the mid position. Scaling perpendicular to this
//line allows arbitrary scale values. Best is to have the scale dir move towards the origin
//as good as possible.
midpoint = p1+(p2-p1)/2.;
scale_dir = (p2-p1).cross(midpoint);
scale_dir = scale_dir.cross(p2-p1);
if(!Kernel::isSame(scale_dir.norm(),0)) scale_dir.normalize();
else scale_dir(0) = 1;
mode = details::two;
m_scale = (p2-p1).norm()/2.;
return m_scale;
};
template<typename Sys>
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcThreePoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
const typename ClusterMath<Sys>::Kernel::Vector3& p2, const typename ClusterMath<Sys>::Kernel::Vector3& p3) {
//Three points form a triangle with it's minimal scale at the center of it's outer circle.
//Arbitrary scale values can be achieved by moving perpendicular to the triangle plane.
typename Kernel::Vector3 d = p2-p1;
typename Kernel::Vector3 e = p3-p1;
typename Kernel::Vector3 f = p1+0.5*d;
typename Kernel::Vector3 g = p1+0.5*e;
scale_dir = d.cross(e);
typename Kernel::Matrix3 m;
m.row(0) = d.transpose();
m.row(1) = e.transpose();
m.row(2) = scale_dir.transpose();
typename Kernel::Vector3 res(d.transpose()*f, e.transpose()*g, scale_dir.transpose()*p1);
midpoint = m.colPivHouseholderQr().solve(res);
scale_dir.normalize();
mode = details::three;
m_scale = (midpoint-p1).norm();
return m_scale;
};
}//details
}//dcm
#endif //GCM_CLUSTERMATH_H

View File

@ -0,0 +1,33 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_DEFINES_3D_H
#define GCM_DEFINES_3D_H
namespace dcm {
namespace details {
enum { cluster3D = 100};
struct m3d {}; //base of module3d::type to allow other modules check for it
}
}
#endif

View File

@ -0,0 +1,292 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 detemplate tails.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_DISTANCE3D_H
#define GCM_DISTANCE3D_H
#include "geometry.hpp"
#include <opendcm/core/constraint.hpp>
namespace dcm {
template<typename Kernel>
struct Distance::type< Kernel, tag::point3D, tag::point3D > {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
Scalar value, sc_value;
//template definition
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
void setScale(Scalar scale) {
sc_value = value*scale;
};
Scalar calculate(Vector& param1, Vector& param2) {
return (param1-param2).norm() - sc_value;
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
return (param1-param2).dot(dparam1) / (param1-param2).norm();
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
return (param1-param2).dot(-dparam2) / (param1-param2).norm();
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient = (param1-param2) / (param1-param2).norm();
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient = (param2-param1) / (param1-param2).norm();
};
};
template<typename Kernel>
struct Distance::type< Kernel, tag::point3D, tag::plane3D > {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
Scalar value, sc_value;
#ifdef USE_LOGGING
src::logger log;
attrs::mutable_constant< std::string > tag;
type() : tag("Distance point3D plane3D") {
log.add_attribute("Tag", tag);
};
#endif
//template definition
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {
//typename Kernel::Vector3 pp = param1.head(3)- ((param1.head(3)-param2.head(3)).dot(param2.tail(3)) / param2.tail(3).norm()*(param2.tail(3)));
//v2.push_back(pp);
typename Kernel::Vector3 dir = (param1.template head<3>()-param2.template head<3>()).cross(param2.template segment<3>(3));
dir = param2.template segment<3>(3).cross(dir).normalized();
typename Kernel::Vector3 pp = param2.head(3) + (param1.head(3)-param2.head(3)).norm()*dir;
v2.push_back(pp);
#ifdef USE_LOGGING
if(!boost::math::isnormal(pp.norm()))
BOOST_LOG(log) << "Unnormal pseudopoint detected";
#endif
};
void setScale(Scalar scale) {
sc_value = value*scale;
};
Scalar calculate(Vector& param1, Vector& param2) {
//(p1-p2)°n / |n| - distance
const Scalar res = (param1.head(3)-param2.head(3)).dot(param2.tail(3)) / param2.tail(3).norm() - sc_value;
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal residual detected: "<<res;
#endif
return res;
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
//dp1°n / |n|
//if(dparam1.norm()!=1) return 0;
const Scalar res = (dparam1.head(3)).dot(param2.tail(3)) / param2.tail(3).norm();
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal first cluster gradient detected: "<<res;
#endif
return res;
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
const typename Kernel::Vector3 p1 = param1.head(3);
const typename Kernel::Vector3 p2 = param2.head(3);
const typename Kernel::Vector3 dp2 = dparam2.head(3);
const typename Kernel::Vector3 n = param2.tail(3);
const typename Kernel::Vector3 dn = dparam2.tail(3);
//if(dparam2.norm()!=1) return 0;
const Scalar res = (((-dp2).dot(n) + (p1-p2).dot(dn)) / n.norm() - (p1-p2).dot(n)* n.dot(dn)/std::pow(n.norm(),3));
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal second cluster gradient detected: "<<res;
#endif
return res;
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient = param2.tail(3) / param2.tail(3).norm();
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
const typename Kernel::Vector3 p1m2 = param1.head(3) - param2.head(3);
const typename Kernel::Vector3 n = param2.tail(3);
gradient.head(3) = -n / n.norm();
gradient.tail(3) = (p1m2)/n.norm() - (p1m2).dot(n)*n/std::pow(n.norm(),3);
};
};
template<typename Kernel>
struct Distance::type< Kernel, tag::plane3D, tag::plane3D > : public Distance::type< Kernel, tag::point3D, tag::plane3D > {
#ifdef USE_LOGGING
type() : Distance::type< Kernel, tag::point3D, tag::plane3D >() {
Distance::type< Kernel, tag::point3D, tag::plane3D >::tag.set("Distance plane3D plane3D");
};
#endif
typedef typename Kernel::VectorMap Vector;
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,g);
g.segment(3,3).setZero();
};
};
template<typename Kernel>
struct Distance::type< Kernel, tag::point3D, tag::line3D > {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
typedef typename Kernel::Vector3 Vector3;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
Scalar value, sc_value;
Vector3 diff, n, dist;
#ifdef USE_LOGGING
src::logger log;
attrs::mutable_constant< std::string > tag;
type() : tag("Distance point3D line3D") {
log.add_attribute("Tag", tag);
};
#endif
//template definition
void calculatePseudo(typename Kernel::Vector& point, Vec& v1, typename Kernel::Vector& line, Vec& v2) {
Vector3 pp = line.head(3) + (line.head(3)-point.head(3)).norm()*line.segment(3,3);
#ifdef USE_LOGGING
if(!boost::math::isnormal(pp.norm()))
BOOST_LOG(log) << "Unnormal pseudopoint detected";
#endif
v2.push_back(pp);
};
void setScale(Scalar scale) {
sc_value = value*scale;
};
Scalar calculate(Vector& point, Vector& line) {
//diff = point1 - point2
n = line.template segment<3>(3);
diff = line.template head<3>() - point.template head<3>();
dist = diff - diff.dot(n)*n;
const Scalar res = dist.norm() - sc_value;
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal residual detected: "<<res;
#endif
return res;
};
Scalar calculateGradientFirst(Vector& point, Vector& line, Vector& dpoint) {
if(dist.norm() == 0)
return 1.;
const Vector3 d_diff = -dpoint.template head<3>();
const Vector3 d_dist = d_diff - d_diff.dot(n)*n;
const Scalar res = dist.dot(d_dist)/dist.norm();
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal first cluster gradient detected: "<<res
<<" with point: "<<point.transpose()<<", line: "<<line.transpose()
<<" and dpoint: "<<dpoint.transpose();
#endif
return res;
};
Scalar calculateGradientSecond(Vector& point, Vector& line, Vector& dline) {
if(dist.norm() == 0)
return 1.;
const Vector3 d_diff = dline.template head<3>();
const Vector3 d_n = dline.template segment<3>(3);
const Vector3 d_dist = d_diff - ((d_diff.dot(n)+diff.dot(d_n))*n + diff.dot(n)*d_n);
const Scalar res = dist.dot(d_dist)/dist.norm();
#ifdef USE_LOGGING
if(!boost::math::isfinite(res))
BOOST_LOG(log) << "Unnormal second cluster gradient detected: "<<res
<<" with point: "<<point.transpose()<<", line: "<<line.transpose()
<< "and dline: "<<dline.transpose();
#endif
return res;
};
void calculateGradientFirstComplete(Vector& point, Vector& line, Vector& gradient) {
if(dist.norm() == 0) {
gradient.head(3).setOnes();
return;
}
const Vector3 res = (n*n.transpose())*dist - dist;
gradient.head(3) = res/dist.norm();
};
void calculateGradientSecondComplete(Vector& point, Vector& line, Vector& gradient) {
if(dist.norm() == 0) {
gradient.head(6).setOnes();
return;
}
const Vector3 res = (-n*n.transpose())*dist + dist;
gradient.head(3) = res/dist.norm();
const Scalar mult = n.transpose()*dist;
gradient.template segment<3>(3) = -(mult*diff + diff.dot(n)*dist)/dist.norm();
};
};
template<typename Kernel>
struct Distance::type< Kernel, tag::line3D, tag::line3D > : public Distance::type< Kernel, tag::point3D, tag::line3D > {
#ifdef USE_LOGGING
type() : Distance::type< Kernel, tag::point3D, tag::line3D >() {
Distance::type< Kernel, tag::point3D, tag::line3D >::tag.set("Distance line3D line3D");
};
#endif
typedef typename Kernel::VectorMap Vector;
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
Distance::type< Kernel, tag::point3D, tag::line3D >::calculateGradientFirstComplete(p1,p2,g);
g.segment(3,3).setZero();
};
};
template<typename Kernel>
struct Distance::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public Distance::type< Kernel, tag::line3D, tag::line3D > {
#ifdef USE_LOGGING
type() : Distance::type< Kernel, tag::line3D, tag::line3D >() {
Distance::type< Kernel, tag::line3D, tag::line3D >::tag.set("Distance cylinder3D cylinder3D");
};
#endif
typedef typename Kernel::VectorMap Vector;
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
Distance::type< Kernel, tag::line3D, tag::line3D >::calculateGradientFirstComplete(p1,p2,g);
g(6) = 0;
};
};
}//namespace dcm
#endif //GCM_DISTANCE3D_H

View File

@ -0,0 +1,133 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_DOF_H
#define GCM_DOF_H
#include <utility>
#include <vector>
namespace dcm {
enum remaining {
nothing = 0,
line,
plane,
volume
};
template<typename K, typename C>
class Dof {
typedef typename K::Vector3 Vec;
typedef std::pair<Vec, C> VecID;
public:
typedef std::vector<C> ConstraintVector;
typedef std::pair<bool, ConstraintVector> Result;
Dof() : m_translation(volume), m_rotation(volume) {};
int dofTranslational() {
return m_translation;
};
int dofRotational() {
return m_rotation;
};
int dof() {
return dofTranslational() + dofRotational();
};
Result removeTranslationDirection(Vec& v, C constraint) {
if(m_translation == nothing) {
ConstraintVector cv;
cv.push_back(tp1.second);
cv.push_back(tp2.second);
cv.push_back(tp3.second);
return std::make_pair(false,cv);
} else if(m_translation == volume) {
m_translation = plane;
tp1 = std::make_pair(v, constraint);
} else if(m_translation == plane) {
if(K::isSame(tp1.first, v) || K::isOpposite(tp1.first, v)) {
ConstraintVector cv;
cv.push_back(tp1.second);
return std::make_pair(false,cv);
}
m_translation = line;
tp2 = std::make_pair(v, constraint);
} else if(m_translation == line) {
if(tp1.first.cross(tp2.first).dot(v) < 0.001) {
ConstraintVector cv;
cv.push_back(tp1.second);
cv.push_back(tp2.second);
return std::make_pair(false,cv);
}
m_translation = nothing;
tp3 = std::make_pair(v, constraint);
}
return std::make_pair(true, ConstraintVector());
};
Result allowOnlyRotationDirection(Vec& v, C constraint) {
if(m_rotation == nothing) {
ConstraintVector cv;
cv.push_back(rp1.second);
cv.push_back(rp2.second);
return std::make_pair(false, cv);
} else if(m_rotation == volume) {
m_rotation = line;
rp1 = std::make_pair(v, constraint);
} else if(m_rotation == plane) {
return std::make_pair(false, ConstraintVector()); //error as every function call removes 2 dof's
} else if(m_rotation == line) {
if(K::isSame(rp1.first, v) || K::isOpposite(rp1.first, v)) {
ConstraintVector cv;
cv.push_back(rp1.second);
return std::make_pair(false, cv);
}
m_rotation = nothing;
rp2 = std::make_pair(v, constraint);
}
return std::make_pair(true, ConstraintVector());
};
private:
int m_translation, m_rotation;
VecID tp1,tp2,tp3; //translation pairs
VecID rp1, rp2; //rotation pairs
};
}
#endif //GCM_DOF_H

View File

@ -0,0 +1,160 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_GEOMETRY_3D_H
#define GCM_GEOMETRY_3D_H
#include <opendcm/core/geometry.hpp>
namespace dcm {
namespace tag {
struct point3D {
typedef mpl::int_<3> parameters;
typedef mpl::int_<1> rotations;
typedef mpl::int_<1> translations;
typedef weight::point weight;
};
struct direction3D {
typedef mpl::int_<3> parameters;
typedef mpl::int_<1> rotations;
typedef mpl::int_<0> translations;
typedef weight::direction weight;
};
struct line3D {
typedef mpl::int_<6> parameters;
typedef mpl::int_<2> rotations;
typedef mpl::int_<1> translations;
typedef weight::line weight;
};
struct plane3D {
typedef mpl::int_<6> parameters;
typedef mpl::int_<2> rotations;
typedef mpl::int_<1> translations;
typedef weight::plane weight;
};
struct cylinder3D {
typedef mpl::int_<7> parameters;
typedef mpl::int_<2> rotations;
typedef mpl::int_<1> translations;
typedef weight::cylinder weight;
};
}
namespace modell {
struct XYZ {
/*Modell XYZ:
* 0 = X;
* 1 = Y;
* 2 = Z;
*/
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void extract(Type& t, Vector& v) {
Accessor a;
v(0) = a.template get<Scalar, 0>(t);
v(1) = a.template get<Scalar, 1>(t);
v(2) = a.template get<Scalar, 2>(t);
}
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void inject(Type& t, Vector& v) {
Accessor a;
a.template set<Scalar, 0>(v(0), t);
a.template set<Scalar, 1>(v(1), t);
a.template set<Scalar, 2>(v(2), t);
};
};
struct XYZ2 {
/*Modell XYZ2: two xyz parts after each other
* 0 = X;
* 1 = Y;
* 2 = Z;
* 3 = X dir;
* 4 = Y dir;
* 5 = Z dir;
*/
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void extract(Type& t, Vector& v) {
Accessor a;
v(0) = a.template get<Scalar, 0>(t);
v(1) = a.template get<Scalar, 1>(t);
v(2) = a.template get<Scalar, 2>(t);
v(3) = a.template get<Scalar, 3>(t);
v(4) = a.template get<Scalar, 4>(t);
v(5) = a.template get<Scalar, 5>(t);
}
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void inject(Type& t, Vector& v) {
Accessor a;
a.template set<Scalar, 0>(v(0), t);
a.template set<Scalar, 1>(v(1), t);
a.template set<Scalar, 2>(v(2), t);
a.template set<Scalar, 3>(v(3), t);
a.template set<Scalar, 4>(v(4), t);
a.template set<Scalar, 5>(v(5), t);
};
};
struct XYZ2P {
/*Modell XYZ2P: two xyz parts after each other and one parameter
* 0 = X;
* 1 = Y;
* 2 = Z;
* 3 = X dir;
* 4 = Y dir;
* 5 = Z dir;
* 6 = Parameter
*/
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void extract(Type& t, Vector& v) {
Accessor a;
v(0) = a.template get<Scalar, 0>(t);
v(1) = a.template get<Scalar, 1>(t);
v(2) = a.template get<Scalar, 2>(t);
v(3) = a.template get<Scalar, 3>(t);
v(4) = a.template get<Scalar, 4>(t);
v(5) = a.template get<Scalar, 5>(t);
v(6) = a.template get<Scalar, 6>(t);
}
template<typename Scalar, typename Accessor, typename Vector, typename Type>
void inject(Type& t, Vector& v) {
Accessor a;
a.template set<Scalar, 0>(v(0), t);
a.template set<Scalar, 1>(v(1), t);
a.template set<Scalar, 2>(v(2), t);
a.template set<Scalar, 3>(v(3), t);
a.template set<Scalar, 4>(v(4), t);
a.template set<Scalar, 5>(v(5), t);
a.template set<Scalar, 6>(v(6), t);
};
};
}
}
#endif //GCM_GEOMETRY_3D_H

View File

@ -0,0 +1,546 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_MODULE_3D_H
#define GCM_MODULE_3D_H
#include <boost/mpl/vector.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/size.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/static_assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include "opendcm/core.hpp"
#include "opendcm/core/object.hpp"
#include "opendcm/core/clustergraph.hpp"
#include "opendcm/core/sheduler.hpp"
#include "opendcm/core/traits.hpp"
#include "opendcm/core/geometry.hpp"
#include "geometry.hpp"
#include "distance.hpp"
#include "parallel.hpp"
#include "angle.hpp"
#include "solver.hpp"
#include "defines.hpp"
#include "clustermath.hpp"
namespace mpl = boost::mpl;
namespace dcm {
namespace details {
template<typename seq, typename t>
struct distance {
typedef typename mpl::find<seq, t>::type iterator;
typedef typename mpl::distance<typename mpl::begin<seq>::type, iterator>::type type;
BOOST_MPL_ASSERT((mpl::not_< boost::is_same<iterator, typename mpl::end<seq>::type > >));
};
}
}//dcm
namespace dcm {
template<typename Typelist, typename ID = No_Identifier>
struct Module3D {
template<typename Sys>
struct type : details::m3d {
struct Constraint3D;
struct Geometry3D;
struct vertex_prop;
struct inheriter_base;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef boost::shared_ptr<Constraint3D> Cons;
typedef mpl::map1< mpl::pair<remove, boost::function<void (Cons) > > > ConsSignal;
typedef ID Identifier;
typedef details::MES<Sys> MES;
typedef details::SystemSolver<Sys> SystemSolver;
template<typename Derived>
class Geometry3D_id : public detail::Geometry<Sys, Derived, Typelist, 3> {
typedef detail::Geometry<Sys, Derived, Typelist, 3> Base;
#ifdef USE_LOGGING
attrs::mutable_constant< std::string > log_id;
#endif
public:
template<typename T>
Geometry3D_id(T geometry, Sys& system);
template<typename T>
void set(T geometry, Identifier id);
//somehow the base class set funtion is not found
template<typename T>
void set(T geometry);
Identifier& getIdentifier();
void setIdentifier(Identifier id);
};
struct Geometry3D : public mpl::if_<boost::is_same<Identifier, No_Identifier>,
detail::Geometry<Sys, Geometry3D, Typelist, 3>, Geometry3D_id<Geometry3D> >::type {
typedef vertex_prop vertex_propertie;
template<typename T>
Geometry3D(T geometry, Sys& system);
//allow accessing the internals by module3d classes but not by users
friend struct details::ClusterMath<Sys>;
friend struct details::ClusterMath<Sys>::map_downstream;
friend struct details::SystemSolver<Sys>;
friend struct details::SystemSolver<Sys>::Rescaler;
friend class detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>;
};
template<typename Derived>
class Constraint3D_id : public detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D> {
typedef detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D> base;
public:
Constraint3D_id(Sys& system, Geom f, Geom s);
Identifier& getIdentifier();
void setIdentifier(Identifier id);
};
struct Constraint3D : public mpl::if_<boost::is_same<Identifier, No_Identifier>,
detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>,
Constraint3D_id<Constraint3D> >::type {
Constraint3D(Sys& system, Geom first, Geom second);
friend struct details::SystemSolver<Sys>;
friend struct details::SystemSolver<Sys>::Rescaler;
friend struct details::MES<Sys>;
friend struct inheriter_base;
};
struct inheriter_base {
inheriter_base();
template<typename T>
Geom createGeometry3D(T geom);
void removeGeometry3D(Geom g);
template<typename T1>
Cons createConstraint3D(Geom first, Geom second, T1 constraint1);
void removeConstraint3D(Cons c);
protected:
Sys* m_this;
void apply_edge_remove(GlobalEdge e);
};
struct inheriter_id : public inheriter_base {
protected:
using inheriter_base::m_this;
public:
template<typename T>
Geom createGeometry3D(T geom, Identifier id);
template<typename T>
Cons createConstraint3D(Identifier id, Geom first, Geom second, T constraint1);
void removeGeometry3D(Identifier id);
void removeConstraint3D(Identifier id);
bool hasGeometry3D(Identifier id);
Geom getGeometry3D(Identifier id);
bool hasConstraint3D(Identifier id);
Cons getConstraint3D(Identifier id);
};
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
struct math_prop {
typedef cluster_property kind;
typedef details::ClusterMath<Sys> type;
};
struct fix_prop {
typedef cluster_property kind;
typedef bool type;
};
struct vertex_prop {
typedef Geometry3D kind;
typedef GlobalVertex type;
};
struct edge_prop {
typedef Constraint3D kind;
typedef GlobalEdge type;
};
typedef mpl::vector4<vertex_prop, edge_prop, math_prop, fix_prop> properties;
typedef mpl::vector<Geometry3D, Constraint3D> objects;
static void system_init(Sys& sys) {
sys.m_sheduler.addProcessJob(new SystemSolver());
};
static void system_copy(const Sys& from, Sys& into) {
//nothing to to as all objects and properties are copyed with the clustergraph
};
};
};
namespace details {
//allow direct access to the stored geometry in a Geometry3D, copyed from boost variant get
template <typename T>
struct get_visitor {
private:
typedef typename boost::add_pointer<T>::type pointer;
typedef typename boost::add_reference<T>::type reference;
public:
typedef pointer result_type;
public:
pointer operator()(reference operand) const {
return boost::addressof(operand);
}
template <typename U>
pointer operator()(const U&) const {
return static_cast<pointer>(0);
}
};
}
template<typename T, typename G>
typename boost::add_reference<T>::type get(G geom) {
typedef typename boost::add_pointer<T>::type T_ptr;
details::get_visitor<T> v;
T_ptr result = geom->apply(v);
//if (!result)
//TODO:throw bad_get();
return *result;
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(T geometry, Sys& system)
: detail::Geometry<Sys, Derived, Typelist, 3>(geometry, system)
#ifdef USE_LOGGING
, log_id("No ID")
#endif
{
#ifdef USE_LOGGING
Base::log.add_attribute("ID", log_id);
#endif
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(T geometry, Identifier id) {
this->template setProperty<id_prop<Identifier> >(id);
Base::set(geometry);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(T geometry) {
Base::set(geometry);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::getIdentifier() {
return this->template getProperty<id_prop<Identifier> >();
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::setIdentifier(Identifier id) {
this->template setProperty<id_prop<Identifier> >(id);
#ifdef USE_LOGGING
std::stringstream str;
str<<this->template getProperty<id_prop<Identifier> >();
log_id.set(str.str());
BOOST_LOG(Base::log)<<"Identifyer set: "<<id;
#endif
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(T geometry, Sys& system)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
detail::Geometry<Sys, Geometry3D, Typelist, 3>,
Geometry3D_id<Geometry3D> >::type(geometry, system) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::Constraint3D_id(Sys& system, Geom f, Geom s)
: detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D>(system, f, s) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::getIdentifier() {
return this->template getProperty<id_prop<Identifier> >();
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::setIdentifier(Identifier id) {
this->template setProperty<id_prop<Identifier> >(id);
};
template<typename Typelist, typename ID>
template<typename Sys>
Module3D<Typelist, ID>::type<Sys>::Constraint3D::Constraint3D(Sys& system, Geom first, Geom second)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>,
Constraint3D_id<Constraint3D> >::type(system, first, second) {
};
template<typename Typelist, typename ID>
template<typename Sys>
Module3D<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
m_this = ((Sys*) this);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D(T geom) {
Geom g(new Geometry3D(geom, * ((Sys*) this)));
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
m_this->push_back(g);
return g;
};
template<typename Typelist, typename ID>
template<typename Sys>
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeGeometry3D(Geom g) {
GlobalVertex v = g->template getProperty<vertex_prop>();
//check if this vertex holds a constraint
Cons c = m_this->m_cluster->template getObject<Constraint3D>(v);
if(c)
c->template emitSignal<remove>(c);
//emit remove geometry signal bevore actually deleting it, in case anyone want to access the
//graph before
g->template emitSignal<remove>(g);
//remove the vertex from graph and emit all edges that get removed with the functor
boost::function<void(GlobalEdge)> functor = boost::bind(&inheriter_base::apply_edge_remove, this, _1);
m_this->m_cluster->removeVertex(v, functor);
m_this->erase(g);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T1>
typename Module3D<Typelist, ID>::template type<Sys>::Cons
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createConstraint3D(Geom first, Geom second, T1 constraint1) {
//build a constraint vector
typedef mpl::vector<> cvec;
typedef typename mpl::if_< mpl::is_sequence<T1>,
typename mpl::fold< T1, cvec, mpl::push_back<mpl::_1,mpl::_2> >::type,
mpl::vector1<T1> >::type cvec1;
//make a fusion sequence to hold the objects (as they hold the options)
typedef typename fusion::result_of::as_vector<cvec1>::type covec;
//set the objects
covec cv;
fusion::at_c<0>(cv) = constraint1;
//now create the constraint
Cons c(new Constraint3D(*m_this, first, second));
//set the type and values
c->template initialize<cvec1>(cv);
//add it to the clustergraph
fusion::vector<LocalEdge, GlobalEdge, bool, bool> res;
res = m_this->m_cluster->addEdge(first->template getProperty<vertex_prop>(),
second->template getProperty<vertex_prop>());
if(!fusion::at_c<2>(res)) {
Cons rc;
return rc; //TODO: throw
};
m_this->m_cluster->template setObject<Constraint3D> (fusion::at_c<1> (res), c);
//add the coresbondig edge to the constraint
c->template setProperty<edge_prop>(fusion::at_c<1>(res));
//store the constraint in general object vector of main system
m_this->push_back(c);
return c;
};
template<typename Typelist, typename ID>
template<typename Sys>
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeConstraint3D(Cons c) {
GlobalEdge e = c->template getProperty<edge_prop>();
c->template emitSignal<remove>(c);
m_this->m_cluster->removeEdge(e);
m_this->erase(c);
};
template<typename Typelist, typename ID>
template<typename Sys>
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::apply_edge_remove(GlobalEdge e) {
Cons c = m_this->m_cluster->template getObject<Constraint3D>(e);
c->template emitSignal<remove>(c);
m_this->erase(c);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(T geom, Identifier id) {
Geom g = inheriter_base::createGeometry3D(geom);
g->setIdentifier(id);
return g;
};
template<typename Typelist, typename ID>
template<typename Sys>
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeGeometry3D(Identifier id) {
if(hasGeometry3D(id))
inheriter_base::removeGeometry3D(getGeometry3D(id));
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename Module3D<Typelist, ID>::template type<Sys>::Cons
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createConstraint3D(Identifier id, Geom first, Geom second, T constraint1) {
Cons c = inheriter_base::createConstraint3D(first, second, constraint1);
c->setIdentifier(id);
return c;
};
template<typename Typelist, typename ID>
template<typename Sys>
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeConstraint3D(Identifier id) {
if(hasConstraint3D(id))
removeConstraint3D(getConstraint3D(id));
};
template<typename Typelist, typename ID>
template<typename Sys>
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasGeometry3D(Identifier id) {
if(getGeometry3D(id)) return true;
return false;
};
template<typename Typelist, typename ID>
template<typename Sys>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getGeometry3D(Identifier id) {
std::vector< Geom >& vec = inheriter_base::m_this->template objectVector<Geometry3D>();
typedef typename std::vector<Geom>::iterator iter;
for(iter it=vec.begin(); it!=vec.end(); it++) {
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
};
return Geom();
};
template<typename Typelist, typename ID>
template<typename Sys>
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasConstraint3D(Identifier id) {
if(getConstraint3D(id)) return true;
return false;
};
template<typename Typelist, typename ID>
template<typename Sys>
typename Module3D<Typelist, ID>::template type<Sys>::Cons
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getConstraint3D(Identifier id) {
std::vector< Cons >& vec = inheriter_base::m_this->template objectVector<Constraint3D>();
typedef typename std::vector<Cons>::iterator iter;
for(iter it=vec.begin(); it!=vec.end(); it++) {
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
};
return Cons();
};
}//dcm
#endif //GCM_GEOMETRY3D_H

View File

@ -0,0 +1,215 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 detemplate tails.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_PARALLEL_H
#define GCM_PARALLEL_H
#include <opendcm/core/constraint.hpp>
#include "geometry.hpp"
#include <boost/math/special_functions/fpclassify.hpp>
using boost::math::isnormal;
namespace dcm {
//the calculations( same as we always calculate directions we can outsource the work to this functions)
namespace parallel_detail {
template<typename Kernel, typename T>
inline typename Kernel::number_type calc(T d1,
T d2,
Direction dir) {
switch(dir) {
case Same:
return (d1-d2).norm();
case Opposite:
return (d1+d2).norm();
case Both:
if(d1.dot(d2) >= 0) {
return (d1-d2).norm();
}
return (d1+d2).norm();
default:
assert(false);
}
return 0;
};
template<typename Kernel, typename T>
inline typename Kernel::number_type calcGradFirst(T d1,
T d2,
T dd1,
Direction dir) {
typename Kernel::number_type res;
switch(dir) {
case Same:
res = ((d1-d2).dot(dd1) / (d1-d2).norm());
break;
case Opposite:
res= ((d1+d2).dot(dd1) / (d1+d2).norm());
break;
case Both:
if(d1.dot(d2) >= 0) {
res = (((d1-d2).dot(dd1) / (d1-d2).norm()));
break;
}
res = (((d1+d2).dot(dd1) / (d1+d2).norm()));
break;
}
if((isnormal)(res)) return res;
return 0;
};
template<typename Kernel, typename T>
inline typename Kernel::number_type calcGradSecond(T d1,
T d2,
T dd2,
Direction dir) {
typename Kernel::number_type res;
switch(dir) {
case Same:
res = ((d1-d2).dot(-dd2) / (d1-d2).norm());
break;
case Opposite:
res = ((d1+d2).dot(dd2) / (d1+d2).norm());
break;
case Both:
if(d1.dot(d2) >= 0) {
res = (((d1-d2).dot(-dd2) / (d1-d2).norm()));
break;
}
res = (((d1+d2).dot(dd2) / (d1+d2).norm()));
break;
}
if((isnormal)(res)) return res;
return 0;
};
template<typename Kernel, typename T>
inline void calcGradFirstComp(T d1,
T d2,
T grad,
Direction dir) {
switch(dir) {
case Same:
grad = (d1-d2) / (d1-d2).norm();
return;
case Opposite:
grad = (d1+d2) / (d1+d2).norm();
return;
case Both:
assert(false);
}
};
template<typename Kernel, typename T>
inline void calcGradSecondComp(T d1,
T d2,
T grad,
Direction dir) {
switch(dir) {
case Same:
grad = (d2-d1) / (d1-d2).norm();
return;
case Opposite:
grad = (d2+d1) / (d1+d2).norm();
return;
case Both:
assert(false);
}
};
}
template< typename Kernel >
struct Parallel::type< Kernel, tag::line3D, tag::line3D > : public dcm::PseudoScale<Kernel> {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
Direction value;
//template definition
Scalar calculate(Vector& param1, Vector& param2) {
return parallel_detail::calc<Kernel>(param1.template tail<3>(), param2.template tail<3>(), value);
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
return parallel_detail::calcGradFirst<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam1.template tail<3>(), value);
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
return parallel_detail::calcGradSecond<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam2.template tail<3>(), value);
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
parallel_detail::calcGradFirstComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>(), value);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
parallel_detail::calcGradSecondComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>(), value);
};
};
template< typename Kernel >
struct Parallel::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::PseudoScale<Kernel>{
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
Direction value;
Scalar calculate(Vector& param1, Vector& param2) {
return parallel_detail::calc<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3), value);
};
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
return parallel_detail::calcGradFirst<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
dparam1.template segment<3>(3), value);
};
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
return parallel_detail::calcGradSecond<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
dparam2.template segment<3>(3), value);
};
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
parallel_detail::calcGradFirstComp<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
gradient.template segment<3>(3), value);
};
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
gradient.template head<3>().setZero();
parallel_detail::calcGradSecondComp<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
gradient.template segment<3>(3), value);
};
};
template< typename Kernel >
struct Parallel::type< Kernel, tag::line3D, tag::plane3D > : public Parallel::type<Kernel, tag::line3D, tag::line3D> {};
template< typename Kernel >
struct Parallel::type< Kernel, tag::plane3D, tag::plane3D > : public Parallel::type<Kernel, tag::line3D, tag::line3D> {};
}
#endif //GCM_ANGLE

View File

@ -0,0 +1,367 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_SOLVER_3D_H
#define GCM_SOLVER_3D_H
#include <boost/graph/adjacency_list.hpp>
#include "defines.hpp"
#include "clustermath.hpp"
#include "opendcm/core/sheduler.hpp"
#include "opendcm/core/traits.hpp"
namespace dcm {
namespace details {
template<typename Sys>
struct MES : public system_traits<Sys>::Kernel::MappedEquationSystem {
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
typedef typename module3d::Geometry3D Geometry3D;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef typename module3d::Constraint3D Constraint3D;
typedef boost::shared_ptr<Constraint3D> Cons;
typedef typename module3d::math_prop math_prop;
typedef typename module3d::fix_prop fix_prop;
typedef typename Kernel::number_type Scalar;
typedef typename system_traits<Sys>::Kernel::MappedEquationSystem Base;
boost::shared_ptr<Cluster> m_cluster;
MES(boost::shared_ptr<Cluster> cl, int par, int eqn);
virtual void recalculate();
};
template<typename Sys>
struct SystemSolver : public Job<Sys> {
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename Kernel::number_type Scalar;
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
typedef typename module3d::Geometry3D Geometry3D;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef typename module3d::Constraint3D Constraint3D;
typedef boost::shared_ptr<Constraint3D> Cons;
typedef typename module3d::math_prop math_prop;
typedef typename module3d::fix_prop fix_prop;
typedef typename module3d::vertex_prop vertex_prop;
typedef MES<Sys> Mes;
#ifdef USE_LOGGING
src::logger log;
#endif
struct Rescaler {
boost::shared_ptr<Cluster> cluster;
Mes& mes;
int rescales;
Rescaler(boost::shared_ptr<Cluster> c, Mes& m);
void operator()();
Scalar scaleClusters();
void collectPseudoPoints(boost::shared_ptr<Cluster> parent,
LocalVertex cluster,
std::vector<typename Kernel::Vector3,
Eigen::aligned_allocator<typename Kernel::Vector3> >& vec);
};
SystemSolver();
virtual void execute(Sys& sys);
void solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys);
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys>
MES<Sys>::MES(boost::shared_ptr<Cluster> cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) {
};
template<typename Sys>
void MES<Sys>::recalculate() {
//first calculate all clusters
typedef typename Cluster::cluster_iterator citer;
std::pair<citer, citer> cit = m_cluster->clusters();
for(; cit.first != cit.second; cit.first++) {
if(!(*cit.first).second->template getClusterProperty<fix_prop>())
(*cit.first).second->template getClusterProperty<math_prop>().recalculate();
};
//with everything updated just nicely we can compute the constraints
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
for(; eit.first != eit.second; eit.first++) {
//as always: every local edge can hold multiple global ones, so iterate over all constraints
//hold by the individual edge
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
for(; oit.first != oit.second; oit.first++) {
if(*oit.first)
(*oit.first)->calculate(Base::Scaling);
}
}
};
template<typename Sys>
SystemSolver<Sys>::Rescaler::Rescaler(boost::shared_ptr<Cluster> c, Mes& m) : cluster(c), mes(m), rescales(0) {
};
template<typename Sys>
void SystemSolver<Sys>::Rescaler::operator()() {
mes.Scaling = scaleClusters();
rescales++;
};
template<typename Sys>
typename SystemSolver<Sys>::Scalar SystemSolver<Sys>::Rescaler::scaleClusters() {
typedef typename Cluster::cluster_iterator citer;
std::pair<citer, citer> cit = cluster->clusters();
//get the maximal scale
Scalar sc = 0;
for(cit = cluster->clusters(); cit.first != cit.second; cit.first++) {
//fixed cluster are irrelevant for scaling
if((*cit.first).second->template getClusterProperty<fix_prop>()) continue;
//get the biggest scale factor
details::ClusterMath<Sys>& math = (*cit.first).second->template getClusterProperty<math_prop>();
//math.m_pseudo.clear();
//collectPseudoPoints(cluster, (*cit.first).first, math.m_pseudo);
const Scalar s = math.calculateClusterScale();
sc = (s>sc) ? s : sc;
}
//if no scaling-value returned we can use 1
sc = (Kernel::isSame(sc,0)) ? 1. : sc;
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
std::pair<iter, iter> it = boost::vertices(*cluster);
for(; it.first != it.second; it.first++) {
if(cluster->isCluster(*it.first)) {
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
c->template getClusterProperty<math_prop>().applyClusterScale(sc,
c->template getClusterProperty<fix_prop>());
} else {
Geom g = cluster->template getObject<Geometry3D>(*it.first);
g->scale(sc*SKALEFAKTOR);
}
}
return 1./(sc*SKALEFAKTOR);
};
template<typename Sys>
void SystemSolver<Sys>::Rescaler::collectPseudoPoints(
boost::shared_ptr<typename SystemSolver<Sys>::Cluster> parent,
LocalVertex cluster,
std::vector<typename SystemSolver<Sys>::Kernel::Vector3,
Eigen::aligned_allocator<typename SystemSolver<Sys>::Kernel::Vector3> >& vec) {
std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > vec2;
typedef typename Cluster::template object_iterator<Constraint3D> c_iter;
typedef typename boost::graph_traits<Cluster>::out_edge_iterator e_iter;
std::pair<e_iter, e_iter> it = boost::out_edges(cluster, *parent);
for(; it.first != it.second; it.first++) {
std::pair< c_iter, c_iter > cit = parent->template getObjects<Constraint3D>(*it.first);
for(; cit.first != cit.second; cit.first++) {
Cons c = *(cit.first);
if(!c)
continue;
//get the first global vertex and see if we have it in the wanted cluster or not
GlobalVertex v = c->first->template getProperty<vertex_prop>();
std::pair<LocalVertex,bool> res = parent->getLocalVertex(v);
if(!res.second)
return; //means the geometry is in non of the clusters which is not allowed
if(res.first == cluster)
c->collectPseudoPoints(vec, vec2);
else
c->collectPseudoPoints(vec2, vec);
}
}
};
template<typename Sys>
SystemSolver<Sys>::SystemSolver() {
Job<Sys>::priority = 1000;
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("SystemSolver3D"));
#endif
};
template<typename Sys>
void SystemSolver<Sys>::execute(Sys& sys) {
solveCluster(sys.m_cluster, sys);
};
template<typename Sys>
void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys) {
//set out and solve all relevant subclusters
typedef typename Cluster::cluster_iterator citer;
std::pair<citer, citer> cit = cluster->clusters();
for(; cit.first != cit.second; cit.first++) {
boost::shared_ptr<Cluster> c = (*cit.first).second;
if(c->template getClusterProperty<changed_prop>() &&
c->template getClusterProperty<type_prop>() == details::cluster3D)
solveCluster(c, sys);
}
int params=0, constraints=0;
typename Kernel::number_type scale = 1;
//get the ammount of parameters and constraint equations we need
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
std::pair<iter, iter> it = boost::vertices(*cluster);
for(; it.first != it.second; it.first++) {
//when cluster and not fixed it has trans and rot parameter
if(cluster->isCluster(*it.first)) {
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first)) {
params += 6;
}
} else {
params += cluster->template getObject<Geometry3D>(*it.first)->m_parameterCount;
};
}
//count the equations in the constraints
typedef typename Cluster::template object_iterator<Constraint3D> ocit;
typedef typename boost::graph_traits<Cluster>::edge_iterator e_iter;
std::pair<e_iter, e_iter> e_it = boost::edges(*cluster);
for(; e_it.first != e_it.second; e_it.first++) {
std::pair< ocit, ocit > it = cluster->template getObjects<Constraint3D>(*e_it.first);
for(; it.first != it.second; it.first++)
constraints += (*it.first)->equationCount();
};
//initialise the system with now known size
//std::cout<<"constraints: "<<constraints<<", params: "<<params+rot_params+trans_params<<std::endl;
Mes mes(cluster, params, constraints);
//iterate all geometrys again and set the needed maps
it = boost::vertices(*cluster);
for(; it.first != it.second; it.first++) {
if(cluster->isCluster(*it.first)) {
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
details::ClusterMath<Sys>& cm = c->template getClusterProperty<math_prop>();
//only get maps and propagate downstream if not fixed
if(!c->template getClusterProperty<fix_prop>()) {
//set norm Quaternion as map to the parameter vector
int offset = mes.setParameterMap(cm.getNormQuaternionMap());
//set translation as map to the parameter vector
mes.setParameterMap(cm.getTranslationMap());
//write initail values to the parameter maps
//remember the parameter offset as all downstream geometry must use this offset
cm.setParameterOffset(offset);
//wirte initial values
cm.initMaps();
} else cm.initFixMaps();
//map all geometrie within that cluster to it's rotation matrix
//for collecting all geometries which need updates
cm.clearGeometry();
cm.mapClusterDownstreamGeometry(c);
} else {
Geom g = cluster->template getObject<Geometry3D>(*it.first);
int offset = mes.setParameterMap(g->m_parameterCount, g->getParameterMap());
g->m_offset = offset;
//init the parametermap with initial values
g->initMap();
}
}
//and now the constraints to set the residual and gradient maps
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
e_it = boost::edges(*cluster);
for(; e_it.first != e_it.second; e_it.first++) {
//as always: every local edge can hold multiple global ones, so iterate over all constraints
//hold by the individual edge
std::pair< oiter, oiter > oit = cluster->template getObjects<Constraint3D>(*e_it.first);
for(; oit.first != oit.second; oit.first++) {
//set the maps
Cons c = *oit.first;
if(c) c->setMaps(mes);
//TODO: else throw (as every global edge was counted as one equation)
}
}
int stop = 0;
Rescaler re(cluster, mes);
re();
stop = Kernel::solve(mes, re);
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
#endif
//now go to all relevant geometries and clusters and write the values back
it = boost::vertices(*cluster);
for(; it.first != it.second; it.first++) {
if(cluster->isCluster(*it.first)) {
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first))
c->template getClusterProperty<math_prop>().finishCalculation();
else
c->template getClusterProperty<math_prop>().finishFixCalculation();
std::vector<Geom>& vec = c->template getClusterProperty<math_prop>().getGeometry();
for(typename std::vector<Geom>::iterator vit = vec.begin(); vit != vec.end(); vit++)
(*vit)->finishCalculation();
} else {
Geom g = cluster->template getObject<Geometry3D>(*it.first);
g->scale(mes.Scaling);
g->finishCalculation();
}
}
//we have solved this cluster
cluster->template setClusterProperty<changed_prop>(false);
};
}//details
}//dcm
#endif //DCM_SOLVER_3D_HPP

View File

@ -0,0 +1,95 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_MODULE3D_STATE_HPP
#define DCM_MODULE3D_STATE_HPP
#include "module.hpp"
#include "opendcm/moduleState/traits.hpp"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace karma = boost::spirit::karma;
namespace ascii = boost::spirit::karma::ascii;
namespace phx = boost::phoenix;
namespace dcm {
namespace details {
struct geom_visitor : public boost::static_visitor<int> {
template<typename T>
int operator()(T& i) const {
return geometry_traits<T>::tag::weight::value;
};
};
template<typename T>
int getWeight(boost::shared_ptr<T> ptr) {
return boost::apply_visitor(geom_visitor(), ptr->m_geometry);
};
template<typename Kernel>
void getStdVector(typename Kernel::Vector& eigen, std::vector<typename Kernel::number_type>& vec) {
vec.resize(eigen.size());
for(int i=0; i<eigen.size(); i++)
vec[i] = eigen(i);
};
}
template<typename System>
struct parser_generate< typename Module3D::type<System>::Geometry3D, System>
: public mpl::true_{};
template<typename System, typename iterator>
struct parser_generator< typename Module3D::type<System>::Geometry3D, System, iterator > {
typedef typename Sys::Kernel Kernel;
typedef typename typename Module3D::type<System>::Geometry3D Geometry;
typedef karma::rule<iterator, boost::shared_ptr<Geometry>() > generator;
static void init(generator& r) {
r = karma::lit("<type>Geometry3D</type>\n<class>")
<< ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
<< "</class>\n<value>"
<< (karma::double_ % " ")[phx::bind(&details::getStdVector<Kernel>, )]
};
};
template<typename System>
struct parser_parse< typename Module3D::type<System>::Geometry3D, System>
: public mpl::true_{};
template<typename System, typename iterator>
struct parser_parser< typename Module3D::type<System>::Geometry3D, System, iterator > {
typedef typename Module3D::type<System>::Geometry3D object_type;
typedef qi::rule<iterator, boost::shared_ptr<object_type>(System*), qi::space_type> parser;
static void init(parser& r) {
r = qi::lexeme[qi::lit("<type>object 1 prop</type>")[ qi::_val =
phx::construct<boost::shared_ptr<object_type> >( phx::new_<object_type>(*qi::_r1))]] >> ("<value>HaHAHAHAHA</value>");
};
};
}
#endif //DCM_MODULE3D_STATE_HPP

View File

@ -0,0 +1,92 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_GEOMETRY_PART_H
#define GCM_GEOMETRY_PART_H
#include <opendcm/core/geometry.hpp>
#include <opendcm/core/kernel.hpp>
namespace dcm {
namespace tag {
struct part {};
}
namespace modell {
struct quaternion_wxyz_vec3 {
/*Modell XYZ:
* 0 = w;
* 1 = x;
* 2 = y;
* 3 = z;
*/
template<typename Kernel, typename Accessor, typename Type>
void extract(Type& t, typename Kernel::Transform3D& trans) {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::Transform3D::Rotation Rotation;
typedef typename Kernel::Transform3D::Translation Translation;
Accessor a;
Rotation r;
r.w() = a.template get<Scalar, 0>(t);
r.x() = a.template get<Scalar, 1>(t);
r.y() = a.template get<Scalar, 2>(t);
r.z() = a.template get<Scalar, 3>(t);
Translation tr;;
tr.vector()(0) = a.template get<Scalar, 4>(t);
tr.vector()(1) = a.template get<Scalar, 5>(t);
tr.vector()(2) = a.template get<Scalar, 6>(t);
trans = r;
trans *= tr;
}
template<typename Kernel, typename Accessor, typename Type>
void inject(Type& t, typename Kernel::Transform3D& trans) {
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::Transform3D::Rotation Rotation;
typedef typename Kernel::Transform3D::Translation Translation;
Accessor a;
const Rotation& r = trans.rotation();
a.template set<Scalar, 0>(r.w(), t);
a.template set<Scalar, 1>(r.x(), t);
a.template set<Scalar, 2>(r.y(), t);
a.template set<Scalar, 3>(r.z(), t);
const Translation& tr = trans.translation();
a.template set<Scalar, 4>(tr.vector()(0), t);
a.template set<Scalar, 5>(tr.vector()(1), t);
a.template set<Scalar, 6>(tr.vector()(2), t);
a.finalize(t);
};
};
}
}
#endif //GCM_GEOMETRY_PART_H

View File

@ -0,0 +1,558 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_MODULE_PART_H
#define GCM_MODULE_PART_H
#include "opendcm/core.hpp"
#include "opendcm/core/traits.hpp"
#include "opendcm/core/clustergraph.hpp"
#include "opendcm/core/property.hpp"
#include "opendcm/module3d.hpp"
#include <boost/mpl/assert.hpp>
#include <boost/utility/enable_if.hpp>
namespace mpl = boost::mpl;
namespace dcm {
enum { clusterPart = 110};
enum CoordinateFrame {Local, Global};
template<typename Typelist, typename ID = No_Identifier>
struct ModulePart {
template<typename Sys>
struct type {
struct Part;
struct PrepareCluster;
struct EvaljuateCluster;
typedef boost::shared_ptr<Part> Partptr;
typedef mpl::map2< mpl::pair<remove, boost::function<void (Partptr) > >,
mpl::pair<recalculated, boost::function<void (Partptr) > > > PartSignal;
typedef ID Identifier;
class Part_base : public Object<Sys, Part, PartSignal > {
protected:
#ifdef USE_LOGGING
src::logger log;
#endif
//check if we have module3d in this system
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<module3d, mpl::void_> >));
//define what we need
typedef typename module3d::Geometry3D Geometry3D;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef typename boost::make_variant_over< Typelist >::type Variant;
typedef Object<Sys, Part, PartSignal> base;
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::Transform3D Transform;
struct cloner : boost::static_visitor<void> {
Variant variant;
cloner(Variant& v) : variant(v) {};
template<typename T>
void operator()(T& t) {
variant = geometry_clone_traits<T>()(t);
};
};
//visitor to write the calculated value into the variant
struct apply_visitor : public boost::static_visitor<void> {
apply_visitor(Transform& t) : m_transform(t) {};
template <typename T>
void operator()(T& t) const {
(typename geometry_traits<T>::modell()).template inject<Kernel,
typename geometry_traits<T>::accessor >(t, m_transform);
}
Transform& m_transform;
};
public:
using Object<Sys, Part, PartSignal >::m_system;
template<typename T>
Part_base(T geometry, Sys& system, boost::shared_ptr<Cluster> cluster);
template<typename Visitor>
typename Visitor::result_type apply(Visitor& vis);
template<typename T>
Geom addGeometry3D(T geom, CoordinateFrame frame = Global);
template<typename T>
void set(T geometry);
virtual boost::shared_ptr<Part> clone(Sys& newSys);
public:
Variant m_geometry;
Transform m_transform;
boost::shared_ptr<Cluster> m_cluster;
void finishCalculation();
void fix(bool fix_value);
};
struct Part_id : public Part_base {
template<typename T>
Part_id(T geometry, Sys& system, boost::shared_ptr<typename Part_base::Cluster> cluster);
template<typename T>
typename Part_base::Geom addGeometry3D(T geom, Identifier id, CoordinateFrame frame = Global);
template<typename T>
void set(T geometry, Identifier id);
bool hasGeometry3D(Identifier id);
typename Part_base::Geom getGeometry3D(Identifier id);
Identifier& getIdentifier();
void setIdentifier(Identifier id);
};
struct Part : public mpl::if_<boost::is_same<Identifier, No_Identifier>, Part_base, Part_id>::type {
typedef typename mpl::if_<boost::is_same<Identifier, No_Identifier>, Part_base, Part_id>::type base;
template<typename T>
Part(T geometry, Sys& system, boost::shared_ptr<typename base::Cluster> cluster);
friend struct PrepareCluster;
friend struct EvaljuateCluster;
};
struct inheriter_base {
inheriter_base();
template<typename T>
Partptr createPart(T geometry);
void removePart(Partptr p);
template<typename T>
void setTransformation(T geom) {
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
details::ClusterMath<Sys>& cm = ((Sys*)this)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
(typename geometry_traits<T>::modell()).template extract<typename Sys::Kernel,
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
};
template<typename T>
T getTransformation() {
T geom;
getTransformation(geom);
return geom;
};
template<typename T>
void getTransformation(T& geom) {
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
details::ClusterMath<Sys>& cm = ((Sys*)this)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
(typename geometry_traits<T>::modell()).template inject<typename Sys::Kernel,
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
};
protected:
Sys* m_this;
//function object to emit remove signal too al geometry which is deleted by part deletion
struct remover {
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
typedef typename module3d::Geometry3D Geometry3D;
typedef boost::shared_ptr<Geometry3D> Geom;
typedef typename module3d::Constraint3D Constraint3D;
typedef boost::shared_ptr<Constraint3D> Cons;
Sys& system;
remover(Sys& s);
//see if we have a geometry or a constraint and emit the remove signal
void operator()(GlobalVertex v);
//we delete all global edges connecting to this part
void operator()(GlobalEdge e);
void operator()(boost::shared_ptr<Cluster> g) {};
};
};
struct inheriter_id : public inheriter_base {
template<typename T>
Partptr createPart(T geometry, Identifier id);
bool hasPart(Identifier id);
Partptr getPart(Identifier id);
};
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
typedef mpl::vector0<> properties;
typedef mpl::vector1<Part> objects;
struct PrepareCluster : public Job<Sys> {
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
PrepareCluster();
virtual void execute(Sys& sys);
};
struct EvaljuateCluster : public Job<Sys> {
typedef typename system_traits<Sys>::Cluster Cluster;
typedef typename system_traits<Sys>::Kernel Kernel;
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
EvaljuateCluster();
virtual void execute(Sys& sys);
};
static void system_init(Sys& sys) {
sys.m_sheduler.addPreprocessJob(new PrepareCluster());
sys.m_sheduler.addPostprocessJob(new EvaljuateCluster());
};
static void system_copy(const Sys& from, Sys& into) {};
};
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
ModulePart<Typelist, ID>::type<Sys>::Part_base::Part_base(T geometry, Sys& system, boost::shared_ptr<Cluster> cluster)
: Object<Sys, Part, PartSignal>(system), m_geometry(geometry), m_cluster(cluster) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Part3D"));
#endif
(typename geometry_traits<T>::modell()).template extract<Kernel,
typename geometry_traits<T>::accessor >(geometry, m_transform);
cluster->template setClusterProperty<typename module3d::fix_prop>(false);
#ifdef USE_LOGGING
BOOST_LOG(log) << "Init: "<<m_transform;
#endif
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Visitor>
typename Visitor::result_type ModulePart<Typelist, ID>::type<Sys>::Part_base::apply(Visitor& vis) {
return boost::apply_visitor(vis, m_geometry);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
ModulePart<Typelist, ID>::type<Sys>::Part_base::addGeometry3D(T geom, CoordinateFrame frame) {
Geom g(new Geometry3D(geom, *m_system));
if(frame == Local)
g->transform(m_transform);
fusion::vector<LocalVertex, GlobalVertex> res = m_cluster->addVertex();
m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
g->template setProperty<typename module3d::vertex_prop>(fusion::at_c<1>(res));
m_system->template objectVector<Geometry3D>().push_back(g);
return g;
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
void ModulePart<Typelist, ID>::type<Sys>::Part_base::set(T geometry) {
Part_base::m_geometry = geometry;
(typename geometry_traits<T>::modell()).template extract<Kernel,
typename geometry_traits<T>::accessor >(geometry, Part_base::m_transform);
};
template<typename Typelist, typename ID>
template<typename Sys>
boost::shared_ptr<typename ModulePart<Typelist, ID>::template type<Sys>::Part>
ModulePart<Typelist, ID>::type<Sys>::Part_base::clone(Sys& newSys) {
//we need to reset the cluster pointer to the new system cluster
LocalVertex lv = Object<Sys, Part, PartSignal>::m_system->m_cluster->getClusterVertex(m_cluster);
GlobalVertex gv = Object<Sys, Part, PartSignal>::m_system->m_cluster->getGlobalVertex(lv);
boost::shared_ptr<Part> np = Object<Sys, Part, PartSignal>::clone(newSys);
//there may be pointer inside the variant
cloner clone_fnc(np->m_geometry);
boost::apply_visitor(clone_fnc, m_geometry);
fusion::vector<LocalVertex, boost::shared_ptr<Cluster>, bool> res = newSys.m_cluster->getLocalVertexGraph(gv);
if(!fusion::at_c<2>(res)) {
//todo: throw
return np;
}
np->m_cluster = fusion::at_c<1>(res)->getVertexCluster(fusion::at_c<0>(res));
return np;
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::Part_base::finishCalculation() {
m_transform.normalize();
apply_visitor vis(m_transform);
apply(vis);
#ifdef USE_LOGGING
BOOST_LOG(log) << "New Value: "<<m_transform;
#endif
//emit the signal for new values
base::template emitSignal<recalculated>(((Part*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::Part_base::fix(bool fix_value) {
m_cluster->template setClusterProperty<typename module3d::fix_prop>(fix_value);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
ModulePart<Typelist, ID>::type<Sys>::Part_id::Part_id(T geometry, Sys& system, boost::shared_ptr<typename Part_base::Cluster> cluster)
: Part_base(geometry, system, cluster) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
ModulePart<Typelist, ID>::type<Sys>::Part_id::addGeometry3D(T geom, Identifier id, CoordinateFrame frame) {
typename Part_base::Geom g = Part_base::addGeometry3D(geom, frame);
g->setIdentifier(id);
return g;
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
void ModulePart<Typelist, ID>::type<Sys>::Part_id::set(T geometry, Identifier id) {
Part_base::set(geometry);
setIdentifier(id);
};
template<typename Typelist, typename ID>
template<typename Sys>
bool ModulePart<Typelist, ID>::type<Sys>::Part_id::hasGeometry3D(Identifier id) {
typename Part_base::Geom g = Part_base::m_system->getGeometry3D(id);
if(!g) return false;
//get the global vertex and check if it is a child of the part cluster
GlobalVertex v = g->template getProperty<typename Part_base::module3d::vertex_prop>();
return Part_base::m_cluster->getLocalVertex(v).second;
};
template<typename Typelist, typename ID>
template<typename Sys>
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
ModulePart<Typelist, ID>::type<Sys>::Part_id::getGeometry3D(Identifier id) {
return Part_base::m_system->getGeometry3D(id);
};
template<typename Typelist, typename ID>
template<typename Sys>
typename ModulePart<Typelist, ID>::template type<Sys>::Identifier&
ModulePart<Typelist, ID>::type<Sys>::Part_id::getIdentifier() {
return this->template getProperty<id_prop<Identifier> >();
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::Part_id::setIdentifier(Identifier id) {
this->template setProperty<id_prop<Identifier> >(id);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
ModulePart<Typelist, ID>::type<Sys>::Part::Part(T geometry, Sys& system, boost::shared_ptr<typename base::Cluster> cluster)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
Part_base, Part_id>::type(geometry, system, cluster) {
};
template<typename Typelist, typename ID>
template<typename Sys>
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
m_this = ((Sys*) this);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::createPart(T geometry) {
typedef typename system_traits<Sys>::Cluster Cluster;
std::pair<boost::shared_ptr<Cluster>, LocalVertex> res = m_this->m_cluster->createCluster();
Partptr p(new Part(geometry, * ((Sys*) this), res.first));
m_this->m_cluster->template setObject<Part> (res.second, p);
m_this->push_back(p);
res.first->template setClusterProperty<type_prop>(clusterPart);
return p;
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::removePart(Partptr p) {
remover r(*m_this);
m_this->m_cluster->removeCluster(p->m_cluster, r);
p->template emitSignal<remove>(p);
m_this->erase(p);
};
template<typename Typelist, typename ID>
template<typename Sys>
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::remover(Sys& s) : system(s) {
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalVertex v) {
Geom g = system.m_cluster->template getObject<Geometry3D>(v);
if(g) {
g->template emitSignal<remove>(g);
system.erase(g);
}
Cons c = system.m_cluster->template getObject<Constraint3D>(v);
if(c) {
c->template emitSignal<remove>(c);
system.erase(c);
}
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalEdge e) {
Cons c = system.m_cluster->template getObject<Constraint3D>(e);
if(c) {
c->template emitSignal<remove>(c);
system.erase(c);
}
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
ModulePart<Typelist, ID>::type<Sys>::inheriter_id::createPart(T geometry, Identifier id) {
Partptr p = inheriter_base::createPart(geometry);
p->setIdentifier(id);
return p;
};
template<typename Typelist, typename ID>
template<typename Sys>
bool ModulePart<Typelist, ID>::type<Sys>::inheriter_id::hasPart(Identifier id) {
if(getPart(id)) return true;
return false;
};
template<typename Typelist, typename ID>
template<typename Sys>
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
ModulePart<Typelist, ID>::type<Sys>::inheriter_id::getPart(Identifier id) {
std::vector< Partptr >& vec = inheriter_base::m_this->template objectVector<Part>();
typedef typename std::vector<Partptr>::iterator iter;
for(iter it=vec.begin(); it!=vec.end(); it++) {
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
};
return Partptr();
};
template<typename Typelist, typename ID>
template<typename Sys>
ModulePart<Typelist, ID>::type<Sys>::PrepareCluster::PrepareCluster() {
Job<Sys>::priority = 1000;
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::PrepareCluster::execute(Sys& sys) {
//get all parts and set their values to the cluster's
typedef typename std::vector<Partptr>::iterator iter;
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
cm.getTransform() = (*it)->m_transform;
};
};
template<typename Typelist, typename ID>
template<typename Sys>
ModulePart<Typelist, ID>::type<Sys>::EvaljuateCluster::EvaljuateCluster() {
Job<Sys>::priority = 1000;
};
template<typename Typelist, typename ID>
template<typename Sys>
void ModulePart<Typelist, ID>::type<Sys>::EvaljuateCluster::execute(Sys& sys) {
//get all parts and set their values to the cluster's
typedef typename std::vector<Partptr>::iterator iter;
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
(*it)->m_transform = cm.getTransform();
(*it)->finishCalculation();
};
};
}
#endif //GCM_MODULEPART_H

View File

@ -0,0 +1,36 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_DEFINES_STATE_H
#define DCM_DEFINES_STATE_H
#include "opendcm/core/property.hpp"
#include "opendcm/core/clustergraph.hpp"
namespace dcm {
namespace details {
struct cluster_vertex_prop {
typedef GlobalVertex type;
typedef cluster_property kind;
};
}
}
#endif

View File

@ -0,0 +1,72 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EDGE_GENERATOR_H
#define DCM_EDGE_GENERATOR_H
#include "property_generator.hpp"
#include "object_generator.hpp"
#include "extractor.hpp"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/include/is_sequence.hpp>
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace dcm {
namespace details {
template<typename Sys>
struct edge_generator : karma::grammar<Iterator, std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >()> {
edge_generator();
karma::rule<Iterator, std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >()> edge_range;
karma::rule<Iterator, fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex>()> edge;
karma::rule<Iterator, std::vector<typename Sys::Cluster::edge_bundle_single>&()> globaledge_range;
karma::rule<Iterator, typename Sys::Cluster::edge_bundle_single()> globaledge;
details::edge_prop_gen<Sys> edge_prop;
details::obj_gen<Sys> objects;
Extractor<Sys> ex;
};
template<typename Sys>
struct vertex_generator : karma::grammar<Iterator, std::vector<typename Sys::Cluster::vertex_bundle>()> {
vertex_generator();
karma::rule<Iterator, std::vector<typename Sys::Cluster::vertex_bundle>()> vertex_range;
karma::rule<Iterator, typename Sys::Cluster::vertex_bundle()> vertex;
details::vertex_prop_gen<Sys> vertex_prop;
details::obj_gen<Sys> objects;
Extractor<Sys> ex;
};
}//details
}//dcm
#ifndef USE_EXTERNAL
#include "edge_vertex_generator_imp.hpp"
#endif
#endif

View File

@ -0,0 +1,57 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EDGE_GENERATOR_IMP_H
#define DCM_EDGE_GENERATOR_IMP_H
#include "edge_vertex_generator.hpp"
namespace dcm {
namespace details {
template<typename Sys>
edge_generator<Sys>::edge_generator() : edge_generator<Sys>::base_type(edge_range) {
globaledge = karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeID, ex, karma::_val, karma::_1)]
<< " source=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeSource, ex, karma::_val, karma::_1)]
<< " target=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeTarget, ex, karma::_val, karma::_1)] << '>'
<< "+" << objects[karma::_1 = phx::at_c<0>(karma::_val)] << "-\n" ;
globaledge_range = *(karma::lit("<GlobalEdge id=")<<globaledge<<karma::lit("</GlobalEdge>"));
edge = karma::lit("source=")<<karma::int_[karma::_1 = phx::at_c<1>(karma::_val)] << " target="<<karma::int_[karma::_1 = phx::at_c<2>(karma::_val)] << ">+"
<< edge_prop[karma::_1 = phx::at_c<0>(phx::at_c<0>(karma::_val))]
<< karma::eol << globaledge_range[karma::_1 = phx::at_c<1>(phx::at_c<0>(karma::_val))] << '-' << karma::eol;
edge_range = (karma::lit("<Edge ") << edge << karma::lit("</Edge>")) % karma::eol;
};
template<typename Sys>
vertex_generator<Sys>::vertex_generator() : vertex_generator<Sys>::base_type(vertex_range) {
vertex = karma::int_ << ">+" << vertex_prop << objects << "-\n";
vertex_range = '\n' << (karma::lit("<Vertex id=") << vertex << karma::lit("</Vertex>")) % karma::eol;
};
}//details
}//dcm
#endif

View File

@ -0,0 +1,71 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EDGE_VERTEX_PARSER_H
#define DCM_EDGE_VERTEX_PARSER_H
#include <boost/spirit/include/qi.hpp>
#include "opendcm/core/clustergraph.hpp"
#include "extractor.hpp"
namespace qi = boost::spirit::qi;
namespace fusion = boost::fusion;
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
namespace details {
template<typename Sys>
struct edge_parser : qi::grammar< IIterator, fusion::vector<LocalEdge, GlobalEdge, bool, bool>(typename Sys::Cluster*, Sys*),
qi::space_type > {
edge_parser();
details::obj_par<Sys> objects;
Injector<Sys> in;
qi::rule<IIterator, fusion::vector<LocalEdge, GlobalEdge, bool, bool>(typename Sys::Cluster*, Sys*), qi::space_type> edge;
qi::rule<IIterator, typename Sys::Cluster::edge_bundle_single(Sys*), qi::space_type> global_edge;
details::edge_prop_par<Sys> edge_prop;
};
template<typename Sys>
struct vertex_parser : qi::grammar< IIterator, fusion::vector<LocalVertex, GlobalVertex>(typename Sys::Cluster*, Sys*),
qi::space_type> {
vertex_parser();
details::obj_par<Sys> objects;
Injector<Sys> in;
qi::rule<IIterator, fusion::vector<LocalVertex, GlobalVertex>(typename Sys::Cluster*, Sys*), qi::space_type> vertex;
details::vertex_prop_par<Sys> prop;
};
}
}
//#ifndef USE_EXTERNAL
//#include "edge_vertex_parser_imp.hpp"
//#endif
#endif

View File

@ -0,0 +1,55 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EDGE_PARSER_IMP_H
#define DCM_EDGE_PARSER_IMP_H
#include "edge_vertex_parser.hpp"
namespace dcm {
namespace details {
template<typename Sys>
edge_parser<Sys>::edge_parser() : edge_parser<Sys>::base_type(edge) {
global_edge = qi::lit("<GlobalEdge") >> qi::lit("id=") >> qi::int_[phx::bind(&GlobalEdge::ID, phx::at_c<1>(qi::_val)) = qi::_1]
>> qi::lit("source=") >> qi::int_[phx::bind(&GlobalEdge::source, phx::at_c<1>(qi::_val)) = qi::_1]
>> qi::lit("target=") >> qi::int_[phx::bind(&GlobalEdge::target, phx::at_c<1>(qi::_val)) = qi::_1] >> '>'
>> objects(qi::_r1)[phx::at_c<0>(qi::_val) = qi::_1] >> "</GlobalEdge>";
edge = (qi::lit("<Edge") >> "source=" >> qi::int_ >> "target=" >> qi::int_ >> '>')[qi::_val = phx::bind((&Sys::Cluster::addEdgeGlobal), qi::_r1, qi::_1, qi::_2)]
>> edge_prop[phx::bind(&Injector<Sys>::setEdgeProperties, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
>> *global_edge(qi::_r2)
>> ("</Edge>");
};
template<typename Sys>
vertex_parser<Sys>::vertex_parser() : vertex_parser<Sys>::base_type(vertex) {
vertex = qi::lit("<Vertex")[phx::bind(&Injector<Sys>::addVertex, in, qi::_r1, qi::_val)] >> qi::lit("id=")
>> qi::int_[phx::at_c<1>(qi::_val) = phx::bind(&Sys::Cluster::setGlobalVertex, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
>> '>' >> prop[phx::bind(&Injector<Sys>::setVertexProperties, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
>> objects(qi::_r2)[phx::bind(&Injector<Sys>::setVertexObjects, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
>> ("</Vertex>");
};
}//details
}//dcm
#endif

View File

@ -0,0 +1,119 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_EXTRACTOR_H
#define DCM_EXTRACTOR_H
#include "defines.hpp"
#include <opendcm/core/clustergraph.hpp>
#include <boost/fusion/include/at_c.hpp>
namespace fusion = boost::fusion;
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
template<typename Sys>
struct Extractor {
typedef typename boost::graph_traits<typename Sys::Cluster>::vertex_iterator viter;
typedef typename boost::graph_traits<typename Sys::Cluster>::edge_iterator eiter;
void getVertexRange(typename Sys::Cluster& cluster, std::vector<typename Sys::Cluster::vertex_bundle>& range) {
std::pair<viter, viter> res = boost::vertices(cluster);
for(; res.first != res.second; res.first++)
range.push_back(cluster[*res.first]);
};
void getEdgeRange(typename Sys::Cluster& cluster,
std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >& range) {
std::pair<eiter, eiter> res = boost::edges(cluster);
for(; res.first != res.second; res.first++)
range.push_back(fusion::make_vector(cluster[*res.first],
cluster.getGlobalVertex(boost::source(*res.first, cluster)),
cluster.getGlobalVertex(boost::target(*res.first, cluster))));
};
void getGlobalEdgeSource(typename Sys::Cluster::edge_bundle_single b, int& source) {
source = fusion::at_c<1>(b).source;
};
void getGlobalEdgeTarget(typename Sys::Cluster::edge_bundle_single b, int& target) {
target = fusion::at_c<1>(b).target;
};
void getGlobalEdgeID(typename Sys::Cluster::edge_bundle_single b, int& id) {
id = fusion::at_c<1>(b).ID;
};
void setVertexID(typename Sys::Cluster* cluster, LocalVertex v, long& l) {
if(v)
l = cluster->getGlobalVertex(v);
else
l = 0;
};
void getClusterRange(typename Sys::Cluster& cluster, std::vector<std::pair<GlobalVertex, typename Sys::Cluster*> >& range) {
typedef typename Sys::Cluster::const_cluster_iterator iter;
for(iter it = cluster.m_clusters.begin(); it != cluster.m_clusters.end(); it++) {
range.push_back( std::make_pair( cluster.getGlobalVertex((*it).first), (*it).second.get() ));
};
};
};
template<typename Sys>
struct Injector {
void setClusterProperties(typename Sys::Cluster* cluster,
typename details::pts<typename Sys::Cluster::cluster_properties>::type& prop) {
cluster->m_cluster_bundle = prop;
};
void setVertexProperties(typename Sys::Cluster* cluster, LocalVertex v,
typename details::pts<typename Sys::vertex_properties>::type& prop) {
fusion::at_c<1>(cluster->operator[](v)) = prop;
};
void setVertexObjects(typename Sys::Cluster* cluster, LocalVertex v,
typename details::sps<typename Sys::objects>::type& obj) {
fusion::at_c<2>(cluster->operator[](v)) = obj;
};
void setEdgeProperties(typename Sys::Cluster* cluster, LocalEdge e,
typename details::pts<typename Sys::edge_properties>::type& prop) {
fusion::at_c<0>(cluster->operator[](e)) = prop;
};
void setVertexProperty(typename Sys::Cluster* cluster, int value) {
cluster->template setClusterProperty<details::cluster_vertex_prop>(value);
};
void addCluster(typename Sys::Cluster* cluster, typename Sys::Cluster* addcl) {
LocalVertex v = cluster->getLocalVertex(addcl->template getClusterProperty<details::cluster_vertex_prop>()).first;
cluster->m_clusters[v] = boost::shared_ptr<typename Sys::Cluster>(addcl);
};
void addVertex(typename Sys::Cluster* cluster, fusion::vector<LocalVertex, GlobalVertex>& vec) {
vec = cluster->addVertex();
};
};
}//namespace dcm
#endif //DCM_GENERATOR_H

View File

@ -0,0 +1,82 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_GENERATOR_H
#define DCM_GENERATOR_H
#include "property_generator.hpp"
#include "edge_vertex_generator.hpp"
#include "extractor.hpp"
#include <opendcm/core/clustergraph.hpp>
#include "traits.hpp"
#include "traits_impl.hpp"
#include "indent.hpp"
#include <boost/mpl/int.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace fusion = boost::fusion;
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
template<typename Sys>
struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
typedef typename Sys::Cluster graph;
typedef typename graph::cluster_bundle graph_bundle;
typedef typename boost::graph_traits<graph>::vertex_iterator viter;
typedef typename boost::graph_traits<graph>::edge_iterator eiter;
generator();
karma::rule<Iterator, graph& ()> start;
karma::rule<Iterator, std::pair<GlobalVertex, graph*>()> cluster_pair;
karma::rule<Iterator, graph&()> cluster;
details::cluster_prop_gen<Sys> cluster_prop;
details::vertex_generator<Sys> vertex_range;
details::edge_generator<Sys> edge_range;
Extractor<Sys> ex;
};
}//namespace dcm
#ifndef USE_EXTERNAL
#include "generator_imp.hpp"
#endif
#endif //DCM_GENERATOR_H

View File

@ -0,0 +1,72 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_GENERATOR_IMP_H
#define DCM_GENERATOR_IMP_H
#include "generator.hpp"
#include "opendcm/core/clustergraph.hpp"
//#include "karma_trans.hpp"
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
BOOST_FUSION_ADAPT_TPL_STRUCT(
(T1)(T2)(T3)(T4),
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
(int, test)
(typename dcm::details::pts<T3>::type, m_cluster_bundle))
namespace boost { namespace spirit { namespace traits
{
template <typename T1, typename T2, typename T3, typename T4>
struct transform_attribute<dcm::ClusterGraph<T1,T2,T3,T4>* const, dcm::ClusterGraph<T1,T2,T3,T4>&, karma::domain>
{
typedef dcm::ClusterGraph<T1,T2,T3,T4>& type;
static type pre(dcm::ClusterGraph<T1,T2,T3,T4>* const& val) {
return *val;
}
};
}}}
namespace dcm {
template<typename Sys>
generator<Sys>::generator() : generator<Sys>::base_type(start) {
cluster %= karma::omit[karma::int_] << cluster_prop << -vertex_range[phx::bind(&Extractor<Sys>::getVertexRange, ex, karma::_val, karma::_1)]
<< -karma::buffer["\n" << edge_range[phx::bind(&Extractor<Sys>::getEdgeRange, ex, karma::_val, karma::_1)]]
<< -karma::buffer["\n" << (cluster_pair % karma::eol)[phx::bind(&Extractor<Sys>::getClusterRange, ex, karma::_val, karma::_1)]] << "-\n"
<< "</Cluster>";
cluster_pair %= karma::lit("<Cluster id=") << karma::int_ << ">+"
<< karma::attr_cast<graph*,graph&>(cluster);
start %= karma::lit("<Cluster id=0>+") << cluster;
};
}//namespace dcm
#endif //DCM_GENERATOR_H

View File

@ -0,0 +1,63 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_INDENT_H
#define DCM_INDENT_H
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/filtering_stream.hpp>
class indent_filter : public boost::iostreams::output_filter {
public:
explicit indent_filter() : indent(0) {};
template<typename Sink>
bool put(Sink& dest, int c) {
if(c == '+') {
indent++;
return true;
} else if(c == '-') {
indent--;
return true;
} else if(c == '\n') {
bool ret = boost::iostreams::put(dest, c);
for(int i=0; (i<indent) && ret; i++) {
ret = boost::iostreams::put(dest, ' ');
ret = boost::iostreams::put(dest, ' ');
}
return ret;
};
indent = (indent < 0) ? 0 : indent;
return boost::iostreams::put(dest, c);
}
template<typename Source>
void close(Source&) {
indent = 0;
}
private:
int indent;
};
#endif //DCM_INDENT_H

View File

@ -0,0 +1,155 @@
/*//////////////////////////////////////////////////////////////////////////////
Copyright (c) 2011 Jamboree
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//////////////////////////////////////////////////////////////////////////////*/
#ifndef BOOST_SPIRIT_REPOSITORY_KARMA_TRANS
#define BOOST_SPIRIT_REPOSITORY_KARMA_TRANS
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost { namespace spirit { namespace repository
{
namespace tag
{
struct trans {};
}
namespace karma
{
// enables trans<T>(f)[...]
template <typename T, typename F>
inline
spirit::stateful_tag_type<F, tag::trans, T> trans(F f)
{
return spirit::stateful_tag_type<F, tag::trans, T>(f);
}
// enables trans(f)[...]
template <typename F>
inline
spirit::stateful_tag_type<F, tag::trans> trans(F f)
{
return spirit::stateful_tag_type<F, tag::trans>(f);
}
}
}}}
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables trans<T>(f)[...]
template <typename F, typename T>
struct use_directive<karma::domain, tag::stateful_tag<F, repository::tag::trans, T> >
: mpl::true_ {};
}} // namespace boost::spirit
namespace boost { namespace spirit { namespace repository {namespace karma
{
template <typename Subject, typename T, typename F>
struct trans_directive
: spirit::karma::unary_generator<trans_directive<Subject, T, F> >
{
typedef Subject subject_type;
template <typename Context, typename Iterator>
struct attribute
: mpl::eval_if
<
is_same<T, unused_type>
, traits::attribute_of<subject_type, Context, Iterator>
, mpl::identity<T>
>
{};
trans_directive(Subject const& subject, F f)
: subject(subject), f(f)
{}
template
<
typename OutputIterator, typename Context
, typename Delimiter, typename Attribute
>
bool generate
(
OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return subject.generate(sink, ctx, d, f(attr));
}
template <typename Context>
info what(Context& context) const
{
return info("trans", subject.what(context));
}
Subject subject;
F f;
};
}}}} // namespace boost::spirit::repository::karma
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename F, typename T, typename Subject, typename Modifiers>
struct make_directive<tag::stateful_tag<F, repository::tag::trans, T>, Subject, Modifiers>
{
typedef repository::karma::trans_directive<Subject, T, F> result_type;
template <typename StatefulTag>
result_type operator()(
StatefulTag const& tag, Subject const& subject, unused_type) const
{
return result_type(subject, tag.data_);
}
};
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T, typename F>
struct has_semantic_action<repository::karma::trans_directive<Subject, T, F> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T, typename F
, typename Attribute, typename Context, typename Iterator>
struct handles_container
<
repository::karma::trans_directive<Subject, T, F>
, Attribute, Context, Iterator
>
: mpl::false_ {}; // FIXME
}}} // namespace boost::spirit::traits
#endif

View File

@ -0,0 +1,98 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_MODULE_STATE_H
#define DCM_MODULE_STATE_H
#include <iosfwd>
#include "indent.hpp"
#include "generator.hpp"
#include "parser.hpp"
#include "defines.hpp"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
namespace qi = boost::spirit::qi;
namespace dcm {
struct ModuleState {
template<typename Sys>
struct type {
typedef Unspecified_Identifier Identifier;
struct inheriter {
inheriter() {
m_this = (Sys*) this;
};
Sys* m_this;
void saveState(std::ostream& stream) {
boost::iostreams::filtering_ostream indent_stream;
indent_stream.push(indent_filter());
indent_stream.push(stream);
std::ostream_iterator<char> out(indent_stream);
generator<Sys> gen;
karma::generate(out, gen, *m_this->m_cluster);
};
void loadState(std::istream& stream) {
//disable skipping of whitespace
stream.unsetf(std::ios::skipws);
// wrap istream into iterator
boost::spirit::istream_iterator begin(stream);
boost::spirit::istream_iterator end;
// use iterator to parse file data
parser<Sys> par;
m_this->clear();
typename Sys::Cluster* cl_ptr = m_this->m_cluster.get();
qi::phrase_parse(begin, end, par(m_this), qi::space, cl_ptr);
};
};
//add only a property to the cluster as we need it to store the clusers global vertex
typedef mpl::vector1<details::cluster_vertex_prop> properties;
typedef mpl::vector0<> objects;
//nothing to do on startup
static void system_init(Sys& sys) {};
};
};
}
#endif //DCM_MODULE_STATE_H

View File

@ -0,0 +1,72 @@
#ifndef DCM_OBJECT_GENERATOR_H
#define DCM_OBJECT_GENERATOR_H
#include "property_generator.hpp"
namespace fusion = boost::fusion;
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
namespace details {
//grammar for a single object
template<typename Sys, typename Object, typename Gen>
struct obj_grammar : public karma::grammar<Iterator, boost::shared_ptr<Object>()> {
typename Gen::generator subrule;
karma::rule<Iterator, boost::shared_ptr<Object>()> start;
details::prop_gen<Sys, typename Object::Sequence > prop;
obj_grammar();
static void getProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq);
};
//when objects should not be generated we need to get a empy rule, as obj_rule_init
//trys always to access the rules attribute and when the parser_generator trait is not
//specialitzed it's impossible to have the attribute type right in the unspecialized trait
template<typename Sys, typename seq, typename state>
struct obj_generator_fold : mpl::fold< seq, state,
mpl::if_< parser_generate<mpl::_2, Sys>,
mpl::push_back<mpl::_1,
obj_grammar<Sys, mpl::_2, dcm::parser_generator<mpl::_2, Sys, Iterator> > >,
mpl::push_back<mpl::_1, details::empty_grammar > > > {};
//currently max. 10 objects are supported
template<typename Sys>
struct obj_gen : public karma::grammar<Iterator, typename details::sps<typename Sys::objects>::type()> {
typedef typename Sys::objects ObjectList;
//create a vector with the appropriate rules for all objects. Do this with the rule init struct, as it gives
//automatic initialisation of the rules when the objects are created
typedef typename obj_generator_fold<Sys, ObjectList,mpl::vector<> >::type init_rules_vector;
//push back a empty rule so that we know where to go when nothing is to do
typedef typename mpl::push_back<init_rules_vector, empty_grammar >::type rules_vector;
//create the fusion sequence of our rules
typedef typename fusion::result_of::as_vector<rules_vector>::type rules_sequnce;
//this struct returns the right accessvalue for the sequences. If we access a value bigger than the property vector size
//we use the last rule, as we made sure this is an empty one
template<int I>
struct index : public mpl::if_< mpl::less<mpl::int_<I>, mpl::size<ObjectList> >,
mpl::int_<I>, typename mpl::size<ObjectList>::prior >::type {};
//this struct tells us if we should execute the generator
template<int I>
struct valid : public mpl::less< mpl::int_<I>, mpl::size<ObjectList> > {};
rules_sequnce rules;
karma::rule<Iterator, typename details::sps<ObjectList>::type()> obj;
obj_gen();
};
} //namespace details
}//dcm
#ifndef USE_EXTERNAL
#include "object_generator_imp.hpp"
#endif
#endif //DCM_OBJECT_GENERATOR_H

View File

@ -0,0 +1,57 @@
#ifndef DCM_OBJECT_GENERATOR_IMP_H
#define DCM_OBJECT_GENERATOR_IMP_H
#include "traits_impl.hpp"
#include "object_generator.hpp"
#include "property_generator_imp.hpp"
using namespace boost::spirit::karma;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace fusion = boost::fusion;
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
namespace details {
template<typename Sys, typename Object, typename Gen>
obj_grammar<Sys, Object,Gen>::obj_grammar() : obj_grammar<Sys, Object,Gen>::base_type(start) {
Gen::init(subrule);
start = lit("\n<Object>") << '+' << eol << subrule
<< prop[phx::bind(&obj_grammar::getProperties, _val, karma::_1)]
<< '-' << eol << lit("</Object>");
};
template<typename Sys, typename Object, typename Gen>
void obj_grammar<Sys, Object,Gen>::getProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq) {
if(ptr) seq = ptr->m_properties;
else {
//TODO: throw
};
};
template<typename Sys>
obj_gen<Sys>::obj_gen() : obj_gen<Sys>::base_type(obj) {
obj = -(eps(valid<0>::value) << eps(phx::at_c<index<0>::value>(_val)) << fusion::at<index<0> >(rules)[karma::_1 = phx::at_c<index<0>::value>(_val)])
<< -(eps(valid<1>::value) << eps(phx::at_c<index<1>::value>(_val)) << fusion::at<index<1> >(rules)[karma::_1 = phx::at_c<index<1>::value>(_val)])
<< -(eps(valid<2>::value) << eps(phx::at_c<index<2>::value>(_val)) << fusion::at<index<2> >(rules)[karma::_1 = phx::at_c<index<2>::value>(_val)])
<< -(eps(valid<3>::value) << eps(phx::at_c<index<3>::value>(_val)) << fusion::at<index<3> >(rules)[karma::_1 = phx::at_c<index<3>::value>(_val)])
<< -(eps(valid<4>::value) << eps(phx::at_c<index<4>::value>(_val)) << fusion::at<index<4> >(rules)[karma::_1 = phx::at_c<index<4>::value>(_val)])
<< -(eps(valid<5>::value) << eps(phx::at_c<index<5>::value>(_val)) << fusion::at<index<5> >(rules)[karma::_1 = phx::at_c<index<5>::value>(_val)])
<< -(eps(valid<6>::value) << eps(phx::at_c<index<6>::value>(_val)) << fusion::at<index<6> >(rules)[karma::_1 = phx::at_c<index<6>::value>(_val)])
<< -(eps(valid<7>::value) << eps(phx::at_c<index<7>::value>(_val)) << fusion::at<index<7> >(rules)[karma::_1 = phx::at_c<index<7>::value>(_val)])
<< -(eps(valid<8>::value) << eps(phx::at_c<index<8>::value>(_val)) << fusion::at<index<8> >(rules)[karma::_1 = phx::at_c<index<8>::value>(_val)])
<< -(eps(valid<9>::value) << eps(phx::at_c<index<9>::value>(_val)) << fusion::at<index<9> >(rules)[karma::_1 = phx::at_c<index<9>::value>(_val)]);
};
} //namespace details
}//dcm
#endif //DCM_OBJECT_GENERATOR_H

View File

@ -0,0 +1,98 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_OBJECT_PARSER_H
#define DCM_OBJECT_PARSER_H
#include "property_parser.hpp"
namespace dcm {
namespace details {
template<typename Obj, typename Sys>
struct empty_obj_parser : public qi::grammar<IIterator, boost::shared_ptr<Obj>(Sys*), qi::space_type> {
qi::rule<IIterator, boost::shared_ptr<Obj>(Sys*), qi::space_type> start;
empty_obj_parser(): empty_obj_parser::base_type(start) {
//start = qi::eps(false);
};
};
//grammar for a single object
template<typename Sys, typename Object, typename Par>
struct obj_parser : public qi::grammar<IIterator, boost::shared_ptr<Object>(Sys*), qi::space_type> {
typename Par::parser subrule;
qi::rule<IIterator, boost::shared_ptr<Object>(Sys*), qi::space_type> start;
prop_par<Sys, typename Object::Sequence > prop;
obj_parser();
static void setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq);
};
//when objects should not be generated we need to get a empy rule, as obj_rule_init
//trys always to access the rules attribute and when the parser_generator trait is not
//specialitzed it's impossible to have the attribute type right in the unspecialized trait
template<typename Sys, typename seq, typename state>
struct obj_parser_fold : mpl::fold< seq, state,
mpl::if_< parser_parse<mpl::_2, Sys>,
mpl::push_back<mpl::_1,
obj_parser<Sys, mpl::_2, dcm::parser_parser<mpl::_2, Sys, IIterator> > >,
mpl::push_back<mpl::_1, empty_obj_parser<mpl::_2, Sys> > > > {};
//currently max. 10 objects are supported
template<typename Sys>
struct obj_par : public qi::grammar<IIterator,
typename details::sps<typename Sys::objects>::type(Sys*),
qi::space_type> {
typedef typename Sys::objects ObjectList;
//create a vector with the appropriate rules for all objects. Do this with the rule init struct, as it gives
//automatic initialisation of the rules when the objects are created
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type init_rules_vector;
//push back a empty rule so that we know where to go when nothing is to do
typedef typename mpl::push_back<init_rules_vector,
empty_obj_parser<typename mpl::back<ObjectList>::type, Sys> >::type rules_vector;
//create the fusion sequence of our rules
typedef typename fusion::result_of::as_vector<rules_vector>::type rules_sequnce;
//this struct returns the right accessvalue for the sequences. If we access a value bigger than the property vector size
//we use the last rule, as we made sure this is an empty one
template<int I>
struct index : public mpl::if_< mpl::less<mpl::int_<I>, mpl::size<ObjectList> >,
mpl::int_<I>, typename mpl::size<ObjectList>::prior >::type {};
//this struct tells us if we should execute the generator
template<int I>
struct valid : public mpl::less< mpl::int_<I>, mpl::size<ObjectList> > {};
rules_sequnce rules;
qi::rule<IIterator, typename details::sps<ObjectList>::type(Sys*), qi::space_type> obj;
obj_par();
};
}//details
}//DCM
#ifndef USE_EXTERNAL
#include "property_parser_imp.hpp"
#endif
#endif

View File

@ -0,0 +1,63 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_OBJECT_PARSER_IMP_H
#define DCM_OBJECT_PARSER_IMP_H
#include "object_parser.hpp"
#include "property_parser_imp.hpp"
namespace dcm {
namespace details {
template<typename Sys, typename Object, typename Par>
obj_parser<Sys, Object, Par>::obj_parser(): obj_parser::base_type(start) {
Par::init(subrule);
start = qi::lit("<Object>") >> subrule(qi::_r1)[qi::_val = qi::_1]
>> qi::eps(qi::_val)[ phx::bind(&Sys::template push_back<Object>, qi::_r1, qi::_val)]
>> prop[phx::bind(&obj_parser::setProperties, qi::_val, qi::_1)]
>> qi::lit("</Object>");
};
template<typename Sys, typename Object, typename Par>
void obj_parser<Sys, Object, Par>::setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq) {
if(ptr) ptr->m_properties = seq;
};
template<typename Sys>
obj_par<Sys>::obj_par(): obj_par<Sys>::base_type(obj) {
obj = -(qi::eps(valid<0>::value) >> fusion::at<index<0> >(rules)(qi::_r1)[phx::at_c<index<0>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<1>::value) >> fusion::at<index<1> >(rules)(qi::_r1)[phx::at_c<index<1>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<2>::value) >> fusion::at<index<2> >(rules)(qi::_r1)[phx::at_c<index<2>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<3>::value) >> fusion::at<index<3> >(rules)(qi::_r1)[phx::at_c<index<3>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<4>::value) >> fusion::at<index<4> >(rules)(qi::_r1)[phx::at_c<index<4>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<5>::value) >> fusion::at<index<5> >(rules)(qi::_r1)[phx::at_c<index<5>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<6>::value) >> fusion::at<index<6> >(rules)(qi::_r1)[phx::at_c<index<6>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<7>::value) >> fusion::at<index<7> >(rules)(qi::_r1)[phx::at_c<index<7>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<8>::value) >> fusion::at<index<8> >(rules)(qi::_r1)[phx::at_c<index<8>::value>(qi::_val) = qi::_1])
>> -(qi::eps(valid<9>::value) >> fusion::at<index<9> >(rules)(qi::_r1)[phx::at_c<index<9>::value>(qi::_val) = qi::_1]);
};
}//details
}//DCM
#endif

View File

@ -0,0 +1,82 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_PARSER_H
#define DCM_PARSER_H
#include <iosfwd>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "opendcm/core/clustergraph.hpp"
#include "property_parser.hpp"
#include "object_parser.hpp"
#include "edge_vertex_parser.hpp"
#include "extractor.hpp"
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
struct sp : qi::grammar<IIterator, std::string()> {
qi::rule<IIterator, std::string()> start;
sp() : sp::base_type(start) {
start %= +qi::char_;
};
static void print(std::string s) {
std::cout<<"parsed string:"<<std::endl<<s<<std::endl<<"done print string"<<std::endl;
};
};
template<typename Sys>
struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<int>, qi::space_type> {
typedef typename Sys::Cluster graph;
parser();
qi::rule<IIterator, graph*(Sys*), qi::locals<int>, qi::space_type> cluster;
details::cluster_prop_par<Sys> cluster_prop;
details::obj_par<Sys> objects;
details::vertex_parser<Sys> vertex;
details::edge_parser<Sys> edge;
sp str;
Injector<Sys> in;
};
}
#ifndef USE_EXTERNAL
#include "parser_imp.hpp"
#endif
#endif //DCM_PARSER_H

View File

@ -0,0 +1,71 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_PARSER_IMP_H
#define DCM_PARSER_IMP_H
#include <boost/spirit/include/qi_attr_cast.hpp>
#include "opendcm/core/system.hpp"
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
BOOST_FUSION_ADAPT_TPL_STRUCT(
(T1)(T2)(T3)(T4),
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
(typename dcm::details::pts<T3>::type, m_cluster_bundle))
#include "parser.hpp"
namespace boost { namespace spirit { namespace traits
{
template <typename T1, typename T2, typename T3, typename T4>
struct transform_attribute<dcm::ClusterGraph<T1,T2,T3,T4>*, dcm::ClusterGraph<T1,T2,T3,T4>, qi::domain>
{
typedef dcm::ClusterGraph<T1,T2,T3,T4>& type;
static type pre(dcm::ClusterGraph<T1,T2,T3,T4>* const& val) {
return *val;
}
static void post(dcm::ClusterGraph<T1,T2,T3,T4>* const& val, dcm::ClusterGraph<T1,T2,T3,T4> const& attr) {}
static void fail(dcm::ClusterGraph<T1,T2,T3,T4>* const&) {}
};
}}}
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
template<typename Sys>
parser<Sys>::parser() : parser<Sys>::base_type(cluster) {
cluster %= qi::lit("<Cluster id=") >> qi::omit[qi::int_[qi::_a = qi::_1]] >> ">"
>> -(qi::eps( qi::_a > 0 )[qi::_val = phx::new_<typename Sys::Cluster>()])
>> qi::eps[phx::bind(&Injector<Sys>::setVertexProperty, in, qi::_val, qi::_a)]
>> qi::attr_cast<graph*, graph>(cluster_prop >> qi::eps)
>> qi::omit[*vertex(qi::_val, qi::_r1)]
>> qi::omit[*edge(qi::_val, qi::_r1)]
>> qi::omit[*(cluster(qi::_r1)[phx::bind(&Injector<Sys>::addCluster, in, qi::_val, qi::_1)])]
>> "</Cluster>";// >> str[&sp::print];
};
}
#endif //DCM_PARSER_H

View File

@ -0,0 +1,102 @@
#ifndef DCM_PROPERTY_GENERATOR_H
#define DCM_PROPERTY_GENERATOR_H
#include <boost/fusion/include/as_vector.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/less_equal.hpp>
#include "traits.hpp"
namespace karma = boost::spirit::karma;
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
namespace details {
//a grammar that does nothing exept failing
struct empty_grammar : public karma::grammar<Iterator> {
karma::rule<Iterator> start;
empty_grammar(): empty_grammar::base_type(start) {
start = karma::eps(true);
};
empty_grammar(const empty_grammar& other) : empty_grammar::base_type(start) {};
};
template<typename Prop>
struct skip_grammar : public karma::grammar<Iterator, typename Prop::type&()> {
karma::rule<Iterator, typename Prop::type&()> start;
skip_grammar() : skip_grammar<Prop>::base_type(start) {
start = karma::eps(true);
};
skip_grammar(const skip_grammar& other) : skip_grammar::base_type(start) {};
};
//grammar for a single property
template<typename Prop, typename Gen>
struct prop_grammar : public karma::grammar<Iterator, typename Prop::type&()> {
typename Gen::generator subrule;
karma::rule<Iterator, typename Prop::type&()> start;
prop_grammar();
prop_grammar(const prop_grammar& other) : prop_grammar::base_type(start) {};
};
template<typename Sys, typename seq, typename state>
struct prop_generator_fold : mpl::fold< seq, state,
mpl::if_< parser_generate<mpl::_2, Sys>,
mpl::push_back<mpl::_1,
prop_grammar<mpl::_2, dcm::parser_generator<mpl::_2, Sys, Iterator> > >,
mpl::push_back<mpl::_1, skip_grammar<mpl::_2> > > > {};
//grammar for a fusion sequence of properties. currently max. 10 properties are supported
template<typename Sys, typename PropertyList>
struct prop_gen : karma::grammar<Iterator, typename details::pts<PropertyList>::type&()> {
//create a vector with the appropriate rules for all properties.
typedef typename prop_generator_fold<Sys, PropertyList, mpl::vector<> >::type init_rules_sequence;
//allow max 10 types as the following code expect this
BOOST_MPL_ASSERT((mpl::less_equal< mpl::size<init_rules_sequence>, mpl::int_<10> >));
//we want to process 10 elements, so create a vector with (10-prop.size()) empty rules
//and append it to our rules vector
typedef mpl::range_c<int,0, mpl::minus< mpl::int_<10>, mpl::size<init_rules_sequence> >::value > range;
typedef typename mpl::fold< range,
init_rules_sequence,
mpl::push_back<mpl::_1, empty_grammar> >::type rules_sequence;
typename fusion::result_of::as_vector<rules_sequence>::type rules;
karma::rule<Iterator, typename details::pts<PropertyList>::type&()> prop;
prop_gen();
};
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
template<typename Sys>
struct cluster_prop_gen : public prop_gen<Sys, typename Sys::Cluster::cluster_properties> {
cluster_prop_gen();
};
template<typename Sys>
struct vertex_prop_gen : public prop_gen<Sys, typename Sys::Cluster::vertex_properties> {
vertex_prop_gen();
};
template<typename Sys>
struct edge_prop_gen : public prop_gen<Sys, typename Sys::Cluster::edge_properties> {
edge_prop_gen();
};
}//details
}//dcm
#ifndef USE_EXTERNAL
#include "property_generator_imp.hpp"
#endif
#endif //DCM_PROPERTY_GENERATOR_H

View File

@ -0,0 +1,43 @@
#ifndef DCM_PROPERTY_GENERATOR_IMP_H
#define DCM_PROPERTY_GENERATOR_IMP_H
#include "property_generator.hpp"
#include "traits_impl.hpp"
namespace dcm {
typedef std::ostream_iterator<char> Iterator;
namespace details {
//grammar for a single property
template<typename Prop, typename Gen>
prop_grammar<Prop, Gen>::prop_grammar() : prop_grammar<Prop, Gen>::base_type(start) {
Gen::init(subrule);
start = karma::lit("\n<Property>") << '+' << karma::eol << subrule
<< '-' << karma::eol << karma::lit("</Property>");
};
template<typename Sys, typename PropertyList>
prop_gen<Sys, PropertyList>::prop_gen() : prop_gen<Sys, PropertyList>::base_type(prop) {
prop = fusion::at_c<0>(rules) << fusion::at_c<1>(rules) << fusion::at_c<2>(rules)
<< fusion::at_c<3>(rules) << fusion::at_c<4>(rules) << fusion::at_c<5>(rules)
<< fusion::at_c<6>(rules) << fusion::at_c<7>(rules) << fusion::at_c<8>(rules)
<< fusion::at_c<9>(rules);
};
template<typename Sys>
cluster_prop_gen<Sys>::cluster_prop_gen() : prop_gen<Sys, typename Sys::Cluster::cluster_properties>() {};
template<typename Sys>
vertex_prop_gen<Sys>::vertex_prop_gen() : prop_gen<Sys, typename Sys::Cluster::vertex_properties>() {};
template<typename Sys>
edge_prop_gen<Sys>::edge_prop_gen() : prop_gen<Sys, typename Sys::Cluster::edge_properties>() {};
}//details
}//dcm
#endif //DCM_PROPERTY_GENERATOR_H

View File

@ -0,0 +1,120 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_PROPERTY_PARSER_H
#define DCM_PROPERTY_PARSER_H
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/int.hpp>
namespace fusion = boost::fusion;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
namespace mpl = boost::mpl;
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
namespace details {
struct empty_parser : public qi::grammar<IIterator> {
qi::rule<IIterator> start;
empty_parser(): empty_parser::base_type(start) {
start = qi::eps(true);
};
empty_parser(const empty_parser& other) : empty_parser::base_type(start) {};
};
template<typename Prop>
struct skip_parser : public qi::grammar<IIterator, typename Prop::type()> {
qi::rule<IIterator, typename Prop::type()> start;
skip_parser() : skip_parser<Prop>::base_type(start) {
start = qi::eps(true);
};
skip_parser(const skip_parser& other) : skip_parser::base_type(start) {};
};
template<typename Prop, typename Par>
struct prop_parser : qi::grammar<IIterator, typename Prop::type(), qi::space_type> {
typename Par::parser subrule;
qi::rule<IIterator, typename Prop::type(), qi::space_type> start;
prop_parser();
prop_parser(const prop_parser& other) : prop_parser::base_type(start) {};
};
template<typename Sys, typename seq, typename state>
struct prop_parser_fold : mpl::fold< seq, state,
mpl::if_< dcm::parser_parse<mpl::_2, Sys>,
mpl::push_back<mpl::_1,
prop_parser<mpl::_2, dcm::parser_parser<mpl::_2, Sys, IIterator> > >,
mpl::push_back<mpl::_1, skip_parser<mpl::_2> > > > {};
//grammar for a fusion sequence of properties. currently max. 10 properties are supported
template<typename Sys, typename PropertyList>
struct prop_par : qi::grammar<IIterator, typename details::pts<PropertyList>::type(), qi::space_type> {
//create a vector with the appropriate rules for all properties.
typedef typename prop_parser_fold<Sys, PropertyList, mpl::vector<> >::type init_rules_sequence;
//allow max 10 types as the following code expect this
BOOST_MPL_ASSERT((mpl::less_equal< mpl::size<init_rules_sequence>, mpl::int_<10> >));
//we want to process 10 elements, so create a vector with (10-prop.size()) empty rules
//and append it to our rules vector
typedef mpl::range_c<int,0, mpl::minus< mpl::int_<10>, mpl::size<init_rules_sequence> >::value > range;
typedef typename mpl::fold< range,
init_rules_sequence,
mpl::push_back<mpl::_1, empty_parser> >::type rules_sequence;
typename fusion::result_of::as_vector<rules_sequence>::type rules;
qi::rule<IIterator, typename details::pts<PropertyList>::type(), qi::space_type> prop;
prop_par();
};
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
template<typename Sys>
struct cluster_prop_par : public prop_par<Sys, typename Sys::Cluster::cluster_properties> {
cluster_prop_par();
};
template<typename Sys>
struct vertex_prop_par : public prop_par<Sys, typename Sys::Cluster::vertex_properties> {
vertex_prop_par();
};
template<typename Sys>
struct edge_prop_par : public prop_par<Sys, typename Sys::Cluster::edge_properties> {
edge_prop_par();
};
} //DCM
} //details
#ifndef USE_EXTERNAL
#include "property_parser_imp.hpp"
#endif
#endif

View File

@ -0,0 +1,60 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_PROPERTY_PARSER_IMP_H
#define DCM_PROPERTY_PARSER_IMP_H
#include "property_parser.hpp"
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
namespace details {
template<typename Prop, typename Par>
prop_parser<Prop, Par>::prop_parser() : prop_parser<Prop, Par>::base_type(start) {
Par::init(subrule);
start %= qi::lit("<Property>") >> subrule >> qi::lit("</Property>");
};
template<typename Sys, typename PropertyList>
prop_par<Sys, PropertyList>::prop_par() : prop_par<Sys, PropertyList>::base_type(prop) {
prop %= fusion::at_c<0>(rules) >> fusion::at_c<1>(rules) >> fusion::at_c<2>(rules)
>> fusion::at_c<3>(rules) >> fusion::at_c<4>(rules) >> fusion::at_c<5>(rules)
>> fusion::at_c<6>(rules) >> fusion::at_c<7>(rules) >> fusion::at_c<8>(rules)
>> fusion::at_c<9>(rules);
};
template<typename Sys>
cluster_prop_par<Sys>::cluster_prop_par() : prop_par<Sys, typename Sys::Cluster::cluster_properties>() {};
template<typename Sys>
vertex_prop_par<Sys>::vertex_prop_par() : prop_par<Sys, typename Sys::Cluster::vertex_properties>() {};
template<typename Sys>
edge_prop_par<Sys>::edge_prop_par() : prop_par<Sys, typename Sys::Cluster::edge_properties>() {};
} //DCM
} //details
#endif

View File

@ -0,0 +1,53 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_PARSER_TRAITS_H
#define DCM_PARSER_TRAITS_H
#include <boost/mpl/bool.hpp>
#include <assert.h>
namespace dcm {
template<typename type, typename System>
struct parser_generate : public boost::mpl::false_ {};
template<typename type, typename System, typename iterator>
struct parser_generator {
typedef int generator;
static void init(generator& r) {
assert(false);
};
};
template<typename type, typename System>
struct parser_parse : public boost::mpl::false_ {};
template<typename type, typename System, typename iterator>
struct parser_parser {
typedef int parser;
static void init(parser& r) {
assert(false);
};
};
}
#endif //DCM_PARSER_TRAITS_H

View File

@ -0,0 +1,160 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//move the traits specializations outside of the traits definition to avoid the spirit header parsing every
//time this module is included and just parse it in externalisation mode when the generator is build
#ifndef DCM_PARSER_TRAITS_IMPL_H
#define DCM_PARSER_TRAITS_IMPL_H
#include "traits.hpp"
#include "defines.hpp"
#include <boost/mpl/bool.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/karma_string.hpp>
#include <boost/spirit/include/karma_int.hpp>
#include <boost/spirit/include/karma_bool.hpp>
#include <boost/spirit/include/karma_rule.hpp>
#include <boost/spirit/include/karma_auto.hpp>
namespace karma = boost::spirit::karma;
namespace qi = boost::spirit::qi;
namespace boost {
namespace spirit {
namespace traits {
template <>
struct create_generator<dcm::No_Identifier> {
typedef BOOST_TYPEOF(karma::eps(false)) type;
static type call() {
return karma::eps(false);
}
};
}
}
}
namespace dcm {
template<typename System>
struct parser_generate<type_prop, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator<type_prop, System, iterator> {
typedef karma::rule<iterator, int&()> generator;
static void init(generator& r) {
r = karma::lit("<type>clustertype</type>\n<value>") << karma::int_ <<"</value>";
};
};
template<typename System>
struct parser_generate<changed_prop, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator<changed_prop, System, iterator> {
typedef karma::rule<iterator, bool&()> generator;
static void init(generator& r) {
r = karma::lit("<type>clusterchanged</type>\n<value>") << karma::bool_ <<"</value>";
};
};
template<typename System>
struct parser_generate<id_prop<typename System::Identifier>, System>
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
template<typename System, typename iterator>
struct parser_generator<id_prop<typename System::Identifier>, System, iterator> {
typedef karma::rule<iterator, typename System::Identifier()> generator;
static void init(generator& r) {
r = karma::lit("<type>id</type>\n<value>") << karma::auto_ <<"</value>";
};
};
template<typename System>
struct parser_parse<type_prop, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser<type_prop, System, iterator> {
typedef qi::rule<iterator, int(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>clustertype</type>") >> ("<value>") >> qi::int_ >>"</value>";
};
};
template<typename System>
struct parser_parse<changed_prop, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser<changed_prop, System, iterator> {
typedef qi::rule<iterator, bool(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>clusterchanged</type>") >> ("<value>") >> qi::bool_ >>"</value>";
};
};
template<typename System>
struct parser_parse<id_prop<typename System::Identifier>, System>
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
template<typename System, typename iterator>
struct parser_parser<id_prop<typename System::Identifier>, System, iterator> {
typedef qi::rule<iterator, typename System::Identifier(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::auto_ >>"</value>";
};
};
/*
template<typename System>
struct parser_generate<details::cluster_vertex_prop, System>
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator<details::cluster_vertex_prop, System, iterator> {
typedef karma::rule<iterator, int()> generator;
static void init(generator& r) {
r = karma::lit("<type>id</type>\n<value>") << karma::int_ <<"</value>";
};
};
template<typename System>
struct parser_parse<details::cluster_vertex_prop, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser<details::cluster_vertex_prop, System, iterator> {
typedef qi::rule<iterator, int(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::int_ >>"</value>";
};
};*/
} //namespace dcm
#endif //DCM_PARSER_TRAITS_IMPL_H

View File

@ -0,0 +1,29 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_MODULEPART_H
#define DCM_MODULEPART_H
#define DCM_USE_MODULEPART
#include "modulePart/geometry.hpp"
#include "modulePart/module.hpp"
#endif //DCM_MODULEPART_H

View File

@ -0,0 +1,29 @@
/*
openDCM, dimensional constraint manager
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef DCM_MODULEPARSER_H
#define DCM_MODULEPARSER_H
#define DCM_USE_MODULESTATE
#include "moduleState/module.hpp"
#include "moduleState/traits.hpp"
#endif //DCM_MODULEPARSER_H