Salome HOME
A fix for the next case:
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
index 36bde98f820d2a17ad264f40cf414f4b4a3a3cda..2a4c36f8f7dada5503b0c0c55875144e3c55344c 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>
@@ -33,10 +34,16 @@ SketchSolver_Constraint::~SketchSolver_Constraint()
     myStorage->removeEntity(anIt2->second);
   myAttributeMap.clear();
 
-  std::map<FeaturePtr, Slvs_hEntity>::const_iterator anIt3 =  myFeatureMap.begin();
-  for (; anIt3 != myFeatureMap.end(); anIt3++)
-    myStorage->removeEntity(anIt3->second);
-  myFeatureMap.clear();
+  std::map<FeaturePtr, Slvs_hEntity>::iterator anIt3 =  myFeatureMap.begin();
+  while (!myFeatureMap.empty()) {
+    std::shared_ptr<SketchPlugin_Feature> aFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt3->first);
+    Slvs_hEntity anEnt = anIt3->second;
+    std::map<FeaturePtr, Slvs_hEntity>::iterator aRemIt = anIt3++;
+    myFeatureMap.erase(aRemIt);
+    if (!myGroup->isInteract(aFeature))
+      myStorage->removeEntity(anEnt);
+  }
 
   std::vector<Slvs_hConstraint>::const_iterator anIt4 = mySlvsConstraints.begin();
   for (; anIt4 != mySlvsConstraints.end(); anIt4++)
@@ -56,6 +63,12 @@ void SketchSolver_Constraint::setGroup(SketchSolver_Group* theGroup)
   process();
 }
 
+void SketchSolver_Constraint::addFeature(FeaturePtr theFeature)
+{
+  int aType;
+  changeEntity(theFeature, aType);
+}
+
 
 void SketchSolver_Constraint::process()
 {
@@ -73,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();
@@ -101,15 +116,53 @@ void SketchSolver_Constraint::process()
   adjustConstraint();
 }
 
+bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
+{
+  // Check the attrbutes of constraint are changed
+  ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+  std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
+  std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+  for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+    AttributeRefAttrPtr aRefAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+    if (aRefAttr) {
+      if (aRefAttr->isObject()) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+        if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+          return true;
+      } else if (aRefAttr->attr() &&
+                 myAttributeMap.find(aRefAttr->attr()) == myAttributeMap.end())
+        return true;
+    }
+    AttributeRefListPtr aRefList =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
+    if (aRefList) {
+      std::list<ObjectPtr> anItems = aRefList->list();
+      std::list<ObjectPtr>::iterator anIt = anItems.begin();
+      for (; anIt != anItems.end(); anIt++) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+        if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
 void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
-  if (theConstraint && theConstraint != myBaseConstraint) {
-    if (theConstraint->getKind() != myBaseConstraint->getKind())
+  bool needToRebuild = (theConstraint && theConstraint != myBaseConstraint);
+  if (!needToRebuild)
+    needToRebuild = checkAttributesChanged(theConstraint);
+  if (needToRebuild) {
+    if (theConstraint && theConstraint->getKind() != myBaseConstraint->getKind())
       return;
     remove(myBaseConstraint);
-    myBaseConstraint = theConstraint;
+    if (theConstraint)
+      myBaseConstraint = theConstraint;
     process();
+    return;
   }
 
   // Update all attributes
@@ -141,7 +194,8 @@ void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
   std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
   for (; aCIter != mySlvsConstraints.end(); aCIter++) {
     Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
-    aConstraint.valA = aValue;
+    if (aValueAttr)
+      aConstraint.valA = aValue;
     Slvs_hEntity* aCoeffs[6] = {
         &aConstraint.ptA, &aConstraint.ptB,
         &aConstraint.entityA, &aConstraint.entityB,
@@ -282,8 +336,10 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttrib
 Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
 {
   Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-  if (!theEntity || !isInitialized(theEntity))
+  if (!theEntity || !isInitialized(theEntity)) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return SLVS_E_UNKNOWN;
+  }
 
   // If the entity is already in the group, try to find it
   std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
@@ -521,7 +577,7 @@ void SketchSolver_Constraint::refresh()
         }
         if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
             fabs(aPoint2D->y() - aXY[1]) > tolerance)
-        aPoint2D->setValue(aXY[0], aXY[1]);
+          aPoint2D->setValue(aXY[0], aXY[1]);
       } else {
         // Scalar value (used for the distance entities)
         AttributeDoublePtr aScalar =
@@ -552,7 +608,15 @@ Slvs_hEntity SketchSolver_Constraint::getId(FeaturePtr theFeature) const
   std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIter = myFeatureMap.find(theFeature);
   if (aFIter == myFeatureMap.end())
     return SLVS_E_UNKNOWN;
-  return aFIter->second;
+  // check the Feature is really in the storage
+  Slvs_Entity anEntity = myStorage->getEntity(aFIter->second);
+  if (anEntity.h == SLVS_E_UNKNOWN) {
+    // rebuild feature
+    int aType;
+    anEntity.h = const_cast<SketchSolver_Constraint*>(this)->changeEntity(aFIter->first, aType);
+    const_cast<SketchSolver_Constraint*>(this)->myFeatureMap[theFeature] = anEntity.h;
+  }
+  return anEntity.h;
 }
 
 Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const
@@ -616,61 +680,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;
   }
 }