new openDCM version

This commit is contained in:
Stefan Tröger
2013-12-19 06:55:41 +01:00
parent 9d196708b1
commit d4fdb92957
62 changed files with 7298 additions and 4850 deletions

View File

@@ -43,5 +43,14 @@
#include "core/kernel.hpp"
#include "core/system.hpp"
#ifdef DCM_EXTERNAL_CORE
#define DCM_EXTERNAL_CORE_INCLUDE_01 "opendcm/core/imp/system_imp.hpp"
#define DCM_EXTERNAL_CORE_01( Sys )\
template class dcm::System<Sys::Kernel, Sys::Module1, Sys::Module2, Sys::Module3>; \
#endif //external
#endif //DCM_CORE_H

File diff suppressed because it is too large Load Diff

View File

@@ -24,9 +24,6 @@
#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>
@@ -36,13 +33,7 @@
#include <boost/mpl/for_each.hpp>
#include <boost/any.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 <boost/preprocessor.hpp>
@@ -61,8 +52,8 @@ namespace detail {
//metafunction to avoid ot-of-range access of mpl sequences
template<typename Sequence, int Value>
struct in_range_value {
typedef typename mpl::prior<mpl::size<Sequence> >::type last_id;
typedef typename mpl::min< mpl::int_<Value>, last_id>::type type;
typedef typename mpl::prior<mpl::size<Sequence> >::type last_id;
typedef typename mpl::min< mpl::int_<Value>, last_id>::type type;
};
//type erasure container for constraints
@@ -119,22 +110,10 @@ protected:
inline void intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_);
int equationCount();
template< typename creator_type>
void resetType(creator_type& c);
int equationCount();
void calculate(Scalar scale, bool rotation_only = false);
void treatLGZ();
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
@@ -174,9 +153,13 @@ protected:
int value;
public:
template< typename ConstraintVector, typename EquationVector>
template< typename ConstraintVector, typename tag1, typename tag2>
struct holder : public placeholder {
//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, tag1, tag2> > >::type EquationVector;
//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;
@@ -309,9 +292,7 @@ public:
virtual void collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
virtual placeholder* clone();
virtual int equationCount();
virtual void disable() {
fusion::for_each(m_sets, disabler());
};
virtual void disable();
virtual std::vector<boost::any> getGenericEquations();
virtual std::vector<boost::any> getGenericConstraints();
@@ -330,599 +311,14 @@ public:
geom_ptr first, second;
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys, int Dim>
Constraint<Sys, Dim>::Constraint(geom_ptr f, geom_ptr s)
: first(f), second(s), content(0) {
//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, int Dim>
Constraint<Sys, Dim>::~Constraint() {
delete content;
//first->template disconnectSignal<reset>(cf);
//second->template disconnectSignal<reset>(cs);
};
template<typename Sys, int Dim>
template<typename tag1, typename tag2, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFromTags(ConstraintVector& v) {
typedef tag_order< tag1, tag2 > 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
content = new holder<ConstraintVector, EquationVector>(v);
//geometry order needs to be the one needed by equations
if(order::swapt::value)
first.swap(second);
};
template<typename Sys, int Dim>
template<typename ConstraintVector>
void Constraint<Sys, Dim>::initialize(ConstraintVector& cv) {
//use the compile time unrolling to retrieve the geometry tags
initializeFirstGeometry<mpl::int_<0> >(cv, mpl::true_());
};
template<typename Sys, int Dim>
int Constraint<Sys, Dim>::equationCount() {
return content->equationCount();
};
template<typename Sys, int Dim>
template< typename creator_type>
void Constraint<Sys, Dim>::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, int Dim>
void Constraint<Sys, Dim>::calculate(Scalar scale, bool rotation_only) {
content->calculate(first, second, scale, rotation_only);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::treatLGZ() {
content->treatLGZ(first, second);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::setMaps(MES& mes) {
content->setMaps(mes, first, second);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
content->collectPseudoPoints(first, second, vec1, vec2);
};
template<typename Sys, int Dim>
std::vector<boost::any> Constraint<Sys, Dim>::getGenericEquations() {
return content->getGenericEquations();
};
template<typename Sys, int Dim>
std::vector<boost::any> Constraint<Sys, Dim>::getGenericConstraints() {
return content->getGenericConstraints();
};
template<typename Sys, int Dim>
std::vector<const std::type_info*> Constraint<Sys, Dim>::getEquationTypes() {
return content->getEquationTypes();
};
template<typename Sys, int Dim>
std::vector<const std::type_info*> Constraint<Sys, Dim>::getConstraintTypes() {
return content->getConstraintTypes();
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template<typename T>
typename boost::enable_if<typename Constraint<Sys, Dim>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type, void>::type
Constraint<Sys, Dim>::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 > >));
fusion::copy(fusion::at<distance>(objects).values, val.m_eq.values);
val.pure_rotation = fusion::at<distance>(objects).pure_rotation;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template<typename T>
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Dim>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type>, void>::type
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only)
: first(f), second(s), scale(sc), rot_only(rotation_only) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Calculater::operator()(T& val) const {
//if the equation is disabled we don't have anything mapped so avoid accessing it
if(!val.enabled)
return;
//if we only need pure rotational functions and we are not such a nice thing, everything becomes 0
if(rot_only && !val.pure_rotation) {
val.m_residual(0) = 0;
if(first->getClusterMode()) {
if(!first->isClusterFixed()) {
val.m_diff_first_rot.setZero();
val.m_diff_first.setZero();
}
}
else
val.m_diff_first.setZero();
if(second->getClusterMode()) {
if(!second->isClusterFixed()) {
val.m_diff_second_rot.setZero();
val.m_diff_second.setZero();
}
}
else
val.m_diff_second.setZero();
}
//we need to calculate, so lets go for it!
else {
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<3; i++) {
val.m_diff_first_rot(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, first->m_diffparam.col(i));
}
//and now with the translations
for(int i=0; i<3; i++) {
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, first->m_diffparam.col(i+3));
}
}
}
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<3; i++) {
val.m_diff_second_rot(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
second->m_parameter, second->m_diffparam.col(i));
}
//and the translation seperated
for(int i=0; i<3; i++) {
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
second->m_parameter, second->m_diffparam.col(i+3));
}
}
}
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, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
: mes(m), first(f), second(s) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::MapSetter::operator()(T& val) const {
if(!val.enabled)
return;
//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_rot, 3, val.m_diff_first_rot);
mes.setJacobiMap(equation, first->m_offset, 3, 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_rot, 3, val.m_diff_second_rot);
mes.setJacobiMap(equation, second->m_offset, 3, val.m_diff_second);
}
}
else
mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::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, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::PseudoCollector::operator()(T& val) const {
if(!val.enabled)
return;
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, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::LGZ::LGZ(geom_ptr f, geom_ptr s)
: first(f), second(s) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::LGZ::operator()(T& val) const {
typedef typename Sys::Kernel Kernel;
if(!val.enabled)
return;
//to treat local gradient zeros we calculate a approximate second derivative of the equations
//only do that if neseccary: residual is not zero
if(!Kernel::isSame(val.m_residual(0),0, 1e-7)) { //TODO: use exact precission and scale value
//rotations exist only in cluster
if(first->getClusterMode() && !first->isClusterFixed()) {
//LGZ exists for rotations only
for(int i=0; i<3; i++) {
//only treat if the gradient realy is zero
if(Kernel::isSame(val.m_diff_first_rot(i), 0, 1e-7)) {
//to get the approximated second derivative we need the slightly moved geometrie
const typename Kernel::Vector p_old = first->m_parameter;
first->m_parameter += first->m_diffparam.col(i)*1e-3;
first->normalize();
//with this changed geometrie we test if a gradient exist now
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, block);
first->m_parameter = p_old;
//let's see if the initial LGZ was a real one
if(!Kernel::isSame(res, 0, 1e-7)) {
//is a fake zero, let's correct it
val.m_diff_first_rot(i) = res;
};
};
};
}
//and the same for the second one too
if(second->getClusterMode() && !second->isClusterFixed()) {
for(int i=0; i<3; i++) {
//only treat if the gradient realy is zero
if(Kernel::isSame(val.m_diff_second_rot(i), 0, 1e-7)) {
//to get the approximated second derivative we need the slightly moved geometrie
const typename Kernel::Vector p_old = second->m_parameter;
second->m_parameter += second->m_diffparam.col(i)*1e-3;
second->normalize();
//with this changed geometrie we test if a gradient exist now
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, block);
second->m_parameter = p_old;
//let's see if the initial LGZ was a real one
if(!Kernel::isSame(res, 0, 1e-7)) {
//is a fake zero, let's correct it
val.m_diff_second_rot(i) = res;
};
};
};
};
};
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericEquations::GenericEquations(std::vector<boost::any>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericEquations::operator()(T& val) const {
vec.push_back(val.m_eq);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericConstraints::GenericConstraints(std::vector<boost::any>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericConstraints::operator()(T& val) const {
vec.push_back(val);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Types::Types(std::vector<const std::type_info*>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Types::operator()(T& val) const {
vec.push_back(&typeid(T));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::holder(Objects& obj) : m_objects(obj) {
//set the initial values in the equations
fusion::for_each(m_sets, OptionSetter(obj));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::calculate(geom_ptr first, geom_ptr second,
Scalar scale, bool rotation_only) {
fusion::for_each(m_sets, Calculater(first, second, scale, rotation_only));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::treatLGZ(geom_ptr first, geom_ptr second) {
fusion::for_each(m_sets, LGZ(first, second));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
typename Constraint<Sys, Dim>::placeholder*
Constraint<Sys, Dim>::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, int Dim>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
fusion::for_each(m_sets, MapSetter(mes, first, second));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
void Constraint<Sys, Dim>::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, int Dim>
template<typename ConstraintVector, typename EquationVector>
typename Constraint<Sys, Dim>::placeholder*
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::clone() {
return new holder(*this);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
int Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::equationCount() {
int count = 0;
EquationCounter counter(count);
fusion::for_each(m_sets, counter);
return count;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
std::vector<boost::any>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getGenericEquations() {
std::vector<boost::any> vec;
fusion::for_each(m_sets, GenericEquations(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
std::vector<boost::any>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getGenericConstraints() {
std::vector<boost::any> vec;
fusion::for_each(m_objects, GenericConstraints(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
std::vector<const std::type_info*>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getEquationTypes() {
std::vector<const std::type_info*> vec;
mpl::for_each< EquationVector >(Types(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename EquationVector>
std::vector<const std::type_info*>
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getConstraintTypes() {
std::vector<const std::type_info*> vec;
mpl::for_each< ConstraintVector >(Types(vec));
return vec;
};
/****************************************************************/
/** compiletime unrolled geometry initialising */
/****************************************************************/
template<typename Sys, int Dim>
template<typename WhichType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
//this function is only for breaking the compilation loop, it should never be called
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
};
template<typename Sys, int Dim>
template<typename WhichType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
typedef typename Sys::geometries geometries;
switch(first->getExactType()) {
#ifdef BOOST_PP_LOCAL_ITERATE
#define BOOST_PP_LOCAL_MACRO(n) \
case (WhichType::value + n): \
return initializeSecondGeometry<boost::mpl::int_<0>,\
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
break;
#define BOOST_PP_LOCAL_LIMITS (0, 10)
#include BOOST_PP_LOCAL_ITERATE()
#endif //BOOST_PP_LOCAL_ITERATE
default:
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
return initializeFirstGeometry<next_which_t, ConstraintVector> (cv,
typename mpl::less< next_which_t, typename mpl::size<geometries>::type >::type());
}
};
template<typename Sys, int Dim>
template<typename WhichType, typename FirstType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
//this function is only for breaking the compilation loop, it should never be called
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
};
template<typename Sys, int Dim>
template<typename WhichType, typename FirstType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
typedef typename Sys::geometries geometries;
switch(second->getExactType()) {
#ifdef BOOST_PP_LOCAL_ITERATE
#define BOOST_PP_LOCAL_MACRO(n) \
case (WhichType::value + n): \
return intitalizeFinalize<FirstType, \
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
break;
#define BOOST_PP_LOCAL_LIMITS (0, 10)
#include BOOST_PP_LOCAL_ITERATE()
#endif //BOOST_PP_LOCAL_ITERATE
default:
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
return initializeSecondGeometry<next_which_t, FirstType, ConstraintVector>
(cv, typename mpl::less
< next_which_t
, typename mpl::size<geometries>::type>::type()
);
}
};
template<typename Sys, int Dim>
template<typename FirstType, typename SecondType, typename ConstraintVector>
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_ /*is_unrolled_t*/) {
initializeFromTags<FirstType, SecondType>(cv);
};
template<typename Sys, int Dim>
template<typename FirstType, typename SecondType, typename ConstraintVector>
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_ /*is_unrolled_t*/) {
//Should never be here at runtime; only required to block code generation that deref's the sequence out of bounds
BOOST_ASSERT(false);
}
};//detail
};//dcm
#ifndef DCM_EXTERNAL_CORE
#include "imp/constraint_imp.hpp"
#include "imp/constraint_holder_imp.hpp"
#endif
#endif //GCM_CONSTRAINT_H

View File

@@ -25,21 +25,13 @@
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/iterator_range.hpp>
#include <boost/fusion/include/copy.hpp>
#include <boost/fusion/include/advance.hpp>
#include <boost/fusion/include/back.hpp>
#include <boost/fusion/include/iterator_range.hpp>
#include <boost/fusion/include/nview.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/as_map.hpp>
#include <boost/fusion/include/at_key.hpp>
#include <boost/fusion/include/filter_view.hpp>
#include <boost/exception/exception.hpp>
namespace fusion = boost::fusion;
@@ -82,8 +74,8 @@ struct PseudoScale {
//type to allow a metaprogramming check for a Equation
struct EQ {};
template<typename Seq, typename T>
struct pushed_seq;
//template<typename Seq, typename T>
//struct pushed_seq;
//metafunctions to retrieve the options of an equation
template<typename T>
@@ -112,66 +104,17 @@ struct constraint_sequence : public seq {
std::cout<<"pretty: "<<__PRETTY_FUNCTION__<<std::endl;
};
//an equation gets added to this sequence
template<typename T>
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type operator &(T& val) {
typedef typename pushed_seq<seq, T>::type Sequence;
typedef typename fusion::result_of::begin<Sequence>::type Begin;
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<seq, T>::S1>::type >::type EndOld;
//create the new sequence
Sequence vec;
//copy the old values into the new sequence
Begin b(vec);
EndOld eo(vec);
fusion::iterator_range<Begin, EndOld> range(b, eo);
fusion::copy(*this, range);
//insert this object at the end of the sequence
*fusion::find<T>(vec) = val;
//and return our new extendet sequence
return vec;
};
//an sequence gets added to this sequence (happens only if sequenced equations like coincident are used)
template<typename T>
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type operator &(T& val) {
typedef typename pushed_seq<T, seq>::type Sequence;
typedef typename fusion::result_of::begin<Sequence>::type Begin;
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<T, seq>::S1>::type >::type EndF;
//create the new sequence
Sequence vec;
Begin b(vec);
EndF ef(vec);
fusion::iterator_range<Begin, EndF> range(b, ef);
fusion::copy(val, range);
//to copy the types of the second sequence is not as easy as before. If types were already present in
//the original sequence they are not added again. therefore we need to find all types of the second sequence
//in the new one and assign the objects to this positions.
//get a index vector for all second-sequence-elements
typedef typename mpl::transform<typename pushed_seq<T, seq>::S2,
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
//and copy the types in
fusion::nview<Sequence, position_vector> view(vec);
fusion::copy(*this, view);
//and return our new extendet sequence
return vec;
};
//dont allow expression equation stacking: the compile time impact is huge if we want to allow
//text parsing
/*
//an equation gets added to this sequence
template<typename T>
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type operator &(T& val);
//an sequence gets added to this sequence (happens only if sequenced equations like coincident are used)
template<typename T>
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type operator &(T& val);
*/
//we also allow to set values directly into the equation, as this makes it more compftable for multi constraints
//as align. Note that this only works if all option types of all equations in this sequence are distinguishable
template<typename T>
@@ -182,6 +125,13 @@ struct constraint_sequence : public seq {
fusion::front(view) = val;
return *this;
};
};
/*
template<typename T>
struct get_equation_id {
typedef typename T::ID type;
};
template<typename Seq, typename T>
@@ -191,12 +141,13 @@ struct pushed_seq {
typedef typename mpl::fold< S2, S1, mpl::if_< boost::is_same<
mpl::find<mpl::_1, mpl::_2>, mpl::end<mpl::_1> >, mpl::push_back<mpl::_1,mpl::_2>, mpl::_1> >::type unique_vector;
typedef typename mpl::sort<unique_vector, mpl::less< get_equation_id<mpl::_1>, get_equation_id<mpl::_2> > >::type sorted_vector;
typedef typename fusion::result_of::as_vector< unique_vector >::type vec;
typedef typename fusion::result_of::as_vector< sorted_vector >::type vec;
typedef constraint_sequence<vec> type;
};
};*/
template<typename Derived, typename Option, bool rotation_only = false>
template<typename Derived, typename Option, int id, bool rotation_only = false>
struct Equation : public EQ {
typedef typename mpl::if_<mpl::is_sequence<Option>, Option, mpl::vector<Option> >::type option_sequence;
@@ -206,17 +157,7 @@ struct Equation : public EQ {
options values;
bool pure_rotation;
struct option_copy {
options* values;
option_copy(options& op) : values(&op) {};
template<typename T>
void operator()(const T& val) const {
if(val.second.first)
fusion::at_key<typename T::first_type>(*values) = val.second;
};
};
typedef mpl::int_<id> ID;
Equation() : pure_rotation(rotation_only) {};
@@ -227,111 +168,49 @@ struct Equation : public EQ {
fusion::at_key<T>(values).first = true;
return *(static_cast<Derived*>(this));
};
//assign option
template<typename T>
typename boost::enable_if<fusion::result_of::has_key<options, T>, Derived&>::type operator=(const T& val) {
return operator()(val);
};
//assign complete equation (we need to override the operator= in the derived class anyway as it
//is automaticly created by the compiler, so we use a different name here to avoid duplicate
//operator= warning on msvc)
Derived& assign(const Derived& eq) {
Derived& assign(const Derived& eq);
//we only copy the values which were set and are therefore valid
option_copy oc(values);
fusion::for_each(eq.values, oc);
//the assigned eqution can be set back to default for convinience in further usage
const_cast<Derived*>(&eq)->setDefault();
return *static_cast<Derived*>(this);
};
//dont allow expression equation stacking: the compile time impact is huge if we want to allow
//text parsing
/*
Derived& operator=(const Derived& eq) {
option_copy oc(values);
fusion::for_each(eq.values, oc);
return *static_cast<Derived*>(this);
};*/
//an equation gets added to this equation
template<typename T>
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val) {
typename pushed_seq<T, Derived>::type vec;
*fusion::find<T>(vec) = val;
*fusion::find<Derived>(vec) = *(static_cast<Derived*>(this));
return vec;
};
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val);
//an sequence gets added to this equation (happens only if sequenced equations like coincident are used)
template<typename T>
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val) {
typedef typename pushed_seq<T, Derived>::type Sequence;
typedef typename fusion::result_of::begin<Sequence>::type Begin;
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<T, Derived>::S1>::type >::type EndOld;
//create the new sequence
Sequence vec;
//copy the old values into the new sequence
Begin b(vec);
EndOld eo(vec);
fusion::iterator_range<Begin, EndOld> range(b, eo);
fusion::copy(val, range);
//insert this object at the end of the sequence
*fusion::find<Derived>(vec) = *static_cast<Derived*>(this);
//and return our new extendet sequence
return vec;
};
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val);
*/
//set default option values, neeeded for repedability and to prevent unexpected behaviour
virtual void setDefault() = 0;
};
//convinience stream functions for debugging
template <typename charT, typename traits>
struct print_pair {
std::basic_ostream<charT,traits>* stream;
template<typename T>
void operator()(const T& t) const {
*stream << "("<<t.second.first << ", "<<t.second.second<<") ";
};
};
template <typename charT, typename traits, typename Eq>
typename boost::enable_if<boost::is_base_of<EQ, Eq>, std::basic_ostream<charT,traits>&>::type
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation)
{
print_pair<charT, traits> pr;
pr.stream = &stream;
stream << typeid(equation).name() << ": ";
fusion::for_each(equation.values, pr);
return stream;
}
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation);
struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace> > {
struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace>, 1 > {
using Equation::operator=;
using Equation::options;
Distance() : Equation() {
setDefault();
};
Distance();
//override needed ass assignmend operator is always created by the compiler
//and we need to ensure that our custom one is used
Distance& operator=(const Distance& d) {
return Equation::assign(d);
};
Distance& operator=(const Distance& d);
void setDefault() {
fusion::at_key<double>(values) = std::make_pair(false, 0.);
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
};
void setDefault();
template< typename Kernel, typename Tag1, typename Tag2 >
struct type {
@@ -388,23 +267,17 @@ struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace>
};
};
struct Orientation : public Equation<Orientation, Direction, true> {
struct Orientation : public Equation<Orientation, Direction, 2, true> {
using Equation::operator=;
using Equation::options;
Orientation() : Equation() {
setDefault();
};
Orientation();
//override needed ass assignmend operator is always created by the compiler
//and we need to ensure that our custom one is used
Orientation& operator=(const Orientation& d) {
return Equation::assign(d);
};
Orientation& operator=(const Orientation& d);
void setDefault() {
fusion::at_key<Direction>(values) = std::make_pair(false, parallel);
};
void setDefault();
template< typename Kernel, typename Tag1, typename Tag2 >
struct type : public PseudoScale<Kernel> {
@@ -454,24 +327,17 @@ struct Orientation : public Equation<Orientation, Direction, true> {
};
};
struct Angle : public Equation<Angle, mpl::vector2<double, SolutionSpace>, true> {
struct Angle : public Equation<Angle, mpl::vector2<double, SolutionSpace>, 3, true> {
using Equation::operator=;
Angle() : Equation() {
setDefault();
};
Angle();
//override needed ass assignmend operator is always created by the compiler
//and we need to ensure that our custom one is used
Angle& operator=(const Angle& d) {
return Equation::assign(d);
};
Angle& operator=(const Angle& d);
void setDefault() {
fusion::at_key<double>(values) = std::make_pair(false, 0.);
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
};
void setDefault();
template< typename Kernel, typename Tag1, typename Tag2 >
struct type : public PseudoScale<Kernel> {
@@ -530,6 +396,10 @@ static Angle angle;
};
#ifndef DCM_EXTERNAL_CORE
#include "imp/equations_imp.hpp"
#endif
#endif //GCM_EQUATIONS_H

View File

@@ -27,21 +27,11 @@
#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/int.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/find.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>
@@ -49,12 +39,7 @@
#include "logging.hpp"
#include "transformation.hpp"
#ifdef USE_LOGGING
#include <boost/math/special_functions.hpp>
#endif
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
@@ -358,216 +343,10 @@ public:
virtual void removed() = 0;
};
} //details
} //dcm
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template< typename Kernel, int Dim, typename TagList>
Geometry<Kernel, Dim, TagList>::Geometry()
: m_isInCluster(false), m_parameter(NULL,0,DS(0,0)),
m_clusterFixed(false), m_init(false) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry"));
#ifndef DCM_EXTERNAL_CORE
#include "imp/geometry_imp.hpp"
#endif
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
template<typename tag>
void Geometry<Kernel, Dim, TagList>::init() {
m_BaseParameterCount = tag::parameters::value;
m_parameterCount = m_BaseParameterCount;
m_rotations = tag::rotations::value;
m_translations = 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();
m_general_type = tag::weight::value;
m_exact_type = mpl::find<TagList, tag>::type::pos::value;
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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
typename Kernel::VectorMap& Geometry<Kernel, Dim, TagList>::getParameterMap() {
m_isInCluster = false;
m_parameterCount = m_BaseParameterCount;
return m_parameter;
};
template< typename Kernel, int Dim, typename TagList>
template<typename T>
void Geometry<Kernel, Dim, TagList>::linkTo(boost::shared_ptr<Geometry<Kernel, Dim, TagList> > geom, int offset) {
init<T>();
m_link = geom;
m_link_offset = offset;
m_global = geom->m_global.segment(offset, m_BaseParameterCount);
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::initMap(typename Kernel::MappedEquationSystem* mes) {
//check should not be needed, but how knows...
if(!m_init) {
if(!isLinked()) {
m_offset = mes->setParameterMap(m_parameterCount, getParameterMap());
m_parameter = m_global;
m_init = true;
}
else {
//it's important that the linked geometry is initialised, as we going to access its parameter map
if(!m_link->isInitialised())
m_link->initMap(mes);
m_offset = m_link->m_offset + m_link_offset;
new(&getParameterMap()) typename Kernel::VectorMap(&m_link->getParameterMap()(m_link_offset), m_parameterCount, typename Kernel::DynStride(1,1));
}
}
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 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 Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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
};
m_init = false;
m_isInCluster = false;
recalculated();
};
template< typename Kernel, int Dim, typename TagList>
template<typename VectorType>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::scale(Scalar value) {
for(int i=0; i!=m_translations; i++)
m_parameter.template segment<Dim>(i*Dim) *= 1./value;
};
}
}
#endif // GCM_GEOMETRY_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,449 @@
/*
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 DCM_CONSTRAINT_HOLDER_IMP_H
#define DCM_CONSTRAINT_HOLDER_IMP_H
#include "opendcm/core/constraint.hpp"
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/size.hpp>
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
namespace detail {
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template<typename T>
typename boost::enable_if<typename Constraint<Sys, Dim>::template holder<ConstraintVector, tag1, tag2>::template has_option<T>::type, void>::type
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::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 > >));
fusion::copy(fusion::at<distance>(objects).values, val.m_eq.values);
val.pure_rotation = fusion::at<distance>(objects).pure_rotation;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template<typename T>
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Dim>::template holder<ConstraintVector, tag1, tag2>::template has_option<T>::type>, void>::type
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::OptionSetter::operator()(EquationSet<T>& val) const {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only)
: first(f), second(s), scale(sc), rot_only(rotation_only) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Calculater::operator()(T& val) const {
//if the equation is disabled we don't have anything mapped so avoid accessing it
if(!val.enabled)
return;
//if we only need pure rotational functions and we are not such a nice thing, everything becomes 0
if(rot_only && !val.pure_rotation) {
val.m_residual(0) = 0;
if(first->getClusterMode()) {
if(!first->isClusterFixed()) {
val.m_diff_first_rot.setZero();
val.m_diff_first.setZero();
}
}
else
val.m_diff_first.setZero();
if(second->getClusterMode()) {
if(!second->isClusterFixed()) {
val.m_diff_second_rot.setZero();
val.m_diff_second.setZero();
}
}
else
val.m_diff_second.setZero();
}
//we need to calculate, so lets go for it!
else {
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<3; i++) {
val.m_diff_first_rot(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, first->m_diffparam.col(i));
}
//and now with the translations
for(int i=0; i<3; i++) {
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, first->m_diffparam.col(i+3));
}
}
}
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<3; i++) {
val.m_diff_second_rot(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
second->m_parameter, second->m_diffparam.col(i));
}
//and the translation seperated
for(int i=0; i<3; i++) {
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
second->m_parameter, second->m_diffparam.col(i+3));
}
}
}
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, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
: mes(m), first(f), second(s) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::MapSetter::operator()(T& val) const {
if(!val.enabled)
return;
//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_rot, 3, val.m_diff_first_rot);
mes.setJacobiMap(equation, first->m_offset, 3, 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_rot, 3, val.m_diff_second_rot);
mes.setJacobiMap(equation, second->m_offset, 3, val.m_diff_second);
}
}
else
mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2)
: first(f), second(s), points1(vec1), points2(vec2) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::PseudoCollector::operator()(T& val) const {
if(!val.enabled)
return;
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, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::LGZ::LGZ(geom_ptr f, geom_ptr s)
: first(f), second(s) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::LGZ::operator()(T& val) const {
typedef typename Sys::Kernel Kernel;
if(!val.enabled)
return;
//to treat local gradient zeros we calculate a approximate second derivative of the equations
//only do that if neseccary: residual is not zero
if(!Kernel::isSame(val.m_residual(0),0, 1e-7)) { //TODO: use exact precission and scale value
//rotations exist only in cluster
if(first->getClusterMode() && !first->isClusterFixed()) {
//LGZ exists for rotations only
for(int i=0; i<3; i++) {
//only treat if the gradient realy is zero
if(Kernel::isSame(val.m_diff_first_rot(i), 0, 1e-7)) {
//to get the approximated second derivative we need the slightly moved geometrie
const typename Kernel::Vector p_old = first->m_parameter;
first->m_parameter += first->m_diffparam.col(i)*1e-3;
first->normalize();
//with this changed geometrie we test if a gradient exist now
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, block);
first->m_parameter = p_old;
//let's see if the initial LGZ was a real one
if(!Kernel::isSame(res, 0, 1e-7)) {
//is a fake zero, let's correct it
val.m_diff_first_rot(i) = res;
};
};
};
}
//and the same for the second one too
if(second->getClusterMode() && !second->isClusterFixed()) {
for(int i=0; i<3; i++) {
//only treat if the gradient realy is zero
if(Kernel::isSame(val.m_diff_second_rot(i), 0, 1e-7)) {
//to get the approximated second derivative we need the slightly moved geometrie
const typename Kernel::Vector p_old = second->m_parameter;
second->m_parameter += second->m_diffparam.col(i)*1e-3;
second->normalize();
//with this changed geometrie we test if a gradient exist now
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
second->m_parameter, block);
second->m_parameter = p_old;
//let's see if the initial LGZ was a real one
if(!Kernel::isSame(res, 0, 1e-7)) {
//is a fake zero, let's correct it
val.m_diff_second_rot(i) = res;
};
};
};
};
};
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericEquations::GenericEquations(std::vector<boost::any>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericEquations::operator()(T& val) const {
vec.push_back(val.m_eq);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericConstraints::GenericConstraints(std::vector<boost::any>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericConstraints::operator()(T& val) const {
vec.push_back(val);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Types::Types(std::vector<const std::type_info*>& v)
: vec(v) {
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
template< typename T >
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Types::operator()(T& val) const {
vec.push_back(&typeid(T));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::holder(Objects& obj) : m_objects(obj) {
//set the initial values in the equations
fusion::for_each(m_sets, OptionSetter(obj));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::calculate(geom_ptr first, geom_ptr second,
Scalar scale, bool rotation_only) {
fusion::for_each(m_sets, Calculater(first, second, scale, rotation_only));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::treatLGZ(geom_ptr first, geom_ptr second) {
fusion::for_each(m_sets, LGZ(first, second));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
typename Constraint<Sys, Dim>::placeholder*
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::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, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
fusion::for_each(m_sets, MapSetter(mes, first, second));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) {
fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2));
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
typename Constraint<Sys, Dim>::placeholder*
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::clone() {
return new holder(*this);
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
int Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::equationCount() {
int count = 0;
EquationCounter counter(count);
fusion::for_each(m_sets, counter);
return count;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
std::vector<boost::any>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getGenericEquations() {
std::vector<boost::any> vec;
fusion::for_each(m_sets, GenericEquations(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
std::vector<boost::any>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getGenericConstraints() {
std::vector<boost::any> vec;
fusion::for_each(m_objects, GenericConstraints(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
std::vector<const std::type_info*>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getEquationTypes() {
std::vector<const std::type_info*> vec;
mpl::for_each< EquationVector >(Types(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
std::vector<const std::type_info*>
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getConstraintTypes() {
std::vector<const std::type_info*> vec;
mpl::for_each< ConstraintVector >(Types(vec));
return vec;
};
template<typename Sys, int Dim>
template<typename ConstraintVector, typename tag1, typename tag2>
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::disable() {
fusion::for_each(m_sets, disabler());
};
};//detail
};//dcm
#endif //GCM_CONSTRAINT_H

View File

@@ -0,0 +1,208 @@
/*
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 DCM_CONSTRAINT_IMP_H
#define DCM_CONSTRAINT_IMP_H
#include "../constraint.hpp"
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/size.hpp>
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
namespace detail {
template<typename Sys, int Dim>
template<typename ConstraintVector>
void Constraint<Sys, Dim>::initialize(ConstraintVector& cv) {
//use the compile time unrolling to retrieve the geometry tags
initializeFirstGeometry<mpl::int_<0> >(cv, mpl::true_());
};
template<typename Sys, int Dim>
template<typename WhichType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
//this function is only for breaking the compilation loop, it should never be called
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
};
template<typename Sys, int Dim>
template<typename WhichType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
typedef typename Sys::geometries geometries;
switch(first->getExactType()) {
#ifdef BOOST_PP_LOCAL_ITERATE
#define BOOST_PP_LOCAL_MACRO(n) \
case (WhichType::value + n): \
return initializeSecondGeometry<boost::mpl::int_<0>,\
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
break;
#define BOOST_PP_LOCAL_LIMITS (0, 10)
#include BOOST_PP_LOCAL_ITERATE()
#endif //BOOST_PP_LOCAL_ITERATE
default:
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
return initializeFirstGeometry<next_which_t, ConstraintVector> (cv,
typename mpl::less< next_which_t, typename mpl::size<geometries>::type >::type());
}
};
template<typename Sys, int Dim>
template<typename WhichType, typename FirstType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
//this function is only for breaking the compilation loop, it should never be called
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
};
template<typename Sys, int Dim>
template<typename WhichType, typename FirstType, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
typedef typename Sys::geometries geometries;
switch(second->getExactType()) {
#ifdef BOOST_PP_LOCAL_ITERATE
#define BOOST_PP_LOCAL_MACRO(n) \
case (WhichType::value + n): \
return intitalizeFinalize<FirstType, \
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
break;
#define BOOST_PP_LOCAL_LIMITS (0, 10)
#include BOOST_PP_LOCAL_ITERATE()
#endif //BOOST_PP_LOCAL_ITERATE
default:
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
return initializeSecondGeometry<next_which_t, FirstType, ConstraintVector>
(cv, typename mpl::less
< next_which_t
, typename mpl::size<geometries>::type>::type()
);
}
};
template<typename Sys, int Dim>
template<typename FirstType, typename SecondType, typename ConstraintVector>
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_ /*is_unrolled_t*/) {
initializeFromTags<FirstType, SecondType>(cv);
};
template<typename Sys, int Dim>
template<typename FirstType, typename SecondType, typename ConstraintVector>
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_ /*is_unrolled_t*/) {
//Should never be here at runtime; only required to block code generation that deref's the sequence out of bounds
BOOST_ASSERT(false);
}
template<typename Sys, int Dim>
template<typename tag1, typename tag2, typename ConstraintVector>
void Constraint<Sys, Dim>::initializeFromTags(ConstraintVector& v) {
typedef tag_order< tag1, tag2 > order;
//and build the placeholder
content = new holder<ConstraintVector, typename order::first_tag, typename order::second_tag >(v);
//geometry order needs to be the one needed by equations
if(order::swapt::value)
first.swap(second);
};
template<typename Sys, int Dim>
Constraint<Sys, Dim>::Constraint(geom_ptr f, geom_ptr s)
: first(f), second(s), content(0) {
//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, int Dim>
Constraint<Sys, Dim>::~Constraint() {
delete content;
//first->template disconnectSignal<reset>(cf);
//second->template disconnectSignal<reset>(cs);
};
template<typename Sys, int Dim>
int Constraint<Sys, Dim>::equationCount() {
return content->equationCount();
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::calculate(Scalar scale, bool rotation_only) {
content->calculate(first, second, scale, rotation_only);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::treatLGZ() {
content->treatLGZ(first, second);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::setMaps(MES& mes) {
content->setMaps(mes, first, second);
};
template<typename Sys, int Dim>
void Constraint<Sys, Dim>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
content->collectPseudoPoints(first, second, vec1, vec2);
};
template<typename Sys, int Dim>
std::vector<boost::any> Constraint<Sys, Dim>::getGenericEquations() {
return content->getGenericEquations();
};
template<typename Sys, int Dim>
std::vector<boost::any> Constraint<Sys, Dim>::getGenericConstraints() {
return content->getGenericConstraints();
};
template<typename Sys, int Dim>
std::vector<const std::type_info*> Constraint<Sys, Dim>::getEquationTypes() {
return content->getEquationTypes();
};
template<typename Sys, int Dim>
std::vector<const std::type_info*> Constraint<Sys, Dim>::getConstraintTypes() {
return content->getConstraintTypes();
};
};//detail
};//dcm
#endif //GCM_CONSTRAINT_H

View File

@@ -0,0 +1,255 @@
/*
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 DCM_EQUATIONS_IMP_H
#define DCM_EQUATIONS_IMP_H
#include <assert.h>
#include "../equations.hpp"
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/sort.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/iterator_range.hpp>
#include <boost/fusion/include/copy.hpp>
#include <boost/fusion/include/advance.hpp>
#include <boost/fusion/include/back.hpp>
#include <boost/fusion/include/iterator_range.hpp>
#include <boost/fusion/include/nview.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/as_map.hpp>
#include <boost/fusion/include/filter_view.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/exception/exception.hpp>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
namespace dcm {
template<typename Seq, typename T>
struct pushed_seq;
/*
template<typename seq>
template<typename T>
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type
constraint_sequence<seq>::operator &(T& val) {
typedef typename pushed_seq<seq, T>::type Sequence;
//create the new sequence
Sequence vec;
//get a index vector for this sequence
typedef typename mpl::transform<typename pushed_seq<seq, T>::S1,
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector_added;
//and copy the types in
fusion::nview<Sequence, position_vector_added> view_added(vec);
fusion::copy(*this, view_added);
//insert this object at the end of the sequence
*fusion::find<T>(vec) = val;
//and return our new extendet sequence
return vec;
};
template<typename seq>
template<typename T>
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type
constraint_sequence<seq>::operator &(T& val) {
typedef typename pushed_seq<T, seq>::type Sequence;
//create the new sequence
Sequence vec;
//get a index vector for the added sequence
typedef typename mpl::transform<typename pushed_seq<T, seq>::S1,
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector_added;
//and copy the types in
fusion::nview<Sequence, position_vector_added> view_added(vec);
fusion::copy(val, view_added);
//to copy the types of the second sequence is not as easy as before. If types were already present in
//the original sequence they are not added again. therefore we need to find all types of the second sequence
//in the new one and assign the objects to this positions.
//get a index vector for all second-sequence-elements
typedef typename mpl::transform<typename pushed_seq<T, seq>::S2,
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
//and copy the types in
fusion::nview<Sequence, position_vector> view(vec);
fusion::copy(*this, view);
//and return our new extendet sequence
return vec;
};
*/
template<typename options>
struct option_copy {
options* values;
option_copy(options& op) : values(&op) {};
template<typename T>
void operator()(const T& val) const {
if(val.second.first)
fusion::at_key<typename T::first_type>(*values) = val.second;
};
};
template<typename Derived, typename Option, int id, bool rotation_only >
Derived& Equation<Derived, Option, id, rotation_only>::assign(const Derived& eq) {
//we only copy the values which were set and are therefore valid
option_copy<options> oc(values);
fusion::for_each(eq.values, oc);
//the assigned eqution can be set back to default for convinience in further usage
const_cast<Derived*>(&eq)->setDefault();
return *static_cast<Derived*>(this);
};
/*
template<typename Derived, typename Option, int id, bool rotation_only >
template<typename T>
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type
Equation<Derived, Option, id, rotation_only>::operator &(T& val) {
typename pushed_seq<T, Derived>::type vec;
*fusion::find<T>(vec) = val;
*fusion::find<Derived>(vec) = *(static_cast<Derived*>(this));
return vec;
};
template<typename Derived, typename Option, int id, bool rotation_only >
template<typename T>
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type
Equation<Derived, Option, id, rotation_only>::operator &(T& val) {
typedef typename pushed_seq<T, Derived>::type Sequence;
//create the new sequence
Sequence vec;
//get a index vector for the added sequence
typedef typename mpl::transform<typename pushed_seq<T, Derived>::S1,
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
//and copy the types in
fusion::nview<Sequence, position_vector> view(vec);
fusion::copy(val, view);
//insert this object into the sequence
*fusion::find<Derived>(vec) = *static_cast<Derived*>(this);
//and return our new extendet sequence
return vec;
};
*/
template<typename Derived, typename Option, int id, bool rotation_only >
void Equation<Derived, Option, id, rotation_only>::setDefault() {
fusion::at_key<double>(values) = std::make_pair(false, 0.);
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
};
//convinience stream functions for debugging
template <typename charT, typename traits>
struct print_pair {
std::basic_ostream<charT,traits>* stream;
template<typename T>
void operator()(const T& t) const {
*stream << "("<<t.second.first << ", "<<t.second.second<<") ";
};
};
template <typename charT, typename traits, typename Eq>
typename boost::enable_if<boost::is_base_of<EQ, Eq>, std::basic_ostream<charT,traits>&>::type
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation)
{
print_pair<charT, traits> pr;
pr.stream = &stream;
stream << typeid(equation).name() << ": ";
fusion::for_each(equation.values, pr);
return stream;
}
Distance::Distance() : Equation() {
setDefault();
};
Distance& Distance::operator=(const Distance& d) {
return Equation::assign(d);
};
void Distance::setDefault() {};
Orientation::Orientation() : Equation() {
setDefault();
};
Orientation& Orientation::operator=(const Orientation& d) {
return Equation::assign(d);
};
void Orientation::setDefault() {
fusion::at_key<Direction>(values) = std::make_pair(false, parallel);
};
Angle::Angle() : Equation() {
setDefault();
};
Angle& Angle::operator=(const Angle& d) {
return Equation::assign(d);
};
void Angle::setDefault() {
fusion::at_key<double>(values) = std::make_pair(false, 0.);
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
};
};
#endif //GCM_EQUATIONS_H

View File

@@ -0,0 +1,266 @@
/*
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_IMP_H
#define GCM_GEOMETRY_IMP_H
#include <iostream>
#include "../geometry.hpp"
#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/int.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/find.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>
#ifdef USE_LOGGING
#include <boost/math/special_functions.hpp>
#endif
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
namespace details {
template< typename Kernel, int Dim, typename TagList>
Geometry<Kernel, Dim, TagList>::Geometry()
: m_isInCluster(false), m_parameter(NULL,0,DS(0,0)),
m_clusterFixed(false), m_init(false) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry"));
#endif
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
template<typename tag>
void Geometry<Kernel, Dim, TagList>::init() {
m_BaseParameterCount = tag::parameters::value;
m_parameterCount = m_BaseParameterCount;
m_rotations = tag::rotations::value;
m_translations = 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();
m_general_type = tag::weight::value;
m_exact_type = mpl::find<TagList, tag>::type::pos::value;
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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
typename Kernel::VectorMap& Geometry<Kernel, Dim, TagList>::getParameterMap() {
m_isInCluster = false;
m_parameterCount = m_BaseParameterCount;
return m_parameter;
};
template< typename Kernel, int Dim, typename TagList>
template<typename T>
void Geometry<Kernel, Dim, TagList>::linkTo(boost::shared_ptr<Geometry<Kernel, Dim, TagList> > geom, int offset) {
init<T>();
m_link = geom;
m_link_offset = offset;
m_global = geom->m_global.segment(offset, m_BaseParameterCount);
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::initMap(typename Kernel::MappedEquationSystem* mes) {
//check should not be needed, but how knows...
if(!m_init) {
if(!isLinked()) {
m_offset = mes->setParameterMap(m_parameterCount, getParameterMap());
m_parameter = m_global;
m_init = true;
}
else {
//it's important that the linked geometry is initialised, as we going to access its parameter map
if(!m_link->isInitialised())
m_link->initMap(mes);
m_offset = m_link->m_offset + m_link_offset;
new(&getParameterMap()) typename Kernel::VectorMap(&m_link->getParameterMap()(m_link_offset), m_parameterCount, typename Kernel::DynStride(1,1));
}
}
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 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 Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
};
template< typename Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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
};
m_init = false;
m_isInCluster = false;
recalculated();
};
template< typename Kernel, int Dim, typename TagList>
template<typename VectorType>
void Geometry<Kernel, Dim, TagList>::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 Kernel, int Dim, typename TagList>
void Geometry<Kernel, Dim, TagList>::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,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 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_KERNEL_IMP_H
#define DCM_KERNEL_IMP_H
#include "../kernel.hpp"
#include <boost/math/special_functions.hpp>
namespace dcm {
template<typename Kernel>
Dogleg<Kernel>::Dogleg(Kernel* k) : m_kernel(k), tolg(1e-40), tolx(1e-20) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
#endif
};
template<typename Kernel>
Dogleg<Kernel>::Dogleg() : tolg(1e-40), tolx(1e-20) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
#endif
};
template<typename Kernel>
void Dogleg<Kernel>::setKernel(Kernel* k) {
m_kernel = k;
};
template<typename Kernel>
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
void Dogleg<Kernel>::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
}
};
template<typename Kernel>
void Dogleg<Kernel>::init(typename Kernel::MappedEquationSystem& sys) {
if(!sys.isValid())
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
F_old.resize(sys.equationCount());
g.resize(sys.equationCount());
J_old.resize(sys.equationCount(), sys.parameterCount());
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
sys.removeLocalGradientZeros();
#ifdef USE_LOGGING
BOOST_LOG(log)<< "LGZ jacobi: "<<std::endl<<sys.Jacobi<<std::endl
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
#endif
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
g_inf = g.template lpNorm<E::Infinity>();
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
delta=5;
nu=2.;
iter=0;
stop=0;
reduce=0;
unused=0;
counter=0;
};
template<typename Kernel>
int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, bool continuous) {
nothing n;
return solve(sys, n, continuous);
};
template<typename Kernel>
template<typename Functor>
int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale, bool continuous) {
clock_t start = clock();
if(!sys.isValid())
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
int maxIterNumber = 5000;//MaxIterations * xsize;
number_type diverging_lim = 1e6*err + 1e12;
do {
// check if finished
if(fx_inf <= m_kernel->template getProperty<precision>()*sys.Scaling) // Success
stop = 1;
else if(g_inf <= tolg)
throw solving_error() << boost::errinfo_errno(2) << error_message("g infinity norm smaller below limit");
else if(delta <= tolx)
throw solving_error() << boost::errinfo_errno(3) << error_message("step size below limit");
else if(iter >= maxIterNumber)
throw solving_error() << boost::errinfo_errno(4) << error_message("maximal iterations reached");
else if(!boost::math::isfinite(err))
throw solving_error() << boost::errinfo_errno(5) << error_message("error is inf or nan");
else if(err > diverging_lim)
throw solving_error() << boost::errinfo_errno(6) << error_message("error diverged");
// 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;
sys.recalculate();
#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++;
}
while(!stop && continuous);
clock_t end = clock();
time = (double(end-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>
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::parameterCount() {
return m_params;
};
template<typename Scalar, template<class> class Nonlinear>
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::equationCount() {
return m_eqns;
};
template<typename Scalar, template<class> class Nonlinear>
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::rotationOnly() {
return rot_only;
};
template<typename Scalar, template<class> class Nonlinear>
Kernel<Scalar, Nonlinear>::MappedEquationSystem::MappedEquationSystem(int params, int equations)
: rot_only(false), m_jacobi(equations, params),
m_parameter(params), Residual(equations),
m_params(params), m_eqns(equations), Scaling(1.),
Jacobi(&m_jacobi(0,0),equations,params,DynStride(equations,1)),
Parameter(&m_parameter(0),params,DynStride(1,1)) {
m_param_rot_offset = 0;
m_param_trans_offset = params;
m_eqn_offset = 0;
m_jacobi.setZero(); //important as some places are never written
};
template<typename Scalar, template<class> class Nonlinear>
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setParameterMap(int number, VectorMap& map, ParameterType t) {
if(t == rotation) {
new(&map) VectorMap(&m_parameter(m_param_rot_offset), number, DynStride(1,1));
m_param_rot_offset += number;
return m_param_rot_offset-number;
}
else {
m_param_trans_offset -= number;
new(&map) VectorMap(&m_parameter(m_param_trans_offset), number, DynStride(1,1));
return m_param_trans_offset;
}
};
template<typename Scalar, template<class> class Nonlinear>
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setParameterMap(Vector3Map& map, ParameterType t) {
if(t == rotation) {
new(&map) Vector3Map(&m_parameter(m_param_rot_offset));
m_param_rot_offset += 3;
return m_param_rot_offset-3;
}
else {
m_param_trans_offset -= 3;
new(&map) Vector3Map(&m_parameter(m_param_trans_offset));
return m_param_trans_offset;
}
};
template<typename Scalar, template<class> class Nonlinear>
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setResidualMap(VectorMap& map) {
new(&map) VectorMap(&Residual(m_eqn_offset), 1, DynStride(1,1));
return m_eqn_offset++;
};
template<typename Scalar, template<class> class Nonlinear>
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setJacobiMap(int eqn, int offset, int number, CVectorMap& map) {
new(&map) CVectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
template<typename Scalar, template<class> class Nonlinear>
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
new(&map) VectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
template<typename Scalar, template<class> class Nonlinear>
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::isValid() {
if(!m_params || !m_eqns)
return false;
return true;
};
template<typename Scalar, template<class> class Nonlinear>
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setAccess(ParameterType t) {
if(t==complete) {
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,m_params,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(0),m_params,DynStride(1,1));
}
else if(t==rotation) {
int num = m_param_trans_offset;
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,num,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(0),num,DynStride(1,1));
}
else if(t==general) {
int num = m_params - m_param_trans_offset;
new(&Jacobi) MatrixMap(&m_jacobi(0,m_param_trans_offset),m_eqns,num,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(m_param_trans_offset),num,DynStride(1,1));
}
};
template<typename Scalar, template<class> class Nonlinear>
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setGeneralEquationAccess(bool general) {
rot_only = !general;
};
template<typename Scalar, template<class> class Nonlinear>
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::hasParameterType(ParameterType t) {
if(t==rotation)
return (m_param_rot_offset>0);
else if(t==general)
return (m_param_trans_offset<m_params);
else
return (m_params>0);
};
template<typename Scalar, template<class> class Nonlinear>
Kernel<Scalar, Nonlinear>::Kernel() {
//init the solver
m_solver.setKernel(this);
}
template<typename Scalar, template<class> class Nonlinear>
SolverInfo Kernel<Scalar, Nonlinear>::getSolverInfo() {
SolverInfo info;
info.iterations = m_solver.iter;
info.error = m_solver.err;
info.time = m_solver.time;
return info;
}
//static comparison versions
template<typename Scalar, template<class> class Nonlinear>
template <typename DerivedA,typename DerivedB>
bool Kernel<Scalar, Nonlinear>::isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
return ((p1-p2).squaredNorm() < precission);
}
template<typename Scalar, template<class> class Nonlinear>
bool Kernel<Scalar, Nonlinear>::isSame(number_type t1, number_type t2, number_type precission) {
return (std::abs(t1-t2) < precission);
}
template<typename Scalar, template<class> class Nonlinear>
template <typename DerivedA,typename DerivedB>
bool Kernel<Scalar, Nonlinear>::isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
return ((p1+p2).squaredNorm() < precission);
}
template<typename Scalar, template<class> class Nonlinear>
template <typename DerivedA,typename DerivedB>
bool Kernel<Scalar, Nonlinear>::isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1-p2).squaredNorm() < getProperty<precision>());
}
template<typename Scalar, template<class> class Nonlinear>
bool Kernel<Scalar, Nonlinear>::isSame(number_type t1, number_type t2) {
return (std::abs(t1-t2) < getProperty<precision>());
}
template<typename Scalar, template<class> class Nonlinear>
template <typename DerivedA,typename DerivedB>
bool Kernel<Scalar, Nonlinear>::isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1+p2).squaredNorm() < getProperty<precision>());
}
template<typename Scalar, template<class> class Nonlinear>
int Kernel<Scalar, Nonlinear>::solve(MappedEquationSystem& mes) {
nothing n;
if(getProperty<solvermode>()==continuous)
m_solver.init(mes);
return m_solver.solve(mes, n);
};
template<typename Scalar, template<class> class Nonlinear>
template<typename Functor>
int Kernel<Scalar, Nonlinear>::solve(MappedEquationSystem& mes, Functor& f) {
if(getProperty<solvermode>()==continuous)
m_solver.init(mes);
return m_solver.solve(mes, f);
};
}
#endif //GCM_KERNEL_H

View File

@@ -0,0 +1,115 @@
/*
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_IMP_H
#define GCM_OBJECT_IMP_H
#include <iostream>
#include <map>
#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/enable_shared_from_this.hpp>
#include "../property.hpp"
#define EMIT_CALL_DEC(z, n, data) \
template<typename SigMap> \
template < \
typename S \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
> \
void SignalOwner<SigMap>::emitSignal( \
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
) \
{ \
if(m_emit_signals) {\
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 map_type; \
map_type& map = fusion::at<distance>(m_signals); \
for (typename map_type::iterator it=map.begin(); it != map.end(); it++) \
(it->second)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
}\
};
namespace dcm {
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 SigMap>
SignalOwner<SigMap>::SignalOwner() : m_emit_signals(true), m_signal_count(0) {};
template<typename SigMap>
template<typename S>
Connection SignalOwner<SigMap>::connectSignal(typename mpl::at<SigMap, 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 map_type;
map_type& map = fusion::at<distance>(m_signals);
map[++m_signal_count] = function;
return m_signal_count;
};
template<typename SigMap>
template<typename S>
void SignalOwner<SigMap>::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 map_type;
map_type& map = fusion::at<distance>(m_signals);
map.erase(c);
};
template<typename SigMap>
void SignalOwner<SigMap>::enableSignals(bool onoff)
{
m_emit_signals = onoff;
};
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
}
#endif //GCM_OBJECT_H

View File

@@ -0,0 +1,257 @@
/*
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_SYSTEM_IMP_H
#define DCM_SYSTEM_IMP_H
#ifdef DCM_EXTERNAL_CORE
#include "kernel_imp.hpp"
#include "transformation_imp.hpp"
#include "clustergraph_imp.hpp"
#include "equations_imp.hpp"
#endif
#include "../system.hpp"
#include <boost/fusion/include/for_each.hpp>
namespace dcm {
struct clearer {
template<typename T>
void operator()(T& vector) const {
vector.clear();
};
};
template<typename System>
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 {};
};
template< typename KernelType, typename T1, typename T2, typename T3 >
System<KernelType, T1, T2, T3>::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);
};
template< typename KernelType, typename T1, typename T2, typename T3 >
System<KernelType, T1, T2, T3>::~System() {
#ifdef USE_LOGGING
stop_log(sink);
#endif
};
template< typename KernelType, typename T1, typename T2, typename T3 >
void System<KernelType, T1, T2, T3>::clear() {
m_cluster->clearClusters();
m_cluster->clear();
fusion::for_each(*m_storage, clearer());
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Object>
typename std::vector< boost::shared_ptr<Object> >::iterator System<KernelType, T1, T2, T3>::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 KernelType, typename T1, typename T2, typename T3 >
template<typename Object>
typename std::vector< boost::shared_ptr<Object> >::iterator System<KernelType, T1, T2, T3>::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 KernelType, typename T1, typename T2, typename T3 >
template<typename Object>
std::vector< boost::shared_ptr<Object> >& System<KernelType, T1, T2, T3>::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 KernelType, typename T1, typename T2, typename T3 >
template<typename Object>
void System<KernelType, T1, T2, T3>::push_back(boost::shared_ptr<Object> ptr) {
objectVector<Object>().push_back(ptr);
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Object>
void System<KernelType, T1, T2, T3>::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());
};
template< typename KernelType, typename T1, typename T2, typename T3 >
SolverInfo System<KernelType, T1, T2, T3>::solve() {
clock_t start = clock();
m_sheduler.execute(*this);
clock_t end = clock();
SolverInfo info = m_kernel.getSolverInfo();
info.time = (double(end-start)* 1000.) / double(CLOCKS_PER_SEC);
//signal our successful solving
BaseType::template emitSignal<solved>(this);
return info;
};
template< typename KernelType, typename T1, typename T2, typename T3 >
boost::shared_ptr<System<KernelType, T1, T2, T3> > System<KernelType, T1, T2, T3>::createSubsystem() {
boost::shared_ptr<System> s = boost::shared_ptr<System>(new System());
s->m_cluster = m_cluster->createCluster().first;
s->m_storage = m_storage;
s->m_cluster->template setProperty<dcm::type_prop>(details::subcluster);
#ifdef USE_LOGGING
stop_log(s->sink);
#endif
//inform modules that we have a subsystem now
Inheriter1::system_sub(s);
Inheriter2::system_sub(s);
Inheriter3::system_sub(s);
m_subsystems.push_back(s);
return s;
};
template< typename KernelType, typename T1, typename T2, typename T3 >
typename std::vector<boost::shared_ptr<System<KernelType, T1, T2, T3> > >::iterator System<KernelType, T1, T2, T3>::beginSubsystems() {
return m_subsystems.begin();
};
template< typename KernelType, typename T1, typename T2, typename T3 >
typename std::vector<boost::shared_ptr<System<KernelType, T1, T2, T3> > >::iterator System<KernelType, T1, T2, T3>::endSubsystems() {
return m_subsystems.end();
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Option>
typename boost::enable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
typename mpl::end<typename KernelType::PropertySequence>::type >, typename Option::type& >::type
System<KernelType, T1, T2, T3>::getOption() {
return m_options.template getProperty<Option>();
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Option>
typename boost::disable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
typename mpl::end<typename KernelType::PropertySequence>::type >, typename Option::type& >::type
System<KernelType, T1, T2, T3>::getOption() {
return m_kernel.template getProperty<Option>();
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Option>
typename boost::enable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
typename mpl::end<typename KernelType::PropertySequence>::type >, void >::type
System<KernelType, T1, T2, T3>::setOption(typename Option::type value) {
m_options.template setProperty<Option>(value);
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Option>
typename boost::disable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
typename mpl::end<typename KernelType::PropertySequence>::type >, void >::type
System<KernelType, T1, T2, T3>::setOption(typename Option::type value) {
m_kernel.template setProperty<Option>(value);
};
template< typename KernelType, typename T1, typename T2, typename T3 >
template<typename Option>
typename Option::type&
System<KernelType, T1, T2, T3>::option() {
return getOption<Option>();
};
template< typename KernelType, typename T1, typename T2, typename T3 >
KernelType& System<KernelType, T1, T2, T3>::kernel() {
return m_kernel;
};
template< typename KernelType, typename T1, typename T2, typename T3 >
void System<KernelType, T1, T2, T3>::copyInto(System<KernelType, T1, T2, T3>& into) const {
//copy the clustergraph and clone all objects while at it. They are also pushed to the storage
cloner<System> 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);
};
template< typename KernelType, typename T1, typename T2, typename T3 >
System<KernelType, T1, T2, T3>* System<KernelType, T1, T2, T3>::clone() const {
System* ns = new System();
this->copyInto(*ns);
return ns;
};
}
#endif //GCM_SYSTEM_H

View File

@@ -0,0 +1,303 @@
/*
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_IMP_H
#define DCM_TRANSFORMATION_IMP_H
#include "../transformation.hpp"
#include <cmath>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <boost/mpl/if.hpp>
namespace dcm {
namespace detail {
template<typename Scalar, int Dim>
Transform<Scalar, Dim>::Transform() : m_rotation(Rotation::Identity()),
m_translation(Translation::Identity()),
m_scale(Scaling(1.)) { };
template<typename Scalar, int Dim>
Transform<Scalar, Dim>::Transform(const Rotation& r) : m_rotation(r),
m_translation(Translation::Identity()),
m_scale(Scaling(1.)) {
m_rotation.normalize();
};
template<typename Scalar, int Dim>
Transform<Scalar, Dim>::Transform(const Rotation& r, const Translation& t) : m_rotation(r),
m_translation(t),
m_scale(Scaling(1.)) {
m_rotation.normalize();
};
template<typename Scalar, int Dim>
Transform<Scalar, Dim>::Transform(const Rotation& r, const Translation& t, const Scaling& s) : m_rotation(r),
m_translation(t),
m_scale(s) {
m_rotation.normalize();
};
template<typename Scalar, int Dim>
const typename Transform<Scalar, Dim>::Rotation& Transform<Scalar, Dim>::rotation() const {
return m_rotation;
}
template<typename Scalar, int Dim>
template<typename Derived>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
m_rotation = rotation.derived().normalized()*m_rotation;
return *this;
}
template<typename Scalar, int Dim>
const typename Transform<Scalar, Dim>::Translation& Transform<Scalar, Dim>::translation() const {
return m_translation;
}
template<typename Scalar, int Dim>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::translate(const Translation& translation) {
m_translation = m_translation*translation;
return *this;
}
template<typename Scalar, int Dim>
const typename Transform<Scalar, Dim>::Scaling& Transform<Scalar, Dim>::scaling() const {
return m_scale;
}
template<typename Scalar, int Dim>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::scale(const Scalar& scaling) {
m_scale *= Scaling(scaling);
return *this;
}
template<typename Scalar, int Dim>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::scale(const Scaling& scaling) {
m_scale.factor() *= scaling.factor();
return *this;
}
template<typename Scalar, int Dim>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::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;
};
template<typename Scalar, int Dim>
Transform<Scalar, Dim> Transform<Scalar, Dim>::inverse() {
Transform res(*this);
res.invert();
return res;
};
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator=(const Translation& t) {
m_translation = t;
m_rotation = Rotation::Identity();
m_scale = Scaling(1.);
return *this;
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Translation& t) const {
Transform res = *this;
res.translate(t);
return res;
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Translation& t) {
return translate(t);
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator=(const Scaling& s) {
m_scale = s;
m_translation = Translation::Identity();
m_rotation = Rotation::Identity();
return *this;
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Scaling& s) const {
Transform res = *this;
res.scale(s);
return res;
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Scaling& s) {
return scale(s);
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::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 Scalar, int Dim>
template<typename Derived>
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
Transform res = *this;
res.rotate(r.derived());
return res;
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
return rotate(r.derived());
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator* (const Transform& other) const {
Transform res(*this);
res*= other;
return res;
}
template<typename Scalar, int Dim>
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::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;
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Derived& Transform<Scalar, Dim>::rotate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_rotation*vec;
return vec.derived();
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Derived& Transform<Scalar, Dim>::translate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_translation*vec;
return vec.derived();
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Derived& Transform<Scalar, Dim>::scale(Eigen::MatrixBase<Derived>& vec) const {
vec*=m_scale.factor();
return vec.derived();
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Derived& Transform<Scalar, Dim>::transform(Eigen::MatrixBase<Derived>& vec) const {
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
return vec.derived();
}
template<typename Scalar, int Dim>
template<typename Derived>
inline Derived Transform<Scalar, Dim>::operator*(const Eigen::MatrixBase<Derived>& vec) const {
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
}
template<typename Scalar, int Dim>
template<typename Derived>
inline void Transform<Scalar, Dim>::operator()(Eigen::MatrixBase<Derived>& vec) const {
transform(vec);
}
template<typename Scalar, int Dim>
bool Transform<Scalar, Dim>::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);
};
template<typename Scalar, int Dim>
void Transform<Scalar, Dim>::setIdentity() {
m_rotation.setIdentity();
m_translation = Translation::Identity();
m_scale = Scaling(1.);
}
template<typename Scalar, int Dim>
const Transform<Scalar, Dim> Transform<Scalar, Dim>::Identity() {
return Transform(Rotation::Identity(), Translation::Identity(), Scaling(1));
}
template<typename Scalar, int Dim>
Transform<Scalar, Dim>& Transform<Scalar, Dim>::normalize() {
m_rotation.normalize();
return *this;
}
template<typename Scalar, int Dim>
DiffTransform<Scalar, Dim>::DiffTransform(Transform<Scalar, Dim>& trans)
: Transform<Scalar, Dim>(trans.rotation(), trans.translation(), trans.scaling()) {
m_diffMatrix.setZero();
};
template<typename Scalar, int Dim>
const typename DiffTransform<Scalar, Dim>::DiffMatrix&
DiffTransform<Scalar, Dim>::differential() {
return m_diffMatrix;
};
template<typename Scalar, int Dim>
inline Scalar&
DiffTransform<Scalar, Dim>::operator()(int f, int s) {
return m_diffMatrix(f,s);
};
template<typename Scalar, int Dim>
inline Scalar&
DiffTransform<Scalar, Dim>::at(int f, int s) {
return m_diffMatrix(f,s);
};
/*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 charT, typename traits, typename Kernel, int Dim>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& 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 charT, typename traits,typename Kernel, int Dim>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& 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;
}
}//detail
}//DCM
#endif //DCM_TRANSFORMATION

View File

@@ -17,27 +17,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_KERNEL_H
#define GCM_KERNEL_H
#ifndef DCM_KERNEL_H
#define DCM_KERNEL_H
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <iostream>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/errinfo_errno.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/mpl/vector.hpp>
#include <time.h>
#include "transformation.hpp"
#include "logging.hpp"
#include "defines.hpp"
#include "multimap.hpp"
#include "property.hpp"
namespace E = Eigen;
@@ -49,6 +38,13 @@ struct nothing {
void operator()() {};
};
//information about solving
struct SolverInfo {
int iterations;
double error;
double time;
};
//the parameter types
enum ParameterType {
general, //every non-rotation parameter, therefore every translation and non transformed parameter
@@ -56,6 +52,11 @@ enum ParameterType {
complete //all parameter
};
enum SolverModes {
continuous,
step
};
//solver settings
struct precision {
@@ -68,6 +69,18 @@ struct precision {
};
};
struct solvermode {
typedef SolverModes type;
typedef setting_property kind;
struct default_value {
SolverModes operator()() {
return continuous;
};
};
};
//and the solver itself
template<typename Kernel>
struct Dogleg {
@@ -76,267 +89,32 @@ struct Dogleg {
#endif
typedef typename Kernel::number_type number_type;
number_type tolg, tolx;
number_type tolg, tolx, delta, nu, g_inf, fx_inf, err, time;
Kernel* m_kernel;
int iter, stop, reduce, unused, counter;
typename Kernel::Vector h_dl, F_old, g;
typename Kernel::Matrix J_old;
Dogleg(Kernel* k) : m_kernel(k), tolg(1e-40), tolx(1e-20){
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
#endif
};
Dogleg(Kernel* k);
Dogleg();
void setKernel(Kernel* k);
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
void calculateStep(const Eigen::MatrixBase<Derived>& g, const Eigen::MatrixBase<Derived3>& jacobi,
const Eigen::MatrixBase<Derived4>& residual, Eigen::MatrixBase<Derived2>& h_dl,
const double delta) {
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
}
};
int solve(typename Kernel::MappedEquationSystem& sys) {
nothing n;
return solve(sys, n);
};
void init(typename Kernel::MappedEquationSystem& sys);
int solve(typename Kernel::MappedEquationSystem& sys, bool continuous = true);
template<typename Functor>
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale) {
clock_t start = clock();
clock_t inc_rec = clock();
if(!sys.isValid())
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
bool translate = true;
typename Kernel::Vector h_dl, F_old(sys.equationCount()), g(sys.equationCount());
typename Kernel::Matrix J_old(sys.equationCount(), sys.parameterCount());
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
sys.removeLocalGradientZeros();
#ifdef USE_LOGGING
BOOST_LOG(log)<< "LGZ jacobi: "<<std::endl<<sys.Jacobi<<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 <= m_kernel->template getProperty<precision>()*sys.Scaling) // Success
stop = 1;
else
if(g_inf <= tolg)
throw solving_error() << boost::errinfo_errno(2) << error_message("g infinity norm smaller below limit");
else
if(delta <= tolx)
throw solving_error() << boost::errinfo_errno(3) << error_message("step size below limit");
else
if(iter >= maxIterNumber)
throw solving_error() << boost::errinfo_errno(4) << error_message("maximal iterations reached");
else
if(!boost::math::isfinite(err))
throw solving_error() << boost::errinfo_errno(5) << error_message("error is inf or nan");
else
if(err > diverging_lim)
throw solving_error() << boost::errinfo_errno(6) << error_message("error diverged");
// 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;
}
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale, bool continuous = true);
};
template<typename Scalar, template<class> class Nonlinear = Dogleg>
struct Kernel : public PropertyOwner< mpl::vector<precision> > {
struct Kernel : public PropertyOwner< mpl::vector2<precision, solvermode> > {
//basics
typedef Scalar number_type;
@@ -403,156 +181,64 @@ struct Kernel : public PropertyOwner< mpl::vector<precision> > {
number_type Scaling;
int parameterCount() {
return m_params;
};
int equationCount() {
return m_eqns;
};
int parameterCount();
int equationCount();
bool rotationOnly();
bool rotationOnly() {
return rot_only;
};
MappedEquationSystem(int params, int equations);
MappedEquationSystem(int params, int equations)
: rot_only(false), m_jacobi(equations, params),
m_parameter(params), Residual(equations),
m_params(params), m_eqns(equations), Scaling(1.),
Jacobi(&m_jacobi(0,0),equations,params,DynStride(equations,1)),
Parameter(&m_parameter(0),params,DynStride(1,1)) {
int setParameterMap(int number, VectorMap& map, ParameterType t = general);
int setParameterMap(Vector3Map& map, ParameterType t = general);
int setResidualMap(VectorMap& map);
void setJacobiMap(int eqn, int offset, int number, CVectorMap& map);
void setJacobiMap(int eqn, int offset, int number, VectorMap& map);
m_param_rot_offset = 0;
m_param_trans_offset = params;
m_eqn_offset = 0;
bool isValid();
m_jacobi.setZero(); //important as some places are never written
};
void setAccess(ParameterType t);
int setParameterMap(int number, VectorMap& map, ParameterType t = general) {
if(t == rotation) {
new(&map) VectorMap(&m_parameter(m_param_rot_offset), number, DynStride(1,1));
m_param_rot_offset += number;
return m_param_rot_offset-number;
}
else {
m_param_trans_offset -= number;
new(&map) VectorMap(&m_parameter(m_param_trans_offset), number, DynStride(1,1));
return m_param_trans_offset;
}
};
int setParameterMap(Vector3Map& map, ParameterType t = general) {
if(t == rotation) {
new(&map) Vector3Map(&m_parameter(m_param_rot_offset));
m_param_rot_offset += 3;
return m_param_rot_offset-3;
}
else {
m_param_trans_offset -= 3;
new(&map) Vector3Map(&m_parameter(m_param_trans_offset));
return m_param_trans_offset;
}
};
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(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
void setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
new(&map) VectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
};
bool isValid() {
if(!m_params || !m_eqns)
return false;
return true;
};
void setAccess(ParameterType t) {
if(t==complete) {
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,m_params,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(0),m_params,DynStride(1,1));
}
else
if(t==rotation) {
int num = m_param_trans_offset;
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,num,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(0),num,DynStride(1,1));
}
else
if(t==general) {
int num = m_params - m_param_trans_offset;
new(&Jacobi) MatrixMap(&m_jacobi(0,m_param_trans_offset),m_eqns,num,DynStride(m_eqns,1));
new(&Parameter) VectorMap(&m_parameter(m_param_trans_offset),num,DynStride(1,1));
}
};
void setGeneralEquationAccess(bool general) {
rot_only = !general;
};
bool hasParameterType(ParameterType t) {
if(t==rotation)
return (m_param_rot_offset>0);
else
if(t==general)
return (m_param_trans_offset<m_params);
else
return (m_params>0);
};
virtual void recalculate() = 0;
void setGeneralEquationAccess(bool general);
bool hasParameterType(ParameterType t);
virtual void recalculate() = 0;
virtual void removeLocalGradientZeros() = 0;
};
Kernel() {};
Kernel();
//static comparison versions
template <typename DerivedA,typename DerivedB>
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
return ((p1-p2).squaredNorm() < precission);
}
static bool isSame(number_type t1, number_type t2, number_type precission) {
return (std::abs(t1-t2) < precission);
}
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission);
static bool isSame(number_type t1, number_type t2, number_type precission);
template <typename DerivedA,typename DerivedB>
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
return ((p1+p2).squaredNorm() < precission);
}
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission);
//runtime comparison versions (which use user settings for precission)
template <typename DerivedA,typename DerivedB>
bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1-p2).squaredNorm() < getProperty<precision>());
}
bool isSame(number_type t1, number_type t2) {
return (std::abs(t1-t2) < getProperty<precision>());
}
bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2);
bool isSame(number_type t1, number_type t2);
template <typename DerivedA,typename DerivedB>
bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
return ((p1+p2).squaredNorm() < getProperty<precision>());
}
int solve(MappedEquationSystem& mes) {
nothing n;
return NonlinearSolver(this).solve(mes, n);
};
bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2);
int solve(MappedEquationSystem& mes);
template<typename Functor>
int solve(MappedEquationSystem& mes, Functor& f) {
return NonlinearSolver(this).solve(mes, f);
};
int solve(MappedEquationSystem& mes, Functor& f);
typedef mpl::vector1<precision> properties;
SolverInfo getSolverInfo();
private:
NonlinearSolver m_solver;
};
}
}//dcm
#ifndef DCM_EXTERNAL_CORE
#include "imp/kernel_imp.hpp"
#endif
#endif //GCM_KERNEL_H

View File

@@ -24,16 +24,11 @@
#include <map>
#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>
@@ -67,26 +62,6 @@ namespace fusion = boost::fusion;
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
);
#define EMIT_CALL_DEC(z, n, data) \
template<typename SigMap> \
template < \
typename S \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
> \
void SignalOwner<SigMap>::emitSignal( \
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
) \
{ \
if(m_emit_signals) {\
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 map_type; \
map_type& map = fusion::at<distance>(m_signals); \
for (typename map_type::iterator it=map.begin(); it != map.end(); it++) \
(it->second)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
}\
};
namespace dcm {
/** @defgroup Objects Objects
@@ -164,7 +139,7 @@ protected:
Signals m_signals;
bool m_emit_signals;
int m_signal_count;
int m_signal_count;
};
/**
@@ -202,61 +177,11 @@ struct Object : public PropertyOwner<typename details::properties_by_object<type
Sys* m_system;
};
}; //dcm
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
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 SigMap>
SignalOwner<SigMap>::SignalOwner() : m_emit_signals(true), m_signal_count(0) {};
template<typename SigMap>
template<typename S>
Connection SignalOwner<SigMap>::connectSignal(typename mpl::at<SigMap, 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 map_type;
map_type& map = fusion::at<distance>(m_signals);
map[++m_signal_count] = function;
return m_signal_count;
};
template<typename SigMap>
template<typename S>
void SignalOwner<SigMap>::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 map_type;
map_type& map = fusion::at<distance>(m_signals);
map.erase(c);
};
template<typename SigMap>
void SignalOwner<SigMap>::enableSignals(bool onoff)
{
m_emit_signals = onoff;
};
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
}
#ifndef DCM_EXTERNAL_CORE
#include "imp/object_imp.hpp"
#endif
#endif //GCM_OBJECT_H

View File

@@ -21,20 +21,17 @@
#define GCM_PROPERTY_H
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/buffer_concepts.hpp>
#include <boost/graph/properties.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/fusion/include/sequence.hpp>
#include <boost/fusion/include/container.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/property_map/property_map.hpp>
@@ -446,11 +443,6 @@ struct PropertyOwner {
Properties m_properties;
};
template<typename T>
void pretty(T t) {
std::cout<<__PRETTY_FUNCTION__<<std::endl;
};
template<typename PropertyList>
PropertyOwner<PropertyList>::PropertyOwner() {

View File

@@ -21,40 +21,50 @@
#define GCM_SYSTEM_H
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector/vector0.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/vector/vector0.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"
#include "object.hpp"
#include "kernel.hpp"
namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace dcm {
struct No_Identifier {};
struct Unspecified_Identifier {};
struct No_Identifier {}; //struct to show that no identifier shall be used
struct Unspecified_Identifier {}; //struct to show that it dosen't matter which identifier type is used
struct solved {}; //signal emitted when solving is done
namespace details {
enum { subcluster = 10};
/**
* @brief Appends a mpl sequences to another
*
* Makes two sequence to one by appending all types of the first to the second sequence. The new
* mpl sequence can be accessed by the ::type typedef.
* Usage: @code vector_fold<Seq1, Seq2>::type @endcode
*
* @tparam state the mpl sequence which will be expanded
* @tparam seq the mpl sequence which will be appended
**/
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>,
@@ -84,6 +94,15 @@ struct get_identifier {
template<typename seq, typename state>
struct map_fold : mpl::fold< seq, state, mpl::insert<mpl::_1,mpl::_2> > {};
template<typename state, typename seq1, typename seq2, typename seq3>
struct map_fold_3 {
typedef typename details::map_fold<seq1,
typename details::map_fold<seq2,
typename details::map_fold<seq3,
state >::type >::type>::type type;
};
struct nothing {};
template<int v>
@@ -91,10 +110,13 @@ struct EmptyModule {
template<typename T>
struct type {
struct inheriter {};
struct inheriter {
void system_sub(boost::shared_ptr<T> subsys) {};
};
typedef mpl::vector<> properties;
typedef mpl::vector<> objects;
typedef mpl::vector<> geometries;
typedef mpl::map<> signals;
typedef Unspecified_Identifier Identifier;
static void system_init(T& sys) {};
@@ -107,22 +129,33 @@ struct is_shared_ptr : boost::mpl::false_ {};
template <class T>
struct is_shared_ptr<boost::shared_ptr<T> > : boost::mpl::true_ {};
template<typename Sys, typename M1, typename M2, typename M3>
struct inheriter : public M1::inheriter, public M2::inheriter, public M3::inheriter,
dcm::SignalOwner<typename details::map_fold_3< mpl::map<mpl::pair<solved, boost::function<void (Sys*)> > >,
typename M1::signals, typename M2::signals, typename M3::signals>::type> {};
}
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 {
class System : public details::inheriter<System<KernelType,T1,T2,T3>, typename T1::template type< System<KernelType,T1,T2,T3> >,
typename T2::template type< System<KernelType,T1,T2,T3> >,
typename T3::template type< System<KernelType,T1,T2,T3> > > {
typedef System<KernelType,T1,T2,T3> BaseType;
public:
typedef T1 Module1;
typedef T2 Module2;
typedef T3 Module3;
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;
typedef typename Type1::inheriter Inheriter1;
typedef typename Type2::inheriter Inheriter2;
typedef typename Type3::inheriter Inheriter3;
//Check if all Identifiers are the same and find out which type it is
typedef typename mpl::fold<TypeVector, mpl::vector<>,
@@ -162,6 +195,12 @@ public:
mpl::vector1<vertex_index_prop> >::type vertex_properties;
typedef typename details::cluster_fold< properties,
mpl::vector2<changed_prop, type_prop> >::type cluster_properties;
//we hold our own PropertyOwner which we use for system settings. Don't inherit it as the user
//should not access the settings via the proeprty getter and setter functions.
typedef PropertyOwner<typename details::properties_by_kind<properties, setting_property>::type> OptionOwner;
OptionOwner m_options;
protected:
//object storage
@@ -173,18 +212,6 @@ protected:
template<typename FT1, typename FT2, typename FT3>
friend struct Object;
struct clearer {
template<typename T>
void operator()(T& vector) const {
vector.clear();
};
};
//we hold our own PropertyOwner which we use for system settings. Don't inherit it as the user
//should not access the settings via the proeprty getter and setter functions.
typedef PropertyOwner<typename details::properties_by_kind<properties, setting_property>::type> SettingOwner;
SettingOwner m_settings;
#ifdef USE_LOGGING
boost::shared_ptr< sink_t > sink;
#endif
@@ -195,173 +222,73 @@ public:
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();
~System();
~System() {
#ifdef USE_LOGGING
stop_log(sink);
#endif
};
void clear() {
m_cluster->clearClusters();
m_cluster->clear();
fusion::for_each(*m_storage, clearer());
};
void clear();
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();
};
typename std::vector< boost::shared_ptr<Object> >::iterator 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();
};
typename std::vector< boost::shared_ptr<Object> >::iterator 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);
};
std::vector< boost::shared_ptr<Object> >& objectVector();
template<typename Object>
void push_back(boost::shared_ptr<Object> ptr) {
objectVector<Object>().push_back(ptr);
};
void push_back(boost::shared_ptr<Object> ptr);
template<typename Object>
void erase(boost::shared_ptr<Object> ptr) {
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);
};
SolverInfo solve();
System* createSubsystem() {
System* s = new System();
s->m_cluster = m_cluster->createCluster().first;
s->m_storage = m_storage;
s->m_cluster->template setProperty<dcm::type_prop>(details::subcluster);
#ifdef USE_LOGGING
stop_log(s->sink);
#endif
return s;
};
boost::shared_ptr< System > createSubsystem();
typename std::vector< boost::shared_ptr<System> >::iterator beginSubsystems();
typename std::vector< boost::shared_ptr<System> >::iterator endSubsystems();
//a kernel has it's own settings, therefore we need to decide which is accessed
template<typename Setting>
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
typename mpl::end<typename Kernel::properties>::type >, typename Setting::type& >::type getSetting() {
return m_settings.template getProperty<Setting>();
};
template<typename Option>
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
typename mpl::end<typename Kernel::PropertySequence>::type >, typename Option::type& >::type getOption();
template<typename Setting>
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
typename mpl::end<typename Kernel::properties>::type >, typename Setting::type& >::type getSetting() {
return m_kernel.template getProperty<Setting>();
};
template<typename Option>
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
typename mpl::end<typename Kernel::PropertySequence>::type >, typename Option::type& >::type getOption();
template<typename Setting>
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
typename mpl::end<typename Kernel::properties>::type >, void >::type setSetting(typename Setting::type value){
m_settings.template setProperty<Setting>(value);
};
template<typename Option>
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
typename mpl::end<typename Kernel::PropertySequence>::type >, void >::type setOption(typename Option::type value);
template<typename Setting>
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
typename mpl::end<typename Kernel::properties>::type >, void >::type setSetting(typename Setting::type value){
m_kernel.template setProperty<Setting>(value);
};
template<typename Option>
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
typename mpl::end<typename Kernel::PropertySequence>::type >, void >::type setOption(typename Option::type value);
//convinience function
template<typename Setting>
typename Setting::type& setting() {
return getSetting<Setting>();
};
template<typename Option>
typename Option::type& option();
//let evryone access and use our math kernel
Kernel& kernel() {
return m_kernel;
};
Kernel& kernel();
private:
struct cloner {
void copyInto(System& into) const;
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;
};
System* clone() const;
boost::shared_ptr<Cluster> m_cluster;
boost::shared_ptr<Storage> m_storage;
Shedule m_sheduler;
Kernel m_kernel;
std::vector<boost::shared_ptr<System> > m_subsystems;
};
}
#ifndef DCM_EXTERNAL_CORE
#include "imp/system_imp.hpp"
#endif
#endif //GCM_SYSTEM_H
@@ -374,3 +301,5 @@ public:

View File

@@ -17,17 +17,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_TRAITS_H
#define GCM_TRAITS_H
#ifndef DCM_TRAITS_H
#define DCM_TRAITS_H
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/at.hpp>
#include <string.h>
@@ -71,32 +69,7 @@ struct compare_traits<std::string> {
};
};
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

@@ -48,187 +48,71 @@ protected:
Scaling m_scale;
public:
Transform() : m_rotation(Rotation::Identity()),
m_translation(Translation::Identity()),
m_scale(Scaling(1.)) { };
Transform();
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();
};
Transform(const Rotation& r);
Transform(const Rotation& r, const Translation& t);
Transform(const Rotation& r, const Translation& t, const Scaling& s);
//access the single parts and manipulate them
//***********************
const Rotation& rotation() const {
return m_rotation;
}
const Rotation& rotation() const;
template<typename Derived>
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
m_rotation = rotation.derived().normalized()*m_rotation;
return *this;
}
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation);
const Translation& translation() const {
return m_translation;
}
Transform& translate(const Translation& translation) {
m_translation = m_translation*translation;
return *this;
}
const Translation& translation() const;
Transform& translate(const Translation& translation);
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;
}
const Scaling& scaling() const;
Transform& scale(const Scalar& scaling);
Transform& scale(const Scaling& scaling);
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;
};
Transform& invert();
Transform inverse();
//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);
}
Transform& operator=(const Translation& t);
Transform operator*(const Translation& s) const;
Transform& operator*=(const Translation& 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);
}
Transform& operator=(const Scaling& s);
Transform operator*(const Scaling& s) const;
Transform& operator*=(const Scaling& 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;
}
Transform& operator=(const Eigen::RotationBase<Derived,Dim>& r);
template<typename Derived>
inline Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
Transform res = *this;
res.rotate(r.derived());
return res;
}
Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const;
template<typename Derived>
inline Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
return rotate(r.derived());
}
Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r);
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 operator* (const Transform& other) const;
Transform& operator*= (const Transform& other);
//transform Vectors
//*****************
template<typename Derived>
inline Derived& rotate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_rotation*vec;
return vec.derived();
}
Derived& rotate(Eigen::MatrixBase<Derived>& vec) const;
template<typename Derived>
inline Derived& translate(Eigen::MatrixBase<Derived>& vec) const {
vec = m_translation*vec;
return vec.derived();
}
Derived& translate(Eigen::MatrixBase<Derived>& vec) const;
template<typename Derived>
inline Derived& scale(Eigen::MatrixBase<Derived>& vec) const {
vec*=m_scale.factor();
return vec.derived();
}
Derived& scale(Eigen::MatrixBase<Derived>& vec) const;
template<typename Derived>
inline Derived& transform(Eigen::MatrixBase<Derived>& vec) const {
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
return vec.derived();
}
Derived& transform(Eigen::MatrixBase<Derived>& vec) const;
template<typename Derived>
inline Derived operator*(const Eigen::MatrixBase<Derived>& vec) const {
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
}
Derived operator*(const Eigen::MatrixBase<Derived>& vec) const;
template<typename Derived>
inline void operator()(Eigen::MatrixBase<Derived>& vec) const {
transform(vec);
}
void operator()(Eigen::MatrixBase<Derived>& vec) const;
//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));
}
bool isApprox(const Transform& other, Scalar prec) const;
void setIdentity();
static const Transform Identity();
Transform& normalize() {
m_rotation.normalize();
return *this;
}
Transform& normalize();
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
@@ -250,21 +134,11 @@ public:
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()) {
DiffTransform(Transform<Scalar, Dim>& trans);
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);
};
const DiffMatrix& differential();
Scalar& operator()(int f, int s);
Scalar& at(int f, int s);
};
/*When you overload a binary operator as a member function of a class the overload is used
@@ -272,26 +146,18 @@ public:
* is the stream and not (usually) the custom class.
*/
template<typename charT, typename traits, typename Kernel, int Dim>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& 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;
}
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, const dcm::detail::Transform<Kernel, Dim>& t);
template<typename charT, typename traits,typename Kernel, int Dim>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& 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;
}
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, dcm::detail::DiffTransform<Kernel, Dim>& t);
}//detail
}//DCM
#ifndef DCM_EXTERNAL_CORE
#include "imp/transformation_imp.hpp"
#endif
#endif //DCM_TRANSFORMATION

View File

@@ -38,7 +38,36 @@
#ifdef DCM_USE_MODULESTATE
#include "module3d/state.hpp"
#endif
#endif //use state
#ifdef DCM_EXTERNAL_3D
#define DCM_EXTERNAL_3D_INCLUDE_01 "opendcm/module3d/imp/clustermath_imp.hpp"
#define DCM_EXTERNAL_3D_01( Sys )\
template struct dcm::details::ClusterMath<Sys>;\
template struct dcm::details::MES<Sys>;\
template struct Sys::Kernel::MappedEquationSystem;\
template struct dcm::details::SystemSolver<Sys>;
#define DCM_EXTERNAL_3D_INCLUDE_02 "opendcm/module3d/imp/constraint3d_holder_imp.hpp"
#define DCM_EXTERNAL_3D_02( System )\
INITIALIZE(System, 3, CONSTRAINT_SEQUENCE);
#define DCM_EXTERNAL_3D_INCLUDE_03 <opendcm/module3d/imp/state_imp.hpp>
#define DCM_EXTERNAL_3D_03( System )\
template struct dcm::parser_generator< dcm::details::getModule3D< System >::type::Geometry3D , System, std::ostream_iterator<char> >; \
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::vertex_prop , System, std::ostream_iterator<char> >; \
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::Constraint3D , System, std::ostream_iterator<char> >; \
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::edge_prop , System, std::ostream_iterator<char> >; \
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::fix_prop, System, std::ostream_iterator<char> >; \
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::edge_prop, System, boost::spirit::istream_iterator >; \
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::vertex_prop, System, boost::spirit::istream_iterator >; \
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::fix_prop, System, boost::spirit::istream_iterator >; \
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::Geometry3D, System, boost::spirit::istream_iterator >; \
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::Constraint3D, System, boost::spirit::istream_iterator >;
#endif //external 3d
#endif //DCM_MODULE3D_H

View File

@@ -29,7 +29,7 @@ namespace dcm {
namespace details {
//we need a custom orientation type to allow coincidents with points. We can't use the ci_orietation
//as some geometries are supporte by align but not by coincident
struct al_orientation : public Equation<al_orientation, Direction, true> {
struct al_orientation : public Equation<al_orientation, Direction, 6, true> {
using Equation::operator=;
using Equation::options;

View File

@@ -17,14 +17,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_CLUSTERMATH_H
#define GCM_CLUSTERMATH_H
#ifndef DCM_CLUSTERMATH_H
#define DCM_CLUSTERMATH_H
#include <vector>
#include <cmath>
#include <Eigen/StdVector>
#include <boost/noncopyable.hpp>
#include <opendcm/core/logging.hpp>
#include <opendcm/core/kernel.hpp>
#include "defines.hpp"
@@ -141,639 +138,12 @@ public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Sys>
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
m_resetTransform = Eigen::AngleAxisd(M_PI*2./3., Eigen::Vector3d(1,1,1).normalized());
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, dcm::ParameterType t) {
if(t == general)
m_offset = offset;
else
m_offset_rot = offset;
};
template<typename Sys>
int ClusterMath<Sys>::getParameterOffset(ParameterType t) {
if(t == general)
return m_offset;
else
return m_offset_rot;
};
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() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish calculation";
#endif
mapsToTransform(m_transform);
init=false;
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().inverse();
};
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(general);
g->m_offset_rot = m_clusterMath.getParameterOffset(rotation);
//position and offset of the parameters must be set to the clusters values
g->setClusterMode(true, m_isFixed);
//calculate the appropriate local values
g->transform(m_transform);
};
template<typename Sys>
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
//we transform the GLOBAL geometries to local ones in the subcluster! therefore
//we are not interested in the successive transformations, we only transform the
//global geometries with the cluster transform we want them to be local in, and thats
//the one supplied in the constructor
//m_transform *= c->template getClusterProperty<math_prop>().getTransform().inverse();
};
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 getProperty<math_prop>(),
cluster->template getProperty<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()) return 1.;
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., 1e-10))
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., 1e-10)) {
if(Kernel::isSame(e.norm(), 0., 1e-10))
return calcOnePoint(p1);
return calcTwoPoints(p1, p3);
} else if(Kernel::isSame(e.norm(), 0., 1e-10)) {
return calcTwoPoints(p1, p2);
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0., 1e-10) &&
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0., 1e-10)) {
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, 1e-10)) {
}
//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, 1e-10))
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, 1e-10)) 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
#ifndef DCM_EXTERNAL_3D
#include "imp/clustermath_imp.hpp"
#endif
#endif //GCM_CLUSTERMATH_H

View File

@@ -28,7 +28,7 @@ namespace dcm {
namespace details {
//we need a custom orientation type to allow coincidents with points
struct ci_orientation : public Equation<ci_orientation, Direction, true> {
struct ci_orientation : public Equation<ci_orientation, Direction, 4, true> {
using Equation::operator=;
using Equation::options;
@@ -184,7 +184,7 @@ struct ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public
//we need a custom distance type to use point-distance functions instead of real geometry distance
struct ci_distance : public Equation<ci_distance, mpl::vector2<double, SolutionSpace> > {
struct ci_distance : public Equation<ci_distance, mpl::vector2<double, SolutionSpace>, 5 > {
using Equation::operator=;
using Equation::options;

View File

@@ -28,6 +28,7 @@ enum { cluster3D = 100};
struct m3d {}; //base of module3d::type to allow other modules check for it
}
}
#endif

View File

@@ -22,6 +22,7 @@
#include "geometry.hpp"
#include <opendcm/core/constraint.hpp>
#include <boost/fusion/include/copy.hpp>
namespace dcm {

View File

@@ -0,0 +1,667 @@
/*
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_CLUSTERMATH_IMP_H
#define DCM_CLUSTERMATH_IMP_H
#include "../clustermath.hpp"
#ifdef DCM_EXTERNAL_CORE
#include "opendcm/core/imp/transformation_imp.hpp"
#endif
//include it here as it is in the same external compilation unit as clustermath
#include "solver_imp.hpp"
namespace dcm {
namespace details {
template<typename Sys>
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
m_resetTransform = Eigen::AngleAxisd(M_PI*2./3., Eigen::Vector3d(1,1,1).normalized());
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, dcm::ParameterType t) {
if(t == general)
m_offset = offset;
else
m_offset_rot = offset;
};
template<typename Sys>
int ClusterMath<Sys>::getParameterOffset(ParameterType t) {
if(t == general)
return m_offset;
else
return m_offset_rot;
};
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() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "Finish calculation";
#endif
mapsToTransform(m_transform);
init=false;
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().inverse();
};
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(general);
g->m_offset_rot = m_clusterMath.getParameterOffset(rotation);
//position and offset of the parameters must be set to the clusters values
g->setClusterMode(true, m_isFixed);
//calculate the appropriate local values
g->transform(m_transform);
};
template<typename Sys>
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
//we transform the GLOBAL geometries to local ones in the subcluster! therefore
//we are not interested in the successive transformations, we only transform the
//global geometries with the cluster transform we want them to be local in, and thats
//the one supplied in the constructor
//m_transform *= c->template getClusterProperty<math_prop>().getTransform().inverse();
};
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 getProperty<math_prop>(),
cluster->template getProperty<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()) return 1.;
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., 1e-10))
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., 1e-10)) {
if(Kernel::isSame(e.norm(), 0., 1e-10))
return calcOnePoint(p1);
return calcTwoPoints(p1, p3);
} else if(Kernel::isSame(e.norm(), 0., 1e-10)) {
return calcTwoPoints(p1, p2);
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0., 1e-10) &&
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0., 1e-10)) {
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, 1e-10)) {
}
//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, 1e-10))
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, 1e-10)) 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,87 @@
/*
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_CONSTRAINT_3D_HOLDER_IMP_H
#define DCM_CONSTRAINT_3D_HOLDER_IMP_H
#include "../geometry.hpp"
#include "opendcm/core/imp/constraint_holder_imp.hpp"
#ifdef DCM_EXTERNAL_CORE
//following macros are used for externalisation. As the holder type can hould a very big set of combinations,
//especially with module states recursive incarnation, we explicitly initiate all possible versions of this
//struct so that it must only be compiled once. To get all possible equation
//combinations boost pp is needed.
template<typename T>
struct fusion_vec {
typedef typename mpl::if_< mpl::is_sequence<T>, T, fusion::vector1<T> >::type type;
};
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/for.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/push_front.hpp>
#include <boost/preprocessor/seq/remove.hpp>
#define TAG_SEQUENCE (dcm::tag::direction3D)(dcm::tag::point3D)(dcm::tag::line3D)(dcm::tag::plane3D)(dcm::tag::cylinder3D)
#define CONSTRAINT_SEQUENCE (dcm::Distance)(dcm::Orientation)(dcm::Angle)(dcm::Coincidence)(dcm::Alignment)
#define LEVEL_2_TYPE(r, state) \
template struct dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::holder<fusion_vec<BOOST_PP_SEQ_ELEM(2,state)>::type, BOOST_PP_SEQ_ELEM(3,state), BOOST_PP_SEQ_ELEM(4,state)>;
#define LEVEL_2_TYPE_OP(r, state) \
BOOST_PP_SEQ_REMOVE(state,4)
#define LEVEL_2_TYPE_PRED(r, state) \
BOOST_PP_LESS(4,BOOST_PP_SEQ_SIZE(state))
#define LEVEL_1_TYPE(r, state) \
template struct dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::holder<fusion_vec<BOOST_PP_SEQ_ELEM(2,state)>::type, BOOST_PP_SEQ_ELEM(3,state), BOOST_PP_SEQ_ELEM(3,state)>;\
BOOST_PP_FOR(state, LEVEL_2_TYPE_PRED, LEVEL_2_TYPE_OP, LEVEL_2_TYPE)
#define LEVEL_1_TYPE_OP(r, state) \
BOOST_PP_SEQ_REMOVE(state,3)
#define LEVEL_1_TYPE_PRED(r, state) \
BOOST_PP_LESS(3,BOOST_PP_SEQ_SIZE(state))
#define INITIALIZE_TYPES(System, Dim, Covec, SEQUENCE) \
BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Covec), Dim), System), LEVEL_1_TYPE_PRED, LEVEL_1_TYPE_OP, LEVEL_1_TYPE)
#define LEVEL_1(r, state) \
INITIALIZE_TYPES(BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state), BOOST_PP_SEQ_ELEM(2,state), TAG_SEQUENCE) \
#define LEVEL_1_OP(r, state) \
BOOST_PP_SEQ_REMOVE(state,2)
#define LEVEL_1_PRED(r, state) \
BOOST_PP_LESS(2,BOOST_PP_SEQ_SIZE(state))
#define INITIALIZE(System, Dim, SEQUENCE) \
BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Dim), System), LEVEL_1_PRED, LEVEL_1_OP, LEVEL_1)
#endif //external
#endif

View File

@@ -0,0 +1,119 @@
/*
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_CONSTRAINT_3D_IMP_H
#define DCM_CONSTRAINT_3D_IMP_H
#include "../module.hpp"
#ifdef DCM_EXTERNAL_CORE
#include "opendcm/core/imp/constraint_imp.hpp"
#include "opendcm/core/imp/object_imp.hpp"
#include "opendcm/core/imp/clustergraph_imp.hpp"
#endif
// #ifdef DCM_EXTERNAL_CORE
// //following macros are used for externalisation. As constraint->initalize is very compiler intensive,
// //especially with module states recursive incarnation, we explicitly initiate all possible calls to this
// //function so that it must only be compiled once, one function at a time. To get all possible equation
// //combinations boost pp is needed.
//
// #include <boost/preprocessor.hpp>
// #include <boost/preprocessor/for.hpp>
// #include <boost/preprocessor/comparison/less.hpp>
// #include <boost/preprocessor/seq/size.hpp>
// #include <boost/preprocessor/seq/enum.hpp>
// #include <boost/preprocessor/seq/elem.hpp>
// #include <boost/preprocessor/seq/push_front.hpp>
// #include <boost/preprocessor/seq/remove.hpp>
//
// #define SEQUENCE (dcm::Distance)(dcm::Orientation)(dcm::Angle)(dcm::Coincidence)(dcm::Alignment)
//
// #define LEVEL_1(r, state) \
// template void dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::initialize(BOOST_PP_SEQ_ELEM(2,state)&); \
//
// #define LEVEL_1_OP(r, state) \
// BOOST_PP_SEQ_REMOVE(state,2)
//
// #define LEVEL_1_PRED(r, state) \
// BOOST_PP_LESS(2,BOOST_PP_SEQ_SIZE(state))
//
// #define INITIALIZE(System, Dim) \
// BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Dim), System), LEVEL_1_PRED, LEVEL_1_OP, LEVEL_1)
//
// #endif //external
namespace dcm {
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Constraint3D_base<Derived>::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 = CBase::content->clone();
//and get the geometry pointers right
if(CBase::first) {
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::first)->template getProperty<vertex_prop>();
np->first = newSys.m_cluster->template getObject<Geometry3D>(v);
}
if(CBase::second) {
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::second)->template getProperty<vertex_prop>();
np->second = newSys.m_cluster->template getObject<Geometry3D>(v);
}
return np;
};
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)
: Constraint3D_base<Derived>(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>,
Constraint3D_base<Constraint3D>,
Constraint3D_id<Constraint3D> >::type(system, first, second) {
};
} //dcm
#endif //DCM_MODULE_3D_IMP_H

View File

@@ -0,0 +1,256 @@
/*
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_GEOMETRY_3D_IMP_H
#define DCM_GEOMETRY_3D_IMP_H
#include "../module.hpp"
#ifdef DCM_EXTERNAL_CORE
#include "opendcm/core/imp/geometry_imp.hpp"
#include "opendcm/core/imp/object_imp.hpp"
#endif
namespace dcm {
namespace details {
template<typename Variant>
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
template<typename Kernel>
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;
};
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(Sys& system)
: Object<Sys, Derived, GeomSig>(system) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
#endif
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(const T& geometry, Sys& system)
: Object<Sys, Derived, GeomSig>(system) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
#endif
m_geometry = geometry;
//first init, so that the geometry internal vector has the right size
Base::template init< typename geometry_traits<T>::tag >();
//now write the value;
(typename geometry_traits<T>::modell()).template extract<Scalar,
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::set(const T& geometry) {
m_geometry = geometry;
//first init, so that the geometry internal vector has the right size
Base::template init< typename geometry_traits<T>::tag >();
//now write the value;
(typename geometry_traits<T>::modell()).template extract<Scalar,
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
reset();
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
T Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::convertTo() {
T t;
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
typename geometry_traits<T>::accessor >(t, Base::m_global);
return t;
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename Visitor>
typename Visitor::result_type Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::apply(Visitor& vis) {
return boost::apply_visitor(vis, m_geometry);
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::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
details::cloner<Variant> clone_fnc(np->m_geometry);
boost::apply_visitor(clone_fnc, m_geometry);
return np;
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::recalculated() {
details::apply_visitor<Kernel> v(Base::getValue());
apply(v);
ObjBase::template emitSignal<dcm::recalculated>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::removed() {
ObjBase::template emitSignal<dcm::remove>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::reset() {
ObjBase::template emitSignal<dcm::reset>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(Sys& system)
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(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>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(const T& geometry, Sys& system)
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(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(const 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(const 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>
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(Sys& system)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
Geometry3D_base<Geometry3D>,
Geometry3D_id<Geometry3D> >::type(system) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(const T& geometry, Sys& system)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
Geometry3D_base<Geometry3D>,
Geometry3D_id<Geometry3D> >::type(geometry, system) {
};
} //dcm
#endif //DCM_MODULE_3D_IMP_H

View File

@@ -0,0 +1,268 @@
/*
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_MODULE_3D_IMP_H
#define DCM_MODULE_3D_IMP_H
#include "../module.hpp"
#include <boost/bind.hpp>
#include "constraint3d_imp.hpp"
#include "geometry3d_imp.hpp"
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 > >));
// };
//build a constraint vector
template<typename T>
struct fusion_vec {
typedef typename mpl::if_< mpl::is_sequence<T>,
T, fusion::vector1<T> >::type type;
};
struct set_constraint_option {
template<typename T>
typename boost::enable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
operator()(T& val) {
return val;
};
template<typename T>
typename boost::disable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
operator()(T& val) {
typename fusion_vec<T>::type vec;
fusion::at_c<0>(vec) = val;
return vec;
};
};
}
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>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D() {
Geom g(new Geometry3D(* ((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>
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) {
//get the fusion vector type
typedef typename details::fusion_vec<T1>::type covec;
//set the objects
covec cv = details::set_constraint_option()(constraint1);
//now create the constraint
Cons c(new Constraint3D(*m_this, first, second));
//initialize constraint
c->initialize(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>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(Identifier id) {
Geom g = inheriter_base::createGeometry3D();
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));
else
throw module3d_error() << boost::errinfo_errno(410) << error_message("no geometry with this ID in this system");
};
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));
else
throw module3d_error() << boost::errinfo_errno(411) << error_message("no constraint with this ID in this system");
};
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 //DCM_MODULE_3D_IMP_H

View File

@@ -0,0 +1,410 @@
/*
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_SOLVER_3D_IMP_H
#define DCM_SOLVER_3D_IMP_H
#include "../solver.hpp"
#include <boost/graph/undirected_dfs.hpp>
#ifdef DCM_EXTERNAL_CORE
#include "opendcm/core/imp/kernel_imp.hpp"
#include "opendcm/core/imp/clustergraph_imp.hpp"
#endif
namespace dcm {
namespace details {
template<typename Sys>
MES<Sys>::MES(boost::shared_ptr<Cluster> cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("MES3D"));
#endif
};
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 getProperty<fix_prop>())
(*cit.first).second->template getProperty<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, Base::rot_only);
}
}
};
template<typename Sys>
void MES<Sys>::removeLocalGradientZeros() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "remove local gradient zero";
#endif
//let the constraints treat the local zeros
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)->treatLGZ();
}
}
};
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 getProperty<fix_prop>())
continue;
//get the biggest scale factor
details::ClusterMath<Sys>& math = (*cit.first).second->template getProperty<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, 1e-10)) ? 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 getProperty<math_prop>().applyClusterScale(sc,
c->template getProperty<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::global_edge_iterator 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->getGlobalEdges(*it.first);
for(; cit.first != cit.second; cit.first++) {
Cons c = parent->template getObject<Constraint3D>(*cit.first);
if(!c)
continue;
//get the first global vertex and see if we have it in the wanted cluster or not
GlobalVertex v = cit.first->source;
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) {
try {
//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 getProperty<changed_prop>() &&
c->template getProperty<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();
};
if(params <= 0 || constraints <= 0) {
//TODO:throw
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Error in system counting: params = " << params << " and constraints = "<<constraints;
#endif
return;
}
//initialise the system with now known size
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 getProperty<math_prop>();
//only get maps and propagate downstream if not fixed
if(!c->template getProperty<fix_prop>()) {
//set norm Quaternion as map to the parameter vector
int offset_rot = mes.setParameterMap(cm.getNormQuaternionMap(), rotation);
//set translation as map to the parameter vector
int offset = mes.setParameterMap(cm.getTranslationMap(), general);
//write initail values to the parameter maps
//remember the parameter offset as all downstream geometry must use this offset
cm.setParameterOffset(offset_rot, rotation);
cm.setParameterOffset(offset, general);
//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);
g->initMap(&mes);
}
}
//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)
}
}
//if we don't have rotations we need no expensive scaling code
if(!mes.hasParameterType(rotation)) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "No rotation parameters in system, solve without scaling";
#endif
DummyScaler re;
sys.kernel().solve(mes, re);
}
else {
// we have rotations, so let's check our options. first search for cycles, as systems with them
// always need the full solver power
bool has_cycle;
cycle_dedector cd(has_cycle);
//create te needed property maps and fill it
property_map<vertex_index_prop, Cluster> vi_map(cluster);
cluster->initIndexMaps();
typedef std::map< LocalVertex, boost::default_color_type> vcmap;
typedef std::map< LocalEdge, boost::default_color_type> ecmap;
vcmap v_cm;
ecmap e_cm;
boost::associative_property_map< vcmap > v_cpm(v_cm);
boost::associative_property_map< ecmap > e_cpm(e_cm);
boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(v_cpm).edge_color_map(e_cpm));
bool done = false;
if(!has_cycle) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "non-cyclic system dedected";
#endif
//cool, lets do uncylic. first all rotational constraints with rotational parameters
mes.setAccess(rotation);
mes.setGeneralEquationAccess(false);
//solve can be done without catching exceptions, because this only fails if the system in
//unsolvable
DummyScaler re;
sys.kernel().solve(mes, re);
//now let's see if we have to go on with the translations
mes.setAccess(general);
mes.setGeneralEquationAccess(true);
mes.recalculate();
if(mes.Residual.norm()<1e-6)
done = true;
else {
//let's try translation only
try {
DummyScaler re;
sys.kernel().solve(mes, re);
done=true;
}
catch(boost::exception&) {
//not successful, so we need brute force
done = false;
}
}
};
//not done already? try it the hard way!
if(!done) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Full scale solver used";
#endif
Rescaler re(cluster, mes);
re();
sys.kernel().solve(mes, re);
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
#endif
};
}
//solving is done, now go to all relevant geometries and clusters and write the values back
//(no need to emit recalculated signal as this cluster is never recalculated in this run)
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 getProperty<math_prop>().finishCalculation();
else
c->template getProperty<math_prop>().finishFixCalculation();
std::vector<Geom>& vec = c->template getProperty<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 setProperty<changed_prop>(false);
}
catch(boost::exception&) {
throw;
}
};
}//details
}//dcm
#endif //DCM_SOLVER_3D_HPP

View File

@@ -0,0 +1,373 @@
/*
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_IMP_HPP
#define DCM_MODULE3D_STATE_IMP_HPP
#include "../state.hpp"
#include "../module.hpp"
#include "../coincident.hpp"
#include "../alignment.hpp"
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/phoenix/fusion/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/greater.hpp>
namespace karma_ascii = boost::spirit::karma::ascii;
namespace qi_ascii = boost::spirit::qi::ascii;
namespace phx = boost::phoenix;
#include <ios>
namespace karma = boost::spirit::karma;
namespace qi = boost::spirit::qi;
namespace karma_ascii = boost::spirit::karma::ascii;
namespace qi_ascii = boost::spirit::qi::ascii;
namespace phx = boost::phoenix;
namespace dcm {
namespace details {
struct geom_visitor : public boost::static_visitor<std::string> {
template<typename T>
std::string operator()(T& i) const {
//we use stings in case new geometry gets added and the weights shift, meaning: backwards
//compatible
std::string type;
switch(geometry_traits<T>::tag::weight::value) {
case tag::weight::direction::value :
return "direction";
case tag::weight::point::value :
return "point";
case tag::weight::line::value :
return "line";
case tag::weight::plane::value :
return "plane";
case tag::weight::cylinder::value :
return "cylinder";
default:
return "unknown";
};
};
};
template<typename T>
std::string getWeight(boost::shared_ptr<T> ptr) {
geom_visitor v;
return ptr->apply(v);
};
template<typename T>
struct get_weight {
typedef typename geometry_traits<T>::tag::weight type;
};
//search the first type in the typevector with the given weight
template<typename Vector, typename Weight>
struct getWeightType {
typedef typename mpl::find_if<Vector, boost::is_same<get_weight<mpl::_1>, Weight > >::type iter;
typedef typename mpl::if_< boost::is_same<iter, typename mpl::end<Vector>::type >, mpl::void_, typename mpl::deref<iter>::type>::type type;
};
typedef std::vector< fusion::vector2<std::string, std::string> > string_vec;
typedef std::vector< fusion::vector2<std::vector<char>, std::vector<char> > > char_vec;
template<typename C>
string_vec getConstraints(boost::shared_ptr<C> con) {
string_vec vec;
std::vector<boost::any> cvec = con->getGenericConstraints();
typename std::vector<boost::any>::iterator it;
for(it = cvec.begin(); it != cvec.end(); it++) {
if((*it).type() == typeid(dcm::Distance)) {
double v = fusion::at_key<double>(boost::any_cast<dcm::Distance>(*it).values).second;
std::string value = boost::lexical_cast<std::string>(v);
vec.push_back(fusion::make_vector(std::string("Distance"), value));
}
else if((*it).type() == typeid(dcm::Angle)) {
double v = fusion::at_key<double>(boost::any_cast<dcm::Angle>(*it).values).second;
std::string value = boost::lexical_cast<std::string>(v);
vec.push_back(fusion::make_vector(std::string("Angle"), value));
}
else if((*it).type() == typeid(dcm::Orientation)) {
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::Orientation>(*it).values).second;
std::string value = boost::lexical_cast<std::string>(v);
vec.push_back(fusion::make_vector(std::string("Orientation"), value));
}
else if((*it).type() == typeid(dcm::details::ci_orientation)) {
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::details::ci_orientation>(*it).values).second;
std::string value = boost::lexical_cast<std::string>(v);
vec.push_back(fusion::make_vector(std::string("Coincidence"), value));
}
else if((*it).type() == typeid(dcm::details::al_orientation)) {
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::details::al_orientation>(*it).values).second;
std::string value = boost::lexical_cast<std::string>(v);
vec.push_back(fusion::make_vector(std::string("Alignment"), value));
};
};
return vec;
};
template<typename C>
void constraintCreation(typename char_vec::iterator it,
typename char_vec::iterator end,
boost::shared_ptr<C> con) {
std::string first(fusion::at_c<0>(*it).begin(), fusion::at_c<0>(*it).end());
std::string second(fusion::at_c<1>(*it).begin(), fusion::at_c<1>(*it).end());
if(first.compare("Distance") == 0) {
double v = boost::lexical_cast<double>(second);
typename details::fusion_vec<dcm::Distance>::type val;
fusion::front(val)=v;
con->template initialize(val);
return;
}
else if(first.compare("Orientation") == 0) {
dcm::Direction v = (dcm::Direction)boost::lexical_cast<int>(second);
typename details::fusion_vec<dcm::Orientation>::type val;
fusion::front(val)=v;
con->template initialize(val);
return;
}
else if(first.compare("Angle") == 0) {
double v = boost::lexical_cast<double>(second);
typename details::fusion_vec<dcm::Angle>::type val;
fusion::front(val)=v;
con->template initialize(val);
return;
}
else if(first.compare("Coincidence") == 0) {
dcm::Direction v = (dcm::Direction)boost::lexical_cast<int>(second);
typename details::fusion_vec<dcm::Coincidence>::type val;
val=v;
con->template initialize(val);
return;
}
else if(first.compare("Alignment") == 0) {
double v = boost::lexical_cast<double>(second);
typename details::fusion_vec<dcm::Alignment>::type val;
val=v;
con->template initialize(val);
return;
}
};
template<typename C>
void setConstraints(char_vec& vec, boost::shared_ptr<C> con) {
constraintCreation<C>(vec.begin(), vec.end(), con);
};
template <typename Geom, typename Row, typename Value>
bool VectorOutput(Geom& v, Row& r, Value& val) {
if(r < v->m_global.rows()) {
val = v->m_global(r++);
return true; // output continues
}
return false; // fail the output
};
template <typename Geom, typename Row, typename Value>
bool VectorInput(Geom& v, Row& r, Value& val) {
v.conservativeResize(r+1);
v(r++) = val;
return true; // output continues
};
template<typename Geom>
struct inject_set {
template<typename Vec, typename Obj>
static void apply(Vec& v, Obj g) {
Geom gt;
(typename geometry_traits<Geom>::modell()).template inject<double,
typename geometry_traits<Geom>::accessor >(gt, v);
g->set(gt);
};
};
//spezialisation if no type in the typelist has the right weight
template<>
struct inject_set<mpl::void_> {
template<typename Obj, typename Vec>
static void apply(Vec& v, Obj g) {
//TODO:throw
};
};
template<typename System>
bool Create(System* sys, std::string& type,
boost::shared_ptr<typename details::getModule3D<System>::type::Geometry3D> geom,
typename System::Kernel::Vector& v) {
typedef typename details::getModule3D<System>::type::geometry_types Typelist;
if(type.compare("direction") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::direction>::type>::apply(v, geom);
}
else if(type.compare("point") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::point>::type>::apply(v, geom);
}
else if(type.compare("line") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::line>::type>::apply(v, geom);
}
else if(type.compare("plane") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::plane>::type>::apply(v, geom);
}
else if(type.compare("cylinder") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::cylinder>::type>::apply(v, geom);
};
return true;
};
// define a new real number formatting policy
template <typename Num>
struct scientific_policy : karma::real_policies<Num>
{
// we want the numbers always to be in scientific format
static int floatfield(Num n) {
return std::ios::scientific;
}
static unsigned precision(Num n) {
return 16;
};
};
// define a new generator type based on the new policy
typedef karma::real_generator<double, scientific_policy<double> > science_type;
static science_type const scientific = science_type();
} //details
} //dcm
BOOST_PHOENIX_ADAPT_FUNCTION(bool, vector_out, dcm::details::VectorOutput, 3)
BOOST_PHOENIX_ADAPT_FUNCTION(bool, vector_in, dcm::details::VectorInput, 3)
BOOST_PHOENIX_ADAPT_FUNCTION(bool, create, dcm::details::Create, 4)
BOOST_FUSION_ADAPT_STRUCT(
dcm::GlobalEdge,
(int, ID)
(int, source)
(int, target)
)
namespace dcm {
template<typename System, typename iterator>
void parser_generator< typename details::getModule3D<System>::type::Geometry3D , System, iterator >::init(generator& r) {
r = karma::lit("<type>Geometry3D</type>\n<class>")
<< karma_ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
<< "</class>" << karma::eol << "<value>"
<< (details::scientific[ boost::spirit::_pass = vector_out(karma::_val, karma::_a, karma::_1) ] % ' ')
<< "</value>";
};
template<typename System, typename iterator>
void parser_generator< typename details::getModule3D<System>::type::vertex_prop , System, iterator >::init(generator& r) {
r = karma::lit("<type>Vertex</type>")
<< karma::eol << "<value>" << karma::int_ << "</value>";
};
template<typename System, typename iterator>
void parser_generator< typename details::getModule3D<System>::type::Constraint3D , System, iterator >::init(generator& r) {
r = karma::lit("<type>Constraint3D</type>") << karma::eol
<< "<connect first=" << karma::int_[karma::_1 = phx::at_c<1>(phx::bind(&Constraint3D::template getProperty<edge_prop>, karma::_val))]
<< " second=" << karma::int_[karma::_1 = phx::at_c<2>(phx::bind(&Constraint3D::template getProperty<edge_prop>, karma::_val))] << "></connect>"
<< (*(karma::eol<<"<constraint type="<<karma_ascii::string<<">"<<karma_ascii::string<<"</constraint>"))[karma::_1 = phx::bind(&details::getConstraints<Constraint3D>, karma::_val)];
};
template<typename System, typename iterator>
void parser_generator< typename details::getModule3D<System>::type::edge_prop , System, iterator >::init(generator& r) {
r %= karma::lit("<type>Edge</type>")
<< karma::eol << "<value>" << karma::int_ << " "
<< karma::int_ << " " << karma::int_ << "</value>";
};
template<typename System, typename iterator>
void parser_generator<typename details::getModule3D<System>::type::fix_prop, System, iterator>::init(generator& r) {
r = karma::lit("<type>Fix</type>\n<value>") << karma::bool_ <<"</value>";
};
/****************************************************************************************************/
/****************************************************************************************************/
template<typename System, typename iterator>
void parser_parser< typename details::getModule3D<System>::type::Geometry3D, System, iterator >::init(parser& r) {
r = qi::lit("<type>Geometry3D</type>")[ qi::_val = phx::construct<boost::shared_ptr<object_type> >(phx::new_<object_type>(*qi::_r1))]
>> "<class>" >> (+qi::char_("a-zA-Z"))[qi::_a = phx::construct<std::string>(phx::begin(qi::_1), phx::end(qi::_1))] >> "</class>"
>> "<value>" >> *qi::double_[ vector_in(qi::_b, qi::_c, qi::_1) ] >> "</value>"
>> qi::eps[ create(qi::_r1, qi::_a, qi::_val, qi::_b) ];
};
template<typename System, typename iterator>
void parser_parser< typename details::getModule3D<System>::type::vertex_prop, System, iterator >::init(parser& r) {
r %= qi::lit("<type>Vertex</type>") >> "<value>" >> qi::int_ >> "</value>";
};
template<typename System, typename iterator>
void parser_parser< typename details::getModule3D<System>::type::Constraint3D, System, iterator >::init(parser& r) {
r = qi::lit("<type>Constraint3D</type>")
>> ("<connect first=" >> qi::int_ >> "second=" >> qi::int_ >> "></connect>")[
qi::_val = phx::construct<boost::shared_ptr<Constraint3D> >(
phx::new_<Constraint3D>(*qi::_r1,
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_1),
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_2)))
]
>> (*("<constraint type=" >> *qi_ascii::alpha >> ">" >> *qi_ascii::alnum >>"</constraint>"))[phx::bind(&details::setConstraints<Constraint3D>, qi::_1, qi::_val)];
};
template<typename System, typename iterator>
void parser_parser< typename details::getModule3D<System>::type::edge_prop, System, iterator >::init(parser& r) {
r %= qi::lit("<type>Edge</type>")
>> "<value>" >> qi::int_ >> qi::int_ >> qi::int_ >> "</value>";
};
template<typename System, typename iterator>
void parser_parser< typename details::getModule3D<System>::type::fix_prop, System, iterator >::init(parser& r) {
r = qi::lit("<type>Fix</type>") >> "<value>" >> qi::bool_ >> "</value>";
};
}
#endif //DCM_MODULE3D_STATE_HPP

View File

@@ -17,26 +17,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GCM_MODULE_3D_H
#define GCM_MODULE_3D_H
#ifndef DCM_MODULE_3D_H
#define DCM_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"
@@ -57,19 +47,6 @@ 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 {
struct reset {}; //signal name
struct module3d_error : virtual boost::exception {}; //exception for all module3d special errors
@@ -123,17 +100,10 @@ struct Module3D {
};
template<typename Visitor>
typename Visitor::result_type apply(Visitor& vis) {
return boost::apply_visitor(vis, m_geometry);
};
typename Visitor::result_type apply(Visitor& vis);
template<typename T>
T convertTo() {
T t;
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
typename geometry_traits<T>::accessor >(t, Base::m_global);
return t;
};
T convertTo();
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
@@ -144,31 +114,6 @@ struct Module3D {
#ifdef USE_LOGGING
src::logger log;
#endif
struct cloner : boost::static_visitor<void> {
typedef typename boost::make_variant_over< ExtTypeList >::type Variant;
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(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;
};
Variant m_geometry; //Variant holding the real geometry type
//override protected event functions to emit signals
@@ -261,42 +206,6 @@ struct Module3D {
struct inheriter_base {
//build a constraint vector
template<typename T>
struct fusion_vec {
typedef typename mpl::if_< mpl::is_sequence<T>,
T, fusion::vector<T> >::type type;
};
template<typename covec>
struct initalizer : public boost::static_visitor<void> {
Cons constraint;
covec& cov;
initalizer(Cons c, covec& co) : constraint(c), cov(co) {};
template<typename T1, typename T2>
void operator()(const T1& t1, const T2& t2) {
constraint->template initialize< typename geometry_traits<T1>::tag,
typename geometry_traits<T2>::tag, covec>(cov);
};
};
struct set_constraint_option {
template<typename T>
typename boost::enable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
operator()(T& val) {
return val;
};
template<typename T>
typename boost::disable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
operator()(T& val) {
typename fusion_vec<T>::type vec;
fusion::at_c<0>(vec) = val;
return vec;
};
};
inheriter_base();
template<typename T>
@@ -308,6 +217,8 @@ struct Module3D {
Cons createConstraint3D(Geom first, Geom second, T1 constraint1);
void removeConstraint3D(Cons c);
void system_sub(boost::shared_ptr<Sys> subsys) {};
protected:
Sys* m_this;
void apply_edge_remove(GlobalEdge e);
@@ -361,6 +272,7 @@ struct Module3D {
typedef mpl::vector4<vertex_prop, edge_prop, math_prop, fix_prop> properties;
typedef mpl::vector2<Geometry3D, Constraint3D> objects;
typedef mpl::vector5<tag::point3D, tag::direction3D, tag::line3D, tag::plane3D, tag::cylinder3D> geometries;
typedef mpl::map0<> signals;
static void system_init(Sys& sys) {
sys.m_sheduler.addProcessJob(new SystemSolver());
@@ -408,444 +320,11 @@ typename boost::add_reference<T>::type get(G geom) {
return *result;
};
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
/*****************************************************************************************************************/
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(Sys& system)
: Object<Sys, Derived, GeomSig>(system) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
#endif
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(const T& geometry, Sys& system)
: Object<Sys, Derived, GeomSig>(system) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
#endif
m_geometry = geometry;
//first init, so that the geometry internal vector has the right size
Base::template init< typename geometry_traits<T>::tag >();
//now write the value;
(typename geometry_traits<T>::modell()).template extract<Scalar,
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
template<typename T>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::set(const T& geometry) {
m_geometry = geometry;
//first init, so that the geometry internal vector has the right size
Base::template init< typename geometry_traits<T>::tag >();
//now write the value;
(typename geometry_traits<T>::modell()).template extract<Scalar,
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
reset();
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::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 Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::recalculated() {
apply_visitor v(Base::getValue());
apply(v);
ObjBase::template emitSignal<dcm::recalculated>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::removed() {
ObjBase::template emitSignal<dcm::remove>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::reset() {
ObjBase::template emitSignal<dcm::reset>(((Derived*)this)->shared_from_this());
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(Sys& system)
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(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>
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(const T& geometry, Sys& system)
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(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(const 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(const 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>
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(Sys& system)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
Geometry3D_base<Geometry3D>,
Geometry3D_id<Geometry3D> >::type(system) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename T>
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(const T& geometry, Sys& system)
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
Geometry3D_base<Geometry3D>,
Geometry3D_id<Geometry3D> >::type(geometry, system) {
};
template<typename Typelist, typename ID>
template<typename Sys>
template<typename Derived>
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Constraint3D_base<Derived>::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 = CBase::content->clone();
//and get the geometry pointers right
if(CBase::first) {
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::first)->template getProperty<vertex_prop>();
np->first = newSys.m_cluster->template getObject<Geometry3D>(v);
}
if(CBase::second) {
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::second)->template getProperty<vertex_prop>();
np->second = newSys.m_cluster->template getObject<Geometry3D>(v);
}
return np;
};
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)
: Constraint3D_base<Derived>(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>,
Constraint3D_base<Constraint3D>,
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>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D() {
Geom g(new Geometry3D(* ((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>
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) {
//get the fusion vector type
typedef typename fusion_vec<T1>::type covec;
//set the objects
covec cv = set_constraint_option()(constraint1);
//now create the constraint
Cons c(new Constraint3D(*m_this, first, second));
//initialize constraint
c->initialize(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>
typename Module3D<Typelist, ID>::template type<Sys>::Geom
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(Identifier id) {
Geom g = inheriter_base::createGeometry3D();
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));
else
throw module3d_error() << boost::errinfo_errno(410) << error_message("no geometry with this ID in this system");
};
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));
else
throw module3d_error() << boost::errinfo_errno(411) << error_message("no constraint with this ID in this system");
};
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
#include "imp/module_imp.hpp"
#endif //DCM_GEOMETRY3D_H

View File

@@ -21,19 +21,11 @@
#define GCM_SOLVER_3D_H
#include "defines.hpp"
#include "clustermath.hpp"
#include "opendcm/core/clustergraph.hpp"
#include "opendcm/core/sheduler.hpp"
#include "opendcm/core/traits.hpp"
#include <opendcm/core/kernel.hpp>
#include <opendcm/core/property.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <boost/graph/undirected_dfs.hpp>
#include <boost/exception/errinfo_errno.hpp>
namespace dcm {
namespace dcm {
namespace details {
template<typename Sys>
@@ -121,383 +113,6 @@ struct SystemSolver : public Job<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) {
#ifdef USE_LOGGING
log.add_attribute("Tag", attrs::constant< std::string >("MES3D"));
#endif
};
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 getProperty<fix_prop>())
(*cit.first).second->template getProperty<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, Base::rot_only);
}
}
};
template<typename Sys>
void MES<Sys>::removeLocalGradientZeros() {
#ifdef USE_LOGGING
BOOST_LOG(log) << "remove local gradient zero";
#endif
//let the constraints treat the local zeros
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)->treatLGZ();
}
}
};
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 getProperty<fix_prop>())
continue;
//get the biggest scale factor
details::ClusterMath<Sys>& math = (*cit.first).second->template getProperty<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, 1e-10)) ? 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 getProperty<math_prop>().applyClusterScale(sc,
c->template getProperty<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::global_edge_iterator 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->getGlobalEdges(*it.first);
for(; cit.first != cit.second; cit.first++) {
Cons c = parent->template getObject<Constraint3D>(*cit.first);
if(!c)
continue;
//get the first global vertex and see if we have it in the wanted cluster or not
GlobalVertex v = cit.first->source;
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) {
try {
//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 getProperty<changed_prop>() &&
c->template getProperty<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();
};
if(params <= 0 || constraints <= 0) {
//TODO:throw
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Error in system counting: params = " << params << " and constraints = "<<constraints;
#endif
return;
}
//initialise the system with now known size
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 getProperty<math_prop>();
//only get maps and propagate downstream if not fixed
if(!c->template getProperty<fix_prop>()) {
//set norm Quaternion as map to the parameter vector
int offset_rot = mes.setParameterMap(cm.getNormQuaternionMap(), rotation);
//set translation as map to the parameter vector
int offset = mes.setParameterMap(cm.getTranslationMap(), general);
//write initail values to the parameter maps
//remember the parameter offset as all downstream geometry must use this offset
cm.setParameterOffset(offset_rot, rotation);
cm.setParameterOffset(offset, general);
//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);
g->initMap(&mes);
}
}
//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)
}
}
//if we don't have rotations we need no expensive scaling code
if(!mes.hasParameterType(rotation)) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "No rotation parameters in system, solve without scaling";
#endif
DummyScaler re;
sys.kernel().solve(mes, re);
}
else {
// we have rotations, so let's check our options. first search for cycles, as systems with them
// always need the full solver power
bool has_cycle;
cycle_dedector cd(has_cycle);
//create te needed property maps and fill it
property_map<vertex_index_prop, Cluster> vi_map(cluster);
cluster->initIndexMaps();
typedef std::map< LocalVertex, boost::default_color_type> vcmap;
typedef std::map< LocalEdge, boost::default_color_type> ecmap;
vcmap v_cm;
ecmap e_cm;
boost::associative_property_map< vcmap > v_cpm(v_cm);
boost::associative_property_map< ecmap > e_cpm(e_cm);
boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(v_cpm).edge_color_map(e_cpm));
bool done = false;
if(!has_cycle) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "non-cyclic system dedected";
#endif
//cool, lets do uncylic. first all rotational constraints with rotational parameters
mes.setAccess(rotation);
mes.setGeneralEquationAccess(false);
//solve can be done without catching exceptions, because this only fails if the system in
//unsolvable
DummyScaler re;
sys.kernel().solve(mes, re);
//now let's see if we have to go on with the translations
mes.setAccess(general);
mes.setGeneralEquationAccess(true);
mes.recalculate();
if(mes.Residual.norm()<1e-6)
done = true;
else {
//let's try translation only
try {
DummyScaler re;
sys.kernel().solve(mes, re);
done=true;
}
catch(boost::exception&) {
//not successful, so we need brute force
done = false;
}
}
};
//not done already? try it the hard way!
if(!done) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Full scale solver used";
#endif
Rescaler re(cluster, mes);
re();
sys.kernel().solve(mes, re);
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
#endif
};
}
//solving is done, 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 getProperty<math_prop>().finishCalculation();
else
c->template getProperty<math_prop>().finishFixCalculation();
std::vector<Geom>& vec = c->template getProperty<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 setProperty<changed_prop>(false);
}
catch(boost::exception&) {
throw;
}
};
}//details
}//dcm

View File

@@ -20,300 +20,53 @@
#ifndef DCM_MODULE3D_STATE_HPP
#define DCM_MODULE3D_STATE_HPP
#include "module.hpp"
#include <opendcm/moduleState/traits.hpp>
#include <opendcm/core/clustergraph.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/greater.hpp>
#include <ios>
namespace karma = boost::spirit::karma;
namespace qi = boost::spirit::qi;
namespace karma_ascii = boost::spirit::karma::ascii;
namespace qi_ascii = boost::spirit::qi::ascii;
namespace phx = boost::phoenix;
namespace dcm {
namespace details {
template<typename Sys>
struct getModule3D {
typedef typename system_traits<Sys>::template getModule<m3d>::type type;
};
}
struct geom_visitor : public boost::static_visitor<std::string> {
template<typename T>
std::string operator()(T& i) const {
//we use stings in case new geometry gets added and the weights shift, meaning: backwards
//compatible
std::string type;
switch( geometry_traits<T>::tag::weight::value ) {
case tag::weight::direction::value :
return "direction";
case tag::weight::point::value :
return "point";
case tag::weight::line::value :
return "line";
case tag::weight::plane::value :
return "plane";
case tag::weight::cylinder::value :
return "cylinder";
default:
return "unknown";
};
};
};
template<typename T>
std::string getWeight(boost::shared_ptr<T> ptr) {
geom_visitor v;
return ptr->apply(v);
};
template<typename T>
struct get_weight {
typedef typename geometry_traits<T>::tag::weight type;
};
//search the first type in the typevector with the given weight
template<typename Vector, typename Weight>
struct getWeightType {
typedef typename mpl::find_if<Vector, boost::is_same<get_weight<mpl::_1>, Weight > >::type iter;
typedef typename mpl::if_< boost::is_same<iter, typename mpl::end<Vector>::type >, mpl::void_, typename mpl::deref<iter>::type>::type type;
};
typedef std::vector< fusion::vector2<std::string, std::string> > string_vec;
typedef std::vector< fusion::vector2<std::vector<char>, std::vector<char> > > char_vec;
template<typename C>
string_vec getConstraints(boost::shared_ptr<C> con) {
string_vec vec;
std::vector<boost::any> cvec = con->getGenericConstraints();
typename std::vector<boost::any>::iterator it;
for(it = cvec.begin(); it != cvec.end(); it++) {
if((*it).type() == typeid(dcm::Distance)) {
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Distance>(*it).value);
vec.push_back(fusion::make_vector(std::string("Distance"), value));
}
else if((*it).type() == typeid(dcm::Angle)) {
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Angle>(*it).value);
vec.push_back(fusion::make_vector(std::string("Angle"), value));
}
else if((*it).type() == typeid(dcm::Orientation)) {
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Orientation>(*it).value);
vec.push_back(fusion::make_vector(std::string("Orientation"), value));
};
};
return vec;
};
template<typename Seq, typename T>
struct push_seq {
typedef typename fusion::result_of::as_vector<typename mpl::push_back< Seq, T >::type>::type type;
};
template<typename State, typename Add>
typename push_seq<State, Add>::type append(State& s, const typename Add::option_type& val) {
typedef typename push_seq<State, Add>::type Sequence;
typedef typename fusion::result_of::begin<Sequence>::type Begin;
typedef typename fusion::result_of::end<Sequence>::type End;
typedef typename fusion::result_of::prior<End>::type EndOld;
//create the new sequence
Sequence vec;
//copy the old values into the new sequence
Begin b(vec);
EndOld eo(vec);
fusion::iterator_range<Begin, EndOld> range(b, eo);
fusion::copy(s, range);
//insert this object at the end of the sequence
fusion::back(vec) = val;
//and return our new extendet sequence
return vec;
};
template<typename State, typename C, typename Count>
typename boost::enable_if<typename mpl::greater<Count, mpl::int_<3> >::type, void>::type
recursiveCreation(typename char_vec::iterator it,
typename char_vec::iterator end,
boost::shared_ptr<C> con,
State s ) {};
template<typename State, typename C, typename Count>
typename boost::enable_if<typename mpl::less_equal<Count, mpl::int_<3> >::type, void>::type
recursiveCreation(typename char_vec::iterator it,
typename char_vec::iterator end,
boost::shared_ptr<C> con,
State s ) {
if(it == end) {
con->template initialize<State>(s);
return;
};
std::string first( fusion::at_c<0>(*it).begin(), fusion::at_c<0>(*it).end() );
std::string second( fusion::at_c<1>(*it).begin(), fusion::at_c<1>(*it).end() );
if( first.compare("Distance") == 0 ) {
typedef typename push_seq<State, dcm::Distance>::type Vec;
Vec vec = append<State, dcm::Distance>(s, boost::lexical_cast<typename dcm::Distance::option_type>(second));
recursiveCreation<Vec, C, typename mpl::next<Count>::type >(++it, end, con, vec);
return;
};
};
template<typename C>
void setConstraints(char_vec& vec, boost::shared_ptr<C> con ) {
recursiveCreation<fusion::vector<>, C, mpl::int_<0> >(vec.begin(), vec.end(), con, fusion::vector<>());
};
template <typename Geom, typename Row, typename Value>
bool VectorOutput(Geom &v, Row& r, Value& val) {
if (r < v->m_global.rows()) {
val = v->m_global(r++);
return true; // output continues
}
return false; // fail the output
};
template <typename Geom, typename Row, typename Value>
bool VectorInput(Geom &v, Row& r, Value& val) {
v.conservativeResize(r+1);
v(r++) = val;
return true; // output continues
};
template<typename Geom>
struct inject_set {
template<typename Vec, typename Obj>
static void apply(Vec& v, Obj g) {
Geom gt;
(typename geometry_traits<Geom>::modell()).template inject<double,
typename geometry_traits<Geom>::accessor >(gt, v);
g->set(gt);
};
};
//spezialisation if no type in the typelist has the right weight
template<>
struct inject_set<mpl::void_> {
template<typename Obj, typename Vec>
static void apply(Vec& v, Obj g) {
//TODO:throw
};
};
template<typename System>
bool Create(System* sys, std::string& type,
boost::shared_ptr<typename details::getModule3D<System>::type::Geometry3D> geom,
typename System::Kernel::Vector& v) {
typedef typename details::getModule3D<System>::type::geometry_types Typelist;
if(type.compare("direction") == 0 ) {
inject_set<typename getWeightType<Typelist, tag::weight::direction>::type>::apply(v, geom);
}
else if(type.compare("point") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::point>::type>::apply(v, geom);
}
else if(type.compare("line") == 0) {
inject_set<typename getWeightType<Typelist, tag::weight::line>::type>::apply(v, geom);
}
else if(type.compare("plane") == 0 ) {
inject_set<typename getWeightType<Typelist, tag::weight::plane>::type>::apply(v, geom);
}
else if(type.compare("cylinder") == 0 ) {
inject_set<typename getWeightType<Typelist, tag::weight::cylinder>::type>::apply(v, geom);
};
return true;
};
// define a new real number formatting policy
template <typename Num>
struct scientific_policy : karma::real_policies<Num>
{
// we want the numbers always to be in scientific format
static int floatfield(Num n) { return std::ios::scientific; }
static unsigned precision(Num n) {return 16;};
};
// define a new generator type based on the new policy
typedef karma::real_generator<double, scientific_policy<double> > science_type;
static science_type const scientific = science_type();
} //details
} //dcm
BOOST_PHOENIX_ADAPT_FUNCTION( bool, vector_out, dcm::details::VectorOutput, 3)
BOOST_PHOENIX_ADAPT_FUNCTION( bool, vector_in, dcm::details::VectorInput, 3)
BOOST_PHOENIX_ADAPT_FUNCTION( bool, create, dcm::details::Create, 4)
BOOST_FUSION_ADAPT_STRUCT(
dcm::GlobalEdge,
(int, ID)
(int, source)
(int, target)
)
namespace dcm {
template<typename System>
struct parser_generate< typename details::getModule3D<System>::type::Geometry3D , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator< typename details::getModule3D<System>::type::Geometry3D , System, iterator > {
typedef typename details::getModule3D<System>::type::Geometry3D Geometry;
typedef karma::rule<iterator, boost::shared_ptr<Geometry>(), karma::locals<int> > generator;
static void init(generator& r) {
r = karma::lit("<type>Geometry3D</type>\n<class>")
<< karma_ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
<< "</class>" << karma::eol << "<value>"
<< (details::scientific[ boost::spirit::_pass = vector_out(karma::_val, karma::_a, karma::_1) ] % ' ')
<< "</value>";
};
static void init(generator& r);
};
template<typename System>
struct parser_generate< typename details::getModule3D<System>::type::vertex_prop , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator< typename details::getModule3D<System>::type::vertex_prop , System, iterator > {
typedef karma::rule<iterator, GlobalVertex()> generator;
static void init(generator& r) {
r = karma::lit("<type>Vertex</type>")
<< karma::eol << "<value>" << karma::int_ << "</value>";
};
static void init(generator& r);
};
template<typename System>
struct parser_generate< typename details::getModule3D<System>::type::Constraint3D , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator< typename details::getModule3D<System>::type::Constraint3D , System, iterator > {
@@ -321,28 +74,20 @@ struct parser_generator< typename details::getModule3D<System>::type::Constraint
typedef typename details::getModule3D<System>::type::Geometry3D Geometry3D;
typedef typename details::getModule3D<System>::type::Constraint3D Constraint3D;
typedef typename details::getModule3D<System>::type::vertex_prop vertex_prop;
typedef typename details::getModule3D<System>::type::edge_prop edge_prop;
typedef karma::rule<iterator, boost::shared_ptr<Constraint3D>()> generator;
static void init(generator& r) {
r = karma::lit("<type>Constraint3D</type>") << karma::eol
<< "<connect first=" << karma::int_[karma::_1 = phx::bind(&Geometry3D::template getProperty<vertex_prop>, phx::bind(&Constraint3D::first, karma::_val))]
<< " second=" << karma::int_[karma::_1 = phx::bind(&Geometry3D::template getProperty<vertex_prop>, phx::bind(&Constraint3D::second, karma::_val))] << "></connect>"
<< (*(karma::eol<<"<constraint type="<<karma_ascii::string<<">"<<karma_ascii::string<<"</constraint>"))[karma::_1 = phx::bind(&details::getConstraints<Constraint3D>, karma::_val)];
};
static void init(generator& r);
};
template<typename System>
struct parser_generate< typename details::getModule3D<System>::type::edge_prop , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator< typename details::getModule3D<System>::type::edge_prop , System, iterator > {
typedef karma::rule<iterator, GlobalEdge&()> generator;
static void init(generator& r) {
r %= karma::lit("<type>Edge</type>")
<< karma::eol << "<value>" << karma::int_ << " "
<< karma::int_ << " " << karma::int_ << "</value>";
};
static void init(generator& r);
};
template<typename System>
@@ -352,9 +97,7 @@ template<typename System, typename iterator>
struct parser_generator<typename details::getModule3D<System>::type::fix_prop, System, iterator> {
typedef karma::rule<iterator, bool&()> generator;
static void init(generator& r) {
r = karma::lit("<type>Fix</type>\n<value>") << karma::bool_ <<"</value>";
};
static void init(generator& r);
};
/****************************************************************************************************/
@@ -362,40 +105,33 @@ struct parser_generator<typename details::getModule3D<System>::type::fix_prop, S
template<typename System>
struct parser_parse< typename details::getModule3D<System>::type::Geometry3D , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser< typename details::getModule3D<System>::type::Geometry3D, System, iterator > {
typedef typename details::getModule3D<System>::type::Geometry3D object_type;
typedef typename System::Kernel Kernel;
typedef qi::rule<iterator, boost::shared_ptr<object_type>(System*), qi::space_type, qi::locals<std::string, typename Kernel::Vector, int> > parser;
static void init(parser& r) {
r = qi::lit("<type>Geometry3D</type>")[ qi::_val = phx::construct<boost::shared_ptr<object_type> >( phx::new_<object_type>(*qi::_r1))]
>> "<class>" >> (+qi::char_("a-zA-Z"))[qi::_a = phx::construct<std::string>(phx::begin(qi::_1), phx::end(qi::_1))] >> "</class>"
>> "<value>" >> *qi::double_[ vector_in(qi::_b, qi::_c, qi::_1) ] >> "</value>"
>> qi::eps[ create(qi::_r1, qi::_a, qi::_val, qi::_b) ];
};
static void init(parser& r);
};
template<typename System>
struct parser_parse< typename details::getModule3D<System>::type::vertex_prop, System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser< typename details::getModule3D<System>::type::vertex_prop, System, iterator > {
typedef qi::rule<iterator, GlobalVertex(), qi::space_type> parser;
static void init(parser& r) {
r %= qi::lit("<type>Vertex</type>") >> "<value>" >> qi::int_ >> "</value>";
};
static void init(parser& r);
};
template<typename System>
struct parser_parse< typename details::getModule3D<System>::type::Constraint3D , System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser< typename details::getModule3D<System>::type::Constraint3D, System, iterator > {
@@ -403,48 +139,37 @@ struct parser_parser< typename details::getModule3D<System>::type::Constraint3D,
typedef typename details::getModule3D<System>::type::Geometry3D Geometry3D;
typedef typename details::getModule3D<System>::type::Constraint3D Constraint3D;
typedef typename System::Kernel Kernel;
typedef qi::rule<iterator, boost::shared_ptr<Constraint3D>(System*), qi::space_type > parser;
static void init(parser& r) {
r = qi::lit("<type>Constraint3D</type>")
>> ("<connect first=" >> qi::int_ >> "second=" >> qi::int_ >> "></connect>")[
qi::_val = phx::construct<boost::shared_ptr<Constraint3D> >(
phx::new_<Constraint3D>(*qi::_r1,
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_1),
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_2) ) )
]
>> (*("<constraint type=" >> *qi_ascii::alpha >> ">" >> *qi_ascii::alnum >>"</constraint>"))[phx::bind(&details::setConstraints<Constraint3D>, qi::_1, qi::_val)];
};
static void init(parser& r);
};
template<typename System>
struct parser_parse< typename details::getModule3D<System>::type::edge_prop, System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser< typename details::getModule3D<System>::type::edge_prop, System, iterator > {
typedef qi::rule<iterator, GlobalEdge(), qi::space_type> parser;
static void init(parser& r) {
r %= qi::lit("<type>Edge</type>")
>> "<value>" >> qi::int_ >> qi::int_ >> qi::int_ >> "</value>";
};
static void init(parser& r);
};
template<typename System>
struct parser_parse< typename details::getModule3D<System>::type::fix_prop, System>
: public mpl::true_{};
: public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser< typename details::getModule3D<System>::type::fix_prop, System, iterator > {
typedef qi::rule<iterator, bool(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>Fix</type>") >> "<value>" >> qi::bool_ >> "</value>";
};
static void init(parser& r);
};
}
#ifndef DCM_EXTERNAL_STATE
#include "imp/state_imp.hpp"
#endif
#endif //DCM_MODULE3D_STATE_HPP
#endif //DCM_MODULE3D_STATE_HPP

View File

@@ -52,6 +52,7 @@ struct ModulePart {
mpl::pair<recalculated, boost::function<void (Partptr) > > > PartSignal;
typedef ID Identifier;
typedef mpl::map1<mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Sys>)> > > signals;
class Part_base : public Object<Sys, Part, PartSignal > {
protected:
@@ -207,6 +208,9 @@ struct ModulePart {
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
};
//needed system functions
void system_sub(boost::shared_ptr<Sys> subsys) {};
protected:
Sys* m_this;
@@ -239,9 +243,14 @@ struct ModulePart {
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
typedef mpl::vector0<> properties;
struct subsystem_property {
typedef Sys* type;
typedef cluster_property kind;
};
typedef mpl::vector1<subsystem_property> properties;
typedef mpl::vector1<Part> objects;
typedef mpl::vector0<> geometries;
typedef mpl::vector0<> geometries;
struct PrepareCluster : public Job<Sys> {
@@ -307,6 +316,7 @@ template<typename T>
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
ModulePart<Typelist, ID>::type<Sys>::Part_base::addGeometry3D(const T& geom, CoordinateFrame frame) {
Geom g(new Geometry3D(geom, *m_system));
if(frame == Local) {
//we need to collect all transforms up to this part!
Transform t;
@@ -389,10 +399,12 @@ ModulePart<Typelist, ID>::type<Sys>::Part_base::clone(Sys& newSys) {
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;
@@ -451,6 +463,7 @@ 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;
@@ -531,11 +544,14 @@ 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);
@@ -546,6 +562,7 @@ 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);
@@ -567,6 +584,7 @@ template<typename Sys>
bool ModulePart<Typelist, ID>::type<Sys>::inheriter_id::hasPart(Identifier id) {
if(getPart(id))
return true;
return false;
};
@@ -576,10 +594,12 @@ 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();
};
@@ -594,6 +614,7 @@ 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 getProperty<typename module3d::math_prop>();
@@ -612,12 +633,21 @@ 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 getProperty<typename module3d::math_prop>();
(*it)->m_transform = cm.getTransform();
(*it)->finishCalculation();
};
//get all subsystems and report their recalculation
typedef typename std::vector<boost::shared_ptr<Sys> >::iterator siter;
for(siter it = sys.beginSubsystems(); it != sys.endSubsystems(); it++) {
(*it)->template emitSignal<recalculated>(*it);
};
};
}

View File

@@ -32,6 +32,8 @@
#include <boost/mpl/map.hpp>
#include <boost/type_traits.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
@@ -426,6 +428,8 @@ struct ModuleShape3D {
m_this = (Sys*)this;
};
void system_sub(boost::shared_ptr<Sys> subsys) {};
protected:
Sys* m_this;
@@ -471,11 +475,11 @@ struct ModuleShape3D {
typedef mpl::vector3<shape_purpose_prop, shape_constraint_prop, shape_geometry_prop> properties;
typedef mpl::vector1<Shape3D> objects;
typedef mpl::vector1<tag::segment3D> geometries;
typedef mpl::map0<> signals;
//needed static functions
static void system_init(Sys& sys) {};
static void system_copy(const Sys& from, Sys& into) {};
};
};
@@ -557,6 +561,7 @@ ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::geometry(purpose
if((*it)->template getProperty<shape_purpose_prop>() == f)
return *it;
};
return boost::shared_ptr<Geometry3D>();
};
@@ -603,14 +608,17 @@ template<typename Derived>
void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::disconnectAll() {
typename GeometryVector::iterator git;
for(git = m_geometries.begin(); git!=m_geometries.end(); git++)
fusion::at_c<0>(*git)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*git));
typename ShapeVector::iterator sit;
for(sit = m_shapes.begin(); sit!=m_shapes.end(); sit++)
fusion::at_c<0>(*sit)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*sit));
typename ConstraintVector::iterator cit;
for(cit = m_constraints.begin(); cit!=m_constraints.end(); cit++)
fusion::at_c<0>(*cit)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*cit));
};
@@ -634,12 +642,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
//get the vector object where the geometry is part of
typename GeometryVector::const_iterator it;
for(it=m_geometries.begin(); it!=m_geometries.end(); it++) {
if(fusion::at_c<0>(*it)==g)
break;
};
m_geometries.erase(std::remove(m_geometries.begin(), m_geometries.end(), *it), m_geometries.end());
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
};
@@ -653,12 +663,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
//get the vector object where the geometry is part of
typename ShapeVector::const_iterator it;
for(it=m_shapes.begin(); it!=m_shapes.end(); it++) {
if(fusion::at_c<0>(*it)==g)
break;
};
m_shapes.erase(std::remove(m_shapes.begin(), m_shapes.end(), *it), m_shapes.end());
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
};
@@ -672,12 +684,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
//get the vector object where the geometry is part of
typename ConstraintVector::const_iterator it;
for(it=m_constraints.begin(); it!=m_constraints.end(); it++) {
if(fusion::at_c<0>(*it)==g)
break;
};
m_constraints.erase(std::remove(m_constraints.begin(), m_constraints.end(), *it), m_constraints.end());
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
};
@@ -780,10 +794,11 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_base::removeShape3D(boost
//remove all constraints is unnessecary as they get removed together with the geometries
//remove all geometries
typedef typename Shape3D::geometry3d_iterator git;
for(git it=g->beginGeometry3D(); it!=g->endGeometry3D(); it++)
m_this->removeGeometry3D(*it);
/* TODO: find out why it iterates over a empty vector and crashs...
//remove all subshapes
typedef typename Shape3D::shape3d_iterator sit;
@@ -801,6 +816,7 @@ template<typename Sys>
bool ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::hasShape3D(Identifier id) {
if(getShape3D(id))
return true;
return false;
};
@@ -810,10 +826,12 @@ boost::shared_ptr<typename ModuleShape3D<Typelist, ID>::template type<Sys>::Shap
ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::getShape3D(Identifier id) {
std::vector< boost::shared_ptr<Shape3D> >& vec = inheriter_base::m_this->template objectVector<Shape3D>();
typedef typename std::vector< boost::shared_ptr<Shape3D> >::iterator iter;
for(iter it=vec.begin(); it!=vec.end(); it++) {
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
return *it;
};
return boost::shared_ptr<Shape3D>();
};
@@ -822,6 +840,7 @@ template<typename Sys>
void ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::removeShape3D(Identifier id) {
boost::shared_ptr<Shape3D> s = getShape3D(id);
if(s)
removeShape3D(s);
};

View File

@@ -22,6 +22,9 @@
#include "opendcm/core/property.hpp"
#include "opendcm/core/clustergraph.hpp"
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace dcm {
namespace details {
@@ -33,4 +36,34 @@ struct cluster_vertex_prop {
}
}
BOOST_FUSION_ADAPT_TPL_STRUCT(
(T1)(T2)(T3)(T4),
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
(int, test)
(typename dcm::details::pts<T3>::type, m_properties))
//fusion adopt struct needs to avoid commas for type definition, as this breaks the macro syntax.
//we use this ugly nested struct to declare the dcm system from template parameters without commas
template<typename T1>
struct t1 {
template<typename T2>
struct t2 {
template<typename T3>
struct t3 {
template<typename T4>
struct t4 {
typedef dcm::System<T1,T2,T3,T4> type;
};
};
};
};
BOOST_FUSION_ADAPT_TPL_STRUCT(
(Kernel)(M1)(M2)(M3),
(dcm::System)(Kernel)(M1)(M2)(M3),
(typename t1<Kernel>::template t2<M1>::template t3<M2>::template t4<M3>::type::OptionOwner::Properties, m_options.m_properties)
(typename Kernel::Properties, m_kernel.m_properties)
(boost::shared_ptr<typename t1<Kernel>::template t2<M1>::template t3<M2>::template t4<M3>::type::Cluster>, m_cluster)
)
#endif

View File

@@ -68,8 +68,8 @@ struct vertex_generator : karma::grammar<Iterator, std::vector<typename Sys::Clu
}//details
}//dcm
#ifndef USE_EXTERNAL
#include "edge_vertex_generator_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/edge_vertex_generator_imp.hpp"
#endif
#endif

View File

@@ -27,6 +27,7 @@
#include <boost/spirit/include/qi.hpp>
#include "opendcm/core/clustergraph.hpp"
#include "extractor.hpp"
#include "object_parser.hpp"
namespace qi = boost::spirit::qi;
namespace fusion = boost::fusion;
@@ -68,8 +69,8 @@ struct vertex_parser : qi::grammar< IIterator, fusion::vector<LocalVertex, Globa
}
}
//#ifndef USE_EXTERNAL
//#include "edge_vertex_parser_imp.hpp"
//#endif
#ifndef DCM_EXTERNAL_STATE
#include "imp/edge_vertex_parser_imp.hpp"
#endif
#endif

View File

@@ -40,6 +40,7 @@ struct Extractor {
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) {
@@ -66,13 +67,13 @@ struct Extractor {
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() ));
};
void getClusterRange(typename Sys::Cluster& cluster, std::vector<std::pair<GlobalVertex, boost::shared_ptr<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));
};
};
};
@@ -101,18 +102,17 @@ struct Injector {
fusion::at_c<1>(cluster->operator[](e)) = bundles;
};
void setVertexProperty(typename Sys::Cluster* cluster, int value) {
cluster->template setProperty<details::cluster_vertex_prop>(value);
cluster->template setProperty<details::cluster_vertex_prop>(value);
};
void addClusters(std::vector<typename Sys::Cluster*>& clusters, typename Sys::Cluster* cluster) {
typename std::vector<typename Sys::Cluster*>::iterator it;
for(it = clusters.begin(); it != clusters.end(); it++) {
LocalVertex v = cluster->getLocalVertex((*it)->template getProperty<details::cluster_vertex_prop>()).first;
cluster->m_clusters[v] = boost::shared_ptr<typename Sys::Cluster>(*it);
};
};
void addVertex(typename Sys::Cluster* cluster, fusion::vector<LocalVertex, GlobalVertex>& vec) {
vec = cluster->addVertex();
void addClusters(std::vector<boost::shared_ptr<typename Sys::Cluster> >& clusters, typename Sys::Cluster* cluster) {
//vertices for the cluster need to be added already (as edges need vertices created)
//so we don't create a vertex here.
typename std::vector<boost::shared_ptr<typename Sys::Cluster> >::iterator it;
for(it = clusters.begin(); it != clusters.end(); it++) {
LocalVertex v = cluster->getLocalVertex((*it)->template getProperty<details::cluster_vertex_prop>()).first;
cluster->m_clusters[v] = *it;
};
};
};

View File

@@ -31,7 +31,7 @@
#include <opendcm/core/clustergraph.hpp>
#include "traits.hpp"
#include "traits_impl.hpp"
#include "imp/traits_impl.hpp"
#include "indent.hpp"
#include <boost/mpl/int.hpp>
@@ -53,7 +53,7 @@ namespace dcm {
typedef std::ostream_iterator<char> Iterator;
template<typename Sys>
struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
struct generator : karma::grammar<Iterator, Sys&()> {
typedef typename Sys::Cluster graph;
typedef typename graph::Properties graph_bundle;
@@ -62,11 +62,15 @@ struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
generator();
karma::rule<Iterator, graph& ()> start;
karma::rule<Iterator, Sys& ()> start;
karma::rule<Iterator, std::pair<GlobalVertex, graph*>()> cluster_pair;
karma::rule<Iterator, std::pair<GlobalVertex, boost::shared_ptr<graph> >()> cluster_pair;
karma::rule<Iterator, graph&()> cluster;
karma::rule<Iterator, Sys&()> system;
details::cluster_prop_gen<Sys> cluster_prop;
details::system_prop_gen<Sys> system_prop;
details::kernel_prop_gen<Sys> kernel_prop;
details::vertex_generator<Sys> vertex_range;
details::edge_generator<Sys> edge_range;
@@ -76,8 +80,8 @@ struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
}//namespace dcm
#ifndef USE_EXTERNAL
#include "generator_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/generator_imp.hpp"
#endif
#endif //DCM_GENERATOR_H

View File

@@ -0,0 +1,58 @@
/*
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"
#include "boost/phoenix/fusion/at.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,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"
#include "boost/phoenix/fusion/at.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))[phx::bind(&Injector<Sys>::setEdgeBundles, &in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
>> ("</Edge>");
};
template<typename Sys>
vertex_parser<Sys>::vertex_parser() : vertex_parser<Sys>::base_type(vertex) {
vertex = qi::lit("<Vertex id=") >> qi::int_[qi::_val = phx::bind(&Sys::Cluster::addVertex, qi::_r1, 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,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_GENERATOR_IMP_H
#define DCM_GENERATOR_IMP_H
#include "../generator.hpp"
#include "opendcm/core/clustergraph.hpp"
#include "../defines.hpp"
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace boost {
namespace spirit {
namespace traits
{
template <typename T1, typename T2, typename T3, typename T4>
struct transform_attribute<boost::shared_ptr<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(boost::shared_ptr<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
<< -karma::buffer[karma::eol << (cluster_pair % karma::eol)[phx::bind(&Extractor<Sys>::getClusterRange, &ex, karma::_val, karma::_1)]]
<< -vertex_range[phx::bind(&Extractor<Sys>::getVertexRange, &ex, karma::_val, karma::_1)]
<< -karma::buffer[karma::eol << edge_range[phx::bind(&Extractor<Sys>::getEdgeRange, &ex, karma::_val, karma::_1)]]
<< "$" << karma::eol
<< karma::lit("</Cluster>");
cluster_pair %= karma::lit("<Cluster id=") << karma::int_ << ">#"
<< qi::attr_cast<boost::shared_ptr<graph>, graph&>(cluster);
system %= system_prop << karma::lit("<Kernel>#") << kernel_prop
<< "$" << karma::eol << karma::lit("</Kernel>") << karma::eol
<< karma::lit("<Cluster id=0>#") << qi::attr_cast<boost::shared_ptr<graph>, graph&>(cluster);
start %= karma::lit("<openDCM>#") << karma::eol << system << "$" << karma::eol << karma::lit("</openDCM>");
};
}//namespace dcm
#endif //DCM_GENERATOR_H

View File

@@ -0,0 +1,70 @@
/*
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_IMP_H
#define DCM_MODULE_STATE_IMP_H
#include <iosfwd>
#include "../module.hpp"
#include "../indent.hpp"
#include "../generator.hpp"
#include "../parser.hpp"
#include "../defines.hpp"
namespace qi = boost::spirit::qi;
namespace dcm {
template<typename Sys>
void ModuleState::type<Sys>::inheriter::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);
};
template<typename Sys>
void ModuleState::type<Sys>::inheriter::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();
qi::phrase_parse(begin, end, par, qi::space, *m_this);
};
}
#endif //DCM_MODULE_STATE_H

View File

@@ -0,0 +1,58 @@
#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"
#include "boost/phoenix/fusion/at.hpp"
#include <boost/phoenix/bind.hpp>
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 = karma::lit("\n<Object>") << '#' << karma::eol << subrule
<< prop[phx::bind(&obj_grammar::getProperties, karma::_val, karma::_1)]
<< '$' << karma::eol << karma::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::PropertySequence>::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 = -(karma::eps(valid<0>::value) << karma::eps(phx::at_c<index<0>::value>(karma::_val)) << fusion::at<index<0> >(rules)[karma::_1 = phx::at_c<index<0>::value>(karma::_val)])
<< -(karma::eps(valid<1>::value) << karma::eps(phx::at_c<index<1>::value>(karma::_val)) << fusion::at<index<1> >(rules)[karma::_1 = phx::at_c<index<1>::value>(karma::_val)])
<< -(karma::eps(valid<2>::value) << karma::eps(phx::at_c<index<2>::value>(karma::_val)) << fusion::at<index<2> >(rules)[karma::_1 = phx::at_c<index<2>::value>(karma::_val)])
<< -(karma::eps(valid<3>::value) << karma::eps(phx::at_c<index<3>::value>(karma::_val)) << fusion::at<index<3> >(rules)[karma::_1 = phx::at_c<index<3>::value>(karma::_val)])
<< -(karma::eps(valid<4>::value) << karma::eps(phx::at_c<index<4>::value>(karma::_val)) << fusion::at<index<4> >(rules)[karma::_1 = phx::at_c<index<4>::value>(karma::_val)])
<< -(karma::eps(valid<5>::value) << karma::eps(phx::at_c<index<5>::value>(karma::_val)) << fusion::at<index<5> >(rules)[karma::_1 = phx::at_c<index<5>::value>(karma::_val)])
<< -(karma::eps(valid<6>::value) << karma::eps(phx::at_c<index<6>::value>(karma::_val)) << fusion::at<index<6> >(rules)[karma::_1 = phx::at_c<index<6>::value>(karma::_val)])
<< -(karma::eps(valid<7>::value) << karma::eps(phx::at_c<index<7>::value>(karma::_val)) << fusion::at<index<7> >(rules)[karma::_1 = phx::at_c<index<7>::value>(karma::_val)])
<< -(karma::eps(valid<8>::value) << karma::eps(phx::at_c<index<8>::value>(karma::_val)) << fusion::at<index<8> >(rules)[karma::_1 = phx::at_c<index<8>::value>(karma::_val)])
<< -(karma::eps(valid<9>::value) << karma::eps(phx::at_c<index<9>::value>(karma::_val)) << fusion::at<index<9> >(rules)[karma::_1 = phx::at_c<index<9>::value>(karma::_val)]);
};
} //namespace details
}//dcm
#endif //DCM_OBJECT_GENERATOR_H

View File

@@ -0,0 +1,78 @@
/*
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"
#include "boost/phoenix/fusion/at.hpp"
namespace dcm {
namespace details {
template<typename srs, typename prs, typename dist>
typename boost::enable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_obj_init(srs& sseq, prs& pseq) {
if(dist::value == 0) {
fusion::at<dist>(pseq) %= fusion::at<dist>(sseq)(qi::_r1, qi::_r2);
}
else {
fusion::at<dist>(pseq) %= fusion::at<typename mpl::prior< typename mpl::max<dist, mpl::int_<1> >::type >::type>(pseq)(qi::_r1, qi::_r2) | fusion::at<dist>(sseq)(qi::_r1, qi::_r2);
}
recursive_obj_init<srs, prs, typename mpl::next<dist>::type>(sseq, pseq);
};
template<typename srs, typename prs, typename dist>
typename boost::disable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_obj_init(srs& sseq, prs& pseq) {};
template<typename Sys, typename ObjList, typename Object, typename Par>
obj_parser<Sys, ObjList, Object, Par>::obj_parser(): obj_parser::base_type(start) {
typedef typename mpl::find<ObjList, Object>::type::pos pos;
Par::init(subrule);
start = qi::lit("<Object>") >> subrule(qi::_r2)[phx::at_c<pos::value>(*qi::_r1) = qi::_1]
>> qi::eps(phx::at_c<pos::value>(*qi::_r1))[ phx::bind(&Sys::template push_back<Object>, qi::_r2, phx::at_c<pos::value>(*qi::_r1))]
>> prop[phx::bind(&obj_parser::setProperties, phx::at_c<pos::value>(*qi::_r1), qi::_1)]
>> qi::lit("</Object>");
};
template<typename Sys, typename ObjList, typename Object, typename Par>
void obj_parser<Sys, ObjList, Object, Par>::setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::PropertySequence>::type& seq) {
if(ptr) ptr->m_properties = seq;
};
template<typename Sys>
obj_par<Sys>::obj_par(): obj_par<Sys>::base_type(obj) {
recursive_obj_init<typename fusion::result_of::as_vector<sub_rules_sequence>::type,
typename fusion::result_of::as_vector<parent_rules_sequence>::type,
mpl::int_<0> >(sub_rules, parent_rules);
obj = *(fusion::back(parent_rules)(&qi::_val, qi::_r1));
};
}//details
}//DCM
#endif

View File

@@ -0,0 +1,77 @@
/*
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>
#include "../parser.hpp"
#include "../defines.hpp"
namespace boost {
namespace spirit {
namespace traits
{
template <typename T1, typename T2, typename T3, typename T4>
struct transform_attribute<boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >, typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties, qi::domain>
{
typedef typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties& type;
static type pre(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >& val) {
return val->m_properties;
}
static void post(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >const& val, typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties const& attr) {}
static void fail(boost::shared_ptr<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(system) {
cluster %= qi::lit("<Cluster id=") >> qi::omit[qi::int_[qi::_a = qi::_1]] >> ">"
>> -(qi::eps(qi::_a > 0)[qi::_val = phx::construct<boost::shared_ptr<graph> >(phx::new_<typename Sys::Cluster>())])
>> qi::eps[phx::bind(&Sys::Cluster::setCopyMode, &(*qi::_val), true)]
>> qi::eps[phx::bind(&Injector<Sys>::setVertexProperty, &in, &(*qi::_val), qi::_a)]
>> qi::attr_cast<boost::shared_ptr<graph>, typename graph::Properties>(cluster_prop >> qi::eps)
>> qi::omit[(*cluster(qi::_r1))[qi::_b = qi::_1]]
>> qi::omit[*vertex(&(*qi::_val), qi::_r1)]
>> qi::omit[*edge(&(*qi::_val), qi::_r1)]
>> qi::eps[phx::bind(&Injector<Sys>::addClusters, &in, qi::_b, &(*qi::_val))]
>> qi::eps[phx::bind(&Sys::Cluster::setCopyMode, &(*qi::_val), false)]
>> "</Cluster>";
system %= qi::lit("<openDCM>") >> -system_prop
>> qi::lit("<Kernel>") >> -kernel_prop >> qi::lit("</Kernel>")
>> cluster(&qi::_val) >> qi::lit("</openDCM>");
};
}
#endif //DCM_PARSER_H

View File

@@ -0,0 +1,50 @@
#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>() {};
template<typename Sys>
system_prop_gen<Sys>::system_prop_gen() : prop_gen<Sys, typename Sys::OptionOwner::PropertySequence>() {};
template<typename Sys>
kernel_prop_gen<Sys>::kernel_prop_gen() : prop_gen<Sys, typename Sys::Kernel::PropertySequence>() {};
}//details
}//dcm
#endif //DCM_PROPERTY_GENERATOR_H

View File

@@ -0,0 +1,101 @@
/*
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"
#include "traits_impl.hpp"
#include <boost/fusion/include/back.hpp>
#include <boost/phoenix/fusion/at.hpp>
namespace dcm {
typedef boost::spirit::istream_iterator IIterator;
namespace details {
template<typename srs, typename prs, typename dist>
typename boost::enable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_init(srs& sseq, prs& pseq) {
if(dist::value == 0) {
fusion::at<dist>(pseq) %= fusion::at<dist>(sseq)(qi::_r1);
}
else {
fusion::at<dist>(pseq) %= fusion::at<typename mpl::prior< typename mpl::max<dist, mpl::int_<1> >::type >::type>(pseq)(qi::_r1) | fusion::at<dist>(sseq)(qi::_r1);
}
recursive_init<srs, prs, typename mpl::next<dist>::type>(sseq, pseq);
};
template<typename srs, typename prs, typename dist>
typename boost::disable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_init(srs& sseq, prs& pseq) {};
template<typename ParentRuleSequence, typename Rule>
typename boost::disable_if<typename fusion::result_of::empty<ParentRuleSequence>::type, void>::type
initalizeLastRule(ParentRuleSequence& pr, Rule& r) {
r = *(fusion::back(pr)(&qi::_val));
};
template<typename ParentRuleSequence, typename Rule>
typename boost::enable_if<typename fusion::result_of::empty<ParentRuleSequence>::type, void>::type
initalizeLastRule(ParentRuleSequence& pr, Rule& r) {};
template<typename PropList, typename Prop, typename Par>
prop_parser<PropList, Prop, Par>::prop_parser() : prop_parser<PropList, Prop, Par>::base_type(start) {
typedef typename mpl::find<PropList, Prop>::type::pos pos;
Par::init(subrule);
start = qi::lit("<Property>") >> subrule[phx::at_c<pos::value>(*qi::_r1) = qi::_1] >> qi::lit("</Property>");
};
template<typename Sys, typename PropertyList>
prop_par<Sys, PropertyList>::prop_par() : prop_par<Sys, PropertyList>::base_type(prop) {
recursive_init<typename fusion::result_of::as_vector<sub_rules_sequence>::type,
typename fusion::result_of::as_vector<parent_rules_sequence>::type,
mpl::int_<0> >(sub_rules, parent_rules);
//we need to specialy treat empty sequences
initalizeLastRule(parent_rules, prop);
};
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>() {};
template<typename Sys>
kernel_prop_par<Sys>::kernel_prop_par() : prop_par<Sys, typename Sys::Kernel::PropertySequence>() {};
template<typename Sys>
system_prop_par<Sys>::system_prop_par() : prop_par<Sys, typename Sys::OptionOwner::PropertySequence>() {};
} //DCM
} //details
#endif

View File

@@ -0,0 +1,185 @@
/*
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 "opendcm/core/kernel.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<precision, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_generator<precision, System, iterator> {
typedef karma::rule<iterator, double&()> generator;
static void init(generator& r) {
r = karma::lit("<type>precision</type>\n<value>") << karma::double_ <<"</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<precision, System> : public mpl::true_ {};
template<typename System, typename iterator>
struct parser_parser<precision, System, iterator> {
typedef qi::rule<iterator, double(), qi::space_type> parser;
static void init(parser& r) {
r = qi::lit("<type>precision</type>") >> ("<value>") >> qi::double_ >>"</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

@@ -31,10 +31,10 @@ public:
template<typename Sink>
bool put(Sink& dest, int c) {
if(c == '+') {
if(c == '#') {
indent++;
return true;
} else if(c == '-') {
} else if(c == '$') {
indent--;
return true;
} else if(c == '\n') {

View File

@@ -21,14 +21,8 @@
#define DCM_MODULE_STATE_H
#include <iosfwd>
#include "indent.hpp"
#include "generator.hpp"
#include "parser.hpp"
#include "defines.hpp"
namespace qi = boost::spirit::qi;
namespace dcm {
struct ModuleState {
@@ -46,47 +40,31 @@ struct ModuleState {
Sys* m_this;
void saveState(std::ostream& stream) {
void saveState(std::ostream& stream);
void loadState(std::istream& 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);
};
void system_sub(boost:shared_ptr<Sys> subsys) {};
};
//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;
typedef mpl::vector0<> geometries;
typedef mpl::map0<> signals;
//nothing to do on startup
//nothing to do on startup and copy
static void system_init(Sys& sys) {};
static void system_copy(const Sys& from, Sys& into) {};
};
};
}
#ifndef DCM_EXTERNAL_STATE
#include "imp/module_imp.hpp"
#endif
#endif //DCM_MODULE_STATE_H

View File

@@ -69,8 +69,8 @@ namespace details {
} //namespace details
}//dcm
#ifndef USE_EXTERNAL
#include "object_generator_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/object_generator_imp.hpp"
#endif
#endif //DCM_OBJECT_GENERATOR_H

View File

@@ -57,19 +57,18 @@ struct obj_par : public qi::grammar<IIterator,
typename details::sps<typename Sys::objects>::type(Sys*),
qi::space_type> {
typedef typename Sys::objects ObjectList;
typedef typename Sys::objects ObjectList;
//create a vector with the appropriate rules for all needed objects.
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type sub_rules_sequence;
//the type of the objectlist rule
typedef qi::rule<IIterator, qi::unused_type(typename details::sps<ObjectList>::type*, Sys*), qi::space_type> parent_rule;
//we need to store all recursive created rules
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
//create a vector with the appropriate rules for all needed objects.
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type sub_rules_sequence;
//the type of the objectlist rule
typedef qi::rule<IIterator, qi::unused_type(typename details::sps<ObjectList>::type*, Sys*), qi::space_type> parent_rule;
//we need to store all recursive created rules
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_rules;
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_rules;
qi::rule<IIterator, typename details::sps<ObjectList>::type(Sys*), qi::space_type> obj;
obj_par();
@@ -78,8 +77,8 @@ typename details::sps<typename Sys::objects>::type(Sys*),
}//details
}//DCM
#ifndef USE_EXTERNAL
#include "property_parser_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/object_parser_imp.hpp"
#endif
#endif

View File

@@ -59,17 +59,21 @@ static void print(std::string s) {
};
template<typename Sys>
struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<int, std::vector<typename Sys::Cluster*> >, qi::space_type> {
struct parser : qi::grammar<IIterator, Sys(), qi::space_type> {
typedef typename Sys::Cluster graph;
parser();
qi::rule<IIterator, graph*(Sys*), qi::locals<int, std::vector<graph*> >, qi::space_type> cluster;
qi::rule<IIterator, Sys(), qi::space_type> system;
details::kernel_prop_par<Sys> kernel_prop;
details::system_prop_par<Sys> system_prop;
qi::rule<IIterator, boost::shared_ptr<graph>(Sys*), qi::locals<int, std::vector<boost::shared_ptr<graph> > >, 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;
@@ -79,8 +83,8 @@ struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<
}
#ifndef USE_EXTERNAL
#include "parser_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/parser_imp.hpp"
#endif
#endif //DCM_PARSER_H

View File

@@ -96,11 +96,21 @@ struct edge_prop_gen : public prop_gen<Sys, typename Sys::Cluster::edge_properti
edge_prop_gen();
};
template<typename Sys>
struct system_prop_gen : public prop_gen<Sys, typename Sys::OptionOwner::PropertySequence> {
system_prop_gen();
};
template<typename Sys>
struct kernel_prop_gen : public prop_gen<Sys, typename Sys::Kernel::PropertySequence> {
kernel_prop_gen();
};
}//details
}//dcm
#ifndef USE_EXTERNAL
#include "property_generator_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/property_generator_imp.hpp"
#endif
#endif //DCM_PROPERTY_GENERATOR_H

View File

@@ -69,37 +69,47 @@ struct prop_par : qi::grammar<IIterator, typename details::pts<PropertyList>::ty
typedef qi::rule<IIterator, qi::unused_type(typename details::pts<PropertyList>::type*), qi::space_type> parent_rule;
//we need to store all recursive created rules
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_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();
};
//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();
};
template<typename Sys>
struct kernel_prop_par : public prop_par<Sys, typename Sys::Kernel::PropertySequence> {
kernel_prop_par();
};
template<typename Sys>
struct system_prop_par : public prop_par<Sys, typename Sys::OptionOwner::PropertySequence> {
system_prop_par();
};
} //DCM
} //details
#ifndef USE_EXTERNAL
#include "property_parser_imp.hpp"
#ifndef DCM_EXTERNAL_STATE
#include "imp/property_parser_imp.hpp"
#endif
#endif

View File

@@ -54,4 +54,8 @@ struct parser_parser {
};
}
#ifndef DCM_EXTERNAL_STATE
#include "imp/traits_impl.hpp"
#endif
#endif //DCM_PARSER_TRAITS_H

View File

@@ -33,5 +33,56 @@
#include "moduleState/module.hpp"
#include "moduleState/traits.hpp"
#ifdef DCM_EXTERNAL_STATE
#define DCM_EXTERNAL_STATE_INCLUDE_001 <opendcm/moduleState/edge_vertex_generator_imp.hpp>
#define DCM_EXTERNAL_STATE_001( System )\
template struct dcm::details::edge_generator<System>; \
template struct dcm::details::vertex_generator<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_002 <opendcm/moduleState/object_generator_imp.hpp>
#define DCM_EXTERNAL_STATE_002( System )\
template struct dcm::details::obj_gen<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_003 <opendcm/moduleState/property_generator_imp.hpp>
#define DCM_EXTERNAL_STATE_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>; \
template struct dcm::details::system_prop_gen<System>; \
template struct dcm::details::kernel_prop_gen<System>;
#define DCM_EXTERNAL_STATE_INCLUDE_004 <opendcm/moduleState/generator_imp.hpp>
#define DCM_EXTERNAL_STATE_004( System )\
template struct dcm::generator<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_005 <opendcm/moduleState/property_parser_imp.hpp>
#define DCM_EXTERNAL_STATE_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>; \
template struct dcm::details::system_prop_par<System>; \
template struct dcm::details::kernel_prop_par<System>;
#define DCM_EXTERNAL_STATE_INCLUDE_006 <opendcm/moduleState/object_parser_imp.hpp>
#define DCM_EXTERNAL_STATE_006( System )\
template struct dcm::details::obj_par<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_007 <opendcm/moduleState/edge_vertex_parser_imp.hpp>
#define DCM_EXTERNAL_STATE_007( System )\
template struct dcm::details::edge_parser<System>; \
template struct dcm::details::vertex_parser<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_008 <opendcm/moduleState/parser_imp.hpp>
#define DCM_EXTERNAL_STATE_008( System )\
template struct dcm::parser<System>; \
#define DCM_EXTERNAL_STATE_INCLUDE_009 <opendcm/moduleState/imp/module_imp.hpp>
#define DCM_EXTERNAL_STATE_009( System )\
template struct dcm::ModuleState::type<System>; \
#endif //external
#endif //DCM_MODULEPARSER_H