From e94feebdafb664910b36c3a2e526b06cd7dd3fdc Mon Sep 17 00:00:00 2001 From: azv Date: Mon, 7 Sep 2015 10:54:58 +0300 Subject: [PATCH] Sort constraints before adding it to the solver (issue #911) --- .../SketchSolver_ConstraintManager.cpp | 179 ++++++++++++------ .../SketchSolver_ConstraintRigid.cpp | 8 +- 2 files changed, 127 insertions(+), 60 deletions(-) diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index b06db8d96..6bcd23b91 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -16,10 +16,22 @@ #include #include +#include #include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include +#include +#include +#include #include #include @@ -38,6 +50,10 @@ SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0; /// Global constraint manager object SketchSolver_ConstraintManager* myManager = SketchSolver_ConstraintManager::Instance(); + +/// \brief Select and sort features applicable for SketchSolver +static std::list selectApplicableFeatures(const std::set& theObjects); + // ======================================================== // ========= SketchSolver_ConstraintManager =============== // ======================================================== @@ -76,71 +92,48 @@ void SketchSolver_ConstraintManager::processEvent( if (myIsComputed) return; if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED) - || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED) - || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { - std::shared_ptr anUpdateMsg = + || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED) + || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { + std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); - std::set aFeatures = anUpdateMsg->objects(); + std::set aFeatures = anUpdateMsg->objects(); - // Shows the message has at least one feature applicable for solver - bool hasProperFeature = false; + // Shows the message has at least one feature applicable for solver + bool hasProperFeature = false; - bool isMovedEvt = theMessage->eventID() - == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); - if (isMovedEvt) { - std::set::iterator aFeatIter; - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - std::shared_ptr aSFeature = + bool isMovedEvt = theMessage->eventID() + == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED); + if (isMovedEvt) { + std::set::iterator aFeatIter; + for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { + std::shared_ptr aSFeature = std::dynamic_pointer_cast(*aFeatIter); - if (aSFeature) { - moveEntity(aSFeature); - hasProperFeature = true; - } + if (aSFeature) { + moveEntity(aSFeature); + hasProperFeature = true; } - } else { - std::set::iterator aFeatIter; - // iterate sketchers fisrt to create all sketches before (on load may exist several sketches) - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - FeaturePtr aFeature = std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature) - continue; - const std::string& aFeatureKind = aFeature->getKind(); - if (aFeatureKind.compare(SketchPlugin_Sketch::ID()) == 0) { - std::shared_ptr aSketch = std::dynamic_pointer_cast< - ModelAPI_CompositeFeature>(aFeature); - hasProperFeature = changeWorkplane(aSketch) || hasProperFeature; - } - } - // then get anything but not the sketch - std::set aComplexConstraints; - // fillet and mirror an tangency constraints will be processed later - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - std::shared_ptr aFeature = - std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature) - continue; - if (aFeature->getKind() == SketchPlugin_ConstraintFillet::ID()) - continue; // skip Fillet features - if (SketchSolver_Group::isComplexConstraint(aFeature)) { - aComplexConstraints.insert(aFeature); - continue; - } - hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature; + } + } else { + std::list aSketchFeatures = selectApplicableFeatures(aFeatures); + std::list::iterator aFeatIter = aSketchFeatures.begin(); + for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) { + if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) { + std::shared_ptr aSketch = + std::dynamic_pointer_cast(*aFeatIter); + hasProperFeature = changeWorkplane(aSketch) || hasProperFeature; + continue; } - // processing remain constraints - aFeatIter = aComplexConstraints.begin(); - for (; aFeatIter != aComplexConstraints.end(); aFeatIter++) { - std::shared_ptr aFeature = + std::shared_ptr aFeature = std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature) - continue; - hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature; - } + if (!aFeature) + continue; + hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature; } + } - // Solve the set of constraints - if (hasProperFeature) - resolveConstraints(isMovedEvt); // send update for movement in any case + // Solve the set of constraints + if (hasProperFeature) + resolveConstraints(isMovedEvt); // send update for movement in any case } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) { std::shared_ptr aDeleteMsg = std::dynamic_pointer_cast(theMessage); @@ -390,3 +383,77 @@ void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdat if (needToUpdate || theForceUpdate) Events_Loop::loop()->flush(anUpdateEvent); } + + + + +// =========== Auxiliary functions ======================================== +static double featureToVal(FeaturePtr theFeature) +{ + if (theFeature->getKind() == SketchPlugin_Sketch::ID()) + return 0.0; // sketch + ConstraintPtr aConstraint = std::dynamic_pointer_cast(theFeature); + if (!aConstraint) + return 1.0; // features (arc, circle, line, point) + + const std::string& anID = aConstraint->getKind(); + if (anID == SketchPlugin_ConstraintCoincidence::ID()) + return 2.0; + if (anID == SketchPlugin_ConstraintDistance::ID() || + anID == SketchPlugin_ConstraintLength::ID() || + anID == SketchPlugin_ConstraintRadius::ID() || + anID == SketchPlugin_ConstraintAngle::ID()) + return 3.0; + if (anID == SketchPlugin_ConstraintHorizontal::ID() || + anID == SketchPlugin_ConstraintVertical::ID() || + anID == SketchPlugin_ConstraintParallel::ID() || + anID == SketchPlugin_ConstraintPerpendicular::ID()) + return 4.0; + if (anID == SketchPlugin_ConstraintEqual::ID()) + return 5.0; + if (anID == SketchPlugin_ConstraintTangent::ID() || + anID == SketchPlugin_ConstraintMirror::ID()) + return 6.0; + if (anID == SketchPlugin_ConstraintRigid::ID()) + return 7.0; + if (anID == SketchPlugin_MultiRotation::ID() || + anID == SketchPlugin_MultiTranslation::ID()) + return 8.0; + + // all other constraints are placed between Equal and Tangent constraints + return 5.5; +} + +static bool operator< (FeaturePtr theFeature1, FeaturePtr theFeature2) +{ + return featureToVal(theFeature1) < featureToVal(theFeature2); +} + +std::list selectApplicableFeatures(const std::set& theObjects) +{ + std::list aResult; + std::list::iterator aResIt; + + std::set::const_iterator anObjIter = theObjects.begin(); + for (; anObjIter != theObjects.end(); ++anObjIter) { + // Operate sketch itself and SketchPlugin features only. + // Also, the Fillet need to be skipped, because there are several separated constraints composing it. + FeaturePtr aFeature = std::dynamic_pointer_cast(*anObjIter); + if (!aFeature) + continue; + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + if ((aFeature->getKind() != SketchPlugin_Sketch::ID() && !aSketchFeature) || + aFeature->getKind() == SketchPlugin_ConstraintFillet::ID()) + continue; + + // Find the place where to insert a feature + for (aResIt = aResult.begin(); aResIt != aResult.end(); ++aResIt) + if (aFeature < *aResIt) + break; + aResult.insert(aResIt, aFeature); + } + + return aResult; +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp index d42668633..3f52e1992 100644 --- a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp @@ -47,10 +47,10 @@ void SketchSolver_ConstraintRigid::fixFeature() anEntID = myFeatureMap.begin()->second; else anEntID = myAttributeMap.begin()->second; - if (myStorage->isEntityFixed(anEntID, true)) { - myErrorMsg = SketchSolver_Error::ALREADY_FIXED(); - return; - } + //if (myStorage->isEntityFixed(anEntID, true)) { + // myErrorMsg = SketchSolver_Error::ALREADY_FIXED(); + // return; + //} std::string aKind; if (!myFeatureMap.empty()) -- 2.39.2