]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Implement sending list of conflicting constraints by the Solver (issues #796, #945)
authorazv <azv@opencascade.com>
Tue, 26 Jan 2016 06:48:13 +0000 (09:48 +0300)
committerazv <azv@opencascade.com>
Tue, 26 Jan 2016 12:47:13 +0000 (15:47 +0300)
20 files changed:
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/SketchPlugin/Test/TestConstraintDistance.py
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_ISolver.h
src/SketchSolver/SketchSolver_Manager.cpp
src/SketchSolver/SketchSolver_Manager.h
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.cpp
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Solver.h
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp
src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.h

index 278867e0afd7b814c2564cde0321ade8e84c8b8b..7aac578b8209ac9d9f2cc42a7d9a67bc503ad746 100644 (file)
@@ -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<ObjectPtr>& theObjects)
+{
+  myObjects = theObjects;
+}
+
+const std::set<ObjectPtr>& ModelAPI_SolverFailedMessage::objects() const
+{
+  return myObjects;
+}
+
index f4fee024af80ffcb7445c878186228bbc48287d9..39518f563a3ee234afb53083eb60ecbc89c7fca9 100644 (file)
@@ -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<ObjectPtr>& theObjects);
+  /// Returns list of conflicting constraints
+  MODELAPI_EXPORT const std::set<ObjectPtr>& objects() const;
+
+private:
+  std::set<ObjectPtr> myObjects;
+};
+
 #endif
index 3adefded128f5ded102ea8d0410c4c8c6bc5fb6d..18998c5fa898b4ee0d23788d59a4b30fb68d7b4a 100644 (file)
@@ -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
 #=========================================================================
index 75242febf8b26d1542d1e61f0b3bb6102ddcf7e2..a2be38efe0ea444771532bb37d0e1069005be4e9 100644 (file)
@@ -32,6 +32,14 @@ PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
   myValue = 0.0;
 }
 
+void PlaneGCSSolver_ConstraintWrapper::setId(const ConstraintID& theID)
+{
+  myID = theID;
+  std::list<GCSConstraintPtr>::iterator anIt = myGCSConstraints.begin();
+  for (; anIt != myGCSConstraints.end(); ++anIt)
+    (*anIt)->setTag((int)theID);
+}
+
 void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ParameterWrapperPtr& theValue)
 {
   myValueParam = theValue;
index 12466118f303a27167f4c870fe8fc64dd0ef97e6..db2972db1b4e3da837947fd2da7564470bed7e00 100644 (file)
@@ -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);
index e66fd13b0aecc9776a3d49f29416622b3d1948cb..3e18488eb8b54b8a5cfef96c77825b8ac5b64ef9 100644 (file)
@@ -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<PlaneGCSSolver_Solver*>(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;
+}
+
index 791cc648a2ac38d4eb86b2a409b254a7db3ce3e1..c2c463c5d41a9fd4954fd749832a975ceffc0241 100644 (file)
@@ -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<GCS::Constraint*> 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
index 5d0578c06af45302b5c3b5e61449a93e7ec74761..625d1ccf1b04ed795627ccf9ead18c8e962f7a2b 100644 (file)
@@ -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;
 }
 
index e82e1d6e431f7700d1734b0b88bed94ace1c7182..f13d158ebfbb35c7248d59c68fcb77089e3f5f8a 100644 (file)
@@ -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<EntityWrapperPtr, std::vector<GCSConstraintPtr> >
                                   myArcConstraintMap;    ///< additional constraints for correct processing of the arcs
index ef10bf57ebb2d0486037b89c2badc09ff86521d0..b7d928e805d3f81ddcbffc638021ed7ba9e95935 100644 (file)
@@ -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);
 }
 
index 950004104df5b14ffcbb08983f976bf11dcd9f02..4b50f02532082c5586615698da11a02032d6a584 100644 (file)
@@ -69,6 +69,15 @@ static void sendMessage(const char* theMessageName)
   Events_Loop::loop()->send(aMessage);
 }
 
+static void sendMessage(const char* theMessageName, const std::set<ObjectPtr>& theConflicting)
+{
+  std::shared_ptr<ModelAPI_SolverFailedMessage> aMessage =
+      std::shared_ptr<ModelAPI_SolverFailedMessage>(
+      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<ObjectPtr> 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;
         }
       }
index a23807ee31275c6511283aa0fac945a84e1fa0c3..fd992971a6759831b69f45124f5969daaab4643f 100644 (file)
@@ -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
index 546186bb53133738fd53f02a2eb2fb3243b831e3..39662623da538a0f816f2691a3e83a96b3db62bf 100644 (file)
@@ -14,6 +14,7 @@
 #include <ModelAPI_Object.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeString.h>
 
 #include <SketchPlugin_Constraint.h>
 
@@ -150,23 +151,32 @@ void SketchSolver_Manager::processEvent(
         break;
 
     if (aFGrIter != aFeatureGroups.end()) {
-      std::vector<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
+      std::list<SketchSolver_Group*> aGroupsToResolve;
+      std::list<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
       std::list<SketchSolver_Group*> 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<SketchSolver_Group*>::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<SketchSolver_Group*>::iterator aGroupIter;
+  std::list<SketchSolver_Group*>::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<SketchPlugin_Feature> t
     return true;
   } else if (aGroups.size() == 1) {  // Only one group => add feature into it
     GroupID aGroupId = *(aGroups.begin());
-    std::vector<SketchSolver_Group*>::iterator aGroupIter;
+    std::list<SketchSolver_Group*>::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<SketchPlugin_Feature> t
     std::set<GroupID>::const_iterator aGroupsIter = aGroups.begin();
 
     // Search first group
-    std::vector<SketchSolver_Group*>::iterator aFirstGroupIter;
+    std::list<SketchSolver_Group*>::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<SketchPlugin_Feature> t
       return false;
 
     // Append other groups to the first one
-    std::vector<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter + 1;
+    std::list<SketchSolver_Group*>::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<SketchSolver_Group*>::iterator aRemoveIt = anOtherGroupIter++;
+      delete *aRemoveIt;
+      myGroups.erase(aRemoveIt);
     }
 
     if (aConstraint)
@@ -288,7 +297,7 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr<SketchPlugin_Feature> t
 void SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
   bool isMoved = false;
-  std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
+  std::list<SketchSolver_Group*>::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<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
 
   SketchSolver_Group* anEmptyGroup = 0;  // appropriate empty group for specified constraint
-  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+  std::list<SketchSolver_Group*>::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<ModelAPI_CompositeFeature> SketchSolver_Manager
   // Already verified workplanes
   std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
 
-  std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+  std::list<SketchSolver_Group*>::const_iterator aGroupIter;
   for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
     std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
     if (aVerified.find(aWP) != aVerified.end())
@@ -365,11 +374,12 @@ std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_Manager
 //  Function: resolveConstraints
 //  Purpose:  change entities according to available constraints
 // ============================================================================
-bool SketchSolver_Manager::resolveConstraints()
+bool SketchSolver_Manager::resolveConstraints(const std::list<SketchSolver_Group*>& theGroups)
 {
   bool needToUpdate = false;
-  std::vector<SketchSolver_Group*>::iterator aGroupIter;
-  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+  const std::list<SketchSolver_Group*>& aGroupsToResolve = theGroups.empty() ? myGroups : theGroups;
+  std::list<SketchSolver_Group*>::const_iterator aGroupIter = aGroupsToResolve.begin();
+  for (; aGroupIter != aGroupsToResolve.end(); aGroupIter++)
     if ((*aGroupIter)->resolveConstraints())
       needToUpdate = true;
   return needToUpdate;
index 6883cd44877d27e2eded0acde185eeb3f7ecb63d..8a6851ef376f924567c26de99154729394f6c9b1 100644 (file)
@@ -14,7 +14,7 @@
 #include <Events_Listener.h>
 #include <SketchPlugin_Constraint.h>
 
-#include <vector>
+#include <list>
 #include <set>
 
 /** \class   SketchSolver_Manager
@@ -83,9 +83,10 @@ protected:
   void moveEntity(std::shared_ptr<SketchPlugin_Feature> 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<SketchSolver_Group*>& theGroups = std::list<SketchSolver_Group*>());
 
 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<SketchSolver_Group*> myGroups;  ///< Groups of constraints
+  std::list<SketchSolver_Group*>   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
index e75992823848cbb6d47635c685004f1d7a6706a3..8370549174a16d7acc09de33e539a67599f88123 100644 (file)
@@ -652,6 +652,21 @@ void SketchSolver_Storage::blockEvents(bool isBlocked)
   myEventsBlocked = isBlocked;
 }
 
+std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
+{
+  std::set<ObjectPtr> aConflicting;
+  std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+      aConstrIt = myConstraintMap.begin();
+  for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
+    std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstrIt->second.begin();
+    for (; anIt != aConstrIt->second.end(); ++anIt)
+      if (theSolver->isConflicting((*anIt)->id())) {
+        aConflicting.insert(aConstrIt->first);
+        break;
+      }
+  }
+  return aConflicting;
+}
 
 
 
index 2be30dec3cd89f4b5999b04ccbdfd2a727e50036..454044c8826f42fea46eee82a5c57d6a89751558 100644 (file)
@@ -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<ObjectPtr> getConflictingConstraints(SolverPtr theSolver) const;
 
   /// \brief Update SketchPlugin features after resolving constraints
   /// \param theFixedOnly [in]  if \c true the fixed points will be updated only
index b2a475f23aed54fb39955b8be67b43b2bfb9f638..f1d72c8bac59a8de424a3c96f09464fa0f1f8600 100644 (file)
@@ -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;
+}
index 3ddadc8e610b5def32dde316df67ba548de1bae4..cc78b95a6eb04061c2d9916fa221e892fb430406 100644 (file)
@@ -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;
index 1f0632b7186fd06096335ea21ca53db7aec36d12..a060f20df32317383b3e201de5c0fb8c7f0d892e 100644 (file)
@@ -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<SolveSpaceSolver_ConstraintWrapper>(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<ConstraintWrapperPtr>::const_iterator aFound = anEqIt->find(aConstraint);
+    if (aFound != anEqIt->end()) {
+      // verify there is a constraint with same ID
+      std::set<ConstraintWrapperPtr>::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());
index b9937ce21219ecd02e556f566a6199603c31c72f..4de890e9f17c22463b780401fabad9db34502d1b 100644 (file)
@@ -178,8 +178,6 @@ private:
 
   bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
 
-  std::set<Slvs_hParam> myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called)
-
   SameConstraintMap myEqualConstraints; ///< list of groups of equal constraints
 };