add opendcm constraint solver
This commit is contained in:
parent
474fbbcb3e
commit
952d9140d3
1
src/Mod/Assembly/App/opendcm/.kdev_include_paths
Normal file
1
src/Mod/Assembly/App/opendcm/.kdev_include_paths
Normal file
|
@ -0,0 +1 @@
|
|||
/usr/include/eigen3
|
28
src/Mod/Assembly/App/opendcm/core.hpp
Normal file
28
src/Mod/Assembly/App/opendcm/core.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CORE_H
|
||||
#define DCM_CORE_H
|
||||
|
||||
#include "core/geometry.hpp"
|
||||
#include "core/kernel.hpp"
|
||||
#include "core/system.hpp"
|
||||
|
||||
#endif //DCM_CORE_H
|
||||
|
1520
src/Mod/Assembly/App/opendcm/core/clustergraph.hpp
Normal file
1520
src/Mod/Assembly/App/opendcm/core/clustergraph.hpp
Normal file
File diff suppressed because it is too large
Load Diff
512
src/Mod/Assembly/App/opendcm/core/constraint.hpp
Normal file
512
src/Mod/Assembly/App/opendcm/core/constraint.hpp
Normal file
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_CONSTRAINT_H
|
||||
#define GCM_CONSTRAINT_H
|
||||
|
||||
|
||||
#include<Eigen/StdVector>
|
||||
|
||||
#include <assert.h>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
|
||||
#include "traits.hpp"
|
||||
#include "object.hpp"
|
||||
#include "equations.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//type erasure container for constraints
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
class Constraint : public Object<Sys, Derived, Signals > {
|
||||
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::DynStride DS;
|
||||
|
||||
typedef boost::shared_ptr<Geometry> geom_ptr;
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
|
||||
public:
|
||||
Constraint(Sys& system, geom_ptr f, geom_ptr s);
|
||||
~Constraint();
|
||||
|
||||
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
|
||||
|
||||
protected:
|
||||
|
||||
template<typename ConstraintVector>
|
||||
void initialize(typename fusion::result_of::as_vector<ConstraintVector>::type& obj);
|
||||
|
||||
int equationCount();
|
||||
|
||||
template< typename creator_type>
|
||||
void resetType(creator_type& c);
|
||||
|
||||
void calculate(Scalar scale);
|
||||
|
||||
void setMaps(MES& mes);
|
||||
|
||||
void geometryReset(geom_ptr g) {
|
||||
/* placeholder* p = content->resetConstraint(first, second);
|
||||
delete content;
|
||||
content = p;*/
|
||||
};
|
||||
|
||||
void collectPseudoPoints(Vec& vec1, Vec& vec2);
|
||||
|
||||
//Equation is the constraint with types, the EquationSet hold all needed Maps for calculation
|
||||
template<typename Equation>
|
||||
struct EquationSet {
|
||||
EquationSet() : m_diff_first(NULL,0,DS(0,0)), m_diff_second(NULL,0,DS(0,0)),
|
||||
m_residual(NULL,0,DS(0,0)) {};
|
||||
|
||||
Equation m_eq;
|
||||
typename Kernel::VectorMap m_diff_first; //first geometry diff
|
||||
typename Kernel::VectorMap m_diff_second; //second geometry diff
|
||||
typename Kernel::VectorMap m_residual;
|
||||
|
||||
typedef Equation eq_type;
|
||||
};
|
||||
|
||||
struct placeholder {
|
||||
virtual ~placeholder() {}
|
||||
virtual placeholder* resetConstraint(geom_ptr first, geom_ptr second) const = 0;
|
||||
virtual void calculate(geom_ptr first, geom_ptr second, Scalar scale) = 0;
|
||||
virtual int equationCount() = 0;
|
||||
virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second) = 0;
|
||||
virtual void collectPseudoPoints(geom_ptr first, geom_ptr second, Vec& vec1, Vec& vec2) = 0;
|
||||
virtual placeholder* clone() = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
template< typename ConstraintVector, typename EquationVector>
|
||||
struct holder : public placeholder {
|
||||
|
||||
//create a vector of EquationSets with some mpl trickery
|
||||
typedef typename mpl::fold< EquationVector, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, EquationSet<mpl::_2> > >::type eq_set_vector;
|
||||
typedef typename fusion::result_of::as_vector<eq_set_vector>::type EquationSets;
|
||||
|
||||
typedef typename fusion::result_of::as_vector<ConstraintVector>::type Objects;
|
||||
|
||||
template<typename T>
|
||||
struct has_option {
|
||||
//we get the index of the eqaution in the eqaution vector, and as it is the same
|
||||
//as the index of the constraint in the constraint vector we can extract the
|
||||
//option type and check if it is no_option
|
||||
typedef typename mpl::find<EquationVector, T>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
|
||||
typedef typename mpl::at<ConstraintVector, distance>::type option_type;
|
||||
typedef mpl::not_<boost::is_same<option_type, no_option> > type;
|
||||
};
|
||||
|
||||
struct OptionSetter {
|
||||
|
||||
Objects& objects;
|
||||
|
||||
OptionSetter(Objects& val);
|
||||
|
||||
//only set the value if the equation has a option
|
||||
template< typename T >
|
||||
typename boost::enable_if<typename has_option<T>::type, void>::type
|
||||
operator()(EquationSet<T>& val) const;
|
||||
//if the equation has no otpion we do nothing!
|
||||
template< typename T >
|
||||
typename boost::enable_if<mpl::not_<typename has_option<T>::type>, void>::type
|
||||
operator()(EquationSet<T>& val) const;
|
||||
};
|
||||
|
||||
struct Calculater {
|
||||
|
||||
geom_ptr first, second;
|
||||
Scalar scale;
|
||||
|
||||
Calculater(geom_ptr f, geom_ptr s, Scalar sc);
|
||||
|
||||
template< typename T >
|
||||
void operator()(T& val) const;
|
||||
};
|
||||
|
||||
struct MapSetter {
|
||||
MES& mes;
|
||||
geom_ptr first, second;
|
||||
|
||||
MapSetter(MES& m, geom_ptr f, geom_ptr s);
|
||||
|
||||
template< typename T >
|
||||
void operator()(T& val) const;
|
||||
};
|
||||
|
||||
struct PseudoCollector {
|
||||
Vec& points1;
|
||||
Vec& points2;
|
||||
geom_ptr first,second;
|
||||
|
||||
PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
|
||||
|
||||
template< typename T >
|
||||
void operator()(T& val) const;
|
||||
};
|
||||
|
||||
holder(Objects& obj);
|
||||
|
||||
virtual void calculate(geom_ptr first, geom_ptr second, Scalar scale);
|
||||
virtual placeholder* resetConstraint(geom_ptr first, geom_ptr second) const;
|
||||
virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second);
|
||||
virtual void collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
|
||||
virtual placeholder* clone();
|
||||
virtual int equationCount() {
|
||||
return mpl::size<EquationVector>::value;
|
||||
};
|
||||
|
||||
EquationSets m_sets;
|
||||
};
|
||||
|
||||
protected:
|
||||
template< typename ConstraintVector >
|
||||
struct creator : public boost::static_visitor<void> {
|
||||
|
||||
typedef typename fusion::result_of::as_vector<ConstraintVector>::type Objects;
|
||||
Objects& objects;
|
||||
|
||||
creator(Objects& obj);
|
||||
|
||||
template<typename C, typename T1, typename T2>
|
||||
struct equation {
|
||||
typedef typename C::template type<Kernel, T1, T2> type;
|
||||
};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void operator()(const T1&, const T2&);
|
||||
|
||||
placeholder* p;
|
||||
bool need_swap;
|
||||
};
|
||||
|
||||
placeholder* content;
|
||||
geom_ptr first, second;
|
||||
Connection cf, cs;
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::Constraint(Sys& system, geom_ptr f, geom_ptr s)
|
||||
: first(f), second(s), content(0) {
|
||||
|
||||
this->m_system = &system;
|
||||
cf = first->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
cs = second->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::~Constraint() {
|
||||
delete content;
|
||||
first->template disconnectSignal<reset>(cf);
|
||||
second->template disconnectSignal<reset>(cs);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
boost::shared_ptr<Derived> Constraint<Sys, Derived, Signals, MES, Geometry>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//copy the internals
|
||||
np->content = content->clone();
|
||||
//and get the geometry pointers right
|
||||
if(first) {
|
||||
GlobalVertex v = first->template getProperty<typename Geometry::vertex_propertie>();
|
||||
np->first = newSys.m_cluster->template getObject<Geometry>(v);
|
||||
}
|
||||
if(second) {
|
||||
GlobalVertex v = second->template getProperty<typename Geometry::vertex_propertie>();
|
||||
np->second = newSys.m_cluster->template getObject<Geometry>(v);
|
||||
}
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::initialize(typename fusion::result_of::as_vector<ConstraintVector>::type& obj) {
|
||||
|
||||
//first create the new placeholder
|
||||
creator<ConstraintVector> c(obj);
|
||||
boost::apply_visitor(c, first->m_geometry, second->m_geometry);
|
||||
|
||||
//and now store it
|
||||
content = c.p;
|
||||
//geometry order needs to be the one needed by equations
|
||||
if(c.need_swap) first.swap(second);
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
int Constraint<Sys, Derived, Signals, MES, Geometry>::equationCount() {
|
||||
return content->equationCount();
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template< typename creator_type>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::resetType(creator_type& c) {
|
||||
boost::apply_visitor(c, first->m_geometry, second->m_geometry);
|
||||
content = c.p;
|
||||
if(c.need_swap) first.swap(second);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::calculate(Scalar scale) {
|
||||
content->calculate(first, second, scale);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::setMaps(MES& mes) {
|
||||
content->setMaps(mes, first, second);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
|
||||
content->collectPseudoPoints(first, second, vec1, vec2);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template<typename T>
|
||||
typename boost::enable_if<typename Constraint<Sys, Derived, Signals, MES, Geometry>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type, void>::type
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
//get the index of the corresbonding equation
|
||||
typedef typename mpl::find<EquationVector, T>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
|
||||
val.m_eq.value = fusion::at<distance>(objects).value;
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template<typename T>
|
||||
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Derived, Signals, MES, Geometry>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type>, void>::type
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc) : first(f), second(s), scale(sc) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::Calculater::operator()(T& val) const {
|
||||
|
||||
val.m_eq.setScale(scale);
|
||||
|
||||
val.m_residual(0) = val.m_eq.calculate(first->m_parameter, second->m_parameter);
|
||||
|
||||
//now see which way we should calculate the gradient (may be diffrent for both geometries)
|
||||
if(first->m_parameterCount) {
|
||||
if(first->getClusterMode()) {
|
||||
//when the cluster is fixed no maps are set as no parameters exist.
|
||||
if(!first->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<6; i++) {
|
||||
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
|
||||
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientFirstComplete(first->m_parameter, second->m_parameter, val.m_diff_first);
|
||||
}
|
||||
}
|
||||
if(second->m_parameterCount) {
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<6; i++) {
|
||||
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
|
||||
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientSecondComplete(first->m_parameter, second->m_parameter, val.m_diff_second);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
|
||||
: mes(m), first(f), second(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::MapSetter::operator()(T& val) const {
|
||||
|
||||
//when in cluster, there are 6 clusterparameter we differentiat for, if not we differentiat
|
||||
//for every parameter in the geometry;
|
||||
int equation = mes.setResidualMap(val.m_residual);
|
||||
if(first->getClusterMode()) {
|
||||
if(!first->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, first->m_offset, 6, val.m_diff_first);
|
||||
}
|
||||
} else mes.setJacobiMap(equation, first->m_offset, first->m_parameterCount, val.m_diff_first);
|
||||
|
||||
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, second->m_offset, 6, val.m_diff_second);
|
||||
}
|
||||
} else mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2)
|
||||
: first(f), second(s), points1(vec1), points2(vec2) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::PseudoCollector::operator()(T& val) const {
|
||||
if(first->m_isInCluster && second->m_isInCluster) {
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, second->m_rotated, points2);
|
||||
} else if(first->m_isInCluster) {
|
||||
typename Kernel::Vector sec = second->m_parameter;
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, sec, points2);
|
||||
} else if(second->m_isInCluster) {
|
||||
typename Kernel::Vector fir = first->m_parameter;
|
||||
val.m_eq.calculatePseudo(fir, points1, second->m_rotated, points2);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::holder(Objects& obj) {
|
||||
//set the initial values in the equations
|
||||
fusion::for_each(m_sets, OptionSetter(obj));
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::calculate(geom_ptr first, geom_ptr second, Scalar scale) {
|
||||
fusion::for_each(m_sets, Calculater(first, second, scale));
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
typename Constraint<Sys, Derived, Signals, MES, Geometry>::placeholder*
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::resetConstraint(geom_ptr first, geom_ptr second) const {
|
||||
//boost::apply_visitor(creator, first->m_geometry, second->m_geometry);
|
||||
//if(creator.need_swap) first.swap(second);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
|
||||
fusion::for_each(m_sets, MapSetter(mes, first, second));
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) {
|
||||
fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2));
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
typename Constraint<Sys, Derived, Signals, MES, Geometry>::placeholder*
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::holder<ConstraintVector, EquationVector>::clone() {
|
||||
return new holder(*this);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template< typename ConstraintVector >
|
||||
Constraint<Sys, Derived, Signals, MES, Geometry>::creator<ConstraintVector>::creator(Objects& obj) : objects(obj) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Signals, typename MES, typename Geometry>
|
||||
template< typename ConstraintVector >
|
||||
template<typename T1, typename T2>
|
||||
void Constraint<Sys, Derived, Signals, MES, Geometry>::creator<ConstraintVector>::operator()(const T1&, const T2&) {
|
||||
typedef tag_order< typename geometry_traits<T1>::tag, typename geometry_traits<T2>::tag > order;
|
||||
|
||||
//transform the constraints into eqautions with the now known types
|
||||
typedef typename mpl::fold< ConstraintVector, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, equation<mpl::_2, typename order::first_tag,
|
||||
typename order::second_tag> > >::type EquationVector;
|
||||
|
||||
//and build the placeholder
|
||||
p = new holder<ConstraintVector, EquationVector>(objects);
|
||||
need_swap = order::swapt::value;
|
||||
};
|
||||
|
||||
|
||||
};//detail
|
||||
|
||||
};//dcm
|
||||
|
||||
#endif //GCM_CONSTRAINT_H
|
||||
|
189
src/Mod/Assembly/App/opendcm/core/equations.hpp
Normal file
189
src/Mod/Assembly/App/opendcm/core/equations.hpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_EQUATIONS_H
|
||||
#define GCM_EQUATIONS_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct no_option {};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Pseudo {
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Scale {
|
||||
void setScale(typename Kernel::number_type scale) {};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct PseudoScale {
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
|
||||
void setScale(typename Kernel::number_type scale) {};
|
||||
};
|
||||
|
||||
struct Distance {
|
||||
|
||||
typedef double option_type;
|
||||
option_type value;
|
||||
|
||||
Distance() : value(0) {};
|
||||
|
||||
Distance& operator=(const option_type val) {
|
||||
value = val;
|
||||
return *this;
|
||||
};
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
|
||||
Scalar value;
|
||||
//template definition
|
||||
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {
|
||||
assert(false);
|
||||
};
|
||||
void setScale(Scalar scale) {
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//the possible directions
|
||||
enum Direction { Same, Opposite, Both };
|
||||
|
||||
struct Parallel {
|
||||
|
||||
typedef Direction option_type;
|
||||
option_type value;
|
||||
|
||||
Parallel() : value(Both) {};
|
||||
|
||||
Parallel& operator=(const option_type val) {
|
||||
value = val;
|
||||
return *this;
|
||||
};
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type : public PseudoScale<Kernel> {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
|
||||
option_type value;
|
||||
|
||||
//template definition
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
assert(false);
|
||||
return 0;
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct Angle {
|
||||
|
||||
typedef double option_type;
|
||||
option_type value;
|
||||
|
||||
Angle() : value(0) {};
|
||||
|
||||
Angle& operator=(const option_type val) {
|
||||
value = val;
|
||||
return *this;
|
||||
};
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type : public PseudoScale<Kernel> {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
|
||||
option_type value;
|
||||
|
||||
//template definition
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//static is needed to restrain the scope of the objects to the current compilation unit. Without it
|
||||
//every compiled file including this header would define these as global and the linker would find
|
||||
//multiple definitions of the same objects
|
||||
static Distance distance;
|
||||
static Parallel parallel;
|
||||
static Angle angle;
|
||||
|
||||
};
|
||||
|
||||
#endif //GCM_EQUATIONS_H
|
||||
|
481
src/Mod/Assembly/App/opendcm/core/geometry.hpp
Normal file
481
src/Mod/Assembly/App/opendcm/core/geometry.hpp
Normal file
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GCM_GEOMETRY_H
|
||||
#define GCM_GEOMETRY_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include "object.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "transformation.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace tag {
|
||||
|
||||
struct undefined {
|
||||
typedef mpl::int_<0> parameters;
|
||||
typedef mpl::int_<0> transformations;
|
||||
};
|
||||
|
||||
//we need to order tags, this values make it easy for module tags
|
||||
namespace weight {
|
||||
struct direction : mpl::int_<0> {};
|
||||
struct point : mpl::int_<1> {};
|
||||
struct line : mpl::int_<2> {};
|
||||
struct plane : mpl::int_<3> {};
|
||||
struct cylinder : mpl::int_<4> {};
|
||||
}
|
||||
}
|
||||
|
||||
struct orderd_bracket_accessor {
|
||||
|
||||
template<typename Scalar, int ID, typename T>
|
||||
Scalar get(T& t) {
|
||||
return t[ID];
|
||||
};
|
||||
template<typename Scalar, int ID, typename T>
|
||||
void set(Scalar value, T& t) {
|
||||
t[ID] = value;
|
||||
};
|
||||
};
|
||||
|
||||
struct orderd_roundbracket_accessor {
|
||||
|
||||
template<typename Scalar, int ID, typename T>
|
||||
Scalar get(T& t) {
|
||||
return t(ID);
|
||||
};
|
||||
template<typename Scalar, int ID, typename T>
|
||||
void set(Scalar value, T& t) {
|
||||
t(ID) = value;
|
||||
};
|
||||
};
|
||||
|
||||
//tag ordering (smaller weight is first tag)
|
||||
template<typename T1, typename T2>
|
||||
struct tag_order {
|
||||
|
||||
BOOST_MPL_ASSERT((mpl::not_< mpl::or_<
|
||||
boost::is_same< typename T1::weight, mpl::int_<0> >,
|
||||
boost::is_same< typename T2::weight, mpl::int_<0> > > >));
|
||||
|
||||
typedef typename mpl::less<typename T2::weight, typename T1::weight>::type swapt;
|
||||
typedef typename mpl::if_<swapt, T2, T1>::type first_tag;
|
||||
typedef typename mpl::if_<swapt, T1, T2>::type second_tag;
|
||||
};
|
||||
|
||||
|
||||
//template<typename T1, typename T2>
|
||||
//struct type_order : public tag_order< typename geometry_traits<T1>::tag, typename geometry_traits<T2>::tag > {};
|
||||
|
||||
|
||||
template< typename T>
|
||||
struct geometry_traits {
|
||||
BOOST_MPL_ASSERT_MSG(false, NO_GEOMETRY_TRAITS_SPECIFIED_FOR_TYPE, (T));
|
||||
};
|
||||
|
||||
template< typename T>
|
||||
struct geometry_clone_traits {
|
||||
T operator()(T& val) {
|
||||
return T(val);
|
||||
};
|
||||
};
|
||||
|
||||
struct reset {}; //signal namespace
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
class Geometry : public Object<Sys, Derived,
|
||||
mpl::map3< mpl::pair<reset, boost::function<void (boost::shared_ptr<Derived>) > >,
|
||||
mpl::pair<remove, boost::function<void (boost::shared_ptr<Derived>) > > ,
|
||||
mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Derived>)> > > > {
|
||||
|
||||
typedef mpl::map3< mpl::pair<reset, boost::function<void (boost::shared_ptr<Derived>) > >,
|
||||
mpl::pair<remove, boost::function<void (boost::shared_ptr<Derived>) > >,
|
||||
mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Derived>)> > > Signals;
|
||||
|
||||
typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant;
|
||||
typedef Object<Sys, Derived, Signals> Base;
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::DynStride DS;
|
||||
typedef typename Kernel::template transform_type<Dim>::type Transform;
|
||||
typedef typename Kernel::template transform_type<Dim>::diff_type DiffTransform;
|
||||
|
||||
struct cloner : boost::static_visitor<void> {
|
||||
typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant;
|
||||
|
||||
Variant variant;
|
||||
cloner(Variant& v) : variant(v) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(T& t) {
|
||||
variant = geometry_clone_traits<T>()(t);
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
protected:
|
||||
src::logger log;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef mpl::int_<Dim> Dimension;
|
||||
|
||||
template<typename T>
|
||||
Geometry(T geometry, Sys& system);
|
||||
|
||||
template<typename T>
|
||||
void set(T geometry);
|
||||
|
||||
template<typename Visitor>
|
||||
typename Visitor::result_type apply(Visitor& vis) {
|
||||
return boost::apply_visitor(vis, m_geometry);
|
||||
};
|
||||
|
||||
//basic ation
|
||||
void transform(const Transform& t);
|
||||
|
||||
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
|
||||
|
||||
//allow accessing the internal values in unittests without making them public,
|
||||
//so that access control of the internal classes is not changed and can be tested
|
||||
#ifdef TESTING
|
||||
typename Kernel::Vector& toplocal() {
|
||||
return m_toplocal;
|
||||
};
|
||||
typename Kernel::Vector& rotated() {
|
||||
return m_rotated;
|
||||
};
|
||||
int& offset() {
|
||||
return m_offset;
|
||||
};
|
||||
void clusterMode(bool iscluster, bool isFixed) {
|
||||
setClusterMode(iscluster, isFixed);
|
||||
};
|
||||
void trans(const Transform& t) {
|
||||
transform(t);
|
||||
};
|
||||
void recalc(DiffTransform& trans) {
|
||||
recalculate(trans);
|
||||
};
|
||||
typename Kernel::Vector3 point() {
|
||||
return getPoint();
|
||||
};
|
||||
int parameterCount() {
|
||||
return m_parameterCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
//protected would be the right way, however, visual studio 10 does not find a way to access them even when constraint::holder structs
|
||||
//are declared friend
|
||||
//protected:
|
||||
Variant m_geometry; //Variant holding the real geometry type
|
||||
int m_BaseParameterCount; //count of the parameters the variant geometry type needs
|
||||
int m_parameterCount; //count of the used parameters (when in cluster:6, else m_BaseParameterCount)
|
||||
int m_offset; //the starting point of our parameters in the math system parameter vector
|
||||
int m_rotations; //count of rotations to be done when original vector gets rotated
|
||||
int m_translations; //count of translations to be done when original vector gets rotated
|
||||
bool m_isInCluster, m_clusterFixed, m_init;
|
||||
typename Kernel::Vector m_toplocal; //the local value in the toplevel cluster used for cuttent solving
|
||||
typename Kernel::Vector m_global; //the global value outside of all clusters
|
||||
typename Kernel::Vector m_rotated; //the global value as the rotation of toplocal (used as temp)
|
||||
typename Kernel::Matrix m_diffparam; //gradient vectors combined as matrix when in cluster
|
||||
typename Kernel::VectorMap m_parameter; //map to the parameters in the solver
|
||||
|
||||
template<typename T>
|
||||
void init(T& t);
|
||||
|
||||
void normalize();
|
||||
|
||||
typename Sys::Kernel::VectorMap& getParameterMap();
|
||||
void initMap();
|
||||
|
||||
void setClusterMode(bool iscluster, bool isFixed);
|
||||
bool getClusterMode() {
|
||||
return m_isInCluster;
|
||||
};
|
||||
bool isClusterFixed() {
|
||||
return m_clusterFixed;
|
||||
};
|
||||
|
||||
void recalculate(DiffTransform& trans);
|
||||
|
||||
typename Kernel::Vector3 getPoint() {
|
||||
return m_toplocal.template segment<Dim>(0);
|
||||
};
|
||||
|
||||
//visitor to write the calculated value into the variant
|
||||
struct apply_visitor : public boost::static_visitor<void> {
|
||||
|
||||
apply_visitor(typename Kernel::Vector& v) : value(v) {};
|
||||
template <typename T>
|
||||
void operator()(T& t) const {
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
|
||||
typename geometry_traits<T>::accessor >(t, value);
|
||||
}
|
||||
typename Kernel::Vector& value;
|
||||
};
|
||||
|
||||
//use m_value or parametermap as new value, dependend on the solving mode
|
||||
void finishCalculation();
|
||||
|
||||
template<typename VectorType>
|
||||
void transform(const Transform& t, VectorType& vec);
|
||||
void scale(Scalar value);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
template<typename T>
|
||||
Geometry<Sys, Derived, GeometrieTypeList, Dim>::Geometry(T geometry, Sys& system)
|
||||
: m_isInCluster(false), m_geometry(geometry), m_parameter(NULL,0,DS(0,0)),
|
||||
m_clusterFixed(false), m_init(false) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
|
||||
#endif
|
||||
|
||||
this->m_system = &system;
|
||||
init<T>(geometry);
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
template<typename T>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::set(T geometry) {
|
||||
m_geometry = geometry;
|
||||
init<T>(geometry);
|
||||
//Base::template emitSignal<reset>( ((Derived*)this)->shared_from_this() );
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::transform(const Transform& t) {
|
||||
|
||||
if(m_isInCluster)
|
||||
transform(t, m_toplocal);
|
||||
else if(m_init)
|
||||
transform(t, m_rotated);
|
||||
else
|
||||
transform(t, m_global);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
boost::shared_ptr<Derived> Geometry<Sys, Derived, GeometrieTypeList, Dim>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//it's possible that the variant contains pointers, so we need to clone them
|
||||
cloner clone_fnc(np->m_geometry);
|
||||
boost::apply_visitor(clone_fnc, m_geometry);
|
||||
return np;
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
template<typename T>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::init(T& t) {
|
||||
|
||||
m_BaseParameterCount = geometry_traits<T>::tag::parameters::value;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
m_rotations = geometry_traits<T>::tag::rotations::value;
|
||||
m_translations = geometry_traits<T>::tag::translations::value;
|
||||
|
||||
m_toplocal.setZero(m_parameterCount);
|
||||
m_global.resize(m_parameterCount);
|
||||
m_rotated.resize(m_parameterCount);
|
||||
m_rotated.setZero();
|
||||
|
||||
m_diffparam.resize(m_parameterCount,6);
|
||||
m_diffparam.setZero();
|
||||
|
||||
(typename geometry_traits<T>::modell()).template extract<Scalar,
|
||||
typename geometry_traits<T>::accessor >(t, m_global);
|
||||
normalize();
|
||||
|
||||
//new value which is not set into parameter, so init is false
|
||||
m_init = false;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init: "<<m_global.transpose();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::normalize() {
|
||||
//directions are not nessessarily normalized, but we need to ensure this in cluster mode
|
||||
for(int i=m_translations; i!=m_rotations; i++)
|
||||
m_global.template segment<Dim>(i*Dim).normalize();
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
typename Sys::Kernel::VectorMap& Geometry<Sys, Derived, GeometrieTypeList, Dim>::getParameterMap() {
|
||||
m_isInCluster = false;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
return m_parameter;
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::initMap() {
|
||||
//when direct parameter solving the global value is wanted (as it's the initial rotation*toplocal)
|
||||
m_parameter = m_global;
|
||||
m_init = true;
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::setClusterMode(bool iscluster, bool isFixed) {
|
||||
|
||||
m_isInCluster = iscluster;
|
||||
m_clusterFixed = isFixed;
|
||||
if(iscluster) {
|
||||
//we are in cluster, therfore the parameter map should not point to a solver value but to
|
||||
//the rotated original value;
|
||||
new(&m_parameter) typename Sys::Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1));
|
||||
//the local value is the global one as no transformation was applied yet
|
||||
m_toplocal = m_global;
|
||||
m_rotated = m_global;
|
||||
} else new(&m_parameter) typename Sys::Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::recalculate(DiffTransform& trans) {
|
||||
if(!m_isInCluster) return;
|
||||
|
||||
for(int i=0; i!=m_rotations; i++) {
|
||||
//first rotate the original to the transformed value
|
||||
m_rotated.block(i*Dim,0,Dim,1) = trans.rotation()*m_toplocal.template segment<Dim>(i*Dim);
|
||||
|
||||
//now calculate the gradient vectors and add them to diffparam
|
||||
for(int j=0; j<Dim; j++)
|
||||
m_diffparam.block(i*Dim,j,Dim,1) = trans.differential().block(0,j*3,Dim,Dim) * m_toplocal.template segment<Dim>(i*Dim);
|
||||
}
|
||||
//after rotating the needed parameters we translate the stuff that needs to be moved
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
m_rotated.block(i*Dim,0,Dim,1) += trans.translation().vector();
|
||||
m_rotated.block(i*Dim,0,Dim,1) *= trans.scaling().factor();
|
||||
//calculate the gradient vectors and add them to diffparam
|
||||
m_diffparam.block(i*Dim,Dim,Dim,Dim).setIdentity();
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isnormal(m_rotated.norm()) || !boost::math::isnormal(m_diffparam.norm())) {
|
||||
BOOST_LOG(log) << "Unnormal recalculated value detected: "<<m_rotated.transpose()<<std::endl
|
||||
<< "or unnormal recalculated diff detected: "<<std::endl<<m_diffparam<<std::endl
|
||||
<<" with Transform: "<<std::endl<<trans;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::finishCalculation() {
|
||||
//if fixed nothing needs to be changed
|
||||
if(m_isInCluster) {
|
||||
//recalculate(1.); //remove scaling to get right global value
|
||||
m_global = m_rotated;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish cluster calculation";
|
||||
#endif
|
||||
}
|
||||
//TODO:non cluster paramter scaling
|
||||
else {
|
||||
m_global = m_parameter;
|
||||
normalize();
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
};
|
||||
apply_visitor v(m_global);
|
||||
apply(v);
|
||||
m_init = false;
|
||||
m_isInCluster = false;
|
||||
|
||||
//emit the signal for recalculation
|
||||
Base::template emitSignal<recalculated>( ((Derived*)this)->shared_from_this() );
|
||||
};
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
template<typename VectorType>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::transform(const Transform& t, VectorType& vec) {
|
||||
|
||||
//everything that needs to be translated needs to be fully transformed
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t*v;
|
||||
}
|
||||
|
||||
for(int i=m_translations; i!=m_rotations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t.rotate(v);
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Transformed with cluster: "<<m_isInCluster
|
||||
<< ", init: "<<m_init<<" into: "<< vec.transpose();
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim>
|
||||
void Geometry<Sys, Derived, GeometrieTypeList, Dim>::scale(Scalar value) {
|
||||
|
||||
for(int i=0; i!=m_translations; i++)
|
||||
m_parameter.template segment<Dim>(i*Dim) *= 1./value;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GCM_GEOMETRY_H
|
425
src/Mod/Assembly/App/opendcm/core/kernel.hpp
Normal file
425
src/Mod/Assembly/App/opendcm/core/kernel.hpp
Normal file
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_KERNEL_H
|
||||
#define GCM_KERNEL_H
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Dense>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <time.h>
|
||||
|
||||
#include "transformation.hpp"
|
||||
#include "logging.hpp"
|
||||
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace E = Eigen;
|
||||
|
||||
struct nothing {
|
||||
void operator()() {};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Dogleg {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
#endif
|
||||
|
||||
typedef typename Kernel::number_type number_type;
|
||||
number_type tolg, tolx, tolf;
|
||||
|
||||
Dogleg() : tolg(1e-40), tolx(1e-20), tolf(1e-5) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
|
||||
int calculateStep(const Eigen::MatrixBase<Derived>& g, const Eigen::MatrixBase<Derived3>& jacobi,
|
||||
const Eigen::MatrixBase<Derived4>& residual, Eigen::MatrixBase<Derived2>& h_dl,
|
||||
const double delta) {
|
||||
|
||||
// get the steepest descent stepsize and direction
|
||||
const double alpha(g.squaredNorm()/(jacobi*g).squaredNorm());
|
||||
const typename Kernel::Vector h_sd = -g;
|
||||
|
||||
// get the gauss-newton step
|
||||
const typename Kernel::Vector h_gn = (jacobi).fullPivLu().solve(-residual);
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(h_gn.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal gauss-newton detected: "<<h_gn.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(h_sd.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal steepest descent detected: "<<h_sd.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(alpha)) {
|
||||
BOOST_LOG(log)<< "Unnormal alpha detected: "<<alpha;
|
||||
}
|
||||
#endif
|
||||
|
||||
// compute the dogleg step
|
||||
if(h_gn.norm() <= delta) {
|
||||
h_dl = h_gn;
|
||||
} else if((alpha*h_sd).norm() >= delta) {
|
||||
//h_dl = alpha*h_sd;
|
||||
h_dl = (delta/(h_sd.norm()))*h_sd;
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(h_dl.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg descent detected: "<<h_dl.norm();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
//compute beta
|
||||
number_type beta = 0;
|
||||
typename Kernel::Vector a = alpha*h_sd;
|
||||
typename Kernel::Vector b = h_gn;
|
||||
number_type c = a.transpose()*(b-a);
|
||||
number_type bas = (b-a).squaredNorm(), as = a.squaredNorm();
|
||||
if(c<0) {
|
||||
beta = -c+std::sqrt(std::pow(c,2)+bas*(std::pow(delta,2)-as));
|
||||
beta /= bas;
|
||||
} else {
|
||||
beta = std::pow(delta,2)-as;
|
||||
beta /= c+std::sqrt(std::pow(c,2) + bas*(std::pow(delta,2)-as));
|
||||
};
|
||||
|
||||
// and update h_dl and dL with beta
|
||||
h_dl = alpha*h_sd + beta*(b-a);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(c)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg c detected: "<<c;
|
||||
}
|
||||
if(!boost::math::isfinite(bas)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg bas detected: "<<bas;
|
||||
}
|
||||
if(!boost::math::isfinite(beta)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg beta detected: "<<beta;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int solve(typename Kernel::MappedEquationSystem& sys) {
|
||||
nothing n;
|
||||
return solve(sys, n);
|
||||
};
|
||||
|
||||
template<typename Functor>
|
||||
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale) {
|
||||
|
||||
clock_t start = clock();
|
||||
clock_t inc_rec = clock();
|
||||
|
||||
if(!sys.isValid()) return 5;
|
||||
|
||||
bool translate = true;
|
||||
|
||||
typename Kernel::Vector h_dl, F_old(sys.m_eqns), g(sys.m_eqns);
|
||||
typename Kernel::Matrix J_old(sys.m_eqns, sys.m_params);
|
||||
|
||||
sys.recalculate();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "initial jacobi: "<<std::endl<<sys.Jacobi<<std::endl
|
||||
<< "residual: "<<sys.Residual.transpose()<<std::endl
|
||||
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
|
||||
#endif
|
||||
|
||||
number_type err = sys.Residual.norm();
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get the infinity norm fx_inf and g_inf
|
||||
number_type g_inf = g.template lpNorm<E::Infinity>();
|
||||
number_type fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
int maxIterNumber = 10000;//MaxIterations * xsize;
|
||||
number_type diverging_lim = 1e6*err + 1e12;
|
||||
|
||||
number_type delta=5;
|
||||
number_type nu=2.;
|
||||
int iter=0, stop=0, reduce=0, unused=0, counter=0;
|
||||
|
||||
|
||||
while(!stop) {
|
||||
|
||||
// check if finished
|
||||
if(fx_inf <= tolf*sys.Scaling) // Success
|
||||
stop = 1;
|
||||
else if(g_inf <= tolg)
|
||||
stop = 2;
|
||||
else if(delta <= tolx)
|
||||
stop = 3;
|
||||
else if(iter >= maxIterNumber)
|
||||
stop = 4;
|
||||
else if(!boost::math::isfinite(err))
|
||||
stop = 5;
|
||||
else if(err > diverging_lim)
|
||||
stop = 6;
|
||||
|
||||
|
||||
// see if we are already finished
|
||||
if(stop)
|
||||
break;
|
||||
|
||||
number_type err_new;
|
||||
number_type dF=0, dL=0;
|
||||
number_type rho;
|
||||
|
||||
//get the update step
|
||||
calculateStep(g, sys.Jacobi, sys.Residual, h_dl, delta);
|
||||
|
||||
// calculate the linear model
|
||||
dL = 0.5*sys.Residual.norm() - 0.5*(sys.Residual + sys.Jacobi*h_dl).norm();
|
||||
|
||||
// get the new values
|
||||
sys.Parameter += h_dl;
|
||||
|
||||
clock_t start_rec = clock();
|
||||
sys.recalculate();
|
||||
clock_t end_rec = clock();
|
||||
inc_rec += end_rec-start_rec;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(sys.Residual.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal residual detected: "<<sys.Residual.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(sys.Jacobi.sum())) {
|
||||
BOOST_LOG(log)<< "Unnormal jacobi detected: "<<sys.Jacobi.sum();
|
||||
}
|
||||
#endif
|
||||
|
||||
//calculate the translation update ratio
|
||||
err_new = sys.Residual.norm();
|
||||
dF = err - err_new;
|
||||
rho = dF/dL;
|
||||
|
||||
if(dF<=0 || dL<=0) rho = -1;
|
||||
// update delta
|
||||
if(rho>0.85) {
|
||||
delta = std::max(delta,2*h_dl.norm());
|
||||
nu = 2;
|
||||
} else if(rho < 0.25) {
|
||||
delta = delta/nu;
|
||||
nu = 2*nu;
|
||||
}
|
||||
|
||||
if(dF > 0 && dL > 0) {
|
||||
|
||||
//see if we got too high differentials
|
||||
if(sys.Jacobi.template lpNorm<Eigen::Infinity>() > 2) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "High differential detected: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>()<<" in iteration: "<<iter;
|
||||
#endif
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
}
|
||||
//it can also happen that the differentials get too small, however, we cant check for that
|
||||
else if(iter>1 && (counter>50)) {
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
err = sys.Residual.norm();
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get infinity norms
|
||||
g_inf = g.template lpNorm<E::Infinity>();
|
||||
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
} else {
|
||||
sys.Residual = F_old;
|
||||
sys.Jacobi = J_old;
|
||||
sys.Parameter -= h_dl;
|
||||
unused++;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Reject step in iter "<<iter;
|
||||
#endif
|
||||
}
|
||||
|
||||
iter++;
|
||||
counter++;
|
||||
}
|
||||
/*
|
||||
clock_t end = clock();
|
||||
double ms = (double(end-start) * 1000.) / double(CLOCKS_PER_SEC);
|
||||
double ms_rec = (double(inc_rec-start) * 1000.) / double(CLOCKS_PER_SEC);
|
||||
*/
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) <<"Done solving: "<<err<<", iter: "<<iter<<", unused: "<<unused<<", reason:"<< stop;
|
||||
BOOST_LOG(log)<< "final jacobi: "<<std::endl<<sys.Jacobi;
|
||||
#endif
|
||||
|
||||
return stop;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear = Dogleg>
|
||||
struct Kernel {
|
||||
|
||||
//basics
|
||||
typedef Scalar number_type;
|
||||
|
||||
//linear algebra types 2D
|
||||
typedef E::Matrix<Scalar, 2, 1> Vector2;
|
||||
|
||||
//Linear algebra types 3D
|
||||
typedef E::Matrix<Scalar, 3, 1> Vector3;
|
||||
typedef E::Matrix<Scalar, 1, 3> CVector3;
|
||||
typedef E::Matrix<Scalar, 3, 3> Matrix3;
|
||||
typedef E::Matrix<Scalar, E::Dynamic, 1> Vector;
|
||||
typedef E::Matrix<Scalar, 1, E::Dynamic> CVector;
|
||||
typedef E::Matrix<Scalar, E::Dynamic, E::Dynamic> Matrix;
|
||||
|
||||
//mapped types
|
||||
typedef E::Stride<E::Dynamic, E::Dynamic> DynStride;
|
||||
typedef E::Map< Vector3 > Vector3Map;
|
||||
typedef E::Map< CVector3> CVector3Map;
|
||||
typedef E::Map< Matrix3 > Matrix3Map;
|
||||
typedef E::Map< Vector, 0, DynStride > VectorMap;
|
||||
typedef E::Map< CVector, 0, DynStride > CVectorMap;
|
||||
typedef E::Map< Matrix, 0, DynStride > MatrixMap;
|
||||
|
||||
//Special types
|
||||
typedef E::Quaternion<Scalar> Quaternion;
|
||||
typedef E::Matrix<Scalar, 3, 9> Matrix39;
|
||||
typedef E::Map< Matrix39 > Matrix39Map;
|
||||
typedef E::Block<Matrix> MatrixBlock;
|
||||
|
||||
typedef detail::Transform<Scalar, 3> Transform3D;
|
||||
typedef detail::DiffTransform<Scalar, 3> DiffTransform3D;
|
||||
|
||||
typedef detail::Transform<Scalar, 2> Transform2D;
|
||||
typedef detail::DiffTransform<Scalar, 2> DiffTransform2D;
|
||||
|
||||
typedef Nonlinear< Kernel<Scalar, Nonlinear> > NonlinearSolver;
|
||||
|
||||
template<int Dim>
|
||||
struct transform_type {
|
||||
typedef typename boost::mpl::if_c<Dim==2, Transform2D, Transform3D>::type type;
|
||||
typedef typename boost::mpl::if_c<Dim==2, DiffTransform2D, DiffTransform3D>::type diff_type;
|
||||
};
|
||||
|
||||
template<int Dim>
|
||||
struct vector_type {
|
||||
typedef E::Matrix<Scalar, Dim, 1> type;
|
||||
};
|
||||
|
||||
|
||||
struct MappedEquationSystem {
|
||||
|
||||
Matrix Jacobi;
|
||||
Vector Parameter;
|
||||
Vector Residual;
|
||||
number_type Scaling;
|
||||
int m_params, m_eqns; //total amount
|
||||
int m_param_offset, m_eqn_offset; //current positions while creation
|
||||
|
||||
MappedEquationSystem(int params, int equations)
|
||||
: Jacobi(equations, params),
|
||||
Parameter(params), Residual(equations),
|
||||
m_params(params), m_eqns(equations), Scaling(1.) {
|
||||
|
||||
m_param_offset = 0;
|
||||
m_eqn_offset = 0;
|
||||
|
||||
Jacobi.setZero(); //important as some places are never written
|
||||
};
|
||||
|
||||
int setParameterMap(int number, VectorMap& map) {
|
||||
|
||||
new(&map) VectorMap(&Parameter(m_param_offset), number, DynStride(1,1));
|
||||
m_param_offset += number;
|
||||
return m_param_offset-number;
|
||||
};
|
||||
int setParameterMap(Vector3Map& map) {
|
||||
|
||||
new(&map) Vector3Map(&Parameter(m_param_offset));
|
||||
m_param_offset += 3;
|
||||
return m_param_offset-3;
|
||||
};
|
||||
int setResidualMap(VectorMap& map) {
|
||||
new(&map) VectorMap(&Residual(m_eqn_offset), 1, DynStride(1,1));
|
||||
return m_eqn_offset++;
|
||||
};
|
||||
void setJacobiMap(int eqn, int offset, int number, CVectorMap& map) {
|
||||
new(&map) CVectorMap(&Jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
void setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
|
||||
new(&map) VectorMap(&Jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
|
||||
bool isValid() {
|
||||
if(!m_params || !m_eqns) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
virtual void recalculate() = 0;
|
||||
|
||||
};
|
||||
|
||||
Kernel() {};
|
||||
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1-p2).squaredNorm() < 0.00001);
|
||||
}
|
||||
static bool isSame(number_type t1, number_type t2) {
|
||||
return (std::abs(t1-t2) < 0.00001);
|
||||
}
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1+p2).squaredNorm() < 0.00001);
|
||||
}
|
||||
|
||||
static int solve(MappedEquationSystem& mes) {
|
||||
nothing n;
|
||||
return Nonlinear< Kernel<Scalar, Nonlinear> >().solve(mes, n);
|
||||
};
|
||||
|
||||
template<typename Functor>
|
||||
static int solve(MappedEquationSystem& mes, Functor& f) {
|
||||
return Nonlinear< Kernel<Scalar, Nonlinear> >().solve(mes, f);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_KERNEL_H
|
||||
|
||||
|
94
src/Mod/Assembly/App/opendcm/core/logging.hpp
Normal file
94
src/Mod/Assembly/App/opendcm/core/logging.hpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_LOGGING_H
|
||||
#define GCM_LOGGING_H
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
#include <boost/log/sinks.hpp>
|
||||
#include <boost/log/attributes.hpp>
|
||||
#include <boost/log/attributes/attribute_def.hpp>
|
||||
#include <boost/log/utility/init/to_file.hpp>
|
||||
#include <boost/log/utility/init/common_attributes.hpp>
|
||||
#include <boost/log/sources/logger.hpp>
|
||||
#include <boost/log/sources/record_ostream.hpp>
|
||||
#include <boost/log/formatters.hpp>
|
||||
#include <boost/log/filters.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace logging = boost::log;
|
||||
namespace sinks = boost::log::sinks;
|
||||
namespace src = boost::log::sources;
|
||||
namespace fmt = boost::log::formatters;
|
||||
namespace flt = boost::log::filters;
|
||||
namespace attrs = boost::log::attributes;
|
||||
namespace keywords = boost::log::keywords;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
static int counter = 0;
|
||||
typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;
|
||||
|
||||
inline boost::shared_ptr< sink_t > init_log() {
|
||||
|
||||
//create the filename
|
||||
std::stringstream str;
|
||||
str<<"openDCM_"<<counter<<"_%N.log";
|
||||
counter++;
|
||||
|
||||
boost::shared_ptr< logging::core > core = logging::core::get();
|
||||
|
||||
boost::shared_ptr< sinks::text_file_backend > backend =
|
||||
boost::make_shared< sinks::text_file_backend >(
|
||||
keywords::file_name = str.str(), //file name pattern
|
||||
keywords::rotation_size = 10 * 1024 * 1024 //Rotation size is 10MB
|
||||
);
|
||||
|
||||
// Wrap it into the frontend and register in the core.
|
||||
// The backend requires synchronization in the frontend.
|
||||
boost::shared_ptr< sink_t > sink(new sink_t(backend));
|
||||
|
||||
sink->set_formatter(
|
||||
fmt::stream <<"[" << fmt::attr<std::string>("Tag") <<"] "
|
||||
<< fmt::if_(flt::has_attr<std::string>("ID")) [
|
||||
fmt::stream << "["<< fmt::attr< std::string >("ID")<<"] "]
|
||||
<< fmt::message()
|
||||
);
|
||||
|
||||
core->add_sink(sink);
|
||||
return sink;
|
||||
};
|
||||
|
||||
inline void stop_log(boost::shared_ptr< sink_t >& sink) {
|
||||
|
||||
boost::shared_ptr< logging::core > core = logging::core::get();
|
||||
|
||||
// Remove the sink from the core, so that no records are passed to it
|
||||
core->remove_sink(sink);
|
||||
sink.reset();
|
||||
};
|
||||
|
||||
}; //dcm
|
||||
|
||||
#endif //USE_LOGGING
|
||||
|
||||
#endif //GCM_LOGGING_H
|
269
src/Mod/Assembly/App/opendcm/core/object.hpp
Normal file
269
src/Mod/Assembly/App/opendcm/core/object.hpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_OBJECT_H
|
||||
#define GCM_OBJECT_H
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/key_type.hpp>
|
||||
#include <boost/mpl/value_type.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#include "property.hpp"
|
||||
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
#define EMIT_ARGUMENTS(z, n, data) \
|
||||
BOOST_PP_CAT(data, n)
|
||||
|
||||
#define EMIT_CALL_DEF(z, n, data) \
|
||||
template < \
|
||||
typename S \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
|
||||
> \
|
||||
void emitSignal( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
|
||||
);
|
||||
|
||||
#define EMIT_CALL_DEC(z, n, data) \
|
||||
template<typename Sys, typename Derived, typename Sig> \
|
||||
template < \
|
||||
typename S \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
|
||||
> \
|
||||
void Object<Sys, Derived, Sig>::emitSignal( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
|
||||
) \
|
||||
{ \
|
||||
typedef typename mpl::find<sig_name, S>::type iterator; \
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance; \
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type; \
|
||||
list_type& list = fusion::at<distance>(m_signals); \
|
||||
for (typename list_type::iterator it=list.begin(); it != list.end(); it++) \
|
||||
(*it)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
|
||||
};
|
||||
|
||||
namespace dcm {
|
||||
|
||||
//few standart signal names
|
||||
struct remove {};
|
||||
struct recalculated {};
|
||||
|
||||
typedef boost::any Connection;
|
||||
|
||||
/**
|
||||
* @brief Base class for all object types
|
||||
*
|
||||
* This class add's property and signal capabilitys to all deriving classes. For properties it is tigthly
|
||||
* integrated with the system class: It searches systems property list for the derived class as specified by
|
||||
* the second template parameter and makes it accessible via appopriate functions. Signals are speciefied by a
|
||||
* mpl::map with signal name type as key and a boost::function as values.
|
||||
*
|
||||
* \tparam Sys class of type System of which the properties are taken
|
||||
* \tparam Obj the type of the derived object
|
||||
* \tparam Sig a mpl::map specifing the object's signals by (type - boost::function) pairs
|
||||
**/
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
struct Object : public boost::enable_shared_from_this<Derived> {
|
||||
|
||||
Object() {};
|
||||
Object(Sys& system);
|
||||
|
||||
/**
|
||||
* @brief Create a new object of the same type with the same values
|
||||
*
|
||||
* Returns a new shared_ptr for the Drived type with the same properties as the initial one. If
|
||||
* the new pointer should be used in a new system the parameter \param newSys needs to be that
|
||||
* new system. Overload this function if you have datamembers in any derived class wich are not
|
||||
* copyconstructable.
|
||||
* @tparam Prop property type which should be accessed
|
||||
* @return Prop::type& a reference to the properties actual value.
|
||||
**/
|
||||
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
|
||||
|
||||
/**
|
||||
* @brief Access properties
|
||||
*
|
||||
* Returns a reference to the propertys actual value. The property type has to be registerd to the
|
||||
* System type which was given as template parameter to this object.
|
||||
* @tparam Prop property type which should be accessed
|
||||
* @return Prop::type& a reference to the properties actual value.
|
||||
**/
|
||||
template<typename Prop>
|
||||
typename Prop::type& getProperty();
|
||||
|
||||
/**
|
||||
* @brief Set properties
|
||||
*
|
||||
* Set'S the value of a specified property. The property type has to be registerd to the
|
||||
* System type which was given as template parameter to this object. Note that setProperty(value)
|
||||
* is equivalent to getProperty() = value.
|
||||
* @tparam Prop property type which should be setProperty
|
||||
* @param value value of type Prop::type which should be set in this object
|
||||
**/
|
||||
template<typename Prop>
|
||||
void setProperty(typename Prop::type value);
|
||||
|
||||
/**
|
||||
* @brief Connects a slot to a specified signal.
|
||||
*
|
||||
* Slots are boost::functions which get called when the signal is emitted. Any valid boost::function
|
||||
* which ressembles the signal tyes signature can be registert. It is important that the signal type
|
||||
* was registerd to this object on creation by the appropriate template parameter.
|
||||
*
|
||||
* @tparam S the signal which should be intercepted
|
||||
* @param function boost::function which resembles the signal type's signature
|
||||
* @return void
|
||||
**/
|
||||
template<typename S>
|
||||
Connection connectSignal(typename mpl::at<Sig, S>::type function);
|
||||
|
||||
/**
|
||||
* @brief Disconnects a slot for a specific signal.
|
||||
*
|
||||
* Disconnects a slot so that it dosn't get called at signal emittion. It's important to
|
||||
* disconnect the slot by the same boost:function it was connected with.
|
||||
*
|
||||
* @tparam S the signal type of interest
|
||||
* @param function boost::function with which the slot was connected
|
||||
* @return void
|
||||
**/
|
||||
template<typename S>
|
||||
void disconnectSignal(Connection c);
|
||||
|
||||
/*properties
|
||||
* search the property map of the system class and get the mpl::vector of properties for the
|
||||
* derived type. It's imortant to not store the properties but their types. These types are
|
||||
* stored and accessed as fusion vector.
|
||||
* */
|
||||
typedef typename mpl::at<typename Sys::object_properties, Derived>::type Mapped;
|
||||
typedef typename mpl::if_< boost::is_same<Mapped, mpl::void_ >, mpl::vector0<>, Mapped>::type Sequence;
|
||||
typedef typename details::pts<Sequence>::type Properties;
|
||||
|
||||
Properties m_properties;
|
||||
Sys* m_system;
|
||||
|
||||
protected:
|
||||
/*signal handling
|
||||
* extract all signal types to allow index search (inex search on signal functions would fail as same
|
||||
* signatures are supported for multiple signals). Create std::vectors to allow multiple slots per signal
|
||||
* and store these vectors in a fusion::vector for easy access.
|
||||
* */
|
||||
typedef typename mpl::fold< Sig, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, mpl::key_type<Sig, mpl::_2> > >::type sig_name;
|
||||
typedef typename mpl::fold< Sig, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, mpl::value_type<Sig, mpl::_2> > >::type sig_functions;
|
||||
typedef typename mpl::fold< sig_functions, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, std::list<mpl::_2> > >::type sig_vectors;
|
||||
typedef typename fusion::result_of::as_vector<sig_vectors>::type Signals;
|
||||
|
||||
Signals m_signals;
|
||||
|
||||
public:
|
||||
//with no vararg templates before c++11 we need preprocessor to create the overloads of emit signal we need
|
||||
BOOST_PP_REPEAT(5, EMIT_CALL_DEF, ~)
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
Object<Sys, Derived, Sig>::Object(Sys& system) : m_system(&system) {};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
boost::shared_ptr<Derived> Object<Sys, Derived, Sig>::clone(Sys& newSys) {
|
||||
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
template<typename Prop>
|
||||
typename Prop::type& Object<Sys, Derived, Sig>::getProperty() {
|
||||
typedef typename mpl::find<Sequence, Prop>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<Sequence>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<Sequence>::type > >));
|
||||
return fusion::at<distance>(m_properties);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
template<typename Prop>
|
||||
void Object<Sys, Derived, Sig>::setProperty(typename Prop::type value) {
|
||||
typedef typename mpl::find<Sequence, Prop>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<Sequence>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<Sequence>::type > >));
|
||||
fusion::at<distance>(m_properties) = value;
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
template<typename S>
|
||||
Connection Object<Sys, Derived, Sig>::connectSignal(typename mpl::at<Sig, S>::type function) {
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type;
|
||||
list_type& list = fusion::at<distance>(m_signals);
|
||||
return list.insert(list.begin(),function);
|
||||
};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
template<typename S>
|
||||
void Object<Sys, Derived, Sig>::disconnectSignal(Connection c) {
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type list_type;
|
||||
list_type& list = fusion::at<distance>(m_signals);
|
||||
list.erase(boost::any_cast<typename list_type::iterator>(c));
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_OBJECT_H
|
||||
|
||||
|
167
src/Mod/Assembly/App/opendcm/core/property.hpp
Normal file
167
src/Mod/Assembly/App/opendcm/core/property.hpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_PROPERTY_H
|
||||
#define GCM_PROPERTY_H
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/buffer_concepts.hpp>
|
||||
#include <boost/fusion/sequence.hpp>
|
||||
#include <boost/fusion/container/vector.hpp>
|
||||
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct vertex_property {};
|
||||
struct edge_property {};
|
||||
struct cluster_property {};
|
||||
struct object_property {};
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Graph>
|
||||
struct vertex_selector {
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
|
||||
typedef typename Graph::vertex_properties sequence_type;
|
||||
};
|
||||
|
||||
template<typename Graph>
|
||||
struct edge_selector {
|
||||
typedef typename boost::graph_traits<Graph>::edge_descriptor key_type;
|
||||
typedef typename Graph::edge_properties sequence_type;
|
||||
};
|
||||
|
||||
template< typename Kind, typename Graph>
|
||||
struct property_selector : public mpl::if_<boost::is_same<Kind, vertex_property>,
|
||||
vertex_selector<Graph>, edge_selector<Graph> >::type {};
|
||||
|
||||
template<typename T>
|
||||
struct property_type {
|
||||
typedef typename T::type type;
|
||||
};
|
||||
template<typename T>
|
||||
struct property_kind {
|
||||
typedef typename T::kind type;
|
||||
};
|
||||
|
||||
//property vector to a fusion sequence of the propety types
|
||||
template<typename T>
|
||||
struct pts { //property type sequence
|
||||
typedef typename mpl::transform<T, details::property_type<mpl::_1> >::type ptv;
|
||||
typedef typename fusion::result_of::as_vector< ptv >::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct is_edge_property : boost::is_same<typename T::kind,edge_property> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_vertex_property : boost::is_same<typename T::kind,vertex_property> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_cluster_property : boost::is_same<typename T::kind,cluster_property> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_object_property : boost::is_same<typename T::kind,object_property> {};
|
||||
|
||||
template <typename Property, typename Graph>
|
||||
class property_map {
|
||||
|
||||
public:
|
||||
typedef typename dcm::details::property_selector<typename Property::kind, Graph>::key_type key_type;
|
||||
typedef typename Property::type value_type;
|
||||
typedef typename Property::type& reference;
|
||||
typedef boost::lvalue_property_map_tag category;
|
||||
|
||||
typedef Property property;
|
||||
typedef typename dcm::details::property_selector<typename Property::kind, Graph>::sequence_type sequence;
|
||||
|
||||
property_map(Graph& g)
|
||||
: m_graph(g) { }
|
||||
|
||||
Graph& m_graph;
|
||||
};
|
||||
|
||||
template<typename P, typename G>
|
||||
typename property_map<P,G>::value_type get(const property_map<P,G>& map,
|
||||
typename property_map<P,G>::key_type key) {
|
||||
|
||||
typedef property_map<P,G> map_t;
|
||||
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
|
||||
return fusion::at<distance>(fusion::at_c<0>(map.m_graph[key]));
|
||||
};
|
||||
|
||||
template <typename P, typename G>
|
||||
void put(const property_map<P,G>& map,
|
||||
typename property_map<P,G>::key_type key,
|
||||
const typename property_map<P,G>::value_type& value) {
|
||||
|
||||
typedef property_map<P,G> map_t;
|
||||
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
|
||||
fusion::at<distance>(fusion::at_c<0>(map.m_graph[key])) = value;
|
||||
};
|
||||
|
||||
|
||||
template <typename P, typename G>
|
||||
typename property_map<P,G>::reference at(const property_map<P,G>& map,
|
||||
typename property_map<P,G>::key_type key) {
|
||||
typedef property_map<P,G> map_t;
|
||||
typedef typename mpl::find<typename map_t::sequence, typename map_t::property>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<typename map_t::sequence>::type, iterator>::type distance;
|
||||
return fusion::at<distance>(fusion::at_c<0>(map.m_graph[key]));
|
||||
}
|
||||
|
||||
|
||||
//now create some standart properties
|
||||
//***********************************
|
||||
|
||||
struct empty_prop {
|
||||
typedef int kind;
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct type_prop {
|
||||
//states the type of a cluster
|
||||
typedef cluster_property kind;
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct changed_prop {
|
||||
typedef cluster_property kind;
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct id_prop {
|
||||
typedef object_property kind;
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //GCM_PROPERTY_H
|
100
src/Mod/Assembly/App/opendcm/core/sheduler.hpp
Normal file
100
src/Mod/Assembly/App/opendcm/core/sheduler.hpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_SHEDULER_H
|
||||
#define GCM_SHEDULER_H
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Sys>
|
||||
struct Job {
|
||||
|
||||
virtual ~Job() {};
|
||||
|
||||
virtual void execute(Sys& sys) = 0;
|
||||
|
||||
bool operator<(const Job<Sys>& j) const {
|
||||
return priority < j.priority;
|
||||
};
|
||||
int priority;
|
||||
};
|
||||
|
||||
template<typename functor, typename System, int prior>
|
||||
struct FunctorJob : Job<System> {
|
||||
FunctorJob(functor f) : m_functor(f) {
|
||||
Job<System>::priority = prior;
|
||||
};
|
||||
virtual void execute(System& sys) {
|
||||
m_functor(sys);
|
||||
};
|
||||
|
||||
functor m_functor;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
class Sheduler {
|
||||
|
||||
public:
|
||||
Sheduler() {};
|
||||
~Sheduler() {
|
||||
|
||||
std::for_each(m_preprocess.begin(), m_preprocess.end(), Deleter());
|
||||
std::for_each(m_process.begin(), m_process.end(), Deleter());
|
||||
std::for_each(m_postprocess.begin(), m_postprocess.end(), Deleter());
|
||||
};
|
||||
|
||||
void addPreprocessJob(Job<Sys>* j) {
|
||||
m_preprocess.insert(j);
|
||||
};
|
||||
void addPostprocessJob(Job<Sys>* j) {
|
||||
m_postprocess.insert(j);
|
||||
};
|
||||
void addProcessJob(Job<Sys>* j) {
|
||||
m_process.insert(j);
|
||||
};
|
||||
|
||||
void execute(Sys& system) {
|
||||
std::for_each(m_preprocess.begin(), m_preprocess.end(), Executer(system));
|
||||
std::for_each(m_process.begin(), m_process.end(), Executer(system));
|
||||
std::for_each(m_postprocess.begin(), m_postprocess.end(), Executer(system));
|
||||
};
|
||||
|
||||
protected:
|
||||
struct Executer {
|
||||
Executer(Sys& s) : m_system(s) {};
|
||||
void operator()(Job<Sys>* j) {
|
||||
j->execute(m_system);
|
||||
};
|
||||
Sys& m_system;
|
||||
};
|
||||
struct Deleter {
|
||||
void operator()(Job<Sys>* j) {
|
||||
delete j;
|
||||
};
|
||||
};
|
||||
|
||||
std::set< Job<Sys>* > m_preprocess, m_process, m_postprocess;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_SHEDULER_H
|
327
src/Mod/Assembly/App/opendcm/core/system.hpp
Normal file
327
src/Mod/Assembly/App/opendcm/core/system.hpp
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_SYSTEM_H
|
||||
#define GCM_SYSTEM_H
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/vector/vector0.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/count.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/less_equal.hpp>
|
||||
#include <boost/mpl/print.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "property.hpp"
|
||||
#include "clustergraph.hpp"
|
||||
#include "sheduler.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "traits.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct No_Identifier {};
|
||||
struct Unspecified_Identifier {};
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
enum { subcluster = 10};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct vector_fold : mpl::fold< seq, state,
|
||||
mpl::push_back<mpl::_1,mpl::_2> > {};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct edge_fold : mpl::fold< seq, state,
|
||||
mpl::if_< is_edge_property<mpl::_2>,
|
||||
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct vertex_fold : mpl::fold< seq, state,
|
||||
mpl::if_< is_vertex_property<mpl::_2>,
|
||||
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct cluster_fold : mpl::fold< seq, state,
|
||||
mpl::if_< is_cluster_property<mpl::_2>,
|
||||
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
|
||||
|
||||
template<typename seq, typename state, typename obj>
|
||||
struct obj_fold : mpl::fold< seq, state,
|
||||
mpl::if_< mpl::or_<
|
||||
boost::is_same< details::property_kind<mpl::_2>, obj>, is_object_property<mpl::_2> >,
|
||||
mpl::push_back<mpl::_1,mpl::_2>, mpl::_1 > > {};
|
||||
|
||||
template<typename objects, typename properties>
|
||||
struct property_map {
|
||||
typedef typename mpl::fold<
|
||||
objects, mpl::map<>, mpl::insert< mpl::_1, mpl::pair<
|
||||
mpl::_2, details::obj_fold<properties, mpl::vector<>, mpl::_2 > > > >::type type;
|
||||
};
|
||||
template<typename T>
|
||||
struct get_identifier {
|
||||
typedef typename T::Identifier type;
|
||||
};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct map_fold : mpl::fold< seq, state, mpl::insert<mpl::_1,mpl::_2> > {};
|
||||
|
||||
struct nothing {};
|
||||
|
||||
template<int v>
|
||||
struct EmptyModule {
|
||||
|
||||
template<typename T>
|
||||
struct type {
|
||||
struct inheriter {};
|
||||
typedef mpl::vector<> properties;
|
||||
typedef mpl::vector<> objects;
|
||||
typedef Unspecified_Identifier Identifier;
|
||||
|
||||
static void system_init(T& sys) {};
|
||||
static void system_copy(const T& from, T& into) {};
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_shared_ptr : boost::mpl::false_ {};
|
||||
template <class T>
|
||||
struct is_shared_ptr<boost::shared_ptr<T> > : boost::mpl::true_ {};
|
||||
|
||||
}
|
||||
|
||||
template< typename KernelType,
|
||||
typename T1 = details::EmptyModule<1>,
|
||||
typename T2 = details::EmptyModule<2>,
|
||||
typename T3 = details::EmptyModule<3> >
|
||||
class System : public T1::template type< System<KernelType,T1,T2,T3> >::inheriter,
|
||||
public T2::template type< System<KernelType,T1,T2,T3> >::inheriter,
|
||||
public T3::template type< System<KernelType,T1,T2,T3> >::inheriter {
|
||||
|
||||
typedef System<KernelType,T1,T2,T3> BaseType;
|
||||
public:
|
||||
typedef typename T1::template type< BaseType > Type1;
|
||||
typedef typename T2::template type< BaseType > Type2;
|
||||
typedef typename T3::template type< BaseType > Type3;
|
||||
typedef mpl::vector3<Type1, Type2, Type3> TypeVector;
|
||||
|
||||
//Check if all Identifiers are the same and find out which type it is
|
||||
typedef typename mpl::fold<TypeVector, mpl::vector<>,
|
||||
mpl::if_<boost::is_same<details::get_identifier<mpl::_2>, Unspecified_Identifier>,
|
||||
mpl::_1, mpl::push_back<mpl::_1, details::get_identifier<mpl::_2> > > >::type Identifiers;
|
||||
BOOST_MPL_ASSERT((mpl::or_<
|
||||
mpl::less_equal<typename mpl::size<Identifiers>::type, mpl::int_<1> >,
|
||||
mpl::equal< typename mpl::count<Identifiers,
|
||||
typename mpl::at_c<Identifiers,0> >::type, typename mpl::size<Identifiers>::type > >));
|
||||
|
||||
typedef typename mpl::if_< mpl::empty<Identifiers>,
|
||||
No_Identifier, typename mpl::at_c<Identifiers, 0>::type >::type Identifier;
|
||||
|
||||
|
||||
public:
|
||||
//get all module objects and properties
|
||||
typedef typename details::vector_fold<typename Type3::objects,
|
||||
typename details::vector_fold<typename Type2::objects,
|
||||
typename details::vector_fold<typename Type1::objects,
|
||||
mpl::vector<> >::type >::type>::type objects;
|
||||
|
||||
typedef typename details::vector_fold<typename Type3::properties,
|
||||
typename details::vector_fold<typename Type2::properties,
|
||||
typename details::vector_fold<typename Type1::properties,
|
||||
mpl::vector<id_prop<Identifier> > >::type >::type>::type properties;
|
||||
|
||||
//make the subcomponent lists of objects and properties
|
||||
typedef typename details::edge_fold< properties, mpl::vector<> >::type edge_properties;
|
||||
typedef typename details::vertex_fold< properties, mpl::vector<> >::type vertex_properties;
|
||||
typedef typename details::cluster_fold< properties,
|
||||
mpl::vector<changed_prop, type_prop> >::type cluster_properties;
|
||||
|
||||
typedef typename details::property_map<objects, properties>::type object_properties;
|
||||
|
||||
protected:
|
||||
//object storage
|
||||
typedef typename mpl::transform<objects, boost::shared_ptr<mpl::_1> >::type sp_objects;
|
||||
typedef typename mpl::fold< sp_objects, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, std::vector<mpl::_2> > >::type object_vectors;
|
||||
typedef typename fusion::result_of::as_vector<object_vectors>::type Storage;
|
||||
|
||||
template<typename FT1, typename FT2, typename FT3>
|
||||
friend struct Object;
|
||||
|
||||
struct clearer {
|
||||
template<typename T>
|
||||
void operator()(T& vector) const {
|
||||
vector.clear();
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
boost::shared_ptr< sink_t > sink;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef ClusterGraph<edge_properties, vertex_properties, cluster_properties, objects> Cluster;
|
||||
typedef Sheduler< BaseType > Shedule;
|
||||
typedef KernelType Kernel;
|
||||
|
||||
public:
|
||||
System() : m_cluster(new Cluster), m_storage(new Storage)
|
||||
#ifdef USE_LOGGING
|
||||
, sink(init_log())
|
||||
#endif
|
||||
{
|
||||
Type1::system_init(*this);
|
||||
Type2::system_init(*this);
|
||||
Type3::system_init(*this);
|
||||
|
||||
};
|
||||
|
||||
|
||||
~System() {
|
||||
#ifdef USE_LOGGING
|
||||
stop_log(sink);
|
||||
#endif
|
||||
};
|
||||
|
||||
void clear() {
|
||||
|
||||
m_cluster->clearClusters();
|
||||
m_cluster->clear();
|
||||
fusion::for_each(*m_storage, clearer());
|
||||
};
|
||||
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator begin() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).begin();
|
||||
};
|
||||
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator end() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).end();
|
||||
};
|
||||
|
||||
template<typename Object>
|
||||
std::vector< boost::shared_ptr<Object> >& objectVector() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage);
|
||||
};
|
||||
|
||||
template<typename Object>
|
||||
void push_back(boost::shared_ptr<Object> ptr) {
|
||||
objectVector<Object>().push_back(ptr);
|
||||
};
|
||||
|
||||
template<typename Object>
|
||||
void erase(boost::shared_ptr<Object> ptr) {
|
||||
|
||||
std::vector< boost::shared_ptr<Object> >& vec = objectVector<Object>();
|
||||
vec.erase(std::remove(vec.begin(), vec.end(), ptr), vec.end());
|
||||
};
|
||||
|
||||
void solve() {
|
||||
clock_t start = clock();
|
||||
m_sheduler.execute(*this);
|
||||
clock_t end = clock();
|
||||
double ms = (double(end-start)* 1000.) / double(CLOCKS_PER_SEC);
|
||||
//Base::Console().Message("overall solving time in ms: %f\n", ms);
|
||||
|
||||
};
|
||||
|
||||
System* createSubsystem() {
|
||||
|
||||
System* s = new System();
|
||||
s->m_cluster = m_cluster->createCluster().first;
|
||||
s->m_storage = m_storage;
|
||||
s->m_cluster->template setClusterProperty<dcm::type_prop>(details::subcluster);
|
||||
return s;
|
||||
};
|
||||
|
||||
private:
|
||||
struct cloner {
|
||||
|
||||
System& newSys;
|
||||
cloner(System& ns) : newSys(ns) {};
|
||||
|
||||
template<typename T>
|
||||
struct test : mpl::and_<details::is_shared_ptr<T>,
|
||||
mpl::not_<boost::is_same<T, boost::shared_ptr<typename System::Cluster> > > > {};
|
||||
|
||||
template<typename T>
|
||||
typename boost::enable_if< test<T>, void>::type operator()(T& p) const {
|
||||
p = p->clone(newSys);
|
||||
newSys.push_back(p);
|
||||
};
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::not_<test<T> >, void>::type operator()(const T& p) const {};
|
||||
};
|
||||
|
||||
public:
|
||||
void copyInto(System& into) const {
|
||||
|
||||
//copy the clustergraph and clone all objects while at it. They are also pushed to the storage
|
||||
cloner cl(into);
|
||||
m_cluster->copyInto(into.m_cluster, cl);
|
||||
|
||||
//notify all modules that they are copied
|
||||
Type1::system_copy(*this, into);
|
||||
Type2::system_copy(*this, into);
|
||||
Type3::system_copy(*this, into);
|
||||
};
|
||||
|
||||
System* clone() const {
|
||||
|
||||
System* ns = new System();
|
||||
this->copyInto(*ns);
|
||||
return ns;
|
||||
};
|
||||
|
||||
boost::shared_ptr<Cluster> m_cluster;
|
||||
boost::shared_ptr<Storage> m_storage;
|
||||
Shedule m_sheduler;
|
||||
Kernel m_kernel;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //GCM_SYSTEM_H
|
||||
|
||||
|
||||
|
101
src/Mod/Assembly/App/opendcm/core/traits.hpp
Normal file
101
src/Mod/Assembly/App/opendcm/core/traits.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_TRAITS_H
|
||||
#define GCM_TRAITS_H
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_shifted.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template< typename T >
|
||||
struct system_traits {
|
||||
typedef typename T::Kernel Kernel;
|
||||
typedef typename T::Cluster Cluster;
|
||||
|
||||
template<typename M>
|
||||
struct getModule {
|
||||
|
||||
typedef typename mpl::if_< boost::is_base_of<M, typename T::Type1>, typename T::Type1, typename T::Type2 >::type test1;
|
||||
typedef typename mpl::if_< boost::is_base_of<M, test1>, test1, typename T::Type3 >::type test2;
|
||||
typedef typename mpl::if_< boost::is_base_of<M, test2>, test2, mpl::void_ >::type type;
|
||||
|
||||
typedef boost::is_same<type, mpl::void_> has_module;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct compare_traits {
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((mpl::not_<boost::is_same<T, const char*> >::value),
|
||||
YOU_SHOULD_NOT_USE_THIS_TYPE_AS_IDENTIFIER,
|
||||
(const char*));
|
||||
|
||||
static bool compare(T& first, T& second) {
|
||||
return first == second;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct compare_traits<std::string> {
|
||||
|
||||
static bool compare(std::string& first, std::string& second) {
|
||||
return !(first.compare(second));
|
||||
};
|
||||
};
|
||||
|
||||
template<typename seq, int size>
|
||||
struct vector_shrink {
|
||||
typedef typename mpl::copy< seq, mpl::back_inserter< mpl::vector<> > >::type type;
|
||||
};
|
||||
|
||||
template<typename seq>
|
||||
struct vector_shrink< seq, 0 > {
|
||||
typedef mpl::vector0<> type;
|
||||
};
|
||||
template<typename seq>
|
||||
struct vector_shrink< seq, 1 > {
|
||||
typedef mpl::vector1< typename mpl::at_c< seq, 0 >::type > type;
|
||||
};
|
||||
|
||||
#define SEQ_TYPES(z, n, data) \
|
||||
typename mpl::at_c< seq, n >::type
|
||||
|
||||
#define VECTOR_SHRINK(z, n, data) \
|
||||
template< typename seq> \
|
||||
struct vector_shrink<seq, n> { \
|
||||
typedef BOOST_PP_CAT(mpl::vector, n) < \
|
||||
BOOST_PP_ENUM(n, SEQ_TYPES, ~) > type; \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2,10, VECTOR_SHRINK, ~)
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //GCM_TRAITS_H
|
292
src/Mod/Assembly/App/opendcm/core/transformation.hpp
Normal file
292
src/Mod/Assembly/App/opendcm/core/transformation.hpp
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DCM_TRANSFORMATION_H
|
||||
#define DCM_TRANSFORMATION_H
|
||||
|
||||
#include <cmath>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace dcm {
|
||||
namespace detail {
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
class Transform {
|
||||
|
||||
public:
|
||||
typedef Eigen::Matrix<Scalar, Dim, 1> Vector;
|
||||
typedef typename boost::mpl::if_c< Dim == 3,
|
||||
Eigen::Quaternion<Scalar>,
|
||||
Eigen::Rotation2D<Scalar> >::type Rotation;
|
||||
typedef Eigen::Translation<Scalar, Dim> Translation;
|
||||
typedef Eigen::UniformScaling<Scalar> Scaling;
|
||||
typedef typename Rotation::RotationMatrixType RotationMatrix;
|
||||
|
||||
protected:
|
||||
Rotation m_rotation;
|
||||
Translation m_translation;
|
||||
Scaling m_scale;
|
||||
|
||||
public:
|
||||
Transform() : m_rotation(Rotation::Identity()),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) { };
|
||||
|
||||
Transform(const Rotation& r) : m_rotation(r),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
Transform(const Rotation& r, const Translation& t) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
Transform(const Rotation& r, const Translation& t, const Scaling& s) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(s) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
//access the single parts and manipulate them
|
||||
//***********************
|
||||
const Rotation& rotation() const {
|
||||
return m_rotation;
|
||||
}
|
||||
template<typename Derived>
|
||||
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
|
||||
m_rotation = rotation.derived().normalized()*m_rotation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Translation& translation() const {
|
||||
return m_translation;
|
||||
}
|
||||
Transform& translate(const Translation& translation) {
|
||||
m_translation = m_translation*translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Scaling& scaling() const {
|
||||
return m_scale;
|
||||
}
|
||||
Transform& scale(const Scalar& scaling) {
|
||||
m_scale *= Scaling(scaling);
|
||||
return *this;
|
||||
}
|
||||
Transform& scale(const Scaling& scaling) {
|
||||
m_scale.factor() *= scaling.factor();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Transform& invert() {
|
||||
m_rotation = m_rotation.inverse();
|
||||
m_translation.vector() = (m_rotation*m_translation.vector()) * (-m_scale.factor());
|
||||
m_scale = Scaling(1./m_scale.factor());
|
||||
return *this;
|
||||
};
|
||||
Transform inverse() {
|
||||
Transform res(*this);
|
||||
res.invert();
|
||||
return res;
|
||||
};
|
||||
|
||||
//operators for value manipulation
|
||||
//********************************
|
||||
|
||||
inline Transform& operator=(const Translation& t) {
|
||||
m_translation = t;
|
||||
m_rotation = Rotation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
return *this;
|
||||
}
|
||||
inline Transform operator*(const Translation& t) const {
|
||||
Transform res = *this;
|
||||
res.translate(t);
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*=(const Translation& t) {
|
||||
return translate(t);
|
||||
}
|
||||
|
||||
inline Transform& operator=(const Scaling& s) {
|
||||
m_scale = s;
|
||||
m_translation = Translation::Identity();
|
||||
m_rotation = Rotation::Identity();
|
||||
return *this;
|
||||
}
|
||||
inline Transform operator*(const Scaling& s) const {
|
||||
Transform res = *this;
|
||||
res.scale(s);
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*=(const Scaling& s) {
|
||||
return scale(s);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
m_rotation = r.derived();
|
||||
m_rotation.normalize();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1);
|
||||
return *this;
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
return res;
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
return rotate(r.derived());
|
||||
}
|
||||
|
||||
inline Transform operator* (const Transform& other) const {
|
||||
Transform res(*this);
|
||||
res*= other;
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*= (const Transform& other) {
|
||||
rotate(other.rotation());
|
||||
other.rotate(m_translation.vector());
|
||||
m_translation.vector() += other.translation().vector()/m_scale.factor();
|
||||
m_scale.factor() *= other.scaling().factor();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//transform Vectors
|
||||
//*****************
|
||||
template<typename Derived>
|
||||
inline Derived& rotate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_rotation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Derived& translate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_translation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Derived& scale(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec*=m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Derived& transform(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
template<typename Derived>
|
||||
inline Derived operator*(const Eigen::MatrixBase<Derived>& vec) const {
|
||||
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
}
|
||||
template<typename Derived>
|
||||
inline void operator()(Eigen::MatrixBase<Derived>& vec) const {
|
||||
transform(vec);
|
||||
}
|
||||
|
||||
//Stuff
|
||||
//*****
|
||||
bool isApprox(const Transform& other, Scalar prec) const {
|
||||
return m_rotation.isApprox(other.rotation(), prec)
|
||||
&& ((m_translation.vector()- other.translation().vector()).norm() < prec)
|
||||
&& (std::abs(m_scale.factor()-other.scaling().factor()) < prec);
|
||||
};
|
||||
void setIdentity() {
|
||||
m_rotation.setIdentity();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
}
|
||||
static const Transform Identity() {
|
||||
return Transform(Rotation::Identity(), Translation::Identity(), Scaling(1));
|
||||
}
|
||||
|
||||
Transform& normalize() {
|
||||
m_rotation.normalize();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
class DiffTransform : public Transform<Scalar, Dim> {
|
||||
|
||||
typedef typename Transform<Scalar, Dim>::Rotation Rotation;
|
||||
typedef typename Transform<Scalar, Dim>::Translation Translation;
|
||||
typedef typename Transform<Scalar, Dim>::Scaling Scaling;
|
||||
typedef Eigen::Matrix<Scalar, Dim, 3*Dim> DiffMatrix;
|
||||
|
||||
DiffMatrix m_diffMatrix;
|
||||
|
||||
public:
|
||||
DiffTransform() : Transform<Scalar, Dim>() { };
|
||||
DiffTransform(const Rotation& r) : Transform<Scalar, Dim>(r) {};
|
||||
DiffTransform(const Rotation& r, const Translation& t) : Transform<Scalar, Dim>(r,t) {};
|
||||
DiffTransform(const Rotation& r, const Translation& t, const Scaling& s) : Transform<Scalar, Dim>(r,t,s) {};
|
||||
|
||||
DiffTransform(Transform<Scalar, Dim>& trans)
|
||||
: Transform<Scalar, Dim>(trans.rotation(), trans.translation(), trans.scaling()) {
|
||||
|
||||
m_diffMatrix.setZero();
|
||||
};
|
||||
|
||||
const DiffMatrix& differential() {
|
||||
return m_diffMatrix;
|
||||
};
|
||||
inline Scalar& operator()(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
inline Scalar& at(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
};
|
||||
|
||||
}//detail
|
||||
}//DCM
|
||||
|
||||
/*When you overload a binary operator as a member function of a class the overload is used
|
||||
* when the first operand is of the class type.For stream operators, the first operand
|
||||
* is the stream and not (usually) the custom class.
|
||||
*/
|
||||
template<typename Kernel, int Dim>
|
||||
std::ostream& operator<<(std::ostream& os, const dcm::detail::Transform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor();
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename Kernel, int Dim>
|
||||
std::ostream& operator<<(std::ostream& os, dcm::detail::DiffTransform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor() << std::endl
|
||||
<< "Differential:" << std::endl<<t.differential();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
#endif //DCM_TRANSFORMATION
|
73
src/Mod/Assembly/App/opendcm/externalize.hpp
Normal file
73
src/Mod/Assembly/App/opendcm/externalize.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EXTERNALIZE_H
|
||||
#define DCM_EXTERNALIZE_H
|
||||
|
||||
#include <boost/preprocessor/list/for_each.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/list/append.hpp>
|
||||
|
||||
#ifdef USE_EXTERNAL
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_001 <opendcm/moduleState/edge_vertex_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_001( System )\
|
||||
template struct dcm::details::edge_generator<System>; \
|
||||
template struct dcm::details::vertex_generator<System>; \
|
||||
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_002 <opendcm/moduleState/object_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_002( System )\
|
||||
template struct dcm::details::obj_gen<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_003 <opendcm/moduleState/property_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_003( System )\
|
||||
template struct dcm::details::vertex_prop_gen<System>; \
|
||||
template struct dcm::details::edge_prop_gen<System>; \
|
||||
template struct dcm::details::cluster_prop_gen<System>;
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_004 <opendcm/moduleState/generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_004( System )\
|
||||
template struct dcm::generator<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_005 <opendcm/moduleState/property_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_005( System )\
|
||||
template struct dcm::details::vertex_prop_par<System>; \
|
||||
template struct dcm::details::edge_prop_par<System>; \
|
||||
template struct dcm::details::cluster_prop_par<System>;
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_006 <opendcm/moduleState/object_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_006( System )\
|
||||
template struct dcm::details::obj_par<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_007 <opendcm/moduleState/edge_vertex_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_007( System )\
|
||||
template struct dcm::details::edge_parser<System>; \
|
||||
template struct dcm::details::vertex_parser<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_INCLUDE_008 <opendcm/moduleState/parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_008( System )\
|
||||
template struct dcm::parser<System>; \
|
||||
|
||||
#else
|
||||
#define DCM_EXTERNALIZE( System )
|
||||
#endif
|
||||
|
||||
#endif //DCM_EXTERNALIZE_H
|
||||
|
32
src/Mod/Assembly/App/opendcm/module3d.hpp
Normal file
32
src/Mod/Assembly/App/opendcm/module3d.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE3D_H
|
||||
#define DCM_MODULE3D_H
|
||||
|
||||
#define DCM_USE_MODULE3D
|
||||
|
||||
#include "module3d/geometry.hpp"
|
||||
#include "module3d/distance.hpp"
|
||||
#include "module3d/parallel.hpp"
|
||||
#include "module3d/angle.hpp"
|
||||
#include "module3d/module.hpp"
|
||||
|
||||
#endif //DCM_MODULE3D_H
|
||||
|
149
src/Mod/Assembly/App/opendcm/module3d/angle.hpp
Normal file
149
src/Mod/Assembly/App/opendcm/module3d/angle.hpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_ANGLE_HPP
|
||||
#define GCM_ANGLE_HPP
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
namespace dcm {
|
||||
|
||||
//the calculations( same as we always calculate directions we can outsource the work to this functions)
|
||||
namespace angle_detail {
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calc(T d1,
|
||||
T d2,
|
||||
typename Kernel::number_type angle) {
|
||||
|
||||
return d1.dot(d2) / (d1.norm()*d2.norm()) - angle;
|
||||
};
|
||||
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calcGradFirst(T d1,
|
||||
T d2,
|
||||
T dd1) {
|
||||
|
||||
typename Kernel::number_type norm = d1.norm()*d2.norm();
|
||||
return dd1.dot(d2)/norm - (d1.dot(d2) * (d1.dot(dd1)/d1.norm())*d2.norm()) / std::pow(norm,2);
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calcGradSecond(T d1,
|
||||
T d2,
|
||||
T dd2) {
|
||||
|
||||
typename Kernel::number_type norm = d1.norm()*d2.norm();
|
||||
return d1.dot(dd2)/norm - (d1.dot(d2) * (d2.dot(dd2)/d2.norm())*d1.norm()) / std::pow(norm,2);
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline void calcGradFirstComp(T d1,
|
||||
T d2,
|
||||
T grad) {
|
||||
|
||||
typename Kernel::number_type norm = d1.norm()*d2.norm();
|
||||
grad = d2/norm - (d1.dot(d2)/std::pow(norm,2))*d1/d1.norm();
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline void calcGradSecondComp(T d1,
|
||||
T d2,
|
||||
T grad) {
|
||||
|
||||
typename Kernel::number_type norm = d1.norm()*d2.norm();
|
||||
grad = d1/norm - (d1.dot(d2)/std::pow(norm,2))*d2/d2.norm();
|
||||
};
|
||||
|
||||
}
|
||||
/*
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct Angle3D {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
Scalar m_angle;
|
||||
|
||||
Angle3D(Scalar d = 0.) : m_angle(std::cos(d)) {};
|
||||
|
||||
//template definition
|
||||
void setScale(Scalar scale){
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
assert(false);
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Kernel >
|
||||
struct Angle3D< Kernel, tag::line3D, tag::line3D > {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
|
||||
Scalar m_angle;
|
||||
|
||||
Angle3D(Scalar d = 0.) : m_angle(std::cos(d)) {};
|
||||
|
||||
Scalar getEquationScaling(typename Kernel::Vector& local1, typename Kernel::Vector& local2) {
|
||||
return 1.;
|
||||
}
|
||||
|
||||
//template definition
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
return angle::calc<Kernel>(param1.template tail<3>(), param2.template tail<3>(), m_angle);
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
return angle::calcGradFirst<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam1.template tail<3>());
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
return angle::calcGradSecond<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam2.template tail<3>());
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
angle::calcGradFirstComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>());
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
angle::calcGradSecondComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>());
|
||||
};
|
||||
};
|
||||
|
||||
//planes like lines have the direction as segment 3-5, so we can use the same implementations
|
||||
template< typename Kernel >
|
||||
struct Angle3D< Kernel, tag::plane3D, tag::plane3D > : public Angle3D<Kernel, tag::line3D, tag::line3D> {};
|
||||
template< typename Kernel >
|
||||
struct Angle3D< Kernel, tag::line3D, tag::plane3D > : public Angle3D<Kernel, tag::line3D, tag::line3D> {};
|
||||
*/
|
||||
}
|
||||
|
||||
#endif //GCM_ANGLE_HPP
|
770
src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp
Normal file
770
src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp
Normal file
|
@ -0,0 +1,770 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_CLUSTERMATH_H
|
||||
#define GCM_CLUSTERMATH_H
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <Eigen/StdVector>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <opendcm/core/logging.hpp>
|
||||
#include "defines.hpp"
|
||||
|
||||
#define MAXFAKTOR 1.2 //the maximal distance allowd by a point normed to the cluster size
|
||||
#define MINFAKTOR 0.8 //the minimal distance allowd by a point normed to the cluster size
|
||||
#define SKALEFAKTOR 1. //the faktor by which the biggest size is multiplied to get the scale value
|
||||
#define NQFAKTOR 0.5 //the faktor by which the norm quaternion is multiplied with to get the RealScalar
|
||||
//norm quaternion to generate the unit quaternion
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
enum Scalemode {
|
||||
one,
|
||||
two,
|
||||
three,
|
||||
multiple_inrange,
|
||||
multiple_outrange
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct ClusterMath {
|
||||
|
||||
public:
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
|
||||
typedef typename module3d::Geometry3D Geometry3D;
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
typedef typename module3d::math_prop math_prop;
|
||||
typedef typename module3d::fix_prop fix_prop;
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
|
||||
typename Kernel::Transform3D m_transform, m_ssrTransform, m_resetTransform;
|
||||
typename Kernel::DiffTransform3D m_diffTrans;
|
||||
typename Kernel::Vector3Map m_normQ;
|
||||
typename Kernel::Quaternion m_resetQuaternion;
|
||||
|
||||
int m_offset;
|
||||
bool init, fix;
|
||||
std::vector<Geom> m_geometry;
|
||||
|
||||
typename Kernel::Vector3Map m_translation;
|
||||
//shift scale stuff
|
||||
typename Kernel::Vector3 midpoint, m_shift, scale_dir, maxm, minm, max, fixtrans;
|
||||
Scalemode mode;
|
||||
Scalar m_scale;
|
||||
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
Vec m_points, m_pseudo;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
#endif
|
||||
|
||||
public:
|
||||
ClusterMath();
|
||||
|
||||
void setParameterOffset(int offset);
|
||||
int getParameterOffset();
|
||||
|
||||
typename Kernel::Vector3Map& getNormQuaternionMap();
|
||||
typename Kernel::Vector3Map& getTranslationMap();
|
||||
void initMaps();
|
||||
void initFixMaps();
|
||||
|
||||
typename Kernel::Transform3D& getTransform();
|
||||
void mapsToTransform(typename Kernel::Transform3D& trans);
|
||||
void transformToMaps(typename Kernel::Transform3D& trans);
|
||||
|
||||
void finishCalculation();
|
||||
void finishFixCalculation();
|
||||
|
||||
void resetClusterRotation(typename Kernel::Transform3D& trans);
|
||||
|
||||
void calcDiffTransform(typename Kernel::DiffTransform3D& trans);
|
||||
void recalculate();
|
||||
|
||||
void addGeometry(Geom g);
|
||||
void clearGeometry();
|
||||
std::vector<Geom>& getGeometry();
|
||||
|
||||
struct map_downstream {
|
||||
|
||||
details::ClusterMath<Sys>& m_clusterMath;
|
||||
typename Kernel::Transform3D m_transform;
|
||||
bool m_isFixed;
|
||||
|
||||
map_downstream(details::ClusterMath<Sys>& cm, bool fix);
|
||||
|
||||
void operator()(Geom g);
|
||||
void operator()(boost::shared_ptr<Cluster> c);
|
||||
};
|
||||
|
||||
void mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster);
|
||||
|
||||
//Calculate the scale of the cluster. Therefore the midpoint is calculated and the scale is
|
||||
// defined as the max distance between the midpoint and the points.
|
||||
Scalar calculateClusterScale();
|
||||
|
||||
void applyClusterScale(Scalar scale, bool isFixed);
|
||||
|
||||
private:
|
||||
Scalar calcOnePoint(const typename Kernel::Vector3& p);
|
||||
|
||||
Scalar calcTwoPoints(const typename Kernel::Vector3& p1, const typename Kernel::Vector3& p2);
|
||||
|
||||
Scalar calcThreePoints(const typename Kernel::Vector3& p1,
|
||||
const typename Kernel::Vector3& p2, const typename Kernel::Vector3& p3);
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
|
||||
|
||||
m_resetTransform = typename Kernel::Quaternion(1,1,1,1);
|
||||
m_shift.setZero();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Clustermath3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::setParameterOffset(int offset) {
|
||||
m_offset = offset;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
int ClusterMath<Sys>::getParameterOffset() {
|
||||
return m_offset;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getNormQuaternionMap() {
|
||||
return m_normQ;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getTranslationMap() {
|
||||
return m_translation;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initMaps() {
|
||||
|
||||
transformToMaps(m_transform);
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=false;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initFixMaps() {
|
||||
//when fixed no maps exist
|
||||
new(&m_translation) typename Kernel::Vector3Map(&fixtrans(0));
|
||||
m_translation = m_transform.translation().vector();
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=true;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init fix transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Transform3D& ClusterMath<Sys>::getTransform() {
|
||||
return m_transform;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapsToTransform(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
//add scale only after possible reset
|
||||
typename Kernel::Transform3D::Scaling scale(m_transform.scaling());
|
||||
trans = m_diffTrans;
|
||||
trans *= scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::transformToMaps(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
const typename Kernel::Quaternion& m_quaternion = trans.rotation();
|
||||
if(m_quaternion.w() < 1.) {
|
||||
Scalar s = std::acos(m_quaternion.w())/std::sin(std::acos(m_quaternion.w()));
|
||||
m_normQ = m_quaternion.vec()*s;
|
||||
m_normQ /= NQFAKTOR;
|
||||
} else {
|
||||
m_normQ.setZero();
|
||||
}
|
||||
m_translation = trans.translation().vector();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishCalculation() {
|
||||
|
||||
mapsToTransform(m_transform);
|
||||
init=false;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
|
||||
m_transform = m_ssrTransform*m_transform;
|
||||
|
||||
//scale all geometries back to the original size
|
||||
m_diffTrans *= typename Kernel::Transform3D::Scaling(1./m_ssrTransform.scaling().factor());
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishFixCalculation() {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix calculation";
|
||||
#endif
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
m_transform *= m_ssrTransform.inverse();
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::resetClusterRotation(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Reset cluster rotation:"<<std::endl<<m_diffTrans;
|
||||
#endif
|
||||
|
||||
trans = m_resetTransform.inverse()*trans;
|
||||
m_ssrTransform *= m_resetTransform;
|
||||
m_transform = m_resetTransform.inverse()*m_transform;
|
||||
|
||||
//apply the needed transformation to all geometries local values
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->transform(m_resetTransform);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::calcDiffTransform(typename ClusterMath<Sys>::Kernel::DiffTransform3D& trans) {
|
||||
|
||||
Scalar norm = m_normQ.norm();
|
||||
trans.setIdentity();
|
||||
|
||||
if(norm < 0.1) {
|
||||
if(norm == 0) {
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
} else {
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac,m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
}
|
||||
transformToMaps(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac, m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::recalculate() {
|
||||
|
||||
|
||||
calcDiffTransform(m_diffTrans);
|
||||
|
||||
const typename Kernel::Quaternion Q = m_diffTrans.rotation();
|
||||
|
||||
// now calculate the gradient quaternions and calculate the diff rotation matrices
|
||||
// m_normQ = (a,b,c)
|
||||
// n = ||m_normQ||
|
||||
//
|
||||
// Q = (a/n sin(n), b/n sin(n), c/n sin(n), cos(n))
|
||||
//
|
||||
|
||||
//n=||m_normQ||, sn = sin(n)/n, sn3 = sin(n)/n^3, cn = cos(n)/n, divn = 1/n;
|
||||
const Scalar n = m_normQ.norm();
|
||||
const Scalar sn = std::sin(NQFAKTOR*n)/n;
|
||||
const Scalar mul = (NQFAKTOR*std::cos(NQFAKTOR*n)-sn)/std::pow(n,2);
|
||||
|
||||
//dxa = dQx/da
|
||||
const Scalar dxa = sn + std::pow(m_normQ(0),2)*mul;
|
||||
const Scalar dxb = m_normQ(0)*m_normQ(1)*mul;
|
||||
const Scalar dxc = m_normQ(0)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dya = m_normQ(1)*m_normQ(0)*mul;
|
||||
const Scalar dyb = sn + std::pow(m_normQ(1),2)*mul;
|
||||
const Scalar dyc = m_normQ(1)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dza = m_normQ(2)*m_normQ(0)*mul;
|
||||
const Scalar dzb = m_normQ(2)*m_normQ(1)*mul;
|
||||
const Scalar dzc = sn + std::pow(m_normQ(2),2)*mul;
|
||||
|
||||
const Scalar dwa = -sn*NQFAKTOR*m_normQ(0);
|
||||
const Scalar dwb = -sn*NQFAKTOR*m_normQ(1);
|
||||
const Scalar dwc = -sn*NQFAKTOR*m_normQ(2);
|
||||
|
||||
//write in the diffrot matrix, starting with dQ/dx
|
||||
m_diffTrans.at(0,0) = -4.0*(Q.y()*dya+Q.z()*dza);
|
||||
m_diffTrans.at(0,1) = -2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(0,2) = 2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(1,0) = 2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(1,1) = -4.0*(Q.x()*dxa+Q.z()*dza);
|
||||
m_diffTrans.at(1,2) = -2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,0) = -2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(2,1) = 2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,2) = -4.0*(Q.x()*dxa+Q.y()*dya);
|
||||
|
||||
//dQ/dy
|
||||
m_diffTrans.at(0,3) = -4.0*(Q.y()*dyb+Q.z()*dzb);
|
||||
m_diffTrans.at(0,4) = -2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(0,5) = 2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(1,3) = 2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(1,4) = -4.0*(Q.x()*dxb+Q.z()*dzb);
|
||||
m_diffTrans.at(1,5) = -2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,3) = -2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(2,4) = 2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,5) = -4.0*(Q.x()*dxb+Q.y()*dyb);
|
||||
|
||||
//dQ/dz
|
||||
m_diffTrans.at(0,6) = -4.0*(Q.y()*dyc+Q.z()*dzc);
|
||||
m_diffTrans.at(0,7) = -2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(0,8) = 2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(1,6) = 2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(1,7) = -4.0*(Q.x()*dxc+Q.z()*dzc);
|
||||
m_diffTrans.at(1,8) = -2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,6) = -2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(2,7) = 2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,8) = -4.0*(Q.x()*dxc+Q.y()*dyc);
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::addGeometry(Geom g) {
|
||||
m_geometry.push_back(g);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::clearGeometry() {
|
||||
m_geometry.clear();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
std::vector<typename ClusterMath<Sys>::Geom>& ClusterMath<Sys>::getGeometry() {
|
||||
return m_geometry;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::map_downstream::map_downstream(details::ClusterMath<Sys>& cm, bool fix)
|
||||
: m_clusterMath(cm), m_isFixed(fix) {
|
||||
m_transform = m_clusterMath.getTransform();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(Geom g) {
|
||||
//allow iteration over all maped geometries
|
||||
m_clusterMath.addGeometry(g);
|
||||
//set the offsets so that geometry knows where it is in the parameter map
|
||||
g->m_offset = m_clusterMath.getParameterOffset();
|
||||
//position and offset of the parameters must be set to the clusters values
|
||||
g->setClusterMode(true, m_isFixed);
|
||||
//calculate the appropriate local values
|
||||
typename Kernel::Transform3D trans = m_transform.inverse();
|
||||
g->transform(trans);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
|
||||
m_transform *= c->template getClusterProperty<math_prop>().getTransform();
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Map downstream geometry";
|
||||
#endif
|
||||
|
||||
map_downstream down(cluster->template getClusterProperty<math_prop>(),
|
||||
cluster->template getClusterProperty<fix_prop>());
|
||||
cluster->template for_each<Geometry3D>(down, true);
|
||||
//TODO: if one subcluster is fixed the hole cluster should be too, as there are no
|
||||
// dof's remaining between parts and so nothing can be moved when one part is fixed.
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calculateClusterScale() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale with transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transformation
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale sec transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
|
||||
//collect all points together
|
||||
m_points.clear();
|
||||
typename Kernel::Transform3D trans(m_transform.rotation(), m_transform.translation());
|
||||
trans.invert();
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_pseudo.begin(); it != m_pseudo.end(); it++) {
|
||||
m_points.push_back(trans*(*it));
|
||||
}
|
||||
typedef typename std::vector<Geom>::iterator g_iter;
|
||||
for(g_iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
m_points.push_back((*it)->getPoint());
|
||||
|
||||
//start scale calculation
|
||||
if(m_points.empty()) assert(false); //TODO: Throw
|
||||
else if(m_points.size() == 1) {
|
||||
const typename Kernel::Vector3 p = m_points[0];
|
||||
return calcOnePoint(p);
|
||||
} else if(m_points.size() == 2) {
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
|
||||
if(Kernel::isSame((p1-p2).norm(), 0.))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(m_points.size() == 3) {
|
||||
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
const typename Kernel::Vector3 p3 = m_points[2];
|
||||
|
||||
const typename Kernel::Vector3 d = p2-p1;
|
||||
const typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
if(Kernel::isSame(d.norm(), 0.)) {
|
||||
|
||||
if(Kernel::isSame(e.norm(), 0.))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p3);
|
||||
} else if(Kernel::isSame(e.norm(), 0.)) {
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0.) &&
|
||||
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0.)) {
|
||||
return calcThreePoints(p1, p2, p3);
|
||||
}
|
||||
//three points on a line need to be treaded as multiple points
|
||||
}
|
||||
|
||||
//more than 3 points dont have a exakt solution. we search for a midpoint from which all points
|
||||
//are at least MAXFAKTOR*scale away, but not closer than MINFAKTOR*scale
|
||||
|
||||
//get the bonding box to get the center of points
|
||||
Scalar xmin=1e10, xmax=1e-10, ymin=1e10, ymax=1e-10, zmin=1e10, zmax=1e-10;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
typename Kernel::Vector3 v = (*it);
|
||||
xmin = (v(0)<xmin) ? v(0) : xmin;
|
||||
xmax = (v(0)<xmax) ? xmax : v(0);
|
||||
ymin = (v(1)<ymin) ? v(1) : ymin;
|
||||
ymax = (v(1)<ymax) ? ymax : v(1);
|
||||
zmin = (v(2)<zmin) ? v(2) : zmin;
|
||||
zmax = (v(2)<zmax) ? zmax : v(2);
|
||||
};
|
||||
//now calculate the midpoint
|
||||
midpoint << xmin+xmax, ymin+ymax, zmin+zmax;
|
||||
midpoint /= 2.;
|
||||
|
||||
|
||||
//get the scale direction an the resulting nearest point indexes
|
||||
double xh = xmax-xmin;
|
||||
double yh = ymax-ymin;
|
||||
double zh = zmax-zmin;
|
||||
int i1, i2, i3;
|
||||
if((xh<=yh) && (xh<=zh)) {
|
||||
i1=1;
|
||||
i2=2;
|
||||
i3=0;
|
||||
} else if((yh<xh) && (yh<zh)) {
|
||||
i1=0;
|
||||
i2=2;
|
||||
i3=1;
|
||||
} else {
|
||||
i1=0;
|
||||
i2=1;
|
||||
i3=2;
|
||||
}
|
||||
scale_dir.setZero();
|
||||
scale_dir(i3) = 1;
|
||||
max = Eigen::Vector3d(xmin,ymin,zmin);
|
||||
m_scale = (midpoint-max).norm()/MAXFAKTOR;
|
||||
mode = multiple_inrange;
|
||||
|
||||
maxm = max-midpoint;
|
||||
Scalar minscale = 1e10;
|
||||
|
||||
//get the closest point
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*m_scale) {
|
||||
|
||||
const double h = std::abs(point(i3)-maxm(i3));
|
||||
const double k = std::pow(MINFAKTOR/MAXFAKTOR,2);
|
||||
double q = std::pow(point(i1),2) + std::pow(point(i2),2);
|
||||
q -= (std::pow(maxm(i1),2) + std::pow(maxm(i2),2) + std::pow(h,2))*k;
|
||||
q /= 1.-k;
|
||||
|
||||
const double p = h*k/(1.-k);
|
||||
|
||||
if(std::pow(p,2)<q) assert(false);
|
||||
|
||||
midpoint(i3) += p + std::sqrt(std::pow(p,2)-q);
|
||||
maxm = max-midpoint;
|
||||
m_scale = maxm.norm()/MAXFAKTOR;
|
||||
|
||||
mode = multiple_outrange;
|
||||
minm = (*it)-midpoint;
|
||||
|
||||
it = m_points.begin();
|
||||
} else if(point.norm()<minscale) {
|
||||
minscale = point.norm();
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==multiple_inrange) {
|
||||
//we are in the range, let's get the perfect balanced scale value
|
||||
m_scale = (minscale+maxm.norm())/2.;
|
||||
}
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::applyClusterScale(Scalar scale, bool isFixed) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Apply cluster scale: "<<scale;
|
||||
BOOST_LOG(log) << "initial transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transform
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
|
||||
|
||||
|
||||
//when fixed, the geometries never get recalculated. therefore we have to do a calculate now
|
||||
//to alow the adoption of the scale. and no shift should been set.
|
||||
if(isFixed) {
|
||||
m_transform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
m_ssrTransform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
//now calculate the scaled geometrys
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Fixed cluster geometry value:" << (*it)->m_rotated.transpose();
|
||||
#endif
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
//if this is our scale then just applie the midpoint as shift
|
||||
if(Kernel::isSame(scale, m_scale)) {
|
||||
|
||||
}
|
||||
//if only one point exists we extend the origin-point-line to match the scale
|
||||
else if(mode==details::one) {
|
||||
if(Kernel::isSame(midpoint.norm(),0))
|
||||
midpoint << scale, 0, 0;
|
||||
else midpoint += scale*scale_dir;
|
||||
}
|
||||
//two and three points form a rectangular triangle, so same procedure
|
||||
else if(mode==details::two || mode==details::three) {
|
||||
|
||||
midpoint+= scale_dir*std::sqrt(std::pow(scale,2) - std::pow(m_scale,2));
|
||||
}
|
||||
//multiple points
|
||||
else if(mode==details::multiple_outrange) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(maxm(1),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(0) += maxm(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(1) += maxm(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(2) += maxm(2) + h;
|
||||
}
|
||||
} else {
|
||||
|
||||
//TODO: it's possible that for this case we get too far away from the outer points.
|
||||
// The m_scale for "midpoint outside the bounding box" may be bigger than the
|
||||
// scale to applie, so it results in an error.
|
||||
//get the closest point
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*scale) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(point(1),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(0) += point(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(1) += point(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(2) += point(2) + h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typename Kernel::Transform3D ssTrans;
|
||||
ssTrans = typename Kernel::Transform3D::Translation(-midpoint);
|
||||
ssTrans *= typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->transform(ssTrans);
|
||||
|
||||
//set the new rotation and translation
|
||||
m_transform = ssTrans.inverse()*m_transform;
|
||||
m_ssrTransform *= ssTrans;
|
||||
|
||||
transformToMaps(m_transform);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "sstrans scale: "<<ssTrans.scaling().factor();
|
||||
BOOST_LOG(log) << "finish transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcOnePoint(const typename ClusterMath<Sys>::Kernel::Vector3& p) {
|
||||
|
||||
//one point can have every scale when moving the midpoint on the origin - point vector
|
||||
midpoint = p;
|
||||
scale_dir = -midpoint;
|
||||
scale_dir.normalize();
|
||||
mode = details::one;
|
||||
m_scale = 0.;
|
||||
return 0.;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcTwoPoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2) {
|
||||
|
||||
//two points have their minimal scale at the mid position. Scaling perpendicular to this
|
||||
//line allows arbitrary scale values. Best is to have the scale dir move towards the origin
|
||||
//as good as possible.
|
||||
midpoint = p1+(p2-p1)/2.;
|
||||
scale_dir = (p2-p1).cross(midpoint);
|
||||
scale_dir = scale_dir.cross(p2-p1);
|
||||
if(!Kernel::isSame(scale_dir.norm(),0)) scale_dir.normalize();
|
||||
else scale_dir(0) = 1;
|
||||
mode = details::two;
|
||||
m_scale = (p2-p1).norm()/2.;
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcThreePoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2, const typename ClusterMath<Sys>::Kernel::Vector3& p3) {
|
||||
|
||||
//Three points form a triangle with it's minimal scale at the center of it's outer circle.
|
||||
//Arbitrary scale values can be achieved by moving perpendicular to the triangle plane.
|
||||
typename Kernel::Vector3 d = p2-p1;
|
||||
typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
typename Kernel::Vector3 f = p1+0.5*d;
|
||||
typename Kernel::Vector3 g = p1+0.5*e;
|
||||
scale_dir = d.cross(e);
|
||||
|
||||
typename Kernel::Matrix3 m;
|
||||
m.row(0) = d.transpose();
|
||||
m.row(1) = e.transpose();
|
||||
m.row(2) = scale_dir.transpose();
|
||||
|
||||
typename Kernel::Vector3 res(d.transpose()*f, e.transpose()*g, scale_dir.transpose()*p1);
|
||||
|
||||
midpoint = m.colPivHouseholderQr().solve(res);
|
||||
scale_dir.normalize();
|
||||
mode = details::three;
|
||||
m_scale = (midpoint-p1).norm();
|
||||
|
||||
return m_scale;
|
||||
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
|
||||
#endif //GCM_CLUSTERMATH_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
33
src/Mod/Assembly/App/opendcm/module3d/defines.hpp
Normal file
33
src/Mod/Assembly/App/opendcm/module3d/defines.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_DEFINES_3D_H
|
||||
#define GCM_DEFINES_3D_H
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
enum { cluster3D = 100};
|
||||
|
||||
struct m3d {}; //base of module3d::type to allow other modules check for it
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
292
src/Mod/Assembly/App/opendcm/module3d/distance.hpp
Normal file
292
src/Mod/Assembly/App/opendcm/module3d/distance.hpp
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_DISTANCE3D_H
|
||||
#define GCM_DISTANCE3D_H
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include <opendcm/core/constraint.hpp>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::point3D, tag::point3D > {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
|
||||
Scalar value, sc_value;
|
||||
|
||||
//template definition
|
||||
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {};
|
||||
void setScale(Scalar scale) {
|
||||
sc_value = value*scale;
|
||||
};
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
return (param1-param2).norm() - sc_value;
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
return (param1-param2).dot(dparam1) / (param1-param2).norm();
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
return (param1-param2).dot(-dparam2) / (param1-param2).norm();
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient = (param1-param2) / (param1-param2).norm();
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient = (param2-param1) / (param1-param2).norm();
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::point3D, tag::plane3D > {
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
|
||||
Scalar value, sc_value;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
attrs::mutable_constant< std::string > tag;
|
||||
|
||||
type() : tag("Distance point3D plane3D") {
|
||||
log.add_attribute("Tag", tag);
|
||||
};
|
||||
#endif
|
||||
|
||||
//template definition
|
||||
void calculatePseudo(typename Kernel::Vector& param1, Vec& v1, typename Kernel::Vector& param2, Vec& v2) {
|
||||
//typename Kernel::Vector3 pp = param1.head(3)- ((param1.head(3)-param2.head(3)).dot(param2.tail(3)) / param2.tail(3).norm()*(param2.tail(3)));
|
||||
//v2.push_back(pp);
|
||||
typename Kernel::Vector3 dir = (param1.template head<3>()-param2.template head<3>()).cross(param2.template segment<3>(3));
|
||||
dir = param2.template segment<3>(3).cross(dir).normalized();
|
||||
typename Kernel::Vector3 pp = param2.head(3) + (param1.head(3)-param2.head(3)).norm()*dir;
|
||||
v2.push_back(pp);
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isnormal(pp.norm()))
|
||||
BOOST_LOG(log) << "Unnormal pseudopoint detected";
|
||||
#endif
|
||||
};
|
||||
void setScale(Scalar scale) {
|
||||
sc_value = value*scale;
|
||||
};
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
//(p1-p2)°n / |n| - distance
|
||||
const Scalar res = (param1.head(3)-param2.head(3)).dot(param2.tail(3)) / param2.tail(3).norm() - sc_value;
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal residual detected: "<<res;
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
//dp1°n / |n|
|
||||
//if(dparam1.norm()!=1) return 0;
|
||||
const Scalar res = (dparam1.head(3)).dot(param2.tail(3)) / param2.tail(3).norm();
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal first cluster gradient detected: "<<res;
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
|
||||
const typename Kernel::Vector3 p1 = param1.head(3);
|
||||
const typename Kernel::Vector3 p2 = param2.head(3);
|
||||
const typename Kernel::Vector3 dp2 = dparam2.head(3);
|
||||
const typename Kernel::Vector3 n = param2.tail(3);
|
||||
const typename Kernel::Vector3 dn = dparam2.tail(3);
|
||||
//if(dparam2.norm()!=1) return 0;
|
||||
const Scalar res = (((-dp2).dot(n) + (p1-p2).dot(dn)) / n.norm() - (p1-p2).dot(n)* n.dot(dn)/std::pow(n.norm(),3));
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal second cluster gradient detected: "<<res;
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient = param2.tail(3) / param2.tail(3).norm();
|
||||
};
|
||||
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
const typename Kernel::Vector3 p1m2 = param1.head(3) - param2.head(3);
|
||||
const typename Kernel::Vector3 n = param2.tail(3);
|
||||
|
||||
gradient.head(3) = -n / n.norm();
|
||||
gradient.tail(3) = (p1m2)/n.norm() - (p1m2).dot(n)*n/std::pow(n.norm(),3);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::plane3D, tag::plane3D > : public Distance::type< Kernel, tag::point3D, tag::plane3D > {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
type() : Distance::type< Kernel, tag::point3D, tag::plane3D >() {
|
||||
Distance::type< Kernel, tag::point3D, tag::plane3D >::tag.set("Distance plane3D plane3D");
|
||||
};
|
||||
#endif
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
|
||||
Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,g);
|
||||
g.segment(3,3).setZero();
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::point3D, tag::line3D > {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
typedef typename Kernel::Vector3 Vector3;
|
||||
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
|
||||
|
||||
Scalar value, sc_value;
|
||||
Vector3 diff, n, dist;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
attrs::mutable_constant< std::string > tag;
|
||||
|
||||
type() : tag("Distance point3D line3D") {
|
||||
log.add_attribute("Tag", tag);
|
||||
};
|
||||
#endif
|
||||
|
||||
//template definition
|
||||
void calculatePseudo(typename Kernel::Vector& point, Vec& v1, typename Kernel::Vector& line, Vec& v2) {
|
||||
Vector3 pp = line.head(3) + (line.head(3)-point.head(3)).norm()*line.segment(3,3);
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isnormal(pp.norm()))
|
||||
BOOST_LOG(log) << "Unnormal pseudopoint detected";
|
||||
#endif
|
||||
v2.push_back(pp);
|
||||
};
|
||||
void setScale(Scalar scale) {
|
||||
sc_value = value*scale;
|
||||
};
|
||||
Scalar calculate(Vector& point, Vector& line) {
|
||||
//diff = point1 - point2
|
||||
n = line.template segment<3>(3);
|
||||
diff = line.template head<3>() - point.template head<3>();
|
||||
dist = diff - diff.dot(n)*n;
|
||||
const Scalar res = dist.norm() - sc_value;
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal residual detected: "<<res;
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
Scalar calculateGradientFirst(Vector& point, Vector& line, Vector& dpoint) {
|
||||
if(dist.norm() == 0)
|
||||
return 1.;
|
||||
|
||||
const Vector3 d_diff = -dpoint.template head<3>();
|
||||
const Vector3 d_dist = d_diff - d_diff.dot(n)*n;
|
||||
const Scalar res = dist.dot(d_dist)/dist.norm();
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal first cluster gradient detected: "<<res
|
||||
<<" with point: "<<point.transpose()<<", line: "<<line.transpose()
|
||||
<<" and dpoint: "<<dpoint.transpose();
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
Scalar calculateGradientSecond(Vector& point, Vector& line, Vector& dline) {
|
||||
if(dist.norm() == 0)
|
||||
return 1.;
|
||||
|
||||
const Vector3 d_diff = dline.template head<3>();
|
||||
const Vector3 d_n = dline.template segment<3>(3);
|
||||
const Vector3 d_dist = d_diff - ((d_diff.dot(n)+diff.dot(d_n))*n + diff.dot(n)*d_n);
|
||||
const Scalar res = dist.dot(d_dist)/dist.norm();
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(res))
|
||||
BOOST_LOG(log) << "Unnormal second cluster gradient detected: "<<res
|
||||
<<" with point: "<<point.transpose()<<", line: "<<line.transpose()
|
||||
<< "and dline: "<<dline.transpose();
|
||||
#endif
|
||||
return res;
|
||||
};
|
||||
|
||||
void calculateGradientFirstComplete(Vector& point, Vector& line, Vector& gradient) {
|
||||
if(dist.norm() == 0) {
|
||||
gradient.head(3).setOnes();
|
||||
return;
|
||||
}
|
||||
|
||||
const Vector3 res = (n*n.transpose())*dist - dist;
|
||||
gradient.head(3) = res/dist.norm();
|
||||
};
|
||||
|
||||
void calculateGradientSecondComplete(Vector& point, Vector& line, Vector& gradient) {
|
||||
if(dist.norm() == 0) {
|
||||
gradient.head(6).setOnes();
|
||||
return;
|
||||
}
|
||||
|
||||
const Vector3 res = (-n*n.transpose())*dist + dist;
|
||||
gradient.head(3) = res/dist.norm();
|
||||
|
||||
const Scalar mult = n.transpose()*dist;
|
||||
gradient.template segment<3>(3) = -(mult*diff + diff.dot(n)*dist)/dist.norm();
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::line3D, tag::line3D > : public Distance::type< Kernel, tag::point3D, tag::line3D > {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
type() : Distance::type< Kernel, tag::point3D, tag::line3D >() {
|
||||
Distance::type< Kernel, tag::point3D, tag::line3D >::tag.set("Distance line3D line3D");
|
||||
};
|
||||
#endif
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
|
||||
Distance::type< Kernel, tag::point3D, tag::line3D >::calculateGradientFirstComplete(p1,p2,g);
|
||||
g.segment(3,3).setZero();
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
struct Distance::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public Distance::type< Kernel, tag::line3D, tag::line3D > {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
type() : Distance::type< Kernel, tag::line3D, tag::line3D >() {
|
||||
Distance::type< Kernel, tag::line3D, tag::line3D >::tag.set("Distance cylinder3D cylinder3D");
|
||||
};
|
||||
#endif
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) {
|
||||
Distance::type< Kernel, tag::line3D, tag::line3D >::calculateGradientFirstComplete(p1,p2,g);
|
||||
g(6) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //GCM_DISTANCE3D_H
|
133
src/Mod/Assembly/App/opendcm/module3d/dof.hpp
Normal file
133
src/Mod/Assembly/App/opendcm/module3d/dof.hpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_DOF_H
|
||||
#define GCM_DOF_H
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
enum remaining {
|
||||
nothing = 0,
|
||||
line,
|
||||
plane,
|
||||
volume
|
||||
};
|
||||
|
||||
template<typename K, typename C>
|
||||
class Dof {
|
||||
|
||||
typedef typename K::Vector3 Vec;
|
||||
typedef std::pair<Vec, C> VecID;
|
||||
|
||||
public:
|
||||
typedef std::vector<C> ConstraintVector;
|
||||
typedef std::pair<bool, ConstraintVector> Result;
|
||||
|
||||
Dof() : m_translation(volume), m_rotation(volume) {};
|
||||
|
||||
int dofTranslational() {
|
||||
return m_translation;
|
||||
};
|
||||
int dofRotational() {
|
||||
return m_rotation;
|
||||
};
|
||||
int dof() {
|
||||
return dofTranslational() + dofRotational();
|
||||
};
|
||||
|
||||
|
||||
Result removeTranslationDirection(Vec& v, C constraint) {
|
||||
|
||||
if(m_translation == nothing) {
|
||||
ConstraintVector cv;
|
||||
cv.push_back(tp1.second);
|
||||
cv.push_back(tp2.second);
|
||||
cv.push_back(tp3.second);
|
||||
return std::make_pair(false,cv);
|
||||
} else if(m_translation == volume) {
|
||||
|
||||
m_translation = plane;
|
||||
tp1 = std::make_pair(v, constraint);
|
||||
} else if(m_translation == plane) {
|
||||
|
||||
if(K::isSame(tp1.first, v) || K::isOpposite(tp1.first, v)) {
|
||||
ConstraintVector cv;
|
||||
cv.push_back(tp1.second);
|
||||
return std::make_pair(false,cv);
|
||||
}
|
||||
m_translation = line;
|
||||
tp2 = std::make_pair(v, constraint);
|
||||
} else if(m_translation == line) {
|
||||
|
||||
if(tp1.first.cross(tp2.first).dot(v) < 0.001) {
|
||||
ConstraintVector cv;
|
||||
cv.push_back(tp1.second);
|
||||
cv.push_back(tp2.second);
|
||||
return std::make_pair(false,cv);
|
||||
}
|
||||
m_translation = nothing;
|
||||
tp3 = std::make_pair(v, constraint);
|
||||
}
|
||||
|
||||
return std::make_pair(true, ConstraintVector());
|
||||
};
|
||||
|
||||
Result allowOnlyRotationDirection(Vec& v, C constraint) {
|
||||
|
||||
if(m_rotation == nothing) {
|
||||
ConstraintVector cv;
|
||||
cv.push_back(rp1.second);
|
||||
cv.push_back(rp2.second);
|
||||
return std::make_pair(false, cv);
|
||||
} else if(m_rotation == volume) {
|
||||
|
||||
m_rotation = line;
|
||||
rp1 = std::make_pair(v, constraint);
|
||||
} else if(m_rotation == plane) {
|
||||
|
||||
return std::make_pair(false, ConstraintVector()); //error as every function call removes 2 dof's
|
||||
} else if(m_rotation == line) {
|
||||
|
||||
if(K::isSame(rp1.first, v) || K::isOpposite(rp1.first, v)) {
|
||||
ConstraintVector cv;
|
||||
cv.push_back(rp1.second);
|
||||
return std::make_pair(false, cv);
|
||||
}
|
||||
m_rotation = nothing;
|
||||
rp2 = std::make_pair(v, constraint);
|
||||
}
|
||||
|
||||
return std::make_pair(true, ConstraintVector());
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
int m_translation, m_rotation;
|
||||
VecID tp1,tp2,tp3; //translation pairs
|
||||
VecID rp1, rp2; //rotation pairs
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_DOF_H
|
160
src/Mod/Assembly/App/opendcm/module3d/geometry.hpp
Normal file
160
src/Mod/Assembly/App/opendcm/module3d/geometry.hpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_GEOMETRY_3D_H
|
||||
#define GCM_GEOMETRY_3D_H
|
||||
|
||||
#include <opendcm/core/geometry.hpp>
|
||||
|
||||
namespace dcm {
|
||||
namespace tag {
|
||||
|
||||
struct point3D {
|
||||
typedef mpl::int_<3> parameters;
|
||||
typedef mpl::int_<1> rotations;
|
||||
typedef mpl::int_<1> translations;
|
||||
typedef weight::point weight;
|
||||
};
|
||||
|
||||
struct direction3D {
|
||||
typedef mpl::int_<3> parameters;
|
||||
typedef mpl::int_<1> rotations;
|
||||
typedef mpl::int_<0> translations;
|
||||
typedef weight::direction weight;
|
||||
};
|
||||
|
||||
struct line3D {
|
||||
typedef mpl::int_<6> parameters;
|
||||
typedef mpl::int_<2> rotations;
|
||||
typedef mpl::int_<1> translations;
|
||||
typedef weight::line weight;
|
||||
};
|
||||
|
||||
struct plane3D {
|
||||
typedef mpl::int_<6> parameters;
|
||||
typedef mpl::int_<2> rotations;
|
||||
typedef mpl::int_<1> translations;
|
||||
typedef weight::plane weight;
|
||||
};
|
||||
|
||||
struct cylinder3D {
|
||||
typedef mpl::int_<7> parameters;
|
||||
typedef mpl::int_<2> rotations;
|
||||
typedef mpl::int_<1> translations;
|
||||
typedef weight::cylinder weight;
|
||||
};
|
||||
}
|
||||
|
||||
namespace modell {
|
||||
|
||||
struct XYZ {
|
||||
/*Modell XYZ:
|
||||
* 0 = X;
|
||||
* 1 = Y;
|
||||
* 2 = Z;
|
||||
*/
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void extract(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
v(0) = a.template get<Scalar, 0>(t);
|
||||
v(1) = a.template get<Scalar, 1>(t);
|
||||
v(2) = a.template get<Scalar, 2>(t);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void inject(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
a.template set<Scalar, 0>(v(0), t);
|
||||
a.template set<Scalar, 1>(v(1), t);
|
||||
a.template set<Scalar, 2>(v(2), t);
|
||||
};
|
||||
};
|
||||
|
||||
struct XYZ2 {
|
||||
/*Modell XYZ2: two xyz parts after each other
|
||||
* 0 = X;
|
||||
* 1 = Y;
|
||||
* 2 = Z;
|
||||
* 3 = X dir;
|
||||
* 4 = Y dir;
|
||||
* 5 = Z dir;
|
||||
*/
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void extract(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
v(0) = a.template get<Scalar, 0>(t);
|
||||
v(1) = a.template get<Scalar, 1>(t);
|
||||
v(2) = a.template get<Scalar, 2>(t);
|
||||
v(3) = a.template get<Scalar, 3>(t);
|
||||
v(4) = a.template get<Scalar, 4>(t);
|
||||
v(5) = a.template get<Scalar, 5>(t);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void inject(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
a.template set<Scalar, 0>(v(0), t);
|
||||
a.template set<Scalar, 1>(v(1), t);
|
||||
a.template set<Scalar, 2>(v(2), t);
|
||||
a.template set<Scalar, 3>(v(3), t);
|
||||
a.template set<Scalar, 4>(v(4), t);
|
||||
a.template set<Scalar, 5>(v(5), t);
|
||||
};
|
||||
};
|
||||
|
||||
struct XYZ2P {
|
||||
/*Modell XYZ2P: two xyz parts after each other and one parameter
|
||||
* 0 = X;
|
||||
* 1 = Y;
|
||||
* 2 = Z;
|
||||
* 3 = X dir;
|
||||
* 4 = Y dir;
|
||||
* 5 = Z dir;
|
||||
* 6 = Parameter
|
||||
*/
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void extract(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
v(0) = a.template get<Scalar, 0>(t);
|
||||
v(1) = a.template get<Scalar, 1>(t);
|
||||
v(2) = a.template get<Scalar, 2>(t);
|
||||
v(3) = a.template get<Scalar, 3>(t);
|
||||
v(4) = a.template get<Scalar, 4>(t);
|
||||
v(5) = a.template get<Scalar, 5>(t);
|
||||
v(6) = a.template get<Scalar, 6>(t);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Accessor, typename Vector, typename Type>
|
||||
void inject(Type& t, Vector& v) {
|
||||
Accessor a;
|
||||
a.template set<Scalar, 0>(v(0), t);
|
||||
a.template set<Scalar, 1>(v(1), t);
|
||||
a.template set<Scalar, 2>(v(2), t);
|
||||
a.template set<Scalar, 3>(v(3), t);
|
||||
a.template set<Scalar, 4>(v(4), t);
|
||||
a.template set<Scalar, 5>(v(5), t);
|
||||
a.template set<Scalar, 6>(v(6), t);
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_GEOMETRY_3D_H
|
546
src/Mod/Assembly/App/opendcm/module3d/module.hpp
Normal file
546
src/Mod/Assembly/App/opendcm/module3d/module.hpp
Normal file
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_MODULE_3D_H
|
||||
#define GCM_MODULE_3D_H
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "opendcm/core.hpp"
|
||||
#include "opendcm/core/object.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "opendcm/core/sheduler.hpp"
|
||||
#include "opendcm/core/traits.hpp"
|
||||
#include "opendcm/core/geometry.hpp"
|
||||
#include "geometry.hpp"
|
||||
#include "distance.hpp"
|
||||
#include "parallel.hpp"
|
||||
#include "angle.hpp"
|
||||
#include "solver.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "clustermath.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename seq, typename t>
|
||||
struct distance {
|
||||
typedef typename mpl::find<seq, t>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<seq>::type, iterator>::type type;
|
||||
BOOST_MPL_ASSERT((mpl::not_< boost::is_same<iterator, typename mpl::end<seq>::type > >));
|
||||
};
|
||||
}
|
||||
}//dcm
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Typelist, typename ID = No_Identifier>
|
||||
struct Module3D {
|
||||
|
||||
template<typename Sys>
|
||||
struct type : details::m3d {
|
||||
struct Constraint3D;
|
||||
struct Geometry3D;
|
||||
struct vertex_prop;
|
||||
struct inheriter_base;
|
||||
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
typedef boost::shared_ptr<Constraint3D> Cons;
|
||||
|
||||
typedef mpl::map1< mpl::pair<remove, boost::function<void (Cons) > > > ConsSignal;
|
||||
|
||||
typedef ID Identifier;
|
||||
|
||||
typedef details::MES<Sys> MES;
|
||||
typedef details::SystemSolver<Sys> SystemSolver;
|
||||
|
||||
template<typename Derived>
|
||||
class Geometry3D_id : public detail::Geometry<Sys, Derived, Typelist, 3> {
|
||||
|
||||
typedef detail::Geometry<Sys, Derived, Typelist, 3> Base;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
attrs::mutable_constant< std::string > log_id;
|
||||
#endif
|
||||
public:
|
||||
template<typename T>
|
||||
Geometry3D_id(T geometry, Sys& system);
|
||||
|
||||
template<typename T>
|
||||
void set(T geometry, Identifier id);
|
||||
//somehow the base class set funtion is not found
|
||||
template<typename T>
|
||||
void set(T geometry);
|
||||
|
||||
Identifier& getIdentifier();
|
||||
void setIdentifier(Identifier id);
|
||||
};
|
||||
|
||||
struct Geometry3D : public mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
detail::Geometry<Sys, Geometry3D, Typelist, 3>, Geometry3D_id<Geometry3D> >::type {
|
||||
|
||||
typedef vertex_prop vertex_propertie;
|
||||
|
||||
template<typename T>
|
||||
Geometry3D(T geometry, Sys& system);
|
||||
|
||||
//allow accessing the internals by module3d classes but not by users
|
||||
friend struct details::ClusterMath<Sys>;
|
||||
friend struct details::ClusterMath<Sys>::map_downstream;
|
||||
friend struct details::SystemSolver<Sys>;
|
||||
friend struct details::SystemSolver<Sys>::Rescaler;
|
||||
friend class detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>;
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
class Constraint3D_id : public detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D> {
|
||||
|
||||
typedef detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D> base;
|
||||
public:
|
||||
Constraint3D_id(Sys& system, Geom f, Geom s);
|
||||
|
||||
Identifier& getIdentifier();
|
||||
void setIdentifier(Identifier id);
|
||||
};
|
||||
|
||||
struct Constraint3D : public mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>,
|
||||
Constraint3D_id<Constraint3D> >::type {
|
||||
|
||||
Constraint3D(Sys& system, Geom first, Geom second);
|
||||
|
||||
friend struct details::SystemSolver<Sys>;
|
||||
friend struct details::SystemSolver<Sys>::Rescaler;
|
||||
friend struct details::MES<Sys>;
|
||||
friend struct inheriter_base;
|
||||
};
|
||||
|
||||
struct inheriter_base {
|
||||
|
||||
inheriter_base();
|
||||
|
||||
template<typename T>
|
||||
Geom createGeometry3D(T geom);
|
||||
void removeGeometry3D(Geom g);
|
||||
|
||||
template<typename T1>
|
||||
Cons createConstraint3D(Geom first, Geom second, T1 constraint1);
|
||||
void removeConstraint3D(Cons c);
|
||||
|
||||
protected:
|
||||
Sys* m_this;
|
||||
void apply_edge_remove(GlobalEdge e);
|
||||
};
|
||||
|
||||
struct inheriter_id : public inheriter_base {
|
||||
|
||||
protected:
|
||||
using inheriter_base::m_this;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
Geom createGeometry3D(T geom, Identifier id);
|
||||
template<typename T>
|
||||
Cons createConstraint3D(Identifier id, Geom first, Geom second, T constraint1);
|
||||
|
||||
void removeGeometry3D(Identifier id);
|
||||
void removeConstraint3D(Identifier id);
|
||||
|
||||
bool hasGeometry3D(Identifier id);
|
||||
Geom getGeometry3D(Identifier id);
|
||||
bool hasConstraint3D(Identifier id);
|
||||
Cons getConstraint3D(Identifier id);
|
||||
};
|
||||
|
||||
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
|
||||
|
||||
struct math_prop {
|
||||
typedef cluster_property kind;
|
||||
typedef details::ClusterMath<Sys> type;
|
||||
};
|
||||
struct fix_prop {
|
||||
typedef cluster_property kind;
|
||||
typedef bool type;
|
||||
};
|
||||
struct vertex_prop {
|
||||
typedef Geometry3D kind;
|
||||
typedef GlobalVertex type;
|
||||
};
|
||||
struct edge_prop {
|
||||
typedef Constraint3D kind;
|
||||
typedef GlobalEdge type;
|
||||
};
|
||||
|
||||
typedef mpl::vector4<vertex_prop, edge_prop, math_prop, fix_prop> properties;
|
||||
typedef mpl::vector<Geometry3D, Constraint3D> objects;
|
||||
|
||||
static void system_init(Sys& sys) {
|
||||
sys.m_sheduler.addProcessJob(new SystemSolver());
|
||||
};
|
||||
static void system_copy(const Sys& from, Sys& into) {
|
||||
//nothing to to as all objects and properties are copyed with the clustergraph
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
namespace details {
|
||||
//allow direct access to the stored geometry in a Geometry3D, copyed from boost variant get
|
||||
template <typename T>
|
||||
struct get_visitor {
|
||||
private:
|
||||
|
||||
typedef typename boost::add_pointer<T>::type pointer;
|
||||
typedef typename boost::add_reference<T>::type reference;
|
||||
|
||||
public:
|
||||
|
||||
typedef pointer result_type;
|
||||
|
||||
public:
|
||||
pointer operator()(reference operand) const {
|
||||
return boost::addressof(operand);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
pointer operator()(const U&) const {
|
||||
return static_cast<pointer>(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename G>
|
||||
typename boost::add_reference<T>::type get(G geom) {
|
||||
|
||||
typedef typename boost::add_pointer<T>::type T_ptr;
|
||||
details::get_visitor<T> v;
|
||||
T_ptr result = geom->apply(v);
|
||||
|
||||
//if (!result)
|
||||
//TODO:throw bad_get();
|
||||
return *result;
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(T geometry, Sys& system)
|
||||
: detail::Geometry<Sys, Derived, Typelist, 3>(geometry, system)
|
||||
#ifdef USE_LOGGING
|
||||
, log_id("No ID")
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
Base::log.add_attribute("ID", log_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(T geometry, Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(T geometry) {
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
#ifdef USE_LOGGING
|
||||
std::stringstream str;
|
||||
str<<this->template getProperty<id_prop<Identifier> >();
|
||||
log_id.set(str.str());
|
||||
BOOST_LOG(Base::log)<<"Identifyer set: "<<id;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(T geometry, Sys& system)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
detail::Geometry<Sys, Geometry3D, Typelist, 3>,
|
||||
Geometry3D_id<Geometry3D> >::type(geometry, system) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::Constraint3D_id(Sys& system, Geom f, Geom s)
|
||||
: detail::Constraint<Sys, Derived, ConsSignal, MES, Geometry3D>(system, f, s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D::Constraint3D(Sys& system, Geom first, Geom second)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
detail::Constraint<Sys, Constraint3D, ConsSignal, MES, Geometry3D>,
|
||||
Constraint3D_id<Constraint3D> >::type(system, first, second) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
|
||||
m_this = ((Sys*) this);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D(T geom) {
|
||||
|
||||
Geom g(new Geometry3D(geom, * ((Sys*) this)));
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
|
||||
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
|
||||
m_this->push_back(g);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeGeometry3D(Geom g) {
|
||||
|
||||
GlobalVertex v = g->template getProperty<vertex_prop>();
|
||||
|
||||
//check if this vertex holds a constraint
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(v);
|
||||
if(c)
|
||||
c->template emitSignal<remove>(c);
|
||||
|
||||
//emit remove geometry signal bevore actually deleting it, in case anyone want to access the
|
||||
//graph before
|
||||
g->template emitSignal<remove>(g);
|
||||
|
||||
//remove the vertex from graph and emit all edges that get removed with the functor
|
||||
boost::function<void(GlobalEdge)> functor = boost::bind(&inheriter_base::apply_edge_remove, this, _1);
|
||||
m_this->m_cluster->removeVertex(v, functor);
|
||||
m_this->erase(g);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T1>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createConstraint3D(Geom first, Geom second, T1 constraint1) {
|
||||
|
||||
//build a constraint vector
|
||||
typedef mpl::vector<> cvec;
|
||||
typedef typename mpl::if_< mpl::is_sequence<T1>,
|
||||
typename mpl::fold< T1, cvec, mpl::push_back<mpl::_1,mpl::_2> >::type,
|
||||
mpl::vector1<T1> >::type cvec1;
|
||||
|
||||
//make a fusion sequence to hold the objects (as they hold the options)
|
||||
typedef typename fusion::result_of::as_vector<cvec1>::type covec;
|
||||
//set the objects
|
||||
covec cv;
|
||||
fusion::at_c<0>(cv) = constraint1;
|
||||
|
||||
//now create the constraint
|
||||
Cons c(new Constraint3D(*m_this, first, second));
|
||||
//set the type and values
|
||||
c->template initialize<cvec1>(cv);
|
||||
|
||||
//add it to the clustergraph
|
||||
fusion::vector<LocalEdge, GlobalEdge, bool, bool> res;
|
||||
res = m_this->m_cluster->addEdge(first->template getProperty<vertex_prop>(),
|
||||
second->template getProperty<vertex_prop>());
|
||||
if(!fusion::at_c<2>(res)) {
|
||||
Cons rc;
|
||||
return rc; //TODO: throw
|
||||
};
|
||||
m_this->m_cluster->template setObject<Constraint3D> (fusion::at_c<1> (res), c);
|
||||
//add the coresbondig edge to the constraint
|
||||
c->template setProperty<edge_prop>(fusion::at_c<1>(res));
|
||||
//store the constraint in general object vector of main system
|
||||
m_this->push_back(c);
|
||||
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeConstraint3D(Cons c) {
|
||||
|
||||
GlobalEdge e = c->template getProperty<edge_prop>();
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->m_cluster->removeEdge(e);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::apply_edge_remove(GlobalEdge e) {
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(e);
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(T geom, Identifier id) {
|
||||
Geom g = inheriter_base::createGeometry3D(geom);
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeGeometry3D(Identifier id) {
|
||||
|
||||
if(hasGeometry3D(id))
|
||||
inheriter_base::removeGeometry3D(getGeometry3D(id));
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createConstraint3D(Identifier id, Geom first, Geom second, T constraint1) {
|
||||
|
||||
Cons c = inheriter_base::createConstraint3D(first, second, constraint1);
|
||||
c->setIdentifier(id);
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeConstraint3D(Identifier id) {
|
||||
|
||||
if(hasConstraint3D(id))
|
||||
removeConstraint3D(getConstraint3D(id));
|
||||
};
|
||||
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasGeometry3D(Identifier id) {
|
||||
if(getGeometry3D(id)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getGeometry3D(Identifier id) {
|
||||
std::vector< Geom >& vec = inheriter_base::m_this->template objectVector<Geometry3D>();
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
|
||||
};
|
||||
return Geom();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasConstraint3D(Identifier id) {
|
||||
if(getConstraint3D(id)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getConstraint3D(Identifier id) {
|
||||
std::vector< Cons >& vec = inheriter_base::m_this->template objectVector<Constraint3D>();
|
||||
typedef typename std::vector<Cons>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
|
||||
};
|
||||
return Cons();
|
||||
};
|
||||
|
||||
}//dcm
|
||||
|
||||
#endif //GCM_GEOMETRY3D_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
215
src/Mod/Assembly/App/opendcm/module3d/parallel.hpp
Normal file
215
src/Mod/Assembly/App/opendcm/module3d/parallel.hpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_PARALLEL_H
|
||||
#define GCM_PARALLEL_H
|
||||
|
||||
#include <opendcm/core/constraint.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
|
||||
using boost::math::isnormal;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
//the calculations( same as we always calculate directions we can outsource the work to this functions)
|
||||
namespace parallel_detail {
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calc(T d1,
|
||||
T d2,
|
||||
Direction dir) {
|
||||
|
||||
switch(dir) {
|
||||
case Same:
|
||||
return (d1-d2).norm();
|
||||
case Opposite:
|
||||
return (d1+d2).norm();
|
||||
case Both:
|
||||
if(d1.dot(d2) >= 0) {
|
||||
return (d1-d2).norm();
|
||||
}
|
||||
return (d1+d2).norm();
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calcGradFirst(T d1,
|
||||
T d2,
|
||||
T dd1,
|
||||
Direction dir) {
|
||||
|
||||
typename Kernel::number_type res;
|
||||
switch(dir) {
|
||||
case Same:
|
||||
res = ((d1-d2).dot(dd1) / (d1-d2).norm());
|
||||
break;
|
||||
case Opposite:
|
||||
res= ((d1+d2).dot(dd1) / (d1+d2).norm());
|
||||
break;
|
||||
case Both:
|
||||
if(d1.dot(d2) >= 0) {
|
||||
res = (((d1-d2).dot(dd1) / (d1-d2).norm()));
|
||||
break;
|
||||
}
|
||||
res = (((d1+d2).dot(dd1) / (d1+d2).norm()));
|
||||
break;
|
||||
}
|
||||
if((isnormal)(res)) return res;
|
||||
return 0;
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline typename Kernel::number_type calcGradSecond(T d1,
|
||||
T d2,
|
||||
T dd2,
|
||||
Direction dir) {
|
||||
|
||||
typename Kernel::number_type res;
|
||||
switch(dir) {
|
||||
case Same:
|
||||
res = ((d1-d2).dot(-dd2) / (d1-d2).norm());
|
||||
break;
|
||||
case Opposite:
|
||||
res = ((d1+d2).dot(dd2) / (d1+d2).norm());
|
||||
break;
|
||||
case Both:
|
||||
if(d1.dot(d2) >= 0) {
|
||||
res = (((d1-d2).dot(-dd2) / (d1-d2).norm()));
|
||||
break;
|
||||
}
|
||||
res = (((d1+d2).dot(dd2) / (d1+d2).norm()));
|
||||
break;
|
||||
}
|
||||
if((isnormal)(res)) return res;
|
||||
return 0;
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline void calcGradFirstComp(T d1,
|
||||
T d2,
|
||||
T grad,
|
||||
Direction dir) {
|
||||
|
||||
switch(dir) {
|
||||
case Same:
|
||||
grad = (d1-d2) / (d1-d2).norm();
|
||||
return;
|
||||
case Opposite:
|
||||
grad = (d1+d2) / (d1+d2).norm();
|
||||
return;
|
||||
case Both:
|
||||
assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, typename T>
|
||||
inline void calcGradSecondComp(T d1,
|
||||
T d2,
|
||||
T grad,
|
||||
Direction dir) {
|
||||
|
||||
switch(dir) {
|
||||
case Same:
|
||||
grad = (d2-d1) / (d1-d2).norm();
|
||||
return;
|
||||
case Opposite:
|
||||
grad = (d2+d1) / (d1+d2).norm();
|
||||
return;
|
||||
case Both:
|
||||
assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template< typename Kernel >
|
||||
struct Parallel::type< Kernel, tag::line3D, tag::line3D > : public dcm::PseudoScale<Kernel> {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
|
||||
Direction value;
|
||||
|
||||
//template definition
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
return parallel_detail::calc<Kernel>(param1.template tail<3>(), param2.template tail<3>(), value);
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
return parallel_detail::calcGradFirst<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam1.template tail<3>(), value);
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
return parallel_detail::calcGradSecond<Kernel>(param1.template tail<3>(), param2.template tail<3>(), dparam2.template tail<3>(), value);
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
parallel_detail::calcGradFirstComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>(), value);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
parallel_detail::calcGradSecondComp<Kernel>(param1.template tail<3>(), param2.template tail<3>(), gradient.template tail<3>(), value);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Kernel >
|
||||
struct Parallel::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::PseudoScale<Kernel>{
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::VectorMap Vector;
|
||||
|
||||
Direction value;
|
||||
|
||||
Scalar calculate(Vector& param1, Vector& param2) {
|
||||
return parallel_detail::calc<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3), value);
|
||||
};
|
||||
Scalar calculateGradientFirst(Vector& param1, Vector& param2, Vector& dparam1) {
|
||||
return parallel_detail::calcGradFirst<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
|
||||
dparam1.template segment<3>(3), value);
|
||||
|
||||
};
|
||||
Scalar calculateGradientSecond(Vector& param1, Vector& param2, Vector& dparam2) {
|
||||
return parallel_detail::calcGradSecond<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
|
||||
dparam2.template segment<3>(3), value);
|
||||
};
|
||||
void calculateGradientFirstComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
parallel_detail::calcGradFirstComp<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
|
||||
gradient.template segment<3>(3), value);
|
||||
};
|
||||
void calculateGradientSecondComplete(Vector& param1, Vector& param2, Vector& gradient) {
|
||||
gradient.template head<3>().setZero();
|
||||
parallel_detail::calcGradSecondComp<Kernel>(param1.template segment<3>(3), param2.template segment<3>(3),
|
||||
gradient.template segment<3>(3), value);
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Kernel >
|
||||
struct Parallel::type< Kernel, tag::line3D, tag::plane3D > : public Parallel::type<Kernel, tag::line3D, tag::line3D> {};
|
||||
|
||||
template< typename Kernel >
|
||||
struct Parallel::type< Kernel, tag::plane3D, tag::plane3D > : public Parallel::type<Kernel, tag::line3D, tag::line3D> {};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_ANGLE
|
367
src/Mod/Assembly/App/opendcm/module3d/solver.hpp
Normal file
367
src/Mod/Assembly/App/opendcm/module3d/solver.hpp
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_SOLVER_3D_H
|
||||
#define GCM_SOLVER_3D_H
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "clustermath.hpp"
|
||||
#include "opendcm/core/sheduler.hpp"
|
||||
#include "opendcm/core/traits.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
struct MES : public system_traits<Sys>::Kernel::MappedEquationSystem {
|
||||
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
|
||||
typedef typename module3d::Geometry3D Geometry3D;
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
typedef typename module3d::Constraint3D Constraint3D;
|
||||
typedef boost::shared_ptr<Constraint3D> Cons;
|
||||
typedef typename module3d::math_prop math_prop;
|
||||
typedef typename module3d::fix_prop fix_prop;
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename system_traits<Sys>::Kernel::MappedEquationSystem Base;
|
||||
|
||||
boost::shared_ptr<Cluster> m_cluster;
|
||||
|
||||
MES(boost::shared_ptr<Cluster> cl, int par, int eqn);
|
||||
virtual void recalculate();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct SystemSolver : public Job<Sys> {
|
||||
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename system_traits<Sys>::template getModule<m3d>::type module3d;
|
||||
typedef typename module3d::Geometry3D Geometry3D;
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
typedef typename module3d::Constraint3D Constraint3D;
|
||||
typedef boost::shared_ptr<Constraint3D> Cons;
|
||||
typedef typename module3d::math_prop math_prop;
|
||||
typedef typename module3d::fix_prop fix_prop;
|
||||
typedef typename module3d::vertex_prop vertex_prop;
|
||||
|
||||
typedef MES<Sys> Mes;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
#endif
|
||||
struct Rescaler {
|
||||
|
||||
boost::shared_ptr<Cluster> cluster;
|
||||
Mes& mes;
|
||||
int rescales;
|
||||
|
||||
Rescaler(boost::shared_ptr<Cluster> c, Mes& m);
|
||||
|
||||
void operator()();
|
||||
|
||||
Scalar scaleClusters();
|
||||
void collectPseudoPoints(boost::shared_ptr<Cluster> parent,
|
||||
LocalVertex cluster,
|
||||
std::vector<typename Kernel::Vector3,
|
||||
Eigen::aligned_allocator<typename Kernel::Vector3> >& vec);
|
||||
};
|
||||
|
||||
SystemSolver();
|
||||
virtual void execute(Sys& sys);
|
||||
void solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys);
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
MES<Sys>::MES(boost::shared_ptr<Cluster> cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void MES<Sys>::recalculate() {
|
||||
|
||||
//first calculate all clusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = m_cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
if(!(*cit.first).second->template getClusterProperty<fix_prop>())
|
||||
(*cit.first).second->template getClusterProperty<math_prop>().recalculate();
|
||||
|
||||
};
|
||||
|
||||
//with everything updated just nicely we can compute the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
|
||||
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
|
||||
for(; eit.first != eit.second; eit.first++) {
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
if(*oit.first)
|
||||
(*oit.first)->calculate(Base::Scaling);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::Rescaler::Rescaler(boost::shared_ptr<Cluster> c, Mes& m) : cluster(c), mes(m), rescales(0) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::operator()() {
|
||||
mes.Scaling = scaleClusters();
|
||||
rescales++;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename SystemSolver<Sys>::Scalar SystemSolver<Sys>::Rescaler::scaleClusters() {
|
||||
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
//get the maximal scale
|
||||
Scalar sc = 0;
|
||||
for(cit = cluster->clusters(); cit.first != cit.second; cit.first++) {
|
||||
//fixed cluster are irrelevant for scaling
|
||||
if((*cit.first).second->template getClusterProperty<fix_prop>()) continue;
|
||||
|
||||
//get the biggest scale factor
|
||||
details::ClusterMath<Sys>& math = (*cit.first).second->template getClusterProperty<math_prop>();
|
||||
|
||||
//math.m_pseudo.clear();
|
||||
//collectPseudoPoints(cluster, (*cit.first).first, math.m_pseudo);
|
||||
|
||||
const Scalar s = math.calculateClusterScale();
|
||||
sc = (s>sc) ? s : sc;
|
||||
}
|
||||
//if no scaling-value returned we can use 1
|
||||
sc = (Kernel::isSame(sc,0)) ? 1. : sc;
|
||||
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
c->template getClusterProperty<math_prop>().applyClusterScale(sc,
|
||||
c->template getClusterProperty<fix_prop>());
|
||||
} else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(sc*SKALEFAKTOR);
|
||||
}
|
||||
}
|
||||
return 1./(sc*SKALEFAKTOR);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::collectPseudoPoints(
|
||||
boost::shared_ptr<typename SystemSolver<Sys>::Cluster> parent,
|
||||
LocalVertex cluster,
|
||||
std::vector<typename SystemSolver<Sys>::Kernel::Vector3,
|
||||
Eigen::aligned_allocator<typename SystemSolver<Sys>::Kernel::Vector3> >& vec) {
|
||||
|
||||
std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > vec2;
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> c_iter;
|
||||
typedef typename boost::graph_traits<Cluster>::out_edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> it = boost::out_edges(cluster, *parent);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
std::pair< c_iter, c_iter > cit = parent->template getObjects<Constraint3D>(*it.first);
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
Cons c = *(cit.first);
|
||||
|
||||
if(!c)
|
||||
continue;
|
||||
|
||||
//get the first global vertex and see if we have it in the wanted cluster or not
|
||||
GlobalVertex v = c->first->template getProperty<vertex_prop>();
|
||||
std::pair<LocalVertex,bool> res = parent->getLocalVertex(v);
|
||||
if(!res.second)
|
||||
return; //means the geometry is in non of the clusters which is not allowed
|
||||
|
||||
if(res.first == cluster)
|
||||
c->collectPseudoPoints(vec, vec2);
|
||||
else
|
||||
c->collectPseudoPoints(vec2, vec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::SystemSolver() {
|
||||
Job<Sys>::priority = 1000;
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("SystemSolver3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::execute(Sys& sys) {
|
||||
solveCluster(sys.m_cluster, sys);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys) {
|
||||
|
||||
//set out and solve all relevant subclusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
boost::shared_ptr<Cluster> c = (*cit.first).second;
|
||||
if(c->template getClusterProperty<changed_prop>() &&
|
||||
c->template getClusterProperty<type_prop>() == details::cluster3D)
|
||||
solveCluster(c, sys);
|
||||
}
|
||||
|
||||
int params=0, constraints=0;
|
||||
typename Kernel::number_type scale = 1;
|
||||
|
||||
//get the ammount of parameters and constraint equations we need
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
//when cluster and not fixed it has trans and rot parameter
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first)) {
|
||||
params += 6;
|
||||
}
|
||||
} else {
|
||||
params += cluster->template getObject<Geometry3D>(*it.first)->m_parameterCount;
|
||||
};
|
||||
}
|
||||
|
||||
//count the equations in the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> ocit;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
std::pair< ocit, ocit > it = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; it.first != it.second; it.first++)
|
||||
constraints += (*it.first)->equationCount();
|
||||
};
|
||||
|
||||
|
||||
//initialise the system with now known size
|
||||
//std::cout<<"constraints: "<<constraints<<", params: "<<params+rot_params+trans_params<<std::endl;
|
||||
Mes mes(cluster, params, constraints);
|
||||
|
||||
//iterate all geometrys again and set the needed maps
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
details::ClusterMath<Sys>& cm = c->template getClusterProperty<math_prop>();
|
||||
//only get maps and propagate downstream if not fixed
|
||||
if(!c->template getClusterProperty<fix_prop>()) {
|
||||
//set norm Quaternion as map to the parameter vector
|
||||
int offset = mes.setParameterMap(cm.getNormQuaternionMap());
|
||||
//set translation as map to the parameter vector
|
||||
mes.setParameterMap(cm.getTranslationMap());
|
||||
//write initail values to the parameter maps
|
||||
//remember the parameter offset as all downstream geometry must use this offset
|
||||
cm.setParameterOffset(offset);
|
||||
//wirte initial values
|
||||
cm.initMaps();
|
||||
} else cm.initFixMaps();
|
||||
|
||||
//map all geometrie within that cluster to it's rotation matrix
|
||||
//for collecting all geometries which need updates
|
||||
cm.clearGeometry();
|
||||
cm.mapClusterDownstreamGeometry(c);
|
||||
|
||||
} else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
int offset = mes.setParameterMap(g->m_parameterCount, g->getParameterMap());
|
||||
g->m_offset = offset;
|
||||
//init the parametermap with initial values
|
||||
g->initMap();
|
||||
}
|
||||
}
|
||||
|
||||
//and now the constraints to set the residual and gradient maps
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
|
||||
//set the maps
|
||||
Cons c = *oit.first;
|
||||
if(c) c->setMaps(mes);
|
||||
//TODO: else throw (as every global edge was counted as one equation)
|
||||
}
|
||||
}
|
||||
|
||||
int stop = 0;
|
||||
Rescaler re(cluster, mes);
|
||||
re();
|
||||
stop = Kernel::solve(mes, re);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
|
||||
#endif
|
||||
|
||||
//now go to all relevant geometries and clusters and write the values back
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first))
|
||||
c->template getClusterProperty<math_prop>().finishCalculation();
|
||||
else
|
||||
c->template getClusterProperty<math_prop>().finishFixCalculation();
|
||||
|
||||
std::vector<Geom>& vec = c->template getClusterProperty<math_prop>().getGeometry();
|
||||
for(typename std::vector<Geom>::iterator vit = vec.begin(); vit != vec.end(); vit++)
|
||||
(*vit)->finishCalculation();
|
||||
|
||||
} else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(mes.Scaling);
|
||||
g->finishCalculation();
|
||||
}
|
||||
}
|
||||
//we have solved this cluster
|
||||
cluster->template setClusterProperty<changed_prop>(false);
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_SOLVER_3D_HPP
|
95
src/Mod/Assembly/App/opendcm/module3d/state.hpp
Normal file
95
src/Mod/Assembly/App/opendcm/module3d/state.hpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE3D_STATE_HPP
|
||||
#define DCM_MODULE3D_STATE_HPP
|
||||
|
||||
#include "module.hpp"
|
||||
#include "opendcm/moduleState/traits.hpp"
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace ascii = boost::spirit::karma::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
struct geom_visitor : public boost::static_visitor<int> {
|
||||
|
||||
template<typename T>
|
||||
int operator()(T& i) const {
|
||||
return geometry_traits<T>::tag::weight::value;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int getWeight(boost::shared_ptr<T> ptr) {
|
||||
return boost::apply_visitor(geom_visitor(), ptr->m_geometry);
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
void getStdVector(typename Kernel::Vector& eigen, std::vector<typename Kernel::number_type>& vec) {
|
||||
vec.resize(eigen.size());
|
||||
for(int i=0; i<eigen.size(); i++)
|
||||
vec[i] = eigen(i);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate< typename Module3D::type<System>::Geometry3D, System>
|
||||
: public mpl::true_{};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator< typename Module3D::type<System>::Geometry3D, System, iterator > {
|
||||
|
||||
typedef typename Sys::Kernel Kernel;
|
||||
typedef typename typename Module3D::type<System>::Geometry3D Geometry;
|
||||
typedef karma::rule<iterator, boost::shared_ptr<Geometry>() > generator;
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>Geometry3D</type>\n<class>")
|
||||
<< ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
|
||||
<< "</class>\n<value>"
|
||||
<< (karma::double_ % " ")[phx::bind(&details::getStdVector<Kernel>, )]
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename Module3D::type<System>::Geometry3D, System>
|
||||
: public mpl::true_{};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename Module3D::type<System>::Geometry3D, System, iterator > {
|
||||
|
||||
typedef typename Module3D::type<System>::Geometry3D object_type;
|
||||
|
||||
typedef qi::rule<iterator, boost::shared_ptr<object_type>(System*), qi::space_type> parser;
|
||||
static void init(parser& r) {
|
||||
r = qi::lexeme[qi::lit("<type>object 1 prop</type>")[ qi::_val =
|
||||
phx::construct<boost::shared_ptr<object_type> >( phx::new_<object_type>(*qi::_r1))]] >> ("<value>HaHAHAHAHA</value>");
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //DCM_MODULE3D_STATE_HPP
|
92
src/Mod/Assembly/App/opendcm/modulePart/geometry.hpp
Normal file
92
src/Mod/Assembly/App/opendcm/modulePart/geometry.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_GEOMETRY_PART_H
|
||||
#define GCM_GEOMETRY_PART_H
|
||||
|
||||
#include <opendcm/core/geometry.hpp>
|
||||
#include <opendcm/core/kernel.hpp>
|
||||
|
||||
namespace dcm {
|
||||
namespace tag {
|
||||
|
||||
struct part {};
|
||||
|
||||
}
|
||||
|
||||
namespace modell {
|
||||
|
||||
struct quaternion_wxyz_vec3 {
|
||||
/*Modell XYZ:
|
||||
* 0 = w;
|
||||
* 1 = x;
|
||||
* 2 = y;
|
||||
* 3 = z;
|
||||
*/
|
||||
template<typename Kernel, typename Accessor, typename Type>
|
||||
void extract(Type& t, typename Kernel::Transform3D& trans) {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::Transform3D::Rotation Rotation;
|
||||
typedef typename Kernel::Transform3D::Translation Translation;
|
||||
|
||||
Accessor a;
|
||||
Rotation r;
|
||||
r.w() = a.template get<Scalar, 0>(t);
|
||||
r.x() = a.template get<Scalar, 1>(t);
|
||||
r.y() = a.template get<Scalar, 2>(t);
|
||||
r.z() = a.template get<Scalar, 3>(t);
|
||||
|
||||
Translation tr;;
|
||||
tr.vector()(0) = a.template get<Scalar, 4>(t);
|
||||
tr.vector()(1) = a.template get<Scalar, 5>(t);
|
||||
tr.vector()(2) = a.template get<Scalar, 6>(t);
|
||||
|
||||
trans = r;
|
||||
trans *= tr;
|
||||
}
|
||||
|
||||
template<typename Kernel, typename Accessor, typename Type>
|
||||
void inject(Type& t, typename Kernel::Transform3D& trans) {
|
||||
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::Transform3D::Rotation Rotation;
|
||||
typedef typename Kernel::Transform3D::Translation Translation;
|
||||
|
||||
Accessor a;
|
||||
|
||||
const Rotation& r = trans.rotation();
|
||||
a.template set<Scalar, 0>(r.w(), t);
|
||||
a.template set<Scalar, 1>(r.x(), t);
|
||||
a.template set<Scalar, 2>(r.y(), t);
|
||||
a.template set<Scalar, 3>(r.z(), t);
|
||||
|
||||
const Translation& tr = trans.translation();
|
||||
a.template set<Scalar, 4>(tr.vector()(0), t);
|
||||
a.template set<Scalar, 5>(tr.vector()(1), t);
|
||||
a.template set<Scalar, 6>(tr.vector()(2), t);
|
||||
|
||||
a.finalize(t);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_GEOMETRY_PART_H
|
558
src/Mod/Assembly/App/opendcm/modulePart/module.hpp
Normal file
558
src/Mod/Assembly/App/opendcm/modulePart/module.hpp
Normal file
|
@ -0,0 +1,558 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_MODULE_PART_H
|
||||
#define GCM_MODULE_PART_H
|
||||
|
||||
#include "opendcm/core.hpp"
|
||||
#include "opendcm/core/traits.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "opendcm/core/property.hpp"
|
||||
#include "opendcm/module3d.hpp"
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
enum { clusterPart = 110};
|
||||
|
||||
enum CoordinateFrame {Local, Global};
|
||||
|
||||
template<typename Typelist, typename ID = No_Identifier>
|
||||
struct ModulePart {
|
||||
|
||||
template<typename Sys>
|
||||
struct type {
|
||||
|
||||
|
||||
struct Part;
|
||||
struct PrepareCluster;
|
||||
struct EvaljuateCluster;
|
||||
typedef boost::shared_ptr<Part> Partptr;
|
||||
typedef mpl::map2< mpl::pair<remove, boost::function<void (Partptr) > >,
|
||||
mpl::pair<recalculated, boost::function<void (Partptr) > > > PartSignal;
|
||||
|
||||
typedef ID Identifier;
|
||||
|
||||
class Part_base : public Object<Sys, Part, PartSignal > {
|
||||
protected:
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
#endif
|
||||
|
||||
//check if we have module3d in this system
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<module3d, mpl::void_> >));
|
||||
|
||||
//define what we need
|
||||
typedef typename module3d::Geometry3D Geometry3D;
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
|
||||
typedef typename boost::make_variant_over< Typelist >::type Variant;
|
||||
typedef Object<Sys, Part, PartSignal> base;
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename Kernel::number_type Scalar;
|
||||
typedef typename Kernel::Transform3D Transform;
|
||||
|
||||
struct cloner : boost::static_visitor<void> {
|
||||
|
||||
Variant variant;
|
||||
cloner(Variant& v) : variant(v) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(T& t) {
|
||||
variant = geometry_clone_traits<T>()(t);
|
||||
};
|
||||
};
|
||||
|
||||
//visitor to write the calculated value into the variant
|
||||
struct apply_visitor : public boost::static_visitor<void> {
|
||||
|
||||
apply_visitor(Transform& t) : m_transform(t) {};
|
||||
|
||||
template <typename T>
|
||||
void operator()(T& t) const {
|
||||
(typename geometry_traits<T>::modell()).template inject<Kernel,
|
||||
typename geometry_traits<T>::accessor >(t, m_transform);
|
||||
}
|
||||
Transform& m_transform;
|
||||
};
|
||||
|
||||
public:
|
||||
using Object<Sys, Part, PartSignal >::m_system;
|
||||
|
||||
template<typename T>
|
||||
Part_base(T geometry, Sys& system, boost::shared_ptr<Cluster> cluster);
|
||||
|
||||
template<typename Visitor>
|
||||
typename Visitor::result_type apply(Visitor& vis);
|
||||
|
||||
template<typename T>
|
||||
Geom addGeometry3D(T geom, CoordinateFrame frame = Global);
|
||||
|
||||
template<typename T>
|
||||
void set(T geometry);
|
||||
|
||||
virtual boost::shared_ptr<Part> clone(Sys& newSys);
|
||||
|
||||
public:
|
||||
Variant m_geometry;
|
||||
Transform m_transform;
|
||||
boost::shared_ptr<Cluster> m_cluster;
|
||||
|
||||
void finishCalculation();
|
||||
void fix(bool fix_value);
|
||||
};
|
||||
|
||||
struct Part_id : public Part_base {
|
||||
|
||||
template<typename T>
|
||||
Part_id(T geometry, Sys& system, boost::shared_ptr<typename Part_base::Cluster> cluster);
|
||||
|
||||
template<typename T>
|
||||
typename Part_base::Geom addGeometry3D(T geom, Identifier id, CoordinateFrame frame = Global);
|
||||
|
||||
template<typename T>
|
||||
void set(T geometry, Identifier id);
|
||||
|
||||
bool hasGeometry3D(Identifier id);
|
||||
typename Part_base::Geom getGeometry3D(Identifier id);
|
||||
|
||||
Identifier& getIdentifier();
|
||||
void setIdentifier(Identifier id);
|
||||
};
|
||||
|
||||
struct Part : public mpl::if_<boost::is_same<Identifier, No_Identifier>, Part_base, Part_id>::type {
|
||||
|
||||
typedef typename mpl::if_<boost::is_same<Identifier, No_Identifier>, Part_base, Part_id>::type base;
|
||||
|
||||
template<typename T>
|
||||
Part(T geometry, Sys& system, boost::shared_ptr<typename base::Cluster> cluster);
|
||||
|
||||
friend struct PrepareCluster;
|
||||
friend struct EvaljuateCluster;
|
||||
};
|
||||
|
||||
|
||||
struct inheriter_base {
|
||||
|
||||
inheriter_base();
|
||||
|
||||
template<typename T>
|
||||
Partptr createPart(T geometry);
|
||||
void removePart(Partptr p);
|
||||
|
||||
template<typename T>
|
||||
void setTransformation(T geom) {
|
||||
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
details::ClusterMath<Sys>& cm = ((Sys*)this)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
|
||||
|
||||
(typename geometry_traits<T>::modell()).template extract<typename Sys::Kernel,
|
||||
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T getTransformation() {
|
||||
|
||||
T geom;
|
||||
getTransformation(geom);
|
||||
return geom;
|
||||
};
|
||||
template<typename T>
|
||||
void getTransformation(T& geom) {
|
||||
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
details::ClusterMath<Sys>& cm = ((Sys*)this)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
|
||||
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Sys::Kernel,
|
||||
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
|
||||
};
|
||||
|
||||
protected:
|
||||
Sys* m_this;
|
||||
|
||||
//function object to emit remove signal too al geometry which is deleted by part deletion
|
||||
struct remover {
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
typedef typename module3d::Geometry3D Geometry3D;
|
||||
typedef boost::shared_ptr<Geometry3D> Geom;
|
||||
typedef typename module3d::Constraint3D Constraint3D;
|
||||
typedef boost::shared_ptr<Constraint3D> Cons;
|
||||
|
||||
Sys& system;
|
||||
remover(Sys& s);
|
||||
//see if we have a geometry or a constraint and emit the remove signal
|
||||
void operator()(GlobalVertex v);
|
||||
//we delete all global edges connecting to this part
|
||||
void operator()(GlobalEdge e);
|
||||
void operator()(boost::shared_ptr<Cluster> g) {};
|
||||
};
|
||||
};
|
||||
|
||||
struct inheriter_id : public inheriter_base {
|
||||
|
||||
template<typename T>
|
||||
Partptr createPart(T geometry, Identifier id);
|
||||
bool hasPart(Identifier id);
|
||||
Partptr getPart(Identifier id);
|
||||
};
|
||||
|
||||
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
|
||||
|
||||
typedef mpl::vector0<> properties;
|
||||
typedef mpl::vector1<Part> objects;
|
||||
|
||||
struct PrepareCluster : public Job<Sys> {
|
||||
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
|
||||
PrepareCluster();
|
||||
virtual void execute(Sys& sys);
|
||||
};
|
||||
|
||||
struct EvaljuateCluster : public Job<Sys> {
|
||||
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
typedef typename system_traits<Sys>::Kernel Kernel;
|
||||
typedef typename system_traits<Sys>::template getModule<details::m3d>::type module3d;
|
||||
|
||||
EvaljuateCluster();
|
||||
virtual void execute(Sys& sys);
|
||||
};
|
||||
|
||||
static void system_init(Sys& sys) {
|
||||
sys.m_sheduler.addPreprocessJob(new PrepareCluster());
|
||||
sys.m_sheduler.addPostprocessJob(new EvaljuateCluster());
|
||||
};
|
||||
static void system_copy(const Sys& from, Sys& into) {};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_base::Part_base(T geometry, Sys& system, boost::shared_ptr<Cluster> cluster)
|
||||
: Object<Sys, Part, PartSignal>(system), m_geometry(geometry), m_cluster(cluster) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Part3D"));
|
||||
#endif
|
||||
|
||||
(typename geometry_traits<T>::modell()).template extract<Kernel,
|
||||
typename geometry_traits<T>::accessor >(geometry, m_transform);
|
||||
|
||||
cluster->template setClusterProperty<typename module3d::fix_prop>(false);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Visitor>
|
||||
typename Visitor::result_type ModulePart<Typelist, ID>::type<Sys>::Part_base::apply(Visitor& vis) {
|
||||
return boost::apply_visitor(vis, m_geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_base::addGeometry3D(T geom, CoordinateFrame frame) {
|
||||
Geom g(new Geometry3D(geom, *m_system));
|
||||
if(frame == Local)
|
||||
g->transform(m_transform);
|
||||
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_cluster->addVertex();
|
||||
m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<typename module3d::vertex_prop>(fusion::at_c<1>(res));
|
||||
m_system->template objectVector<Geometry3D>().push_back(g);
|
||||
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::Part_base::set(T geometry) {
|
||||
Part_base::m_geometry = geometry;
|
||||
(typename geometry_traits<T>::modell()).template extract<Kernel,
|
||||
typename geometry_traits<T>::accessor >(geometry, Part_base::m_transform);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
boost::shared_ptr<typename ModulePart<Typelist, ID>::template type<Sys>::Part>
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_base::clone(Sys& newSys) {
|
||||
|
||||
//we need to reset the cluster pointer to the new system cluster
|
||||
LocalVertex lv = Object<Sys, Part, PartSignal>::m_system->m_cluster->getClusterVertex(m_cluster);
|
||||
GlobalVertex gv = Object<Sys, Part, PartSignal>::m_system->m_cluster->getGlobalVertex(lv);
|
||||
|
||||
boost::shared_ptr<Part> np = Object<Sys, Part, PartSignal>::clone(newSys);
|
||||
//there may be pointer inside the variant
|
||||
cloner clone_fnc(np->m_geometry);
|
||||
boost::apply_visitor(clone_fnc, m_geometry);
|
||||
|
||||
fusion::vector<LocalVertex, boost::shared_ptr<Cluster>, bool> res = newSys.m_cluster->getLocalVertexGraph(gv);
|
||||
if(!fusion::at_c<2>(res)) {
|
||||
//todo: throw
|
||||
return np;
|
||||
}
|
||||
np->m_cluster = fusion::at_c<1>(res)->getVertexCluster(fusion::at_c<0>(res));
|
||||
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::Part_base::finishCalculation() {
|
||||
|
||||
m_transform.normalize();
|
||||
apply_visitor vis(m_transform);
|
||||
apply(vis);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "New Value: "<<m_transform;
|
||||
#endif
|
||||
|
||||
//emit the signal for new values
|
||||
base::template emitSignal<recalculated>(((Part*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::Part_base::fix(bool fix_value) {
|
||||
m_cluster->template setClusterProperty<typename module3d::fix_prop>(fix_value);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_id::Part_id(T geometry, Sys& system, boost::shared_ptr<typename Part_base::Cluster> cluster)
|
||||
: Part_base(geometry, system, cluster) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_id::addGeometry3D(T geom, Identifier id, CoordinateFrame frame) {
|
||||
|
||||
typename Part_base::Geom g = Part_base::addGeometry3D(geom, frame);
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::Part_id::set(T geometry, Identifier id) {
|
||||
Part_base::set(geometry);
|
||||
setIdentifier(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool ModulePart<Typelist, ID>::type<Sys>::Part_id::hasGeometry3D(Identifier id) {
|
||||
typename Part_base::Geom g = Part_base::m_system->getGeometry3D(id);
|
||||
if(!g) return false;
|
||||
|
||||
//get the global vertex and check if it is a child of the part cluster
|
||||
GlobalVertex v = g->template getProperty<typename Part_base::module3d::vertex_prop>();
|
||||
return Part_base::m_cluster->getLocalVertex(v).second;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_id::getGeometry3D(Identifier id) {
|
||||
return Part_base::m_system->getGeometry3D(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Identifier&
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_id::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::Part_id::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part::Part(T geometry, Sys& system, boost::shared_ptr<typename base::Cluster> cluster)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Part_base, Part_id>::type(geometry, system, cluster) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
|
||||
m_this = ((Sys*) this);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::createPart(T geometry) {
|
||||
|
||||
typedef typename system_traits<Sys>::Cluster Cluster;
|
||||
std::pair<boost::shared_ptr<Cluster>, LocalVertex> res = m_this->m_cluster->createCluster();
|
||||
Partptr p(new Part(geometry, * ((Sys*) this), res.first));
|
||||
|
||||
m_this->m_cluster->template setObject<Part> (res.second, p);
|
||||
m_this->push_back(p);
|
||||
|
||||
res.first->template setClusterProperty<type_prop>(clusterPart);
|
||||
return p;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::removePart(Partptr p) {
|
||||
|
||||
remover r(*m_this);
|
||||
m_this->m_cluster->removeCluster(p->m_cluster, r);
|
||||
p->template emitSignal<remove>(p);
|
||||
m_this->erase(p);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::remover(Sys& s) : system(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalVertex v) {
|
||||
Geom g = system.m_cluster->template getObject<Geometry3D>(v);
|
||||
if(g) {
|
||||
g->template emitSignal<remove>(g);
|
||||
system.erase(g);
|
||||
}
|
||||
Cons c = system.m_cluster->template getObject<Constraint3D>(v);
|
||||
if(c) {
|
||||
c->template emitSignal<remove>(c);
|
||||
system.erase(c);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalEdge e) {
|
||||
Cons c = system.m_cluster->template getObject<Constraint3D>(e);
|
||||
if(c) {
|
||||
c->template emitSignal<remove>(c);
|
||||
system.erase(c);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_id::createPart(T geometry, Identifier id) {
|
||||
Partptr p = inheriter_base::createPart(geometry);
|
||||
p->setIdentifier(id);
|
||||
return p;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool ModulePart<Typelist, ID>::type<Sys>::inheriter_id::hasPart(Identifier id) {
|
||||
if(getPart(id)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_id::getPart(Identifier id) {
|
||||
std::vector< Partptr >& vec = inheriter_base::m_this->template objectVector<Part>();
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id)) return *it;
|
||||
};
|
||||
return Partptr();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
ModulePart<Typelist, ID>::type<Sys>::PrepareCluster::PrepareCluster() {
|
||||
Job<Sys>::priority = 1000;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::PrepareCluster::execute(Sys& sys) {
|
||||
//get all parts and set their values to the cluster's
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
|
||||
|
||||
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
|
||||
cm.getTransform() = (*it)->m_transform;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
ModulePart<Typelist, ID>::type<Sys>::EvaljuateCluster::EvaljuateCluster() {
|
||||
Job<Sys>::priority = 1000;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::EvaljuateCluster::execute(Sys& sys) {
|
||||
//get all parts and set their values to the cluster's
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
|
||||
|
||||
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getClusterProperty<typename module3d::math_prop>();
|
||||
(*it)->m_transform = cm.getTransform();
|
||||
(*it)->finishCalculation();
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_MODULEPART_H
|
||||
|
||||
|
||||
|
||||
|
36
src/Mod/Assembly/App/opendcm/moduleState/defines.hpp
Normal file
36
src/Mod/Assembly/App/opendcm/moduleState/defines.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_DEFINES_STATE_H
|
||||
#define DCM_DEFINES_STATE_H
|
||||
|
||||
#include "opendcm/core/property.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
struct cluster_vertex_prop {
|
||||
typedef GlobalVertex type;
|
||||
typedef cluster_property kind;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_GENERATOR_H
|
||||
#define DCM_EDGE_GENERATOR_H
|
||||
|
||||
#include "property_generator.hpp"
|
||||
#include "object_generator.hpp"
|
||||
#include "extractor.hpp"
|
||||
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/fusion/support/is_sequence.hpp>
|
||||
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_generator : karma::grammar<Iterator, std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >()> {
|
||||
|
||||
edge_generator();
|
||||
|
||||
karma::rule<Iterator, std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >()> edge_range;
|
||||
karma::rule<Iterator, fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex>()> edge;
|
||||
karma::rule<Iterator, std::vector<typename Sys::Cluster::edge_bundle_single>&()> globaledge_range;
|
||||
karma::rule<Iterator, typename Sys::Cluster::edge_bundle_single()> globaledge;
|
||||
details::edge_prop_gen<Sys> edge_prop;
|
||||
details::obj_gen<Sys> objects;
|
||||
Extractor<Sys> ex;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_generator : karma::grammar<Iterator, std::vector<typename Sys::Cluster::vertex_bundle>()> {
|
||||
|
||||
vertex_generator();
|
||||
|
||||
karma::rule<Iterator, std::vector<typename Sys::Cluster::vertex_bundle>()> vertex_range;
|
||||
karma::rule<Iterator, typename Sys::Cluster::vertex_bundle()> vertex;
|
||||
details::vertex_prop_gen<Sys> vertex_prop;
|
||||
details::obj_gen<Sys> objects;
|
||||
Extractor<Sys> ex;
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "edge_vertex_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_GENERATOR_IMP_H
|
||||
#define DCM_EDGE_GENERATOR_IMP_H
|
||||
|
||||
#include "edge_vertex_generator.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
edge_generator<Sys>::edge_generator() : edge_generator<Sys>::base_type(edge_range) {
|
||||
|
||||
globaledge = karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeID, ex, karma::_val, karma::_1)]
|
||||
<< " source=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeSource, ex, karma::_val, karma::_1)]
|
||||
<< " target=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeTarget, ex, karma::_val, karma::_1)] << '>'
|
||||
<< "+" << objects[karma::_1 = phx::at_c<0>(karma::_val)] << "-\n" ;
|
||||
|
||||
|
||||
globaledge_range = *(karma::lit("<GlobalEdge id=")<<globaledge<<karma::lit("</GlobalEdge>"));
|
||||
|
||||
edge = karma::lit("source=")<<karma::int_[karma::_1 = phx::at_c<1>(karma::_val)] << " target="<<karma::int_[karma::_1 = phx::at_c<2>(karma::_val)] << ">+"
|
||||
<< edge_prop[karma::_1 = phx::at_c<0>(phx::at_c<0>(karma::_val))]
|
||||
<< karma::eol << globaledge_range[karma::_1 = phx::at_c<1>(phx::at_c<0>(karma::_val))] << '-' << karma::eol;
|
||||
|
||||
edge_range = (karma::lit("<Edge ") << edge << karma::lit("</Edge>")) % karma::eol;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_generator<Sys>::vertex_generator() : vertex_generator<Sys>::base_type(vertex_range) {
|
||||
|
||||
vertex = karma::int_ << ">+" << vertex_prop << objects << "-\n";
|
||||
|
||||
vertex_range = '\n' << (karma::lit("<Vertex id=") << vertex << karma::lit("</Vertex>")) % karma::eol;
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_VERTEX_PARSER_H
|
||||
#define DCM_EDGE_VERTEX_PARSER_H
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "extractor.hpp"
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_parser : qi::grammar< IIterator, fusion::vector<LocalEdge, GlobalEdge, bool, bool>(typename Sys::Cluster*, Sys*),
|
||||
qi::space_type > {
|
||||
|
||||
edge_parser();
|
||||
details::obj_par<Sys> objects;
|
||||
Injector<Sys> in;
|
||||
|
||||
qi::rule<IIterator, fusion::vector<LocalEdge, GlobalEdge, bool, bool>(typename Sys::Cluster*, Sys*), qi::space_type> edge;
|
||||
qi::rule<IIterator, typename Sys::Cluster::edge_bundle_single(Sys*), qi::space_type> global_edge;
|
||||
details::edge_prop_par<Sys> edge_prop;
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_parser : qi::grammar< IIterator, fusion::vector<LocalVertex, GlobalVertex>(typename Sys::Cluster*, Sys*),
|
||||
qi::space_type> {
|
||||
|
||||
vertex_parser();
|
||||
|
||||
details::obj_par<Sys> objects;
|
||||
Injector<Sys> in;
|
||||
|
||||
qi::rule<IIterator, fusion::vector<LocalVertex, GlobalVertex>(typename Sys::Cluster*, Sys*), qi::space_type> vertex;
|
||||
details::vertex_prop_par<Sys> prop;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//#ifndef USE_EXTERNAL
|
||||
//#include "edge_vertex_parser_imp.hpp"
|
||||
//#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_PARSER_IMP_H
|
||||
#define DCM_EDGE_PARSER_IMP_H
|
||||
|
||||
#include "edge_vertex_parser.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
edge_parser<Sys>::edge_parser() : edge_parser<Sys>::base_type(edge) {
|
||||
|
||||
global_edge = qi::lit("<GlobalEdge") >> qi::lit("id=") >> qi::int_[phx::bind(&GlobalEdge::ID, phx::at_c<1>(qi::_val)) = qi::_1]
|
||||
>> qi::lit("source=") >> qi::int_[phx::bind(&GlobalEdge::source, phx::at_c<1>(qi::_val)) = qi::_1]
|
||||
>> qi::lit("target=") >> qi::int_[phx::bind(&GlobalEdge::target, phx::at_c<1>(qi::_val)) = qi::_1] >> '>'
|
||||
>> objects(qi::_r1)[phx::at_c<0>(qi::_val) = qi::_1] >> "</GlobalEdge>";
|
||||
|
||||
edge = (qi::lit("<Edge") >> "source=" >> qi::int_ >> "target=" >> qi::int_ >> '>')[qi::_val = phx::bind((&Sys::Cluster::addEdgeGlobal), qi::_r1, qi::_1, qi::_2)]
|
||||
>> edge_prop[phx::bind(&Injector<Sys>::setEdgeProperties, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> *global_edge(qi::_r2)
|
||||
>> ("</Edge>");
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_parser<Sys>::vertex_parser() : vertex_parser<Sys>::base_type(vertex) {
|
||||
|
||||
vertex = qi::lit("<Vertex")[phx::bind(&Injector<Sys>::addVertex, in, qi::_r1, qi::_val)] >> qi::lit("id=")
|
||||
>> qi::int_[phx::at_c<1>(qi::_val) = phx::bind(&Sys::Cluster::setGlobalVertex, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> '>' >> prop[phx::bind(&Injector<Sys>::setVertexProperties, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> objects(qi::_r2)[phx::bind(&Injector<Sys>::setVertexObjects, in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> ("</Vertex>");
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif
|
119
src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp
Normal file
119
src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EXTRACTOR_H
|
||||
#define DCM_EXTRACTOR_H
|
||||
|
||||
#include "defines.hpp"
|
||||
#include <opendcm/core/clustergraph.hpp>
|
||||
#include <boost/fusion/include/at_c.hpp>
|
||||
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
template<typename Sys>
|
||||
struct Extractor {
|
||||
|
||||
typedef typename boost::graph_traits<typename Sys::Cluster>::vertex_iterator viter;
|
||||
typedef typename boost::graph_traits<typename Sys::Cluster>::edge_iterator eiter;
|
||||
|
||||
void getVertexRange(typename Sys::Cluster& cluster, std::vector<typename Sys::Cluster::vertex_bundle>& range) {
|
||||
std::pair<viter, viter> res = boost::vertices(cluster);
|
||||
for(; res.first != res.second; res.first++)
|
||||
range.push_back(cluster[*res.first]);
|
||||
};
|
||||
void getEdgeRange(typename Sys::Cluster& cluster,
|
||||
std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >& range) {
|
||||
|
||||
std::pair<eiter, eiter> res = boost::edges(cluster);
|
||||
for(; res.first != res.second; res.first++)
|
||||
range.push_back(fusion::make_vector(cluster[*res.first],
|
||||
cluster.getGlobalVertex(boost::source(*res.first, cluster)),
|
||||
cluster.getGlobalVertex(boost::target(*res.first, cluster))));
|
||||
|
||||
};
|
||||
void getGlobalEdgeSource(typename Sys::Cluster::edge_bundle_single b, int& source) {
|
||||
source = fusion::at_c<1>(b).source;
|
||||
};
|
||||
void getGlobalEdgeTarget(typename Sys::Cluster::edge_bundle_single b, int& target) {
|
||||
target = fusion::at_c<1>(b).target;
|
||||
};
|
||||
void getGlobalEdgeID(typename Sys::Cluster::edge_bundle_single b, int& id) {
|
||||
id = fusion::at_c<1>(b).ID;
|
||||
};
|
||||
void setVertexID(typename Sys::Cluster* cluster, LocalVertex v, long& l) {
|
||||
if(v)
|
||||
l = cluster->getGlobalVertex(v);
|
||||
else
|
||||
l = 0;
|
||||
};
|
||||
void getClusterRange(typename Sys::Cluster& cluster, std::vector<std::pair<GlobalVertex, typename Sys::Cluster*> >& range) {
|
||||
|
||||
typedef typename Sys::Cluster::const_cluster_iterator iter;
|
||||
|
||||
for(iter it = cluster.m_clusters.begin(); it != cluster.m_clusters.end(); it++) {
|
||||
range.push_back( std::make_pair( cluster.getGlobalVertex((*it).first), (*it).second.get() ));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct Injector {
|
||||
|
||||
void setClusterProperties(typename Sys::Cluster* cluster,
|
||||
typename details::pts<typename Sys::Cluster::cluster_properties>::type& prop) {
|
||||
cluster->m_cluster_bundle = prop;
|
||||
};
|
||||
void setVertexProperties(typename Sys::Cluster* cluster, LocalVertex v,
|
||||
typename details::pts<typename Sys::vertex_properties>::type& prop) {
|
||||
fusion::at_c<1>(cluster->operator[](v)) = prop;
|
||||
};
|
||||
void setVertexObjects(typename Sys::Cluster* cluster, LocalVertex v,
|
||||
typename details::sps<typename Sys::objects>::type& obj) {
|
||||
fusion::at_c<2>(cluster->operator[](v)) = obj;
|
||||
};
|
||||
|
||||
void setEdgeProperties(typename Sys::Cluster* cluster, LocalEdge e,
|
||||
typename details::pts<typename Sys::edge_properties>::type& prop) {
|
||||
fusion::at_c<0>(cluster->operator[](e)) = prop;
|
||||
};
|
||||
void setVertexProperty(typename Sys::Cluster* cluster, int value) {
|
||||
cluster->template setClusterProperty<details::cluster_vertex_prop>(value);
|
||||
};
|
||||
void addCluster(typename Sys::Cluster* cluster, typename Sys::Cluster* addcl) {
|
||||
LocalVertex v = cluster->getLocalVertex(addcl->template getClusterProperty<details::cluster_vertex_prop>()).first;
|
||||
cluster->m_clusters[v] = boost::shared_ptr<typename Sys::Cluster>(addcl);
|
||||
};
|
||||
void addVertex(typename Sys::Cluster* cluster, fusion::vector<LocalVertex, GlobalVertex>& vec) {
|
||||
vec = cluster->addVertex();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //DCM_GENERATOR_H
|
||||
|
||||
|
||||
|
||||
|
82
src/Mod/Assembly/App/opendcm/moduleState/generator.hpp
Normal file
82
src/Mod/Assembly/App/opendcm/moduleState/generator.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_GENERATOR_H
|
||||
#define DCM_GENERATOR_H
|
||||
|
||||
#include "property_generator.hpp"
|
||||
#include "edge_vertex_generator.hpp"
|
||||
#include "extractor.hpp"
|
||||
|
||||
#include <opendcm/core/clustergraph.hpp>
|
||||
|
||||
#include "traits.hpp"
|
||||
#include "traits_impl.hpp"
|
||||
#include "indent.hpp"
|
||||
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/fusion/container/vector/convert.hpp>
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/at_c.hpp>
|
||||
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace phx = boost::phoenix;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
template<typename Sys>
|
||||
struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
|
||||
|
||||
typedef typename Sys::Cluster graph;
|
||||
typedef typename graph::cluster_bundle graph_bundle;
|
||||
typedef typename boost::graph_traits<graph>::vertex_iterator viter;
|
||||
typedef typename boost::graph_traits<graph>::edge_iterator eiter;
|
||||
|
||||
generator();
|
||||
|
||||
karma::rule<Iterator, graph& ()> start;
|
||||
|
||||
karma::rule<Iterator, std::pair<GlobalVertex, graph*>()> cluster_pair;
|
||||
karma::rule<Iterator, graph&()> cluster;
|
||||
details::cluster_prop_gen<Sys> cluster_prop;
|
||||
|
||||
details::vertex_generator<Sys> vertex_range;
|
||||
details::edge_generator<Sys> edge_range;
|
||||
|
||||
Extractor<Sys> ex;
|
||||
};
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_GENERATOR_H
|
||||
|
||||
|
||||
|
72
src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp
Normal file
72
src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_GENERATOR_IMP_H
|
||||
#define DCM_GENERATOR_IMP_H
|
||||
|
||||
#include "generator.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
//#include "karma_trans.hpp"
|
||||
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
|
||||
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||
(T1)(T2)(T3)(T4),
|
||||
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
|
||||
(int, test)
|
||||
(typename dcm::details::pts<T3>::type, m_cluster_bundle))
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
struct transform_attribute<dcm::ClusterGraph<T1,T2,T3,T4>* const, dcm::ClusterGraph<T1,T2,T3,T4>&, karma::domain>
|
||||
{
|
||||
typedef dcm::ClusterGraph<T1,T2,T3,T4>& type;
|
||||
static type pre(dcm::ClusterGraph<T1,T2,T3,T4>* const& val) {
|
||||
return *val;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Sys>
|
||||
generator<Sys>::generator() : generator<Sys>::base_type(start) {
|
||||
|
||||
cluster %= karma::omit[karma::int_] << cluster_prop << -vertex_range[phx::bind(&Extractor<Sys>::getVertexRange, ex, karma::_val, karma::_1)]
|
||||
<< -karma::buffer["\n" << edge_range[phx::bind(&Extractor<Sys>::getEdgeRange, ex, karma::_val, karma::_1)]]
|
||||
<< -karma::buffer["\n" << (cluster_pair % karma::eol)[phx::bind(&Extractor<Sys>::getClusterRange, ex, karma::_val, karma::_1)]] << "-\n"
|
||||
<< "</Cluster>";
|
||||
|
||||
cluster_pair %= karma::lit("<Cluster id=") << karma::int_ << ">+"
|
||||
<< karma::attr_cast<graph*,graph&>(cluster);
|
||||
|
||||
start %= karma::lit("<Cluster id=0>+") << cluster;
|
||||
};
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //DCM_GENERATOR_H
|
||||
|
||||
|
||||
|
63
src/Mod/Assembly/App/opendcm/moduleState/indent.hpp
Normal file
63
src/Mod/Assembly/App/opendcm/moduleState/indent.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_INDENT_H
|
||||
#define DCM_INDENT_H
|
||||
|
||||
#include <boost/iostreams/concepts.hpp>
|
||||
#include <boost/iostreams/operations.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
|
||||
class indent_filter : public boost::iostreams::output_filter {
|
||||
public:
|
||||
explicit indent_filter() : indent(0) {};
|
||||
|
||||
template<typename Sink>
|
||||
bool put(Sink& dest, int c) {
|
||||
|
||||
if(c == '+') {
|
||||
indent++;
|
||||
return true;
|
||||
} else if(c == '-') {
|
||||
indent--;
|
||||
return true;
|
||||
} else if(c == '\n') {
|
||||
bool ret = boost::iostreams::put(dest, c);
|
||||
for(int i=0; (i<indent) && ret; i++) {
|
||||
ret = boost::iostreams::put(dest, ' ');
|
||||
ret = boost::iostreams::put(dest, ' ');
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
indent = (indent < 0) ? 0 : indent;
|
||||
|
||||
return boost::iostreams::put(dest, c);
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
void close(Source&) {
|
||||
indent = 0;
|
||||
}
|
||||
private:
|
||||
int indent;
|
||||
};
|
||||
|
||||
#endif //DCM_INDENT_H
|
155
src/Mod/Assembly/App/opendcm/moduleState/karma_trans.hpp
Normal file
155
src/Mod/Assembly/App/opendcm/moduleState/karma_trans.hpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Copyright (c) 2011 Jamboree
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//////////////////////////////////////////////////////////////////////////////*/
|
||||
#ifndef BOOST_SPIRIT_REPOSITORY_KARMA_TRANS
|
||||
#define BOOST_SPIRIT_REPOSITORY_KARMA_TRANS
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/karma/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/karma/generator.hpp>
|
||||
#include <boost/spirit/home/karma/domain.hpp>
|
||||
#include <boost/spirit/home/support/unused.hpp>
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/support/has_semantic_action.hpp>
|
||||
#include <boost/spirit/home/support/handles_container.hpp>
|
||||
#include <boost/spirit/home/karma/detail/attributes.hpp>
|
||||
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace repository
|
||||
{
|
||||
namespace tag
|
||||
{
|
||||
struct trans {};
|
||||
}
|
||||
|
||||
namespace karma
|
||||
{
|
||||
// enables trans<T>(f)[...]
|
||||
template <typename T, typename F>
|
||||
inline
|
||||
spirit::stateful_tag_type<F, tag::trans, T> trans(F f)
|
||||
{
|
||||
return spirit::stateful_tag_type<F, tag::trans, T>(f);
|
||||
}
|
||||
|
||||
// enables trans(f)[...]
|
||||
template <typename F>
|
||||
inline
|
||||
spirit::stateful_tag_type<F, tag::trans> trans(F f)
|
||||
{
|
||||
return spirit::stateful_tag_type<F, tag::trans>(f);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enablers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// enables trans<T>(f)[...]
|
||||
template <typename F, typename T>
|
||||
struct use_directive<karma::domain, tag::stateful_tag<F, repository::tag::trans, T> >
|
||||
: mpl::true_ {};
|
||||
}} // namespace boost::spirit
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace repository {namespace karma
|
||||
{
|
||||
template <typename Subject, typename T, typename F>
|
||||
struct trans_directive
|
||||
: spirit::karma::unary_generator<trans_directive<Subject, T, F> >
|
||||
{
|
||||
typedef Subject subject_type;
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
: mpl::eval_if
|
||||
<
|
||||
is_same<T, unused_type>
|
||||
, traits::attribute_of<subject_type, Context, Iterator>
|
||||
, mpl::identity<T>
|
||||
>
|
||||
{};
|
||||
|
||||
trans_directive(Subject const& subject, F f)
|
||||
: subject(subject), f(f)
|
||||
{}
|
||||
|
||||
template
|
||||
<
|
||||
typename OutputIterator, typename Context
|
||||
, typename Delimiter, typename Attribute
|
||||
>
|
||||
bool generate
|
||||
(
|
||||
OutputIterator& sink, Context& ctx, Delimiter const& d
|
||||
, Attribute const& attr) const
|
||||
{
|
||||
return subject.generate(sink, ctx, d, f(attr));
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
info what(Context& context) const
|
||||
{
|
||||
return info("trans", subject.what(context));
|
||||
}
|
||||
|
||||
Subject subject;
|
||||
F f;
|
||||
};
|
||||
}}}} // namespace boost::spirit::repository::karma
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace karma
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator generators: make_xxx function (objects)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename F, typename T, typename Subject, typename Modifiers>
|
||||
struct make_directive<tag::stateful_tag<F, repository::tag::trans, T>, Subject, Modifiers>
|
||||
{
|
||||
typedef repository::karma::trans_directive<Subject, T, F> result_type;
|
||||
|
||||
template <typename StatefulTag>
|
||||
result_type operator()(
|
||||
StatefulTag const& tag, Subject const& subject, unused_type) const
|
||||
{
|
||||
return result_type(subject, tag.data_);
|
||||
}
|
||||
};
|
||||
}}} // namespace boost::spirit::karma
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename T, typename F>
|
||||
struct has_semantic_action<repository::karma::trans_directive<Subject, T, F> >
|
||||
: unary_has_semantic_action<Subject> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Subject, typename T, typename F
|
||||
, typename Attribute, typename Context, typename Iterator>
|
||||
struct handles_container
|
||||
<
|
||||
repository::karma::trans_directive<Subject, T, F>
|
||||
, Attribute, Context, Iterator
|
||||
>
|
||||
: mpl::false_ {}; // FIXME
|
||||
}}} // namespace boost::spirit::traits
|
||||
|
||||
|
||||
#endif
|
98
src/Mod/Assembly/App/opendcm/moduleState/module.hpp
Normal file
98
src/Mod/Assembly/App/opendcm/moduleState/module.hpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE_STATE_H
|
||||
#define DCM_MODULE_STATE_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "indent.hpp"
|
||||
#include "generator.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/support_istream_iterator.hpp>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct ModuleState {
|
||||
|
||||
template<typename Sys>
|
||||
struct type {
|
||||
|
||||
typedef Unspecified_Identifier Identifier;
|
||||
|
||||
struct inheriter {
|
||||
|
||||
inheriter() {
|
||||
m_this = (Sys*) this;
|
||||
};
|
||||
|
||||
Sys* m_this;
|
||||
|
||||
void saveState(std::ostream& stream) {
|
||||
|
||||
boost::iostreams::filtering_ostream indent_stream;
|
||||
indent_stream.push(indent_filter());
|
||||
indent_stream.push(stream);
|
||||
|
||||
std::ostream_iterator<char> out(indent_stream);
|
||||
generator<Sys> gen;
|
||||
|
||||
karma::generate(out, gen, *m_this->m_cluster);
|
||||
};
|
||||
|
||||
void loadState(std::istream& stream) {
|
||||
|
||||
//disable skipping of whitespace
|
||||
stream.unsetf(std::ios::skipws);
|
||||
|
||||
// wrap istream into iterator
|
||||
boost::spirit::istream_iterator begin(stream);
|
||||
boost::spirit::istream_iterator end;
|
||||
|
||||
// use iterator to parse file data
|
||||
parser<Sys> par;
|
||||
m_this->clear();
|
||||
typename Sys::Cluster* cl_ptr = m_this->m_cluster.get();
|
||||
qi::phrase_parse(begin, end, par(m_this), qi::space, cl_ptr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//add only a property to the cluster as we need it to store the clusers global vertex
|
||||
typedef mpl::vector1<details::cluster_vertex_prop> properties;
|
||||
typedef mpl::vector0<> objects;
|
||||
|
||||
//nothing to do on startup
|
||||
static void system_init(Sys& sys) {};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //DCM_MODULE_STATE_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef DCM_OBJECT_GENERATOR_H
|
||||
#define DCM_OBJECT_GENERATOR_H
|
||||
|
||||
#include "property_generator.hpp"
|
||||
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
//grammar for a single object
|
||||
template<typename Sys, typename Object, typename Gen>
|
||||
struct obj_grammar : public karma::grammar<Iterator, boost::shared_ptr<Object>()> {
|
||||
typename Gen::generator subrule;
|
||||
karma::rule<Iterator, boost::shared_ptr<Object>()> start;
|
||||
details::prop_gen<Sys, typename Object::Sequence > prop;
|
||||
|
||||
obj_grammar();
|
||||
static void getProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq);
|
||||
};
|
||||
|
||||
//when objects should not be generated we need to get a empy rule, as obj_rule_init
|
||||
//trys always to access the rules attribute and when the parser_generator trait is not
|
||||
//specialitzed it's impossible to have the attribute type right in the unspecialized trait
|
||||
template<typename Sys, typename seq, typename state>
|
||||
struct obj_generator_fold : mpl::fold< seq, state,
|
||||
mpl::if_< parser_generate<mpl::_2, Sys>,
|
||||
mpl::push_back<mpl::_1,
|
||||
obj_grammar<Sys, mpl::_2, dcm::parser_generator<mpl::_2, Sys, Iterator> > >,
|
||||
mpl::push_back<mpl::_1, details::empty_grammar > > > {};
|
||||
|
||||
//currently max. 10 objects are supported
|
||||
template<typename Sys>
|
||||
struct obj_gen : public karma::grammar<Iterator, typename details::sps<typename Sys::objects>::type()> {
|
||||
|
||||
typedef typename Sys::objects ObjectList;
|
||||
|
||||
//create a vector with the appropriate rules for all objects. Do this with the rule init struct, as it gives
|
||||
//automatic initialisation of the rules when the objects are created
|
||||
typedef typename obj_generator_fold<Sys, ObjectList,mpl::vector<> >::type init_rules_vector;
|
||||
//push back a empty rule so that we know where to go when nothing is to do
|
||||
typedef typename mpl::push_back<init_rules_vector, empty_grammar >::type rules_vector;
|
||||
|
||||
//create the fusion sequence of our rules
|
||||
typedef typename fusion::result_of::as_vector<rules_vector>::type rules_sequnce;
|
||||
|
||||
//this struct returns the right accessvalue for the sequences. If we access a value bigger than the property vector size
|
||||
//we use the last rule, as we made sure this is an empty one
|
||||
template<int I>
|
||||
struct index : public mpl::if_< mpl::less<mpl::int_<I>, mpl::size<ObjectList> >,
|
||||
mpl::int_<I>, typename mpl::size<ObjectList>::prior >::type {};
|
||||
//this struct tells us if we should execute the generator
|
||||
template<int I>
|
||||
struct valid : public mpl::less< mpl::int_<I>, mpl::size<ObjectList> > {};
|
||||
|
||||
rules_sequnce rules;
|
||||
karma::rule<Iterator, typename details::sps<ObjectList>::type()> obj;
|
||||
|
||||
obj_gen();
|
||||
};
|
||||
} //namespace details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "object_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_OBJECT_GENERATOR_H
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef DCM_OBJECT_GENERATOR_IMP_H
|
||||
#define DCM_OBJECT_GENERATOR_IMP_H
|
||||
|
||||
|
||||
#include "traits_impl.hpp"
|
||||
#include "object_generator.hpp"
|
||||
#include "property_generator_imp.hpp"
|
||||
|
||||
using namespace boost::spirit::karma;
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace phx = boost::phoenix;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Sys, typename Object, typename Gen>
|
||||
obj_grammar<Sys, Object,Gen>::obj_grammar() : obj_grammar<Sys, Object,Gen>::base_type(start) {
|
||||
Gen::init(subrule);
|
||||
start = lit("\n<Object>") << '+' << eol << subrule
|
||||
<< prop[phx::bind(&obj_grammar::getProperties, _val, karma::_1)]
|
||||
<< '-' << eol << lit("</Object>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename Object, typename Gen>
|
||||
void obj_grammar<Sys, Object,Gen>::getProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq) {
|
||||
|
||||
if(ptr) seq = ptr->m_properties;
|
||||
else {
|
||||
//TODO: throw
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
obj_gen<Sys>::obj_gen() : obj_gen<Sys>::base_type(obj) {
|
||||
|
||||
obj = -(eps(valid<0>::value) << eps(phx::at_c<index<0>::value>(_val)) << fusion::at<index<0> >(rules)[karma::_1 = phx::at_c<index<0>::value>(_val)])
|
||||
<< -(eps(valid<1>::value) << eps(phx::at_c<index<1>::value>(_val)) << fusion::at<index<1> >(rules)[karma::_1 = phx::at_c<index<1>::value>(_val)])
|
||||
<< -(eps(valid<2>::value) << eps(phx::at_c<index<2>::value>(_val)) << fusion::at<index<2> >(rules)[karma::_1 = phx::at_c<index<2>::value>(_val)])
|
||||
<< -(eps(valid<3>::value) << eps(phx::at_c<index<3>::value>(_val)) << fusion::at<index<3> >(rules)[karma::_1 = phx::at_c<index<3>::value>(_val)])
|
||||
<< -(eps(valid<4>::value) << eps(phx::at_c<index<4>::value>(_val)) << fusion::at<index<4> >(rules)[karma::_1 = phx::at_c<index<4>::value>(_val)])
|
||||
<< -(eps(valid<5>::value) << eps(phx::at_c<index<5>::value>(_val)) << fusion::at<index<5> >(rules)[karma::_1 = phx::at_c<index<5>::value>(_val)])
|
||||
<< -(eps(valid<6>::value) << eps(phx::at_c<index<6>::value>(_val)) << fusion::at<index<6> >(rules)[karma::_1 = phx::at_c<index<6>::value>(_val)])
|
||||
<< -(eps(valid<7>::value) << eps(phx::at_c<index<7>::value>(_val)) << fusion::at<index<7> >(rules)[karma::_1 = phx::at_c<index<7>::value>(_val)])
|
||||
<< -(eps(valid<8>::value) << eps(phx::at_c<index<8>::value>(_val)) << fusion::at<index<8> >(rules)[karma::_1 = phx::at_c<index<8>::value>(_val)])
|
||||
<< -(eps(valid<9>::value) << eps(phx::at_c<index<9>::value>(_val)) << fusion::at<index<9> >(rules)[karma::_1 = phx::at_c<index<9>::value>(_val)]);
|
||||
|
||||
};
|
||||
|
||||
} //namespace details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_OBJECT_GENERATOR_H
|
98
src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp
Normal file
98
src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_OBJECT_PARSER_H
|
||||
#define DCM_OBJECT_PARSER_H
|
||||
|
||||
#include "property_parser.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Obj, typename Sys>
|
||||
struct empty_obj_parser : public qi::grammar<IIterator, boost::shared_ptr<Obj>(Sys*), qi::space_type> {
|
||||
qi::rule<IIterator, boost::shared_ptr<Obj>(Sys*), qi::space_type> start;
|
||||
empty_obj_parser(): empty_obj_parser::base_type(start) {
|
||||
//start = qi::eps(false);
|
||||
};
|
||||
};
|
||||
|
||||
//grammar for a single object
|
||||
template<typename Sys, typename Object, typename Par>
|
||||
struct obj_parser : public qi::grammar<IIterator, boost::shared_ptr<Object>(Sys*), qi::space_type> {
|
||||
typename Par::parser subrule;
|
||||
qi::rule<IIterator, boost::shared_ptr<Object>(Sys*), qi::space_type> start;
|
||||
prop_par<Sys, typename Object::Sequence > prop;
|
||||
|
||||
obj_parser();
|
||||
|
||||
static void setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq);
|
||||
};
|
||||
|
||||
//when objects should not be generated we need to get a empy rule, as obj_rule_init
|
||||
//trys always to access the rules attribute and when the parser_generator trait is not
|
||||
//specialitzed it's impossible to have the attribute type right in the unspecialized trait
|
||||
template<typename Sys, typename seq, typename state>
|
||||
struct obj_parser_fold : mpl::fold< seq, state,
|
||||
mpl::if_< parser_parse<mpl::_2, Sys>,
|
||||
mpl::push_back<mpl::_1,
|
||||
obj_parser<Sys, mpl::_2, dcm::parser_parser<mpl::_2, Sys, IIterator> > >,
|
||||
mpl::push_back<mpl::_1, empty_obj_parser<mpl::_2, Sys> > > > {};
|
||||
|
||||
//currently max. 10 objects are supported
|
||||
template<typename Sys>
|
||||
struct obj_par : public qi::grammar<IIterator,
|
||||
typename details::sps<typename Sys::objects>::type(Sys*),
|
||||
qi::space_type> {
|
||||
|
||||
typedef typename Sys::objects ObjectList;
|
||||
|
||||
//create a vector with the appropriate rules for all objects. Do this with the rule init struct, as it gives
|
||||
//automatic initialisation of the rules when the objects are created
|
||||
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type init_rules_vector;
|
||||
//push back a empty rule so that we know where to go when nothing is to do
|
||||
typedef typename mpl::push_back<init_rules_vector,
|
||||
empty_obj_parser<typename mpl::back<ObjectList>::type, Sys> >::type rules_vector;
|
||||
|
||||
//create the fusion sequence of our rules
|
||||
typedef typename fusion::result_of::as_vector<rules_vector>::type rules_sequnce;
|
||||
|
||||
//this struct returns the right accessvalue for the sequences. If we access a value bigger than the property vector size
|
||||
//we use the last rule, as we made sure this is an empty one
|
||||
template<int I>
|
||||
struct index : public mpl::if_< mpl::less<mpl::int_<I>, mpl::size<ObjectList> >,
|
||||
mpl::int_<I>, typename mpl::size<ObjectList>::prior >::type {};
|
||||
//this struct tells us if we should execute the generator
|
||||
template<int I>
|
||||
struct valid : public mpl::less< mpl::int_<I>, mpl::size<ObjectList> > {};
|
||||
|
||||
rules_sequnce rules;
|
||||
qi::rule<IIterator, typename details::sps<ObjectList>::type(Sys*), qi::space_type> obj;
|
||||
|
||||
obj_par();
|
||||
};
|
||||
|
||||
}//details
|
||||
}//DCM
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_OBJECT_PARSER_IMP_H
|
||||
#define DCM_OBJECT_PARSER_IMP_H
|
||||
|
||||
#include "object_parser.hpp"
|
||||
#include "property_parser_imp.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys, typename Object, typename Par>
|
||||
obj_parser<Sys, Object, Par>::obj_parser(): obj_parser::base_type(start) {
|
||||
Par::init(subrule);
|
||||
start = qi::lit("<Object>") >> subrule(qi::_r1)[qi::_val = qi::_1]
|
||||
>> qi::eps(qi::_val)[ phx::bind(&Sys::template push_back<Object>, qi::_r1, qi::_val)]
|
||||
>> prop[phx::bind(&obj_parser::setProperties, qi::_val, qi::_1)]
|
||||
>> qi::lit("</Object>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename Object, typename Par>
|
||||
void obj_parser<Sys, Object, Par>::setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::Sequence>::type& seq) {
|
||||
if(ptr) ptr->m_properties = seq;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
obj_par<Sys>::obj_par(): obj_par<Sys>::base_type(obj) {
|
||||
|
||||
obj = -(qi::eps(valid<0>::value) >> fusion::at<index<0> >(rules)(qi::_r1)[phx::at_c<index<0>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<1>::value) >> fusion::at<index<1> >(rules)(qi::_r1)[phx::at_c<index<1>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<2>::value) >> fusion::at<index<2> >(rules)(qi::_r1)[phx::at_c<index<2>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<3>::value) >> fusion::at<index<3> >(rules)(qi::_r1)[phx::at_c<index<3>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<4>::value) >> fusion::at<index<4> >(rules)(qi::_r1)[phx::at_c<index<4>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<5>::value) >> fusion::at<index<5> >(rules)(qi::_r1)[phx::at_c<index<5>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<6>::value) >> fusion::at<index<6> >(rules)(qi::_r1)[phx::at_c<index<6>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<7>::value) >> fusion::at<index<7> >(rules)(qi::_r1)[phx::at_c<index<7>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<8>::value) >> fusion::at<index<8> >(rules)(qi::_r1)[phx::at_c<index<8>::value>(qi::_val) = qi::_1])
|
||||
>> -(qi::eps(valid<9>::value) >> fusion::at<index<9> >(rules)(qi::_r1)[phx::at_c<index<9>::value>(qi::_val) = qi::_1]);
|
||||
|
||||
};
|
||||
|
||||
}//details
|
||||
}//DCM
|
||||
|
||||
|
||||
#endif
|
82
src/Mod/Assembly/App/opendcm/moduleState/parser.hpp
Normal file
82
src/Mod/Assembly/App/opendcm/moduleState/parser.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PARSER_H
|
||||
#define DCM_PARSER_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/support_istream_iterator.hpp>
|
||||
#include <boost/spirit/include/qi_string.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
|
||||
#include "property_parser.hpp"
|
||||
#include "object_parser.hpp"
|
||||
#include "edge_vertex_parser.hpp"
|
||||
#include "extractor.hpp"
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
struct sp : qi::grammar<IIterator, std::string()> {
|
||||
|
||||
qi::rule<IIterator, std::string()> start;
|
||||
sp() : sp::base_type(start) {
|
||||
start %= +qi::char_;
|
||||
};
|
||||
static void print(std::string s) {
|
||||
std::cout<<"parsed string:"<<std::endl<<s<<std::endl<<"done print string"<<std::endl;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<int>, qi::space_type> {
|
||||
|
||||
typedef typename Sys::Cluster graph;
|
||||
|
||||
parser();
|
||||
|
||||
qi::rule<IIterator, graph*(Sys*), qi::locals<int>, qi::space_type> cluster;
|
||||
details::cluster_prop_par<Sys> cluster_prop;
|
||||
|
||||
details::obj_par<Sys> objects;
|
||||
|
||||
details::vertex_parser<Sys> vertex;
|
||||
details::edge_parser<Sys> edge;
|
||||
|
||||
sp str;
|
||||
Injector<Sys> in;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_PARSER_H
|
71
src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp
Normal file
71
src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PARSER_IMP_H
|
||||
#define DCM_PARSER_IMP_H
|
||||
|
||||
#include <boost/spirit/include/qi_attr_cast.hpp>
|
||||
|
||||
#include "opendcm/core/system.hpp"
|
||||
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||
(T1)(T2)(T3)(T4),
|
||||
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
|
||||
(typename dcm::details::pts<T3>::type, m_cluster_bundle))
|
||||
|
||||
#include "parser.hpp"
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace traits
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
struct transform_attribute<dcm::ClusterGraph<T1,T2,T3,T4>*, dcm::ClusterGraph<T1,T2,T3,T4>, qi::domain>
|
||||
{
|
||||
typedef dcm::ClusterGraph<T1,T2,T3,T4>& type;
|
||||
static type pre(dcm::ClusterGraph<T1,T2,T3,T4>* const& val) {
|
||||
return *val;
|
||||
}
|
||||
static void post(dcm::ClusterGraph<T1,T2,T3,T4>* const& val, dcm::ClusterGraph<T1,T2,T3,T4> const& attr) {}
|
||||
static void fail(dcm::ClusterGraph<T1,T2,T3,T4>* const&) {}
|
||||
};
|
||||
}}}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
template<typename Sys>
|
||||
parser<Sys>::parser() : parser<Sys>::base_type(cluster) {
|
||||
|
||||
cluster %= qi::lit("<Cluster id=") >> qi::omit[qi::int_[qi::_a = qi::_1]] >> ">"
|
||||
>> -(qi::eps( qi::_a > 0 )[qi::_val = phx::new_<typename Sys::Cluster>()])
|
||||
>> qi::eps[phx::bind(&Injector<Sys>::setVertexProperty, in, qi::_val, qi::_a)]
|
||||
>> qi::attr_cast<graph*, graph>(cluster_prop >> qi::eps)
|
||||
>> qi::omit[*vertex(qi::_val, qi::_r1)]
|
||||
>> qi::omit[*edge(qi::_val, qi::_r1)]
|
||||
>> qi::omit[*(cluster(qi::_r1)[phx::bind(&Injector<Sys>::addCluster, in, qi::_val, qi::_1)])]
|
||||
>> "</Cluster>";// >> str[&sp::print];
|
||||
};
|
||||
|
||||
}
|
||||
#endif //DCM_PARSER_H
|
102
src/Mod/Assembly/App/opendcm/moduleState/property_generator.hpp
Normal file
102
src/Mod/Assembly/App/opendcm/moduleState/property_generator.hpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
#ifndef DCM_PROPERTY_GENERATOR_H
|
||||
#define DCM_PROPERTY_GENERATOR_H
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
|
||||
#include <boost/mpl/range_c.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/minus.hpp>
|
||||
#include <boost/mpl/less_equal.hpp>
|
||||
|
||||
#include "traits.hpp"
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace fusion = boost::fusion;
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
//a grammar that does nothing exept failing
|
||||
struct empty_grammar : public karma::grammar<Iterator> {
|
||||
karma::rule<Iterator> start;
|
||||
empty_grammar(): empty_grammar::base_type(start) {
|
||||
start = karma::eps(true);
|
||||
};
|
||||
empty_grammar(const empty_grammar& other) : empty_grammar::base_type(start) {};
|
||||
};
|
||||
|
||||
template<typename Prop>
|
||||
struct skip_grammar : public karma::grammar<Iterator, typename Prop::type&()> {
|
||||
karma::rule<Iterator, typename Prop::type&()> start;
|
||||
skip_grammar() : skip_grammar<Prop>::base_type(start) {
|
||||
start = karma::eps(true);
|
||||
};
|
||||
skip_grammar(const skip_grammar& other) : skip_grammar::base_type(start) {};
|
||||
};
|
||||
|
||||
//grammar for a single property
|
||||
template<typename Prop, typename Gen>
|
||||
struct prop_grammar : public karma::grammar<Iterator, typename Prop::type&()> {
|
||||
typename Gen::generator subrule;
|
||||
karma::rule<Iterator, typename Prop::type&()> start;
|
||||
prop_grammar();
|
||||
prop_grammar(const prop_grammar& other) : prop_grammar::base_type(start) {};
|
||||
};
|
||||
|
||||
template<typename Sys, typename seq, typename state>
|
||||
struct prop_generator_fold : mpl::fold< seq, state,
|
||||
mpl::if_< parser_generate<mpl::_2, Sys>,
|
||||
mpl::push_back<mpl::_1,
|
||||
prop_grammar<mpl::_2, dcm::parser_generator<mpl::_2, Sys, Iterator> > >,
|
||||
mpl::push_back<mpl::_1, skip_grammar<mpl::_2> > > > {};
|
||||
|
||||
//grammar for a fusion sequence of properties. currently max. 10 properties are supported
|
||||
template<typename Sys, typename PropertyList>
|
||||
struct prop_gen : karma::grammar<Iterator, typename details::pts<PropertyList>::type&()> {
|
||||
|
||||
//create a vector with the appropriate rules for all properties.
|
||||
typedef typename prop_generator_fold<Sys, PropertyList, mpl::vector<> >::type init_rules_sequence;
|
||||
//allow max 10 types as the following code expect this
|
||||
BOOST_MPL_ASSERT((mpl::less_equal< mpl::size<init_rules_sequence>, mpl::int_<10> >));
|
||||
//we want to process 10 elements, so create a vector with (10-prop.size()) empty rules
|
||||
//and append it to our rules vector
|
||||
typedef mpl::range_c<int,0, mpl::minus< mpl::int_<10>, mpl::size<init_rules_sequence> >::value > range;
|
||||
typedef typename mpl::fold< range,
|
||||
init_rules_sequence,
|
||||
mpl::push_back<mpl::_1, empty_grammar> >::type rules_sequence;
|
||||
|
||||
typename fusion::result_of::as_vector<rules_sequence>::type rules;
|
||||
karma::rule<Iterator, typename details::pts<PropertyList>::type&()> prop;
|
||||
|
||||
prop_gen();
|
||||
};
|
||||
|
||||
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
|
||||
template<typename Sys>
|
||||
struct cluster_prop_gen : public prop_gen<Sys, typename Sys::Cluster::cluster_properties> {
|
||||
cluster_prop_gen();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_prop_gen : public prop_gen<Sys, typename Sys::Cluster::vertex_properties> {
|
||||
vertex_prop_gen();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_prop_gen : public prop_gen<Sys, typename Sys::Cluster::edge_properties> {
|
||||
edge_prop_gen();
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_PROPERTY_GENERATOR_H
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef DCM_PROPERTY_GENERATOR_IMP_H
|
||||
#define DCM_PROPERTY_GENERATOR_IMP_H
|
||||
|
||||
#include "property_generator.hpp"
|
||||
#include "traits_impl.hpp"
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
//grammar for a single property
|
||||
template<typename Prop, typename Gen>
|
||||
prop_grammar<Prop, Gen>::prop_grammar() : prop_grammar<Prop, Gen>::base_type(start) {
|
||||
|
||||
Gen::init(subrule);
|
||||
start = karma::lit("\n<Property>") << '+' << karma::eol << subrule
|
||||
<< '-' << karma::eol << karma::lit("</Property>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename PropertyList>
|
||||
prop_gen<Sys, PropertyList>::prop_gen() : prop_gen<Sys, PropertyList>::base_type(prop) {
|
||||
|
||||
prop = fusion::at_c<0>(rules) << fusion::at_c<1>(rules) << fusion::at_c<2>(rules)
|
||||
<< fusion::at_c<3>(rules) << fusion::at_c<4>(rules) << fusion::at_c<5>(rules)
|
||||
<< fusion::at_c<6>(rules) << fusion::at_c<7>(rules) << fusion::at_c<8>(rules)
|
||||
<< fusion::at_c<9>(rules);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
cluster_prop_gen<Sys>::cluster_prop_gen() : prop_gen<Sys, typename Sys::Cluster::cluster_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_prop_gen<Sys>::vertex_prop_gen() : prop_gen<Sys, typename Sys::Cluster::vertex_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
edge_prop_gen<Sys>::edge_prop_gen() : prop_gen<Sys, typename Sys::Cluster::edge_properties>() {};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_PROPERTY_GENERATOR_H
|
120
src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp
Normal file
120
src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PROPERTY_PARSER_H
|
||||
#define DCM_PROPERTY_PARSER_H
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/support_istream_iterator.hpp>
|
||||
#include <boost/spirit/include/qi_string.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
|
||||
namespace fusion = boost::fusion;
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
struct empty_parser : public qi::grammar<IIterator> {
|
||||
qi::rule<IIterator> start;
|
||||
empty_parser(): empty_parser::base_type(start) {
|
||||
start = qi::eps(true);
|
||||
};
|
||||
empty_parser(const empty_parser& other) : empty_parser::base_type(start) {};
|
||||
};
|
||||
|
||||
template<typename Prop>
|
||||
struct skip_parser : public qi::grammar<IIterator, typename Prop::type()> {
|
||||
qi::rule<IIterator, typename Prop::type()> start;
|
||||
skip_parser() : skip_parser<Prop>::base_type(start) {
|
||||
start = qi::eps(true);
|
||||
};
|
||||
skip_parser(const skip_parser& other) : skip_parser::base_type(start) {};
|
||||
};
|
||||
|
||||
template<typename Prop, typename Par>
|
||||
struct prop_parser : qi::grammar<IIterator, typename Prop::type(), qi::space_type> {
|
||||
|
||||
typename Par::parser subrule;
|
||||
qi::rule<IIterator, typename Prop::type(), qi::space_type> start;
|
||||
prop_parser();
|
||||
prop_parser(const prop_parser& other) : prop_parser::base_type(start) {};
|
||||
};
|
||||
|
||||
template<typename Sys, typename seq, typename state>
|
||||
struct prop_parser_fold : mpl::fold< seq, state,
|
||||
mpl::if_< dcm::parser_parse<mpl::_2, Sys>,
|
||||
mpl::push_back<mpl::_1,
|
||||
prop_parser<mpl::_2, dcm::parser_parser<mpl::_2, Sys, IIterator> > >,
|
||||
mpl::push_back<mpl::_1, skip_parser<mpl::_2> > > > {};
|
||||
|
||||
//grammar for a fusion sequence of properties. currently max. 10 properties are supported
|
||||
template<typename Sys, typename PropertyList>
|
||||
struct prop_par : qi::grammar<IIterator, typename details::pts<PropertyList>::type(), qi::space_type> {
|
||||
|
||||
//create a vector with the appropriate rules for all properties.
|
||||
typedef typename prop_parser_fold<Sys, PropertyList, mpl::vector<> >::type init_rules_sequence;
|
||||
//allow max 10 types as the following code expect this
|
||||
BOOST_MPL_ASSERT((mpl::less_equal< mpl::size<init_rules_sequence>, mpl::int_<10> >));
|
||||
//we want to process 10 elements, so create a vector with (10-prop.size()) empty rules
|
||||
//and append it to our rules vector
|
||||
typedef mpl::range_c<int,0, mpl::minus< mpl::int_<10>, mpl::size<init_rules_sequence> >::value > range;
|
||||
typedef typename mpl::fold< range,
|
||||
init_rules_sequence,
|
||||
mpl::push_back<mpl::_1, empty_parser> >::type rules_sequence;
|
||||
|
||||
typename fusion::result_of::as_vector<rules_sequence>::type rules;
|
||||
qi::rule<IIterator, typename details::pts<PropertyList>::type(), qi::space_type> prop;
|
||||
|
||||
prop_par();
|
||||
};
|
||||
|
||||
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
|
||||
template<typename Sys>
|
||||
struct cluster_prop_par : public prop_par<Sys, typename Sys::Cluster::cluster_properties> {
|
||||
cluster_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_prop_par : public prop_par<Sys, typename Sys::Cluster::vertex_properties> {
|
||||
vertex_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_prop_par : public prop_par<Sys, typename Sys::Cluster::edge_properties> {
|
||||
edge_prop_par();
|
||||
};
|
||||
|
||||
} //DCM
|
||||
} //details
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PROPERTY_PARSER_IMP_H
|
||||
#define DCM_PROPERTY_PARSER_IMP_H
|
||||
|
||||
#include "property_parser.hpp"
|
||||
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Prop, typename Par>
|
||||
prop_parser<Prop, Par>::prop_parser() : prop_parser<Prop, Par>::base_type(start) {
|
||||
Par::init(subrule);
|
||||
start %= qi::lit("<Property>") >> subrule >> qi::lit("</Property>");
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys, typename PropertyList>
|
||||
prop_par<Sys, PropertyList>::prop_par() : prop_par<Sys, PropertyList>::base_type(prop) {
|
||||
|
||||
prop %= fusion::at_c<0>(rules) >> fusion::at_c<1>(rules) >> fusion::at_c<2>(rules)
|
||||
>> fusion::at_c<3>(rules) >> fusion::at_c<4>(rules) >> fusion::at_c<5>(rules)
|
||||
>> fusion::at_c<6>(rules) >> fusion::at_c<7>(rules) >> fusion::at_c<8>(rules)
|
||||
>> fusion::at_c<9>(rules);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
cluster_prop_par<Sys>::cluster_prop_par() : prop_par<Sys, typename Sys::Cluster::cluster_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_prop_par<Sys>::vertex_prop_par() : prop_par<Sys, typename Sys::Cluster::vertex_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
edge_prop_par<Sys>::edge_prop_par() : prop_par<Sys, typename Sys::Cluster::edge_properties>() {};
|
||||
|
||||
} //DCM
|
||||
} //details
|
||||
|
||||
#endif
|
53
src/Mod/Assembly/App/opendcm/moduleState/traits.hpp
Normal file
53
src/Mod/Assembly/App/opendcm/moduleState/traits.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PARSER_TRAITS_H
|
||||
#define DCM_PARSER_TRAITS_H
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <assert.h>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename type, typename System>
|
||||
struct parser_generate : public boost::mpl::false_ {};
|
||||
|
||||
template<typename type, typename System, typename iterator>
|
||||
struct parser_generator {
|
||||
typedef int generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename type, typename System>
|
||||
struct parser_parse : public boost::mpl::false_ {};
|
||||
|
||||
template<typename type, typename System, typename iterator>
|
||||
struct parser_parser {
|
||||
typedef int parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
assert(false);
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
#endif //DCM_PARSER_TRAITS_H
|
160
src/Mod/Assembly/App/opendcm/moduleState/traits_impl.hpp
Normal file
160
src/Mod/Assembly/App/opendcm/moduleState/traits_impl.hpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
//move the traits specializations outside of the traits definition to avoid the spirit header parsing every
|
||||
//time this module is included and just parse it in externalisation mode when the generator is build
|
||||
|
||||
#ifndef DCM_PARSER_TRAITS_IMPL_H
|
||||
#define DCM_PARSER_TRAITS_IMPL_H
|
||||
|
||||
#include "traits.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/karma_string.hpp>
|
||||
#include <boost/spirit/include/karma_int.hpp>
|
||||
#include <boost/spirit/include/karma_bool.hpp>
|
||||
#include <boost/spirit/include/karma_rule.hpp>
|
||||
#include <boost/spirit/include/karma_auto.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace traits {
|
||||
template <>
|
||||
struct create_generator<dcm::No_Identifier> {
|
||||
|
||||
typedef BOOST_TYPEOF(karma::eps(false)) type;
|
||||
static type call() {
|
||||
return karma::eps(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<type_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<type_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, int&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>clustertype</type>\n<value>") << karma::int_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<changed_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<changed_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, bool&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>clusterchanged</type>\n<value>") << karma::bool_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<id_prop<typename System::Identifier>, System>
|
||||
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<id_prop<typename System::Identifier>, System, iterator> {
|
||||
typedef karma::rule<iterator, typename System::Identifier()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>id</type>\n<value>") << karma::auto_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<type_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<type_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, int(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>clustertype</type>") >> ("<value>") >> qi::int_ >>"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<changed_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<changed_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, bool(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>clusterchanged</type>") >> ("<value>") >> qi::bool_ >>"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<id_prop<typename System::Identifier>, System>
|
||||
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<id_prop<typename System::Identifier>, System, iterator> {
|
||||
typedef qi::rule<iterator, typename System::Identifier(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::auto_ >>"</value>";
|
||||
};
|
||||
};
|
||||
/*
|
||||
template<typename System>
|
||||
struct parser_generate<details::cluster_vertex_prop, System>
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<details::cluster_vertex_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, int()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>id</type>\n<value>") << karma::int_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<details::cluster_vertex_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<details::cluster_vertex_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, int(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::int_ >>"</value>";
|
||||
};
|
||||
};*/
|
||||
|
||||
} //namespace dcm
|
||||
|
||||
#endif //DCM_PARSER_TRAITS_IMPL_H
|
29
src/Mod/Assembly/App/opendcm/modulepart.hpp
Normal file
29
src/Mod/Assembly/App/opendcm/modulepart.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULEPART_H
|
||||
#define DCM_MODULEPART_H
|
||||
|
||||
#define DCM_USE_MODULEPART
|
||||
|
||||
#include "modulePart/geometry.hpp"
|
||||
#include "modulePart/module.hpp"
|
||||
|
||||
#endif //DCM_MODULEPART_H
|
||||
|
29
src/Mod/Assembly/App/opendcm/modulestate.hpp
Normal file
29
src/Mod/Assembly/App/opendcm/modulestate.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULEPARSER_H
|
||||
#define DCM_MODULEPARSER_H
|
||||
|
||||
#define DCM_USE_MODULESTATE
|
||||
|
||||
#include "moduleState/module.hpp"
|
||||
#include "moduleState/traits.hpp"
|
||||
|
||||
#endif //DCM_MODULEPARSER_H
|
||||
|
Loading…
Reference in New Issue
Block a user