new openDCM version
This commit is contained in:
@@ -43,5 +43,14 @@
|
||||
#include "core/kernel.hpp"
|
||||
#include "core/system.hpp"
|
||||
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
|
||||
#define DCM_EXTERNAL_CORE_INCLUDE_01 "opendcm/core/imp/system_imp.hpp"
|
||||
#define DCM_EXTERNAL_CORE_01( Sys )\
|
||||
template class dcm::System<Sys::Kernel, Sys::Module1, Sys::Module2, Sys::Module3>; \
|
||||
|
||||
#endif //external
|
||||
|
||||
#endif //DCM_CORE_H
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,9 +24,6 @@
|
||||
#include<Eigen/StdVector>
|
||||
|
||||
#include <assert.h>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
@@ -36,13 +33,7 @@
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
@@ -61,8 +52,8 @@ namespace detail {
|
||||
//metafunction to avoid ot-of-range access of mpl sequences
|
||||
template<typename Sequence, int Value>
|
||||
struct in_range_value {
|
||||
typedef typename mpl::prior<mpl::size<Sequence> >::type last_id;
|
||||
typedef typename mpl::min< mpl::int_<Value>, last_id>::type type;
|
||||
typedef typename mpl::prior<mpl::size<Sequence> >::type last_id;
|
||||
typedef typename mpl::min< mpl::int_<Value>, last_id>::type type;
|
||||
};
|
||||
|
||||
//type erasure container for constraints
|
||||
@@ -119,22 +110,10 @@ protected:
|
||||
inline void intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_);
|
||||
|
||||
|
||||
int equationCount();
|
||||
|
||||
template< typename creator_type>
|
||||
void resetType(creator_type& c);
|
||||
|
||||
int equationCount();
|
||||
void calculate(Scalar scale, bool rotation_only = false);
|
||||
void treatLGZ();
|
||||
|
||||
void setMaps(MES& mes);
|
||||
|
||||
void geometryReset(geom_ptr g) {
|
||||
/* placeholder* p = content->resetConstraint(first, second);
|
||||
delete content;
|
||||
content = p;*/
|
||||
};
|
||||
|
||||
void collectPseudoPoints(Vec& vec1, Vec& vec2);
|
||||
|
||||
//Equation is the constraint with types, the EquationSet hold all needed Maps for calculation
|
||||
@@ -174,9 +153,13 @@ protected:
|
||||
int value;
|
||||
|
||||
public:
|
||||
template< typename ConstraintVector, typename EquationVector>
|
||||
template< typename ConstraintVector, typename tag1, typename tag2>
|
||||
struct holder : public placeholder {
|
||||
|
||||
//transform the constraints into eqautions with the now known types
|
||||
typedef typename mpl::fold< ConstraintVector, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, equation<mpl::_2, tag1, tag2> > >::type EquationVector;
|
||||
|
||||
//create a vector of EquationSets with some mpl trickery
|
||||
typedef typename mpl::fold< EquationVector, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, EquationSet<mpl::_2> > >::type eq_set_vector;
|
||||
@@ -309,9 +292,7 @@ public:
|
||||
virtual void collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2);
|
||||
virtual placeholder* clone();
|
||||
virtual int equationCount();
|
||||
virtual void disable() {
|
||||
fusion::for_each(m_sets, disabler());
|
||||
};
|
||||
virtual void disable();
|
||||
|
||||
virtual std::vector<boost::any> getGenericEquations();
|
||||
virtual std::vector<boost::any> getGenericConstraints();
|
||||
@@ -330,599 +311,14 @@ public:
|
||||
geom_ptr first, second;
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
Constraint<Sys, Dim>::Constraint(geom_ptr f, geom_ptr s)
|
||||
: first(f), second(s), content(0) {
|
||||
|
||||
//cf = first->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
//cs = second->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
Constraint<Sys, Dim>::~Constraint() {
|
||||
delete content;
|
||||
//first->template disconnectSignal<reset>(cf);
|
||||
//second->template disconnectSignal<reset>(cs);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename tag1, typename tag2, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFromTags(ConstraintVector& v) {
|
||||
|
||||
typedef tag_order< tag1, tag2 > order;
|
||||
|
||||
//transform the constraints into eqautions with the now known types
|
||||
typedef typename mpl::fold< ConstraintVector, mpl::vector<>,
|
||||
mpl::push_back<mpl::_1, equation<mpl::_2, typename order::first_tag,
|
||||
typename order::second_tag> > >::type EquationVector;
|
||||
|
||||
//and build the placeholder
|
||||
content = new holder<ConstraintVector, EquationVector>(v);
|
||||
|
||||
//geometry order needs to be the one needed by equations
|
||||
if(order::swapt::value)
|
||||
first.swap(second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initialize(ConstraintVector& cv) {
|
||||
|
||||
//use the compile time unrolling to retrieve the geometry tags
|
||||
initializeFirstGeometry<mpl::int_<0> >(cv, mpl::true_());
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
int Constraint<Sys, Dim>::equationCount() {
|
||||
return content->equationCount();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template< typename creator_type>
|
||||
void Constraint<Sys, Dim>::resetType(creator_type& c) {
|
||||
boost::apply_visitor(c, first->m_geometry, second->m_geometry);
|
||||
content = c.p;
|
||||
if(c.need_swap)
|
||||
first.swap(second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::calculate(Scalar scale, bool rotation_only) {
|
||||
content->calculate(first, second, scale, rotation_only);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::treatLGZ() {
|
||||
content->treatLGZ(first, second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::setMaps(MES& mes) {
|
||||
content->setMaps(mes, first, second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
|
||||
content->collectPseudoPoints(first, second, vec1, vec2);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<boost::any> Constraint<Sys, Dim>::getGenericEquations() {
|
||||
return content->getGenericEquations();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<boost::any> Constraint<Sys, Dim>::getGenericConstraints() {
|
||||
return content->getGenericConstraints();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<const std::type_info*> Constraint<Sys, Dim>::getEquationTypes() {
|
||||
return content->getEquationTypes();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<const std::type_info*> Constraint<Sys, Dim>::getConstraintTypes() {
|
||||
return content->getConstraintTypes();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template<typename T>
|
||||
typename boost::enable_if<typename Constraint<Sys, Dim>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type, void>::type
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
//get the index of the corresbonding equation
|
||||
typedef typename mpl::find<EquationVector, T>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
|
||||
fusion::copy(fusion::at<distance>(objects).values, val.m_eq.values);
|
||||
val.pure_rotation = fusion::at<distance>(objects).pure_rotation;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template<typename T>
|
||||
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Dim>::template holder<ConstraintVector, EquationVector>::template has_option<T>::type>, void>::type
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only)
|
||||
: first(f), second(s), scale(sc), rot_only(rotation_only) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Calculater::operator()(T& val) const {
|
||||
|
||||
//if the equation is disabled we don't have anything mapped so avoid accessing it
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//if we only need pure rotational functions and we are not such a nice thing, everything becomes 0
|
||||
if(rot_only && !val.pure_rotation) {
|
||||
|
||||
val.m_residual(0) = 0;
|
||||
if(first->getClusterMode()) {
|
||||
if(!first->isClusterFixed()) {
|
||||
val.m_diff_first_rot.setZero();
|
||||
val.m_diff_first.setZero();
|
||||
}
|
||||
}
|
||||
else
|
||||
val.m_diff_first.setZero();
|
||||
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
val.m_diff_second_rot.setZero();
|
||||
val.m_diff_second.setZero();
|
||||
}
|
||||
}
|
||||
else
|
||||
val.m_diff_second.setZero();
|
||||
|
||||
}
|
||||
//we need to calculate, so lets go for it!
|
||||
else {
|
||||
|
||||
val.m_eq.setScale(scale);
|
||||
|
||||
val.m_residual(0) = val.m_eq.calculate(first->m_parameter, second->m_parameter);
|
||||
|
||||
//now see which way we should calculate the gradient (may be diffrent for both geometries)
|
||||
if(first->m_parameterCount) {
|
||||
if(first->getClusterMode()) {
|
||||
//when the cluster is fixed no maps are set as no parameters exist.
|
||||
if(!first->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_first_rot(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, first->m_diffparam.col(i));
|
||||
}
|
||||
//and now with the translations
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, first->m_diffparam.col(i+3));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientFirstComplete(first->m_parameter, second->m_parameter, val.m_diff_first);
|
||||
}
|
||||
}
|
||||
if(second->m_parameterCount) {
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_second_rot(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
|
||||
second->m_parameter, second->m_diffparam.col(i));
|
||||
}
|
||||
//and the translation seperated
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
|
||||
second->m_parameter, second->m_diffparam.col(i+3));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientSecondComplete(first->m_parameter, second->m_parameter, val.m_diff_second);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
|
||||
: mes(m), first(f), second(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::MapSetter::operator()(T& val) const {
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//when in cluster, there are 6 clusterparameter we differentiat for, if not we differentiat
|
||||
//for every parameter in the geometry;
|
||||
int equation = mes.setResidualMap(val.m_residual);
|
||||
if(first->getClusterMode()) {
|
||||
if(!first->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, first->m_offset_rot, 3, val.m_diff_first_rot);
|
||||
mes.setJacobiMap(equation, first->m_offset, 3, val.m_diff_first);
|
||||
}
|
||||
}
|
||||
else
|
||||
mes.setJacobiMap(equation, first->m_offset, first->m_parameterCount, val.m_diff_first);
|
||||
|
||||
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, second->m_offset_rot, 3, val.m_diff_second_rot);
|
||||
mes.setJacobiMap(equation, second->m_offset, 3, val.m_diff_second);
|
||||
}
|
||||
}
|
||||
else
|
||||
mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2)
|
||||
: first(f), second(s), points1(vec1), points2(vec2) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::PseudoCollector::operator()(T& val) const {
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
if(first->m_isInCluster && second->m_isInCluster) {
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, second->m_rotated, points2);
|
||||
}
|
||||
else
|
||||
if(first->m_isInCluster) {
|
||||
typename Kernel::Vector sec = second->m_parameter;
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, sec, points2);
|
||||
}
|
||||
else
|
||||
if(second->m_isInCluster) {
|
||||
typename Kernel::Vector fir = first->m_parameter;
|
||||
val.m_eq.calculatePseudo(fir, points1, second->m_rotated, points2);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::LGZ::LGZ(geom_ptr f, geom_ptr s)
|
||||
: first(f), second(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::LGZ::operator()(T& val) const {
|
||||
|
||||
typedef typename Sys::Kernel Kernel;
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//to treat local gradient zeros we calculate a approximate second derivative of the equations
|
||||
//only do that if neseccary: residual is not zero
|
||||
if(!Kernel::isSame(val.m_residual(0),0, 1e-7)) { //TODO: use exact precission and scale value
|
||||
|
||||
//rotations exist only in cluster
|
||||
if(first->getClusterMode() && !first->isClusterFixed()) {
|
||||
//LGZ exists for rotations only
|
||||
for(int i=0; i<3; i++) {
|
||||
|
||||
//only treat if the gradient realy is zero
|
||||
if(Kernel::isSame(val.m_diff_first_rot(i), 0, 1e-7)) {
|
||||
|
||||
//to get the approximated second derivative we need the slightly moved geometrie
|
||||
const typename Kernel::Vector p_old = first->m_parameter;
|
||||
first->m_parameter += first->m_diffparam.col(i)*1e-3;
|
||||
first->normalize();
|
||||
//with this changed geometrie we test if a gradient exist now
|
||||
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
|
||||
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
first->m_parameter = p_old;
|
||||
|
||||
//let's see if the initial LGZ was a real one
|
||||
if(!Kernel::isSame(res, 0, 1e-7)) {
|
||||
|
||||
//is a fake zero, let's correct it
|
||||
val.m_diff_first_rot(i) = res;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
//and the same for the second one too
|
||||
if(second->getClusterMode() && !second->isClusterFixed()) {
|
||||
|
||||
for(int i=0; i<3; i++) {
|
||||
|
||||
//only treat if the gradient realy is zero
|
||||
if(Kernel::isSame(val.m_diff_second_rot(i), 0, 1e-7)) {
|
||||
|
||||
//to get the approximated second derivative we need the slightly moved geometrie
|
||||
const typename Kernel::Vector p_old = second->m_parameter;
|
||||
second->m_parameter += second->m_diffparam.col(i)*1e-3;
|
||||
second->normalize();
|
||||
//with this changed geometrie we test if a gradient exist now
|
||||
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
|
||||
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
second->m_parameter = p_old;
|
||||
|
||||
//let's see if the initial LGZ was a real one
|
||||
if(!Kernel::isSame(res, 0, 1e-7)) {
|
||||
|
||||
//is a fake zero, let's correct it
|
||||
val.m_diff_second_rot(i) = res;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericEquations::GenericEquations(std::vector<boost::any>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericEquations::operator()(T& val) const {
|
||||
vec.push_back(val.m_eq);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericConstraints::GenericConstraints(std::vector<boost::any>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::GenericConstraints::operator()(T& val) const {
|
||||
vec.push_back(val);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Types::Types(std::vector<const std::type_info*>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::Types::operator()(T& val) const {
|
||||
vec.push_back(&typeid(T));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::holder(Objects& obj) : m_objects(obj) {
|
||||
//set the initial values in the equations
|
||||
fusion::for_each(m_sets, OptionSetter(obj));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::calculate(geom_ptr first, geom_ptr second,
|
||||
Scalar scale, bool rotation_only) {
|
||||
fusion::for_each(m_sets, Calculater(first, second, scale, rotation_only));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::treatLGZ(geom_ptr first, geom_ptr second) {
|
||||
fusion::for_each(m_sets, LGZ(first, second));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
typename Constraint<Sys, Dim>::placeholder*
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::resetConstraint(geom_ptr first, geom_ptr second) const {
|
||||
//boost::apply_visitor(creator, first->m_geometry, second->m_geometry);
|
||||
//if(creator.need_swap) first.swap(second);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
|
||||
fusion::for_each(m_sets, MapSetter(mes, first, second));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) {
|
||||
fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
typename Constraint<Sys, Dim>::placeholder*
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::clone() {
|
||||
return new holder(*this);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
int Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::equationCount() {
|
||||
int count = 0;
|
||||
EquationCounter counter(count);
|
||||
fusion::for_each(m_sets, counter);
|
||||
return count;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
std::vector<boost::any>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getGenericEquations() {
|
||||
std::vector<boost::any> vec;
|
||||
fusion::for_each(m_sets, GenericEquations(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
std::vector<boost::any>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getGenericConstraints() {
|
||||
std::vector<boost::any> vec;
|
||||
fusion::for_each(m_objects, GenericConstraints(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
std::vector<const std::type_info*>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getEquationTypes() {
|
||||
std::vector<const std::type_info*> vec;
|
||||
mpl::for_each< EquationVector >(Types(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename EquationVector>
|
||||
std::vector<const std::type_info*>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, EquationVector>::getConstraintTypes() {
|
||||
std::vector<const std::type_info*> vec;
|
||||
mpl::for_each< ConstraintVector >(Types(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
/****************************************************************/
|
||||
/** compiletime unrolled geometry initialising */
|
||||
/****************************************************************/
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
|
||||
//this function is only for breaking the compilation loop, it should never be called
|
||||
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
|
||||
|
||||
typedef typename Sys::geometries geometries;
|
||||
|
||||
switch(first->getExactType()) {
|
||||
|
||||
#ifdef BOOST_PP_LOCAL_ITERATE
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
case (WhichType::value + n): \
|
||||
return initializeSecondGeometry<boost::mpl::int_<0>,\
|
||||
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
|
||||
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
|
||||
break;
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, 10)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
#endif //BOOST_PP_LOCAL_ITERATE
|
||||
default:
|
||||
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
|
||||
return initializeFirstGeometry<next_which_t, ConstraintVector> (cv,
|
||||
typename mpl::less< next_which_t, typename mpl::size<geometries>::type >::type());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename FirstType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
|
||||
//this function is only for breaking the compilation loop, it should never be called
|
||||
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename FirstType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
|
||||
|
||||
typedef typename Sys::geometries geometries;
|
||||
switch(second->getExactType()) {
|
||||
|
||||
#ifdef BOOST_PP_LOCAL_ITERATE
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
case (WhichType::value + n): \
|
||||
return intitalizeFinalize<FirstType, \
|
||||
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
|
||||
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
|
||||
break;
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, 10)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
#endif //BOOST_PP_LOCAL_ITERATE
|
||||
default:
|
||||
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
|
||||
return initializeSecondGeometry<next_which_t, FirstType, ConstraintVector>
|
||||
(cv, typename mpl::less
|
||||
< next_which_t
|
||||
, typename mpl::size<geometries>::type>::type()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename FirstType, typename SecondType, typename ConstraintVector>
|
||||
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_ /*is_unrolled_t*/) {
|
||||
|
||||
initializeFromTags<FirstType, SecondType>(cv);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename FirstType, typename SecondType, typename ConstraintVector>
|
||||
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_ /*is_unrolled_t*/) {
|
||||
//Should never be here at runtime; only required to block code generation that deref's the sequence out of bounds
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};//detail
|
||||
|
||||
};//dcm
|
||||
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/constraint_imp.hpp"
|
||||
#include "imp/constraint_holder_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_CONSTRAINT_H
|
||||
|
||||
|
||||
|
||||
@@ -25,21 +25,13 @@
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/iterator_range.hpp>
|
||||
#include <boost/fusion/include/copy.hpp>
|
||||
#include <boost/fusion/include/advance.hpp>
|
||||
#include <boost/fusion/include/back.hpp>
|
||||
#include <boost/fusion/include/iterator_range.hpp>
|
||||
#include <boost/fusion/include/nview.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/include/map.hpp>
|
||||
#include <boost/fusion/include/as_map.hpp>
|
||||
#include <boost/fusion/include/at_key.hpp>
|
||||
#include <boost/fusion/include/filter_view.hpp>
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
|
||||
namespace fusion = boost::fusion;
|
||||
@@ -82,8 +74,8 @@ struct PseudoScale {
|
||||
//type to allow a metaprogramming check for a Equation
|
||||
struct EQ {};
|
||||
|
||||
template<typename Seq, typename T>
|
||||
struct pushed_seq;
|
||||
//template<typename Seq, typename T>
|
||||
//struct pushed_seq;
|
||||
|
||||
//metafunctions to retrieve the options of an equation
|
||||
template<typename T>
|
||||
@@ -112,66 +104,17 @@ struct constraint_sequence : public seq {
|
||||
std::cout<<"pretty: "<<__PRETTY_FUNCTION__<<std::endl;
|
||||
};
|
||||
|
||||
//an equation gets added to this sequence
|
||||
template<typename T>
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<seq, T>::type Sequence;
|
||||
typedef typename fusion::result_of::begin<Sequence>::type Begin;
|
||||
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<seq, T>::S1>::type >::type EndOld;
|
||||
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//copy the old values into the new sequence
|
||||
Begin b(vec);
|
||||
EndOld eo(vec);
|
||||
|
||||
fusion::iterator_range<Begin, EndOld> range(b, eo);
|
||||
fusion::copy(*this, range);
|
||||
|
||||
//insert this object at the end of the sequence
|
||||
*fusion::find<T>(vec) = val;
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
|
||||
//an sequence gets added to this sequence (happens only if sequenced equations like coincident are used)
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<T, seq>::type Sequence;
|
||||
typedef typename fusion::result_of::begin<Sequence>::type Begin;
|
||||
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<T, seq>::S1>::type >::type EndF;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
Begin b(vec);
|
||||
EndF ef(vec);
|
||||
|
||||
fusion::iterator_range<Begin, EndF> range(b, ef);
|
||||
fusion::copy(val, range);
|
||||
|
||||
//to copy the types of the second sequence is not as easy as before. If types were already present in
|
||||
//the original sequence they are not added again. therefore we need to find all types of the second sequence
|
||||
//in the new one and assign the objects to this positions.
|
||||
|
||||
//get a index vector for all second-sequence-elements
|
||||
typedef typename mpl::transform<typename pushed_seq<T, seq>::S2,
|
||||
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
|
||||
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
|
||||
|
||||
//and copy the types in
|
||||
fusion::nview<Sequence, position_vector> view(vec);
|
||||
fusion::copy(*this, view);
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
//dont allow expression equation stacking: the compile time impact is huge if we want to allow
|
||||
//text parsing
|
||||
/*
|
||||
//an equation gets added to this sequence
|
||||
template<typename T>
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type operator &(T& val);
|
||||
|
||||
//an sequence gets added to this sequence (happens only if sequenced equations like coincident are used)
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type operator &(T& val);
|
||||
*/
|
||||
//we also allow to set values directly into the equation, as this makes it more compftable for multi constraints
|
||||
//as align. Note that this only works if all option types of all equations in this sequence are distinguishable
|
||||
template<typename T>
|
||||
@@ -182,6 +125,13 @@ struct constraint_sequence : public seq {
|
||||
fusion::front(view) = val;
|
||||
return *this;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
struct get_equation_id {
|
||||
typedef typename T::ID type;
|
||||
};
|
||||
|
||||
template<typename Seq, typename T>
|
||||
@@ -191,12 +141,13 @@ struct pushed_seq {
|
||||
|
||||
typedef typename mpl::fold< S2, S1, mpl::if_< boost::is_same<
|
||||
mpl::find<mpl::_1, mpl::_2>, mpl::end<mpl::_1> >, mpl::push_back<mpl::_1,mpl::_2>, mpl::_1> >::type unique_vector;
|
||||
typedef typename mpl::sort<unique_vector, mpl::less< get_equation_id<mpl::_1>, get_equation_id<mpl::_2> > >::type sorted_vector;
|
||||
|
||||
typedef typename fusion::result_of::as_vector< unique_vector >::type vec;
|
||||
typedef typename fusion::result_of::as_vector< sorted_vector >::type vec;
|
||||
typedef constraint_sequence<vec> type;
|
||||
};
|
||||
};*/
|
||||
|
||||
template<typename Derived, typename Option, bool rotation_only = false>
|
||||
template<typename Derived, typename Option, int id, bool rotation_only = false>
|
||||
struct Equation : public EQ {
|
||||
|
||||
typedef typename mpl::if_<mpl::is_sequence<Option>, Option, mpl::vector<Option> >::type option_sequence;
|
||||
@@ -206,17 +157,7 @@ struct Equation : public EQ {
|
||||
options values;
|
||||
bool pure_rotation;
|
||||
|
||||
struct option_copy {
|
||||
|
||||
options* values;
|
||||
option_copy(options& op) : values(&op) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& val) const {
|
||||
if(val.second.first)
|
||||
fusion::at_key<typename T::first_type>(*values) = val.second;
|
||||
};
|
||||
};
|
||||
typedef mpl::int_<id> ID;
|
||||
|
||||
Equation() : pure_rotation(rotation_only) {};
|
||||
|
||||
@@ -227,111 +168,49 @@ struct Equation : public EQ {
|
||||
fusion::at_key<T>(values).first = true;
|
||||
return *(static_cast<Derived*>(this));
|
||||
};
|
||||
|
||||
//assign option
|
||||
template<typename T>
|
||||
typename boost::enable_if<fusion::result_of::has_key<options, T>, Derived&>::type operator=(const T& val) {
|
||||
return operator()(val);
|
||||
};
|
||||
|
||||
//assign complete equation (we need to override the operator= in the derived class anyway as it
|
||||
//is automaticly created by the compiler, so we use a different name here to avoid duplicate
|
||||
//operator= warning on msvc)
|
||||
Derived& assign(const Derived& eq) {
|
||||
Derived& assign(const Derived& eq);
|
||||
|
||||
//we only copy the values which were set and are therefore valid
|
||||
option_copy oc(values);
|
||||
fusion::for_each(eq.values, oc);
|
||||
|
||||
//the assigned eqution can be set back to default for convinience in further usage
|
||||
const_cast<Derived*>(&eq)->setDefault();
|
||||
|
||||
return *static_cast<Derived*>(this);
|
||||
};
|
||||
//dont allow expression equation stacking: the compile time impact is huge if we want to allow
|
||||
//text parsing
|
||||
/*
|
||||
Derived& operator=(const Derived& eq) {
|
||||
option_copy oc(values);
|
||||
fusion::for_each(eq.values, oc);
|
||||
return *static_cast<Derived*>(this);
|
||||
};*/
|
||||
|
||||
//an equation gets added to this equation
|
||||
template<typename T>
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val) {
|
||||
|
||||
typename pushed_seq<T, Derived>::type vec;
|
||||
*fusion::find<T>(vec) = val;
|
||||
*fusion::find<Derived>(vec) = *(static_cast<Derived*>(this));
|
||||
return vec;
|
||||
};
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val);
|
||||
|
||||
//an sequence gets added to this equation (happens only if sequenced equations like coincident are used)
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<T, Derived>::type Sequence;
|
||||
typedef typename fusion::result_of::begin<Sequence>::type Begin;
|
||||
typedef typename fusion::result_of::find<Sequence, typename fusion::result_of::back<typename pushed_seq<T, Derived>::S1>::type >::type EndOld;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//copy the old values into the new sequence
|
||||
Begin b(vec);
|
||||
EndOld eo(vec);
|
||||
|
||||
fusion::iterator_range<Begin, EndOld> range(b, eo);
|
||||
fusion::copy(val, range);
|
||||
|
||||
//insert this object at the end of the sequence
|
||||
*fusion::find<Derived>(vec) = *static_cast<Derived*>(this);
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type operator &(T& val);
|
||||
*/
|
||||
|
||||
//set default option values, neeeded for repedability and to prevent unexpected behaviour
|
||||
virtual void setDefault() = 0;
|
||||
};
|
||||
|
||||
//convinience stream functions for debugging
|
||||
template <typename charT, typename traits>
|
||||
struct print_pair {
|
||||
std::basic_ostream<charT,traits>* stream;
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& t) const {
|
||||
*stream << "("<<t.second.first << ", "<<t.second.second<<") ";
|
||||
};
|
||||
};
|
||||
|
||||
template <typename charT, typename traits, typename Eq>
|
||||
typename boost::enable_if<boost::is_base_of<EQ, Eq>, std::basic_ostream<charT,traits>&>::type
|
||||
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation)
|
||||
{
|
||||
print_pair<charT, traits> pr;
|
||||
pr.stream = &stream;
|
||||
stream << typeid(equation).name() << ": ";
|
||||
fusion::for_each(equation.values, pr);
|
||||
return stream;
|
||||
}
|
||||
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation);
|
||||
|
||||
struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace> > {
|
||||
struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace>, 1 > {
|
||||
|
||||
using Equation::operator=;
|
||||
using Equation::options;
|
||||
Distance() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
Distance();
|
||||
|
||||
//override needed ass assignmend operator is always created by the compiler
|
||||
//and we need to ensure that our custom one is used
|
||||
Distance& operator=(const Distance& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
Distance& operator=(const Distance& d);
|
||||
|
||||
void setDefault() {
|
||||
fusion::at_key<double>(values) = std::make_pair(false, 0.);
|
||||
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
|
||||
};
|
||||
void setDefault();
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type {
|
||||
@@ -388,23 +267,17 @@ struct Distance : public Equation<Distance, mpl::vector2<double, SolutionSpace>
|
||||
};
|
||||
};
|
||||
|
||||
struct Orientation : public Equation<Orientation, Direction, true> {
|
||||
struct Orientation : public Equation<Orientation, Direction, 2, true> {
|
||||
|
||||
using Equation::operator=;
|
||||
using Equation::options;
|
||||
Orientation() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
Orientation();
|
||||
|
||||
//override needed ass assignmend operator is always created by the compiler
|
||||
//and we need to ensure that our custom one is used
|
||||
Orientation& operator=(const Orientation& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
Orientation& operator=(const Orientation& d);
|
||||
|
||||
void setDefault() {
|
||||
fusion::at_key<Direction>(values) = std::make_pair(false, parallel);
|
||||
};
|
||||
void setDefault();
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type : public PseudoScale<Kernel> {
|
||||
@@ -454,24 +327,17 @@ struct Orientation : public Equation<Orientation, Direction, true> {
|
||||
};
|
||||
};
|
||||
|
||||
struct Angle : public Equation<Angle, mpl::vector2<double, SolutionSpace>, true> {
|
||||
struct Angle : public Equation<Angle, mpl::vector2<double, SolutionSpace>, 3, true> {
|
||||
|
||||
using Equation::operator=;
|
||||
|
||||
Angle() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
Angle();
|
||||
|
||||
//override needed ass assignmend operator is always created by the compiler
|
||||
//and we need to ensure that our custom one is used
|
||||
Angle& operator=(const Angle& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
Angle& operator=(const Angle& d);
|
||||
|
||||
void setDefault() {
|
||||
fusion::at_key<double>(values) = std::make_pair(false, 0.);
|
||||
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
|
||||
};
|
||||
void setDefault();
|
||||
|
||||
template< typename Kernel, typename Tag1, typename Tag2 >
|
||||
struct type : public PseudoScale<Kernel> {
|
||||
@@ -530,6 +396,10 @@ static Angle angle;
|
||||
|
||||
};
|
||||
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/equations_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_EQUATIONS_H
|
||||
|
||||
|
||||
|
||||
@@ -27,21 +27,11 @@
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
@@ -49,12 +39,7 @@
|
||||
#include "logging.hpp"
|
||||
#include "transformation.hpp"
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
#include <boost/math/special_functions.hpp>
|
||||
#endif
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
@@ -358,216 +343,10 @@ public:
|
||||
virtual void removed() = 0;
|
||||
};
|
||||
|
||||
} //details
|
||||
} //dcm
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
Geometry<Kernel, Dim, TagList>::Geometry()
|
||||
: m_isInCluster(false), m_parameter(NULL,0,DS(0,0)),
|
||||
m_clusterFixed(false), m_init(false) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry"));
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/geometry_imp.hpp"
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::transform(const Transform& t) {
|
||||
|
||||
if(m_isInCluster)
|
||||
transform(t, m_toplocal);
|
||||
else
|
||||
if(m_init)
|
||||
transform(t, m_rotated);
|
||||
else
|
||||
transform(t, m_global);
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename tag>
|
||||
void Geometry<Kernel, Dim, TagList>::init() {
|
||||
|
||||
m_BaseParameterCount = tag::parameters::value;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
m_rotations = tag::rotations::value;
|
||||
m_translations = tag::translations::value;
|
||||
|
||||
m_toplocal.setZero(m_parameterCount);
|
||||
m_global.resize(m_parameterCount);
|
||||
m_rotated.resize(m_parameterCount);
|
||||
m_rotated.setZero();
|
||||
|
||||
m_diffparam.resize(m_parameterCount,6);
|
||||
m_diffparam.setZero();
|
||||
|
||||
m_general_type = tag::weight::value;
|
||||
m_exact_type = mpl::find<TagList, tag>::type::pos::value;
|
||||
|
||||
normalize();
|
||||
|
||||
//new value which is not set into parameter, so init is false
|
||||
m_init = false;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init: "<<m_global.transpose();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::normalize() {
|
||||
//directions are not nessessarily normalized, but we need to ensure this in cluster mode
|
||||
for(int i=m_translations; i!=m_rotations; i++)
|
||||
m_global.template segment<Dim>(i*Dim).normalize();
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
typename Kernel::VectorMap& Geometry<Kernel, Dim, TagList>::getParameterMap() {
|
||||
m_isInCluster = false;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
return m_parameter;
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename T>
|
||||
void Geometry<Kernel, Dim, TagList>::linkTo(boost::shared_ptr<Geometry<Kernel, Dim, TagList> > geom, int offset) {
|
||||
|
||||
init<T>();
|
||||
m_link = geom;
|
||||
m_link_offset = offset;
|
||||
m_global = geom->m_global.segment(offset, m_BaseParameterCount);
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::initMap(typename Kernel::MappedEquationSystem* mes) {
|
||||
|
||||
//check should not be needed, but how knows...
|
||||
if(!m_init) {
|
||||
|
||||
if(!isLinked()) {
|
||||
m_offset = mes->setParameterMap(m_parameterCount, getParameterMap());
|
||||
m_parameter = m_global;
|
||||
m_init = true;
|
||||
}
|
||||
else {
|
||||
//it's important that the linked geometry is initialised, as we going to access its parameter map
|
||||
if(!m_link->isInitialised())
|
||||
m_link->initMap(mes);
|
||||
|
||||
m_offset = m_link->m_offset + m_link_offset;
|
||||
new(&getParameterMap()) typename Kernel::VectorMap(&m_link->getParameterMap()(m_link_offset), m_parameterCount, typename Kernel::DynStride(1,1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::setClusterMode(bool iscluster, bool isFixed) {
|
||||
|
||||
m_isInCluster = iscluster;
|
||||
m_clusterFixed = isFixed;
|
||||
if(iscluster) {
|
||||
//we are in cluster, therfore the parameter map should not point to a solver value but to
|
||||
//the rotated original value;
|
||||
new(&m_parameter) typename Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1));
|
||||
//the local value is the global one as no transformation was applied yet
|
||||
m_toplocal = m_global;
|
||||
m_rotated = m_global;
|
||||
}
|
||||
else
|
||||
new(&m_parameter) typename Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::recalculate(DiffTransform& trans) {
|
||||
if(!m_isInCluster)
|
||||
return;
|
||||
|
||||
for(int i=0; i!=m_rotations; i++) {
|
||||
//first rotate the original to the transformed value
|
||||
m_rotated.block(i*Dim,0,Dim,1) = trans.rotation()*m_toplocal.template segment<Dim>(i*Dim);
|
||||
|
||||
//now calculate the gradient vectors and add them to diffparam
|
||||
for(int j=0; j<Dim; j++)
|
||||
m_diffparam.block(i*Dim,j,Dim,1) = trans.differential().block(0,j*3,Dim,Dim) * m_toplocal.template segment<Dim>(i*Dim);
|
||||
}
|
||||
//after rotating the needed parameters we translate the stuff that needs to be moved
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
m_rotated.block(i*Dim,0,Dim,1) += trans.translation().vector();
|
||||
m_rotated.block(i*Dim,0,Dim,1) *= trans.scaling().factor();
|
||||
//calculate the gradient vectors and add them to diffparam
|
||||
m_diffparam.block(i*Dim,Dim,Dim,Dim).setIdentity();
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isnormal(m_rotated.norm()) || !boost::math::isnormal(m_diffparam.norm())) {
|
||||
BOOST_LOG(log) << "Unnormal recalculated value detected: "<<m_rotated.transpose()<<std::endl
|
||||
<< "or unnormal recalculated diff detected: "<<std::endl<<m_diffparam<<std::endl
|
||||
<<" with Transform: "<<std::endl<<trans;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::finishCalculation() {
|
||||
//if fixed nothing needs to be changed
|
||||
if(m_isInCluster) {
|
||||
//recalculate(1.); //remove scaling to get right global value
|
||||
m_global = m_rotated;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish cluster calculation";
|
||||
#endif
|
||||
}
|
||||
//TODO:non cluster paramter scaling
|
||||
else {
|
||||
m_global = m_parameter;
|
||||
normalize();
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
};
|
||||
|
||||
m_init = false;
|
||||
m_isInCluster = false;
|
||||
|
||||
recalculated();
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename VectorType>
|
||||
void Geometry<Kernel, Dim, TagList>::transform(const Transform& t, VectorType& vec) {
|
||||
|
||||
//everything that needs to be translated needs to be fully transformed
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t*v;
|
||||
}
|
||||
|
||||
for(int i=m_translations; i!=m_rotations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t.rotate(v);
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Transformed with cluster: "<<m_isInCluster
|
||||
<< ", init: "<<m_init<<" into: "<< vec.transpose();
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::scale(Scalar value) {
|
||||
|
||||
for(int i=0; i!=m_translations; i++)
|
||||
m_parameter.template segment<Dim>(i*Dim) *= 1./value;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GCM_GEOMETRY_H
|
||||
|
||||
1220
src/Mod/Assembly/App/opendcm/core/imp/clustergraph_imp.hpp
Normal file
1220
src/Mod/Assembly/App/opendcm/core/imp/clustergraph_imp.hpp
Normal file
File diff suppressed because it is too large
Load Diff
449
src/Mod/Assembly/App/opendcm/core/imp/constraint_holder_imp.hpp
Normal file
449
src/Mod/Assembly/App/opendcm/core/imp/constraint_holder_imp.hpp
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CONSTRAINT_HOLDER_IMP_H
|
||||
#define DCM_CONSTRAINT_HOLDER_IMP_H
|
||||
|
||||
#include "opendcm/core/constraint.hpp"
|
||||
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::OptionSetter::OptionSetter(Objects& val) : objects(val) {};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template<typename T>
|
||||
typename boost::enable_if<typename Constraint<Sys, Dim>::template holder<ConstraintVector, tag1, tag2>::template has_option<T>::type, void>::type
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
//get the index of the corresbonding equation
|
||||
typedef typename mpl::find<EquationVector, T>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<EquationVector>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<EquationVector>::type > >));
|
||||
fusion::copy(fusion::at<distance>(objects).values, val.m_eq.values);
|
||||
val.pure_rotation = fusion::at<distance>(objects).pure_rotation;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template<typename T>
|
||||
typename boost::enable_if<mpl::not_<typename Constraint<Sys, Dim>::template holder<ConstraintVector, tag1, tag2>::template has_option<T>::type>, void>::type
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::OptionSetter::operator()(EquationSet<T>& val) const {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only)
|
||||
: first(f), second(s), scale(sc), rot_only(rotation_only) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Calculater::operator()(T& val) const {
|
||||
|
||||
//if the equation is disabled we don't have anything mapped so avoid accessing it
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//if we only need pure rotational functions and we are not such a nice thing, everything becomes 0
|
||||
if(rot_only && !val.pure_rotation) {
|
||||
|
||||
val.m_residual(0) = 0;
|
||||
if(first->getClusterMode()) {
|
||||
if(!first->isClusterFixed()) {
|
||||
val.m_diff_first_rot.setZero();
|
||||
val.m_diff_first.setZero();
|
||||
}
|
||||
}
|
||||
else
|
||||
val.m_diff_first.setZero();
|
||||
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
val.m_diff_second_rot.setZero();
|
||||
val.m_diff_second.setZero();
|
||||
}
|
||||
}
|
||||
else
|
||||
val.m_diff_second.setZero();
|
||||
|
||||
}
|
||||
//we need to calculate, so lets go for it!
|
||||
else {
|
||||
|
||||
val.m_eq.setScale(scale);
|
||||
|
||||
val.m_residual(0) = val.m_eq.calculate(first->m_parameter, second->m_parameter);
|
||||
|
||||
//now see which way we should calculate the gradient (may be diffrent for both geometries)
|
||||
if(first->m_parameterCount) {
|
||||
if(first->getClusterMode()) {
|
||||
//when the cluster is fixed no maps are set as no parameters exist.
|
||||
if(!first->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_first_rot(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, first->m_diffparam.col(i));
|
||||
}
|
||||
//and now with the translations
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_first(i) = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, first->m_diffparam.col(i+3));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientFirstComplete(first->m_parameter, second->m_parameter, val.m_diff_first);
|
||||
}
|
||||
}
|
||||
if(second->m_parameterCount) {
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
|
||||
//cluster mode, so we do a full calculation with all 3 rotation diffparam vectors
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_second_rot(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
|
||||
second->m_parameter, second->m_diffparam.col(i));
|
||||
}
|
||||
//and the translation seperated
|
||||
for(int i=0; i<3; i++) {
|
||||
val.m_diff_second(i) = val.m_eq.calculateGradientSecond(first->m_parameter,
|
||||
second->m_parameter, second->m_diffparam.col(i+3));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//not in cluster, so allow the constraint to optimize the gradient calculation
|
||||
val.m_eq.calculateGradientSecondComplete(first->m_parameter, second->m_parameter, val.m_diff_second);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s)
|
||||
: mes(m), first(f), second(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::MapSetter::operator()(T& val) const {
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//when in cluster, there are 6 clusterparameter we differentiat for, if not we differentiat
|
||||
//for every parameter in the geometry;
|
||||
int equation = mes.setResidualMap(val.m_residual);
|
||||
if(first->getClusterMode()) {
|
||||
if(!first->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, first->m_offset_rot, 3, val.m_diff_first_rot);
|
||||
mes.setJacobiMap(equation, first->m_offset, 3, val.m_diff_first);
|
||||
}
|
||||
}
|
||||
else
|
||||
mes.setJacobiMap(equation, first->m_offset, first->m_parameterCount, val.m_diff_first);
|
||||
|
||||
|
||||
if(second->getClusterMode()) {
|
||||
if(!second->isClusterFixed()) {
|
||||
mes.setJacobiMap(equation, second->m_offset_rot, 3, val.m_diff_second_rot);
|
||||
mes.setJacobiMap(equation, second->m_offset, 3, val.m_diff_second);
|
||||
}
|
||||
}
|
||||
else
|
||||
mes.setJacobiMap(equation, second->m_offset, second->m_parameterCount, val.m_diff_second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2)
|
||||
: first(f), second(s), points1(vec1), points2(vec2) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::PseudoCollector::operator()(T& val) const {
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
if(first->m_isInCluster && second->m_isInCluster) {
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, second->m_rotated, points2);
|
||||
}
|
||||
else if(first->m_isInCluster) {
|
||||
typename Kernel::Vector sec = second->m_parameter;
|
||||
val.m_eq.calculatePseudo(first->m_rotated, points1, sec, points2);
|
||||
}
|
||||
else if(second->m_isInCluster) {
|
||||
typename Kernel::Vector fir = first->m_parameter;
|
||||
val.m_eq.calculatePseudo(fir, points1, second->m_rotated, points2);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::LGZ::LGZ(geom_ptr f, geom_ptr s)
|
||||
: first(f), second(s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::LGZ::operator()(T& val) const {
|
||||
|
||||
typedef typename Sys::Kernel Kernel;
|
||||
|
||||
if(!val.enabled)
|
||||
return;
|
||||
|
||||
//to treat local gradient zeros we calculate a approximate second derivative of the equations
|
||||
//only do that if neseccary: residual is not zero
|
||||
if(!Kernel::isSame(val.m_residual(0),0, 1e-7)) { //TODO: use exact precission and scale value
|
||||
|
||||
//rotations exist only in cluster
|
||||
if(first->getClusterMode() && !first->isClusterFixed()) {
|
||||
//LGZ exists for rotations only
|
||||
for(int i=0; i<3; i++) {
|
||||
|
||||
//only treat if the gradient realy is zero
|
||||
if(Kernel::isSame(val.m_diff_first_rot(i), 0, 1e-7)) {
|
||||
|
||||
//to get the approximated second derivative we need the slightly moved geometrie
|
||||
const typename Kernel::Vector p_old = first->m_parameter;
|
||||
first->m_parameter += first->m_diffparam.col(i)*1e-3;
|
||||
first->normalize();
|
||||
//with this changed geometrie we test if a gradient exist now
|
||||
typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1));
|
||||
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
first->m_parameter = p_old;
|
||||
|
||||
//let's see if the initial LGZ was a real one
|
||||
if(!Kernel::isSame(res, 0, 1e-7)) {
|
||||
|
||||
//is a fake zero, let's correct it
|
||||
val.m_diff_first_rot(i) = res;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
//and the same for the second one too
|
||||
if(second->getClusterMode() && !second->isClusterFixed()) {
|
||||
|
||||
for(int i=0; i<3; i++) {
|
||||
|
||||
//only treat if the gradient realy is zero
|
||||
if(Kernel::isSame(val.m_diff_second_rot(i), 0, 1e-7)) {
|
||||
|
||||
//to get the approximated second derivative we need the slightly moved geometrie
|
||||
const typename Kernel::Vector p_old = second->m_parameter;
|
||||
second->m_parameter += second->m_diffparam.col(i)*1e-3;
|
||||
second->normalize();
|
||||
//with this changed geometrie we test if a gradient exist now
|
||||
typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1));
|
||||
typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter,
|
||||
second->m_parameter, block);
|
||||
second->m_parameter = p_old;
|
||||
|
||||
//let's see if the initial LGZ was a real one
|
||||
if(!Kernel::isSame(res, 0, 1e-7)) {
|
||||
|
||||
//is a fake zero, let's correct it
|
||||
val.m_diff_second_rot(i) = res;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericEquations::GenericEquations(std::vector<boost::any>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericEquations::operator()(T& val) const {
|
||||
vec.push_back(val.m_eq);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericConstraints::GenericConstraints(std::vector<boost::any>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::GenericConstraints::operator()(T& val) const {
|
||||
vec.push_back(val);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Types::Types(std::vector<const std::type_info*>& v)
|
||||
: vec(v) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
template< typename T >
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::Types::operator()(T& val) const {
|
||||
vec.push_back(&typeid(T));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::holder(Objects& obj) : m_objects(obj) {
|
||||
//set the initial values in the equations
|
||||
fusion::for_each(m_sets, OptionSetter(obj));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::calculate(geom_ptr first, geom_ptr second,
|
||||
Scalar scale, bool rotation_only) {
|
||||
fusion::for_each(m_sets, Calculater(first, second, scale, rotation_only));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::treatLGZ(geom_ptr first, geom_ptr second) {
|
||||
fusion::for_each(m_sets, LGZ(first, second));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
typename Constraint<Sys, Dim>::placeholder*
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::resetConstraint(geom_ptr first, geom_ptr second) const {
|
||||
//boost::apply_visitor(creator, first->m_geometry, second->m_geometry);
|
||||
//if(creator.need_swap) first.swap(second);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::setMaps(MES& mes, geom_ptr first, geom_ptr second) {
|
||||
fusion::for_each(m_sets, MapSetter(mes, first, second));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) {
|
||||
fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
typename Constraint<Sys, Dim>::placeholder*
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::clone() {
|
||||
return new holder(*this);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
int Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::equationCount() {
|
||||
int count = 0;
|
||||
EquationCounter counter(count);
|
||||
fusion::for_each(m_sets, counter);
|
||||
return count;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
std::vector<boost::any>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getGenericEquations() {
|
||||
std::vector<boost::any> vec;
|
||||
fusion::for_each(m_sets, GenericEquations(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
std::vector<boost::any>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getGenericConstraints() {
|
||||
std::vector<boost::any> vec;
|
||||
fusion::for_each(m_objects, GenericConstraints(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
std::vector<const std::type_info*>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getEquationTypes() {
|
||||
std::vector<const std::type_info*> vec;
|
||||
mpl::for_each< EquationVector >(Types(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
std::vector<const std::type_info*>
|
||||
Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::getConstraintTypes() {
|
||||
std::vector<const std::type_info*> vec;
|
||||
mpl::for_each< ConstraintVector >(Types(vec));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector, typename tag1, typename tag2>
|
||||
void Constraint<Sys, Dim>::holder<ConstraintVector, tag1, tag2>::disable() {
|
||||
fusion::for_each(m_sets, disabler());
|
||||
};
|
||||
|
||||
};//detail
|
||||
|
||||
};//dcm
|
||||
|
||||
#endif //GCM_CONSTRAINT_H
|
||||
|
||||
|
||||
|
||||
208
src/Mod/Assembly/App/opendcm/core/imp/constraint_imp.hpp
Normal file
208
src/Mod/Assembly/App/opendcm/core/imp/constraint_imp.hpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CONSTRAINT_IMP_H
|
||||
#define DCM_CONSTRAINT_IMP_H
|
||||
|
||||
#include "../constraint.hpp"
|
||||
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initialize(ConstraintVector& cv) {
|
||||
|
||||
//use the compile time unrolling to retrieve the geometry tags
|
||||
initializeFirstGeometry<mpl::int_<0> >(cv, mpl::true_());
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
|
||||
//this function is only for breaking the compilation loop, it should never be called
|
||||
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
|
||||
|
||||
typedef typename Sys::geometries geometries;
|
||||
|
||||
switch(first->getExactType()) {
|
||||
|
||||
#ifdef BOOST_PP_LOCAL_ITERATE
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
case (WhichType::value + n): \
|
||||
return initializeSecondGeometry<boost::mpl::int_<0>,\
|
||||
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
|
||||
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
|
||||
break;
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, 10)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
#endif //BOOST_PP_LOCAL_ITERATE
|
||||
default:
|
||||
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
|
||||
return initializeFirstGeometry<next_which_t, ConstraintVector> (cv,
|
||||
typename mpl::less< next_which_t, typename mpl::size<geometries>::type >::type());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename FirstType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) {
|
||||
//this function is only for breaking the compilation loop, it should never be called
|
||||
BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename WhichType, typename FirstType, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) {
|
||||
|
||||
typedef typename Sys::geometries geometries;
|
||||
switch(second->getExactType()) {
|
||||
|
||||
#ifdef BOOST_PP_LOCAL_ITERATE
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
case (WhichType::value + n): \
|
||||
return intitalizeFinalize<FirstType, \
|
||||
typename mpl::at<geometries, typename in_range_value<geometries, WhichType::value + n>::type >::type,\
|
||||
ConstraintVector>(cv, typename boost::mpl::less<boost::mpl::int_<WhichType::value + n>, boost::mpl::size<geometries> >::type()); \
|
||||
break;
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, 10)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
#endif //BOOST_PP_LOCAL_ITERATE
|
||||
default:
|
||||
typedef typename mpl::int_<WhichType::value + 10> next_which_t;
|
||||
return initializeSecondGeometry<next_which_t, FirstType, ConstraintVector>
|
||||
(cv, typename mpl::less
|
||||
< next_which_t
|
||||
, typename mpl::size<geometries>::type>::type()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename FirstType, typename SecondType, typename ConstraintVector>
|
||||
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_ /*is_unrolled_t*/) {
|
||||
|
||||
initializeFromTags<FirstType, SecondType>(cv);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename FirstType, typename SecondType, typename ConstraintVector>
|
||||
inline void Constraint<Sys, Dim>::intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_ /*is_unrolled_t*/) {
|
||||
//Should never be here at runtime; only required to block code generation that deref's the sequence out of bounds
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
template<typename tag1, typename tag2, typename ConstraintVector>
|
||||
void Constraint<Sys, Dim>::initializeFromTags(ConstraintVector& v) {
|
||||
|
||||
typedef tag_order< tag1, tag2 > order;
|
||||
|
||||
//and build the placeholder
|
||||
content = new holder<ConstraintVector, typename order::first_tag, typename order::second_tag >(v);
|
||||
|
||||
//geometry order needs to be the one needed by equations
|
||||
if(order::swapt::value)
|
||||
first.swap(second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
Constraint<Sys, Dim>::Constraint(geom_ptr f, geom_ptr s)
|
||||
: first(f), second(s), content(0) {
|
||||
|
||||
//cf = first->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
//cs = second->template connectSignal<reset> (boost::bind(&Constraint::geometryReset, this, _1));
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
Constraint<Sys, Dim>::~Constraint() {
|
||||
delete content;
|
||||
//first->template disconnectSignal<reset>(cf);
|
||||
//second->template disconnectSignal<reset>(cs);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
int Constraint<Sys, Dim>::equationCount() {
|
||||
return content->equationCount();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::calculate(Scalar scale, bool rotation_only) {
|
||||
content->calculate(first, second, scale, rotation_only);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::treatLGZ() {
|
||||
content->treatLGZ(first, second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::setMaps(MES& mes) {
|
||||
content->setMaps(mes, first, second);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
void Constraint<Sys, Dim>::collectPseudoPoints(Vec& vec1, Vec& vec2) {
|
||||
content->collectPseudoPoints(first, second, vec1, vec2);
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<boost::any> Constraint<Sys, Dim>::getGenericEquations() {
|
||||
return content->getGenericEquations();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<boost::any> Constraint<Sys, Dim>::getGenericConstraints() {
|
||||
return content->getGenericConstraints();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<const std::type_info*> Constraint<Sys, Dim>::getEquationTypes() {
|
||||
return content->getEquationTypes();
|
||||
};
|
||||
|
||||
template<typename Sys, int Dim>
|
||||
std::vector<const std::type_info*> Constraint<Sys, Dim>::getConstraintTypes() {
|
||||
return content->getConstraintTypes();
|
||||
};
|
||||
|
||||
};//detail
|
||||
|
||||
};//dcm
|
||||
|
||||
#endif //GCM_CONSTRAINT_H
|
||||
|
||||
|
||||
|
||||
255
src/Mod/Assembly/App/opendcm/core/imp/equations_imp.hpp
Normal file
255
src/Mod/Assembly/App/opendcm/core/imp/equations_imp.hpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more detemplate tails.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EQUATIONS_IMP_H
|
||||
#define DCM_EQUATIONS_IMP_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../equations.hpp"
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/sort.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/iterator_range.hpp>
|
||||
#include <boost/fusion/include/copy.hpp>
|
||||
#include <boost/fusion/include/advance.hpp>
|
||||
#include <boost/fusion/include/back.hpp>
|
||||
#include <boost/fusion/include/iterator_range.hpp>
|
||||
#include <boost/fusion/include/nview.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/fusion/include/map.hpp>
|
||||
#include <boost/fusion/include/as_map.hpp>
|
||||
#include <boost/fusion/include/filter_view.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
|
||||
namespace fusion = boost::fusion;
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Seq, typename T>
|
||||
struct pushed_seq;
|
||||
|
||||
/*
|
||||
template<typename seq>
|
||||
template<typename T>
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<seq, T>::type >::type
|
||||
constraint_sequence<seq>::operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<seq, T>::type Sequence;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//get a index vector for this sequence
|
||||
typedef typename mpl::transform<typename pushed_seq<seq, T>::S1,
|
||||
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
|
||||
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector_added;
|
||||
|
||||
//and copy the types in
|
||||
fusion::nview<Sequence, position_vector_added> view_added(vec);
|
||||
fusion::copy(*this, view_added);
|
||||
|
||||
//insert this object at the end of the sequence
|
||||
*fusion::find<T>(vec) = val;
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename seq>
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, seq>::type >::type
|
||||
constraint_sequence<seq>::operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<T, seq>::type Sequence;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//get a index vector for the added sequence
|
||||
typedef typename mpl::transform<typename pushed_seq<T, seq>::S1,
|
||||
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
|
||||
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector_added;
|
||||
|
||||
//and copy the types in
|
||||
fusion::nview<Sequence, position_vector_added> view_added(vec);
|
||||
fusion::copy(val, view_added);
|
||||
|
||||
//to copy the types of the second sequence is not as easy as before. If types were already present in
|
||||
//the original sequence they are not added again. therefore we need to find all types of the second sequence
|
||||
//in the new one and assign the objects to this positions.
|
||||
|
||||
//get a index vector for all second-sequence-elements
|
||||
typedef typename mpl::transform<typename pushed_seq<T, seq>::S2,
|
||||
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
|
||||
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
|
||||
|
||||
//and copy the types in
|
||||
fusion::nview<Sequence, position_vector> view(vec);
|
||||
fusion::copy(*this, view);
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
*/
|
||||
template<typename options>
|
||||
struct option_copy {
|
||||
|
||||
options* values;
|
||||
option_copy(options& op) : values(&op) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& val) const {
|
||||
if(val.second.first)
|
||||
fusion::at_key<typename T::first_type>(*values) = val.second;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Derived, typename Option, int id, bool rotation_only >
|
||||
Derived& Equation<Derived, Option, id, rotation_only>::assign(const Derived& eq) {
|
||||
|
||||
//we only copy the values which were set and are therefore valid
|
||||
option_copy<options> oc(values);
|
||||
fusion::for_each(eq.values, oc);
|
||||
|
||||
//the assigned eqution can be set back to default for convinience in further usage
|
||||
const_cast<Derived*>(&eq)->setDefault();
|
||||
|
||||
return *static_cast<Derived*>(this);
|
||||
};
|
||||
|
||||
/*
|
||||
template<typename Derived, typename Option, int id, bool rotation_only >
|
||||
template<typename T>
|
||||
typename boost::enable_if< boost::is_base_of< dcm::EQ, T>, typename pushed_seq<T, Derived>::type >::type
|
||||
Equation<Derived, Option, id, rotation_only>::operator &(T& val) {
|
||||
|
||||
typename pushed_seq<T, Derived>::type vec;
|
||||
*fusion::find<T>(vec) = val;
|
||||
*fusion::find<Derived>(vec) = *(static_cast<Derived*>(this));
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Derived, typename Option, int id, bool rotation_only >
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::is_sequence<T>, typename pushed_seq<T, Derived>::type >::type
|
||||
Equation<Derived, Option, id, rotation_only>::operator &(T& val) {
|
||||
|
||||
typedef typename pushed_seq<T, Derived>::type Sequence;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//get a index vector for the added sequence
|
||||
typedef typename mpl::transform<typename pushed_seq<T, Derived>::S1,
|
||||
fusion::result_of::distance<typename fusion::result_of::begin<Sequence>::type,
|
||||
fusion::result_of::find<Sequence, mpl::_1> > >::type position_vector;
|
||||
|
||||
//and copy the types in
|
||||
fusion::nview<Sequence, position_vector> view(vec);
|
||||
fusion::copy(val, view);
|
||||
|
||||
//insert this object into the sequence
|
||||
*fusion::find<Derived>(vec) = *static_cast<Derived*>(this);
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
*/
|
||||
|
||||
template<typename Derived, typename Option, int id, bool rotation_only >
|
||||
void Equation<Derived, Option, id, rotation_only>::setDefault() {
|
||||
fusion::at_key<double>(values) = std::make_pair(false, 0.);
|
||||
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
|
||||
};
|
||||
|
||||
//convinience stream functions for debugging
|
||||
template <typename charT, typename traits>
|
||||
struct print_pair {
|
||||
std::basic_ostream<charT,traits>* stream;
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& t) const {
|
||||
*stream << "("<<t.second.first << ", "<<t.second.second<<") ";
|
||||
};
|
||||
};
|
||||
|
||||
template <typename charT, typename traits, typename Eq>
|
||||
typename boost::enable_if<boost::is_base_of<EQ, Eq>, std::basic_ostream<charT,traits>&>::type
|
||||
operator << (std::basic_ostream<charT,traits>& stream, const Eq& equation)
|
||||
{
|
||||
print_pair<charT, traits> pr;
|
||||
pr.stream = &stream;
|
||||
stream << typeid(equation).name() << ": ";
|
||||
fusion::for_each(equation.values, pr);
|
||||
return stream;
|
||||
}
|
||||
|
||||
Distance::Distance() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
|
||||
Distance& Distance::operator=(const Distance& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
|
||||
void Distance::setDefault() {};
|
||||
|
||||
|
||||
|
||||
Orientation::Orientation() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
|
||||
Orientation& Orientation::operator=(const Orientation& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
|
||||
void Orientation::setDefault() {
|
||||
fusion::at_key<Direction>(values) = std::make_pair(false, parallel);
|
||||
};
|
||||
|
||||
Angle::Angle() : Equation() {
|
||||
setDefault();
|
||||
};
|
||||
|
||||
Angle& Angle::operator=(const Angle& d) {
|
||||
return Equation::assign(d);
|
||||
};
|
||||
|
||||
void Angle::setDefault() {
|
||||
fusion::at_key<double>(values) = std::make_pair(false, 0.);
|
||||
fusion::at_key<SolutionSpace>(values) = std::make_pair(false, bidirectional);
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //GCM_EQUATIONS_H
|
||||
|
||||
|
||||
266
src/Mod/Assembly/App/opendcm/core/imp/geometry_imp.hpp
Normal file
266
src/Mod/Assembly/App/opendcm/core/imp/geometry_imp.hpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GCM_GEOMETRY_IMP_H
|
||||
#define GCM_GEOMETRY_IMP_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../geometry.hpp"
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
#include <boost/math/special_functions.hpp>
|
||||
#endif
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
Geometry<Kernel, Dim, TagList>::Geometry()
|
||||
: m_isInCluster(false), m_parameter(NULL,0,DS(0,0)),
|
||||
m_clusterFixed(false), m_init(false) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry"));
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::transform(const Transform& t) {
|
||||
|
||||
if(m_isInCluster)
|
||||
transform(t, m_toplocal);
|
||||
else
|
||||
if(m_init)
|
||||
transform(t, m_rotated);
|
||||
else
|
||||
transform(t, m_global);
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename tag>
|
||||
void Geometry<Kernel, Dim, TagList>::init() {
|
||||
|
||||
m_BaseParameterCount = tag::parameters::value;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
m_rotations = tag::rotations::value;
|
||||
m_translations = tag::translations::value;
|
||||
|
||||
m_toplocal.setZero(m_parameterCount);
|
||||
m_global.resize(m_parameterCount);
|
||||
m_rotated.resize(m_parameterCount);
|
||||
m_rotated.setZero();
|
||||
|
||||
m_diffparam.resize(m_parameterCount,6);
|
||||
m_diffparam.setZero();
|
||||
|
||||
m_general_type = tag::weight::value;
|
||||
m_exact_type = mpl::find<TagList, tag>::type::pos::value;
|
||||
|
||||
normalize();
|
||||
|
||||
//new value which is not set into parameter, so init is false
|
||||
m_init = false;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init: "<<m_global.transpose();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::normalize() {
|
||||
//directions are not nessessarily normalized, but we need to ensure this in cluster mode
|
||||
for(int i=m_translations; i!=m_rotations; i++)
|
||||
m_global.template segment<Dim>(i*Dim).normalize();
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
typename Kernel::VectorMap& Geometry<Kernel, Dim, TagList>::getParameterMap() {
|
||||
m_isInCluster = false;
|
||||
m_parameterCount = m_BaseParameterCount;
|
||||
return m_parameter;
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename T>
|
||||
void Geometry<Kernel, Dim, TagList>::linkTo(boost::shared_ptr<Geometry<Kernel, Dim, TagList> > geom, int offset) {
|
||||
|
||||
init<T>();
|
||||
m_link = geom;
|
||||
m_link_offset = offset;
|
||||
m_global = geom->m_global.segment(offset, m_BaseParameterCount);
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::initMap(typename Kernel::MappedEquationSystem* mes) {
|
||||
|
||||
//check should not be needed, but how knows...
|
||||
if(!m_init) {
|
||||
|
||||
if(!isLinked()) {
|
||||
m_offset = mes->setParameterMap(m_parameterCount, getParameterMap());
|
||||
m_parameter = m_global;
|
||||
m_init = true;
|
||||
}
|
||||
else {
|
||||
//it's important that the linked geometry is initialised, as we going to access its parameter map
|
||||
if(!m_link->isInitialised())
|
||||
m_link->initMap(mes);
|
||||
|
||||
m_offset = m_link->m_offset + m_link_offset;
|
||||
new(&getParameterMap()) typename Kernel::VectorMap(&m_link->getParameterMap()(m_link_offset), m_parameterCount, typename Kernel::DynStride(1,1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::setClusterMode(bool iscluster, bool isFixed) {
|
||||
|
||||
m_isInCluster = iscluster;
|
||||
m_clusterFixed = isFixed;
|
||||
if(iscluster) {
|
||||
//we are in cluster, therfore the parameter map should not point to a solver value but to
|
||||
//the rotated original value;
|
||||
new(&m_parameter) typename Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1));
|
||||
//the local value is the global one as no transformation was applied yet
|
||||
m_toplocal = m_global;
|
||||
m_rotated = m_global;
|
||||
}
|
||||
else
|
||||
new(&m_parameter) typename Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1));
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::recalculate(DiffTransform& trans) {
|
||||
if(!m_isInCluster)
|
||||
return;
|
||||
|
||||
for(int i=0; i!=m_rotations; i++) {
|
||||
//first rotate the original to the transformed value
|
||||
m_rotated.block(i*Dim,0,Dim,1) = trans.rotation()*m_toplocal.template segment<Dim>(i*Dim);
|
||||
|
||||
//now calculate the gradient vectors and add them to diffparam
|
||||
for(int j=0; j<Dim; j++)
|
||||
m_diffparam.block(i*Dim,j,Dim,1) = trans.differential().block(0,j*3,Dim,Dim) * m_toplocal.template segment<Dim>(i*Dim);
|
||||
}
|
||||
//after rotating the needed parameters we translate the stuff that needs to be moved
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
m_rotated.block(i*Dim,0,Dim,1) += trans.translation().vector();
|
||||
m_rotated.block(i*Dim,0,Dim,1) *= trans.scaling().factor();
|
||||
//calculate the gradient vectors and add them to diffparam
|
||||
m_diffparam.block(i*Dim,Dim,Dim,Dim).setIdentity();
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isnormal(m_rotated.norm()) || !boost::math::isnormal(m_diffparam.norm())) {
|
||||
BOOST_LOG(log) << "Unnormal recalculated value detected: "<<m_rotated.transpose()<<std::endl
|
||||
<< "or unnormal recalculated diff detected: "<<std::endl<<m_diffparam<<std::endl
|
||||
<<" with Transform: "<<std::endl<<trans;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::finishCalculation() {
|
||||
//if fixed nothing needs to be changed
|
||||
if(m_isInCluster) {
|
||||
//recalculate(1.); //remove scaling to get right global value
|
||||
m_global = m_rotated;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish cluster calculation";
|
||||
#endif
|
||||
}
|
||||
//TODO:non cluster paramter scaling
|
||||
else {
|
||||
m_global = m_parameter;
|
||||
normalize();
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
};
|
||||
|
||||
m_init = false;
|
||||
m_isInCluster = false;
|
||||
|
||||
recalculated();
|
||||
};
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
template<typename VectorType>
|
||||
void Geometry<Kernel, Dim, TagList>::transform(const Transform& t, VectorType& vec) {
|
||||
|
||||
//everything that needs to be translated needs to be fully transformed
|
||||
for(int i=0; i!=m_translations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t*v;
|
||||
}
|
||||
|
||||
for(int i=m_translations; i!=m_rotations; i++) {
|
||||
typename Kernel::Vector3 v = vec.template segment<Dim>(i*Dim);
|
||||
vec.template segment<Dim>(i*Dim) = t.rotate(v);
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Transformed with cluster: "<<m_isInCluster
|
||||
<< ", init: "<<m_init<<" into: "<< vec.transpose();
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Kernel, int Dim, typename TagList>
|
||||
void Geometry<Kernel, Dim, TagList>::scale(Scalar value) {
|
||||
|
||||
for(int i=0; i!=m_translations; i++)
|
||||
m_parameter.template segment<Dim>(i*Dim) *= 1./value;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GCM_GEOMETRY_H
|
||||
512
src/Mod/Assembly/App/opendcm/core/imp/kernel_imp.hpp
Normal file
512
src/Mod/Assembly/App/opendcm/core/imp/kernel_imp.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 details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_KERNEL_IMP_H
|
||||
#define DCM_KERNEL_IMP_H
|
||||
|
||||
#include "../kernel.hpp"
|
||||
#include <boost/math/special_functions.hpp>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Kernel>
|
||||
Dogleg<Kernel>::Dogleg(Kernel* k) : m_kernel(k), tolg(1e-40), tolx(1e-20) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
Dogleg<Kernel>::Dogleg() : tolg(1e-40), tolx(1e-20) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
void Dogleg<Kernel>::setKernel(Kernel* k) {
|
||||
|
||||
m_kernel = k;
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
|
||||
void Dogleg<Kernel>::calculateStep(const Eigen::MatrixBase<Derived>& g, const Eigen::MatrixBase<Derived3>& jacobi,
|
||||
const Eigen::MatrixBase<Derived4>& residual, Eigen::MatrixBase<Derived2>& h_dl,
|
||||
const double delta) {
|
||||
|
||||
// get the steepest descent stepsize and direction
|
||||
const double alpha(g.squaredNorm()/(jacobi*g).squaredNorm());
|
||||
const typename Kernel::Vector h_sd = -g;
|
||||
|
||||
// get the gauss-newton step
|
||||
const typename Kernel::Vector h_gn = (jacobi).fullPivLu().solve(-residual);
|
||||
#ifdef USE_LOGGING
|
||||
|
||||
if(!boost::math::isfinite(h_gn.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal gauss-newton detected: "<<h_gn.norm();
|
||||
}
|
||||
|
||||
if(!boost::math::isfinite(h_sd.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal steepest descent detected: "<<h_sd.norm();
|
||||
}
|
||||
|
||||
if(!boost::math::isfinite(alpha)) {
|
||||
BOOST_LOG(log)<< "Unnormal alpha detected: "<<alpha;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// compute the dogleg step
|
||||
if(h_gn.norm() <= delta) {
|
||||
h_dl = h_gn;
|
||||
}
|
||||
else if((alpha*h_sd).norm() >= delta) {
|
||||
//h_dl = alpha*h_sd;
|
||||
h_dl = (delta/(h_sd.norm()))*h_sd;
|
||||
#ifdef USE_LOGGING
|
||||
|
||||
if(!boost::math::isfinite(h_dl.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg descent detected: "<<h_dl.norm();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
//compute beta
|
||||
number_type beta = 0;
|
||||
typename Kernel::Vector a = alpha*h_sd;
|
||||
typename Kernel::Vector b = h_gn;
|
||||
number_type c = a.transpose()*(b-a);
|
||||
number_type bas = (b-a).squaredNorm(), as = a.squaredNorm();
|
||||
|
||||
if(c<0) {
|
||||
beta = -c+std::sqrt(std::pow(c,2)+bas*(std::pow(delta,2)-as));
|
||||
beta /= bas;
|
||||
}
|
||||
else {
|
||||
beta = std::pow(delta,2)-as;
|
||||
beta /= c+std::sqrt(std::pow(c,2) + bas*(std::pow(delta,2)-as));
|
||||
};
|
||||
|
||||
// and update h_dl and dL with beta
|
||||
h_dl = alpha*h_sd + beta*(b-a);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(c)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg c detected: "<<c;
|
||||
}
|
||||
|
||||
if(!boost::math::isfinite(bas)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg bas detected: "<<bas;
|
||||
}
|
||||
|
||||
if(!boost::math::isfinite(beta)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg beta detected: "<<beta;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
void Dogleg<Kernel>::init(typename Kernel::MappedEquationSystem& sys) {
|
||||
|
||||
if(!sys.isValid())
|
||||
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
|
||||
|
||||
F_old.resize(sys.equationCount());
|
||||
g.resize(sys.equationCount());
|
||||
J_old.resize(sys.equationCount(), sys.parameterCount());
|
||||
|
||||
sys.recalculate();
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "initial jacobi: "<<std::endl<<sys.Jacobi<<std::endl
|
||||
<< "residual: "<<sys.Residual.transpose()<<std::endl
|
||||
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
|
||||
#endif
|
||||
sys.removeLocalGradientZeros();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "LGZ jacobi: "<<std::endl<<sys.Jacobi<<std::endl
|
||||
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
|
||||
#endif
|
||||
|
||||
err = sys.Residual.norm();
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get the infinity norm fx_inf and g_inf
|
||||
g_inf = g.template lpNorm<E::Infinity>();
|
||||
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
delta=5;
|
||||
nu=2.;
|
||||
iter=0;
|
||||
stop=0;
|
||||
reduce=0;
|
||||
unused=0;
|
||||
counter=0;
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, bool continuous) {
|
||||
nothing n;
|
||||
return solve(sys, n, continuous);
|
||||
};
|
||||
|
||||
template<typename Kernel>
|
||||
template<typename Functor>
|
||||
int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale, bool continuous) {
|
||||
|
||||
clock_t start = clock();
|
||||
|
||||
if(!sys.isValid())
|
||||
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
|
||||
|
||||
int maxIterNumber = 5000;//MaxIterations * xsize;
|
||||
number_type diverging_lim = 1e6*err + 1e12;
|
||||
|
||||
do {
|
||||
|
||||
// check if finished
|
||||
if(fx_inf <= m_kernel->template getProperty<precision>()*sys.Scaling) // Success
|
||||
stop = 1;
|
||||
else if(g_inf <= tolg)
|
||||
throw solving_error() << boost::errinfo_errno(2) << error_message("g infinity norm smaller below limit");
|
||||
else if(delta <= tolx)
|
||||
throw solving_error() << boost::errinfo_errno(3) << error_message("step size below limit");
|
||||
else if(iter >= maxIterNumber)
|
||||
throw solving_error() << boost::errinfo_errno(4) << error_message("maximal iterations reached");
|
||||
else if(!boost::math::isfinite(err))
|
||||
throw solving_error() << boost::errinfo_errno(5) << error_message("error is inf or nan");
|
||||
else if(err > diverging_lim)
|
||||
throw solving_error() << boost::errinfo_errno(6) << error_message("error diverged");
|
||||
|
||||
|
||||
// see if we are already finished
|
||||
if(stop)
|
||||
break;
|
||||
|
||||
number_type err_new;
|
||||
number_type dF=0, dL=0;
|
||||
number_type rho;
|
||||
|
||||
//get the update step
|
||||
calculateStep(g, sys.Jacobi, sys.Residual, h_dl, delta);
|
||||
|
||||
// calculate the linear model
|
||||
dL = 0.5*sys.Residual.norm() - 0.5*(sys.Residual + sys.Jacobi*h_dl).norm();
|
||||
|
||||
// get the new values
|
||||
sys.Parameter += h_dl;
|
||||
sys.recalculate();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
|
||||
if(!boost::math::isfinite(sys.Residual.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal residual detected: "<<sys.Residual.norm();
|
||||
}
|
||||
|
||||
if(!boost::math::isfinite(sys.Jacobi.sum())) {
|
||||
BOOST_LOG(log)<< "Unnormal jacobi detected: "<<sys.Jacobi.sum();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//calculate the translation update ratio
|
||||
err_new = sys.Residual.norm();
|
||||
dF = err - err_new;
|
||||
rho = dF/dL;
|
||||
|
||||
if(dF<=0 || dL<=0)
|
||||
rho = -1;
|
||||
|
||||
// update delta
|
||||
if(rho>0.85) {
|
||||
delta = std::max(delta,2*h_dl.norm());
|
||||
nu = 2;
|
||||
}
|
||||
else if(rho < 0.25) {
|
||||
delta = delta/nu;
|
||||
nu = 2*nu;
|
||||
}
|
||||
|
||||
if(dF > 0 && dL > 0) {
|
||||
|
||||
//see if we got too high differentials
|
||||
if(sys.Jacobi.template lpNorm<Eigen::Infinity>() > 2) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "High differential detected: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>()<<" in iteration: "<<iter;
|
||||
#endif
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
}
|
||||
//it can also happen that the differentials get too small, however, we cant check for that
|
||||
else if(iter>1 && (counter>50)) {
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
err = sys.Residual.norm();
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get infinity norms
|
||||
g_inf = g.template lpNorm<E::Infinity>();
|
||||
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
}
|
||||
else {
|
||||
sys.Residual = F_old;
|
||||
sys.Jacobi = J_old;
|
||||
sys.Parameter -= h_dl;
|
||||
unused++;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Reject step in iter "<<iter;
|
||||
#endif
|
||||
}
|
||||
|
||||
iter++;
|
||||
counter++;
|
||||
}
|
||||
while(!stop && continuous);
|
||||
|
||||
|
||||
clock_t end = clock();
|
||||
time = (double(end-start) * 1000.) / double(CLOCKS_PER_SEC);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) <<"Done solving: "<<err<<", iter: "<<iter<<", unused: "<<unused<<", reason:"<< stop;
|
||||
BOOST_LOG(log)<< "final jacobi: "<<std::endl<<sys.Jacobi;
|
||||
#endif
|
||||
|
||||
return stop;
|
||||
}
|
||||
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::parameterCount() {
|
||||
return m_params;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::equationCount() {
|
||||
return m_eqns;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::rotationOnly() {
|
||||
return rot_only;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
Kernel<Scalar, Nonlinear>::MappedEquationSystem::MappedEquationSystem(int params, int equations)
|
||||
: rot_only(false), m_jacobi(equations, params),
|
||||
m_parameter(params), Residual(equations),
|
||||
m_params(params), m_eqns(equations), Scaling(1.),
|
||||
Jacobi(&m_jacobi(0,0),equations,params,DynStride(equations,1)),
|
||||
Parameter(&m_parameter(0),params,DynStride(1,1)) {
|
||||
|
||||
m_param_rot_offset = 0;
|
||||
m_param_trans_offset = params;
|
||||
m_eqn_offset = 0;
|
||||
|
||||
m_jacobi.setZero(); //important as some places are never written
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setParameterMap(int number, VectorMap& map, ParameterType t) {
|
||||
|
||||
if(t == rotation) {
|
||||
new(&map) VectorMap(&m_parameter(m_param_rot_offset), number, DynStride(1,1));
|
||||
m_param_rot_offset += number;
|
||||
return m_param_rot_offset-number;
|
||||
}
|
||||
else {
|
||||
m_param_trans_offset -= number;
|
||||
new(&map) VectorMap(&m_parameter(m_param_trans_offset), number, DynStride(1,1));
|
||||
return m_param_trans_offset;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setParameterMap(Vector3Map& map, ParameterType t) {
|
||||
|
||||
if(t == rotation) {
|
||||
new(&map) Vector3Map(&m_parameter(m_param_rot_offset));
|
||||
m_param_rot_offset += 3;
|
||||
return m_param_rot_offset-3;
|
||||
}
|
||||
else {
|
||||
m_param_trans_offset -= 3;
|
||||
new(&map) Vector3Map(&m_parameter(m_param_trans_offset));
|
||||
return m_param_trans_offset;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::MappedEquationSystem::setResidualMap(VectorMap& map) {
|
||||
new(&map) VectorMap(&Residual(m_eqn_offset), 1, DynStride(1,1));
|
||||
return m_eqn_offset++;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setJacobiMap(int eqn, int offset, int number, CVectorMap& map) {
|
||||
new(&map) CVectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
|
||||
new(&map) VectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::isValid() {
|
||||
if(!m_params || !m_eqns)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setAccess(ParameterType t) {
|
||||
|
||||
if(t==complete) {
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,m_params,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(0),m_params,DynStride(1,1));
|
||||
}
|
||||
else if(t==rotation) {
|
||||
int num = m_param_trans_offset;
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,num,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(0),num,DynStride(1,1));
|
||||
}
|
||||
else if(t==general) {
|
||||
int num = m_params - m_param_trans_offset;
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,m_param_trans_offset),m_eqns,num,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(m_param_trans_offset),num,DynStride(1,1));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
void Kernel<Scalar, Nonlinear>::MappedEquationSystem::setGeneralEquationAccess(bool general) {
|
||||
rot_only = !general;
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
bool Kernel<Scalar, Nonlinear>::MappedEquationSystem::hasParameterType(ParameterType t) {
|
||||
|
||||
if(t==rotation)
|
||||
return (m_param_rot_offset>0);
|
||||
else if(t==general)
|
||||
return (m_param_trans_offset<m_params);
|
||||
else
|
||||
return (m_params>0);
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
Kernel<Scalar, Nonlinear>::Kernel() {
|
||||
//init the solver
|
||||
m_solver.setKernel(this);
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
SolverInfo Kernel<Scalar, Nonlinear>::getSolverInfo() {
|
||||
|
||||
SolverInfo info;
|
||||
info.iterations = m_solver.iter;
|
||||
info.error = m_solver.err;
|
||||
info.time = m_solver.time;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
//static comparison versions
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool Kernel<Scalar, Nonlinear>::isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
|
||||
return ((p1-p2).squaredNorm() < precission);
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
bool Kernel<Scalar, Nonlinear>::isSame(number_type t1, number_type t2, number_type precission) {
|
||||
return (std::abs(t1-t2) < precission);
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool Kernel<Scalar, Nonlinear>::isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
|
||||
return ((p1+p2).squaredNorm() < precission);
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool Kernel<Scalar, Nonlinear>::isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1-p2).squaredNorm() < getProperty<precision>());
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
bool Kernel<Scalar, Nonlinear>::isSame(number_type t1, number_type t2) {
|
||||
return (std::abs(t1-t2) < getProperty<precision>());
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool Kernel<Scalar, Nonlinear>::isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1+p2).squaredNorm() < getProperty<precision>());
|
||||
}
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
int Kernel<Scalar, Nonlinear>::solve(MappedEquationSystem& mes) {
|
||||
|
||||
nothing n;
|
||||
|
||||
if(getProperty<solvermode>()==continuous)
|
||||
m_solver.init(mes);
|
||||
|
||||
return m_solver.solve(mes, n);
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear>
|
||||
template<typename Functor>
|
||||
int Kernel<Scalar, Nonlinear>::solve(MappedEquationSystem& mes, Functor& f) {
|
||||
|
||||
if(getProperty<solvermode>()==continuous)
|
||||
m_solver.init(mes);
|
||||
|
||||
return m_solver.solve(mes, f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_KERNEL_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
115
src/Mod/Assembly/App/opendcm/core/imp/object_imp.hpp
Normal file
115
src/Mod/Assembly/App/opendcm/core/imp/object_imp.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_OBJECT_IMP_H
|
||||
#define GCM_OBJECT_IMP_H
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/key_type.hpp>
|
||||
#include <boost/mpl/value_type.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "../property.hpp"
|
||||
|
||||
#define EMIT_CALL_DEC(z, n, data) \
|
||||
template<typename SigMap> \
|
||||
template < \
|
||||
typename S \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
|
||||
> \
|
||||
void SignalOwner<SigMap>::emitSignal( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
|
||||
) \
|
||||
{ \
|
||||
if(m_emit_signals) {\
|
||||
typedef typename mpl::find<sig_name, S>::type iterator; \
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance; \
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type; \
|
||||
map_type& map = fusion::at<distance>(m_signals); \
|
||||
for (typename map_type::iterator it=map.begin(); it != map.end(); it++) \
|
||||
(it->second)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
|
||||
}\
|
||||
};
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
Object<Sys, Derived, Sig>::Object(Sys& system) : m_system(&system) {};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
boost::shared_ptr<Derived> Object<Sys, Derived, Sig>::clone(Sys& newSys)
|
||||
{
|
||||
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
SignalOwner<SigMap>::SignalOwner() : m_emit_signals(true), m_signal_count(0) {};
|
||||
|
||||
template<typename SigMap>
|
||||
template<typename S>
|
||||
Connection SignalOwner<SigMap>::connectSignal(typename mpl::at<SigMap, S>::type function)
|
||||
{
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type;
|
||||
map_type& map = fusion::at<distance>(m_signals);
|
||||
map[++m_signal_count] = function;
|
||||
return m_signal_count;
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
template<typename S>
|
||||
void SignalOwner<SigMap>::disconnectSignal(Connection c)
|
||||
{
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type;
|
||||
map_type& map = fusion::at<distance>(m_signals);
|
||||
map.erase(c);
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
void SignalOwner<SigMap>::enableSignals(bool onoff)
|
||||
{
|
||||
m_emit_signals = onoff;
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
|
||||
|
||||
}
|
||||
|
||||
#endif //GCM_OBJECT_H
|
||||
|
||||
|
||||
257
src/Mod/Assembly/App/opendcm/core/imp/system_imp.hpp
Normal file
257
src/Mod/Assembly/App/opendcm/core/imp/system_imp.hpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_SYSTEM_IMP_H
|
||||
#define DCM_SYSTEM_IMP_H
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
#include "kernel_imp.hpp"
|
||||
#include "transformation_imp.hpp"
|
||||
#include "clustergraph_imp.hpp"
|
||||
#include "equations_imp.hpp"
|
||||
#endif
|
||||
|
||||
#include "../system.hpp"
|
||||
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct clearer {
|
||||
template<typename T>
|
||||
void operator()(T& vector) const {
|
||||
vector.clear();
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct cloner {
|
||||
|
||||
System& newSys;
|
||||
cloner(System& ns) : newSys(ns) {};
|
||||
|
||||
template<typename T>
|
||||
struct test : mpl::and_<details::is_shared_ptr<T>,
|
||||
mpl::not_<boost::is_same<T, boost::shared_ptr<typename System::Cluster> > > > {};
|
||||
|
||||
template<typename T>
|
||||
typename boost::enable_if< test<T>, void>::type operator()(T& p) const {
|
||||
p = p->clone(newSys);
|
||||
newSys.push_back(p);
|
||||
};
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::not_<test<T> >, void>::type operator()(const T& p) const {};
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
System<KernelType, T1, T2, T3>::System() : m_cluster(new Cluster), m_storage(new Storage)
|
||||
#ifdef USE_LOGGING
|
||||
, sink(init_log())
|
||||
#endif
|
||||
{
|
||||
Type1::system_init(*this);
|
||||
Type2::system_init(*this);
|
||||
Type3::system_init(*this);
|
||||
};
|
||||
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
System<KernelType, T1, T2, T3>::~System() {
|
||||
#ifdef USE_LOGGING
|
||||
stop_log(sink);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
void System<KernelType, T1, T2, T3>::clear() {
|
||||
|
||||
m_cluster->clearClusters();
|
||||
m_cluster->clear();
|
||||
fusion::for_each(*m_storage, clearer());
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator System<KernelType, T1, T2, T3>::begin() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).begin();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator System<KernelType, T1, T2, T3>::end() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).end();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Object>
|
||||
std::vector< boost::shared_ptr<Object> >& System<KernelType, T1, T2, T3>::objectVector() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage);
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Object>
|
||||
void System<KernelType, T1, T2, T3>::push_back(boost::shared_ptr<Object> ptr) {
|
||||
objectVector<Object>().push_back(ptr);
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Object>
|
||||
void System<KernelType, T1, T2, T3>::erase(boost::shared_ptr<Object> ptr) {
|
||||
|
||||
std::vector< boost::shared_ptr<Object> >& vec = objectVector<Object>();
|
||||
vec.erase(std::remove(vec.begin(), vec.end(), ptr), vec.end());
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
SolverInfo System<KernelType, T1, T2, T3>::solve() {
|
||||
clock_t start = clock();
|
||||
m_sheduler.execute(*this);
|
||||
clock_t end = clock();
|
||||
|
||||
SolverInfo info = m_kernel.getSolverInfo();
|
||||
info.time = (double(end-start)* 1000.) / double(CLOCKS_PER_SEC);
|
||||
|
||||
//signal our successful solving
|
||||
BaseType::template emitSignal<solved>(this);
|
||||
|
||||
return info;
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
boost::shared_ptr<System<KernelType, T1, T2, T3> > System<KernelType, T1, T2, T3>::createSubsystem() {
|
||||
|
||||
boost::shared_ptr<System> s = boost::shared_ptr<System>(new System());
|
||||
s->m_cluster = m_cluster->createCluster().first;
|
||||
s->m_storage = m_storage;
|
||||
s->m_cluster->template setProperty<dcm::type_prop>(details::subcluster);
|
||||
#ifdef USE_LOGGING
|
||||
stop_log(s->sink);
|
||||
#endif
|
||||
|
||||
//inform modules that we have a subsystem now
|
||||
Inheriter1::system_sub(s);
|
||||
Inheriter2::system_sub(s);
|
||||
Inheriter3::system_sub(s);
|
||||
|
||||
m_subsystems.push_back(s);
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
typename std::vector<boost::shared_ptr<System<KernelType, T1, T2, T3> > >::iterator System<KernelType, T1, T2, T3>::beginSubsystems() {
|
||||
return m_subsystems.begin();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
typename std::vector<boost::shared_ptr<System<KernelType, T1, T2, T3> > >::iterator System<KernelType, T1, T2, T3>::endSubsystems() {
|
||||
return m_subsystems.end();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Option>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename KernelType::PropertySequence>::type >, typename Option::type& >::type
|
||||
System<KernelType, T1, T2, T3>::getOption() {
|
||||
return m_options.template getProperty<Option>();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Option>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename KernelType::PropertySequence>::type >, typename Option::type& >::type
|
||||
System<KernelType, T1, T2, T3>::getOption() {
|
||||
return m_kernel.template getProperty<Option>();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Option>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename KernelType::PropertySequence>::type >, void >::type
|
||||
System<KernelType, T1, T2, T3>::setOption(typename Option::type value) {
|
||||
m_options.template setProperty<Option>(value);
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Option>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename KernelType::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename KernelType::PropertySequence>::type >, void >::type
|
||||
System<KernelType, T1, T2, T3>::setOption(typename Option::type value) {
|
||||
m_kernel.template setProperty<Option>(value);
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
template<typename Option>
|
||||
typename Option::type&
|
||||
System<KernelType, T1, T2, T3>::option() {
|
||||
return getOption<Option>();
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
KernelType& System<KernelType, T1, T2, T3>::kernel() {
|
||||
return m_kernel;
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
void System<KernelType, T1, T2, T3>::copyInto(System<KernelType, T1, T2, T3>& into) const {
|
||||
|
||||
//copy the clustergraph and clone all objects while at it. They are also pushed to the storage
|
||||
cloner<System> cl(into);
|
||||
m_cluster->copyInto(into.m_cluster, cl);
|
||||
|
||||
//notify all modules that they are copied
|
||||
Type1::system_copy(*this, into);
|
||||
Type2::system_copy(*this, into);
|
||||
Type3::system_copy(*this, into);
|
||||
};
|
||||
|
||||
template< typename KernelType, typename T1, typename T2, typename T3 >
|
||||
System<KernelType, T1, T2, T3>* System<KernelType, T1, T2, T3>::clone() const {
|
||||
|
||||
System* ns = new System();
|
||||
this->copyInto(*ns);
|
||||
return ns;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //GCM_SYSTEM_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
303
src/Mod/Assembly/App/opendcm/core/imp/transformation_imp.hpp
Normal file
303
src/Mod/Assembly/App/opendcm/core/imp/transformation_imp.hpp
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DCM_TRANSFORMATION_IMP_H
|
||||
#define DCM_TRANSFORMATION_IMP_H
|
||||
|
||||
#include "../transformation.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace dcm {
|
||||
namespace detail {
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>::Transform() : m_rotation(Rotation::Identity()),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) { };
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>::Transform(const Rotation& r) : m_rotation(r),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>::Transform(const Rotation& r, const Translation& t) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>::Transform(const Rotation& r, const Translation& t, const Scaling& s) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(s) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
const typename Transform<Scalar, Dim>::Rotation& Transform<Scalar, Dim>::rotation() const {
|
||||
return m_rotation;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
|
||||
m_rotation = rotation.derived().normalized()*m_rotation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
const typename Transform<Scalar, Dim>::Translation& Transform<Scalar, Dim>::translation() const {
|
||||
return m_translation;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::translate(const Translation& translation) {
|
||||
m_translation = m_translation*translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
const typename Transform<Scalar, Dim>::Scaling& Transform<Scalar, Dim>::scaling() const {
|
||||
return m_scale;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::scale(const Scalar& scaling) {
|
||||
m_scale *= Scaling(scaling);
|
||||
return *this;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::scale(const Scaling& scaling) {
|
||||
m_scale.factor() *= scaling.factor();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::invert() {
|
||||
m_rotation = m_rotation.inverse();
|
||||
m_translation.vector() = (m_rotation*m_translation.vector()) * (-m_scale.factor());
|
||||
m_scale = Scaling(1./m_scale.factor());
|
||||
return *this;
|
||||
};
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim> Transform<Scalar, Dim>::inverse() {
|
||||
Transform res(*this);
|
||||
res.invert();
|
||||
return res;
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator=(const Translation& t) {
|
||||
m_translation = t;
|
||||
m_rotation = Rotation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
return *this;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Translation& t) const {
|
||||
Transform res = *this;
|
||||
res.translate(t);
|
||||
return res;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Translation& t) {
|
||||
return translate(t);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator=(const Scaling& s) {
|
||||
m_scale = s;
|
||||
m_translation = Translation::Identity();
|
||||
m_rotation = Rotation::Identity();
|
||||
return *this;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Scaling& s) const {
|
||||
Transform res = *this;
|
||||
res.scale(s);
|
||||
return res;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Scaling& s) {
|
||||
return scale(s);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
m_rotation = r.derived();
|
||||
m_rotation.normalize();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1);
|
||||
return *this;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
return res;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
return rotate(r.derived());
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim> Transform<Scalar, Dim>::operator* (const Transform& other) const {
|
||||
Transform res(*this);
|
||||
res*= other;
|
||||
return res;
|
||||
}
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar, Dim>& Transform<Scalar, Dim>::operator*= (const Transform& other) {
|
||||
rotate(other.rotation());
|
||||
other.rotate(m_translation.vector());
|
||||
m_translation.vector() += other.translation().vector()/m_scale.factor();
|
||||
m_scale.factor() *= other.scaling().factor();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Derived& Transform<Scalar, Dim>::rotate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_rotation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Derived& Transform<Scalar, Dim>::translate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_translation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Derived& Transform<Scalar, Dim>::scale(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec*=m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Derived& Transform<Scalar, Dim>::transform(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Derived Transform<Scalar, Dim>::operator*(const Eigen::MatrixBase<Derived>& vec) const {
|
||||
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline void Transform<Scalar, Dim>::operator()(Eigen::MatrixBase<Derived>& vec) const {
|
||||
transform(vec);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
bool Transform<Scalar, Dim>::isApprox(const Transform& other, Scalar prec) const {
|
||||
return m_rotation.isApprox(other.rotation(), prec)
|
||||
&& ((m_translation.vector()- other.translation().vector()).norm() < prec)
|
||||
&& (std::abs(m_scale.factor()-other.scaling().factor()) < prec);
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
void Transform<Scalar, Dim>::setIdentity() {
|
||||
m_rotation.setIdentity();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
const Transform<Scalar, Dim> Transform<Scalar, Dim>::Identity() {
|
||||
return Transform(Rotation::Identity(), Translation::Identity(), Scaling(1));
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar, Dim>& Transform<Scalar, Dim>::normalize() {
|
||||
m_rotation.normalize();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
DiffTransform<Scalar, Dim>::DiffTransform(Transform<Scalar, Dim>& trans)
|
||||
: Transform<Scalar, Dim>(trans.rotation(), trans.translation(), trans.scaling()) {
|
||||
|
||||
m_diffMatrix.setZero();
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
const typename DiffTransform<Scalar, Dim>::DiffMatrix&
|
||||
DiffTransform<Scalar, Dim>::differential() {
|
||||
return m_diffMatrix;
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Scalar&
|
||||
DiffTransform<Scalar, Dim>::operator()(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Scalar&
|
||||
DiffTransform<Scalar, Dim>::at(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
|
||||
|
||||
/*When you overload a binary operator as a member function of a class the overload is used
|
||||
* when the first operand is of the class type.For stream operators, the first operand
|
||||
* is the stream and not (usually) the custom class.
|
||||
*/
|
||||
template<typename charT, typename traits, typename Kernel, int Dim>
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, const dcm::detail::Transform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor();
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits,typename Kernel, int Dim>
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, dcm::detail::DiffTransform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor() << std::endl
|
||||
<< "Differential:" << std::endl<<t.differential();
|
||||
return os;
|
||||
}
|
||||
|
||||
}//detail
|
||||
}//DCM
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //DCM_TRANSFORMATION
|
||||
@@ -17,27 +17,16 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_KERNEL_H
|
||||
#define GCM_KERNEL_H
|
||||
#ifndef DCM_KERNEL_H
|
||||
#define DCM_KERNEL_H
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Dense>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/errinfo_errno.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "transformation.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "multimap.hpp"
|
||||
#include "property.hpp"
|
||||
|
||||
namespace E = Eigen;
|
||||
@@ -49,6 +38,13 @@ struct nothing {
|
||||
void operator()() {};
|
||||
};
|
||||
|
||||
//information about solving
|
||||
struct SolverInfo {
|
||||
int iterations;
|
||||
double error;
|
||||
double time;
|
||||
};
|
||||
|
||||
//the parameter types
|
||||
enum ParameterType {
|
||||
general, //every non-rotation parameter, therefore every translation and non transformed parameter
|
||||
@@ -56,6 +52,11 @@ enum ParameterType {
|
||||
complete //all parameter
|
||||
};
|
||||
|
||||
enum SolverModes {
|
||||
continuous,
|
||||
step
|
||||
};
|
||||
|
||||
//solver settings
|
||||
struct precision {
|
||||
|
||||
@@ -68,6 +69,18 @@ struct precision {
|
||||
};
|
||||
};
|
||||
|
||||
struct solvermode {
|
||||
|
||||
typedef SolverModes type;
|
||||
typedef setting_property kind;
|
||||
struct default_value {
|
||||
SolverModes operator()() {
|
||||
return continuous;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//and the solver itself
|
||||
template<typename Kernel>
|
||||
struct Dogleg {
|
||||
|
||||
@@ -76,267 +89,32 @@ struct Dogleg {
|
||||
#endif
|
||||
|
||||
typedef typename Kernel::number_type number_type;
|
||||
number_type tolg, tolx;
|
||||
number_type tolg, tolx, delta, nu, g_inf, fx_inf, err, time;
|
||||
Kernel* m_kernel;
|
||||
int iter, stop, reduce, unused, counter;
|
||||
typename Kernel::Vector h_dl, F_old, g;
|
||||
typename Kernel::Matrix J_old;
|
||||
|
||||
Dogleg(Kernel* k) : m_kernel(k), tolg(1e-40), tolx(1e-20){
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Dogleg"));
|
||||
#endif
|
||||
};
|
||||
Dogleg(Kernel* k);
|
||||
Dogleg();
|
||||
|
||||
void setKernel(Kernel* k);
|
||||
|
||||
template <typename Derived, typename Derived2, typename Derived3, typename Derived4>
|
||||
void calculateStep(const Eigen::MatrixBase<Derived>& g, const Eigen::MatrixBase<Derived3>& jacobi,
|
||||
const Eigen::MatrixBase<Derived4>& residual, Eigen::MatrixBase<Derived2>& h_dl,
|
||||
const double delta) {
|
||||
const double delta);
|
||||
|
||||
// get the steepest descent stepsize and direction
|
||||
const double alpha(g.squaredNorm()/(jacobi*g).squaredNorm());
|
||||
const typename Kernel::Vector h_sd = -g;
|
||||
|
||||
// get the gauss-newton step
|
||||
const typename Kernel::Vector h_gn = (jacobi).fullPivLu().solve(-residual);
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(h_gn.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal gauss-newton detected: "<<h_gn.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(h_sd.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal steepest descent detected: "<<h_sd.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(alpha)) {
|
||||
BOOST_LOG(log)<< "Unnormal alpha detected: "<<alpha;
|
||||
}
|
||||
#endif
|
||||
|
||||
// compute the dogleg step
|
||||
if(h_gn.norm() <= delta) {
|
||||
h_dl = h_gn;
|
||||
}
|
||||
else
|
||||
if((alpha*h_sd).norm() >= delta) {
|
||||
//h_dl = alpha*h_sd;
|
||||
h_dl = (delta/(h_sd.norm()))*h_sd;
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(h_dl.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg descent detected: "<<h_dl.norm();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
//compute beta
|
||||
number_type beta = 0;
|
||||
typename Kernel::Vector a = alpha*h_sd;
|
||||
typename Kernel::Vector b = h_gn;
|
||||
number_type c = a.transpose()*(b-a);
|
||||
number_type bas = (b-a).squaredNorm(), as = a.squaredNorm();
|
||||
if(c<0) {
|
||||
beta = -c+std::sqrt(std::pow(c,2)+bas*(std::pow(delta,2)-as));
|
||||
beta /= bas;
|
||||
}
|
||||
else {
|
||||
beta = std::pow(delta,2)-as;
|
||||
beta /= c+std::sqrt(std::pow(c,2) + bas*(std::pow(delta,2)-as));
|
||||
};
|
||||
|
||||
// and update h_dl and dL with beta
|
||||
h_dl = alpha*h_sd + beta*(b-a);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(c)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg c detected: "<<c;
|
||||
}
|
||||
if(!boost::math::isfinite(bas)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg bas detected: "<<bas;
|
||||
}
|
||||
if(!boost::math::isfinite(beta)) {
|
||||
BOOST_LOG(log)<< "Unnormal dogleg beta detected: "<<beta;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int solve(typename Kernel::MappedEquationSystem& sys) {
|
||||
nothing n;
|
||||
return solve(sys, n);
|
||||
};
|
||||
void init(typename Kernel::MappedEquationSystem& sys);
|
||||
|
||||
int solve(typename Kernel::MappedEquationSystem& sys, bool continuous = true);
|
||||
|
||||
template<typename Functor>
|
||||
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale) {
|
||||
|
||||
clock_t start = clock();
|
||||
clock_t inc_rec = clock();
|
||||
|
||||
if(!sys.isValid())
|
||||
throw solving_error() << boost::errinfo_errno(5) << error_message("invalid equation system");
|
||||
|
||||
|
||||
bool translate = true;
|
||||
|
||||
typename Kernel::Vector h_dl, F_old(sys.equationCount()), g(sys.equationCount());
|
||||
typename Kernel::Matrix J_old(sys.equationCount(), sys.parameterCount());
|
||||
|
||||
sys.recalculate();
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "initial jacobi: "<<std::endl<<sys.Jacobi<<std::endl
|
||||
<< "residual: "<<sys.Residual.transpose()<<std::endl
|
||||
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
|
||||
#endif
|
||||
sys.removeLocalGradientZeros();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "LGZ jacobi: "<<std::endl<<sys.Jacobi<<std::endl
|
||||
<< "maximal differential: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>();
|
||||
#endif
|
||||
|
||||
number_type err = sys.Residual.norm();
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get the infinity norm fx_inf and g_inf
|
||||
number_type g_inf = g.template lpNorm<E::Infinity>();
|
||||
number_type fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
int maxIterNumber = 10000;//MaxIterations * xsize;
|
||||
number_type diverging_lim = 1e6*err + 1e12;
|
||||
|
||||
number_type delta=5;
|
||||
number_type nu=2.;
|
||||
int iter=0, stop=0, reduce=0, unused=0, counter=0;
|
||||
|
||||
|
||||
while(!stop) {
|
||||
|
||||
// check if finished
|
||||
if(fx_inf <= m_kernel->template getProperty<precision>()*sys.Scaling) // Success
|
||||
stop = 1;
|
||||
else
|
||||
if(g_inf <= tolg)
|
||||
throw solving_error() << boost::errinfo_errno(2) << error_message("g infinity norm smaller below limit");
|
||||
else
|
||||
if(delta <= tolx)
|
||||
throw solving_error() << boost::errinfo_errno(3) << error_message("step size below limit");
|
||||
else
|
||||
if(iter >= maxIterNumber)
|
||||
throw solving_error() << boost::errinfo_errno(4) << error_message("maximal iterations reached");
|
||||
else
|
||||
if(!boost::math::isfinite(err))
|
||||
throw solving_error() << boost::errinfo_errno(5) << error_message("error is inf or nan");
|
||||
else
|
||||
if(err > diverging_lim)
|
||||
throw solving_error() << boost::errinfo_errno(6) << error_message("error diverged");
|
||||
|
||||
|
||||
// see if we are already finished
|
||||
if(stop)
|
||||
break;
|
||||
|
||||
number_type err_new;
|
||||
number_type dF=0, dL=0;
|
||||
number_type rho;
|
||||
|
||||
//get the update step
|
||||
calculateStep(g, sys.Jacobi, sys.Residual, h_dl, delta);
|
||||
|
||||
// calculate the linear model
|
||||
dL = 0.5*sys.Residual.norm() - 0.5*(sys.Residual + sys.Jacobi*h_dl).norm();
|
||||
|
||||
// get the new values
|
||||
sys.Parameter += h_dl;
|
||||
|
||||
clock_t start_rec = clock();
|
||||
sys.recalculate();
|
||||
clock_t end_rec = clock();
|
||||
inc_rec += end_rec-start_rec;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
if(!boost::math::isfinite(sys.Residual.norm())) {
|
||||
BOOST_LOG(log)<< "Unnormal residual detected: "<<sys.Residual.norm();
|
||||
}
|
||||
if(!boost::math::isfinite(sys.Jacobi.sum())) {
|
||||
BOOST_LOG(log)<< "Unnormal jacobi detected: "<<sys.Jacobi.sum();
|
||||
}
|
||||
#endif
|
||||
|
||||
//calculate the translation update ratio
|
||||
err_new = sys.Residual.norm();
|
||||
dF = err - err_new;
|
||||
rho = dF/dL;
|
||||
|
||||
if(dF<=0 || dL<=0)
|
||||
rho = -1;
|
||||
// update delta
|
||||
if(rho>0.85) {
|
||||
delta = std::max(delta,2*h_dl.norm());
|
||||
nu = 2;
|
||||
}
|
||||
else
|
||||
if(rho < 0.25) {
|
||||
delta = delta/nu;
|
||||
nu = 2*nu;
|
||||
}
|
||||
|
||||
if(dF > 0 && dL > 0) {
|
||||
|
||||
//see if we got too high differentials
|
||||
if(sys.Jacobi.template lpNorm<Eigen::Infinity>() > 2) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "High differential detected: "<<sys.Jacobi.template lpNorm<Eigen::Infinity>()<<" in iteration: "<<iter;
|
||||
#endif
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
}
|
||||
//it can also happen that the differentials get too small, however, we cant check for that
|
||||
else
|
||||
if(iter>1 && (counter>50)) {
|
||||
rescale();
|
||||
sys.recalculate();
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
F_old = sys.Residual;
|
||||
J_old = sys.Jacobi;
|
||||
|
||||
err = sys.Residual.norm();
|
||||
g = sys.Jacobi.transpose()*(sys.Residual);
|
||||
|
||||
// get infinity norms
|
||||
g_inf = g.template lpNorm<E::Infinity>();
|
||||
fx_inf = sys.Residual.template lpNorm<E::Infinity>();
|
||||
|
||||
}
|
||||
else {
|
||||
sys.Residual = F_old;
|
||||
sys.Jacobi = J_old;
|
||||
sys.Parameter -= h_dl;
|
||||
unused++;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Reject step in iter "<<iter;
|
||||
#endif
|
||||
}
|
||||
|
||||
iter++;
|
||||
counter++;
|
||||
}
|
||||
/*
|
||||
clock_t end = clock();
|
||||
double ms = (double(end-start) * 1000.) / double(CLOCKS_PER_SEC);
|
||||
double ms_rec = (double(inc_rec-start) * 1000.) / double(CLOCKS_PER_SEC);
|
||||
*/
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) <<"Done solving: "<<err<<", iter: "<<iter<<", unused: "<<unused<<", reason:"<< stop;
|
||||
BOOST_LOG(log)<< "final jacobi: "<<std::endl<<sys.Jacobi;
|
||||
#endif
|
||||
|
||||
return stop;
|
||||
}
|
||||
int solve(typename Kernel::MappedEquationSystem& sys, Functor& rescale, bool continuous = true);
|
||||
};
|
||||
|
||||
template<typename Scalar, template<class> class Nonlinear = Dogleg>
|
||||
struct Kernel : public PropertyOwner< mpl::vector<precision> > {
|
||||
struct Kernel : public PropertyOwner< mpl::vector2<precision, solvermode> > {
|
||||
|
||||
//basics
|
||||
typedef Scalar number_type;
|
||||
@@ -403,156 +181,64 @@ struct Kernel : public PropertyOwner< mpl::vector<precision> > {
|
||||
|
||||
number_type Scaling;
|
||||
|
||||
int parameterCount() {
|
||||
return m_params;
|
||||
};
|
||||
int equationCount() {
|
||||
return m_eqns;
|
||||
};
|
||||
int parameterCount();
|
||||
int equationCount();
|
||||
bool rotationOnly();
|
||||
|
||||
bool rotationOnly() {
|
||||
return rot_only;
|
||||
};
|
||||
MappedEquationSystem(int params, int equations);
|
||||
|
||||
MappedEquationSystem(int params, int equations)
|
||||
: rot_only(false), m_jacobi(equations, params),
|
||||
m_parameter(params), Residual(equations),
|
||||
m_params(params), m_eqns(equations), Scaling(1.),
|
||||
Jacobi(&m_jacobi(0,0),equations,params,DynStride(equations,1)),
|
||||
Parameter(&m_parameter(0),params,DynStride(1,1)) {
|
||||
int setParameterMap(int number, VectorMap& map, ParameterType t = general);
|
||||
int setParameterMap(Vector3Map& map, ParameterType t = general);
|
||||
int setResidualMap(VectorMap& map);
|
||||
void setJacobiMap(int eqn, int offset, int number, CVectorMap& map);
|
||||
void setJacobiMap(int eqn, int offset, int number, VectorMap& map);
|
||||
|
||||
m_param_rot_offset = 0;
|
||||
m_param_trans_offset = params;
|
||||
m_eqn_offset = 0;
|
||||
bool isValid();
|
||||
|
||||
m_jacobi.setZero(); //important as some places are never written
|
||||
};
|
||||
void setAccess(ParameterType t);
|
||||
|
||||
int setParameterMap(int number, VectorMap& map, ParameterType t = general) {
|
||||
|
||||
if(t == rotation) {
|
||||
new(&map) VectorMap(&m_parameter(m_param_rot_offset), number, DynStride(1,1));
|
||||
m_param_rot_offset += number;
|
||||
return m_param_rot_offset-number;
|
||||
}
|
||||
else {
|
||||
m_param_trans_offset -= number;
|
||||
new(&map) VectorMap(&m_parameter(m_param_trans_offset), number, DynStride(1,1));
|
||||
return m_param_trans_offset;
|
||||
}
|
||||
};
|
||||
int setParameterMap(Vector3Map& map, ParameterType t = general) {
|
||||
|
||||
if(t == rotation) {
|
||||
new(&map) Vector3Map(&m_parameter(m_param_rot_offset));
|
||||
m_param_rot_offset += 3;
|
||||
return m_param_rot_offset-3;
|
||||
}
|
||||
else {
|
||||
m_param_trans_offset -= 3;
|
||||
new(&map) Vector3Map(&m_parameter(m_param_trans_offset));
|
||||
return m_param_trans_offset;
|
||||
}
|
||||
};
|
||||
int setResidualMap(VectorMap& map) {
|
||||
new(&map) VectorMap(&Residual(m_eqn_offset), 1, DynStride(1,1));
|
||||
return m_eqn_offset++;
|
||||
};
|
||||
void setJacobiMap(int eqn, int offset, int number, CVectorMap& map) {
|
||||
new(&map) CVectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
void setJacobiMap(int eqn, int offset, int number, VectorMap& map) {
|
||||
new(&map) VectorMap(&m_jacobi(eqn, offset), number, DynStride(0,m_eqns));
|
||||
};
|
||||
|
||||
bool isValid() {
|
||||
if(!m_params || !m_eqns)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
void setAccess(ParameterType t) {
|
||||
|
||||
if(t==complete) {
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,m_params,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(0),m_params,DynStride(1,1));
|
||||
}
|
||||
else
|
||||
if(t==rotation) {
|
||||
int num = m_param_trans_offset;
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,0),m_eqns,num,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(0),num,DynStride(1,1));
|
||||
}
|
||||
else
|
||||
if(t==general) {
|
||||
int num = m_params - m_param_trans_offset;
|
||||
new(&Jacobi) MatrixMap(&m_jacobi(0,m_param_trans_offset),m_eqns,num,DynStride(m_eqns,1));
|
||||
new(&Parameter) VectorMap(&m_parameter(m_param_trans_offset),num,DynStride(1,1));
|
||||
}
|
||||
};
|
||||
|
||||
void setGeneralEquationAccess(bool general) {
|
||||
rot_only = !general;
|
||||
};
|
||||
|
||||
bool hasParameterType(ParameterType t) {
|
||||
|
||||
if(t==rotation)
|
||||
return (m_param_rot_offset>0);
|
||||
else
|
||||
if(t==general)
|
||||
return (m_param_trans_offset<m_params);
|
||||
else
|
||||
return (m_params>0);
|
||||
};
|
||||
|
||||
virtual void recalculate() = 0;
|
||||
void setGeneralEquationAccess(bool general);
|
||||
bool hasParameterType(ParameterType t);
|
||||
|
||||
virtual void recalculate() = 0;
|
||||
virtual void removeLocalGradientZeros() = 0;
|
||||
|
||||
};
|
||||
|
||||
Kernel() {};
|
||||
|
||||
Kernel();
|
||||
|
||||
//static comparison versions
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
|
||||
return ((p1-p2).squaredNorm() < precission);
|
||||
}
|
||||
static bool isSame(number_type t1, number_type t2, number_type precission) {
|
||||
return (std::abs(t1-t2) < precission);
|
||||
}
|
||||
static bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission);
|
||||
static bool isSame(number_type t1, number_type t2, number_type precission);
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission) {
|
||||
return ((p1+p2).squaredNorm() < precission);
|
||||
}
|
||||
static bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2, number_type precission);
|
||||
|
||||
//runtime comparison versions (which use user settings for precission)
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1-p2).squaredNorm() < getProperty<precision>());
|
||||
}
|
||||
bool isSame(number_type t1, number_type t2) {
|
||||
return (std::abs(t1-t2) < getProperty<precision>());
|
||||
}
|
||||
bool isSame(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2);
|
||||
bool isSame(number_type t1, number_type t2);
|
||||
template <typename DerivedA,typename DerivedB>
|
||||
bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2) {
|
||||
return ((p1+p2).squaredNorm() < getProperty<precision>());
|
||||
}
|
||||
|
||||
int solve(MappedEquationSystem& mes) {
|
||||
nothing n;
|
||||
return NonlinearSolver(this).solve(mes, n);
|
||||
};
|
||||
bool isOpposite(const E::MatrixBase<DerivedA>& p1,const E::MatrixBase<DerivedB>& p2);
|
||||
|
||||
int solve(MappedEquationSystem& mes);
|
||||
|
||||
template<typename Functor>
|
||||
int solve(MappedEquationSystem& mes, Functor& f) {
|
||||
return NonlinearSolver(this).solve(mes, f);
|
||||
};
|
||||
int solve(MappedEquationSystem& mes, Functor& f);
|
||||
|
||||
typedef mpl::vector1<precision> properties;
|
||||
SolverInfo getSolverInfo();
|
||||
|
||||
private:
|
||||
NonlinearSolver m_solver;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}//dcm
|
||||
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/kernel_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_KERNEL_H
|
||||
|
||||
|
||||
@@ -24,16 +24,11 @@
|
||||
#include <map>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/key_type.hpp>
|
||||
#include <boost/mpl/value_type.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
@@ -67,26 +62,6 @@ namespace fusion = boost::fusion;
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
|
||||
);
|
||||
|
||||
#define EMIT_CALL_DEC(z, n, data) \
|
||||
template<typename SigMap> \
|
||||
template < \
|
||||
typename S \
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \
|
||||
> \
|
||||
void SignalOwner<SigMap>::emitSignal( \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \
|
||||
) \
|
||||
{ \
|
||||
if(m_emit_signals) {\
|
||||
typedef typename mpl::find<sig_name, S>::type iterator; \
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance; \
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type; \
|
||||
map_type& map = fusion::at<distance>(m_signals); \
|
||||
for (typename map_type::iterator it=map.begin(); it != map.end(); it++) \
|
||||
(it->second)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \
|
||||
}\
|
||||
};
|
||||
|
||||
namespace dcm {
|
||||
|
||||
/** @defgroup Objects Objects
|
||||
@@ -164,7 +139,7 @@ protected:
|
||||
|
||||
Signals m_signals;
|
||||
bool m_emit_signals;
|
||||
int m_signal_count;
|
||||
int m_signal_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -202,61 +177,11 @@ struct Object : public PropertyOwner<typename details::properties_by_object<type
|
||||
Sys* m_system;
|
||||
};
|
||||
|
||||
}; //dcm
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
Object<Sys, Derived, Sig>::Object(Sys& system) : m_system(&system) {};
|
||||
|
||||
template<typename Sys, typename Derived, typename Sig>
|
||||
boost::shared_ptr<Derived> Object<Sys, Derived, Sig>::clone(Sys& newSys)
|
||||
{
|
||||
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
SignalOwner<SigMap>::SignalOwner() : m_emit_signals(true), m_signal_count(0) {};
|
||||
|
||||
template<typename SigMap>
|
||||
template<typename S>
|
||||
Connection SignalOwner<SigMap>::connectSignal(typename mpl::at<SigMap, S>::type function)
|
||||
{
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type;
|
||||
map_type& map = fusion::at<distance>(m_signals);
|
||||
map[++m_signal_count] = function;
|
||||
return m_signal_count;
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
template<typename S>
|
||||
void SignalOwner<SigMap>::disconnectSignal(Connection c)
|
||||
{
|
||||
typedef typename mpl::find<sig_name, S>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<sig_name>::type, iterator>::type distance;
|
||||
|
||||
typedef typename fusion::result_of::value_at<Signals, distance>::type map_type;
|
||||
map_type& map = fusion::at<distance>(m_signals);
|
||||
map.erase(c);
|
||||
};
|
||||
|
||||
template<typename SigMap>
|
||||
void SignalOwner<SigMap>::enableSignals(bool onoff)
|
||||
{
|
||||
m_emit_signals = onoff;
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~)
|
||||
|
||||
}
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/object_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_OBJECT_H
|
||||
|
||||
|
||||
@@ -21,20 +21,17 @@
|
||||
#define GCM_PROPERTY_H
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/buffer_concepts.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
|
||||
#include <boost/fusion/mpl.hpp>
|
||||
#include <boost/fusion/include/sequence.hpp>
|
||||
#include <boost/fusion/include/container.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/fusion/include/size.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
@@ -446,11 +443,6 @@ struct PropertyOwner {
|
||||
Properties m_properties;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void pretty(T t) {
|
||||
std::cout<<__PRETTY_FUNCTION__<<std::endl;
|
||||
};
|
||||
|
||||
template<typename PropertyList>
|
||||
PropertyOwner<PropertyList>::PropertyOwner() {
|
||||
|
||||
|
||||
@@ -21,40 +21,50 @@
|
||||
#define GCM_SYSTEM_H
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/vector/vector0.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/vector/vector0.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/count.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/less_equal.hpp>
|
||||
#include <boost/mpl/print.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "property.hpp"
|
||||
#include "clustergraph.hpp"
|
||||
#include "sheduler.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "object.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct No_Identifier {};
|
||||
struct Unspecified_Identifier {};
|
||||
|
||||
struct No_Identifier {}; //struct to show that no identifier shall be used
|
||||
struct Unspecified_Identifier {}; //struct to show that it dosen't matter which identifier type is used
|
||||
struct solved {}; //signal emitted when solving is done
|
||||
|
||||
namespace details {
|
||||
|
||||
enum { subcluster = 10};
|
||||
|
||||
/**
|
||||
* @brief Appends a mpl sequences to another
|
||||
*
|
||||
* Makes two sequence to one by appending all types of the first to the second sequence. The new
|
||||
* mpl sequence can be accessed by the ::type typedef.
|
||||
* Usage: @code vector_fold<Seq1, Seq2>::type @endcode
|
||||
*
|
||||
* @tparam state the mpl sequence which will be expanded
|
||||
* @tparam seq the mpl sequence which will be appended
|
||||
**/
|
||||
template<typename seq, typename state>
|
||||
struct vector_fold : mpl::fold < seq, state,
|
||||
mpl::push_back<mpl::_1, mpl::_2> > {};
|
||||
|
||||
template<typename seq, typename state>
|
||||
struct edge_fold : mpl::fold< seq, state,
|
||||
mpl::if_< is_edge_property<mpl::_2>,
|
||||
@@ -84,6 +94,15 @@ struct get_identifier {
|
||||
template<typename seq, typename state>
|
||||
struct map_fold : mpl::fold< seq, state, mpl::insert<mpl::_1,mpl::_2> > {};
|
||||
|
||||
|
||||
template<typename state, typename seq1, typename seq2, typename seq3>
|
||||
struct map_fold_3 {
|
||||
typedef typename details::map_fold<seq1,
|
||||
typename details::map_fold<seq2,
|
||||
typename details::map_fold<seq3,
|
||||
state >::type >::type>::type type;
|
||||
};
|
||||
|
||||
struct nothing {};
|
||||
|
||||
template<int v>
|
||||
@@ -91,10 +110,13 @@ struct EmptyModule {
|
||||
|
||||
template<typename T>
|
||||
struct type {
|
||||
struct inheriter {};
|
||||
struct inheriter {
|
||||
void system_sub(boost::shared_ptr<T> subsys) {};
|
||||
};
|
||||
typedef mpl::vector<> properties;
|
||||
typedef mpl::vector<> objects;
|
||||
typedef mpl::vector<> geometries;
|
||||
typedef mpl::map<> signals;
|
||||
typedef Unspecified_Identifier Identifier;
|
||||
|
||||
static void system_init(T& sys) {};
|
||||
@@ -107,22 +129,33 @@ struct is_shared_ptr : boost::mpl::false_ {};
|
||||
template <class T>
|
||||
struct is_shared_ptr<boost::shared_ptr<T> > : boost::mpl::true_ {};
|
||||
|
||||
template<typename Sys, typename M1, typename M2, typename M3>
|
||||
struct inheriter : public M1::inheriter, public M2::inheriter, public M3::inheriter,
|
||||
dcm::SignalOwner<typename details::map_fold_3< mpl::map<mpl::pair<solved, boost::function<void (Sys*)> > >,
|
||||
typename M1::signals, typename M2::signals, typename M3::signals>::type> {};
|
||||
}
|
||||
|
||||
template< typename KernelType,
|
||||
typename T1 = details::EmptyModule<1>,
|
||||
typename T2 = details::EmptyModule<2>,
|
||||
typename T3 = details::EmptyModule<3> >
|
||||
class System : public T1::template type< System<KernelType,T1,T2,T3> >::inheriter,
|
||||
public T2::template type< System<KernelType,T1,T2,T3> >::inheriter,
|
||||
public T3::template type< System<KernelType,T1,T2,T3> >::inheriter {
|
||||
class System : public details::inheriter<System<KernelType,T1,T2,T3>, typename T1::template type< System<KernelType,T1,T2,T3> >,
|
||||
typename T2::template type< System<KernelType,T1,T2,T3> >,
|
||||
typename T3::template type< System<KernelType,T1,T2,T3> > > {
|
||||
|
||||
typedef System<KernelType,T1,T2,T3> BaseType;
|
||||
public:
|
||||
|
||||
typedef T1 Module1;
|
||||
typedef T2 Module2;
|
||||
typedef T3 Module3;
|
||||
typedef typename T1::template type< BaseType > Type1;
|
||||
typedef typename T2::template type< BaseType > Type2;
|
||||
typedef typename T3::template type< BaseType > Type3;
|
||||
typedef mpl::vector3<Type1, Type2, Type3> TypeVector;
|
||||
typedef typename Type1::inheriter Inheriter1;
|
||||
typedef typename Type2::inheriter Inheriter2;
|
||||
typedef typename Type3::inheriter Inheriter3;
|
||||
|
||||
//Check if all Identifiers are the same and find out which type it is
|
||||
typedef typename mpl::fold<TypeVector, mpl::vector<>,
|
||||
@@ -162,6 +195,12 @@ public:
|
||||
mpl::vector1<vertex_index_prop> >::type vertex_properties;
|
||||
typedef typename details::cluster_fold< properties,
|
||||
mpl::vector2<changed_prop, type_prop> >::type cluster_properties;
|
||||
|
||||
//we hold our own PropertyOwner which we use for system settings. Don't inherit it as the user
|
||||
//should not access the settings via the proeprty getter and setter functions.
|
||||
typedef PropertyOwner<typename details::properties_by_kind<properties, setting_property>::type> OptionOwner;
|
||||
OptionOwner m_options;
|
||||
|
||||
|
||||
protected:
|
||||
//object storage
|
||||
@@ -173,18 +212,6 @@ protected:
|
||||
template<typename FT1, typename FT2, typename FT3>
|
||||
friend struct Object;
|
||||
|
||||
struct clearer {
|
||||
template<typename T>
|
||||
void operator()(T& vector) const {
|
||||
vector.clear();
|
||||
};
|
||||
};
|
||||
|
||||
//we hold our own PropertyOwner which we use for system settings. Don't inherit it as the user
|
||||
//should not access the settings via the proeprty getter and setter functions.
|
||||
typedef PropertyOwner<typename details::properties_by_kind<properties, setting_property>::type> SettingOwner;
|
||||
SettingOwner m_settings;
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
boost::shared_ptr< sink_t > sink;
|
||||
#endif
|
||||
@@ -195,173 +222,73 @@ public:
|
||||
typedef KernelType Kernel;
|
||||
|
||||
public:
|
||||
System() : m_cluster(new Cluster), m_storage(new Storage)
|
||||
#ifdef USE_LOGGING
|
||||
, sink(init_log())
|
||||
#endif
|
||||
{
|
||||
Type1::system_init(*this);
|
||||
Type2::system_init(*this);
|
||||
Type3::system_init(*this);
|
||||
|
||||
};
|
||||
System();
|
||||
~System();
|
||||
|
||||
|
||||
~System() {
|
||||
#ifdef USE_LOGGING
|
||||
stop_log(sink);
|
||||
#endif
|
||||
};
|
||||
|
||||
void clear() {
|
||||
|
||||
m_cluster->clearClusters();
|
||||
m_cluster->clear();
|
||||
fusion::for_each(*m_storage, clearer());
|
||||
};
|
||||
void clear();
|
||||
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator begin() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).begin();
|
||||
};
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator begin();
|
||||
|
||||
template<typename Object>
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator end() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage).end();
|
||||
};
|
||||
typename std::vector< boost::shared_ptr<Object> >::iterator end();
|
||||
|
||||
template<typename Object>
|
||||
std::vector< boost::shared_ptr<Object> >& objectVector() {
|
||||
|
||||
typedef typename mpl::find<objects, Object>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<objects>::type, iterator>::type distance;
|
||||
BOOST_MPL_ASSERT((mpl::not_<boost::is_same<iterator, typename mpl::end<objects>::type > >));
|
||||
return fusion::at<distance>(*m_storage);
|
||||
};
|
||||
std::vector< boost::shared_ptr<Object> >& objectVector();
|
||||
|
||||
template<typename Object>
|
||||
void push_back(boost::shared_ptr<Object> ptr) {
|
||||
objectVector<Object>().push_back(ptr);
|
||||
};
|
||||
void push_back(boost::shared_ptr<Object> ptr);
|
||||
|
||||
template<typename Object>
|
||||
void erase(boost::shared_ptr<Object> ptr) {
|
||||
void erase(boost::shared_ptr<Object> ptr);
|
||||
|
||||
std::vector< boost::shared_ptr<Object> >& vec = objectVector<Object>();
|
||||
vec.erase(std::remove(vec.begin(), vec.end(), ptr), vec.end());
|
||||
};
|
||||
|
||||
void solve() {
|
||||
clock_t start = clock();
|
||||
m_sheduler.execute(*this);
|
||||
clock_t end = clock();
|
||||
double ms = (double(end-start)* 1000.) / double(CLOCKS_PER_SEC);
|
||||
//Base::Console().Message("overall solving time in ms: %f\n", ms);
|
||||
|
||||
};
|
||||
SolverInfo solve();
|
||||
|
||||
System* createSubsystem() {
|
||||
|
||||
System* s = new System();
|
||||
s->m_cluster = m_cluster->createCluster().first;
|
||||
s->m_storage = m_storage;
|
||||
s->m_cluster->template setProperty<dcm::type_prop>(details::subcluster);
|
||||
#ifdef USE_LOGGING
|
||||
stop_log(s->sink);
|
||||
#endif
|
||||
return s;
|
||||
};
|
||||
boost::shared_ptr< System > createSubsystem();
|
||||
typename std::vector< boost::shared_ptr<System> >::iterator beginSubsystems();
|
||||
typename std::vector< boost::shared_ptr<System> >::iterator endSubsystems();
|
||||
|
||||
//a kernel has it's own settings, therefore we need to decide which is accessed
|
||||
template<typename Setting>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
|
||||
typename mpl::end<typename Kernel::properties>::type >, typename Setting::type& >::type getSetting() {
|
||||
return m_settings.template getProperty<Setting>();
|
||||
};
|
||||
template<typename Option>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename Kernel::PropertySequence>::type >, typename Option::type& >::type getOption();
|
||||
|
||||
template<typename Setting>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
|
||||
typename mpl::end<typename Kernel::properties>::type >, typename Setting::type& >::type getSetting() {
|
||||
return m_kernel.template getProperty<Setting>();
|
||||
};
|
||||
template<typename Option>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename Kernel::PropertySequence>::type >, typename Option::type& >::type getOption();
|
||||
|
||||
template<typename Setting>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
|
||||
typename mpl::end<typename Kernel::properties>::type >, void >::type setSetting(typename Setting::type value){
|
||||
m_settings.template setProperty<Setting>(value);
|
||||
};
|
||||
template<typename Option>
|
||||
typename boost::enable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename Kernel::PropertySequence>::type >, void >::type setOption(typename Option::type value);
|
||||
|
||||
template<typename Setting>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::properties, Setting>::type,
|
||||
typename mpl::end<typename Kernel::properties>::type >, void >::type setSetting(typename Setting::type value){
|
||||
m_kernel.template setProperty<Setting>(value);
|
||||
};
|
||||
template<typename Option>
|
||||
typename boost::disable_if< boost::is_same< typename mpl::find<typename Kernel::PropertySequence, Option>::type,
|
||||
typename mpl::end<typename Kernel::PropertySequence>::type >, void >::type setOption(typename Option::type value);
|
||||
|
||||
//convinience function
|
||||
template<typename Setting>
|
||||
typename Setting::type& setting() {
|
||||
return getSetting<Setting>();
|
||||
};
|
||||
template<typename Option>
|
||||
typename Option::type& option();
|
||||
|
||||
//let evryone access and use our math kernel
|
||||
Kernel& kernel() {
|
||||
return m_kernel;
|
||||
};
|
||||
Kernel& kernel();
|
||||
|
||||
private:
|
||||
struct cloner {
|
||||
void copyInto(System& into) const;
|
||||
|
||||
System& newSys;
|
||||
cloner(System& ns) : newSys(ns) {};
|
||||
|
||||
template<typename T>
|
||||
struct test : mpl::and_<details::is_shared_ptr<T>,
|
||||
mpl::not_<boost::is_same<T, boost::shared_ptr<typename System::Cluster> > > > {};
|
||||
|
||||
template<typename T>
|
||||
typename boost::enable_if< test<T>, void>::type operator()(T& p) const {
|
||||
p = p->clone(newSys);
|
||||
newSys.push_back(p);
|
||||
};
|
||||
template<typename T>
|
||||
typename boost::enable_if< mpl::not_<test<T> >, void>::type operator()(const T& p) const {};
|
||||
};
|
||||
|
||||
public:
|
||||
void copyInto(System& into) const {
|
||||
|
||||
//copy the clustergraph and clone all objects while at it. They are also pushed to the storage
|
||||
cloner cl(into);
|
||||
m_cluster->copyInto(into.m_cluster, cl);
|
||||
|
||||
//notify all modules that they are copied
|
||||
Type1::system_copy(*this, into);
|
||||
Type2::system_copy(*this, into);
|
||||
Type3::system_copy(*this, into);
|
||||
};
|
||||
|
||||
System* clone() const {
|
||||
|
||||
System* ns = new System();
|
||||
this->copyInto(*ns);
|
||||
return ns;
|
||||
};
|
||||
System* clone() const;
|
||||
|
||||
boost::shared_ptr<Cluster> m_cluster;
|
||||
boost::shared_ptr<Storage> m_storage;
|
||||
Shedule m_sheduler;
|
||||
Kernel m_kernel;
|
||||
std::vector<boost::shared_ptr<System> > m_subsystems;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/system_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_SYSTEM_H
|
||||
|
||||
|
||||
@@ -374,3 +301,5 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,17 +17,15 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_TRAITS_H
|
||||
#define GCM_TRAITS_H
|
||||
#ifndef DCM_TRAITS_H
|
||||
#define DCM_TRAITS_H
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/void.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_shifted.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/mpl/copy.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -71,32 +69,7 @@ struct compare_traits<std::string> {
|
||||
};
|
||||
};
|
||||
|
||||
template<typename seq, int size>
|
||||
struct vector_shrink {
|
||||
typedef typename mpl::copy< seq, mpl::back_inserter< mpl::vector<> > >::type type;
|
||||
};
|
||||
|
||||
template<typename seq>
|
||||
struct vector_shrink< seq, 0 > {
|
||||
typedef mpl::vector0<> type;
|
||||
};
|
||||
template<typename seq>
|
||||
struct vector_shrink< seq, 1 > {
|
||||
typedef mpl::vector1< typename mpl::at_c< seq, 0 >::type > type;
|
||||
};
|
||||
|
||||
#define SEQ_TYPES(z, n, data) \
|
||||
typename mpl::at_c< seq, n >::type
|
||||
|
||||
#define VECTOR_SHRINK(z, n, data) \
|
||||
template< typename seq> \
|
||||
struct vector_shrink<seq, n> { \
|
||||
typedef BOOST_PP_CAT(mpl::vector, n) < \
|
||||
BOOST_PP_ENUM(n, SEQ_TYPES, ~) > type; \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2,10, VECTOR_SHRINK, ~)
|
||||
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //GCM_TRAITS_H
|
||||
|
||||
@@ -48,187 +48,71 @@ protected:
|
||||
Scaling m_scale;
|
||||
|
||||
public:
|
||||
Transform() : m_rotation(Rotation::Identity()),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) { };
|
||||
Transform();
|
||||
|
||||
Transform(const Rotation& r) : m_rotation(r),
|
||||
m_translation(Translation::Identity()),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
Transform(const Rotation& r, const Translation& t) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(Scaling(1.)) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
|
||||
Transform(const Rotation& r, const Translation& t, const Scaling& s) : m_rotation(r),
|
||||
m_translation(t),
|
||||
m_scale(s) {
|
||||
m_rotation.normalize();
|
||||
};
|
||||
Transform(const Rotation& r);
|
||||
Transform(const Rotation& r, const Translation& t);
|
||||
Transform(const Rotation& r, const Translation& t, const Scaling& s);
|
||||
|
||||
//access the single parts and manipulate them
|
||||
//***********************
|
||||
const Rotation& rotation() const {
|
||||
return m_rotation;
|
||||
}
|
||||
const Rotation& rotation() const;
|
||||
template<typename Derived>
|
||||
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation) {
|
||||
m_rotation = rotation.derived().normalized()*m_rotation;
|
||||
return *this;
|
||||
}
|
||||
Transform& rotate(const Eigen::RotationBase<Derived,Dim>& rotation);
|
||||
|
||||
const Translation& translation() const {
|
||||
return m_translation;
|
||||
}
|
||||
Transform& translate(const Translation& translation) {
|
||||
m_translation = m_translation*translation;
|
||||
return *this;
|
||||
}
|
||||
const Translation& translation() const;
|
||||
Transform& translate(const Translation& translation);
|
||||
|
||||
const Scaling& scaling() const {
|
||||
return m_scale;
|
||||
}
|
||||
Transform& scale(const Scalar& scaling) {
|
||||
m_scale *= Scaling(scaling);
|
||||
return *this;
|
||||
}
|
||||
Transform& scale(const Scaling& scaling) {
|
||||
m_scale.factor() *= scaling.factor();
|
||||
return *this;
|
||||
}
|
||||
const Scaling& scaling() const;
|
||||
Transform& scale(const Scalar& scaling);
|
||||
Transform& scale(const Scaling& scaling);
|
||||
|
||||
Transform& invert() {
|
||||
m_rotation = m_rotation.inverse();
|
||||
m_translation.vector() = (m_rotation*m_translation.vector()) * (-m_scale.factor());
|
||||
m_scale = Scaling(1./m_scale.factor());
|
||||
return *this;
|
||||
};
|
||||
Transform inverse() {
|
||||
Transform res(*this);
|
||||
res.invert();
|
||||
return res;
|
||||
};
|
||||
Transform& invert();
|
||||
Transform inverse();
|
||||
|
||||
//operators for value manipulation
|
||||
//********************************
|
||||
|
||||
inline Transform& operator=(const Translation& t) {
|
||||
m_translation = t;
|
||||
m_rotation = Rotation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
return *this;
|
||||
}
|
||||
inline Transform operator*(const Translation& t) const {
|
||||
Transform res = *this;
|
||||
res.translate(t);
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*=(const Translation& t) {
|
||||
return translate(t);
|
||||
}
|
||||
Transform& operator=(const Translation& t);
|
||||
Transform operator*(const Translation& s) const;
|
||||
Transform& operator*=(const Translation& t);
|
||||
|
||||
inline Transform& operator=(const Scaling& s) {
|
||||
m_scale = s;
|
||||
m_translation = Translation::Identity();
|
||||
m_rotation = Rotation::Identity();
|
||||
return *this;
|
||||
}
|
||||
inline Transform operator*(const Scaling& s) const {
|
||||
Transform res = *this;
|
||||
res.scale(s);
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*=(const Scaling& s) {
|
||||
return scale(s);
|
||||
}
|
||||
Transform& operator=(const Scaling& s);
|
||||
Transform operator*(const Scaling& s) const;
|
||||
Transform& operator*=(const Scaling& s);
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
m_rotation = r.derived();
|
||||
m_rotation.normalize();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1);
|
||||
return *this;
|
||||
}
|
||||
Transform& operator=(const Eigen::RotationBase<Derived,Dim>& r);
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const {
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
return res;
|
||||
}
|
||||
Transform operator*(const Eigen::RotationBase<Derived,Dim>& r) const;
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r) {
|
||||
return rotate(r.derived());
|
||||
}
|
||||
Transform& operator*=(const Eigen::RotationBase<Derived,Dim>& r);
|
||||
|
||||
inline Transform operator* (const Transform& other) const {
|
||||
Transform res(*this);
|
||||
res*= other;
|
||||
return res;
|
||||
}
|
||||
inline Transform& operator*= (const Transform& other) {
|
||||
rotate(other.rotation());
|
||||
other.rotate(m_translation.vector());
|
||||
m_translation.vector() += other.translation().vector()/m_scale.factor();
|
||||
m_scale.factor() *= other.scaling().factor();
|
||||
return *this;
|
||||
}
|
||||
Transform operator* (const Transform& other) const;
|
||||
Transform& operator*= (const Transform& other);
|
||||
|
||||
//transform Vectors
|
||||
//*****************
|
||||
template<typename Derived>
|
||||
inline Derived& rotate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_rotation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
Derived& rotate(Eigen::MatrixBase<Derived>& vec) const;
|
||||
template<typename Derived>
|
||||
inline Derived& translate(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = m_translation*vec;
|
||||
return vec.derived();
|
||||
}
|
||||
Derived& translate(Eigen::MatrixBase<Derived>& vec) const;
|
||||
template<typename Derived>
|
||||
inline Derived& scale(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec*=m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
Derived& scale(Eigen::MatrixBase<Derived>& vec) const;
|
||||
template<typename Derived>
|
||||
inline Derived& transform(Eigen::MatrixBase<Derived>& vec) const {
|
||||
vec = (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
return vec.derived();
|
||||
}
|
||||
Derived& transform(Eigen::MatrixBase<Derived>& vec) const;
|
||||
template<typename Derived>
|
||||
inline Derived operator*(const Eigen::MatrixBase<Derived>& vec) const {
|
||||
return (m_rotation*vec + m_translation.vector())*m_scale.factor();
|
||||
}
|
||||
Derived operator*(const Eigen::MatrixBase<Derived>& vec) const;
|
||||
template<typename Derived>
|
||||
inline void operator()(Eigen::MatrixBase<Derived>& vec) const {
|
||||
transform(vec);
|
||||
}
|
||||
void operator()(Eigen::MatrixBase<Derived>& vec) const;
|
||||
|
||||
//Stuff
|
||||
//*****
|
||||
bool isApprox(const Transform& other, Scalar prec) const {
|
||||
return m_rotation.isApprox(other.rotation(), prec)
|
||||
&& ((m_translation.vector()- other.translation().vector()).norm() < prec)
|
||||
&& (std::abs(m_scale.factor()-other.scaling().factor()) < prec);
|
||||
};
|
||||
void setIdentity() {
|
||||
m_rotation.setIdentity();
|
||||
m_translation = Translation::Identity();
|
||||
m_scale = Scaling(1.);
|
||||
}
|
||||
static const Transform Identity() {
|
||||
return Transform(Rotation::Identity(), Translation::Identity(), Scaling(1));
|
||||
}
|
||||
bool isApprox(const Transform& other, Scalar prec) const;
|
||||
void setIdentity();
|
||||
static const Transform Identity();
|
||||
|
||||
Transform& normalize() {
|
||||
m_rotation.normalize();
|
||||
return *this;
|
||||
}
|
||||
Transform& normalize();
|
||||
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
@@ -250,21 +134,11 @@ public:
|
||||
DiffTransform(const Rotation& r, const Translation& t) : Transform<Scalar, Dim>(r,t) {};
|
||||
DiffTransform(const Rotation& r, const Translation& t, const Scaling& s) : Transform<Scalar, Dim>(r,t,s) {};
|
||||
|
||||
DiffTransform(Transform<Scalar, Dim>& trans)
|
||||
: Transform<Scalar, Dim>(trans.rotation(), trans.translation(), trans.scaling()) {
|
||||
DiffTransform(Transform<Scalar, Dim>& trans);
|
||||
|
||||
m_diffMatrix.setZero();
|
||||
};
|
||||
|
||||
const DiffMatrix& differential() {
|
||||
return m_diffMatrix;
|
||||
};
|
||||
inline Scalar& operator()(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
inline Scalar& at(int f, int s) {
|
||||
return m_diffMatrix(f,s);
|
||||
};
|
||||
const DiffMatrix& differential();
|
||||
Scalar& operator()(int f, int s);
|
||||
Scalar& at(int f, int s);
|
||||
};
|
||||
|
||||
/*When you overload a binary operator as a member function of a class the overload is used
|
||||
@@ -272,26 +146,18 @@ public:
|
||||
* is the stream and not (usually) the custom class.
|
||||
*/
|
||||
template<typename charT, typename traits, typename Kernel, int Dim>
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, const dcm::detail::Transform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor();
|
||||
return os;
|
||||
}
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, const dcm::detail::Transform<Kernel, Dim>& t);
|
||||
|
||||
template<typename charT, typename traits,typename Kernel, int Dim>
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, dcm::detail::DiffTransform<Kernel, Dim>& t) {
|
||||
os << "Rotation: " << t.rotation().coeffs().transpose() << std::endl
|
||||
<< "Translation: " << t.translation().vector().transpose() <<std::endl
|
||||
<< "Scale: " << t.scaling().factor() << std::endl
|
||||
<< "Differential:" << std::endl<<t.differential();
|
||||
return os;
|
||||
}
|
||||
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>& os, dcm::detail::DiffTransform<Kernel, Dim>& t);
|
||||
|
||||
|
||||
}//detail
|
||||
}//DCM
|
||||
|
||||
|
||||
#ifndef DCM_EXTERNAL_CORE
|
||||
#include "imp/transformation_imp.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //DCM_TRANSFORMATION
|
||||
|
||||
@@ -38,7 +38,36 @@
|
||||
|
||||
#ifdef DCM_USE_MODULESTATE
|
||||
#include "module3d/state.hpp"
|
||||
#endif
|
||||
#endif //use state
|
||||
|
||||
#ifdef DCM_EXTERNAL_3D
|
||||
|
||||
#define DCM_EXTERNAL_3D_INCLUDE_01 "opendcm/module3d/imp/clustermath_imp.hpp"
|
||||
#define DCM_EXTERNAL_3D_01( Sys )\
|
||||
template struct dcm::details::ClusterMath<Sys>;\
|
||||
template struct dcm::details::MES<Sys>;\
|
||||
template struct Sys::Kernel::MappedEquationSystem;\
|
||||
template struct dcm::details::SystemSolver<Sys>;
|
||||
|
||||
#define DCM_EXTERNAL_3D_INCLUDE_02 "opendcm/module3d/imp/constraint3d_holder_imp.hpp"
|
||||
#define DCM_EXTERNAL_3D_02( System )\
|
||||
INITIALIZE(System, 3, CONSTRAINT_SEQUENCE);
|
||||
|
||||
#define DCM_EXTERNAL_3D_INCLUDE_03 <opendcm/module3d/imp/state_imp.hpp>
|
||||
#define DCM_EXTERNAL_3D_03( System )\
|
||||
template struct dcm::parser_generator< dcm::details::getModule3D< System >::type::Geometry3D , System, std::ostream_iterator<char> >; \
|
||||
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::vertex_prop , System, std::ostream_iterator<char> >; \
|
||||
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::Constraint3D , System, std::ostream_iterator<char> >; \
|
||||
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::edge_prop , System, std::ostream_iterator<char> >; \
|
||||
template struct dcm::parser_generator< dcm::details::getModule3D<System>::type::fix_prop, System, std::ostream_iterator<char> >; \
|
||||
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::edge_prop, System, boost::spirit::istream_iterator >; \
|
||||
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::vertex_prop, System, boost::spirit::istream_iterator >; \
|
||||
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::fix_prop, System, boost::spirit::istream_iterator >; \
|
||||
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::Geometry3D, System, boost::spirit::istream_iterator >; \
|
||||
template struct dcm::parser_parser< dcm::details::getModule3D<System>::type::Constraint3D, System, boost::spirit::istream_iterator >;
|
||||
|
||||
#endif //external 3d
|
||||
|
||||
|
||||
#endif //DCM_MODULE3D_H
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace dcm {
|
||||
namespace details {
|
||||
//we need a custom orientation type to allow coincidents with points. We can't use the ci_orietation
|
||||
//as some geometries are supporte by align but not by coincident
|
||||
struct al_orientation : public Equation<al_orientation, Direction, true> {
|
||||
struct al_orientation : public Equation<al_orientation, Direction, 6, true> {
|
||||
|
||||
using Equation::operator=;
|
||||
using Equation::options;
|
||||
|
||||
@@ -17,14 +17,11 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_CLUSTERMATH_H
|
||||
#define GCM_CLUSTERMATH_H
|
||||
#ifndef DCM_CLUSTERMATH_H
|
||||
#define DCM_CLUSTERMATH_H
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <Eigen/StdVector>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <opendcm/core/logging.hpp>
|
||||
#include <opendcm/core/kernel.hpp>
|
||||
#include "defines.hpp"
|
||||
@@ -141,639 +138,12 @@ public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
|
||||
|
||||
m_resetTransform = Eigen::AngleAxisd(M_PI*2./3., Eigen::Vector3d(1,1,1).normalized());
|
||||
m_shift.setZero();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Clustermath3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::setParameterOffset(int offset, dcm::ParameterType t) {
|
||||
if(t == general)
|
||||
m_offset = offset;
|
||||
else
|
||||
m_offset_rot = offset;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
int ClusterMath<Sys>::getParameterOffset(ParameterType t) {
|
||||
if(t == general)
|
||||
return m_offset;
|
||||
else
|
||||
return m_offset_rot;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getNormQuaternionMap() {
|
||||
return m_normQ;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getTranslationMap() {
|
||||
return m_translation;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initMaps() {
|
||||
|
||||
transformToMaps(m_transform);
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=false;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initFixMaps() {
|
||||
//when fixed no maps exist
|
||||
new(&m_translation) typename Kernel::Vector3Map(&fixtrans(0));
|
||||
m_translation = m_transform.translation().vector();
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=true;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init fix transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Transform3D& ClusterMath<Sys>::getTransform() {
|
||||
return m_transform;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapsToTransform(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
//add scale only after possible reset
|
||||
typename Kernel::Transform3D::Scaling scale(m_transform.scaling());
|
||||
trans = m_diffTrans;
|
||||
trans *= scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::transformToMaps(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
const typename Kernel::Quaternion& m_quaternion = trans.rotation();
|
||||
if(m_quaternion.w() < 1.) {
|
||||
Scalar s = std::acos(m_quaternion.w())/std::sin(std::acos(m_quaternion.w()));
|
||||
m_normQ = m_quaternion.vec()*s;
|
||||
m_normQ /= NQFAKTOR;
|
||||
} else {
|
||||
m_normQ.setZero();
|
||||
}
|
||||
m_translation = trans.translation().vector();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishCalculation() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
|
||||
mapsToTransform(m_transform);
|
||||
init=false;
|
||||
|
||||
m_transform = m_ssrTransform*m_transform;
|
||||
|
||||
//scale all geometries back to the original size
|
||||
m_diffTrans *= typename Kernel::Transform3D::Scaling(1./m_ssrTransform.scaling().factor());
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishFixCalculation() {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix calculation";
|
||||
#endif
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
m_transform *= m_ssrTransform.inverse();
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::resetClusterRotation(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Reset cluster rotation:"<<std::endl<<m_diffTrans;
|
||||
#endif
|
||||
|
||||
trans = m_resetTransform.inverse()*trans;
|
||||
m_ssrTransform *= m_resetTransform;
|
||||
m_transform = m_resetTransform.inverse()*m_transform;
|
||||
|
||||
//apply the needed transformation to all geometries local values
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->transform(m_resetTransform);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::calcDiffTransform(typename ClusterMath<Sys>::Kernel::DiffTransform3D& trans) {
|
||||
|
||||
Scalar norm = m_normQ.norm();
|
||||
trans.setIdentity();
|
||||
|
||||
if(norm < 0.1) {
|
||||
if(norm == 0) {
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
} else {
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac,m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
}
|
||||
transformToMaps(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac, m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::recalculate() {
|
||||
|
||||
|
||||
calcDiffTransform(m_diffTrans);
|
||||
|
||||
const typename Kernel::Quaternion Q = m_diffTrans.rotation();
|
||||
|
||||
// now calculate the gradient quaternions and calculate the diff rotation matrices
|
||||
// m_normQ = (a,b,c)
|
||||
// n = ||m_normQ||
|
||||
//
|
||||
// Q = (a/n sin(n), b/n sin(n), c/n sin(n), cos(n))
|
||||
//
|
||||
|
||||
//n=||m_normQ||, sn = sin(n)/n, sn3 = sin(n)/n^3, cn = cos(n)/n, divn = 1/n;
|
||||
const Scalar n = m_normQ.norm();
|
||||
const Scalar sn = std::sin(NQFAKTOR*n)/n;
|
||||
const Scalar mul = (NQFAKTOR*std::cos(NQFAKTOR*n)-sn)/std::pow(n,2);
|
||||
|
||||
//dxa = dQx/da
|
||||
const Scalar dxa = sn + std::pow(m_normQ(0),2)*mul;
|
||||
const Scalar dxb = m_normQ(0)*m_normQ(1)*mul;
|
||||
const Scalar dxc = m_normQ(0)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dya = m_normQ(1)*m_normQ(0)*mul;
|
||||
const Scalar dyb = sn + std::pow(m_normQ(1),2)*mul;
|
||||
const Scalar dyc = m_normQ(1)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dza = m_normQ(2)*m_normQ(0)*mul;
|
||||
const Scalar dzb = m_normQ(2)*m_normQ(1)*mul;
|
||||
const Scalar dzc = sn + std::pow(m_normQ(2),2)*mul;
|
||||
|
||||
const Scalar dwa = -sn*NQFAKTOR*m_normQ(0);
|
||||
const Scalar dwb = -sn*NQFAKTOR*m_normQ(1);
|
||||
const Scalar dwc = -sn*NQFAKTOR*m_normQ(2);
|
||||
|
||||
//write in the diffrot matrix, starting with dQ/dx
|
||||
m_diffTrans.at(0,0) = -4.0*(Q.y()*dya+Q.z()*dza);
|
||||
m_diffTrans.at(0,1) = -2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(0,2) = 2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(1,0) = 2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(1,1) = -4.0*(Q.x()*dxa+Q.z()*dza);
|
||||
m_diffTrans.at(1,2) = -2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,0) = -2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(2,1) = 2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,2) = -4.0*(Q.x()*dxa+Q.y()*dya);
|
||||
|
||||
//dQ/dy
|
||||
m_diffTrans.at(0,3) = -4.0*(Q.y()*dyb+Q.z()*dzb);
|
||||
m_diffTrans.at(0,4) = -2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(0,5) = 2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(1,3) = 2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(1,4) = -4.0*(Q.x()*dxb+Q.z()*dzb);
|
||||
m_diffTrans.at(1,5) = -2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,3) = -2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(2,4) = 2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,5) = -4.0*(Q.x()*dxb+Q.y()*dyb);
|
||||
|
||||
//dQ/dz
|
||||
m_diffTrans.at(0,6) = -4.0*(Q.y()*dyc+Q.z()*dzc);
|
||||
m_diffTrans.at(0,7) = -2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(0,8) = 2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(1,6) = 2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(1,7) = -4.0*(Q.x()*dxc+Q.z()*dzc);
|
||||
m_diffTrans.at(1,8) = -2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,6) = -2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(2,7) = 2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,8) = -4.0*(Q.x()*dxc+Q.y()*dyc);
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::addGeometry(Geom g) {
|
||||
m_geometry.push_back(g);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::clearGeometry() {
|
||||
m_geometry.clear();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
std::vector<typename ClusterMath<Sys>::Geom>& ClusterMath<Sys>::getGeometry() {
|
||||
return m_geometry;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::map_downstream::map_downstream(details::ClusterMath<Sys>& cm, bool fix)
|
||||
: m_clusterMath(cm), m_isFixed(fix) {
|
||||
m_transform = m_clusterMath.getTransform().inverse();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(Geom g) {
|
||||
//allow iteration over all maped geometries
|
||||
m_clusterMath.addGeometry(g);
|
||||
//set the offsets so that geometry knows where it is in the parameter map
|
||||
g->m_offset = m_clusterMath.getParameterOffset(general);
|
||||
g->m_offset_rot = m_clusterMath.getParameterOffset(rotation);
|
||||
//position and offset of the parameters must be set to the clusters values
|
||||
g->setClusterMode(true, m_isFixed);
|
||||
//calculate the appropriate local values
|
||||
g->transform(m_transform);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
|
||||
//we transform the GLOBAL geometries to local ones in the subcluster! therefore
|
||||
//we are not interested in the successive transformations, we only transform the
|
||||
//global geometries with the cluster transform we want them to be local in, and thats
|
||||
//the one supplied in the constructor
|
||||
//m_transform *= c->template getClusterProperty<math_prop>().getTransform().inverse();
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Map downstream geometry";
|
||||
#endif
|
||||
|
||||
map_downstream down(cluster->template getProperty<math_prop>(),
|
||||
cluster->template getProperty<fix_prop>());
|
||||
cluster->template for_each<Geometry3D>(down, true);
|
||||
//TODO: if one subcluster is fixed the hole cluster should be too, as there are no
|
||||
// dof's remaining between parts and so nothing can be moved when one part is fixed.
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calculateClusterScale() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale with transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transformation
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale sec transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
|
||||
//collect all points together
|
||||
m_points.clear();
|
||||
typename Kernel::Transform3D trans(m_transform.rotation(), m_transform.translation());
|
||||
trans.invert();
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_pseudo.begin(); it != m_pseudo.end(); it++) {
|
||||
m_points.push_back(trans*(*it));
|
||||
}
|
||||
typedef typename std::vector<Geom>::iterator g_iter;
|
||||
for(g_iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
m_points.push_back((*it)->getPoint());
|
||||
|
||||
//start scale calculation
|
||||
if(m_points.empty()) return 1.;
|
||||
else if(m_points.size() == 1) {
|
||||
const typename Kernel::Vector3 p = m_points[0];
|
||||
return calcOnePoint(p);
|
||||
} else if(m_points.size() == 2) {
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
|
||||
if(Kernel::isSame((p1-p2).norm(), 0., 1e-10))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(m_points.size() == 3) {
|
||||
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
const typename Kernel::Vector3 p3 = m_points[2];
|
||||
|
||||
const typename Kernel::Vector3 d = p2-p1;
|
||||
const typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
if(Kernel::isSame(d.norm(), 0., 1e-10)) {
|
||||
|
||||
if(Kernel::isSame(e.norm(), 0., 1e-10))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p3);
|
||||
} else if(Kernel::isSame(e.norm(), 0., 1e-10)) {
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0., 1e-10) &&
|
||||
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0., 1e-10)) {
|
||||
return calcThreePoints(p1, p2, p3);
|
||||
}
|
||||
//three points on a line need to be treaded as multiple points
|
||||
}
|
||||
|
||||
//more than 3 points dont have a exakt solution. we search for a midpoint from which all points
|
||||
//are at least MAXFAKTOR*scale away, but not closer than MINFAKTOR*scale
|
||||
|
||||
//get the bonding box to get the center of points
|
||||
Scalar xmin=1e10, xmax=1e-10, ymin=1e10, ymax=1e-10, zmin=1e10, zmax=1e-10;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
typename Kernel::Vector3 v = (*it);
|
||||
xmin = (v(0)<xmin) ? v(0) : xmin;
|
||||
xmax = (v(0)<xmax) ? xmax : v(0);
|
||||
ymin = (v(1)<ymin) ? v(1) : ymin;
|
||||
ymax = (v(1)<ymax) ? ymax : v(1);
|
||||
zmin = (v(2)<zmin) ? v(2) : zmin;
|
||||
zmax = (v(2)<zmax) ? zmax : v(2);
|
||||
};
|
||||
//now calculate the midpoint
|
||||
midpoint << xmin+xmax, ymin+ymax, zmin+zmax;
|
||||
midpoint /= 2.;
|
||||
|
||||
|
||||
//get the scale direction an the resulting nearest point indexes
|
||||
double xh = xmax-xmin;
|
||||
double yh = ymax-ymin;
|
||||
double zh = zmax-zmin;
|
||||
int i1, i2, i3;
|
||||
if((xh<=yh) && (xh<=zh)) {
|
||||
i1=1;
|
||||
i2=2;
|
||||
i3=0;
|
||||
} else if((yh<xh) && (yh<zh)) {
|
||||
i1=0;
|
||||
i2=2;
|
||||
i3=1;
|
||||
} else {
|
||||
i1=0;
|
||||
i2=1;
|
||||
i3=2;
|
||||
}
|
||||
scale_dir.setZero();
|
||||
scale_dir(i3) = 1;
|
||||
max = Eigen::Vector3d(xmin,ymin,zmin);
|
||||
m_scale = (midpoint-max).norm()/MAXFAKTOR;
|
||||
mode = multiple_inrange;
|
||||
|
||||
maxm = max-midpoint;
|
||||
Scalar minscale = 1e10;
|
||||
|
||||
//get the closest point
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*m_scale) {
|
||||
|
||||
const double h = std::abs(point(i3)-maxm(i3));
|
||||
const double k = std::pow(MINFAKTOR/MAXFAKTOR,2);
|
||||
double q = std::pow(point(i1),2) + std::pow(point(i2),2);
|
||||
q -= (std::pow(maxm(i1),2) + std::pow(maxm(i2),2) + std::pow(h,2))*k;
|
||||
q /= 1.-k;
|
||||
|
||||
const double p = h*k/(1.-k);
|
||||
|
||||
if(std::pow(p,2)<q) assert(false);
|
||||
|
||||
midpoint(i3) += p + std::sqrt(std::pow(p,2)-q);
|
||||
maxm = max-midpoint;
|
||||
m_scale = maxm.norm()/MAXFAKTOR;
|
||||
|
||||
mode = multiple_outrange;
|
||||
minm = (*it)-midpoint;
|
||||
|
||||
it = m_points.begin();
|
||||
} else if(point.norm()<minscale) {
|
||||
minscale = point.norm();
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==multiple_inrange) {
|
||||
//we are in the range, let's get the perfect balanced scale value
|
||||
m_scale = (minscale+maxm.norm())/2.;
|
||||
}
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::applyClusterScale(Scalar scale, bool isFixed) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Apply cluster scale: "<<scale;
|
||||
BOOST_LOG(log) << "initial transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transform
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
|
||||
|
||||
|
||||
//when fixed, the geometries never get recalculated. therefore we have to do a calculate now
|
||||
//to alow the adoption of the scale. and no shift should been set.
|
||||
if(isFixed) {
|
||||
m_transform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
m_ssrTransform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
//now calculate the scaled geometrys
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Fixed cluster geometry value:" << (*it)->m_rotated.transpose();
|
||||
#endif
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
//if this is our scale then just applie the midpoint as shift
|
||||
if(Kernel::isSame(scale, m_scale, 1e-10)) {
|
||||
|
||||
}
|
||||
//if only one point exists we extend the origin-point-line to match the scale
|
||||
else if(mode==details::one) {
|
||||
if(Kernel::isSame(midpoint.norm(),0, 1e-10))
|
||||
midpoint << scale, 0, 0;
|
||||
else midpoint += scale*scale_dir;
|
||||
}
|
||||
//two and three points form a rectangular triangle, so same procedure
|
||||
else if(mode==details::two || mode==details::three) {
|
||||
|
||||
midpoint+= scale_dir*std::sqrt(std::pow(scale,2) - std::pow(m_scale,2));
|
||||
}
|
||||
//multiple points
|
||||
else if(mode==details::multiple_outrange) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(maxm(1),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(0) += maxm(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(1) += maxm(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(2) += maxm(2) + h;
|
||||
}
|
||||
} else {
|
||||
|
||||
//TODO: it's possible that for this case we get too far away from the outer points.
|
||||
// The m_scale for "midpoint outside the bounding box" may be bigger than the
|
||||
// scale to applie, so it results in an error.
|
||||
//get the closest point
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*scale) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(point(1),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(0) += point(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(1) += point(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(2) += point(2) + h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typename Kernel::Transform3D ssTrans;
|
||||
ssTrans = typename Kernel::Transform3D::Translation(-midpoint);
|
||||
ssTrans *= typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->transform(ssTrans);
|
||||
|
||||
//set the new rotation and translation
|
||||
m_transform = ssTrans.inverse()*m_transform;
|
||||
m_ssrTransform *= ssTrans;
|
||||
|
||||
transformToMaps(m_transform);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "sstrans scale: "<<ssTrans.scaling().factor();
|
||||
BOOST_LOG(log) << "finish transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcOnePoint(const typename ClusterMath<Sys>::Kernel::Vector3& p) {
|
||||
|
||||
//one point can have every scale when moving the midpoint on the origin - point vector
|
||||
midpoint = p;
|
||||
scale_dir = -midpoint;
|
||||
scale_dir.normalize();
|
||||
mode = details::one;
|
||||
m_scale = 0.;
|
||||
return 0.;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcTwoPoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2) {
|
||||
|
||||
//two points have their minimal scale at the mid position. Scaling perpendicular to this
|
||||
//line allows arbitrary scale values. Best is to have the scale dir move towards the origin
|
||||
//as good as possible.
|
||||
midpoint = p1+(p2-p1)/2.;
|
||||
scale_dir = (p2-p1).cross(midpoint);
|
||||
scale_dir = scale_dir.cross(p2-p1);
|
||||
if(!Kernel::isSame(scale_dir.norm(),0, 1e-10)) scale_dir.normalize();
|
||||
else scale_dir(0) = 1;
|
||||
mode = details::two;
|
||||
m_scale = (p2-p1).norm()/2.;
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcThreePoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2, const typename ClusterMath<Sys>::Kernel::Vector3& p3) {
|
||||
|
||||
//Three points form a triangle with it's minimal scale at the center of it's outer circle.
|
||||
//Arbitrary scale values can be achieved by moving perpendicular to the triangle plane.
|
||||
typename Kernel::Vector3 d = p2-p1;
|
||||
typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
typename Kernel::Vector3 f = p1+0.5*d;
|
||||
typename Kernel::Vector3 g = p1+0.5*e;
|
||||
scale_dir = d.cross(e);
|
||||
|
||||
typename Kernel::Matrix3 m;
|
||||
m.row(0) = d.transpose();
|
||||
m.row(1) = e.transpose();
|
||||
m.row(2) = scale_dir.transpose();
|
||||
|
||||
typename Kernel::Vector3 res(d.transpose()*f, e.transpose()*g, scale_dir.transpose()*p1);
|
||||
|
||||
midpoint = m.colPivHouseholderQr().solve(res);
|
||||
scale_dir.normalize();
|
||||
mode = details::three;
|
||||
m_scale = (midpoint-p1).norm();
|
||||
|
||||
return m_scale;
|
||||
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#ifndef DCM_EXTERNAL_3D
|
||||
#include "imp/clustermath_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //GCM_CLUSTERMATH_H
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace dcm {
|
||||
namespace details {
|
||||
|
||||
//we need a custom orientation type to allow coincidents with points
|
||||
struct ci_orientation : public Equation<ci_orientation, Direction, true> {
|
||||
struct ci_orientation : public Equation<ci_orientation, Direction, 4, true> {
|
||||
|
||||
using Equation::operator=;
|
||||
using Equation::options;
|
||||
@@ -184,7 +184,7 @@ struct ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public
|
||||
|
||||
|
||||
//we need a custom distance type to use point-distance functions instead of real geometry distance
|
||||
struct ci_distance : public Equation<ci_distance, mpl::vector2<double, SolutionSpace> > {
|
||||
struct ci_distance : public Equation<ci_distance, mpl::vector2<double, SolutionSpace>, 5 > {
|
||||
|
||||
using Equation::operator=;
|
||||
using Equation::options;
|
||||
|
||||
@@ -28,6 +28,7 @@ enum { cluster3D = 100};
|
||||
struct m3d {}; //base of module3d::type to allow other modules check for it
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include <opendcm/core/constraint.hpp>
|
||||
#include <boost/fusion/include/copy.hpp>
|
||||
|
||||
namespace dcm {
|
||||
|
||||
|
||||
667
src/Mod/Assembly/App/opendcm/module3d/imp/clustermath_imp.hpp
Normal file
667
src/Mod/Assembly/App/opendcm/module3d/imp/clustermath_imp.hpp
Normal file
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CLUSTERMATH_IMP_H
|
||||
#define DCM_CLUSTERMATH_IMP_H
|
||||
|
||||
#include "../clustermath.hpp"
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
#include "opendcm/core/imp/transformation_imp.hpp"
|
||||
#endif
|
||||
|
||||
//include it here as it is in the same external compilation unit as clustermath
|
||||
#include "solver_imp.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) {
|
||||
|
||||
m_resetTransform = Eigen::AngleAxisd(M_PI*2./3., Eigen::Vector3d(1,1,1).normalized());
|
||||
m_shift.setZero();
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Clustermath3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::setParameterOffset(int offset, dcm::ParameterType t) {
|
||||
if(t == general)
|
||||
m_offset = offset;
|
||||
else
|
||||
m_offset_rot = offset;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
int ClusterMath<Sys>::getParameterOffset(ParameterType t) {
|
||||
if(t == general)
|
||||
return m_offset;
|
||||
else
|
||||
return m_offset_rot;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getNormQuaternionMap() {
|
||||
return m_normQ;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Vector3Map& ClusterMath<Sys>::getTranslationMap() {
|
||||
return m_translation;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initMaps() {
|
||||
|
||||
transformToMaps(m_transform);
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=false;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::initFixMaps() {
|
||||
//when fixed no maps exist
|
||||
new(&m_translation) typename Kernel::Vector3Map(&fixtrans(0));
|
||||
m_translation = m_transform.translation().vector();
|
||||
init = true;
|
||||
midpoint.setZero();
|
||||
m_shift.setZero();
|
||||
m_ssrTransform.setIdentity();
|
||||
m_diffTrans = m_transform;
|
||||
fix=true;
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Init fix transform: "<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Kernel::Transform3D& ClusterMath<Sys>::getTransform() {
|
||||
return m_transform;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapsToTransform(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
//add scale only after possible reset
|
||||
typename Kernel::Transform3D::Scaling scale(m_transform.scaling());
|
||||
trans = m_diffTrans;
|
||||
trans *= scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::transformToMaps(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
const typename Kernel::Quaternion& m_quaternion = trans.rotation();
|
||||
if(m_quaternion.w() < 1.) {
|
||||
Scalar s = std::acos(m_quaternion.w())/std::sin(std::acos(m_quaternion.w()));
|
||||
m_normQ = m_quaternion.vec()*s;
|
||||
m_normQ /= NQFAKTOR;
|
||||
} else {
|
||||
m_normQ.setZero();
|
||||
}
|
||||
m_translation = trans.translation().vector();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishCalculation() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish calculation";
|
||||
#endif
|
||||
|
||||
mapsToTransform(m_transform);
|
||||
init=false;
|
||||
|
||||
m_transform = m_ssrTransform*m_transform;
|
||||
|
||||
//scale all geometries back to the original size
|
||||
m_diffTrans *= typename Kernel::Transform3D::Scaling(1./m_ssrTransform.scaling().factor());
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::finishFixCalculation() {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix calculation";
|
||||
#endif
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
m_transform *= m_ssrTransform.inverse();
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Finish fix transform:"<<std::endl<<m_transform;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::resetClusterRotation(typename ClusterMath<Sys>::Kernel::Transform3D& trans) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Reset cluster rotation:"<<std::endl<<m_diffTrans;
|
||||
#endif
|
||||
|
||||
trans = m_resetTransform.inverse()*trans;
|
||||
m_ssrTransform *= m_resetTransform;
|
||||
m_transform = m_resetTransform.inverse()*m_transform;
|
||||
|
||||
//apply the needed transformation to all geometries local values
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->transform(m_resetTransform);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::calcDiffTransform(typename ClusterMath<Sys>::Kernel::DiffTransform3D& trans) {
|
||||
|
||||
Scalar norm = m_normQ.norm();
|
||||
trans.setIdentity();
|
||||
|
||||
if(norm < 0.1) {
|
||||
if(norm == 0) {
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
} else {
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac,m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
resetClusterRotation(trans);
|
||||
}
|
||||
transformToMaps(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
const Scalar fac = std::sin(NQFAKTOR*norm)/norm;
|
||||
trans = typename Kernel::Quaternion(std::cos(NQFAKTOR*norm), m_normQ(0)*fac, m_normQ(1)*fac, m_normQ(2)*fac);
|
||||
trans *= typename Kernel::Transform3D::Translation(m_translation);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::recalculate() {
|
||||
|
||||
|
||||
calcDiffTransform(m_diffTrans);
|
||||
|
||||
const typename Kernel::Quaternion Q = m_diffTrans.rotation();
|
||||
|
||||
// now calculate the gradient quaternions and calculate the diff rotation matrices
|
||||
// m_normQ = (a,b,c)
|
||||
// n = ||m_normQ||
|
||||
//
|
||||
// Q = (a/n sin(n), b/n sin(n), c/n sin(n), cos(n))
|
||||
//
|
||||
|
||||
//n=||m_normQ||, sn = sin(n)/n, sn3 = sin(n)/n^3, cn = cos(n)/n, divn = 1/n;
|
||||
const Scalar n = m_normQ.norm();
|
||||
const Scalar sn = std::sin(NQFAKTOR*n)/n;
|
||||
const Scalar mul = (NQFAKTOR*std::cos(NQFAKTOR*n)-sn)/std::pow(n,2);
|
||||
|
||||
//dxa = dQx/da
|
||||
const Scalar dxa = sn + std::pow(m_normQ(0),2)*mul;
|
||||
const Scalar dxb = m_normQ(0)*m_normQ(1)*mul;
|
||||
const Scalar dxc = m_normQ(0)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dya = m_normQ(1)*m_normQ(0)*mul;
|
||||
const Scalar dyb = sn + std::pow(m_normQ(1),2)*mul;
|
||||
const Scalar dyc = m_normQ(1)*m_normQ(2)*mul;
|
||||
|
||||
const Scalar dza = m_normQ(2)*m_normQ(0)*mul;
|
||||
const Scalar dzb = m_normQ(2)*m_normQ(1)*mul;
|
||||
const Scalar dzc = sn + std::pow(m_normQ(2),2)*mul;
|
||||
|
||||
const Scalar dwa = -sn*NQFAKTOR*m_normQ(0);
|
||||
const Scalar dwb = -sn*NQFAKTOR*m_normQ(1);
|
||||
const Scalar dwc = -sn*NQFAKTOR*m_normQ(2);
|
||||
|
||||
//write in the diffrot matrix, starting with dQ/dx
|
||||
m_diffTrans.at(0,0) = -4.0*(Q.y()*dya+Q.z()*dza);
|
||||
m_diffTrans.at(0,1) = -2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(0,2) = 2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(1,0) = 2.0*(Q.w()*dza+dwa*Q.z())+2.0*(Q.x()*dya+dxa*Q.y());
|
||||
m_diffTrans.at(1,1) = -4.0*(Q.x()*dxa+Q.z()*dza);
|
||||
m_diffTrans.at(1,2) = -2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,0) = -2.0*(dwa*Q.y()+Q.w()*dya)+2.0*(dxa*Q.z()+Q.x()*dza);
|
||||
m_diffTrans.at(2,1) = 2.0*(dwa*Q.x()+Q.w()*dxa)+2.0*(dya*Q.z()+Q.y()*dza);
|
||||
m_diffTrans.at(2,2) = -4.0*(Q.x()*dxa+Q.y()*dya);
|
||||
|
||||
//dQ/dy
|
||||
m_diffTrans.at(0,3) = -4.0*(Q.y()*dyb+Q.z()*dzb);
|
||||
m_diffTrans.at(0,4) = -2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(0,5) = 2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(1,3) = 2.0*(Q.w()*dzb+dwb*Q.z())+2.0*(Q.x()*dyb+dxb*Q.y());
|
||||
m_diffTrans.at(1,4) = -4.0*(Q.x()*dxb+Q.z()*dzb);
|
||||
m_diffTrans.at(1,5) = -2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,3) = -2.0*(dwb*Q.y()+Q.w()*dyb)+2.0*(dxb*Q.z()+Q.x()*dzb);
|
||||
m_diffTrans.at(2,4) = 2.0*(dwb*Q.x()+Q.w()*dxb)+2.0*(dyb*Q.z()+Q.y()*dzb);
|
||||
m_diffTrans.at(2,5) = -4.0*(Q.x()*dxb+Q.y()*dyb);
|
||||
|
||||
//dQ/dz
|
||||
m_diffTrans.at(0,6) = -4.0*(Q.y()*dyc+Q.z()*dzc);
|
||||
m_diffTrans.at(0,7) = -2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(0,8) = 2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(1,6) = 2.0*(Q.w()*dzc+dwc*Q.z())+2.0*(Q.x()*dyc+dxc*Q.y());
|
||||
m_diffTrans.at(1,7) = -4.0*(Q.x()*dxc+Q.z()*dzc);
|
||||
m_diffTrans.at(1,8) = -2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,6) = -2.0*(dwc*Q.y()+Q.w()*dyc)+2.0*(dxc*Q.z()+Q.x()*dzc);
|
||||
m_diffTrans.at(2,7) = 2.0*(dwc*Q.x()+Q.w()*dxc)+2.0*(dyc*Q.z()+Q.y()*dzc);
|
||||
m_diffTrans.at(2,8) = -4.0*(Q.x()*dxc+Q.y()*dyc);
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->recalculate(m_diffTrans);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::addGeometry(Geom g) {
|
||||
m_geometry.push_back(g);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::clearGeometry() {
|
||||
m_geometry.clear();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
std::vector<typename ClusterMath<Sys>::Geom>& ClusterMath<Sys>::getGeometry() {
|
||||
return m_geometry;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
ClusterMath<Sys>::map_downstream::map_downstream(details::ClusterMath<Sys>& cm, bool fix)
|
||||
: m_clusterMath(cm), m_isFixed(fix) {
|
||||
m_transform = m_clusterMath.getTransform().inverse();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(Geom g) {
|
||||
//allow iteration over all maped geometries
|
||||
m_clusterMath.addGeometry(g);
|
||||
//set the offsets so that geometry knows where it is in the parameter map
|
||||
g->m_offset = m_clusterMath.getParameterOffset(general);
|
||||
g->m_offset_rot = m_clusterMath.getParameterOffset(rotation);
|
||||
//position and offset of the parameters must be set to the clusters values
|
||||
g->setClusterMode(true, m_isFixed);
|
||||
//calculate the appropriate local values
|
||||
g->transform(m_transform);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::map_downstream::operator()(boost::shared_ptr<Cluster> c) {
|
||||
//we transform the GLOBAL geometries to local ones in the subcluster! therefore
|
||||
//we are not interested in the successive transformations, we only transform the
|
||||
//global geometries with the cluster transform we want them to be local in, and thats
|
||||
//the one supplied in the constructor
|
||||
//m_transform *= c->template getClusterProperty<math_prop>().getTransform().inverse();
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::mapClusterDownstreamGeometry(boost::shared_ptr<Cluster> cluster) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Map downstream geometry";
|
||||
#endif
|
||||
|
||||
map_downstream down(cluster->template getProperty<math_prop>(),
|
||||
cluster->template getProperty<fix_prop>());
|
||||
cluster->template for_each<Geometry3D>(down, true);
|
||||
//TODO: if one subcluster is fixed the hole cluster should be too, as there are no
|
||||
// dof's remaining between parts and so nothing can be moved when one part is fixed.
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calculateClusterScale() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale with transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transformation
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Calculate cluster scale sec transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
|
||||
//collect all points together
|
||||
m_points.clear();
|
||||
typename Kernel::Transform3D trans(m_transform.rotation(), m_transform.translation());
|
||||
trans.invert();
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_pseudo.begin(); it != m_pseudo.end(); it++) {
|
||||
m_points.push_back(trans*(*it));
|
||||
}
|
||||
typedef typename std::vector<Geom>::iterator g_iter;
|
||||
for(g_iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
m_points.push_back((*it)->getPoint());
|
||||
|
||||
//start scale calculation
|
||||
if(m_points.empty()) return 1.;
|
||||
else if(m_points.size() == 1) {
|
||||
const typename Kernel::Vector3 p = m_points[0];
|
||||
return calcOnePoint(p);
|
||||
} else if(m_points.size() == 2) {
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
|
||||
if(Kernel::isSame((p1-p2).norm(), 0., 1e-10))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(m_points.size() == 3) {
|
||||
|
||||
const typename Kernel::Vector3 p1 = m_points[0];
|
||||
const typename Kernel::Vector3 p2 = m_points[1];
|
||||
const typename Kernel::Vector3 p3 = m_points[2];
|
||||
|
||||
const typename Kernel::Vector3 d = p2-p1;
|
||||
const typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
if(Kernel::isSame(d.norm(), 0., 1e-10)) {
|
||||
|
||||
if(Kernel::isSame(e.norm(), 0., 1e-10))
|
||||
return calcOnePoint(p1);
|
||||
|
||||
return calcTwoPoints(p1, p3);
|
||||
} else if(Kernel::isSame(e.norm(), 0., 1e-10)) {
|
||||
return calcTwoPoints(p1, p2);
|
||||
} else if(!Kernel::isSame((d/d.norm() - e/e.norm()).norm(), 0., 1e-10) &&
|
||||
!Kernel::isSame((d/d.norm() + e/e.norm()).norm(), 0., 1e-10)) {
|
||||
return calcThreePoints(p1, p2, p3);
|
||||
}
|
||||
//three points on a line need to be treaded as multiple points
|
||||
}
|
||||
|
||||
//more than 3 points dont have a exakt solution. we search for a midpoint from which all points
|
||||
//are at least MAXFAKTOR*scale away, but not closer than MINFAKTOR*scale
|
||||
|
||||
//get the bonding box to get the center of points
|
||||
Scalar xmin=1e10, xmax=1e-10, ymin=1e10, ymax=1e-10, zmin=1e10, zmax=1e-10;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
typename Kernel::Vector3 v = (*it);
|
||||
xmin = (v(0)<xmin) ? v(0) : xmin;
|
||||
xmax = (v(0)<xmax) ? xmax : v(0);
|
||||
ymin = (v(1)<ymin) ? v(1) : ymin;
|
||||
ymax = (v(1)<ymax) ? ymax : v(1);
|
||||
zmin = (v(2)<zmin) ? v(2) : zmin;
|
||||
zmax = (v(2)<zmax) ? zmax : v(2);
|
||||
};
|
||||
//now calculate the midpoint
|
||||
midpoint << xmin+xmax, ymin+ymax, zmin+zmax;
|
||||
midpoint /= 2.;
|
||||
|
||||
|
||||
//get the scale direction an the resulting nearest point indexes
|
||||
double xh = xmax-xmin;
|
||||
double yh = ymax-ymin;
|
||||
double zh = zmax-zmin;
|
||||
int i1, i2, i3;
|
||||
if((xh<=yh) && (xh<=zh)) {
|
||||
i1=1;
|
||||
i2=2;
|
||||
i3=0;
|
||||
} else if((yh<xh) && (yh<zh)) {
|
||||
i1=0;
|
||||
i2=2;
|
||||
i3=1;
|
||||
} else {
|
||||
i1=0;
|
||||
i2=1;
|
||||
i3=2;
|
||||
}
|
||||
scale_dir.setZero();
|
||||
scale_dir(i3) = 1;
|
||||
max = Eigen::Vector3d(xmin,ymin,zmin);
|
||||
m_scale = (midpoint-max).norm()/MAXFAKTOR;
|
||||
mode = multiple_inrange;
|
||||
|
||||
maxm = max-midpoint;
|
||||
Scalar minscale = 1e10;
|
||||
|
||||
//get the closest point
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*m_scale) {
|
||||
|
||||
const double h = std::abs(point(i3)-maxm(i3));
|
||||
const double k = std::pow(MINFAKTOR/MAXFAKTOR,2);
|
||||
double q = std::pow(point(i1),2) + std::pow(point(i2),2);
|
||||
q -= (std::pow(maxm(i1),2) + std::pow(maxm(i2),2) + std::pow(h,2))*k;
|
||||
q /= 1.-k;
|
||||
|
||||
const double p = h*k/(1.-k);
|
||||
|
||||
if(std::pow(p,2)<q) assert(false);
|
||||
|
||||
midpoint(i3) += p + std::sqrt(std::pow(p,2)-q);
|
||||
maxm = max-midpoint;
|
||||
m_scale = maxm.norm()/MAXFAKTOR;
|
||||
|
||||
mode = multiple_outrange;
|
||||
minm = (*it)-midpoint;
|
||||
|
||||
it = m_points.begin();
|
||||
} else if(point.norm()<minscale) {
|
||||
minscale = point.norm();
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==multiple_inrange) {
|
||||
//we are in the range, let's get the perfect balanced scale value
|
||||
m_scale = (minscale+maxm.norm())/2.;
|
||||
}
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ClusterMath<Sys>::applyClusterScale(Scalar scale, bool isFixed) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Apply cluster scale: "<<scale;
|
||||
BOOST_LOG(log) << "initial transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
//ensure the usage of the right transform
|
||||
if(!fix)
|
||||
mapsToTransform(m_transform);
|
||||
|
||||
|
||||
|
||||
//when fixed, the geometries never get recalculated. therefore we have to do a calculate now
|
||||
//to alow the adoption of the scale. and no shift should been set.
|
||||
if(isFixed) {
|
||||
m_transform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
m_ssrTransform*=typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
typename Kernel::DiffTransform3D diff(m_transform);
|
||||
//now calculate the scaled geometrys
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++) {
|
||||
(*it)->recalculate(diff);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "Fixed cluster geometry value:" << (*it)->m_rotated.transpose();
|
||||
#endif
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
//if this is our scale then just applie the midpoint as shift
|
||||
if(Kernel::isSame(scale, m_scale, 1e-10)) {
|
||||
|
||||
}
|
||||
//if only one point exists we extend the origin-point-line to match the scale
|
||||
else if(mode==details::one) {
|
||||
if(Kernel::isSame(midpoint.norm(),0, 1e-10))
|
||||
midpoint << scale, 0, 0;
|
||||
else midpoint += scale*scale_dir;
|
||||
}
|
||||
//two and three points form a rectangular triangle, so same procedure
|
||||
else if(mode==details::two || mode==details::three) {
|
||||
|
||||
midpoint+= scale_dir*std::sqrt(std::pow(scale,2) - std::pow(m_scale,2));
|
||||
}
|
||||
//multiple points
|
||||
else if(mode==details::multiple_outrange) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(maxm(1),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(0) += maxm(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(1) += maxm(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(maxm(0),2) + std::pow(maxm(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MAXFAKTOR*scale,2)-d);
|
||||
midpoint(2) += maxm(2) + h;
|
||||
}
|
||||
} else {
|
||||
|
||||
//TODO: it's possible that for this case we get too far away from the outer points.
|
||||
// The m_scale for "midpoint outside the bounding box" may be bigger than the
|
||||
// scale to applie, so it results in an error.
|
||||
//get the closest point
|
||||
typedef typename Vec::iterator iter;
|
||||
for(iter it = m_points.begin(); it != m_points.end(); it++) {
|
||||
|
||||
const Eigen::Vector3d point = (*it)-midpoint;
|
||||
if(point.norm()<MINFAKTOR*scale) {
|
||||
|
||||
if(scale_dir(0)) {
|
||||
Scalar d = std::pow(point(1),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(0) += point(0) + h;
|
||||
} else if(scale_dir(1)) {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(2),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(1) += point(1) + h;
|
||||
} else {
|
||||
Scalar d = std::pow(point(0),2) + std::pow(point(1),2);
|
||||
Scalar h = std::sqrt(std::pow(MINFAKTOR*scale,2)-d);
|
||||
midpoint(2) += point(2) + h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typename Kernel::Transform3D ssTrans;
|
||||
ssTrans = typename Kernel::Transform3D::Translation(-midpoint);
|
||||
ssTrans *= typename Kernel::Transform3D::Scaling(1./(scale*SKALEFAKTOR));
|
||||
|
||||
//recalculate all geometries
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it = m_geometry.begin(); it != m_geometry.end(); it++)
|
||||
(*it)->transform(ssTrans);
|
||||
|
||||
//set the new rotation and translation
|
||||
m_transform = ssTrans.inverse()*m_transform;
|
||||
m_ssrTransform *= ssTrans;
|
||||
|
||||
transformToMaps(m_transform);
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "sstrans scale: "<<ssTrans.scaling().factor();
|
||||
BOOST_LOG(log) << "finish transform scale: "<<m_transform.scaling().factor();
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcOnePoint(const typename ClusterMath<Sys>::Kernel::Vector3& p) {
|
||||
|
||||
//one point can have every scale when moving the midpoint on the origin - point vector
|
||||
midpoint = p;
|
||||
scale_dir = -midpoint;
|
||||
scale_dir.normalize();
|
||||
mode = details::one;
|
||||
m_scale = 0.;
|
||||
return 0.;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcTwoPoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2) {
|
||||
|
||||
//two points have their minimal scale at the mid position. Scaling perpendicular to this
|
||||
//line allows arbitrary scale values. Best is to have the scale dir move towards the origin
|
||||
//as good as possible.
|
||||
midpoint = p1+(p2-p1)/2.;
|
||||
scale_dir = (p2-p1).cross(midpoint);
|
||||
scale_dir = scale_dir.cross(p2-p1);
|
||||
if(!Kernel::isSame(scale_dir.norm(),0, 1e-10)) scale_dir.normalize();
|
||||
else scale_dir(0) = 1;
|
||||
mode = details::two;
|
||||
m_scale = (p2-p1).norm()/2.;
|
||||
return m_scale;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename ClusterMath<Sys>::Scalar ClusterMath<Sys>::calcThreePoints(const typename ClusterMath<Sys>::Kernel::Vector3& p1,
|
||||
const typename ClusterMath<Sys>::Kernel::Vector3& p2, const typename ClusterMath<Sys>::Kernel::Vector3& p3) {
|
||||
|
||||
//Three points form a triangle with it's minimal scale at the center of it's outer circle.
|
||||
//Arbitrary scale values can be achieved by moving perpendicular to the triangle plane.
|
||||
typename Kernel::Vector3 d = p2-p1;
|
||||
typename Kernel::Vector3 e = p3-p1;
|
||||
|
||||
typename Kernel::Vector3 f = p1+0.5*d;
|
||||
typename Kernel::Vector3 g = p1+0.5*e;
|
||||
scale_dir = d.cross(e);
|
||||
|
||||
typename Kernel::Matrix3 m;
|
||||
m.row(0) = d.transpose();
|
||||
m.row(1) = e.transpose();
|
||||
m.row(2) = scale_dir.transpose();
|
||||
|
||||
typename Kernel::Vector3 res(d.transpose()*f, e.transpose()*g, scale_dir.transpose()*p1);
|
||||
|
||||
midpoint = m.colPivHouseholderQr().solve(res);
|
||||
scale_dir.normalize();
|
||||
mode = details::three;
|
||||
m_scale = (midpoint-p1).norm();
|
||||
|
||||
return m_scale;
|
||||
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
|
||||
#endif //GCM_CLUSTERMATH_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CONSTRAINT_3D_HOLDER_IMP_H
|
||||
#define DCM_CONSTRAINT_3D_HOLDER_IMP_H
|
||||
|
||||
#include "../geometry.hpp"
|
||||
#include "opendcm/core/imp/constraint_holder_imp.hpp"
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
//following macros are used for externalisation. As the holder type can hould a very big set of combinations,
|
||||
//especially with module states recursive incarnation, we explicitly initiate all possible versions of this
|
||||
//struct so that it must only be compiled once. To get all possible equation
|
||||
//combinations boost pp is needed.
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct fusion_vec {
|
||||
typedef typename mpl::if_< mpl::is_sequence<T>, T, fusion::vector1<T> >::type type;
|
||||
};
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/for.hpp>
|
||||
#include <boost/preprocessor/comparison/less.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/preprocessor/seq/elem.hpp>
|
||||
#include <boost/preprocessor/seq/push_front.hpp>
|
||||
#include <boost/preprocessor/seq/remove.hpp>
|
||||
|
||||
#define TAG_SEQUENCE (dcm::tag::direction3D)(dcm::tag::point3D)(dcm::tag::line3D)(dcm::tag::plane3D)(dcm::tag::cylinder3D)
|
||||
#define CONSTRAINT_SEQUENCE (dcm::Distance)(dcm::Orientation)(dcm::Angle)(dcm::Coincidence)(dcm::Alignment)
|
||||
|
||||
#define LEVEL_2_TYPE(r, state) \
|
||||
template struct dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::holder<fusion_vec<BOOST_PP_SEQ_ELEM(2,state)>::type, BOOST_PP_SEQ_ELEM(3,state), BOOST_PP_SEQ_ELEM(4,state)>;
|
||||
|
||||
#define LEVEL_2_TYPE_OP(r, state) \
|
||||
BOOST_PP_SEQ_REMOVE(state,4)
|
||||
|
||||
#define LEVEL_2_TYPE_PRED(r, state) \
|
||||
BOOST_PP_LESS(4,BOOST_PP_SEQ_SIZE(state))
|
||||
|
||||
#define LEVEL_1_TYPE(r, state) \
|
||||
template struct dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::holder<fusion_vec<BOOST_PP_SEQ_ELEM(2,state)>::type, BOOST_PP_SEQ_ELEM(3,state), BOOST_PP_SEQ_ELEM(3,state)>;\
|
||||
BOOST_PP_FOR(state, LEVEL_2_TYPE_PRED, LEVEL_2_TYPE_OP, LEVEL_2_TYPE)
|
||||
|
||||
#define LEVEL_1_TYPE_OP(r, state) \
|
||||
BOOST_PP_SEQ_REMOVE(state,3)
|
||||
|
||||
#define LEVEL_1_TYPE_PRED(r, state) \
|
||||
BOOST_PP_LESS(3,BOOST_PP_SEQ_SIZE(state))
|
||||
|
||||
#define INITIALIZE_TYPES(System, Dim, Covec, SEQUENCE) \
|
||||
BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Covec), Dim), System), LEVEL_1_TYPE_PRED, LEVEL_1_TYPE_OP, LEVEL_1_TYPE)
|
||||
|
||||
|
||||
#define LEVEL_1(r, state) \
|
||||
INITIALIZE_TYPES(BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state), BOOST_PP_SEQ_ELEM(2,state), TAG_SEQUENCE) \
|
||||
|
||||
#define LEVEL_1_OP(r, state) \
|
||||
BOOST_PP_SEQ_REMOVE(state,2)
|
||||
|
||||
#define LEVEL_1_PRED(r, state) \
|
||||
BOOST_PP_LESS(2,BOOST_PP_SEQ_SIZE(state))
|
||||
|
||||
#define INITIALIZE(System, Dim, SEQUENCE) \
|
||||
BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Dim), System), LEVEL_1_PRED, LEVEL_1_OP, LEVEL_1)
|
||||
|
||||
#endif //external
|
||||
|
||||
#endif
|
||||
119
src/Mod/Assembly/App/opendcm/module3d/imp/constraint3d_imp.hpp
Normal file
119
src/Mod/Assembly/App/opendcm/module3d/imp/constraint3d_imp.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_CONSTRAINT_3D_IMP_H
|
||||
#define DCM_CONSTRAINT_3D_IMP_H
|
||||
|
||||
#include "../module.hpp"
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
#include "opendcm/core/imp/constraint_imp.hpp"
|
||||
#include "opendcm/core/imp/object_imp.hpp"
|
||||
#include "opendcm/core/imp/clustergraph_imp.hpp"
|
||||
#endif
|
||||
|
||||
// #ifdef DCM_EXTERNAL_CORE
|
||||
// //following macros are used for externalisation. As constraint->initalize is very compiler intensive,
|
||||
// //especially with module states recursive incarnation, we explicitly initiate all possible calls to this
|
||||
// //function so that it must only be compiled once, one function at a time. To get all possible equation
|
||||
// //combinations boost pp is needed.
|
||||
//
|
||||
// #include <boost/preprocessor.hpp>
|
||||
// #include <boost/preprocessor/for.hpp>
|
||||
// #include <boost/preprocessor/comparison/less.hpp>
|
||||
// #include <boost/preprocessor/seq/size.hpp>
|
||||
// #include <boost/preprocessor/seq/enum.hpp>
|
||||
// #include <boost/preprocessor/seq/elem.hpp>
|
||||
// #include <boost/preprocessor/seq/push_front.hpp>
|
||||
// #include <boost/preprocessor/seq/remove.hpp>
|
||||
//
|
||||
// #define SEQUENCE (dcm::Distance)(dcm::Orientation)(dcm::Angle)(dcm::Coincidence)(dcm::Alignment)
|
||||
//
|
||||
// #define LEVEL_1(r, state) \
|
||||
// template void dcm::detail::Constraint<BOOST_PP_SEQ_ELEM(0,state), BOOST_PP_SEQ_ELEM(1,state)>::initialize(BOOST_PP_SEQ_ELEM(2,state)&); \
|
||||
//
|
||||
// #define LEVEL_1_OP(r, state) \
|
||||
// BOOST_PP_SEQ_REMOVE(state,2)
|
||||
//
|
||||
// #define LEVEL_1_PRED(r, state) \
|
||||
// BOOST_PP_LESS(2,BOOST_PP_SEQ_SIZE(state))
|
||||
//
|
||||
// #define INITIALIZE(System, Dim) \
|
||||
// BOOST_PP_FOR(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_FRONT(SEQUENCE, Dim), System), LEVEL_1_PRED, LEVEL_1_OP, LEVEL_1)
|
||||
//
|
||||
// #endif //external
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Constraint3D_base<Derived>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//copy the internals
|
||||
np->content = CBase::content->clone();
|
||||
//and get the geometry pointers right
|
||||
if(CBase::first) {
|
||||
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::first)->template getProperty<vertex_prop>();
|
||||
np->first = newSys.m_cluster->template getObject<Geometry3D>(v);
|
||||
}
|
||||
if(CBase::second) {
|
||||
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::second)->template getProperty<vertex_prop>();
|
||||
np->second = newSys.m_cluster->template getObject<Geometry3D>(v);
|
||||
}
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::Constraint3D_id(Sys& system, Geom f, Geom s)
|
||||
: Constraint3D_base<Derived>(system, f, s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D::Constraint3D(Sys& system, Geom first, Geom second)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Constraint3D_base<Constraint3D>,
|
||||
Constraint3D_id<Constraint3D> >::type(system, first, second) {
|
||||
};
|
||||
|
||||
} //dcm
|
||||
|
||||
#endif //DCM_MODULE_3D_IMP_H
|
||||
256
src/Mod/Assembly/App/opendcm/module3d/imp/geometry3d_imp.hpp
Normal file
256
src/Mod/Assembly/App/opendcm/module3d/imp/geometry3d_imp.hpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_GEOMETRY_3D_IMP_H
|
||||
#define DCM_GEOMETRY_3D_IMP_H
|
||||
|
||||
#include "../module.hpp"
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
#include "opendcm/core/imp/geometry_imp.hpp"
|
||||
#include "opendcm/core/imp/object_imp.hpp"
|
||||
#endif
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Variant>
|
||||
struct cloner : boost::static_visitor<void> {
|
||||
|
||||
Variant variant;
|
||||
cloner(Variant& v) : variant(v) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(T& t) {
|
||||
variant = geometry_clone_traits<T>()(t);
|
||||
};
|
||||
};
|
||||
|
||||
//visitor to write the calculated value into the variant
|
||||
template<typename Kernel>
|
||||
struct apply_visitor : public boost::static_visitor<void> {
|
||||
|
||||
apply_visitor(typename Kernel::Vector& v) : value(v) {};
|
||||
template <typename T>
|
||||
void operator()(T& t) const {
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
|
||||
typename geometry_traits<T>::accessor >(t, value);
|
||||
}
|
||||
typename Kernel::Vector& value;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(Sys& system)
|
||||
: Object<Sys, Derived, GeomSig>(system) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(const T& geometry, Sys& system)
|
||||
: Object<Sys, Derived, GeomSig>(system) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
|
||||
#endif
|
||||
|
||||
m_geometry = geometry;
|
||||
//first init, so that the geometry internal vector has the right size
|
||||
Base::template init< typename geometry_traits<T>::tag >();
|
||||
//now write the value;
|
||||
(typename geometry_traits<T>::modell()).template extract<Scalar,
|
||||
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::set(const T& geometry) {
|
||||
|
||||
m_geometry = geometry;
|
||||
//first init, so that the geometry internal vector has the right size
|
||||
Base::template init< typename geometry_traits<T>::tag >();
|
||||
//now write the value;
|
||||
(typename geometry_traits<T>::modell()).template extract<Scalar,
|
||||
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
|
||||
|
||||
reset();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
T Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::convertTo() {
|
||||
T t;
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
|
||||
typename geometry_traits<T>::accessor >(t, Base::m_global);
|
||||
return t;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename Visitor>
|
||||
typename Visitor::result_type Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::apply(Visitor& vis) {
|
||||
return boost::apply_visitor(vis, m_geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//it's possible that the variant contains pointers, so we need to clone them
|
||||
details::cloner<Variant> clone_fnc(np->m_geometry);
|
||||
boost::apply_visitor(clone_fnc, m_geometry);
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::recalculated() {
|
||||
|
||||
details::apply_visitor<Kernel> v(Base::getValue());
|
||||
apply(v);
|
||||
|
||||
ObjBase::template emitSignal<dcm::recalculated>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::removed() {
|
||||
|
||||
ObjBase::template emitSignal<dcm::remove>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::reset() {
|
||||
|
||||
ObjBase::template emitSignal<dcm::reset>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(Sys& system)
|
||||
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(system)
|
||||
#ifdef USE_LOGGING
|
||||
, log_id("No ID")
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
Base::log.add_attribute("ID", log_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(const T& geometry, Sys& system)
|
||||
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(geometry, system)
|
||||
#ifdef USE_LOGGING
|
||||
, log_id("No ID")
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
Base::log.add_attribute("ID", log_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(const T& geometry, Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(const T& geometry) {
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
#ifdef USE_LOGGING
|
||||
std::stringstream str;
|
||||
str<<this->template getProperty<id_prop<Identifier> >();
|
||||
log_id.set(str.str());
|
||||
BOOST_LOG(Base::log)<<"Identifyer set: "<<id;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(Sys& system)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Geometry3D_base<Geometry3D>,
|
||||
Geometry3D_id<Geometry3D> >::type(system) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(const T& geometry, Sys& system)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Geometry3D_base<Geometry3D>,
|
||||
Geometry3D_id<Geometry3D> >::type(geometry, system) {
|
||||
|
||||
};
|
||||
|
||||
} //dcm
|
||||
|
||||
#endif //DCM_MODULE_3D_IMP_H
|
||||
268
src/Mod/Assembly/App/opendcm/module3d/imp/module_imp.hpp
Normal file
268
src/Mod/Assembly/App/opendcm/module3d/imp/module_imp.hpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE_3D_IMP_H
|
||||
#define DCM_MODULE_3D_IMP_H
|
||||
|
||||
#include "../module.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "constraint3d_imp.hpp"
|
||||
#include "geometry3d_imp.hpp"
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
// template<typename seq, typename t>
|
||||
// struct distance {
|
||||
// typedef typename mpl::find<seq, t>::type iterator;
|
||||
// typedef typename mpl::distance<typename mpl::begin<seq>::type, iterator>::type type;
|
||||
// BOOST_MPL_ASSERT((mpl::not_< boost::is_same<iterator, typename mpl::end<seq>::type > >));
|
||||
// };
|
||||
|
||||
//build a constraint vector
|
||||
template<typename T>
|
||||
struct fusion_vec {
|
||||
typedef typename mpl::if_< mpl::is_sequence<T>,
|
||||
T, fusion::vector1<T> >::type type;
|
||||
};
|
||||
|
||||
struct set_constraint_option {
|
||||
|
||||
template<typename T>
|
||||
typename boost::enable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
|
||||
operator()(T& val) {
|
||||
return val;
|
||||
};
|
||||
template<typename T>
|
||||
typename boost::disable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
|
||||
operator()(T& val) {
|
||||
typename fusion_vec<T>::type vec;
|
||||
fusion::at_c<0>(vec) = val;
|
||||
return vec;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
|
||||
m_this = ((Sys*) this);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D() {
|
||||
|
||||
Geom g(new Geometry3D(* ((Sys*) this)));
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
|
||||
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
|
||||
m_this->push_back(g);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D(T geom) {
|
||||
|
||||
Geom g(new Geometry3D(geom, * ((Sys*) this)));
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
|
||||
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
|
||||
m_this->push_back(g);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeGeometry3D(Geom g) {
|
||||
|
||||
GlobalVertex v = g->template getProperty<vertex_prop>();
|
||||
|
||||
//check if this vertex holds a constraint
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(v);
|
||||
if(c)
|
||||
c->template emitSignal<remove>(c);
|
||||
|
||||
//emit remove geometry signal bevore actually deleting it, in case anyone want to access the
|
||||
//graph before
|
||||
g->template emitSignal<remove>(g);
|
||||
|
||||
//remove the vertex from graph and emit all edges that get removed with the functor
|
||||
boost::function<void(GlobalEdge)> functor = boost::bind(&inheriter_base::apply_edge_remove, this, _1);
|
||||
m_this->m_cluster->removeVertex(v, functor);
|
||||
m_this->erase(g);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T1>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createConstraint3D(Geom first, Geom second, T1 constraint1) {
|
||||
|
||||
//get the fusion vector type
|
||||
typedef typename details::fusion_vec<T1>::type covec;
|
||||
|
||||
//set the objects
|
||||
covec cv = details::set_constraint_option()(constraint1);
|
||||
|
||||
//now create the constraint
|
||||
Cons c(new Constraint3D(*m_this, first, second));
|
||||
//initialize constraint
|
||||
c->initialize(cv);
|
||||
|
||||
//add it to the clustergraph
|
||||
fusion::vector<LocalEdge, GlobalEdge, bool, bool> res;
|
||||
res = m_this->m_cluster->addEdge(first->template getProperty<vertex_prop>(),
|
||||
second->template getProperty<vertex_prop>());
|
||||
if(!fusion::at_c<2>(res)) {
|
||||
Cons rc;
|
||||
return rc; //TODO: throw
|
||||
};
|
||||
m_this->m_cluster->template setObject<Constraint3D> (fusion::at_c<1> (res), c);
|
||||
//add the coresbondig edge to the constraint
|
||||
c->template setProperty<edge_prop>(fusion::at_c<1>(res));
|
||||
//store the constraint in general object vector of main system
|
||||
m_this->push_back(c);
|
||||
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeConstraint3D(Cons c) {
|
||||
|
||||
GlobalEdge e = c->template getProperty<edge_prop>();
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->m_cluster->removeEdge(e);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::apply_edge_remove(GlobalEdge e) {
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(e);
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(T geom, Identifier id) {
|
||||
Geom g = inheriter_base::createGeometry3D(geom);
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(Identifier id) {
|
||||
Geom g = inheriter_base::createGeometry3D();
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeGeometry3D(Identifier id) {
|
||||
|
||||
if(hasGeometry3D(id))
|
||||
inheriter_base::removeGeometry3D(getGeometry3D(id));
|
||||
else
|
||||
throw module3d_error() << boost::errinfo_errno(410) << error_message("no geometry with this ID in this system");
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createConstraint3D(Identifier id, Geom first, Geom second, T constraint1) {
|
||||
|
||||
Cons c = inheriter_base::createConstraint3D(first, second, constraint1);
|
||||
c->setIdentifier(id);
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeConstraint3D(Identifier id) {
|
||||
|
||||
if(hasConstraint3D(id))
|
||||
removeConstraint3D(getConstraint3D(id));
|
||||
else
|
||||
throw module3d_error() << boost::errinfo_errno(411) << error_message("no constraint with this ID in this system");
|
||||
};
|
||||
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasGeometry3D(Identifier id) {
|
||||
if(getGeometry3D(id))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getGeometry3D(Identifier id) {
|
||||
std::vector< Geom >& vec = inheriter_base::m_this->template objectVector<Geometry3D>();
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
return Geom();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasConstraint3D(Identifier id) {
|
||||
if(getConstraint3D(id))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getConstraint3D(Identifier id) {
|
||||
std::vector< Cons >& vec = inheriter_base::m_this->template objectVector<Constraint3D>();
|
||||
typedef typename std::vector<Cons>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
return Cons();
|
||||
};
|
||||
|
||||
} //dcm
|
||||
|
||||
#endif //DCM_MODULE_3D_IMP_H
|
||||
410
src/Mod/Assembly/App/opendcm/module3d/imp/solver_imp.hpp
Normal file
410
src/Mod/Assembly/App/opendcm/module3d/imp/solver_imp.hpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2012 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_SOLVER_3D_IMP_H
|
||||
#define DCM_SOLVER_3D_IMP_H
|
||||
|
||||
#include "../solver.hpp"
|
||||
|
||||
#include <boost/graph/undirected_dfs.hpp>
|
||||
|
||||
#ifdef DCM_EXTERNAL_CORE
|
||||
#include "opendcm/core/imp/kernel_imp.hpp"
|
||||
#include "opendcm/core/imp/clustergraph_imp.hpp"
|
||||
#endif
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
MES<Sys>::MES(boost::shared_ptr<Cluster> cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) {
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("MES3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void MES<Sys>::recalculate() {
|
||||
|
||||
//first calculate all clusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = m_cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
if(!(*cit.first).second->template getProperty<fix_prop>())
|
||||
(*cit.first).second->template getProperty<math_prop>().recalculate();
|
||||
|
||||
};
|
||||
|
||||
//with everything updated just nicely we can compute the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
|
||||
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
|
||||
for(; eit.first != eit.second; eit.first++) {
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
if(*oit.first)
|
||||
(*oit.first)->calculate(Base::Scaling, Base::rot_only);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void MES<Sys>::removeLocalGradientZeros() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "remove local gradient zero";
|
||||
#endif
|
||||
//let the constraints treat the local zeros
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
|
||||
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
|
||||
for(; eit.first != eit.second; eit.first++) {
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
if(*oit.first)
|
||||
(*oit.first)->treatLGZ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::Rescaler::Rescaler(boost::shared_ptr<Cluster> c, Mes& m) : cluster(c), mes(m), rescales(0) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::operator()() {
|
||||
mes.Scaling = scaleClusters();
|
||||
rescales++;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename SystemSolver<Sys>::Scalar SystemSolver<Sys>::Rescaler::scaleClusters() {
|
||||
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
//get the maximal scale
|
||||
Scalar sc = 0;
|
||||
for(cit = cluster->clusters(); cit.first != cit.second; cit.first++) {
|
||||
//fixed cluster are irrelevant for scaling
|
||||
if((*cit.first).second->template getProperty<fix_prop>())
|
||||
continue;
|
||||
|
||||
//get the biggest scale factor
|
||||
details::ClusterMath<Sys>& math = (*cit.first).second->template getProperty<math_prop>();
|
||||
|
||||
math.m_pseudo.clear();
|
||||
collectPseudoPoints(cluster, (*cit.first).first, math.m_pseudo);
|
||||
|
||||
const Scalar s = math.calculateClusterScale();
|
||||
sc = (s>sc) ? s : sc;
|
||||
}
|
||||
//if no scaling-value returned we can use 1
|
||||
sc = (Kernel::isSame(sc,0, 1e-10)) ? 1. : sc;
|
||||
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
c->template getProperty<math_prop>().applyClusterScale(sc,
|
||||
c->template getProperty<fix_prop>());
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(sc*SKALEFAKTOR);
|
||||
}
|
||||
}
|
||||
return 1./(sc*SKALEFAKTOR);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::collectPseudoPoints(
|
||||
boost::shared_ptr<typename SystemSolver<Sys>::Cluster> parent,
|
||||
LocalVertex cluster,
|
||||
std::vector<typename SystemSolver<Sys>::Kernel::Vector3,
|
||||
Eigen::aligned_allocator<typename SystemSolver<Sys>::Kernel::Vector3> >& vec) {
|
||||
|
||||
std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > vec2;
|
||||
typedef typename Cluster::global_edge_iterator c_iter;
|
||||
typedef typename boost::graph_traits<Cluster>::out_edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> it = boost::out_edges(cluster, *parent);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
std::pair< c_iter, c_iter > cit = parent->getGlobalEdges(*it.first);
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
Cons c = parent->template getObject<Constraint3D>(*cit.first);
|
||||
|
||||
if(!c)
|
||||
continue;
|
||||
|
||||
//get the first global vertex and see if we have it in the wanted cluster or not
|
||||
GlobalVertex v = cit.first->source;
|
||||
std::pair<LocalVertex,bool> res = parent->getLocalVertex(v);
|
||||
if(!res.second)
|
||||
return; //means the geometry is in non of the clusters which is not allowed
|
||||
|
||||
if(res.first == cluster)
|
||||
c->collectPseudoPoints(vec, vec2);
|
||||
else
|
||||
c->collectPseudoPoints(vec2, vec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::SystemSolver() {
|
||||
Job<Sys>::priority = 1000;
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("SystemSolver3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::execute(Sys& sys) {
|
||||
solveCluster(sys.m_cluster, sys);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys) {
|
||||
|
||||
try {
|
||||
//set out and solve all relevant subclusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
boost::shared_ptr<Cluster> c = (*cit.first).second;
|
||||
if(c->template getProperty<changed_prop>() &&
|
||||
c->template getProperty<type_prop>() == details::cluster3D)
|
||||
solveCluster(c, sys);
|
||||
}
|
||||
|
||||
int params=0, constraints=0;
|
||||
typename Kernel::number_type scale = 1;
|
||||
|
||||
//get the ammount of parameters and constraint equations we need
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
//when cluster and not fixed it has trans and rot parameter
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first)) {
|
||||
params += 6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
params += cluster->template getObject<Geometry3D>(*it.first)->m_parameterCount;
|
||||
};
|
||||
}
|
||||
|
||||
//count the equations in the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> ocit;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
std::pair< ocit, ocit > it = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; it.first != it.second; it.first++)
|
||||
constraints += (*it.first)->equationCount();
|
||||
};
|
||||
|
||||
if(params <= 0 || constraints <= 0) {
|
||||
//TODO:throw
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Error in system counting: params = " << params << " and constraints = "<<constraints;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//initialise the system with now known size
|
||||
Mes mes(cluster, params, constraints);
|
||||
|
||||
//iterate all geometrys again and set the needed maps
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
details::ClusterMath<Sys>& cm = c->template getProperty<math_prop>();
|
||||
//only get maps and propagate downstream if not fixed
|
||||
if(!c->template getProperty<fix_prop>()) {
|
||||
//set norm Quaternion as map to the parameter vector
|
||||
int offset_rot = mes.setParameterMap(cm.getNormQuaternionMap(), rotation);
|
||||
//set translation as map to the parameter vector
|
||||
int offset = mes.setParameterMap(cm.getTranslationMap(), general);
|
||||
//write initail values to the parameter maps
|
||||
//remember the parameter offset as all downstream geometry must use this offset
|
||||
cm.setParameterOffset(offset_rot, rotation);
|
||||
cm.setParameterOffset(offset, general);
|
||||
//wirte initial values
|
||||
cm.initMaps();
|
||||
}
|
||||
else
|
||||
cm.initFixMaps();
|
||||
|
||||
//map all geometrie within that cluster to it's rotation matrix
|
||||
//for collecting all geometries which need updates
|
||||
cm.clearGeometry();
|
||||
cm.mapClusterDownstreamGeometry(c);
|
||||
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->initMap(&mes);
|
||||
}
|
||||
}
|
||||
|
||||
//and now the constraints to set the residual and gradient maps
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
|
||||
//set the maps
|
||||
Cons c = *oit.first;
|
||||
if(c)
|
||||
c->setMaps(mes);
|
||||
//TODO: else throw (as every global edge was counted as one equation)
|
||||
}
|
||||
}
|
||||
|
||||
//if we don't have rotations we need no expensive scaling code
|
||||
if(!mes.hasParameterType(rotation)) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "No rotation parameters in system, solve without scaling";
|
||||
#endif
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// we have rotations, so let's check our options. first search for cycles, as systems with them
|
||||
// always need the full solver power
|
||||
bool has_cycle;
|
||||
cycle_dedector cd(has_cycle);
|
||||
//create te needed property maps and fill it
|
||||
property_map<vertex_index_prop, Cluster> vi_map(cluster);
|
||||
cluster->initIndexMaps();
|
||||
typedef std::map< LocalVertex, boost::default_color_type> vcmap;
|
||||
typedef std::map< LocalEdge, boost::default_color_type> ecmap;
|
||||
vcmap v_cm;
|
||||
ecmap e_cm;
|
||||
boost::associative_property_map< vcmap > v_cpm(v_cm);
|
||||
boost::associative_property_map< ecmap > e_cpm(e_cm);
|
||||
|
||||
boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(v_cpm).edge_color_map(e_cpm));
|
||||
|
||||
bool done = false;
|
||||
if(!has_cycle) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "non-cyclic system dedected";
|
||||
#endif
|
||||
//cool, lets do uncylic. first all rotational constraints with rotational parameters
|
||||
mes.setAccess(rotation);
|
||||
mes.setGeneralEquationAccess(false);
|
||||
//solve can be done without catching exceptions, because this only fails if the system in
|
||||
//unsolvable
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
|
||||
//now let's see if we have to go on with the translations
|
||||
mes.setAccess(general);
|
||||
mes.setGeneralEquationAccess(true);
|
||||
mes.recalculate();
|
||||
if(mes.Residual.norm()<1e-6)
|
||||
done = true;
|
||||
else {
|
||||
//let's try translation only
|
||||
try {
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
done=true;
|
||||
}
|
||||
catch(boost::exception&) {
|
||||
//not successful, so we need brute force
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//not done already? try it the hard way!
|
||||
if(!done) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Full scale solver used";
|
||||
#endif
|
||||
Rescaler re(cluster, mes);
|
||||
re();
|
||||
sys.kernel().solve(mes, re);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
//solving is done, now go to all relevant geometries and clusters and write the values back
|
||||
//(no need to emit recalculated signal as this cluster is never recalculated in this run)
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first))
|
||||
c->template getProperty<math_prop>().finishCalculation();
|
||||
else
|
||||
c->template getProperty<math_prop>().finishFixCalculation();
|
||||
|
||||
std::vector<Geom>& vec = c->template getProperty<math_prop>().getGeometry();
|
||||
for(typename std::vector<Geom>::iterator vit = vec.begin(); vit != vec.end(); vit++)
|
||||
(*vit)->finishCalculation();
|
||||
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(mes.Scaling);
|
||||
g->finishCalculation();
|
||||
}
|
||||
}
|
||||
//we have solved this cluster
|
||||
cluster->template setProperty<changed_prop>(false);
|
||||
}
|
||||
catch(boost::exception&) {
|
||||
throw;
|
||||
}
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_SOLVER_3D_HPP
|
||||
|
||||
373
src/Mod/Assembly/App/opendcm/module3d/imp/state_imp.hpp
Normal file
373
src/Mod/Assembly/App/opendcm/module3d/imp/state_imp.hpp
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE3D_STATE_IMP_HPP
|
||||
#define DCM_MODULE3D_STATE_IMP_HPP
|
||||
|
||||
#include "../state.hpp"
|
||||
|
||||
#include "../module.hpp"
|
||||
#include "../coincident.hpp"
|
||||
#include "../alignment.hpp"
|
||||
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/phoenix/function/adapt_function.hpp>
|
||||
#include <boost/phoenix/fusion/at.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/greater.hpp>
|
||||
|
||||
namespace karma_ascii = boost::spirit::karma::ascii;
|
||||
namespace qi_ascii = boost::spirit::qi::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
#include <ios>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace karma_ascii = boost::spirit::karma::ascii;
|
||||
namespace qi_ascii = boost::spirit::qi::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
struct geom_visitor : public boost::static_visitor<std::string> {
|
||||
|
||||
template<typename T>
|
||||
std::string operator()(T& i) const {
|
||||
|
||||
//we use stings in case new geometry gets added and the weights shift, meaning: backwards
|
||||
//compatible
|
||||
std::string type;
|
||||
switch(geometry_traits<T>::tag::weight::value) {
|
||||
case tag::weight::direction::value :
|
||||
return "direction";
|
||||
case tag::weight::point::value :
|
||||
return "point";
|
||||
case tag::weight::line::value :
|
||||
return "line";
|
||||
case tag::weight::plane::value :
|
||||
return "plane";
|
||||
case tag::weight::cylinder::value :
|
||||
return "cylinder";
|
||||
default:
|
||||
return "unknown";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::string getWeight(boost::shared_ptr<T> ptr) {
|
||||
geom_visitor v;
|
||||
return ptr->apply(v);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct get_weight {
|
||||
typedef typename geometry_traits<T>::tag::weight type;
|
||||
};
|
||||
|
||||
//search the first type in the typevector with the given weight
|
||||
template<typename Vector, typename Weight>
|
||||
struct getWeightType {
|
||||
typedef typename mpl::find_if<Vector, boost::is_same<get_weight<mpl::_1>, Weight > >::type iter;
|
||||
typedef typename mpl::if_< boost::is_same<iter, typename mpl::end<Vector>::type >, mpl::void_, typename mpl::deref<iter>::type>::type type;
|
||||
};
|
||||
|
||||
typedef std::vector< fusion::vector2<std::string, std::string> > string_vec;
|
||||
typedef std::vector< fusion::vector2<std::vector<char>, std::vector<char> > > char_vec;
|
||||
|
||||
template<typename C>
|
||||
string_vec getConstraints(boost::shared_ptr<C> con) {
|
||||
|
||||
string_vec vec;
|
||||
std::vector<boost::any> cvec = con->getGenericConstraints();
|
||||
|
||||
typename std::vector<boost::any>::iterator it;
|
||||
for(it = cvec.begin(); it != cvec.end(); it++) {
|
||||
|
||||
if((*it).type() == typeid(dcm::Distance)) {
|
||||
double v = fusion::at_key<double>(boost::any_cast<dcm::Distance>(*it).values).second;
|
||||
std::string value = boost::lexical_cast<std::string>(v);
|
||||
vec.push_back(fusion::make_vector(std::string("Distance"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::Angle)) {
|
||||
double v = fusion::at_key<double>(boost::any_cast<dcm::Angle>(*it).values).second;
|
||||
std::string value = boost::lexical_cast<std::string>(v);
|
||||
vec.push_back(fusion::make_vector(std::string("Angle"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::Orientation)) {
|
||||
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::Orientation>(*it).values).second;
|
||||
std::string value = boost::lexical_cast<std::string>(v);
|
||||
vec.push_back(fusion::make_vector(std::string("Orientation"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::details::ci_orientation)) {
|
||||
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::details::ci_orientation>(*it).values).second;
|
||||
std::string value = boost::lexical_cast<std::string>(v);
|
||||
vec.push_back(fusion::make_vector(std::string("Coincidence"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::details::al_orientation)) {
|
||||
int v = fusion::at_key<dcm::Direction>(boost::any_cast<dcm::details::al_orientation>(*it).values).second;
|
||||
std::string value = boost::lexical_cast<std::string>(v);
|
||||
vec.push_back(fusion::make_vector(std::string("Alignment"), value));
|
||||
};
|
||||
};
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
void constraintCreation(typename char_vec::iterator it,
|
||||
typename char_vec::iterator end,
|
||||
boost::shared_ptr<C> con) {
|
||||
|
||||
std::string first(fusion::at_c<0>(*it).begin(), fusion::at_c<0>(*it).end());
|
||||
std::string second(fusion::at_c<1>(*it).begin(), fusion::at_c<1>(*it).end());
|
||||
|
||||
if(first.compare("Distance") == 0) {
|
||||
double v = boost::lexical_cast<double>(second);
|
||||
typename details::fusion_vec<dcm::Distance>::type val;
|
||||
fusion::front(val)=v;
|
||||
con->template initialize(val);
|
||||
return;
|
||||
}
|
||||
else if(first.compare("Orientation") == 0) {
|
||||
dcm::Direction v = (dcm::Direction)boost::lexical_cast<int>(second);
|
||||
typename details::fusion_vec<dcm::Orientation>::type val;
|
||||
fusion::front(val)=v;
|
||||
con->template initialize(val);
|
||||
return;
|
||||
}
|
||||
else if(first.compare("Angle") == 0) {
|
||||
double v = boost::lexical_cast<double>(second);
|
||||
typename details::fusion_vec<dcm::Angle>::type val;
|
||||
fusion::front(val)=v;
|
||||
con->template initialize(val);
|
||||
return;
|
||||
}
|
||||
else if(first.compare("Coincidence") == 0) {
|
||||
dcm::Direction v = (dcm::Direction)boost::lexical_cast<int>(second);
|
||||
typename details::fusion_vec<dcm::Coincidence>::type val;
|
||||
val=v;
|
||||
con->template initialize(val);
|
||||
return;
|
||||
}
|
||||
else if(first.compare("Alignment") == 0) {
|
||||
double v = boost::lexical_cast<double>(second);
|
||||
typename details::fusion_vec<dcm::Alignment>::type val;
|
||||
val=v;
|
||||
con->template initialize(val);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
void setConstraints(char_vec& vec, boost::shared_ptr<C> con) {
|
||||
constraintCreation<C>(vec.begin(), vec.end(), con);
|
||||
};
|
||||
|
||||
template <typename Geom, typename Row, typename Value>
|
||||
bool VectorOutput(Geom& v, Row& r, Value& val) {
|
||||
|
||||
if(r < v->m_global.rows()) {
|
||||
|
||||
val = v->m_global(r++);
|
||||
return true; // output continues
|
||||
}
|
||||
return false; // fail the output
|
||||
};
|
||||
|
||||
template <typename Geom, typename Row, typename Value>
|
||||
bool VectorInput(Geom& v, Row& r, Value& val) {
|
||||
|
||||
v.conservativeResize(r+1);
|
||||
v(r++) = val;
|
||||
return true; // output continues
|
||||
};
|
||||
|
||||
template<typename Geom>
|
||||
struct inject_set {
|
||||
|
||||
template<typename Vec, typename Obj>
|
||||
static void apply(Vec& v, Obj g) {
|
||||
Geom gt;
|
||||
(typename geometry_traits<Geom>::modell()).template inject<double,
|
||||
typename geometry_traits<Geom>::accessor >(gt, v);
|
||||
g->set(gt);
|
||||
};
|
||||
};
|
||||
//spezialisation if no type in the typelist has the right weight
|
||||
template<>
|
||||
struct inject_set<mpl::void_> {
|
||||
|
||||
template<typename Obj, typename Vec>
|
||||
static void apply(Vec& v, Obj g) {
|
||||
//TODO:throw
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
bool Create(System* sys, std::string& type,
|
||||
boost::shared_ptr<typename details::getModule3D<System>::type::Geometry3D> geom,
|
||||
typename System::Kernel::Vector& v) {
|
||||
|
||||
typedef typename details::getModule3D<System>::type::geometry_types Typelist;
|
||||
|
||||
if(type.compare("direction") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::direction>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("point") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::point>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("line") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::line>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("plane") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::plane>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("cylinder") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::cylinder>::type>::apply(v, geom);
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
// define a new real number formatting policy
|
||||
template <typename Num>
|
||||
struct scientific_policy : karma::real_policies<Num>
|
||||
{
|
||||
// we want the numbers always to be in scientific format
|
||||
static int floatfield(Num n) {
|
||||
return std::ios::scientific;
|
||||
}
|
||||
static unsigned precision(Num n) {
|
||||
return 16;
|
||||
};
|
||||
};
|
||||
|
||||
// define a new generator type based on the new policy
|
||||
typedef karma::real_generator<double, scientific_policy<double> > science_type;
|
||||
static science_type const scientific = science_type();
|
||||
} //details
|
||||
} //dcm
|
||||
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION(bool, vector_out, dcm::details::VectorOutput, 3)
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION(bool, vector_in, dcm::details::VectorInput, 3)
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION(bool, create, dcm::details::Create, 4)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
dcm::GlobalEdge,
|
||||
(int, ID)
|
||||
(int, source)
|
||||
(int, target)
|
||||
)
|
||||
|
||||
namespace dcm {
|
||||
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_generator< typename details::getModule3D<System>::type::Geometry3D , System, iterator >::init(generator& r) {
|
||||
|
||||
r = karma::lit("<type>Geometry3D</type>\n<class>")
|
||||
<< karma_ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
|
||||
<< "</class>" << karma::eol << "<value>"
|
||||
<< (details::scientific[ boost::spirit::_pass = vector_out(karma::_val, karma::_a, karma::_1) ] % ' ')
|
||||
<< "</value>";
|
||||
};
|
||||
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_generator< typename details::getModule3D<System>::type::vertex_prop , System, iterator >::init(generator& r) {
|
||||
|
||||
r = karma::lit("<type>Vertex</type>")
|
||||
<< karma::eol << "<value>" << karma::int_ << "</value>";
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_generator< typename details::getModule3D<System>::type::Constraint3D , System, iterator >::init(generator& r) {
|
||||
|
||||
r = karma::lit("<type>Constraint3D</type>") << karma::eol
|
||||
<< "<connect first=" << karma::int_[karma::_1 = phx::at_c<1>(phx::bind(&Constraint3D::template getProperty<edge_prop>, karma::_val))]
|
||||
<< " second=" << karma::int_[karma::_1 = phx::at_c<2>(phx::bind(&Constraint3D::template getProperty<edge_prop>, karma::_val))] << "></connect>"
|
||||
<< (*(karma::eol<<"<constraint type="<<karma_ascii::string<<">"<<karma_ascii::string<<"</constraint>"))[karma::_1 = phx::bind(&details::getConstraints<Constraint3D>, karma::_val)];
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_generator< typename details::getModule3D<System>::type::edge_prop , System, iterator >::init(generator& r) {
|
||||
|
||||
r %= karma::lit("<type>Edge</type>")
|
||||
<< karma::eol << "<value>" << karma::int_ << " "
|
||||
<< karma::int_ << " " << karma::int_ << "</value>";
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_generator<typename details::getModule3D<System>::type::fix_prop, System, iterator>::init(generator& r) {
|
||||
|
||||
r = karma::lit("<type>Fix</type>\n<value>") << karma::bool_ <<"</value>";
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************************/
|
||||
/****************************************************************************************************/
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_parser< typename details::getModule3D<System>::type::Geometry3D, System, iterator >::init(parser& r) {
|
||||
|
||||
r = qi::lit("<type>Geometry3D</type>")[ qi::_val = phx::construct<boost::shared_ptr<object_type> >(phx::new_<object_type>(*qi::_r1))]
|
||||
>> "<class>" >> (+qi::char_("a-zA-Z"))[qi::_a = phx::construct<std::string>(phx::begin(qi::_1), phx::end(qi::_1))] >> "</class>"
|
||||
>> "<value>" >> *qi::double_[ vector_in(qi::_b, qi::_c, qi::_1) ] >> "</value>"
|
||||
>> qi::eps[ create(qi::_r1, qi::_a, qi::_val, qi::_b) ];
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_parser< typename details::getModule3D<System>::type::vertex_prop, System, iterator >::init(parser& r) {
|
||||
|
||||
r %= qi::lit("<type>Vertex</type>") >> "<value>" >> qi::int_ >> "</value>";
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_parser< typename details::getModule3D<System>::type::Constraint3D, System, iterator >::init(parser& r) {
|
||||
|
||||
r = qi::lit("<type>Constraint3D</type>")
|
||||
>> ("<connect first=" >> qi::int_ >> "second=" >> qi::int_ >> "></connect>")[
|
||||
qi::_val = phx::construct<boost::shared_ptr<Constraint3D> >(
|
||||
phx::new_<Constraint3D>(*qi::_r1,
|
||||
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_1),
|
||||
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_2)))
|
||||
]
|
||||
>> (*("<constraint type=" >> *qi_ascii::alpha >> ">" >> *qi_ascii::alnum >>"</constraint>"))[phx::bind(&details::setConstraints<Constraint3D>, qi::_1, qi::_val)];
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_parser< typename details::getModule3D<System>::type::edge_prop, System, iterator >::init(parser& r) {
|
||||
|
||||
r %= qi::lit("<type>Edge</type>")
|
||||
>> "<value>" >> qi::int_ >> qi::int_ >> qi::int_ >> "</value>";
|
||||
};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
void parser_parser< typename details::getModule3D<System>::type::fix_prop, System, iterator >::init(parser& r) {
|
||||
|
||||
r = qi::lit("<type>Fix</type>") >> "<value>" >> qi::bool_ >> "</value>";
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //DCM_MODULE3D_STATE_HPP
|
||||
@@ -17,26 +17,16 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GCM_MODULE_3D_H
|
||||
#define GCM_MODULE_3D_H
|
||||
#ifndef DCM_MODULE_3D_H
|
||||
#define DCM_MODULE_3D_H
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
#include <boost/fusion/include/as_vector.hpp>
|
||||
#include <boost/fusion/include/mpl.hpp>
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "opendcm/core.hpp"
|
||||
#include "opendcm/core/object.hpp"
|
||||
@@ -57,19 +47,6 @@ namespace mpl = boost::mpl;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename seq, typename t>
|
||||
struct distance {
|
||||
typedef typename mpl::find<seq, t>::type iterator;
|
||||
typedef typename mpl::distance<typename mpl::begin<seq>::type, iterator>::type type;
|
||||
BOOST_MPL_ASSERT((mpl::not_< boost::is_same<iterator, typename mpl::end<seq>::type > >));
|
||||
};
|
||||
}
|
||||
}//dcm
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct reset {}; //signal name
|
||||
struct module3d_error : virtual boost::exception {}; //exception for all module3d special errors
|
||||
|
||||
@@ -123,17 +100,10 @@ struct Module3D {
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
typename Visitor::result_type apply(Visitor& vis) {
|
||||
return boost::apply_visitor(vis, m_geometry);
|
||||
};
|
||||
typename Visitor::result_type apply(Visitor& vis);
|
||||
|
||||
template<typename T>
|
||||
T convertTo() {
|
||||
T t;
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
|
||||
typename geometry_traits<T>::accessor >(t, Base::m_global);
|
||||
return t;
|
||||
};
|
||||
T convertTo();
|
||||
|
||||
virtual boost::shared_ptr<Derived> clone(Sys& newSys);
|
||||
|
||||
@@ -144,31 +114,6 @@ struct Module3D {
|
||||
#ifdef USE_LOGGING
|
||||
src::logger log;
|
||||
#endif
|
||||
|
||||
struct cloner : boost::static_visitor<void> {
|
||||
typedef typename boost::make_variant_over< ExtTypeList >::type Variant;
|
||||
|
||||
Variant variant;
|
||||
cloner(Variant& v) : variant(v) {};
|
||||
|
||||
template<typename T>
|
||||
void operator()(T& t) {
|
||||
variant = geometry_clone_traits<T>()(t);
|
||||
};
|
||||
};
|
||||
|
||||
//visitor to write the calculated value into the variant
|
||||
struct apply_visitor : public boost::static_visitor<void> {
|
||||
|
||||
apply_visitor(typename Kernel::Vector& v) : value(v) {};
|
||||
template <typename T>
|
||||
void operator()(T& t) const {
|
||||
(typename geometry_traits<T>::modell()).template inject<typename Kernel::number_type,
|
||||
typename geometry_traits<T>::accessor >(t, value);
|
||||
}
|
||||
typename Kernel::Vector& value;
|
||||
};
|
||||
|
||||
Variant m_geometry; //Variant holding the real geometry type
|
||||
|
||||
//override protected event functions to emit signals
|
||||
@@ -261,42 +206,6 @@ struct Module3D {
|
||||
|
||||
struct inheriter_base {
|
||||
|
||||
//build a constraint vector
|
||||
template<typename T>
|
||||
struct fusion_vec {
|
||||
typedef typename mpl::if_< mpl::is_sequence<T>,
|
||||
T, fusion::vector<T> >::type type;
|
||||
};
|
||||
|
||||
template<typename covec>
|
||||
struct initalizer : public boost::static_visitor<void> {
|
||||
|
||||
Cons constraint;
|
||||
covec& cov;
|
||||
initalizer(Cons c, covec& co) : constraint(c), cov(co) {};
|
||||
template<typename T1, typename T2>
|
||||
void operator()(const T1& t1, const T2& t2) {
|
||||
constraint->template initialize< typename geometry_traits<T1>::tag,
|
||||
typename geometry_traits<T2>::tag, covec>(cov);
|
||||
};
|
||||
};
|
||||
|
||||
struct set_constraint_option {
|
||||
|
||||
template<typename T>
|
||||
typename boost::enable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
|
||||
operator()(T& val) {
|
||||
return val;
|
||||
};
|
||||
template<typename T>
|
||||
typename boost::disable_if<mpl::is_sequence<T>, typename fusion_vec<T>::type >::type
|
||||
operator()(T& val) {
|
||||
typename fusion_vec<T>::type vec;
|
||||
fusion::at_c<0>(vec) = val;
|
||||
return vec;
|
||||
};
|
||||
};
|
||||
|
||||
inheriter_base();
|
||||
|
||||
template<typename T>
|
||||
@@ -308,6 +217,8 @@ struct Module3D {
|
||||
Cons createConstraint3D(Geom first, Geom second, T1 constraint1);
|
||||
void removeConstraint3D(Cons c);
|
||||
|
||||
void system_sub(boost::shared_ptr<Sys> subsys) {};
|
||||
|
||||
protected:
|
||||
Sys* m_this;
|
||||
void apply_edge_remove(GlobalEdge e);
|
||||
@@ -361,6 +272,7 @@ struct Module3D {
|
||||
typedef mpl::vector4<vertex_prop, edge_prop, math_prop, fix_prop> properties;
|
||||
typedef mpl::vector2<Geometry3D, Constraint3D> objects;
|
||||
typedef mpl::vector5<tag::point3D, tag::direction3D, tag::line3D, tag::plane3D, tag::cylinder3D> geometries;
|
||||
typedef mpl::map0<> signals;
|
||||
|
||||
static void system_init(Sys& sys) {
|
||||
sys.m_sheduler.addProcessJob(new SystemSolver());
|
||||
@@ -408,444 +320,11 @@ typename boost::add_reference<T>::type get(G geom) {
|
||||
return *result;
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(Sys& system)
|
||||
: Object<Sys, Derived, GeomSig>(system) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::Geometry3D_base(const T& geometry, Sys& system)
|
||||
: Object<Sys, Derived, GeomSig>(system) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D"));
|
||||
#endif
|
||||
|
||||
m_geometry = geometry;
|
||||
//first init, so that the geometry internal vector has the right size
|
||||
Base::template init< typename geometry_traits<T>::tag >();
|
||||
//now write the value;
|
||||
(typename geometry_traits<T>::modell()).template extract<Scalar,
|
||||
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::set(const T& geometry) {
|
||||
|
||||
m_geometry = geometry;
|
||||
//first init, so that the geometry internal vector has the right size
|
||||
Base::template init< typename geometry_traits<T>::tag >();
|
||||
//now write the value;
|
||||
(typename geometry_traits<T>::modell()).template extract<Scalar,
|
||||
typename geometry_traits<T>::accessor >(geometry, Base::getValue());
|
||||
|
||||
reset();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//it's possible that the variant contains pointers, so we need to clone them
|
||||
cloner clone_fnc(np->m_geometry);
|
||||
boost::apply_visitor(clone_fnc, m_geometry);
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::recalculated() {
|
||||
|
||||
apply_visitor v(Base::getValue());
|
||||
apply(v);
|
||||
|
||||
ObjBase::template emitSignal<dcm::recalculated>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::removed() {
|
||||
|
||||
ObjBase::template emitSignal<dcm::remove>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_base<Derived>::reset() {
|
||||
|
||||
ObjBase::template emitSignal<dcm::reset>(((Derived*)this)->shared_from_this());
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(Sys& system)
|
||||
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(system)
|
||||
#ifdef USE_LOGGING
|
||||
, log_id("No ID")
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
Base::log.add_attribute("ID", log_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::Geometry3D_id(const T& geometry, Sys& system)
|
||||
: Module3D<Typelist, ID>::template type<Sys>::template Geometry3D_base<Derived>(geometry, system)
|
||||
#ifdef USE_LOGGING
|
||||
, log_id("No ID")
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
Base::log.add_attribute("ID", log_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(const T& geometry, Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
template<typename T>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::set(const T& geometry) {
|
||||
Base::set(geometry);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Geometry3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
#ifdef USE_LOGGING
|
||||
std::stringstream str;
|
||||
str<<this->template getProperty<id_prop<Identifier> >();
|
||||
log_id.set(str.str());
|
||||
BOOST_LOG(Base::log)<<"Identifyer set: "<<id;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(Sys& system)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Geometry3D_base<Geometry3D>,
|
||||
Geometry3D_id<Geometry3D> >::type(system) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
Module3D<Typelist, ID>::type<Sys>::Geometry3D::Geometry3D(const T& geometry, Sys& system)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Geometry3D_base<Geometry3D>,
|
||||
Geometry3D_id<Geometry3D> >::type(geometry, system) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
boost::shared_ptr<Derived> Module3D<Typelist, ID>::type<Sys>::Constraint3D_base<Derived>::clone(Sys& newSys) {
|
||||
|
||||
//copy the standart stuff
|
||||
boost::shared_ptr<Derived> np = boost::shared_ptr<Derived>(new Derived(*static_cast<Derived*>(this)));
|
||||
np->m_system = &newSys;
|
||||
//copy the internals
|
||||
np->content = CBase::content->clone();
|
||||
//and get the geometry pointers right
|
||||
if(CBase::first) {
|
||||
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::first)->template getProperty<vertex_prop>();
|
||||
np->first = newSys.m_cluster->template getObject<Geometry3D>(v);
|
||||
}
|
||||
if(CBase::second) {
|
||||
GlobalVertex v = boost::static_pointer_cast<Geometry3D>(CBase::second)->template getProperty<vertex_prop>();
|
||||
np->second = newSys.m_cluster->template getObject<Geometry3D>(v);
|
||||
}
|
||||
return np;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::Constraint3D_id(Sys& system, Geom f, Geom s)
|
||||
: Constraint3D_base<Derived>(system, f, s) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Identifier&
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::getIdentifier() {
|
||||
return this->template getProperty<id_prop<Identifier> >();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename Derived>
|
||||
void Module3D<Typelist, ID>::type<Sys>::Constraint3D_id<Derived>::setIdentifier(Identifier id) {
|
||||
this->template setProperty<id_prop<Identifier> >(id);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::Constraint3D::Constraint3D(Sys& system, Geom first, Geom second)
|
||||
: mpl::if_<boost::is_same<Identifier, No_Identifier>,
|
||||
Constraint3D_base<Constraint3D>,
|
||||
Constraint3D_id<Constraint3D> >::type(system, first, second) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::inheriter_base() {
|
||||
m_this = ((Sys*) this);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D() {
|
||||
|
||||
Geom g(new Geometry3D(* ((Sys*) this)));
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
|
||||
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
|
||||
m_this->push_back(g);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createGeometry3D(T geom) {
|
||||
|
||||
Geom g(new Geometry3D(geom, * ((Sys*) this)));
|
||||
fusion::vector<LocalVertex, GlobalVertex> res = m_this->m_cluster->addVertex();
|
||||
m_this->m_cluster->template setObject<Geometry3D> (fusion::at_c<0> (res), g);
|
||||
g->template setProperty<vertex_prop>(fusion::at_c<1>(res));
|
||||
m_this->push_back(g);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeGeometry3D(Geom g) {
|
||||
|
||||
GlobalVertex v = g->template getProperty<vertex_prop>();
|
||||
|
||||
//check if this vertex holds a constraint
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(v);
|
||||
if(c)
|
||||
c->template emitSignal<remove>(c);
|
||||
|
||||
//emit remove geometry signal bevore actually deleting it, in case anyone want to access the
|
||||
//graph before
|
||||
g->template emitSignal<remove>(g);
|
||||
|
||||
//remove the vertex from graph and emit all edges that get removed with the functor
|
||||
boost::function<void(GlobalEdge)> functor = boost::bind(&inheriter_base::apply_edge_remove, this, _1);
|
||||
m_this->m_cluster->removeVertex(v, functor);
|
||||
m_this->erase(g);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T1>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_base::createConstraint3D(Geom first, Geom second, T1 constraint1) {
|
||||
|
||||
//get the fusion vector type
|
||||
typedef typename fusion_vec<T1>::type covec;
|
||||
|
||||
//set the objects
|
||||
covec cv = set_constraint_option()(constraint1);
|
||||
|
||||
//now create the constraint
|
||||
Cons c(new Constraint3D(*m_this, first, second));
|
||||
//initialize constraint
|
||||
c->initialize(cv);
|
||||
|
||||
//add it to the clustergraph
|
||||
fusion::vector<LocalEdge, GlobalEdge, bool, bool> res;
|
||||
res = m_this->m_cluster->addEdge(first->template getProperty<vertex_prop>(),
|
||||
second->template getProperty<vertex_prop>());
|
||||
if(!fusion::at_c<2>(res)) {
|
||||
Cons rc;
|
||||
return rc; //TODO: throw
|
||||
};
|
||||
m_this->m_cluster->template setObject<Constraint3D> (fusion::at_c<1> (res), c);
|
||||
//add the coresbondig edge to the constraint
|
||||
c->template setProperty<edge_prop>(fusion::at_c<1>(res));
|
||||
//store the constraint in general object vector of main system
|
||||
m_this->push_back(c);
|
||||
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::removeConstraint3D(Cons c) {
|
||||
|
||||
GlobalEdge e = c->template getProperty<edge_prop>();
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->m_cluster->removeEdge(e);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_base::apply_edge_remove(GlobalEdge e) {
|
||||
Cons c = m_this->m_cluster->template getObject<Constraint3D>(e);
|
||||
c->template emitSignal<remove>(c);
|
||||
m_this->erase(c);
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(T geom, Identifier id) {
|
||||
Geom g = inheriter_base::createGeometry3D(geom);
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createGeometry3D(Identifier id) {
|
||||
Geom g = inheriter_base::createGeometry3D();
|
||||
g->setIdentifier(id);
|
||||
return g;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeGeometry3D(Identifier id) {
|
||||
|
||||
if(hasGeometry3D(id))
|
||||
inheriter_base::removeGeometry3D(getGeometry3D(id));
|
||||
else
|
||||
throw module3d_error() << boost::errinfo_errno(410) << error_message("no geometry with this ID in this system");
|
||||
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
template<typename T>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::createConstraint3D(Identifier id, Geom first, Geom second, T constraint1) {
|
||||
|
||||
Cons c = inheriter_base::createConstraint3D(first, second, constraint1);
|
||||
c->setIdentifier(id);
|
||||
return c;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void Module3D<Typelist, ID>::type<Sys>::inheriter_id::removeConstraint3D(Identifier id) {
|
||||
|
||||
if(hasConstraint3D(id))
|
||||
removeConstraint3D(getConstraint3D(id));
|
||||
else
|
||||
throw module3d_error() << boost::errinfo_errno(411) << error_message("no constraint with this ID in this system");
|
||||
};
|
||||
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasGeometry3D(Identifier id) {
|
||||
if(getGeometry3D(id))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Geom
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getGeometry3D(Identifier id) {
|
||||
std::vector< Geom >& vec = inheriter_base::m_this->template objectVector<Geometry3D>();
|
||||
typedef typename std::vector<Geom>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
return Geom();
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool Module3D<Typelist, ID>::type<Sys>::inheriter_id::hasConstraint3D(Identifier id) {
|
||||
if(getConstraint3D(id))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
typename Module3D<Typelist, ID>::template type<Sys>::Cons
|
||||
Module3D<Typelist, ID>::type<Sys>::inheriter_id::getConstraint3D(Identifier id) {
|
||||
std::vector< Cons >& vec = inheriter_base::m_this->template objectVector<Constraint3D>();
|
||||
typedef typename std::vector<Cons>::iterator iter;
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
return Cons();
|
||||
};
|
||||
|
||||
}//dcm
|
||||
|
||||
#endif //GCM_GEOMETRY3D_H
|
||||
#include "imp/module_imp.hpp"
|
||||
|
||||
#endif //DCM_GEOMETRY3D_H
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,19 +21,11 @@
|
||||
#define GCM_SOLVER_3D_H
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "clustermath.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "opendcm/core/sheduler.hpp"
|
||||
#include "opendcm/core/traits.hpp"
|
||||
#include <opendcm/core/kernel.hpp>
|
||||
#include <opendcm/core/property.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/graph/undirected_dfs.hpp>
|
||||
#include <boost/exception/errinfo_errno.hpp>
|
||||
|
||||
namespace dcm {
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
@@ -121,383 +113,6 @@ struct SystemSolver : public Job<Sys> {
|
||||
void solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys);
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
/*****************************************************************************************************************/
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
MES<Sys>::MES(boost::shared_ptr<Cluster> cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) {
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("MES3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void MES<Sys>::recalculate() {
|
||||
|
||||
//first calculate all clusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = m_cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
if(!(*cit.first).second->template getProperty<fix_prop>())
|
||||
(*cit.first).second->template getProperty<math_prop>().recalculate();
|
||||
|
||||
};
|
||||
|
||||
//with everything updated just nicely we can compute the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
|
||||
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
|
||||
for(; eit.first != eit.second; eit.first++) {
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
if(*oit.first)
|
||||
(*oit.first)->calculate(Base::Scaling, Base::rot_only);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void MES<Sys>::removeLocalGradientZeros() {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log) << "remove local gradient zero";
|
||||
#endif
|
||||
//let the constraints treat the local zeros
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator eiter;
|
||||
std::pair<eiter, eiter> eit = boost::edges(*m_cluster);
|
||||
for(; eit.first != eit.second; eit.first++) {
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = m_cluster->template getObjects<Constraint3D>(*eit.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
if(*oit.first)
|
||||
(*oit.first)->treatLGZ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::Rescaler::Rescaler(boost::shared_ptr<Cluster> c, Mes& m) : cluster(c), mes(m), rescales(0) {
|
||||
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::operator()() {
|
||||
mes.Scaling = scaleClusters();
|
||||
rescales++;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
typename SystemSolver<Sys>::Scalar SystemSolver<Sys>::Rescaler::scaleClusters() {
|
||||
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
//get the maximal scale
|
||||
Scalar sc = 0;
|
||||
for(cit = cluster->clusters(); cit.first != cit.second; cit.first++) {
|
||||
//fixed cluster are irrelevant for scaling
|
||||
if((*cit.first).second->template getProperty<fix_prop>())
|
||||
continue;
|
||||
|
||||
//get the biggest scale factor
|
||||
details::ClusterMath<Sys>& math = (*cit.first).second->template getProperty<math_prop>();
|
||||
|
||||
math.m_pseudo.clear();
|
||||
collectPseudoPoints(cluster, (*cit.first).first, math.m_pseudo);
|
||||
|
||||
const Scalar s = math.calculateClusterScale();
|
||||
sc = (s>sc) ? s : sc;
|
||||
}
|
||||
//if no scaling-value returned we can use 1
|
||||
sc = (Kernel::isSame(sc,0, 1e-10)) ? 1. : sc;
|
||||
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
c->template getProperty<math_prop>().applyClusterScale(sc,
|
||||
c->template getProperty<fix_prop>());
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(sc*SKALEFAKTOR);
|
||||
}
|
||||
}
|
||||
return 1./(sc*SKALEFAKTOR);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::Rescaler::collectPseudoPoints(
|
||||
boost::shared_ptr<typename SystemSolver<Sys>::Cluster> parent,
|
||||
LocalVertex cluster,
|
||||
std::vector<typename SystemSolver<Sys>::Kernel::Vector3,
|
||||
Eigen::aligned_allocator<typename SystemSolver<Sys>::Kernel::Vector3> >& vec) {
|
||||
|
||||
std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > vec2;
|
||||
typedef typename Cluster::global_edge_iterator c_iter;
|
||||
typedef typename boost::graph_traits<Cluster>::out_edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> it = boost::out_edges(cluster, *parent);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
std::pair< c_iter, c_iter > cit = parent->getGlobalEdges(*it.first);
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
Cons c = parent->template getObject<Constraint3D>(*cit.first);
|
||||
|
||||
if(!c)
|
||||
continue;
|
||||
|
||||
//get the first global vertex and see if we have it in the wanted cluster or not
|
||||
GlobalVertex v = cit.first->source;
|
||||
std::pair<LocalVertex,bool> res = parent->getLocalVertex(v);
|
||||
if(!res.second)
|
||||
return; //means the geometry is in non of the clusters which is not allowed
|
||||
|
||||
if(res.first == cluster)
|
||||
c->collectPseudoPoints(vec, vec2);
|
||||
else
|
||||
c->collectPseudoPoints(vec2, vec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
SystemSolver<Sys>::SystemSolver() {
|
||||
Job<Sys>::priority = 1000;
|
||||
#ifdef USE_LOGGING
|
||||
log.add_attribute("Tag", attrs::constant< std::string >("SystemSolver3D"));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::execute(Sys& sys) {
|
||||
solveCluster(sys.m_cluster, sys);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sys) {
|
||||
|
||||
try {
|
||||
//set out and solve all relevant subclusters
|
||||
typedef typename Cluster::cluster_iterator citer;
|
||||
std::pair<citer, citer> cit = cluster->clusters();
|
||||
for(; cit.first != cit.second; cit.first++) {
|
||||
|
||||
boost::shared_ptr<Cluster> c = (*cit.first).second;
|
||||
if(c->template getProperty<changed_prop>() &&
|
||||
c->template getProperty<type_prop>() == details::cluster3D)
|
||||
solveCluster(c, sys);
|
||||
}
|
||||
|
||||
int params=0, constraints=0;
|
||||
typename Kernel::number_type scale = 1;
|
||||
|
||||
//get the ammount of parameters and constraint equations we need
|
||||
typedef typename boost::graph_traits<Cluster>::vertex_iterator iter;
|
||||
std::pair<iter, iter> it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
//when cluster and not fixed it has trans and rot parameter
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first)) {
|
||||
params += 6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
params += cluster->template getObject<Geometry3D>(*it.first)->m_parameterCount;
|
||||
};
|
||||
}
|
||||
|
||||
//count the equations in the constraints
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> ocit;
|
||||
typedef typename boost::graph_traits<Cluster>::edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
std::pair< ocit, ocit > it = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; it.first != it.second; it.first++)
|
||||
constraints += (*it.first)->equationCount();
|
||||
};
|
||||
|
||||
if(params <= 0 || constraints <= 0) {
|
||||
//TODO:throw
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Error in system counting: params = " << params << " and constraints = "<<constraints;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//initialise the system with now known size
|
||||
Mes mes(cluster, params, constraints);
|
||||
|
||||
//iterate all geometrys again and set the needed maps
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
details::ClusterMath<Sys>& cm = c->template getProperty<math_prop>();
|
||||
//only get maps and propagate downstream if not fixed
|
||||
if(!c->template getProperty<fix_prop>()) {
|
||||
//set norm Quaternion as map to the parameter vector
|
||||
int offset_rot = mes.setParameterMap(cm.getNormQuaternionMap(), rotation);
|
||||
//set translation as map to the parameter vector
|
||||
int offset = mes.setParameterMap(cm.getTranslationMap(), general);
|
||||
//write initail values to the parameter maps
|
||||
//remember the parameter offset as all downstream geometry must use this offset
|
||||
cm.setParameterOffset(offset_rot, rotation);
|
||||
cm.setParameterOffset(offset, general);
|
||||
//wirte initial values
|
||||
cm.initMaps();
|
||||
}
|
||||
else
|
||||
cm.initFixMaps();
|
||||
|
||||
//map all geometrie within that cluster to it's rotation matrix
|
||||
//for collecting all geometries which need updates
|
||||
cm.clearGeometry();
|
||||
cm.mapClusterDownstreamGeometry(c);
|
||||
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->initMap(&mes);
|
||||
}
|
||||
}
|
||||
|
||||
//and now the constraints to set the residual and gradient maps
|
||||
typedef typename Cluster::template object_iterator<Constraint3D> oiter;
|
||||
e_it = boost::edges(*cluster);
|
||||
for(; e_it.first != e_it.second; e_it.first++) {
|
||||
|
||||
//as always: every local edge can hold multiple global ones, so iterate over all constraints
|
||||
//hold by the individual edge
|
||||
std::pair< oiter, oiter > oit = cluster->template getObjects<Constraint3D>(*e_it.first);
|
||||
for(; oit.first != oit.second; oit.first++) {
|
||||
|
||||
//set the maps
|
||||
Cons c = *oit.first;
|
||||
if(c)
|
||||
c->setMaps(mes);
|
||||
//TODO: else throw (as every global edge was counted as one equation)
|
||||
}
|
||||
}
|
||||
|
||||
//if we don't have rotations we need no expensive scaling code
|
||||
if(!mes.hasParameterType(rotation)) {
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "No rotation parameters in system, solve without scaling";
|
||||
#endif
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// we have rotations, so let's check our options. first search for cycles, as systems with them
|
||||
// always need the full solver power
|
||||
bool has_cycle;
|
||||
cycle_dedector cd(has_cycle);
|
||||
//create te needed property maps and fill it
|
||||
property_map<vertex_index_prop, Cluster> vi_map(cluster);
|
||||
cluster->initIndexMaps();
|
||||
typedef std::map< LocalVertex, boost::default_color_type> vcmap;
|
||||
typedef std::map< LocalEdge, boost::default_color_type> ecmap;
|
||||
vcmap v_cm;
|
||||
ecmap e_cm;
|
||||
boost::associative_property_map< vcmap > v_cpm(v_cm);
|
||||
boost::associative_property_map< ecmap > e_cpm(e_cm);
|
||||
|
||||
boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(v_cpm).edge_color_map(e_cpm));
|
||||
|
||||
bool done = false;
|
||||
if(!has_cycle) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "non-cyclic system dedected";
|
||||
#endif
|
||||
//cool, lets do uncylic. first all rotational constraints with rotational parameters
|
||||
mes.setAccess(rotation);
|
||||
mes.setGeneralEquationAccess(false);
|
||||
//solve can be done without catching exceptions, because this only fails if the system in
|
||||
//unsolvable
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
|
||||
//now let's see if we have to go on with the translations
|
||||
mes.setAccess(general);
|
||||
mes.setGeneralEquationAccess(true);
|
||||
mes.recalculate();
|
||||
if(mes.Residual.norm()<1e-6)
|
||||
done = true;
|
||||
else {
|
||||
//let's try translation only
|
||||
try {
|
||||
DummyScaler re;
|
||||
sys.kernel().solve(mes, re);
|
||||
done=true;
|
||||
}
|
||||
catch(boost::exception&) {
|
||||
//not successful, so we need brute force
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//not done already? try it the hard way!
|
||||
if(!done) {
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Full scale solver used";
|
||||
#endif
|
||||
Rescaler re(cluster, mes);
|
||||
re();
|
||||
sys.kernel().solve(mes, re);
|
||||
#ifdef USE_LOGGING
|
||||
BOOST_LOG(log)<< "Numbers of rescale: "<<re.rescales;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
//solving is done, now go to all relevant geometries and clusters and write the values back
|
||||
it = boost::vertices(*cluster);
|
||||
for(; it.first != it.second; it.first++) {
|
||||
|
||||
if(cluster->isCluster(*it.first)) {
|
||||
boost::shared_ptr<Cluster> c = cluster->getVertexCluster(*it.first);
|
||||
if(!cluster->template getSubclusterProperty<fix_prop>(*it.first))
|
||||
c->template getProperty<math_prop>().finishCalculation();
|
||||
else
|
||||
c->template getProperty<math_prop>().finishFixCalculation();
|
||||
|
||||
std::vector<Geom>& vec = c->template getProperty<math_prop>().getGeometry();
|
||||
for(typename std::vector<Geom>::iterator vit = vec.begin(); vit != vec.end(); vit++)
|
||||
(*vit)->finishCalculation();
|
||||
|
||||
}
|
||||
else {
|
||||
Geom g = cluster->template getObject<Geometry3D>(*it.first);
|
||||
g->scale(mes.Scaling);
|
||||
g->finishCalculation();
|
||||
}
|
||||
}
|
||||
//we have solved this cluster
|
||||
cluster->template setProperty<changed_prop>(false);
|
||||
|
||||
}
|
||||
catch(boost::exception&) {
|
||||
throw;
|
||||
}
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
|
||||
@@ -20,300 +20,53 @@
|
||||
#ifndef DCM_MODULE3D_STATE_HPP
|
||||
#define DCM_MODULE3D_STATE_HPP
|
||||
|
||||
#include "module.hpp"
|
||||
#include <opendcm/moduleState/traits.hpp>
|
||||
#include <opendcm/core/clustergraph.hpp>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/phoenix/function/adapt_function.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/greater.hpp>
|
||||
|
||||
#include <ios>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace karma_ascii = boost::spirit::karma::ascii;
|
||||
namespace qi_ascii = boost::spirit::qi::ascii;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
struct getModule3D {
|
||||
typedef typename system_traits<Sys>::template getModule<m3d>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
struct geom_visitor : public boost::static_visitor<std::string> {
|
||||
|
||||
template<typename T>
|
||||
std::string operator()(T& i) const {
|
||||
|
||||
//we use stings in case new geometry gets added and the weights shift, meaning: backwards
|
||||
//compatible
|
||||
std::string type;
|
||||
switch( geometry_traits<T>::tag::weight::value ) {
|
||||
case tag::weight::direction::value :
|
||||
return "direction";
|
||||
case tag::weight::point::value :
|
||||
return "point";
|
||||
case tag::weight::line::value :
|
||||
return "line";
|
||||
case tag::weight::plane::value :
|
||||
return "plane";
|
||||
case tag::weight::cylinder::value :
|
||||
return "cylinder";
|
||||
default:
|
||||
return "unknown";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::string getWeight(boost::shared_ptr<T> ptr) {
|
||||
geom_visitor v;
|
||||
return ptr->apply(v);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct get_weight {
|
||||
typedef typename geometry_traits<T>::tag::weight type;
|
||||
};
|
||||
|
||||
//search the first type in the typevector with the given weight
|
||||
template<typename Vector, typename Weight>
|
||||
struct getWeightType {
|
||||
typedef typename mpl::find_if<Vector, boost::is_same<get_weight<mpl::_1>, Weight > >::type iter;
|
||||
typedef typename mpl::if_< boost::is_same<iter, typename mpl::end<Vector>::type >, mpl::void_, typename mpl::deref<iter>::type>::type type;
|
||||
};
|
||||
|
||||
typedef std::vector< fusion::vector2<std::string, std::string> > string_vec;
|
||||
typedef std::vector< fusion::vector2<std::vector<char>, std::vector<char> > > char_vec;
|
||||
|
||||
template<typename C>
|
||||
string_vec getConstraints(boost::shared_ptr<C> con) {
|
||||
|
||||
string_vec vec;
|
||||
std::vector<boost::any> cvec = con->getGenericConstraints();
|
||||
|
||||
typename std::vector<boost::any>::iterator it;
|
||||
for(it = cvec.begin(); it != cvec.end(); it++) {
|
||||
|
||||
if((*it).type() == typeid(dcm::Distance)) {
|
||||
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Distance>(*it).value);
|
||||
vec.push_back(fusion::make_vector(std::string("Distance"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::Angle)) {
|
||||
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Angle>(*it).value);
|
||||
vec.push_back(fusion::make_vector(std::string("Angle"), value));
|
||||
}
|
||||
else if((*it).type() == typeid(dcm::Orientation)) {
|
||||
std::string value = boost::lexical_cast<std::string>(boost::any_cast<dcm::Orientation>(*it).value);
|
||||
vec.push_back(fusion::make_vector(std::string("Orientation"), value));
|
||||
};
|
||||
};
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename Seq, typename T>
|
||||
struct push_seq {
|
||||
typedef typename fusion::result_of::as_vector<typename mpl::push_back< Seq, T >::type>::type type;
|
||||
};
|
||||
|
||||
template<typename State, typename Add>
|
||||
typename push_seq<State, Add>::type append(State& s, const typename Add::option_type& val) {
|
||||
|
||||
typedef typename push_seq<State, Add>::type Sequence;
|
||||
typedef typename fusion::result_of::begin<Sequence>::type Begin;
|
||||
typedef typename fusion::result_of::end<Sequence>::type End;
|
||||
typedef typename fusion::result_of::prior<End>::type EndOld;
|
||||
|
||||
//create the new sequence
|
||||
Sequence vec;
|
||||
|
||||
//copy the old values into the new sequence
|
||||
Begin b(vec);
|
||||
EndOld eo(vec);
|
||||
|
||||
fusion::iterator_range<Begin, EndOld> range(b, eo);
|
||||
fusion::copy(s, range);
|
||||
|
||||
//insert this object at the end of the sequence
|
||||
fusion::back(vec) = val;
|
||||
|
||||
//and return our new extendet sequence
|
||||
return vec;
|
||||
};
|
||||
|
||||
template<typename State, typename C, typename Count>
|
||||
typename boost::enable_if<typename mpl::greater<Count, mpl::int_<3> >::type, void>::type
|
||||
recursiveCreation(typename char_vec::iterator it,
|
||||
typename char_vec::iterator end,
|
||||
boost::shared_ptr<C> con,
|
||||
State s ) {};
|
||||
|
||||
template<typename State, typename C, typename Count>
|
||||
typename boost::enable_if<typename mpl::less_equal<Count, mpl::int_<3> >::type, void>::type
|
||||
recursiveCreation(typename char_vec::iterator it,
|
||||
typename char_vec::iterator end,
|
||||
boost::shared_ptr<C> con,
|
||||
State s ) {
|
||||
|
||||
if(it == end) {
|
||||
con->template initialize<State>(s);
|
||||
return;
|
||||
};
|
||||
|
||||
std::string first( fusion::at_c<0>(*it).begin(), fusion::at_c<0>(*it).end() );
|
||||
std::string second( fusion::at_c<1>(*it).begin(), fusion::at_c<1>(*it).end() );
|
||||
|
||||
if( first.compare("Distance") == 0 ) {
|
||||
typedef typename push_seq<State, dcm::Distance>::type Vec;
|
||||
Vec vec = append<State, dcm::Distance>(s, boost::lexical_cast<typename dcm::Distance::option_type>(second));
|
||||
recursiveCreation<Vec, C, typename mpl::next<Count>::type >(++it, end, con, vec);
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
void setConstraints(char_vec& vec, boost::shared_ptr<C> con ) {
|
||||
recursiveCreation<fusion::vector<>, C, mpl::int_<0> >(vec.begin(), vec.end(), con, fusion::vector<>());
|
||||
};
|
||||
|
||||
template <typename Geom, typename Row, typename Value>
|
||||
bool VectorOutput(Geom &v, Row& r, Value& val) {
|
||||
|
||||
if (r < v->m_global.rows()) {
|
||||
|
||||
val = v->m_global(r++);
|
||||
return true; // output continues
|
||||
}
|
||||
return false; // fail the output
|
||||
};
|
||||
|
||||
template <typename Geom, typename Row, typename Value>
|
||||
bool VectorInput(Geom &v, Row& r, Value& val) {
|
||||
|
||||
v.conservativeResize(r+1);
|
||||
v(r++) = val;
|
||||
return true; // output continues
|
||||
};
|
||||
|
||||
template<typename Geom>
|
||||
struct inject_set {
|
||||
|
||||
template<typename Vec, typename Obj>
|
||||
static void apply(Vec& v, Obj g) {
|
||||
Geom gt;
|
||||
(typename geometry_traits<Geom>::modell()).template inject<double,
|
||||
typename geometry_traits<Geom>::accessor >(gt, v);
|
||||
g->set(gt);
|
||||
};
|
||||
};
|
||||
//spezialisation if no type in the typelist has the right weight
|
||||
template<>
|
||||
struct inject_set<mpl::void_> {
|
||||
|
||||
template<typename Obj, typename Vec>
|
||||
static void apply(Vec& v, Obj g) {
|
||||
//TODO:throw
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
bool Create(System* sys, std::string& type,
|
||||
boost::shared_ptr<typename details::getModule3D<System>::type::Geometry3D> geom,
|
||||
typename System::Kernel::Vector& v) {
|
||||
|
||||
typedef typename details::getModule3D<System>::type::geometry_types Typelist;
|
||||
|
||||
if(type.compare("direction") == 0 ) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::direction>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("point") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::point>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("line") == 0) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::line>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("plane") == 0 ) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::plane>::type>::apply(v, geom);
|
||||
}
|
||||
else if(type.compare("cylinder") == 0 ) {
|
||||
inject_set<typename getWeightType<Typelist, tag::weight::cylinder>::type>::apply(v, geom);
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
// define a new real number formatting policy
|
||||
template <typename Num>
|
||||
struct scientific_policy : karma::real_policies<Num>
|
||||
{
|
||||
// we want the numbers always to be in scientific format
|
||||
static int floatfield(Num n) { return std::ios::scientific; }
|
||||
static unsigned precision(Num n) {return 16;};
|
||||
};
|
||||
|
||||
// define a new generator type based on the new policy
|
||||
typedef karma::real_generator<double, scientific_policy<double> > science_type;
|
||||
static science_type const scientific = science_type();
|
||||
} //details
|
||||
} //dcm
|
||||
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION( bool, vector_out, dcm::details::VectorOutput, 3)
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION( bool, vector_in, dcm::details::VectorInput, 3)
|
||||
BOOST_PHOENIX_ADAPT_FUNCTION( bool, create, dcm::details::Create, 4)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
dcm::GlobalEdge,
|
||||
(int, ID)
|
||||
(int, source)
|
||||
(int, target)
|
||||
)
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate< typename details::getModule3D<System>::type::Geometry3D , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator< typename details::getModule3D<System>::type::Geometry3D , System, iterator > {
|
||||
|
||||
typedef typename details::getModule3D<System>::type::Geometry3D Geometry;
|
||||
typedef karma::rule<iterator, boost::shared_ptr<Geometry>(), karma::locals<int> > generator;
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>Geometry3D</type>\n<class>")
|
||||
<< karma_ascii::string[karma::_1 = phx::bind(&details::getWeight<Geometry>, karma::_val)]
|
||||
<< "</class>" << karma::eol << "<value>"
|
||||
<< (details::scientific[ boost::spirit::_pass = vector_out(karma::_val, karma::_a, karma::_1) ] % ' ')
|
||||
<< "</value>";
|
||||
};
|
||||
static void init(generator& r);
|
||||
};
|
||||
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate< typename details::getModule3D<System>::type::vertex_prop , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator< typename details::getModule3D<System>::type::vertex_prop , System, iterator > {
|
||||
|
||||
typedef karma::rule<iterator, GlobalVertex()> generator;
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>Vertex</type>")
|
||||
<< karma::eol << "<value>" << karma::int_ << "</value>";
|
||||
};
|
||||
static void init(generator& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate< typename details::getModule3D<System>::type::Constraint3D , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator< typename details::getModule3D<System>::type::Constraint3D , System, iterator > {
|
||||
@@ -321,28 +74,20 @@ struct parser_generator< typename details::getModule3D<System>::type::Constraint
|
||||
typedef typename details::getModule3D<System>::type::Geometry3D Geometry3D;
|
||||
typedef typename details::getModule3D<System>::type::Constraint3D Constraint3D;
|
||||
typedef typename details::getModule3D<System>::type::vertex_prop vertex_prop;
|
||||
typedef typename details::getModule3D<System>::type::edge_prop edge_prop;
|
||||
typedef karma::rule<iterator, boost::shared_ptr<Constraint3D>()> generator;
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>Constraint3D</type>") << karma::eol
|
||||
<< "<connect first=" << karma::int_[karma::_1 = phx::bind(&Geometry3D::template getProperty<vertex_prop>, phx::bind(&Constraint3D::first, karma::_val))]
|
||||
<< " second=" << karma::int_[karma::_1 = phx::bind(&Geometry3D::template getProperty<vertex_prop>, phx::bind(&Constraint3D::second, karma::_val))] << "></connect>"
|
||||
<< (*(karma::eol<<"<constraint type="<<karma_ascii::string<<">"<<karma_ascii::string<<"</constraint>"))[karma::_1 = phx::bind(&details::getConstraints<Constraint3D>, karma::_val)];
|
||||
};
|
||||
static void init(generator& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate< typename details::getModule3D<System>::type::edge_prop , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator< typename details::getModule3D<System>::type::edge_prop , System, iterator > {
|
||||
|
||||
typedef karma::rule<iterator, GlobalEdge&()> generator;
|
||||
static void init(generator& r) {
|
||||
r %= karma::lit("<type>Edge</type>")
|
||||
<< karma::eol << "<value>" << karma::int_ << " "
|
||||
<< karma::int_ << " " << karma::int_ << "</value>";
|
||||
};
|
||||
static void init(generator& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
@@ -352,9 +97,7 @@ template<typename System, typename iterator>
|
||||
struct parser_generator<typename details::getModule3D<System>::type::fix_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, bool&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>Fix</type>\n<value>") << karma::bool_ <<"</value>";
|
||||
};
|
||||
static void init(generator& r);
|
||||
};
|
||||
|
||||
/****************************************************************************************************/
|
||||
@@ -362,40 +105,33 @@ struct parser_generator<typename details::getModule3D<System>::type::fix_prop, S
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename details::getModule3D<System>::type::Geometry3D , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename details::getModule3D<System>::type::Geometry3D, System, iterator > {
|
||||
|
||||
typedef typename details::getModule3D<System>::type::Geometry3D object_type;
|
||||
typedef typename System::Kernel Kernel;
|
||||
|
||||
|
||||
typedef qi::rule<iterator, boost::shared_ptr<object_type>(System*), qi::space_type, qi::locals<std::string, typename Kernel::Vector, int> > parser;
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>Geometry3D</type>")[ qi::_val = phx::construct<boost::shared_ptr<object_type> >( phx::new_<object_type>(*qi::_r1))]
|
||||
>> "<class>" >> (+qi::char_("a-zA-Z"))[qi::_a = phx::construct<std::string>(phx::begin(qi::_1), phx::end(qi::_1))] >> "</class>"
|
||||
>> "<value>" >> *qi::double_[ vector_in(qi::_b, qi::_c, qi::_1) ] >> "</value>"
|
||||
>> qi::eps[ create(qi::_r1, qi::_a, qi::_val, qi::_b) ];
|
||||
};
|
||||
static void init(parser& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename details::getModule3D<System>::type::vertex_prop, System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename details::getModule3D<System>::type::vertex_prop, System, iterator > {
|
||||
|
||||
|
||||
typedef qi::rule<iterator, GlobalVertex(), qi::space_type> parser;
|
||||
static void init(parser& r) {
|
||||
r %= qi::lit("<type>Vertex</type>") >> "<value>" >> qi::int_ >> "</value>";
|
||||
};
|
||||
static void init(parser& r);
|
||||
};
|
||||
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename details::getModule3D<System>::type::Constraint3D , System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename details::getModule3D<System>::type::Constraint3D, System, iterator > {
|
||||
@@ -403,48 +139,37 @@ struct parser_parser< typename details::getModule3D<System>::type::Constraint3D,
|
||||
typedef typename details::getModule3D<System>::type::Geometry3D Geometry3D;
|
||||
typedef typename details::getModule3D<System>::type::Constraint3D Constraint3D;
|
||||
typedef typename System::Kernel Kernel;
|
||||
|
||||
|
||||
typedef qi::rule<iterator, boost::shared_ptr<Constraint3D>(System*), qi::space_type > parser;
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>Constraint3D</type>")
|
||||
>> ("<connect first=" >> qi::int_ >> "second=" >> qi::int_ >> "></connect>")[
|
||||
qi::_val = phx::construct<boost::shared_ptr<Constraint3D> >(
|
||||
phx::new_<Constraint3D>(*qi::_r1,
|
||||
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_1),
|
||||
phx::bind(&System::Cluster::template getObject<Geometry3D, GlobalVertex>, phx::bind(&System::m_cluster, qi::_r1), qi::_2) ) )
|
||||
]
|
||||
>> (*("<constraint type=" >> *qi_ascii::alpha >> ">" >> *qi_ascii::alnum >>"</constraint>"))[phx::bind(&details::setConstraints<Constraint3D>, qi::_1, qi::_val)];
|
||||
};
|
||||
static void init(parser& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename details::getModule3D<System>::type::edge_prop, System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename details::getModule3D<System>::type::edge_prop, System, iterator > {
|
||||
|
||||
|
||||
typedef qi::rule<iterator, GlobalEdge(), qi::space_type> parser;
|
||||
static void init(parser& r) {
|
||||
r %= qi::lit("<type>Edge</type>")
|
||||
>> "<value>" >> qi::int_ >> qi::int_ >> qi::int_ >> "</value>";
|
||||
};
|
||||
static void init(parser& r);
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse< typename details::getModule3D<System>::type::fix_prop, System>
|
||||
: public mpl::true_{};
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser< typename details::getModule3D<System>::type::fix_prop, System, iterator > {
|
||||
|
||||
|
||||
typedef qi::rule<iterator, bool(), qi::space_type> parser;
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>Fix</type>") >> "<value>" >> qi::bool_ >> "</value>";
|
||||
};
|
||||
static void init(parser& r);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/state_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_MODULE3D_STATE_HPP
|
||||
#endif //DCM_MODULE3D_STATE_HPP
|
||||
|
||||
@@ -52,6 +52,7 @@ struct ModulePart {
|
||||
mpl::pair<recalculated, boost::function<void (Partptr) > > > PartSignal;
|
||||
|
||||
typedef ID Identifier;
|
||||
typedef mpl::map1<mpl::pair<recalculated, boost::function<void (boost::shared_ptr<Sys>)> > > signals;
|
||||
|
||||
class Part_base : public Object<Sys, Part, PartSignal > {
|
||||
protected:
|
||||
@@ -207,6 +208,9 @@ struct ModulePart {
|
||||
typename geometry_traits<T>::accessor >(geom, cm.getTransform());
|
||||
};
|
||||
|
||||
//needed system functions
|
||||
void system_sub(boost::shared_ptr<Sys> subsys) {};
|
||||
|
||||
protected:
|
||||
Sys* m_this;
|
||||
|
||||
@@ -239,9 +243,14 @@ struct ModulePart {
|
||||
|
||||
struct inheriter : public mpl::if_<boost::is_same<Identifier, No_Identifier>, inheriter_base, inheriter_id>::type {};
|
||||
|
||||
typedef mpl::vector0<> properties;
|
||||
struct subsystem_property {
|
||||
typedef Sys* type;
|
||||
typedef cluster_property kind;
|
||||
};
|
||||
|
||||
typedef mpl::vector1<subsystem_property> properties;
|
||||
typedef mpl::vector1<Part> objects;
|
||||
typedef mpl::vector0<> geometries;
|
||||
typedef mpl::vector0<> geometries;
|
||||
|
||||
struct PrepareCluster : public Job<Sys> {
|
||||
|
||||
@@ -307,6 +316,7 @@ template<typename T>
|
||||
typename ModulePart<Typelist, ID>::template type<Sys>::Part_base::Geom
|
||||
ModulePart<Typelist, ID>::type<Sys>::Part_base::addGeometry3D(const T& geom, CoordinateFrame frame) {
|
||||
Geom g(new Geometry3D(geom, *m_system));
|
||||
|
||||
if(frame == Local) {
|
||||
//we need to collect all transforms up to this part!
|
||||
Transform t;
|
||||
@@ -389,10 +399,12 @@ ModulePart<Typelist, ID>::type<Sys>::Part_base::clone(Sys& newSys) {
|
||||
boost::apply_visitor(clone_fnc, m_geometry);
|
||||
|
||||
fusion::vector<LocalVertex, boost::shared_ptr<Cluster>, bool> res = newSys.m_cluster->getLocalVertexGraph(gv);
|
||||
|
||||
if(!fusion::at_c<2>(res)) {
|
||||
//todo: throw
|
||||
return np;
|
||||
}
|
||||
|
||||
np->m_cluster = fusion::at_c<1>(res)->getVertexCluster(fusion::at_c<0>(res));
|
||||
|
||||
return np;
|
||||
@@ -451,6 +463,7 @@ template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
bool ModulePart<Typelist, ID>::type<Sys>::Part_id::hasGeometry3D(Identifier id) {
|
||||
typename Part_base::Geom g = Part_base::m_system->getGeometry3D(id);
|
||||
|
||||
if(!g)
|
||||
return false;
|
||||
|
||||
@@ -531,11 +544,14 @@ template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalVertex v) {
|
||||
Geom g = system.m_cluster->template getObject<Geometry3D>(v);
|
||||
|
||||
if(g) {
|
||||
g->template emitSignal<remove>(g);
|
||||
system.erase(g);
|
||||
}
|
||||
|
||||
Cons c = system.m_cluster->template getObject<Constraint3D>(v);
|
||||
|
||||
if(c) {
|
||||
c->template emitSignal<remove>(c);
|
||||
system.erase(c);
|
||||
@@ -546,6 +562,7 @@ template<typename Typelist, typename ID>
|
||||
template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::inheriter_base::remover::operator()(GlobalEdge e) {
|
||||
Cons c = system.m_cluster->template getObject<Constraint3D>(e);
|
||||
|
||||
if(c) {
|
||||
c->template emitSignal<remove>(c);
|
||||
system.erase(c);
|
||||
@@ -567,6 +584,7 @@ template<typename Sys>
|
||||
bool ModulePart<Typelist, ID>::type<Sys>::inheriter_id::hasPart(Identifier id) {
|
||||
if(getPart(id))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -576,10 +594,12 @@ typename ModulePart<Typelist, ID>::template type<Sys>::Partptr
|
||||
ModulePart<Typelist, ID>::type<Sys>::inheriter_id::getPart(Identifier id) {
|
||||
std::vector< Partptr >& vec = inheriter_base::m_this->template objectVector<Part>();
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
|
||||
return Partptr();
|
||||
};
|
||||
|
||||
@@ -594,6 +614,7 @@ template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::PrepareCluster::execute(Sys& sys) {
|
||||
//get all parts and set their values to the cluster's
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
|
||||
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
|
||||
|
||||
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getProperty<typename module3d::math_prop>();
|
||||
@@ -612,12 +633,21 @@ template<typename Sys>
|
||||
void ModulePart<Typelist, ID>::type<Sys>::EvaljuateCluster::execute(Sys& sys) {
|
||||
//get all parts and set their values to the cluster's
|
||||
typedef typename std::vector<Partptr>::iterator iter;
|
||||
|
||||
for(iter it = sys.template begin<Part>(); it != sys.template end<Part>(); it++) {
|
||||
|
||||
details::ClusterMath<Sys>& cm = (*it)->m_cluster->template getProperty<typename module3d::math_prop>();
|
||||
(*it)->m_transform = cm.getTransform();
|
||||
(*it)->finishCalculation();
|
||||
};
|
||||
|
||||
//get all subsystems and report their recalculation
|
||||
typedef typename std::vector<boost::shared_ptr<Sys> >::iterator siter;
|
||||
|
||||
for(siter it = sys.beginSubsystems(); it != sys.endSubsystems(); it++) {
|
||||
|
||||
(*it)->template emitSignal<recalculated>(*it);
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/fusion/include/make_vector.hpp>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
@@ -426,6 +428,8 @@ struct ModuleShape3D {
|
||||
m_this = (Sys*)this;
|
||||
};
|
||||
|
||||
void system_sub(boost::shared_ptr<Sys> subsys) {};
|
||||
|
||||
protected:
|
||||
Sys* m_this;
|
||||
|
||||
@@ -471,11 +475,11 @@ struct ModuleShape3D {
|
||||
typedef mpl::vector3<shape_purpose_prop, shape_constraint_prop, shape_geometry_prop> properties;
|
||||
typedef mpl::vector1<Shape3D> objects;
|
||||
typedef mpl::vector1<tag::segment3D> geometries;
|
||||
typedef mpl::map0<> signals;
|
||||
|
||||
//needed static functions
|
||||
static void system_init(Sys& sys) {};
|
||||
static void system_copy(const Sys& from, Sys& into) {};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -557,6 +561,7 @@ ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::geometry(purpose
|
||||
if((*it)->template getProperty<shape_purpose_prop>() == f)
|
||||
return *it;
|
||||
};
|
||||
|
||||
return boost::shared_ptr<Geometry3D>();
|
||||
};
|
||||
|
||||
@@ -603,14 +608,17 @@ template<typename Derived>
|
||||
void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::disconnectAll() {
|
||||
|
||||
typename GeometryVector::iterator git;
|
||||
|
||||
for(git = m_geometries.begin(); git!=m_geometries.end(); git++)
|
||||
fusion::at_c<0>(*git)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*git));
|
||||
|
||||
typename ShapeVector::iterator sit;
|
||||
|
||||
for(sit = m_shapes.begin(); sit!=m_shapes.end(); sit++)
|
||||
fusion::at_c<0>(*sit)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*sit));
|
||||
|
||||
typename ConstraintVector::iterator cit;
|
||||
|
||||
for(cit = m_constraints.begin(); cit!=m_constraints.end(); cit++)
|
||||
fusion::at_c<0>(*cit)->template disconnectSignal<dcm::remove>(fusion::at_c<1>(*cit));
|
||||
};
|
||||
@@ -634,12 +642,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
|
||||
|
||||
//get the vector object where the geometry is part of
|
||||
typename GeometryVector::const_iterator it;
|
||||
|
||||
for(it=m_geometries.begin(); it!=m_geometries.end(); it++) {
|
||||
if(fusion::at_c<0>(*it)==g)
|
||||
break;
|
||||
};
|
||||
|
||||
m_geometries.erase(std::remove(m_geometries.begin(), m_geometries.end(), *it), m_geometries.end());
|
||||
|
||||
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
|
||||
};
|
||||
|
||||
@@ -653,12 +663,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
|
||||
|
||||
//get the vector object where the geometry is part of
|
||||
typename ShapeVector::const_iterator it;
|
||||
|
||||
for(it=m_shapes.begin(); it!=m_shapes.end(); it++) {
|
||||
if(fusion::at_c<0>(*it)==g)
|
||||
break;
|
||||
};
|
||||
|
||||
m_shapes.erase(std::remove(m_shapes.begin(), m_shapes.end(), *it), m_shapes.end());
|
||||
|
||||
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
|
||||
};
|
||||
|
||||
@@ -672,12 +684,14 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::Shape3D_base<Derived>::remove(boost
|
||||
|
||||
//get the vector object where the geometry is part of
|
||||
typename ConstraintVector::const_iterator it;
|
||||
|
||||
for(it=m_constraints.begin(); it!=m_constraints.end(); it++) {
|
||||
if(fusion::at_c<0>(*it)==g)
|
||||
break;
|
||||
};
|
||||
|
||||
m_constraints.erase(std::remove(m_constraints.begin(), m_constraints.end(), *it), m_constraints.end());
|
||||
|
||||
ObjBase::m_system->removeShape3D(ObjBase::shared_from_this());
|
||||
};
|
||||
|
||||
@@ -780,10 +794,11 @@ void ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_base::removeShape3D(boost
|
||||
//remove all constraints is unnessecary as they get removed together with the geometries
|
||||
//remove all geometries
|
||||
typedef typename Shape3D::geometry3d_iterator git;
|
||||
|
||||
for(git it=g->beginGeometry3D(); it!=g->endGeometry3D(); it++)
|
||||
m_this->removeGeometry3D(*it);
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: find out why it iterates over a empty vector and crashs...
|
||||
//remove all subshapes
|
||||
typedef typename Shape3D::shape3d_iterator sit;
|
||||
@@ -801,6 +816,7 @@ template<typename Sys>
|
||||
bool ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::hasShape3D(Identifier id) {
|
||||
if(getShape3D(id))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -810,10 +826,12 @@ boost::shared_ptr<typename ModuleShape3D<Typelist, ID>::template type<Sys>::Shap
|
||||
ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::getShape3D(Identifier id) {
|
||||
std::vector< boost::shared_ptr<Shape3D> >& vec = inheriter_base::m_this->template objectVector<Shape3D>();
|
||||
typedef typename std::vector< boost::shared_ptr<Shape3D> >::iterator iter;
|
||||
|
||||
for(iter it=vec.begin(); it!=vec.end(); it++) {
|
||||
if(compare_traits<Identifier>::compare((*it)->getIdentifier(), id))
|
||||
return *it;
|
||||
};
|
||||
|
||||
return boost::shared_ptr<Shape3D>();
|
||||
};
|
||||
|
||||
@@ -822,6 +840,7 @@ template<typename Sys>
|
||||
void ModuleShape3D<Typelist, ID>::type<Sys>::inheriter_id::removeShape3D(Identifier id) {
|
||||
|
||||
boost::shared_ptr<Shape3D> s = getShape3D(id);
|
||||
|
||||
if(s)
|
||||
removeShape3D(s);
|
||||
};
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "opendcm/core/property.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
@@ -33,4 +36,34 @@ struct cluster_vertex_prop {
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||
(T1)(T2)(T3)(T4),
|
||||
(dcm::ClusterGraph) (T1)(T2)(T3)(T4),
|
||||
(int, test)
|
||||
(typename dcm::details::pts<T3>::type, m_properties))
|
||||
|
||||
//fusion adopt struct needs to avoid commas for type definition, as this breaks the macro syntax.
|
||||
//we use this ugly nested struct to declare the dcm system from template parameters without commas
|
||||
template<typename T1>
|
||||
struct t1 {
|
||||
template<typename T2>
|
||||
struct t2 {
|
||||
template<typename T3>
|
||||
struct t3 {
|
||||
template<typename T4>
|
||||
struct t4 {
|
||||
typedef dcm::System<T1,T2,T3,T4> type;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||
(Kernel)(M1)(M2)(M3),
|
||||
(dcm::System)(Kernel)(M1)(M2)(M3),
|
||||
(typename t1<Kernel>::template t2<M1>::template t3<M2>::template t4<M3>::type::OptionOwner::Properties, m_options.m_properties)
|
||||
(typename Kernel::Properties, m_kernel.m_properties)
|
||||
(boost::shared_ptr<typename t1<Kernel>::template t2<M1>::template t3<M2>::template t4<M3>::type::Cluster>, m_cluster)
|
||||
)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -68,8 +68,8 @@ struct vertex_generator : karma::grammar<Iterator, std::vector<typename Sys::Clu
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "edge_vertex_generator_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/edge_vertex_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "extractor.hpp"
|
||||
#include "object_parser.hpp"
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace fusion = boost::fusion;
|
||||
@@ -68,8 +69,8 @@ struct vertex_parser : qi::grammar< IIterator, fusion::vector<LocalVertex, Globa
|
||||
}
|
||||
}
|
||||
|
||||
//#ifndef USE_EXTERNAL
|
||||
//#include "edge_vertex_parser_imp.hpp"
|
||||
//#endif
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/edge_vertex_parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,7 @@ struct Extractor {
|
||||
std::pair<viter, viter> res = boost::vertices(cluster);
|
||||
for(; res.first != res.second; res.first++)
|
||||
range.push_back(cluster[*res.first]);
|
||||
|
||||
};
|
||||
void getEdgeRange(typename Sys::Cluster& cluster,
|
||||
std::vector<fusion::vector3<typename Sys::Cluster::edge_bundle, GlobalVertex, GlobalVertex> >& range) {
|
||||
@@ -66,13 +67,13 @@ struct Extractor {
|
||||
else
|
||||
l = 0;
|
||||
};
|
||||
void getClusterRange(typename Sys::Cluster& cluster, std::vector<std::pair<GlobalVertex, typename Sys::Cluster*> >& range) {
|
||||
|
||||
typedef typename Sys::Cluster::const_cluster_iterator iter;
|
||||
|
||||
for(iter it = cluster.m_clusters.begin(); it != cluster.m_clusters.end(); it++) {
|
||||
range.push_back( std::make_pair( cluster.getGlobalVertex((*it).first), (*it).second.get() ));
|
||||
};
|
||||
void getClusterRange(typename Sys::Cluster& cluster, std::vector<std::pair<GlobalVertex, boost::shared_ptr<typename Sys::Cluster> > >& range) {
|
||||
|
||||
typedef typename Sys::Cluster::const_cluster_iterator iter;
|
||||
|
||||
for(iter it = cluster.m_clusters.begin(); it != cluster.m_clusters.end(); it++) {
|
||||
range.push_back(std::make_pair(cluster.getGlobalVertex((*it).first), (*it).second));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -101,18 +102,17 @@ struct Injector {
|
||||
fusion::at_c<1>(cluster->operator[](e)) = bundles;
|
||||
};
|
||||
void setVertexProperty(typename Sys::Cluster* cluster, int value) {
|
||||
cluster->template setProperty<details::cluster_vertex_prop>(value);
|
||||
cluster->template setProperty<details::cluster_vertex_prop>(value);
|
||||
};
|
||||
void addClusters(std::vector<typename Sys::Cluster*>& clusters, typename Sys::Cluster* cluster) {
|
||||
|
||||
typename std::vector<typename Sys::Cluster*>::iterator it;
|
||||
for(it = clusters.begin(); it != clusters.end(); it++) {
|
||||
LocalVertex v = cluster->getLocalVertex((*it)->template getProperty<details::cluster_vertex_prop>()).first;
|
||||
cluster->m_clusters[v] = boost::shared_ptr<typename Sys::Cluster>(*it);
|
||||
};
|
||||
};
|
||||
void addVertex(typename Sys::Cluster* cluster, fusion::vector<LocalVertex, GlobalVertex>& vec) {
|
||||
vec = cluster->addVertex();
|
||||
void addClusters(std::vector<boost::shared_ptr<typename Sys::Cluster> >& clusters, typename Sys::Cluster* cluster) {
|
||||
|
||||
//vertices for the cluster need to be added already (as edges need vertices created)
|
||||
//so we don't create a vertex here.
|
||||
typename std::vector<boost::shared_ptr<typename Sys::Cluster> >::iterator it;
|
||||
for(it = clusters.begin(); it != clusters.end(); it++) {
|
||||
LocalVertex v = cluster->getLocalVertex((*it)->template getProperty<details::cluster_vertex_prop>()).first;
|
||||
cluster->m_clusters[v] = *it;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <opendcm/core/clustergraph.hpp>
|
||||
|
||||
#include "traits.hpp"
|
||||
#include "traits_impl.hpp"
|
||||
#include "imp/traits_impl.hpp"
|
||||
#include "indent.hpp"
|
||||
|
||||
#include <boost/mpl/int.hpp>
|
||||
@@ -53,7 +53,7 @@ namespace dcm {
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
template<typename Sys>
|
||||
struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
|
||||
struct generator : karma::grammar<Iterator, Sys&()> {
|
||||
|
||||
typedef typename Sys::Cluster graph;
|
||||
typedef typename graph::Properties graph_bundle;
|
||||
@@ -62,11 +62,15 @@ struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
|
||||
|
||||
generator();
|
||||
|
||||
karma::rule<Iterator, graph& ()> start;
|
||||
karma::rule<Iterator, Sys& ()> start;
|
||||
|
||||
karma::rule<Iterator, std::pair<GlobalVertex, graph*>()> cluster_pair;
|
||||
karma::rule<Iterator, std::pair<GlobalVertex, boost::shared_ptr<graph> >()> cluster_pair;
|
||||
karma::rule<Iterator, graph&()> cluster;
|
||||
karma::rule<Iterator, Sys&()> system;
|
||||
|
||||
details::cluster_prop_gen<Sys> cluster_prop;
|
||||
details::system_prop_gen<Sys> system_prop;
|
||||
details::kernel_prop_gen<Sys> kernel_prop;
|
||||
|
||||
details::vertex_generator<Sys> vertex_range;
|
||||
details::edge_generator<Sys> edge_range;
|
||||
@@ -76,8 +80,8 @@ struct generator : karma::grammar<Iterator, typename Sys::Cluster& ()> {
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "generator_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_GENERATOR_H
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_GENERATOR_IMP_H
|
||||
#define DCM_EDGE_GENERATOR_IMP_H
|
||||
|
||||
#include "../edge_vertex_generator.hpp"
|
||||
#include "boost/phoenix/fusion/at.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
edge_generator<Sys>::edge_generator() : edge_generator<Sys>::base_type(edge_range) {
|
||||
|
||||
globaledge = karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeID, &ex, karma::_val, karma::_1)]
|
||||
<< " source=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeSource, &ex, karma::_val, karma::_1)]
|
||||
<< " target=" << karma::int_[phx::bind(&Extractor<Sys>::getGlobalEdgeTarget, &ex, karma::_val, karma::_1)] << '>'
|
||||
<< "#" << objects[karma::_1 = phx::at_c<0>(karma::_val)] << "$\n" ;
|
||||
|
||||
|
||||
globaledge_range = *(karma::lit("<GlobalEdge id=")<<globaledge<<karma::lit("</GlobalEdge>"));
|
||||
|
||||
edge = karma::lit("source=")<<karma::int_[karma::_1 = phx::at_c<1>(karma::_val)] << " target="<<karma::int_[karma::_1 = phx::at_c<2>(karma::_val)] << ">#"
|
||||
<< edge_prop[karma::_1 = phx::at_c<0>(phx::at_c<0>(karma::_val))]
|
||||
<< karma::eol << globaledge_range[karma::_1 = phx::at_c<1>(phx::at_c<0>(karma::_val))] << '$' << karma::eol;
|
||||
|
||||
edge_range = (karma::lit("<Edge ") << edge << karma::lit("</Edge>")) % karma::eol;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_generator<Sys>::vertex_generator() : vertex_generator<Sys>::base_type(vertex_range) {
|
||||
|
||||
vertex = karma::int_ << ">#" << vertex_prop << objects << "$\n";
|
||||
|
||||
vertex_range = '\n' << (karma::lit("<Vertex id=") << vertex << karma::lit("</Vertex>")) % karma::eol;
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_EDGE_PARSER_IMP_H
|
||||
#define DCM_EDGE_PARSER_IMP_H
|
||||
|
||||
#include "../edge_vertex_parser.hpp"
|
||||
#include "boost/phoenix/fusion/at.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename Sys>
|
||||
edge_parser<Sys>::edge_parser() : edge_parser<Sys>::base_type(edge) {
|
||||
|
||||
global_edge = qi::lit("<GlobalEdge") >> qi::lit("id=") >> qi::int_[phx::bind(&GlobalEdge::ID, phx::at_c<1>(qi::_val)) = qi::_1]
|
||||
>> qi::lit("source=") >> qi::int_[phx::bind(&GlobalEdge::source, phx::at_c<1>(qi::_val)) = qi::_1]
|
||||
>> qi::lit("target=") >> qi::int_[phx::bind(&GlobalEdge::target, phx::at_c<1>(qi::_val)) = qi::_1] >> '>'
|
||||
>> objects(qi::_r1)[phx::at_c<0>(qi::_val) = qi::_1] >> "</GlobalEdge>";
|
||||
|
||||
edge = (qi::lit("<Edge") >> "source=" >> qi::int_ >> "target=" >> qi::int_ >> '>')[qi::_val = phx::bind((&Sys::Cluster::addEdgeGlobal), qi::_r1, qi::_1, qi::_2)]
|
||||
>> edge_prop[phx::bind(&Injector<Sys>::setEdgeProperties, &in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> (*global_edge(qi::_r2))[phx::bind(&Injector<Sys>::setEdgeBundles, &in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> ("</Edge>");
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_parser<Sys>::vertex_parser() : vertex_parser<Sys>::base_type(vertex) {
|
||||
|
||||
vertex = qi::lit("<Vertex id=") >> qi::int_[qi::_val = phx::bind(&Sys::Cluster::addVertex, qi::_r1, qi::_1)]
|
||||
>> '>' >> prop[phx::bind(&Injector<Sys>::setVertexProperties, &in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> objects(qi::_r2)[phx::bind(&Injector<Sys>::setVertexObjects, &in, qi::_r1, phx::at_c<0>(qi::_val), qi::_1)]
|
||||
>> ("</Vertex>");
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_GENERATOR_IMP_H
|
||||
#define DCM_GENERATOR_IMP_H
|
||||
|
||||
#include "../generator.hpp"
|
||||
#include "opendcm/core/clustergraph.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/fusion/adapted/struct.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace traits
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
struct transform_attribute<boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> > const, dcm::ClusterGraph<T1,T2,T3,T4>&, karma::domain>
|
||||
{
|
||||
typedef dcm::ClusterGraph<T1,T2,T3,T4>& type;
|
||||
static type pre(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> > const& val) {
|
||||
return *val;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Sys>
|
||||
generator<Sys>::generator() : generator<Sys>::base_type(start) {
|
||||
|
||||
cluster %= karma::omit[karma::int_] << cluster_prop
|
||||
<< -karma::buffer[karma::eol << (cluster_pair % karma::eol)[phx::bind(&Extractor<Sys>::getClusterRange, &ex, karma::_val, karma::_1)]]
|
||||
<< -vertex_range[phx::bind(&Extractor<Sys>::getVertexRange, &ex, karma::_val, karma::_1)]
|
||||
<< -karma::buffer[karma::eol << edge_range[phx::bind(&Extractor<Sys>::getEdgeRange, &ex, karma::_val, karma::_1)]]
|
||||
<< "$" << karma::eol
|
||||
<< karma::lit("</Cluster>");
|
||||
|
||||
cluster_pair %= karma::lit("<Cluster id=") << karma::int_ << ">#"
|
||||
<< qi::attr_cast<boost::shared_ptr<graph>, graph&>(cluster);
|
||||
|
||||
system %= system_prop << karma::lit("<Kernel>#") << kernel_prop
|
||||
<< "$" << karma::eol << karma::lit("</Kernel>") << karma::eol
|
||||
<< karma::lit("<Cluster id=0>#") << qi::attr_cast<boost::shared_ptr<graph>, graph&>(cluster);
|
||||
|
||||
start %= karma::lit("<openDCM>#") << karma::eol << system << "$" << karma::eol << karma::lit("</openDCM>");
|
||||
};
|
||||
|
||||
}//namespace dcm
|
||||
|
||||
#endif //DCM_GENERATOR_H
|
||||
|
||||
|
||||
|
||||
70
src/Mod/Assembly/App/opendcm/moduleState/imp/module_imp.hpp
Normal file
70
src/Mod/Assembly/App/opendcm/moduleState/imp/module_imp.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_MODULE_STATE_IMP_H
|
||||
#define DCM_MODULE_STATE_IMP_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "../module.hpp"
|
||||
#include "../indent.hpp"
|
||||
#include "../generator.hpp"
|
||||
#include "../parser.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename Sys>
|
||||
void ModuleState::type<Sys>::inheriter::saveState(std::ostream& stream) {
|
||||
|
||||
boost::iostreams::filtering_ostream indent_stream;
|
||||
indent_stream.push(indent_filter());
|
||||
indent_stream.push(stream);
|
||||
|
||||
std::ostream_iterator<char> out(indent_stream);
|
||||
generator<Sys> gen;
|
||||
|
||||
karma::generate(out, gen, *m_this);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
void ModuleState::type<Sys>::inheriter::loadState(std::istream& stream) {
|
||||
|
||||
//disable skipping of whitespace
|
||||
stream.unsetf(std::ios::skipws);
|
||||
|
||||
// wrap istream into iterator
|
||||
boost::spirit::istream_iterator begin(stream);
|
||||
boost::spirit::istream_iterator end;
|
||||
|
||||
// use iterator to parse file data
|
||||
parser<Sys> par;
|
||||
m_this->clear();
|
||||
qi::phrase_parse(begin, end, par, qi::space, *m_this);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //DCM_MODULE_STATE_H
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef DCM_OBJECT_GENERATOR_IMP_H
|
||||
#define DCM_OBJECT_GENERATOR_IMP_H
|
||||
|
||||
|
||||
#include "traits_impl.hpp"
|
||||
#include "../object_generator.hpp"
|
||||
#include "property_generator_imp.hpp"
|
||||
|
||||
#include "boost/phoenix/fusion/at.hpp"
|
||||
#include <boost/phoenix/bind.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace phx = boost::phoenix;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename Sys, typename Object, typename Gen>
|
||||
obj_grammar<Sys, Object,Gen>::obj_grammar() : obj_grammar<Sys, Object,Gen>::base_type(start) {
|
||||
Gen::init(subrule);
|
||||
start = karma::lit("\n<Object>") << '#' << karma::eol << subrule
|
||||
<< prop[phx::bind(&obj_grammar::getProperties, karma::_val, karma::_1)]
|
||||
<< '$' << karma::eol << karma::lit("</Object>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename Object, typename Gen>
|
||||
void obj_grammar<Sys, Object,Gen>::getProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::PropertySequence>::type& seq) {
|
||||
|
||||
if(ptr) seq = ptr->m_properties;
|
||||
else {
|
||||
//TODO: throw
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
obj_gen<Sys>::obj_gen() : obj_gen<Sys>::base_type(obj) {
|
||||
|
||||
obj = -(karma::eps(valid<0>::value) << karma::eps(phx::at_c<index<0>::value>(karma::_val)) << fusion::at<index<0> >(rules)[karma::_1 = phx::at_c<index<0>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<1>::value) << karma::eps(phx::at_c<index<1>::value>(karma::_val)) << fusion::at<index<1> >(rules)[karma::_1 = phx::at_c<index<1>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<2>::value) << karma::eps(phx::at_c<index<2>::value>(karma::_val)) << fusion::at<index<2> >(rules)[karma::_1 = phx::at_c<index<2>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<3>::value) << karma::eps(phx::at_c<index<3>::value>(karma::_val)) << fusion::at<index<3> >(rules)[karma::_1 = phx::at_c<index<3>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<4>::value) << karma::eps(phx::at_c<index<4>::value>(karma::_val)) << fusion::at<index<4> >(rules)[karma::_1 = phx::at_c<index<4>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<5>::value) << karma::eps(phx::at_c<index<5>::value>(karma::_val)) << fusion::at<index<5> >(rules)[karma::_1 = phx::at_c<index<5>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<6>::value) << karma::eps(phx::at_c<index<6>::value>(karma::_val)) << fusion::at<index<6> >(rules)[karma::_1 = phx::at_c<index<6>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<7>::value) << karma::eps(phx::at_c<index<7>::value>(karma::_val)) << fusion::at<index<7> >(rules)[karma::_1 = phx::at_c<index<7>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<8>::value) << karma::eps(phx::at_c<index<8>::value>(karma::_val)) << fusion::at<index<8> >(rules)[karma::_1 = phx::at_c<index<8>::value>(karma::_val)])
|
||||
<< -(karma::eps(valid<9>::value) << karma::eps(phx::at_c<index<9>::value>(karma::_val)) << fusion::at<index<9> >(rules)[karma::_1 = phx::at_c<index<9>::value>(karma::_val)]);
|
||||
|
||||
};
|
||||
|
||||
} //namespace details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_OBJECT_GENERATOR_H
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_OBJECT_PARSER_IMP_H
|
||||
#define DCM_OBJECT_PARSER_IMP_H
|
||||
|
||||
#include "../object_parser.hpp"
|
||||
#include "property_parser_imp.hpp"
|
||||
#include "boost/phoenix/fusion/at.hpp"
|
||||
|
||||
namespace dcm {
|
||||
namespace details {
|
||||
|
||||
template<typename srs, typename prs, typename dist>
|
||||
typename boost::enable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_obj_init(srs& sseq, prs& pseq) {
|
||||
|
||||
if(dist::value == 0) {
|
||||
fusion::at<dist>(pseq) %= fusion::at<dist>(sseq)(qi::_r1, qi::_r2);
|
||||
}
|
||||
else {
|
||||
fusion::at<dist>(pseq) %= fusion::at<typename mpl::prior< typename mpl::max<dist, mpl::int_<1> >::type >::type>(pseq)(qi::_r1, qi::_r2) | fusion::at<dist>(sseq)(qi::_r1, qi::_r2);
|
||||
}
|
||||
|
||||
recursive_obj_init<srs, prs, typename mpl::next<dist>::type>(sseq, pseq);
|
||||
};
|
||||
|
||||
template<typename srs, typename prs, typename dist>
|
||||
typename boost::disable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_obj_init(srs& sseq, prs& pseq) {};
|
||||
|
||||
|
||||
template<typename Sys, typename ObjList, typename Object, typename Par>
|
||||
obj_parser<Sys, ObjList, Object, Par>::obj_parser(): obj_parser::base_type(start) {
|
||||
|
||||
typedef typename mpl::find<ObjList, Object>::type::pos pos;
|
||||
|
||||
Par::init(subrule);
|
||||
start = qi::lit("<Object>") >> subrule(qi::_r2)[phx::at_c<pos::value>(*qi::_r1) = qi::_1]
|
||||
>> qi::eps(phx::at_c<pos::value>(*qi::_r1))[ phx::bind(&Sys::template push_back<Object>, qi::_r2, phx::at_c<pos::value>(*qi::_r1))]
|
||||
>> prop[phx::bind(&obj_parser::setProperties, phx::at_c<pos::value>(*qi::_r1), qi::_1)]
|
||||
>> qi::lit("</Object>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename ObjList, typename Object, typename Par>
|
||||
void obj_parser<Sys, ObjList, Object, Par>::setProperties(boost::shared_ptr<Object> ptr, typename details::pts<typename Object::PropertySequence>::type& seq) {
|
||||
if(ptr) ptr->m_properties = seq;
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
obj_par<Sys>::obj_par(): obj_par<Sys>::base_type(obj) {
|
||||
|
||||
recursive_obj_init<typename fusion::result_of::as_vector<sub_rules_sequence>::type,
|
||||
typename fusion::result_of::as_vector<parent_rules_sequence>::type,
|
||||
mpl::int_<0> >(sub_rules, parent_rules);
|
||||
|
||||
obj = *(fusion::back(parent_rules)(&qi::_val, qi::_r1));
|
||||
};
|
||||
|
||||
}//details
|
||||
}//DCM
|
||||
|
||||
|
||||
#endif
|
||||
77
src/Mod/Assembly/App/opendcm/moduleState/imp/parser_imp.hpp
Normal file
77
src/Mod/Assembly/App/opendcm/moduleState/imp/parser_imp.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PARSER_IMP_H
|
||||
#define DCM_PARSER_IMP_H
|
||||
|
||||
#include <boost/spirit/include/qi_attr_cast.hpp>
|
||||
|
||||
#include "opendcm/core/system.hpp"
|
||||
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
#include "../parser.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace traits
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
struct transform_attribute<boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >, typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties, qi::domain>
|
||||
{
|
||||
typedef typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties& type;
|
||||
static type pre(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >& val) {
|
||||
return val->m_properties;
|
||||
}
|
||||
static void post(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> >const& val, typename dcm::ClusterGraph<T1,T2,T3,T4>::Properties const& attr) {}
|
||||
static void fail(boost::shared_ptr<dcm::ClusterGraph<T1,T2,T3,T4> > const&) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
template<typename Sys>
|
||||
parser<Sys>::parser() : parser<Sys>::base_type(system) {
|
||||
|
||||
cluster %= qi::lit("<Cluster id=") >> qi::omit[qi::int_[qi::_a = qi::_1]] >> ">"
|
||||
>> -(qi::eps(qi::_a > 0)[qi::_val = phx::construct<boost::shared_ptr<graph> >(phx::new_<typename Sys::Cluster>())])
|
||||
>> qi::eps[phx::bind(&Sys::Cluster::setCopyMode, &(*qi::_val), true)]
|
||||
>> qi::eps[phx::bind(&Injector<Sys>::setVertexProperty, &in, &(*qi::_val), qi::_a)]
|
||||
>> qi::attr_cast<boost::shared_ptr<graph>, typename graph::Properties>(cluster_prop >> qi::eps)
|
||||
>> qi::omit[(*cluster(qi::_r1))[qi::_b = qi::_1]]
|
||||
>> qi::omit[*vertex(&(*qi::_val), qi::_r1)]
|
||||
>> qi::omit[*edge(&(*qi::_val), qi::_r1)]
|
||||
>> qi::eps[phx::bind(&Injector<Sys>::addClusters, &in, qi::_b, &(*qi::_val))]
|
||||
>> qi::eps[phx::bind(&Sys::Cluster::setCopyMode, &(*qi::_val), false)]
|
||||
>> "</Cluster>";
|
||||
|
||||
system %= qi::lit("<openDCM>") >> -system_prop
|
||||
>> qi::lit("<Kernel>") >> -kernel_prop >> qi::lit("</Kernel>")
|
||||
>> cluster(&qi::_val) >> qi::lit("</openDCM>");
|
||||
};
|
||||
|
||||
}
|
||||
#endif //DCM_PARSER_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef DCM_PROPERTY_GENERATOR_IMP_H
|
||||
#define DCM_PROPERTY_GENERATOR_IMP_H
|
||||
|
||||
#include "../property_generator.hpp"
|
||||
#include "traits_impl.hpp"
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef std::ostream_iterator<char> Iterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
//grammar for a single property
|
||||
template<typename Prop, typename Gen>
|
||||
prop_grammar<Prop, Gen>::prop_grammar() : prop_grammar<Prop, Gen>::base_type(start) {
|
||||
|
||||
Gen::init(subrule);
|
||||
start = karma::lit("\n<Property>") << '#' << karma::eol << subrule
|
||||
<< '$' << karma::eol << karma::lit("</Property>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename PropertyList>
|
||||
prop_gen<Sys, PropertyList>::prop_gen() : prop_gen<Sys, PropertyList>::base_type(prop) {
|
||||
|
||||
prop = fusion::at_c<0>(rules) << fusion::at_c<1>(rules) << fusion::at_c<2>(rules)
|
||||
<< fusion::at_c<3>(rules) << fusion::at_c<4>(rules) << fusion::at_c<5>(rules)
|
||||
<< fusion::at_c<6>(rules) << fusion::at_c<7>(rules) << fusion::at_c<8>(rules)
|
||||
<< fusion::at_c<9>(rules);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
cluster_prop_gen<Sys>::cluster_prop_gen() : prop_gen<Sys, typename Sys::Cluster::cluster_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_prop_gen<Sys>::vertex_prop_gen() : prop_gen<Sys, typename Sys::Cluster::vertex_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
edge_prop_gen<Sys>::edge_prop_gen() : prop_gen<Sys, typename Sys::Cluster::edge_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
system_prop_gen<Sys>::system_prop_gen() : prop_gen<Sys, typename Sys::OptionOwner::PropertySequence>() {};
|
||||
|
||||
template<typename Sys>
|
||||
kernel_prop_gen<Sys>::kernel_prop_gen() : prop_gen<Sys, typename Sys::Kernel::PropertySequence>() {};
|
||||
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#endif //DCM_PROPERTY_GENERATOR_H
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef DCM_PROPERTY_PARSER_IMP_H
|
||||
#define DCM_PROPERTY_PARSER_IMP_H
|
||||
|
||||
#include "../property_parser.hpp"
|
||||
#include "traits_impl.hpp"
|
||||
|
||||
#include <boost/fusion/include/back.hpp>
|
||||
#include <boost/phoenix/fusion/at.hpp>
|
||||
|
||||
|
||||
namespace dcm {
|
||||
|
||||
typedef boost::spirit::istream_iterator IIterator;
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename srs, typename prs, typename dist>
|
||||
typename boost::enable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_init(srs& sseq, prs& pseq) {
|
||||
|
||||
if(dist::value == 0) {
|
||||
fusion::at<dist>(pseq) %= fusion::at<dist>(sseq)(qi::_r1);
|
||||
}
|
||||
else {
|
||||
fusion::at<dist>(pseq) %= fusion::at<typename mpl::prior< typename mpl::max<dist, mpl::int_<1> >::type >::type>(pseq)(qi::_r1) | fusion::at<dist>(sseq)(qi::_r1);
|
||||
}
|
||||
|
||||
recursive_init<srs, prs, typename mpl::next<dist>::type>(sseq, pseq);
|
||||
};
|
||||
|
||||
template<typename srs, typename prs, typename dist>
|
||||
typename boost::disable_if<mpl::less< dist, mpl::size<srs> >, void >::type recursive_init(srs& sseq, prs& pseq) {};
|
||||
|
||||
template<typename ParentRuleSequence, typename Rule>
|
||||
typename boost::disable_if<typename fusion::result_of::empty<ParentRuleSequence>::type, void>::type
|
||||
initalizeLastRule(ParentRuleSequence& pr, Rule& r) {
|
||||
r = *(fusion::back(pr)(&qi::_val));
|
||||
};
|
||||
|
||||
template<typename ParentRuleSequence, typename Rule>
|
||||
typename boost::enable_if<typename fusion::result_of::empty<ParentRuleSequence>::type, void>::type
|
||||
initalizeLastRule(ParentRuleSequence& pr, Rule& r) {};
|
||||
|
||||
|
||||
template<typename PropList, typename Prop, typename Par>
|
||||
prop_parser<PropList, Prop, Par>::prop_parser() : prop_parser<PropList, Prop, Par>::base_type(start) {
|
||||
|
||||
typedef typename mpl::find<PropList, Prop>::type::pos pos;
|
||||
|
||||
Par::init(subrule);
|
||||
start = qi::lit("<Property>") >> subrule[phx::at_c<pos::value>(*qi::_r1) = qi::_1] >> qi::lit("</Property>");
|
||||
};
|
||||
|
||||
template<typename Sys, typename PropertyList>
|
||||
prop_par<Sys, PropertyList>::prop_par() : prop_par<Sys, PropertyList>::base_type(prop) {
|
||||
|
||||
recursive_init<typename fusion::result_of::as_vector<sub_rules_sequence>::type,
|
||||
typename fusion::result_of::as_vector<parent_rules_sequence>::type,
|
||||
mpl::int_<0> >(sub_rules, parent_rules);
|
||||
|
||||
//we need to specialy treat empty sequences
|
||||
initalizeLastRule(parent_rules, prop);
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
cluster_prop_par<Sys>::cluster_prop_par() : prop_par<Sys, typename Sys::Cluster::cluster_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
vertex_prop_par<Sys>::vertex_prop_par() : prop_par<Sys, typename Sys::Cluster::vertex_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
edge_prop_par<Sys>::edge_prop_par() : prop_par<Sys, typename Sys::Cluster::edge_properties>() {};
|
||||
|
||||
template<typename Sys>
|
||||
kernel_prop_par<Sys>::kernel_prop_par() : prop_par<Sys, typename Sys::Kernel::PropertySequence>() {};
|
||||
|
||||
template<typename Sys>
|
||||
system_prop_par<Sys>::system_prop_par() : prop_par<Sys, typename Sys::OptionOwner::PropertySequence>() {};
|
||||
|
||||
} //DCM
|
||||
} //details
|
||||
|
||||
#endif
|
||||
185
src/Mod/Assembly/App/opendcm/moduleState/imp/traits_impl.hpp
Normal file
185
src/Mod/Assembly/App/opendcm/moduleState/imp/traits_impl.hpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
openDCM, dimensional constraint manager
|
||||
Copyright (C) 2013 Stefan Troeger <stefantroeger@gmx.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
//move the traits specializations outside of the traits definition to avoid the spirit header parsing every
|
||||
//time this module is included and just parse it in externalisation mode when the generator is build
|
||||
|
||||
#ifndef DCM_PARSER_TRAITS_IMPL_H
|
||||
#define DCM_PARSER_TRAITS_IMPL_H
|
||||
|
||||
#include "../traits.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "opendcm/core/kernel.hpp"
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/spirit/include/karma_string.hpp>
|
||||
#include <boost/spirit/include/karma_int.hpp>
|
||||
#include <boost/spirit/include/karma_bool.hpp>
|
||||
#include <boost/spirit/include/karma_rule.hpp>
|
||||
#include <boost/spirit/include/karma_auto.hpp>
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace boost {
|
||||
namespace spirit {
|
||||
namespace traits {
|
||||
template <>
|
||||
struct create_generator<dcm::No_Identifier> {
|
||||
|
||||
typedef BOOST_TYPEOF(karma::eps(false)) type;
|
||||
static type call() {
|
||||
return karma::eps(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace dcm {
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<type_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<type_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, int&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>clustertype</type>\n<value>") << karma::int_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<changed_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<changed_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, bool&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>clusterchanged</type>\n<value>") << karma::bool_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<precision, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<precision, System, iterator> {
|
||||
typedef karma::rule<iterator, double&()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>precision</type>\n<value>") << karma::double_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_generate<id_prop<typename System::Identifier>, System>
|
||||
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<id_prop<typename System::Identifier>, System, iterator> {
|
||||
typedef karma::rule<iterator, typename System::Identifier()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>id</type>\n<value>") << karma::auto_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<type_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<type_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, int(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>clustertype</type>") >> ("<value>") >> qi::int_ >>"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<changed_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<changed_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, bool(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>clusterchanged</type>") >> ("<value>") >> qi::bool_ >>"</value>" ;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<precision, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<precision, System, iterator> {
|
||||
typedef qi::rule<iterator, double(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>precision</type>") >> ("<value>") >> qi::double_ >>"</value>" ;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<id_prop<typename System::Identifier>, System>
|
||||
: public mpl::not_<boost::is_same<typename System::Identifier, No_Identifier> > {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<id_prop<typename System::Identifier>, System, iterator> {
|
||||
typedef qi::rule<iterator, typename System::Identifier(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::auto_ >>"</value>";
|
||||
};
|
||||
};
|
||||
/*
|
||||
template<typename System>
|
||||
struct parser_generate<details::cluster_vertex_prop, System>
|
||||
: public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_generator<details::cluster_vertex_prop, System, iterator> {
|
||||
typedef karma::rule<iterator, int()> generator;
|
||||
|
||||
static void init(generator& r) {
|
||||
r = karma::lit("<type>id</type>\n<value>") << karma::int_ <<"</value>";
|
||||
};
|
||||
};
|
||||
|
||||
template<typename System>
|
||||
struct parser_parse<details::cluster_vertex_prop, System> : public mpl::true_ {};
|
||||
|
||||
template<typename System, typename iterator>
|
||||
struct parser_parser<details::cluster_vertex_prop, System, iterator> {
|
||||
typedef qi::rule<iterator, int(), qi::space_type> parser;
|
||||
|
||||
static void init(parser& r) {
|
||||
r = qi::lit("<type>id</type>") >> ("<value>") >> qi::int_ >>"</value>";
|
||||
};
|
||||
};*/
|
||||
|
||||
} //namespace dcm
|
||||
|
||||
#endif //DCM_PARSER_TRAITS_IMPL_H
|
||||
@@ -31,10 +31,10 @@ public:
|
||||
template<typename Sink>
|
||||
bool put(Sink& dest, int c) {
|
||||
|
||||
if(c == '+') {
|
||||
if(c == '#') {
|
||||
indent++;
|
||||
return true;
|
||||
} else if(c == '-') {
|
||||
} else if(c == '$') {
|
||||
indent--;
|
||||
return true;
|
||||
} else if(c == '\n') {
|
||||
|
||||
@@ -21,14 +21,8 @@
|
||||
#define DCM_MODULE_STATE_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "indent.hpp"
|
||||
#include "generator.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "defines.hpp"
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace dcm {
|
||||
|
||||
struct ModuleState {
|
||||
@@ -46,47 +40,31 @@ struct ModuleState {
|
||||
|
||||
Sys* m_this;
|
||||
|
||||
void saveState(std::ostream& stream) {
|
||||
void saveState(std::ostream& stream);
|
||||
void loadState(std::istream& stream);
|
||||
|
||||
boost::iostreams::filtering_ostream indent_stream;
|
||||
indent_stream.push(indent_filter());
|
||||
indent_stream.push(stream);
|
||||
|
||||
std::ostream_iterator<char> out(indent_stream);
|
||||
generator<Sys> gen;
|
||||
|
||||
karma::generate(out, gen, *m_this->m_cluster);
|
||||
};
|
||||
|
||||
void loadState(std::istream& stream) {
|
||||
|
||||
//disable skipping of whitespace
|
||||
stream.unsetf(std::ios::skipws);
|
||||
|
||||
// wrap istream into iterator
|
||||
boost::spirit::istream_iterator begin(stream);
|
||||
boost::spirit::istream_iterator end;
|
||||
|
||||
// use iterator to parse file data
|
||||
parser<Sys> par;
|
||||
m_this->clear();
|
||||
typename Sys::Cluster* cl_ptr = m_this->m_cluster.get();
|
||||
qi::phrase_parse(begin, end, par(m_this), qi::space, cl_ptr);
|
||||
};
|
||||
void system_sub(boost:shared_ptr<Sys> subsys) {};
|
||||
};
|
||||
|
||||
|
||||
//add only a property to the cluster as we need it to store the clusers global vertex
|
||||
typedef mpl::vector1<details::cluster_vertex_prop> properties;
|
||||
typedef mpl::vector0<> objects;
|
||||
typedef mpl::vector0<> geometries;
|
||||
typedef mpl::map0<> signals;
|
||||
|
||||
//nothing to do on startup
|
||||
//nothing to do on startup and copy
|
||||
static void system_init(Sys& sys) {};
|
||||
static void system_copy(const Sys& from, Sys& into) {};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/module_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_MODULE_STATE_H
|
||||
|
||||
|
||||
|
||||
@@ -69,8 +69,8 @@ namespace details {
|
||||
} //namespace details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "object_generator_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/object_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_OBJECT_GENERATOR_H
|
||||
@@ -57,19 +57,18 @@ struct obj_par : public qi::grammar<IIterator,
|
||||
typename details::sps<typename Sys::objects>::type(Sys*),
|
||||
qi::space_type> {
|
||||
|
||||
typedef typename Sys::objects ObjectList;
|
||||
typedef typename Sys::objects ObjectList;
|
||||
//create a vector with the appropriate rules for all needed objects.
|
||||
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type sub_rules_sequence;
|
||||
//the type of the objectlist rule
|
||||
typedef qi::rule<IIterator, qi::unused_type(typename details::sps<ObjectList>::type*, Sys*), qi::space_type> parent_rule;
|
||||
//we need to store all recursive created rules
|
||||
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
|
||||
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
|
||||
|
||||
//create a vector with the appropriate rules for all needed objects.
|
||||
typedef typename obj_parser_fold<Sys, ObjectList, mpl::vector<> >::type sub_rules_sequence;
|
||||
//the type of the objectlist rule
|
||||
typedef qi::rule<IIterator, qi::unused_type(typename details::sps<ObjectList>::type*, Sys*), qi::space_type> parent_rule;
|
||||
//we need to store all recursive created rules
|
||||
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
|
||||
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
|
||||
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
|
||||
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_rules;
|
||||
|
||||
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
|
||||
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_rules;
|
||||
|
||||
qi::rule<IIterator, typename details::sps<ObjectList>::type(Sys*), qi::space_type> obj;
|
||||
|
||||
obj_par();
|
||||
@@ -78,8 +77,8 @@ typename details::sps<typename Sys::objects>::type(Sys*),
|
||||
}//details
|
||||
}//DCM
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_parser_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/object_parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -59,17 +59,21 @@ static void print(std::string s) {
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<int, std::vector<typename Sys::Cluster*> >, qi::space_type> {
|
||||
struct parser : qi::grammar<IIterator, Sys(), qi::space_type> {
|
||||
|
||||
typedef typename Sys::Cluster graph;
|
||||
|
||||
|
||||
parser();
|
||||
|
||||
qi::rule<IIterator, graph*(Sys*), qi::locals<int, std::vector<graph*> >, qi::space_type> cluster;
|
||||
qi::rule<IIterator, Sys(), qi::space_type> system;
|
||||
details::kernel_prop_par<Sys> kernel_prop;
|
||||
details::system_prop_par<Sys> system_prop;
|
||||
|
||||
qi::rule<IIterator, boost::shared_ptr<graph>(Sys*), qi::locals<int, std::vector<boost::shared_ptr<graph> > >, qi::space_type> cluster;
|
||||
details::cluster_prop_par<Sys> cluster_prop;
|
||||
|
||||
|
||||
details::obj_par<Sys> objects;
|
||||
|
||||
|
||||
details::vertex_parser<Sys> vertex;
|
||||
details::edge_parser<Sys> edge;
|
||||
|
||||
@@ -79,8 +83,8 @@ struct parser : qi::grammar<IIterator, typename Sys::Cluster*(Sys*), qi::locals<
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "parser_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_PARSER_H
|
||||
|
||||
@@ -96,11 +96,21 @@ struct edge_prop_gen : public prop_gen<Sys, typename Sys::Cluster::edge_properti
|
||||
edge_prop_gen();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct system_prop_gen : public prop_gen<Sys, typename Sys::OptionOwner::PropertySequence> {
|
||||
system_prop_gen();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct kernel_prop_gen : public prop_gen<Sys, typename Sys::Kernel::PropertySequence> {
|
||||
kernel_prop_gen();
|
||||
};
|
||||
|
||||
}//details
|
||||
}//dcm
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_generator_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/property_generator_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif //DCM_PROPERTY_GENERATOR_H
|
||||
|
||||
@@ -69,37 +69,47 @@ struct prop_par : qi::grammar<IIterator, typename details::pts<PropertyList>::ty
|
||||
typedef qi::rule<IIterator, qi::unused_type(typename details::pts<PropertyList>::type*), qi::space_type> parent_rule;
|
||||
//we need to store all recursive created rules
|
||||
typedef typename mpl::fold< sub_rules_sequence, mpl::vector0<>,
|
||||
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
|
||||
mpl::push_back<mpl::_1, parent_rule> >::type parent_rules_sequence;
|
||||
|
||||
typename fusion::result_of::as_vector<sub_rules_sequence>::type sub_rules;
|
||||
typename fusion::result_of::as_vector<parent_rules_sequence>::type parent_rules;
|
||||
|
||||
|
||||
qi::rule<IIterator, typename details::pts<PropertyList>::type(), qi::space_type> prop;
|
||||
|
||||
prop_par();
|
||||
};
|
||||
|
||||
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
|
||||
template<typename Sys>
|
||||
struct cluster_prop_par : public prop_par<Sys, typename Sys::Cluster::cluster_properties> {
|
||||
cluster_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_prop_par : public prop_par<Sys, typename Sys::Cluster::vertex_properties> {
|
||||
vertex_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_prop_par : public prop_par<Sys, typename Sys::Cluster::edge_properties> {
|
||||
edge_prop_par();
|
||||
};
|
||||
//special prop classes for better externalisaton, therefore the outside constructor to avoid auto inline
|
||||
template<typename Sys>
|
||||
struct cluster_prop_par : public prop_par<Sys, typename Sys::Cluster::cluster_properties> {
|
||||
cluster_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct vertex_prop_par : public prop_par<Sys, typename Sys::Cluster::vertex_properties> {
|
||||
vertex_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct edge_prop_par : public prop_par<Sys, typename Sys::Cluster::edge_properties> {
|
||||
edge_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct kernel_prop_par : public prop_par<Sys, typename Sys::Kernel::PropertySequence> {
|
||||
kernel_prop_par();
|
||||
};
|
||||
|
||||
template<typename Sys>
|
||||
struct system_prop_par : public prop_par<Sys, typename Sys::OptionOwner::PropertySequence> {
|
||||
system_prop_par();
|
||||
};
|
||||
|
||||
} //DCM
|
||||
} //details
|
||||
|
||||
#ifndef USE_EXTERNAL
|
||||
#include "property_parser_imp.hpp"
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/property_parser_imp.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -54,4 +54,8 @@ struct parser_parser {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DCM_EXTERNAL_STATE
|
||||
#include "imp/traits_impl.hpp"
|
||||
#endif
|
||||
#endif //DCM_PARSER_TRAITS_H
|
||||
|
||||
@@ -33,5 +33,56 @@
|
||||
#include "moduleState/module.hpp"
|
||||
#include "moduleState/traits.hpp"
|
||||
|
||||
#ifdef DCM_EXTERNAL_STATE
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_001 <opendcm/moduleState/edge_vertex_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_001( System )\
|
||||
template struct dcm::details::edge_generator<System>; \
|
||||
template struct dcm::details::vertex_generator<System>; \
|
||||
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_002 <opendcm/moduleState/object_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_002( System )\
|
||||
template struct dcm::details::obj_gen<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_003 <opendcm/moduleState/property_generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_003( System )\
|
||||
template struct dcm::details::vertex_prop_gen<System>; \
|
||||
template struct dcm::details::edge_prop_gen<System>; \
|
||||
template struct dcm::details::cluster_prop_gen<System>; \
|
||||
template struct dcm::details::system_prop_gen<System>; \
|
||||
template struct dcm::details::kernel_prop_gen<System>;
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_004 <opendcm/moduleState/generator_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_004( System )\
|
||||
template struct dcm::generator<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_005 <opendcm/moduleState/property_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_005( System )\
|
||||
template struct dcm::details::vertex_prop_par<System>; \
|
||||
template struct dcm::details::edge_prop_par<System>; \
|
||||
template struct dcm::details::cluster_prop_par<System>; \
|
||||
template struct dcm::details::system_prop_par<System>; \
|
||||
template struct dcm::details::kernel_prop_par<System>;
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_006 <opendcm/moduleState/object_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_006( System )\
|
||||
template struct dcm::details::obj_par<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_007 <opendcm/moduleState/edge_vertex_parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_007( System )\
|
||||
template struct dcm::details::edge_parser<System>; \
|
||||
template struct dcm::details::vertex_parser<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_008 <opendcm/moduleState/parser_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_008( System )\
|
||||
template struct dcm::parser<System>; \
|
||||
|
||||
#define DCM_EXTERNAL_STATE_INCLUDE_009 <opendcm/moduleState/imp/module_imp.hpp>
|
||||
#define DCM_EXTERNAL_STATE_009( System )\
|
||||
template struct dcm::ModuleState::type<System>; \
|
||||
|
||||
#endif //external
|
||||
|
||||
#endif //DCM_MODULEPARSER_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user