]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #1848: Redesign Sketcher mirrorEntities
authorazv <azv@opencascade.com>
Thu, 30 Mar 2017 06:00:34 +0000 (09:00 +0300)
committerazv <azv@opencascade.com>
Thu, 30 Mar 2017 06:00:49 +0000 (09:00 +0300)
Generate error when cyclic dependency between original and mirrored entities has been detected

src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_msg_en.ts

index 335997a2ed1979910353a93d7f6390b55114b6c3..b338983cadae47a19e8c0c6a78a4e8934452f601 100644 (file)
@@ -62,13 +62,6 @@ void SketchSolver_ConstraintMirror::getAttributes(
       myFeatures.insert(aFeature);
     }
   }
-  // add mirrored features to the list
-  aList = aMirroredRefList->list();
-  for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
-    if (aFeature)
-      myFeatures.insert(aFeature);
-  }
 }
 
 void SketchSolver_ConstraintMirror::process()
@@ -118,6 +111,10 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
     FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
     mirrorEntities(aMirrorLine, aBase, aMirrored);
+
+    // update mirrored entity if it exists in the storage
+    if (myStorage->entity(aMirrored))
+      myStorage->update(aMirrored);
   }
 }
 
index 64e08004506305ee43ce874c0e7a0bf77bcd832b..a4fe899451b0339d61c03287085b45402d278cb1 100644 (file)
@@ -24,6 +24,14 @@ class SketchSolver_Error
       "To fix this, you can either undo your operation or remove a conflicting constraint.");
     return MY_ERROR_VALUE;
   }
+  /// Cyclic dependency of copied features with their originals
+  inline static const std::string& INFINITE_LOOP()
+  {
+    static const std::string MY_ERROR_VALUE(
+      "There is a circular reference between copied sketch entities and their originals. "
+      "To fix this, you can either undo your operation or remove wrong constraint.");
+    return MY_ERROR_VALUE;
+  }
   /// Constraints should use objects instead of features as attributes
   inline static const std::string& NEED_OBJECT_NOT_FEATURE()
   {
index 329f6f84cd2e899fad3a4a0592c7d11ab7d2d5a0..26b960e2ab9f86102835c19d867f5366d8ad129e 100644 (file)
 #include <Events_InfoMessage.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Events.h>
+#include <SketchPlugin_ConstraintMirror.h>
 #include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
 
 
 static void sendMessage(const char* theMessageName)
@@ -60,7 +63,8 @@ SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
   : mySketch(theWorkplane),
     myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN),
     myDOF(0),
-    myIsEventsBlocked(false)
+    myIsEventsBlocked(false),
+    myMultiConstraintUpdateStack(0)
 {
   mySketchSolver = SolverPtr(new PlaneGCSSolver_Solver);
   myStorage = StoragePtr(new PlaneGCSSolver_Storage(mySketchSolver));
@@ -100,6 +104,9 @@ bool SketchSolver_Group::changeConstraint(
   }
   else
     myConstraints[theConstraint]->update();
+
+  // constraint is created/updated => reset stack of "multi" constraints updates
+  myMultiConstraintUpdateStack = 0;
   return true;
 }
 
@@ -136,6 +143,16 @@ bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 // ============================================================================
 bool SketchSolver_Group::resolveConstraints()
 {
+  // check the "Multi" constraints do not drop sketch into infinite loop
+  if (myMultiConstraintUpdateStack > 1) {
+    myPrevResult = PlaneGCSSolver_Solver::STATUS_FAILED;
+    // generate error message due to loop update of the sketch
+    getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
+      ->setValue(SketchSolver_Error::INFINITE_LOOP());
+    sendMessage(EVENT_SOLVER_FAILED, myConflictingConstraints);
+    return false;
+  }
+
   bool aResolved = false;
   bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
   if (myStorage->isNeedToResolve() &&
@@ -144,7 +161,7 @@ bool SketchSolver_Group::resolveConstraints()
 
     PlaneGCSSolver_Solver::SolveStatus aResult = PlaneGCSSolver_Solver::STATUS_OK;
     try {
-      if (!isGroupEmpty)
+      if (!isGroupEmpty && myMultiConstraintUpdateStack <= 1)
         aResult = mySketchSolver->solve();
     } catch (...) {
       getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
@@ -163,19 +180,27 @@ bool SketchSolver_Group::resolveConstraints()
         aResult == PlaneGCSSolver_Solver::STATUS_EMPTYSET) {
       myStorage->setNeedToResolve(false);
       myStorage->refresh();
-////      updateMultiConstraints(myConstraints);
-////      // multi-constraints updated some parameters, need to store them
-////      if (myStorage->isNeedToResolve())
-////        resolveConstraints();
 
-      if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK ||
-          myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) {
-        getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
-        std::set<ObjectPtr> aConflicting = myConflictingConstraints;
-        myConflictingConstraints.clear();
-        myPrevResult = PlaneGCSSolver_Solver::STATUS_OK;
-        // the error message should be changed before sending the message
-        sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
+      // additional check that copied entities used in Mirror and other "Multi" constraints
+      // is not connected with their originals by constraints.
+      myMultiConstraintUpdateStack += 1;
+      updateMultiConstraints();
+      aResolved = true;
+      if (myStorage->isNeedToResolve())
+        aResolved = resolveConstraints();
+
+      if (aResolved) {
+        myMultiConstraintUpdateStack -= 1;
+
+        if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK ||
+            myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) {
+          getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
+          std::set<ObjectPtr> aConflicting = myConflictingConstraints;
+          myConflictingConstraints.clear();
+          myPrevResult = PlaneGCSSolver_Solver::STATUS_OK;
+          // the error message should be changed before sending the message
+          sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
+        }
       }
 
       // show degrees of freedom
@@ -209,7 +234,6 @@ bool SketchSolver_Group::resolveConstraints()
       }
     }
 
-    aResolved = true;
   } else if (isGroupEmpty && isWorkplaneValid())
     computeDoF();
   removeTemporaryConstraints();
@@ -301,6 +325,9 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
   for (; aCIter != myConstraints.end(); aCIter++)
     if (aCIter->first == theConstraint) {
       aCIter->second->remove(); // the constraint is not fully removed
+
+      // constraint is removed => reset stack of "multi" constraints updates
+      myMultiConstraintUpdateStack = 0;
       break;
     }
   if (aCIter != myConstraints.end())
@@ -337,3 +364,19 @@ void SketchSolver_Group::blockEvents(bool isBlocked)
 
   myIsEventsBlocked = isBlocked;
 }
+
+// ============================================================================
+//  Function: updateMultiConstraints
+//  Class:    SketchSolver_Group
+//  Purpose:  update multi constraints
+// ============================================================================
+void SketchSolver_Group::updateMultiConstraints()
+{
+  ConstraintConstraintMap::iterator anIt = myConstraints.begin();
+  for (; anIt != myConstraints.end(); ++anIt) {
+    if (anIt->first->getKind() == SketchPlugin_ConstraintMirror::ID() ||
+        anIt->first->getKind() == SketchPlugin_MultiRotation::ID() ||
+        anIt->first->getKind() == SketchPlugin_MultiTranslation::ID())
+      anIt->second->update();
+  }
+}
index a5fb221aea74dc0bc4f5803a496b1722ea1511e1..4db35d4fe7a483dd0c7eb5210e7c1422562a1bf6 100644 (file)
@@ -95,6 +95,9 @@ private:
   /// \brief Append given constraint to the group of temporary constraints
   void setTemporary(SolverConstraintPtr theConstraint);
 
+  /// \brief Update dependent (copied) features created by Mirror and other "Multi" constraints
+  void updateMultiConstraints();
+
   /// \brief Compute DoF of the sketch and set corresponding field
   void computeDoF();
 
@@ -113,6 +116,8 @@ private:
   int  myDOF; ///< degrees of freedom of the current sketch
 
   bool myIsEventsBlocked; ///< shows the events are blocked for this group
+
+  int myMultiConstraintUpdateStack; ///< depth of the stack updating "Multi" constraints
 };
 
 typedef std::shared_ptr<SketchSolver_Group> SketchGroupPtr;
index 424f5d40f7950c092c975a9a3b24cba639568013..f3b66c60984ff2a31af9f06a11a8ea72606e88dc 100755 (executable)
@@ -7,6 +7,10 @@
       <source>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</source>
       <translation>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</translation>
     </message>
+    <message>
+      <source>There is a circular reference between copied sketch entities and their originals. To fix this, you can either undo your operation or remove wrong constraint.</source>
+      <translation>There is a circular reference between copied sketch entities and their originals. To fix this, you can either undo your operation or remove wrong constraint.</translation>
+    </message>
     <message>
       <source>Caution: SolveSpace crash! Constraints are wrong</source>
       <translation>Caution: SolveSpace crash! Constraints are wrong</translation>