Salome HOME
Fix for crash in Object Browser when object was deleted but message not sent
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
index ce0fc9797ba9ebba75042cc6369036538ab758d9..6a7ecdb09d03347693177ef95fd4bc733c8cc691 100644 (file)
@@ -7,6 +7,7 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
+#include <GeomAPI_Dir2d.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeDouble.h>
@@ -85,6 +86,8 @@ void SketchSolver_Constraint::process()
   getAttributes(aValue, anAttributes);
   if (!myErrorMsg.empty())
     return;
+  if (aConstrType == SLVS_C_UNKNOWN)
+    aConstrType = getType();
 
   Slvs_hGroup aGroupID = myGroup->getId();
   Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
@@ -115,6 +118,17 @@ void SketchSolver_Constraint::process()
 
 bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
 {
+  std::set<Slvs_hEntity> aCurAttrs; // list of currently used attributes
+  std::vector<Slvs_hConstraint>::const_iterator aConstrIter = mySlvsConstraints.begin();
+  for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
+    Slvs_Constraint aConstr = myStorage->getConstraint(*aConstrIter);
+    if (aConstr.ptA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptA);
+    if (aConstr.ptB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptB);
+    if (aConstr.entityA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityA);
+    if (aConstr.entityB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityB);
+    if (aConstr.entityC != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityC);
+    if (aConstr.entityD != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityD);
+  }
   // Check the attrbutes of constraint are changed
   ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
   std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
@@ -125,11 +139,14 @@ bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint
     if (aRefAttr) {
       if (aRefAttr->isObject()) {
         FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-        if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+        std::map<FeaturePtr, Slvs_hEntity>::iterator aFIt = myFeatureMap.find(aFeature);
+        if (aFeature && (aFIt == myFeatureMap.end() || aCurAttrs.find(aFIt->second) == aCurAttrs.end()))
+          return true;
+      } else if (aRefAttr->attr()) {
+        std::map<AttributePtr, Slvs_hEntity>::iterator anAIt = myAttributeMap.find(aRefAttr->attr());
+        if (anAIt == myAttributeMap.end() || aCurAttrs.find(anAIt->second) == aCurAttrs.end())
           return true;
-      } else if (aRefAttr->attr() &&
-                 myAttributeMap.find(aRefAttr->attr()) == myAttributeMap.end())
-        return true;
+      }
     }
     AttributeRefListPtr aRefList =
         std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
@@ -260,6 +277,11 @@ void SketchSolver_Constraint::cleanRemovedEntities()
     std::map<AttributePtr, Slvs_hParam>::iterator aTmpIter = aValIt++;
     myValueMap.erase(aTmpIter);
   }
+  for (size_t i = 0; i < mySlvsConstraints.size(); i++)
+    if (aRemovedConstraints.find(mySlvsConstraints[i]) != aRemovedConstraints.end()) {
+      mySlvsConstraints.erase(mySlvsConstraints.begin() + i);
+      i--;
+    }
 }
 
 void SketchSolver_Constraint::getAttributes(
@@ -677,61 +699,16 @@ void SketchSolver_Constraint::calculateMiddlePoint(
       return;
     }
 
-    double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad;
-    double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad;
-    double aTanStart = abs(xStart) < tolerance ? yStart : yStart / xStart;
-    double aTanEnd   = abs(xEnd) < tolerance   ? yEnd   : yEnd / xEnd;
-    double aCotStart = abs(yStart) < tolerance ? xStart : xStart / yStart;
-    double aCotEnd   = abs(yEnd) < tolerance   ? xEnd   : xEnd / yEnd;
-    if (anArcPoint[1][0] * anArcPoint[2][0] < 0.0) {
-      if (anArcPoint[1][0] > 0.0)
-        yEnd = 2.0 - yEnd;
-      else
-        yStart = -2.0 - yStart;
-    } else {
-      if (aTanStart > aTanEnd) {
-        if (yStart > yEnd) {
-          yStart = 2.0 - yStart;
-          yEnd = -2.0 - yEnd;
-        } else {
-          yStart = -2.0 - yStart;
-          yEnd = 2.0 - yEnd;
-        }
-      }
-    }
-    if (anArcPoint[1][1] * anArcPoint[2][1] < 0.0) {
-      if (anArcPoint[1][1] > 0.0)
-        xEnd = 2.0 - xEnd;
-      else
-        xStart = -2.0 - xStart;
-    } else {
-      if (aCotStart < aCotEnd) {
-        if (xStart > xEnd) {
-          xStart = 2.0 - xStart;
-          xEnd = -2.0 - xEnd;
-        } else {
-          xStart = -2.0 - xStart;
-          xEnd = 2.0 - xEnd;
-        }
-      }
-    }
-    x = (1.0 - theCoeff) * xStart + theCoeff * xEnd;
-    y = (1.0 - theCoeff) * yStart + theCoeff * yEnd;
-    if (x > 1.0) x = 2.0 - x;
-    if (x < -1.0) x = -2.0 - x;
-    if (y > 1.0) y = 2.0 - y;
-    if (y < -1.0) y = -2.0 - y;
-
-    aNorm = sqrt(x*x + y*y);
-    if (aNorm >= tolerance) {
-      x *= aRad / aNorm;
-      y *= aRad / aNorm;
-    } else {
-      x = -0.5 * (anArcPoint[2][1] + anArcPoint[1][1]);
-      y = -0.5 * (anArcPoint[2][0] + anArcPoint[1][0]);
-    }
-    theX = anArcPoint[0][0] + x;
-    theY = anArcPoint[0][1] + y;
+    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+    double anAngle = aStartDir->angle(aEndDir);
+    if (anAngle < 0)
+      anAngle += 2.0 * PI;
+    anAngle *= theCoeff;
+    double aCos = cos(anAngle);
+    double aSin = sin(anAngle);
+    theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+    theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
   }
 }