Fix solution space behaviour and further distinguish alignment/coincident

This commit is contained in:
Stefan Tröger
2013-10-20 15:01:47 +02:00
parent 45a3f149c3
commit 64ec142d61
7 changed files with 273 additions and 25 deletions

View File

@@ -75,17 +75,25 @@ App::DocumentObjectExecReturn* ItemAssembly::execute(void) {
}
catch(dcm::solving_error& e) {
Base::Console().Error("Solver failed with error %i: %s",
Base::Console().Error("Solver failed with error %i: %s\n",
*boost::get_error_info<boost::errinfo_errno>(e),
boost::get_error_info<dcm::error_message>(e)->c_str());
}
catch(dcm::creation_error& e) {
Base::Console().Error("Creation failed with error %i: %s",
Base::Console().Error("Creation failed with error %i: %s\n",
*boost::get_error_info<boost::errinfo_errno>(e),
boost::get_error_info<dcm::error_message>(e)->c_str());
}
catch(boost::exception& e) {
Base::Console().Error("Solver exception raised: %i: %s\n",
*boost::get_error_info<boost::errinfo_errno>(e),
boost::get_error_info<dcm::error_message>(e)->c_str());
}
catch(std::exception& e) {
Base::Console().Error("Exception raised in assembly solver: %s", e.what());
Base::Console().Error("Exception raised in assembly solver: %s\n", e.what());
}
catch(...) {
Base::Console().Error("Unknown Exception raised in assembly solver during execution\n");
};
this->touch();
return App::DocumentObject::StdReturn;

View File

@@ -22,12 +22,107 @@
#include <opendcm/core/equations.hpp>
#include "distance.hpp"
#include "coincident.hpp"
namespace dcm {
struct Alignment : public constraint_sequence< fusion::vector2< Distance, Orientation > > {
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> {
using Equation::operator=;
using Equation::options;
al_orientation() : Equation() {
setDefault();
};
al_orientation& operator=(const al_orientation& d) {
return Equation::operator=(d);
};
void setDefault() {
fusion::at_key<Direction>(values) = std::make_pair(false, parallel);
};
template< typename Kernel, typename Tag1, typename Tag2 >
struct type : public PseudoScale<Kernel> {
type() {
throw constraint_error() << boost::errinfo_errno(103) << error_message("unsupported geometry in alignment orientation constraint")
<< error_type_first_geometry(typeid(Tag1).name()) << error_type_second_geometry(typeid(Tag2).name());
};
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
typedef std::vector<typename Kernel::Vector3, Eigen::aligned_allocator<typename Kernel::Vector3> > Vec;
typename al_orientation::options values;
template <typename DerivedA,typename DerivedB>
Scalar calculate(const E::MatrixBase<DerivedA>& param1, const E::MatrixBase<DerivedB>& param2) {
assert(false);
return 0;
};
template <typename DerivedA,typename DerivedB, typename DerivedC>
Scalar calculateGradientFirst(const E::MatrixBase<DerivedA>& param1,
const E::MatrixBase<DerivedB>& param2,
const E::MatrixBase<DerivedC>& dparam1) {
assert(false);
return 0;
};
template <typename DerivedA,typename DerivedB, typename DerivedC>
Scalar calculateGradientSecond(const E::MatrixBase<DerivedA>& param1,
const E::MatrixBase<DerivedB>& param2,
const E::MatrixBase<DerivedC>& dparam2) {
assert(false);
return 0;
};
template <typename DerivedA,typename DerivedB, typename DerivedC>
void calculateGradientFirstComplete(const E::MatrixBase<DerivedA>& param1,
const E::MatrixBase<DerivedB>& param2,
E::MatrixBase<DerivedC>& gradient) {
assert(false);
};
template <typename DerivedA,typename DerivedB, typename DerivedC>
void calculateGradientSecondComplete(const E::MatrixBase<DerivedA>& param1,
const E::MatrixBase<DerivedB>& param2,
E::MatrixBase<DerivedC>& gradient) {
assert(false);
};
};
};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::line3D, tag::line3D > : public ci_orientation::type< Kernel, tag::line3D, tag::line3D > {};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::line3D, tag::plane3D > : public ci_orientation::type< Kernel, tag::line3D, tag::plane3D > {};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::line3D, tag::cylinder3D > : public ci_orientation::type< Kernel, tag::line3D, tag::cylinder3D > {};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::plane3D, tag::plane3D > : public ci_orientation::type< Kernel, tag::plane3D, tag::plane3D > {};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::plane3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::plane3D, tag::cylinder3D > {
//we missuse the scale method to change whatever direction was set to the only valid one: perpendicular
void setScale(typename Kernel::number_type scale) {
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::plane3D >::values).second = perpendicular;
};
};
template< typename Kernel >
struct al_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > {};
using constraint_sequence::operator=;
}; //namespace details
//use al_orientation to ensure the correct orientations for alignment (distance is only defined for special
//orientations)
struct Alignment : public constraint_sequence< fusion::vector2< Distance, details::al_orientation > > {
using constraint_sequence::operator=;
};
static Alignment alignment;

View File

@@ -35,7 +35,7 @@ struct ci_orientation : public Equation<ci_orientation, Direction, true> {
ci_orientation() : Equation() {
setDefault();
};
ci_orientation& operator=(const ci_orientation& d) {
return Equation::operator=(d);
};
@@ -138,19 +138,48 @@ template< typename Kernel >
struct ci_orientation::type< Kernel, tag::point3D, tag::cylinder3D > : public ci_orientation::type< Kernel, tag::point3D, tag::point3D > {};
template< typename Kernel >
struct ci_orientation::type< Kernel, tag::line3D, tag::line3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::line3D > {};
struct ci_orientation::type< Kernel, tag::line3D, tag::line3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::line3D > {
//we missuse the scale method to prevent a unallowed direcion: perpendicular (ad distance is not defined for it)
void setScale(typename Kernel::number_type scale) {
if(fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::line3D >::values).second == perpendicular)
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::line3D >::values).second = parallel;
};
};
template< typename Kernel >
struct ci_orientation::type< Kernel, tag::line3D, tag::plane3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::plane3D > {};
struct ci_orientation::type< Kernel, tag::line3D, tag::plane3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::plane3D > {
//we missuse the scale method to change whatever direction was set to the only valid one: perpendicular
void setScale(typename Kernel::number_type scale) {
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::plane3D >::values).second = perpendicular;
};
};
template< typename Kernel >
struct ci_orientation::type< Kernel, tag::line3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::cylinder3D > {};
struct ci_orientation::type< Kernel, tag::line3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::line3D, tag::cylinder3D > {
//we missuse the scale method to prevent a unallowed direcion: perpendicular (ad distance is not defined for it)
void setScale(typename Kernel::number_type scale) {
if(fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::cylinder3D >::values).second == perpendicular)
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::line3D, tag::cylinder3D >::values).second = parallel;
};
};
template< typename Kernel >
struct ci_orientation::type< Kernel, tag::plane3D, tag::plane3D > : public dcm::Orientation::type< Kernel, tag::plane3D, tag::plane3D > {};
struct ci_orientation::type< Kernel, tag::plane3D, tag::plane3D > : public dcm::Orientation::type< Kernel, tag::plane3D, tag::plane3D > {
//we missuse the scale method to prevent a unallowed direcion: perpendicular (ad distance is not defined for it)
void setScale(typename Kernel::number_type scale) {
if(fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::plane3D, tag::plane3D >::values).second == perpendicular)
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::plane3D, tag::plane3D >::values).second = parallel;
};
};
template< typename Kernel >
struct ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > {};
struct ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > {
//we missuse the scale method to prevent a unallowed direcion: perpendicular (ad distance is not defined for it)
void setScale(typename Kernel::number_type scale) {
if(fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D >::values).second == perpendicular)
fusion::at_key<Direction>(dcm::Orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D >::values).second = parallel;
};
};
@@ -162,7 +191,7 @@ struct ci_distance : public Equation<ci_distance, mpl::vector2<double, SolutionS
ci_distance() : Equation() {
setDefault();
};
ci_distance& operator=(const ci_distance& d) {
return Equation::operator=(d);
};

View File

@@ -571,6 +571,9 @@ struct Distance::type< Kernel, tag::line3D, tag::cylinder3D > : public Distance:
typedef typename Kernel::number_type Scalar;
typedef typename Kernel::VectorMap Vector;
using Distance::type< Kernel, tag::line3D, tag::line3D >::sc_value;
Scalar result;
SolutionSpace sspace;
#ifdef USE_LOGGING
type() : Distance::type< Kernel, tag::line3D, tag::line3D >() {
@@ -578,11 +581,22 @@ struct Distance::type< Kernel, tag::line3D, tag::cylinder3D > : public Distance:
};
#endif
void setScale(Scalar scale) {
Distance::type< Kernel, tag::line3D, tag::line3D >::setScale(scale);
sspace = fusion::at_key<SolutionSpace>(Distance::type< Kernel, tag::line3D, tag::line3D >::values).second;
};
template <typename DerivedA,typename DerivedB>
Scalar calculate(const E::MatrixBase<DerivedA>& param1, const E::MatrixBase<DerivedB>& param2) {
//(p1-p2)°n / |n| - distance
const Scalar res = Distance::type< Kernel, tag::line3D, tag::line3D >::calculate(param1, param2);
return res - param2(6);
result = Distance::type< Kernel, tag::line3D, tag::line3D >::calculate(param1, param2) - param2(6);
//for parallel line and cylinder we may use the solution space methods
if(Kernel::isSame(Distance::type< Kernel, tag::line3D, tag::line3D >::nxn_n, 0, 1e-6) &&
(sspace==negative_directional || (sspace == bidirectional && (result+sc_value)<0.)))
return result+2*sc_value;
return result;
};
template <typename DerivedA,typename DerivedB, typename DerivedC>

View File

@@ -47,7 +47,8 @@ inline typename Kernel::number_type calc(const E::MatrixBase<T1>& d1,
return (d1+d2).norm();
case perpendicular:
return d1.dot(d2);
default:
default
:
assert(false);
}
return 0;
@@ -265,13 +266,9 @@ struct Orientation::type< Kernel, tag::line3D, tag::plane3D > : public Orientati
options values;
dcm::Direction getValue() {
dcm::Direction value = fusion::at_key<Direction>(values).second;
if(value==parallel)
return perpendicular;
if(value==perpendicular)
return parallel;
return value;
//makes it possible to allow only partial directions for derived constraints
inline dcm::Direction getValue() {
return fusion::at_key<Direction>(values).second;
};
//template definition