fix unsupported geometry crashs, add visual feedback for unsupported geometry and fix crash on both parts in subassemblys

This commit is contained in:
Stefan Tröger
2013-12-22 10:40:03 +01:00
parent 61a47d7c22
commit 66f9afbef3
8 changed files with 549 additions and 456 deletions

View File

@@ -63,6 +63,11 @@ struct ConstraintInitException : std::exception {
return "Constraint cout not be initialised: unsoported geometry";
}
};
struct ConstraintPartException : std::exception {
const char* what() const throw() {
return "Constraint cout not be initialised: parts are invalid";
}
};
struct ConstraintLinkException : std::exception {
const char* what() const throw() {
return "Constraint cout not be initialised: unsoported link type";
@@ -96,7 +101,7 @@ Constraint::Constraint()
vec2.push_back("Coincident");
vec2.push_back("None");
Type.setEnumVector(vec2);
std::vector<std::string> vec3;
vec3.push_back("Bidirectional");
vec3.push_back("Positiv directional");
@@ -131,6 +136,7 @@ boost::shared_ptr<Geometry3D> Constraint::initLink(App::PropertyLinkSub& link) {
};
Assembly::ItemPart* part = static_cast<Assembly::ItemPart*>(link.getValue());
if(!part)
return boost::shared_ptr<Geometry3D>();
@@ -159,52 +165,58 @@ void Constraint::init(Assembly::ItemAssembly* ass)
if(Type.getValue() == 0) {
if(part1)
part1->m_part->fix(true);
else if(part2)
part2->m_part->fix(true);
else
if(part2)
part2->m_part->fix(true);
throw ConstraintPartException();
};
//all other constraints need poth parts
if(!part1 || !part2) {
Base::Console().Message("Geometry initialisation error: invalid parts\n");
return;
throw ConstraintPartException();
};
//and both geometries
if(!m_first_geom || !m_second_geom) {
Base::Console().Message("Geometry initialisation error: invalid geometries\n");
return;
throw ConstraintInitException();
};
//we may need the orientation
dcm::Direction dir;
switch(Orientation.getValue()) {
case 0:
dir = dcm::parallel;
break;
case 1:
dir = dcm::equal;
break;
case 2:
dir = dcm::opposite;
break;
default:
dir = dcm::perpendicular;
};
//we may need the SolutionSpace
dcm::SolutionSpace sspace;
switch(SolutionSpace.getValue()) {
case 0:
sspace = dcm::bidirectional;
break;
case 1:
sspace = dcm::positiv_directional;
break;
default:
sspace = dcm::negative_directional;
};
//distance constraint
if(Type.getValue() == 1)
m_constraint = ass->m_solver->createConstraint3D(getNameInDocument(), m_first_geom, m_second_geom, (dcm::distance = Value.getValue()) = sspace);
@@ -232,6 +244,7 @@ PyObject* Constraint::getPyObject(void)
// ref counter is set to 1
PythonObject = Py::Object(new ConstraintPy(this),true);
}
return Py::new_reference_to(PythonObject);
}

View File

@@ -70,14 +70,15 @@ App::DocumentObjectExecReturn* ItemAssembly::execute(void) {
m_downstream_placement = Base::Placement(Base::Vector3<double>(0,0,0), Base::Rotation());
Base::Placement dummy;
initSolver(boost::shared_ptr<Solver>(), dummy, false);
#ifdef ASSEMBLY_DEBUG_FACILITIES
if(ApplyAtFailure.getValue())
m_solver->setOption<dcm::solverfailure>(dcm::ApplyResults);
else
m_solver->setOption<dcm::solverfailure>(dcm::IgnoreResults);
m_solver->setOption<dcm::precision>(Precision.getValue());
if(ApplyAtFailure.getValue())
m_solver->setOption<dcm::solverfailure>(dcm::ApplyResults);
else
m_solver->setOption<dcm::solverfailure>(dcm::IgnoreResults);
m_solver->setOption<dcm::precision>(Precision.getValue());
#endif
initConstraints(boost::shared_ptr<Solver>());
@@ -198,7 +199,7 @@ ItemAssembly* ItemAssembly::getParentAssembly(ItemPart* part) {
std::pair<ItemPart*, ItemAssembly*> ItemAssembly::getContainingPart(App::DocumentObject* obj) {
std::pair<ItemPart*, ItemAssembly*> ItemAssembly::getContainingPart(App::DocumentObject* obj, bool isTop) {
typedef std::vector<App::DocumentObject*>::const_iterator iter;
@@ -212,10 +213,15 @@ std::pair<ItemPart*, ItemAssembly*> ItemAssembly::getContainingPart(App::Documen
}
else if((*it)->getTypeId() == Assembly::ItemAssembly::getClassTypeId()) {
std::pair<ItemPart*, ItemAssembly*> part = static_cast<Assembly::ItemAssembly*>(*it)->getContainingPart(obj);
std::pair<ItemPart*, ItemAssembly*> part = static_cast<Assembly::ItemAssembly*>(*it)->getContainingPart(obj, false);
if(part.first && part.second)
return part;
if(part.first && part.second) {
if(isTop)
return part;
else
return std::make_pair(part.first, this);
}
}
};
@@ -242,6 +248,7 @@ void ItemAssembly::initSolver(boost::shared_ptr<Solver> parent, Base::Placement&
typedef std::vector<App::DocumentObject*>::const_iterator iter;
const std::vector<App::DocumentObject*>& vector = Items.getValues();
for(iter it=vector.begin(); it != vector.end(); it++) {
if((*it)->getTypeId() == Assembly::ItemAssembly::getClassTypeId()) {

View File

@@ -62,7 +62,11 @@ public:
bool isParentAssembly(ItemPart* part);
ItemAssembly* getParentAssembly(ItemPart* part);
std::pair< ItemPart*, ItemAssembly* > getContainingPart(App::DocumentObject* obj);
//returns the ItemPart which holds the given document object and the ItemAssembly, which holds
//the this part and is a direct children of this ItemAssembly. The returned ItemAssembly is therefore
//the "TopLevel" Assembly holding the part of all children of this assembly. If this assembly holds
//the children directly, without any subassembly, the returned ItemAssembly is this.
std::pair< ItemPart*, ItemAssembly* > getContainingPart(App::DocumentObject* obj, bool isTop=true);
//create a new solver for this assembly and initalise all downstream itemassemblys either with a
//subsystem (if they are rigid) or with this solver plus the downstream placement

View File

@@ -188,7 +188,7 @@ int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, Functor& r
unused=0;
counter=0;
int maxIterNumber = 5000;//MaxIterations * xsize;
int maxIterNumber = 10000;//MaxIterations * xsize;
number_type diverging_lim = 1e6*err + 1e12;
do {
@@ -219,11 +219,11 @@ int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, Functor& r
//get the update step
calculateStep(g, sys.Jacobi, sys.Residual, h_dl, delta);
#ifdef USE_LOGGING
BOOST_LOG(log)<< "Step in iter "<<iter<<std::endl
<< "Step: "<<h_dl.transpose()<<std::endl
<< "Jacobi: "<<sys.Jacobi<<std::endl;
#endif
// #ifdef USE_LOGGING
// BOOST_LOG(log)<< "Step in iter "<<iter<<std::endl
// << "Step: "<<h_dl.transpose()<<std::endl
// << "Jacobi: "<<sys.Jacobi<<std::endl;
// #endif
// calculate the linear model
dL = sys.Residual.norm() - (sys.Residual + sys.Jacobi*h_dl).norm();
@@ -262,10 +262,10 @@ int Dogleg<Kernel>::solve(typename Kernel::MappedEquationSystem& sys, Functor& r
nu = 2*nu;
}
#ifdef USE_LOGGING
BOOST_LOG(log)<<"Result of step dF: "<<dF<<", dL: "<<dL<<std::endl
<< "New Residual: "<< sys.Residual.transpose()<<std::endl;
#endif
// #ifdef USE_LOGGING
// BOOST_LOG(log)<<"Result of step dF: "<<dF<<", dL: "<<dL<<std::endl
// << "New Residual: "<< sys.Residual.transpose()<<std::endl;
// #endif
if(dF > 0 && dL > 0) {

View File

@@ -355,7 +355,7 @@ void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sy
bool done = false;
if(!has_cycle) {
//if(!has_cycle) {
#ifdef USE_LOGGING
BOOST_LOG(log)<< "non-cyclic system dedected: solve rotation only";
#endif
@@ -392,7 +392,7 @@ void SystemSolver<Sys>::solveCluster(boost::shared_ptr<Cluster> cluster, Sys& sy
done = false;
}
}
};
//};
//not done already? try it the hard way!
if(!done) {

View File

@@ -168,7 +168,7 @@ void CmdAssemblyConstraint::activated(int iMsg)
//check if this is the right place for the constraint
if(part1.first && part2.first && (part1.second == part2.second) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}
@@ -238,7 +238,7 @@ void CmdAssemblyConstraintDistance::activated(int iMsg)
//check if this is the right place for the constraint
if((part1.second == part2.second) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}
@@ -370,7 +370,7 @@ void CmdAssemblyConstraintAngle::activated(int iMsg)
//check if this is the right place for the constraint
if(((part1.second == part2.second) && part1.second != Asm) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}
@@ -439,7 +439,7 @@ void CmdAssemblyConstraintOrientation::activated(int iMsg)
//check if this is the right place for the constraint
if((part1.second == part2.second) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}
@@ -507,7 +507,7 @@ void CmdAssemblyConstraintCoincidence::activated(int iMsg)
//check if this is the right place for the constraint
if((part1.second == part2.second) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}
@@ -575,7 +575,7 @@ void CmdAssemblyConstraintAlignment::activated(int iMsg)
//check if this is the right place for the constraint
if((part1.second == part2.second) && part1.second != Asm) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected parts belong both to the same subproduct, please add constraints there"));
QObject::tr("The selected parts belong both to the same subassembly, please add constraints there"));
return;
}

View File

@@ -65,16 +65,19 @@ TaskAssemblyConstraints::TaskAssemblyConstraints(ViewProviderConstraint* vp)
//set all basic values
Assembly::ItemAssembly* ass = NULL;
Assembly::Constraint* obj = dynamic_cast<Assembly::Constraint*>(vp->getObject());
if(obj->First.getValue()) {
QString str;
str = QString::fromAscii(obj->First.getValue()->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(obj->First.getSubValues().front());
ui->first_geom->setText(str);
ass = dynamic_cast<Assembly::ItemPart*>(obj->First.getValue())->getParentAssembly();
};
if(obj->Second.getValue()) {
QString str;
str = QString::fromAscii(obj->Second.getValue()->getNameInDocument()) + QString::fromAscii(".") + QString::fromStdString(obj->Second.getSubValues().front());
ui->second_geom->setText(str);
if(!ass)
ass = dynamic_cast<Assembly::ItemPart*>(obj->Second.getValue())->getParentAssembly();
};
@@ -88,6 +91,7 @@ TaskAssemblyConstraints::TaskAssemblyConstraints(ViewProviderConstraint* vp)
setSolutionSpace(dcm::SolutionSpace(obj->SolutionSpace.getValue()));
int v = obj->Type.getValue();
if(v==0)
ui->fix->setChecked(true);
@@ -169,8 +173,10 @@ dcm::Direction TaskAssemblyConstraints::getOrientation()
{
if(ui->parallel->isChecked())
return dcm::parallel;
if(ui->equal->isChecked())
return dcm::equal;
if(ui->opposite->isChecked())
return dcm::opposite;
@@ -183,12 +189,15 @@ void TaskAssemblyConstraints::setOrientation(dcm::Direction d)
case dcm::perpendicular:
ui->perpendicular->setChecked(true);
break;
case dcm::equal:
ui->equal->setChecked(true);
break;
case dcm::opposite:
ui->opposite->setChecked(true);
break;
default
:
ui->parallel->setChecked(true);
@@ -199,6 +208,7 @@ dcm::SolutionSpace TaskAssemblyConstraints::getSolutionSpace()
{
if(ui->bidirectional->isChecked())
return dcm::bidirectional;
if(ui->pos_direction->isChecked())
return dcm::positiv_directional;
@@ -211,9 +221,11 @@ void TaskAssemblyConstraints::setSolutionSpace(dcm::SolutionSpace d)
case dcm::bidirectional:
ui->bidirectional->setChecked(true);
break;
case dcm::positiv_directional:
ui->pos_direction->setChecked(true);
break;
default
:
ui->neg_direction->setChecked(true);
@@ -305,6 +317,7 @@ void TaskAssemblyConstraints::on_constraint_selection(bool clicked)
App::GetApplication().getActiveDocument()->recompute();
view->draw();
}
setPossibleOptions();
}
@@ -377,9 +390,11 @@ void TaskAssemblyConstraints::setPossibleOptions() {
//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;
@@ -387,13 +402,22 @@ void TaskAssemblyConstraints::setPossibleOptions() {
//extract the geometries to use for comparison
boost::shared_ptr<Geometry3D> g1 = ass->m_solver->getGeometry3D(obj->First.getSubValues()[0].c_str());
if(!g1)
return;
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());
if(!g2)
return;
//distance
if(obj->Type.getValue() == 1) {
@@ -404,6 +428,7 @@ void TaskAssemblyConstraints::setPossibleOptions() {
ui->neg_direction->setEnabled(true);
};
};
//align & coincident
if(obj->Type.getValue() == 4 || obj->Type.getValue() == 5) {
@@ -468,6 +493,7 @@ void TaskAssemblyConstraints::setPossibleConstraints()
ui->coincident->setEnabled(false);
Assembly::Constraint* obj = dynamic_cast<Assembly::Constraint*>(view->getObject());
if(obj->First.getValue()) {
Assembly::ItemPart* p1 = dynamic_cast<Assembly::ItemPart*>(obj->First.getValue());
@@ -479,30 +505,63 @@ void TaskAssemblyConstraints::setPossibleConstraints()
//extract the geometries to use for comparison
boost::shared_ptr<Geometry3D> g1 = ass->m_solver->getGeometry3D(obj->First.getSubValues()[0].c_str());
//let's see if we have a part, if not give feedback to the user by color
if(!g1) {
QPalette palette = ui->widget->palette();
palette.setColor(ui->first_geom->backgroundRole(), QColor(255, 0, 0, 127));
ui->first_geom->setPalette(palette);
}
else {
//set normal color as we ma need to revert the red background
ui->first_geom->setPalette(ui->widget->palette());
}
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());
//let's see if we have a part, if not give feedback to the user by color
if(!g2) {
QPalette palette = ui->widget->palette();
palette.setColor(ui->second_geom->backgroundRole(), QColor(255, 0, 0, 127));
ui->second_geom->setPalette(palette);
}
else {
//set normal color as we ma need to revert the red background
ui->second_geom->setPalette(ui->widget->palette());
}
//return only here to allow coloring both line edits red if needed
if(!g1 || !g2)
return;
//check all valid combinaions
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::point)) {
ui->distance->setEnabled(true);
ui->coincident->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::line)) {
ui->distance->setEnabled(true);
ui->coincident->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::plane)) {
ui->distance->setEnabled(true);
ui->coincident->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::point, dcm::geometry::cylinder)) {
ui->distance->setEnabled(true);
ui->coincident->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::line)) {
ui->distance->setEnabled(true);
ui->orientation->setEnabled(true);
@@ -510,12 +569,14 @@ void TaskAssemblyConstraints::setPossibleConstraints()
ui->coincident->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::plane)) {
ui->orientation->setEnabled(true);
ui->angle->setEnabled(true);
ui->coincident->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::line, dcm::geometry::cylinder)) {
ui->distance->setEnabled(true);
ui->orientation->setEnabled(true);
@@ -523,17 +584,20 @@ void TaskAssemblyConstraints::setPossibleConstraints()
ui->coincident->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::plane)) {
ui->orientation->setEnabled(true);
ui->angle->setEnabled(true);
ui->coincident->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::plane, dcm::geometry::cylinder)) {
ui->orientation->setEnabled(true);
ui->angle->setEnabled(true);
ui->align->setEnabled(true);
};
if(isCombination(g1,g2, dcm::geometry::cylinder, dcm::geometry::cylinder)) {
ui->coincident->setEnabled(true);
ui->orientation->setEnabled(true);
@@ -541,6 +605,10 @@ void TaskAssemblyConstraints::setPossibleConstraints()
};
}
else {
//return here to allow check for second geometry and color both red if needed
if(!g1)
return;
//only fix works
ui->fix->setEnabled(true);
};

File diff suppressed because one or more lines are too long