Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintManager.cpp
index a69eb95bcae4cf6f924d4cb1e7cb545ba45a1a93..bd346fb35fe35fac2343b7ff27b2600dae9c9544 100644 (file)
@@ -1,3 +1,5 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
 // File:    SketchSolver_ConstraintManager.cpp
 // Created: 08 May 2014
 // Author:  Artem ZHIDKOV
@@ -15,6 +17,7 @@
 #include <ModelAPI_Attribute.h>
 
 #include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
@@ -102,17 +105,26 @@ void SketchSolver_ConstraintManager::processEvent(
         }
       }
       // then get anything but not the sketch
+      // at first, add coincidence constraints, because they may be used by other constraints
       for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
         std::shared_ptr<SketchPlugin_Feature> aFeature = 
           std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (!aFeature)
+        if (!aFeature || aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
+          continue;
+        changeConstraintOrEntity(aFeature);
+      }
+      // after that, add all features except coincidence
+      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+        std::shared_ptr<SketchPlugin_Feature> aFeature = 
+          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (!aFeature /*|| aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()*/)
           continue;
         changeConstraintOrEntity(aFeature);
       }
     }
 
     // Solve the set of constraints
-    resolveConstraints();
+    resolveConstraints(isMovedEvt); // send update for movement in any case
   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
@@ -352,13 +364,16 @@ std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_ConstraintManager
     if (aVerified.find(aWP) != aVerified.end())
       continue;
 
-    std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
-        ModelAPI_AttributeRefList>(aWP->data()->attribute(SketchPlugin_Sketch::FEATURES_ID()));
-    std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
-    std::list<ObjectPtr>::const_iterator anIter;
-    for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
-      if (*anIter == theFeature)
-        return aWP;  // workplane is found
+    DataPtr aData = aWP->data();
+    if (aData) {
+      std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
+          ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
+      std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
+      std::list<ObjectPtr>::const_iterator anIter;
+      for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
+        if (*anIter == theFeature)
+          return aWP;  // workplane is found
+    }
     aVerified.insert(aWP);
   }
 
@@ -370,7 +385,7 @@ std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_ConstraintManager
 //  Class:    SketchSolver_Session
 //  Purpose:  change entities according to available constraints
 // ============================================================================
-void SketchSolver_ConstraintManager::resolveConstraints()
+void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdate)
 {
   myIsComputed = true;
   bool needToUpdate = false;
@@ -386,12 +401,14 @@ void SketchSolver_ConstraintManager::resolveConstraints()
     if ((*aGroupIter)->resolveConstraints())
       needToUpdate = true;
 
-  // Features may be updated => now send events, btu for all changed at once
+  // Features may be updated => now send events, but for all changed at once
   if (isUpdateFlushed) {
     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
   }
-  if (needToUpdate)
-    Events_Loop::loop()->flush(anUpdateEvent);
+  // Must be before flush because on "Updated" flush the results may be produced
+  // and the creation event is appeared with many new objects. If myIsComputed these
+  // events are missed in processEvents and some elements are not added.
   myIsComputed = false;
+  if (needToUpdate || theForceUpdate)
+    Events_Loop::loop()->flush(anUpdateEvent);
 }
-