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

View File

@ -108,6 +108,7 @@ TaskAssemblyConstraints::TaskAssemblyConstraints(ViewProviderConstraint* vp)
setPossibleConstraints();
setPossibleOptions();
//setup all signals for event processing
QObject::connect(
@ -188,7 +189,8 @@ void TaskAssemblyConstraints::setOrientation(dcm::Direction d)
case dcm::opposite:
ui->opposite->setChecked(true);
break;
default:
default
:
ui->parallel->setChecked(true);
}
}
@ -212,7 +214,8 @@ void TaskAssemblyConstraints::setSolutionSpace(dcm::SolutionSpace d)
case dcm::positiv_directional:
ui->pos_direction->setChecked(true);
break;
default:
default
:
ui->neg_direction->setChecked(true);
}
}
@ -246,6 +249,7 @@ void TaskAssemblyConstraints::onSelectionChanged(const Gui::SelectionChanges& ms
App::GetApplication().getActiveDocument()->recompute();
setPossibleConstraints();
setPossibleOptions();
view->draw();
return;
}
@ -268,6 +272,7 @@ void TaskAssemblyConstraints::onSelectionChanged(const Gui::SelectionChanges& ms
App::GetApplication().getActiveDocument()->recompute();
setPossibleConstraints();
setPossibleOptions();
view->draw();
return;
}
@ -300,6 +305,7 @@ void TaskAssemblyConstraints::on_constraint_selection(bool clicked)
App::GetApplication().getActiveDocument()->recompute();
view->draw();
}
setPossibleOptions();
}
@ -341,6 +347,7 @@ void TaskAssemblyConstraints::on_clear_first()
obj->First.setValue(NULL);
ui->first_geom->clear();
setPossibleConstraints();
setPossibleOptions();
view->draw();
}
@ -351,11 +358,107 @@ void TaskAssemblyConstraints::on_clear_second()
obj->Second.setValue(NULL);
ui->second_geom->clear();
setPossibleConstraints();
setPossibleOptions();
view->draw();
}
void TaskAssemblyConstraints::setPossibleOptions() {
//disable all orientations for later easy disabling
ui->parallel->setEnabled(false);
ui->equal->setEnabled(false);
ui->opposite->setEnabled(false);
ui->perpendicular->setEnabled(false);
//disable solution spaces for later easy enabling
ui->bidirectional->setEnabled(false);
ui->pos_direction->setEnabled(false);
ui->neg_direction->setEnabled(false);
//this only works if both objects are set
Assembly::Constraint* obj = dynamic_cast<Assembly::Constraint*>(view->getObject());
if(obj->First.getValue()) {
Assembly::ItemPart* p1 = dynamic_cast<Assembly::ItemPart*>(obj->First.getValue());
if(!p1)
return;
Assembly::ItemAssembly* ass = p1->getParentAssembly();
//extract the geometries to use for comparison
boost::shared_ptr<Geometry3D> g1 = ass->m_solver->getGeometry3D(obj->First.getSubValues()[0].c_str());
if(obj->Second.getValue()) {
Assembly::ItemPart* p2 = dynamic_cast<Assembly::ItemPart*>(obj->Second.getValue());
if(!p2)
return;
boost::shared_ptr<Geometry3D> g2 = ass->m_solver->getGeometry3D(obj->Second.getSubValues()[0].c_str());
//distance
if(obj->Type.getValue() == 1) {
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder)) {
ui->bidirectional->setEnabled(true);
ui->pos_direction->setEnabled(true);
ui->neg_direction->setEnabled(true);
};
};
//align & coincident
if(obj->Type.getValue() == 4 || obj->Type.getValue() == 5) {
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder) ||
isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder) ||
isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) {
ui->bidirectional->setEnabled(true);
ui->pos_direction->setEnabled(true);
ui->neg_direction->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder) ||
isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder)) {
ui->parallel->setEnabled(true);
ui->equal->setEnabled(true);
ui->opposite->setEnabled(true);
//ensure that perpendicular is not checked
if(ui->perpendicular->isChecked()) {
ui->parallel->setChecked(true);
obj->Orientation.setValue((long)0);
}
};
if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane) ||
isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) {
ui->perpendicular->setEnabled(true);
//ensure that perpendicular is checked
if(!ui->perpendicular->isChecked()) {
ui->perpendicular->setChecked(true);
obj->Orientation.setValue((long)3);
}
};
};
//orientation
if(obj->Type.getValue() == 2) {
ui->parallel->setEnabled(true);
ui->equal->setEnabled(true);
ui->opposite->setEnabled(true);
ui->perpendicular->setEnabled(true);
}
}
}
};
void TaskAssemblyConstraints::setPossibleConstraints()
{
//diasble all constraints for easyer enabling
ui->fix->setEnabled(false);
ui->distance->setEnabled(false);
ui->orientation->setEnabled(false);
@ -428,11 +531,12 @@ void TaskAssemblyConstraints::setPossibleConstraints()
if(isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) {
ui->orientation->setEnabled(true);
ui->angle->setEnabled(true);
ui->coincident->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::cylinder, dcm::geometry::cylinder)) {
ui->coincident->setEnabled(true);
ui->orientation->setEnabled(true);
ui->angle->setEnabled(true);
};
}
else {

View File

@ -67,6 +67,7 @@ private:
void setSolutionSpace(dcm::SolutionSpace d);
dcm::SolutionSpace getSolutionSpace();
void setPossibleConstraints();
void setPossibleOptions();
bool isCombination(boost::shared_ptr<Geometry3D> g1, boost::shared_ptr<Geometry3D> g2, dcm::geometry::types t1, dcm::geometry::types t2);
};