From: azv Date: Tue, 26 Jan 2016 06:48:13 +0000 (+0300) Subject: Implement sending list of conflicting constraints by the Solver (issues #796, #945) X-Git-Tag: V_2.2.0~176 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=9ddc291385b55eb7efd9a560a1a5c468a98dc324;p=modules%2Fshaper.git Implement sending list of conflicting constraints by the Solver (issues #796, #945) --- diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp index 278867e0a..7aac578b8 100644 --- a/src/ModelAPI/ModelAPI_Events.cpp +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -226,3 +226,25 @@ void ModelAPI_ReplaceParameterMessage::setObject(ObjectPtr theObject) { myObject = theObject; } + + +// ===== ModelAPI_SolverFailedMessage ===== +ModelAPI_SolverFailedMessage::ModelAPI_SolverFailedMessage(const Events_ID theID, const void* theSender) + : Events_Message(theID, theSender) +{ +} + +ModelAPI_SolverFailedMessage::~ModelAPI_SolverFailedMessage() +{ +} + +void ModelAPI_SolverFailedMessage::setObjects(const std::set& theObjects) +{ + myObjects = theObjects; +} + +const std::set& ModelAPI_SolverFailedMessage::objects() const +{ + return myObjects; +} + diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index f4fee024a..39518f563 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -50,7 +50,9 @@ static const char * EVENT_FEATURE_STATE_RESPONSE = "FeatureStateResponse"; static const char * EVENT_UPDATE_VIEWER_BLOCKED = "UpdateViewerBlocked"; static const char * EVENT_UPDATE_VIEWER_UNBLOCKED = "UpdateViewerUnblocked"; +/// Event ID that solver has conflicting constraints (comes with ModelAPI_SolverFailedMessage) static const char * EVENT_SOLVER_FAILED = "SolverFailed"; +/// Event ID that the problem in solver disappeared static const char * EVENT_SOLVER_REPAIRED = "SolverRepaired"; /// Event ID that order of objects in group is changed, so, tree must be fully rectreated (movement of feature) @@ -305,4 +307,20 @@ class ModelAPI_ReplaceParameterMessage : public Events_Message MODELAPI_EXPORT void setObject(ObjectPtr theObject); }; + +class ModelAPI_SolverFailedMessage : public Events_Message +{ +public: + MODELAPI_EXPORT ModelAPI_SolverFailedMessage(const Events_ID theID, const void* theSender = 0); + MODELAPI_EXPORT virtual ~ModelAPI_SolverFailedMessage(); + + /// Sets list of conflicting constraints + MODELAPI_EXPORT void setObjects(const std::set& theObjects); + /// Returns list of conflicting constraints + MODELAPI_EXPORT const std::set& objects() const; + +private: + std::set myObjects; +}; + #endif diff --git a/src/SketchPlugin/Test/TestConstraintDistance.py b/src/SketchPlugin/Test/TestConstraintDistance.py index 3adefded1..18998c5fa 100644 --- a/src/SketchPlugin/Test/TestConstraintDistance.py +++ b/src/SketchPlugin/Test/TestConstraintDistance.py @@ -115,7 +115,7 @@ assert math.fabs(aDistance.value() - aDist) < 1.e-4, "Distance values are differ aSession.startOperation() aDistance.setValue(PT_PT_DIST) aSession.finishOperation() -assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) == PT_PT_DIST) +assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10) #========================================================================= # Move line, check that distance is constant #========================================================================= @@ -123,7 +123,7 @@ aSession.startOperation() aLineAStartPoint.setValue(0., 40.) aLineAEndPoint.setValue(100., 40.) aSession.finishOperation() -assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) == PT_PT_DIST) +assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10) #========================================================================= # Remove constraint, check the points are unconstrained now #========================================================================= @@ -133,7 +133,7 @@ aSession.finishOperation() aSession.startOperation() aSketchPointCoords.setValue(0., 0.) aSession.finishOperation() -assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) != PT_PT_DIST) +assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) > 1.e-10) #========================================================================= # Add distance between point and line @@ -163,7 +163,7 @@ assert math.fabs(aDistance.value() - aDist) < 1.e-4, "Distance values are differ aSession.startOperation() aDistance.setValue(PT_LINE_DIST) aSession.finishOperation() -assert (distancePointLine(aSketchPointCoords, aSketchLine) == PT_LINE_DIST) +assert (math.fabs(distancePointLine(aSketchPointCoords, aSketchLine) - PT_LINE_DIST) < 1.e-10) #========================================================================= # Set distance between line boundaries #========================================================================= @@ -171,7 +171,7 @@ aSession.startOperation() refattrA.setAttr(aLineAStartPoint) refattrB.setAttr(aLineAEndPoint) aSession.finishOperation() -assert (distancePointPoint(aLineAStartPoint, aLineAEndPoint) != PT_LINE_DIST) +assert (math.fabs(distancePointPoint(aLineAStartPoint, aLineAEndPoint) - PT_LINE_DIST) < 1.e-10) #========================================================================= # End of test #========================================================================= diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp index 75242febf..a2be38efe 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp @@ -32,6 +32,14 @@ PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper( myValue = 0.0; } +void PlaneGCSSolver_ConstraintWrapper::setId(const ConstraintID& theID) +{ + myID = theID; + std::list::iterator anIt = myGCSConstraints.begin(); + for (; anIt != myGCSConstraints.end(); ++anIt) + (*anIt)->setTag((int)theID); +} + void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ParameterWrapperPtr& theValue) { myValueParam = theValue; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h index 12466118f..db2972db1 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h @@ -32,6 +32,8 @@ public: /// \brief Return ID of current entity virtual ConstraintID id() const { return myID; } + /// \brief Change constraint ID + void setId( const ConstraintID& theID); /// \brief Change group for the constraint virtual void setGroup(const GroupID& theGroup); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index e66fd13b0..3e18488eb 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -44,13 +44,17 @@ void PlaneGCSSolver_Solver::removeConstraint(GCSConstraintPtr theConstraint) SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve() { + // clear list of conflicting constraints + if (myConfCollected) { + myConflictingIDs.clear(); + myConfCollected = false; + } + if (myConstraints.empty()) return STATUS_EMPTYSET; if (myParameters.empty()) return STATUS_INCONSISTENT; - //myEquationSystem.calculateFaileds = myFindFaileds ? 1 : 0; - Events_LongOp::start(this); GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters); Events_LongOp::end(this); @@ -69,3 +73,27 @@ void PlaneGCSSolver_Solver::undo() { myEquationSystem.undoSolution(); } + +bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const +{ + if (!myConfCollected) + const_cast(this)->collectConflicting(); + + GCS::VEC_I::const_iterator anIt = myConflictingIDs.begin(); + for (; anIt != myConflictingIDs.end(); ++anIt) + if (*anIt == (int)theConstraint) + return true; + return false; +} + +void PlaneGCSSolver_Solver::collectConflicting() +{ + myEquationSystem.getConflicting(myConflictingIDs); + + GCS::VEC_I aRedundantID; + myEquationSystem.getRedundant(aRedundantID); + myConflictingIDs.insert(myConflictingIDs.end(), aRedundantID.begin(), aRedundantID.end()); + + myConfCollected = true; +} + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h index 791cc648a..c2c463c5d 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h @@ -46,10 +46,19 @@ public: /// \brief Revert solution to initial values virtual void undo(); + /// \brief Check the constraint is conflicted with others + virtual bool isConflicting(const ConstraintID& theConstraint) const; + +private: + void collectConflicting(); + private: GCS::VEC_pD myParameters; ///< list of unknowns std::set myConstraints; ///< list of constraints already processed by the system GCS::System myEquationSystem; ///< set of equations for solving in FreeGCS + + GCS::VEC_I myConflictingIDs; ///< list of IDs of conflicting constraints + bool myConfCollected; ///< specifies the conflicting constraints are already collected }; #endif diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 5d0578c06..625d1ccf1 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -25,7 +25,8 @@ PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup) : SketchSolver_Storage(theGroup), - myEntityLastID(EID_SKETCH) + myEntityLastID(EID_SKETCH), + myConstraintLastID(CID_UNKNOWN) { } @@ -66,6 +67,10 @@ bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint) for (; anIt != anEntities.end(); ++anIt) isUpdated = update(*anIt) || isUpdated; + // Change ID of constraints + if (aConstraint->id() == CID_UNKNOWN) + aConstraint->setId(++myConstraintLastID); + return isUpdated; } @@ -184,6 +189,10 @@ bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint) setNeedToResolve(true); myRemovedConstraints.insert(myRemovedConstraints.end(), aConstraint->constraints().begin(), aConstraint->constraints().end()); + + if (isFullyRemoved && theConstraint->id() == myConstraintLastID) + --myConstraintLastID; + return isFullyRemoved; } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h index e82e1d6e4..f13d158eb 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h @@ -104,6 +104,7 @@ private: GCS::VEC_pD myParameters; ///< list of parameters GCS::VEC_pD myConst; ///< list of constants EntityID myEntityLastID; ///< identifier of last added entity + ConstraintID myConstraintLastID; ///< identifier of last added constraint std::map > myArcConstraintMap; ///< additional constraints for correct processing of the arcs diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index ef10bf57e..b7d928e80 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -133,7 +133,13 @@ void SketchSolver_Constraint::update() if (aRefAttr) { if (aRefAttr->isObject()) { FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object()); - aFeatures.insert(aFeat); + if (myBaseConstraint->getKind() != SketchPlugin_ConstraintLength::ID()) + aFeatures.insert(aFeat); + else { + // Workaround for the Length constraint: add points of line, not line itself + anAttributes.insert(aFeat->attribute(SketchPlugin_Line::START_ID())); + anAttributes.insert(aFeat->attribute(SketchPlugin_Line::END_ID())); + } } else anAttributes.insert(aRefAttr->attr()); } else @@ -179,6 +185,7 @@ void SketchSolver_Constraint::update() bool SketchSolver_Constraint::remove() { cleanErrorMsg(); + myType = CONSTRAINT_UNKNOWN; return myStorage->removeConstraint(myBaseConstraint); } diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 950004104..4b50f0253 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -69,6 +69,15 @@ static void sendMessage(const char* theMessageName) Events_Loop::loop()->send(aMessage); } +static void sendMessage(const char* theMessageName, const std::set& theConflicting) +{ + std::shared_ptr aMessage = + std::shared_ptr( + new ModelAPI_SolverFailedMessage(Events_Loop::eventByName(theMessageName))); + aMessage->setObjects(theConflicting); + Events_Loop::loop()->send(aMessage); +} + // ======================================================== @@ -340,8 +349,11 @@ bool SketchSolver_Group::resolveConstraints() // Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS()); if (myPrevResult != aResult || myPrevResult == STATUS_UNKNOWN) { + // Obtain list of conflicting constraints + std::set aConflicting = myStorage->getConflictingConstraints(mySketchSolver); + // the error message should be changed before sending the message - sendMessage(EVENT_SOLVER_FAILED); + sendMessage(EVENT_SOLVER_FAILED, aConflicting); myPrevResult = aResult; } } diff --git a/src/SketchSolver/SketchSolver_ISolver.h b/src/SketchSolver/SketchSolver_ISolver.h index a23807ee3..fd992971a 100644 --- a/src/SketchSolver/SketchSolver_ISolver.h +++ b/src/SketchSolver/SketchSolver_ISolver.h @@ -47,6 +47,9 @@ public: /// \brief Revert solution to initial values virtual void undo() = 0; + /// \brief Check the constraint is conflicted with others + virtual bool isConflicting(const ConstraintID& theConstraint) const = 0; + protected: GroupID myGroup; ///< ID of the group to be solved bool myFindFaileds; ///< flag to find conflicting or inappropriate constraints diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp index 546186bb5..39662623d 100644 --- a/src/SketchSolver/SketchSolver_Manager.cpp +++ b/src/SketchSolver/SketchSolver_Manager.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -150,23 +151,32 @@ void SketchSolver_Manager::processEvent( break; if (aFGrIter != aFeatureGroups.end()) { - std::vector::iterator aGroupIter = myGroups.begin(); + std::list aGroupsToResolve; + std::list::iterator aGroupIter = myGroups.begin(); std::list aSeparatedGroups; while (aGroupIter != myGroups.end()) { if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed delete *aGroupIter; - int aShift = aGroupIter - myGroups.begin(); - myGroups.erase(aGroupIter); - aGroupIter = myGroups.begin() + aShift; + std::list::iterator aRemoveIt = aGroupIter++; + myGroups.erase(aRemoveIt); continue; } if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group (*aGroupIter)->splitGroup(aSeparatedGroups); + if (!(*aGroupIter)->getWorkplane()->string( + SketchPlugin_Sketch::SOLVER_ERROR())->value().empty()) + aGroupsToResolve.push_back(*aGroupIter); } aGroupIter++; } - if (aSeparatedGroups.size() > 0) + if (aSeparatedGroups.size() > 0) { myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end()); + aGroupsToResolve.insert(aGroupsToResolve.end(), + aSeparatedGroups.begin(), aSeparatedGroups.end()); + } + + if (!aGroupsToResolve.empty()) + resolveConstraints(aGroupsToResolve); } } myIsComputed = false; @@ -181,7 +191,7 @@ bool SketchSolver_Manager::changeWorkplane(CompositeFeaturePtr theSketch) bool aResult = true; // changed when a workplane wrongly updated bool isUpdated = false; // Try to update specified workplane in all groups - std::vector::iterator aGroupIter; + std::list::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) if ((*aGroupIter)->isBaseWorkplane(theSketch)) { isUpdated = true; @@ -230,7 +240,7 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr t return true; } else if (aGroups.size() == 1) { // Only one group => add feature into it GroupID aGroupId = *(aGroups.begin()); - std::vector::iterator aGroupIter; + std::list::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) if ((*aGroupIter)->getId() == aGroupId) { // If the group is empty, the feature is not added (the constraint only) @@ -242,7 +252,7 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr t std::set::const_iterator aGroupsIter = aGroups.begin(); // Search first group - std::vector::iterator aFirstGroupIter; + std::list::iterator aFirstGroupIter; for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++) if ((*aFirstGroupIter)->getId() == *aGroupsIter) break; @@ -250,23 +260,22 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr t return false; // Append other groups to the first one - std::vector::iterator anOtherGroupIter = aFirstGroupIter + 1; + std::list::iterator anOtherGroupIter = aFirstGroupIter; + ++anOtherGroupIter; for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) { for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++) if ((*anOtherGroupIter)->getId() == *aGroupsIter) break; if (anOtherGroupIter == myGroups.end()) { // Group disappears - anOtherGroupIter = aFirstGroupIter + 1; + anOtherGroupIter = aFirstGroupIter; + ++anOtherGroupIter; continue; } (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter); - int aShiftFirst = aFirstGroupIter - myGroups.begin(); - int aShiftOther = anOtherGroupIter - myGroups.begin(); - delete *anOtherGroupIter; - myGroups.erase(anOtherGroupIter); - aFirstGroupIter = myGroups.begin() + aShiftFirst; - anOtherGroupIter = myGroups.begin() + aShiftOther; + std::list::iterator aRemoveIt = anOtherGroupIter++; + delete *aRemoveIt; + myGroups.erase(aRemoveIt); } if (aConstraint) @@ -288,7 +297,7 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr t void SketchSolver_Manager::moveEntity(std::shared_ptr theFeature) { bool isMoved = false; - std::vector::iterator aGroupIt = myGroups.begin(); + std::list::iterator aGroupIt = myGroups.begin(); for (; aGroupIt != myGroups.end(); aGroupIt++) if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) { (*aGroupIt)->moveFeature(theFeature); @@ -315,7 +324,7 @@ void SketchSolver_Manager::findGroups( std::shared_ptr aWP = findWorkplane(theFeature); SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint - std::vector::const_iterator aGroupIter; + std::list::const_iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) { if (!(*aGroupIter)->isEmpty()) @@ -339,7 +348,7 @@ std::shared_ptr SketchSolver_Manager // Already verified workplanes std::set > aVerified; - std::vector::const_iterator aGroupIter; + std::list::const_iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { std::shared_ptr aWP = (*aGroupIter)->getWorkplane(); if (aVerified.find(aWP) != aVerified.end()) @@ -365,11 +374,12 @@ std::shared_ptr SketchSolver_Manager // Function: resolveConstraints // Purpose: change entities according to available constraints // ============================================================================ -bool SketchSolver_Manager::resolveConstraints() +bool SketchSolver_Manager::resolveConstraints(const std::list& theGroups) { bool needToUpdate = false; - std::vector::iterator aGroupIter; - for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) + const std::list& aGroupsToResolve = theGroups.empty() ? myGroups : theGroups; + std::list::const_iterator aGroupIter = aGroupsToResolve.begin(); + for (; aGroupIter != aGroupsToResolve.end(); aGroupIter++) if ((*aGroupIter)->resolveConstraints()) needToUpdate = true; return needToUpdate; diff --git a/src/SketchSolver/SketchSolver_Manager.h b/src/SketchSolver/SketchSolver_Manager.h index 6883cd448..8a6851ef3 100644 --- a/src/SketchSolver/SketchSolver_Manager.h +++ b/src/SketchSolver/SketchSolver_Manager.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include /** \class SketchSolver_Manager @@ -83,9 +83,10 @@ protected: void moveEntity(std::shared_ptr theFeature); /** \brief Goes through the list of groups and solve the constraints + * \param[in] theGroups list of groups to be resolved (if empty list, all groups are resolved) * \return \c true, if groups are resolved, and features should be updated (send the Update event) */ - bool resolveConstraints(); + bool resolveConstraints(const std::list& theGroups = std::list()); private: /** \brief Searches list of groups which interact with specified feature @@ -110,7 +111,7 @@ private: private: static SketchSolver_Manager* mySelf; ///< Self pointer to implement singleton functionality - std::vector myGroups; ///< Groups of constraints + std::list myGroups; ///< Groups of constraints BuilderPtr myBuilder; ///< Builder for solver's entities /// true if computation is performed and all "updates" are generated by this algo /// and needs no recomputation diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index e75992823..837054917 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -652,6 +652,21 @@ void SketchSolver_Storage::blockEvents(bool isBlocked) myEventsBlocked = isBlocked; } +std::set SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const +{ + std::set aConflicting; + std::map >::const_iterator + aConstrIt = myConstraintMap.begin(); + for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) { + std::list::const_iterator anIt = aConstrIt->second.begin(); + for (; anIt != aConstrIt->second.end(); ++anIt) + if (theSolver->isConflicting((*anIt)->id())) { + aConflicting.insert(aConstrIt->first); + break; + } + } + return aConflicting; +} diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 2be30dec3..454044c88 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -131,6 +131,8 @@ public: /// \brief Initialize solver by constraints, entities and parameters virtual void initializeSolver(SolverPtr theSolver) = 0; + /// \brief Return list of conflicting constraints + std::set getConflictingConstraints(SolverPtr theSolver) const; /// \brief Update SketchPlugin features after resolving constraints /// \param theFixedOnly [in] if \c true the fixed points will be updated only diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp index b2a475f23..f1d72c8ba 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp @@ -90,7 +90,11 @@ SketchSolver_SolveStatus SolveSpaceSolver_Solver::solve() //if (myEquationsSystem.constraints <= 0) // return STATUS_EMPTYSET; - myEquationsSystem.calculateFaileds = myFindFaileds ? 1 : 0; + myEquationsSystem.calculateFaileds = 0; + if (myFindFaileds) { + myEquationsSystem.calculateFaileds = 1; + myEquationsSystem.faileds = myEquationsSystem.constraints; + } Events_LongOp::start(this); Slvs_Solve(&myEquationsSystem, myGroup); @@ -193,3 +197,11 @@ bool SolveSpaceSolver_Solver::hasDegeneratedArcs() const } return false; } + +bool SolveSpaceSolver_Solver::isConflicting(const ConstraintID& theConstraint) const +{ + for (int i = 0; i < myEquationsSystem.faileds; ++i) + if (myEquationsSystem.failed[i] == (Slvs_hConstraint)theConstraint) + return true; + return false; +} diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h index 3ddadc8e6..cc78b95a6 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h @@ -80,6 +80,9 @@ public: /// \brief Revert solution to initial values virtual void undo(); + /// \brief Check the constraint is conflicted with others + virtual bool isConflicting(const ConstraintID& theConstraint) const; + private: /// \brief Check whether degenerated arcs exist bool hasDegeneratedArcs() const; diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp index 1f0632b71..a060f20df 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp @@ -107,7 +107,7 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint) aConstraint->changeConstraint() = getConstraint(aConstrID); isUpdated = true; // check duplicated constraints based on different attributes - if (myDuplicatedConstraint && !hasDupConstraints && findSameConstraint(aConstraint)) + if (myDuplicatedConstraint && findSameConstraint(aConstraint) && !hasDupConstraints) myDuplicatedConstraint = false; } } @@ -492,8 +492,8 @@ bool SolveSpaceSolver_Storage::findSameConstraint(ConstraintWrapperPtr theConstr (*aCWIt)->type() == CONSTRAINT_MULTI_TRANSLATION) continue; if ((*aCWIt)->type() == theConstraint->type()) { - const Slvs_Constraint& aCComp = std::dynamic_pointer_cast< - SolveSpaceSolver_ConstraintWrapper>(*aCWIt)->constraint(); + const Slvs_Constraint& aCComp = getConstraint((Slvs_hConstraint)(*aCWIt)->id()); + if (aCBase.ptA == aCComp.ptA && aCBase.ptB == aCComp.ptB && aCBase.entityA == aCComp.entityA && aCBase.entityB == aCComp.entityB && aCBase.entityC == aCComp.entityC && aCBase.entityD == aCComp.entityD && @@ -614,10 +614,8 @@ Slvs_hParam SolveSpaceSolver_Storage::updateParameter(const Slvs_Param& theParam // parameter already used, rewrite it int aPos = Search(theParam.h, myParameters); if (aPos >= 0 && aPos < (int)myParameters.size()) { - if (IsNotEqual(myParameters[aPos], theParam)) { - myUpdatedParameters.insert(theParam.h); + if (IsNotEqual(myParameters[aPos], theParam)) setNeedToResolve(true); - } myParameters[aPos] = theParam; return theParam.h; } @@ -772,7 +770,7 @@ Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB && aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) { myDuplicatedConstraint = true; - return aCIt->h; + break; } } @@ -964,13 +962,23 @@ bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint) std::dynamic_pointer_cast(theConstraint); // verify whether the constraint has duplicated + bool hasSameID = false; SameConstraintMap::iterator anEqIt = myEqualConstraints.begin(); - for (; anEqIt != myEqualConstraints.end(); ++anEqIt) - if (anEqIt->find(aConstraint) != anEqIt->end()) { + for (; anEqIt != myEqualConstraints.end(); ++anEqIt) { + std::set::const_iterator aFound = anEqIt->find(aConstraint); + if (aFound != anEqIt->end()) { + // verify there is a constraint with same ID + std::set::const_iterator anIt = anEqIt->begin(); + ConstraintID anID = (*aFound)->id(); + for (++anIt; anIt != anEqIt->end() && !hasSameID; ++anIt) + if ((*anIt)->id() == anID && aFound != anIt) + hasSameID = true; + // erase constraint anEqIt->erase(aConstraint); break; } - if (anEqIt != myEqualConstraints.end()) + } + if (anEqIt != myEqualConstraints.end() && hasSameID) return true; bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id()); diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h index b9937ce21..4de890e9f 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h @@ -178,8 +178,6 @@ private: bool myDuplicatedConstraint; ///< shows the storage has same constraint twice - std::set myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called) - SameConstraintMap myEqualConstraints; ///< list of groups of equal constraints };