Salome HOME
SketchSolver library refactoring
authorazv <azv@opencascade.com>
Thu, 2 Apr 2015 05:44:56 +0000 (08:44 +0300)
committerazv <azv@opencascade.com>
Fri, 3 Apr 2015 06:27:13 +0000 (09:27 +0300)
1. Implemented Fillet
2. Implemented Mirror constraint
3. Update Rigid constraint
4. Code clean up

17 files changed:
src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp
src/SketchSolver/CMakeLists.txt
src/SketchSolver/SketchSolver_Builder.cpp
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_Constraint.h
src/SketchSolver/SketchSolver_ConstraintFillet.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintFillet.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintManager.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintMirror.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintRigid.cpp
src/SketchSolver/SketchSolver_ConstraintRigid.h
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_FeatureStorage.cpp
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_Storage.cpp

index 5dc94ef4a28b5e38b00440fc1dc9daebeae646de..fd765dec9fb452fbc9e13b89f07a32b7e43fe460 100644 (file)
@@ -11,6 +11,7 @@
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 
@@ -90,6 +91,8 @@ void SketchPlugin_ConstraintMirror::execute()
       aMirrorIter++;
   }
 
+  static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
   // Check consistency of initial list and mirrored list
   anInitialList =  aRefListOfShapes->list();
   anInitIter = anInitialList.begin();
@@ -131,6 +134,7 @@ void SketchPlugin_ConstraintMirror::execute()
       FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind());
       aFeatureIn->data()->copyTo(aNewFeature->data());
       aNewFeature->execute();
+      ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
 
       std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
       const std::list<ResultPtr>& aResults = aNewFeature->results();
index bc1b78af75a0a39d5ab2d766aded967c4181a16a..d8070e05f68e641d867a06d03615301154c05efe 100644 (file)
@@ -11,7 +11,9 @@ SET(PROJECT_HEADERS
     SketchSolver_ConstraintCoincidence.h
     SketchSolver_ConstraintDistance.h
     SketchSolver_ConstraintEqual.h
+    SketchSolver_ConstraintFillet.h
     SketchSolver_ConstraintLength.h
+    SketchSolver_ConstraintMirror.h
     SketchSolver_ConstraintRigid.h
     SketchSolver_ConstraintTangent.h
     SketchSolver_Builder.h
@@ -27,7 +29,9 @@ SET(PROJECT_SOURCES
     SketchSolver_ConstraintCoincidence.cpp
     SketchSolver_ConstraintDistance.cpp
     SketchSolver_ConstraintEqual.cpp
+    SketchSolver_ConstraintFillet.cpp
     SketchSolver_ConstraintLength.cpp
+    SketchSolver_ConstraintMirror.cpp
     SketchSolver_ConstraintRigid.cpp
     SketchSolver_ConstraintTangent.cpp
     SketchSolver_Builder.cpp
index 6bf3a61c080d5ec4df21cc309e17d897512e9fac..a1823bd369f97863da524216696d72d394cdf971 100644 (file)
@@ -8,7 +8,9 @@
 #include <SketchSolver_ConstraintCoincidence.h>
 #include <SketchSolver_ConstraintDistance.h>
 #include <SketchSolver_ConstraintEqual.h>
+#include <SketchSolver_ConstraintFillet.h>
 #include <SketchSolver_ConstraintLength.h>
+#include <SketchSolver_ConstraintMirror.h>
 #include <SketchSolver_ConstraintRigid.h>
 #include <SketchSolver_ConstraintTangent.h>
 
@@ -65,13 +67,13 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
-////    return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint));
+    return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintHorizontal(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
-////    return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
+    return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintParallel(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
index c382cdeb30e86ec4d051643104d75e95ec23aeec..012c45c6ec172d20e99fee1afca8d7671eac4cc3 100644 (file)
@@ -169,6 +169,7 @@ bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
     myValueMap.clear();
   } else
     cleanRemovedEntities();
+  mySlvsConstraints.clear();
   return true;
 }
 
@@ -278,7 +279,7 @@ 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())
+  if (!isInitialized(theEntity))
     return SLVS_E_UNKNOWN;
 
   // If the entity is already in the group, try to find it
@@ -373,7 +374,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int&
 Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
 {
   Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-  if (!theEntity->data()->isValid())
+  if (!theEntity->data() || !theEntity->data()->isValid())
     return SLVS_E_UNKNOWN;
   // If the entity is already in the group, try to find it
   std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
@@ -392,85 +393,82 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th
 
   Slvs_hGroup aGroupID = myGroup->getId();
   Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+  DataPtr aData = theEntity->data();
+
   // SketchPlugin features
-  std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
-      SketchPlugin_Feature>(theEntity);
-  if (aFeature) {  // Verify the feature by its kind
-    const std::string& aFeatureKind = aFeature->getKind();
-    AttributePtr anAttribute;
-    int anAttrType;
-
-    // Line
-    if (aFeatureKind == SketchPlugin_Line::ID()) {
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+  const std::string& aFeatureKind = theEntity->getKind();
+  AttributePtr anAttribute;
+  int anAttrType;
+  // Line
+  if (aFeatureKind == SketchPlugin_Line::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Line::START_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Line::END_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
 
-      if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-        aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
-      else {
-        aCurrentEntity.point[0] = aStart;
-        aCurrentEntity.point[1] = aEnd;
-      }
-      aResult = myStorage->addEntity(aCurrentEntity);
-    }
-    // Circle
-    else if (aFeatureKind == SketchPlugin_Circle::ID()) {
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
-
-      if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-        Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-        aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-                                         aCenter, aWorkplane.normal, aRadius);
-      } else {
-        aCurrentEntity.point[0] = aCenter;
-        aCurrentEntity.distance = aRadius;
-      }
-      aResult = myStorage->addEntity(aCurrentEntity);
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+      aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
+    else {
+      aCurrentEntity.point[0] = aStart;
+      aCurrentEntity.point[1] = aEnd;
     }
-    // Arc
-    else if (aFeatureKind == SketchPlugin_Arc::ID()) {
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
-
-      if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-        Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-        aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-                                              aWorkplane.normal, aCenter, aStart, aEnd);
-      } else {
-        aCurrentEntity.point[0] = aCenter;
-        aCurrentEntity.point[1] = aStart;
-        aCurrentEntity.point[2] = aEnd;
-      }
-      aResult = myStorage->addEntity(aCurrentEntity);
+    aResult = myStorage->addEntity(aCurrentEntity);
+  }
+  // Circle
+  else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+      aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+                                        aCenter, aWorkplane.normal, aRadius);
+    } else {
+      aCurrentEntity.point[0] = aCenter;
+      aCurrentEntity.distance = aRadius;
     }
-    // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-    else if (aFeatureKind == SketchPlugin_Point::ID()) {
-      anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
-      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-      // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
-      aResult = changeEntity(anAttribute, anAttrType);
-      aCurrentEntity.type = SLVS_E_POINT_IN_3D;
+    aResult = myStorage->addEntity(aCurrentEntity);
+  }
+  // Arc
+  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Arc::START_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+    anAttribute = aData->attribute(SketchPlugin_Arc::END_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+
+    if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+      Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+      aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+                                            aWorkplane.normal, aCenter, aStart, aEnd);
+    } else {
+      aCurrentEntity.point[0] = aCenter;
+      aCurrentEntity.point[1] = aStart;
+      aCurrentEntity.point[2] = aEnd;
     }
+    aResult = myStorage->addEntity(aCurrentEntity);
+  }
+  // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+  else if (aFeatureKind == SketchPlugin_Point::ID()) {
+    anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID());
+    if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+    // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
+    aResult = changeEntity(anAttribute, anAttrType);
+    aCurrentEntity.type = SLVS_E_POINT_IN_3D;
   }
 
   if (aResult != SLVS_E_UNKNOWN) {
@@ -501,19 +499,24 @@ void SketchSolver_Constraint::refresh()
         Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
         aXYZ[i] = aPar.val;
       }
-      aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
+      if (fabs(aPoint->x() - aXYZ[0]) > tolerance ||
+          fabs(aPoint->y() - aXYZ[1]) > tolerance ||
+          fabs(aPoint->z() - aXYZ[2]) > tolerance)
+        aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
     } else {
       // Point in 2D
       std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
       if (aPoint2D) {
         Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
-        double aXYZ[2];
+        double aXY[2];
         for (int i = 0; i < 2; i++) {
           Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
-          aXYZ[i] = aPar.val;
+          aXY[i] = aPar.val;
         }
-        aPoint2D->setValue(aXYZ[0], aXYZ[1]);
+        if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
+            fabs(aPoint2D->y() - aXY[1]) > tolerance)
+        aPoint2D->setValue(aXY[0], aXY[1]);
       } else {
         // Scalar value (used for the distance entities)
         AttributeDoublePtr aScalar =
@@ -521,7 +524,8 @@ void SketchSolver_Constraint::refresh()
         if (aScalar) {
           Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
           Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
-          aScalar->setValue(aPar.val);
+          if (fabs(aScalar->value() - aPar.val) > tolerance)
+            aScalar->setValue(aPar.val);
         }
       }
     }
@@ -554,3 +558,106 @@ Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const
   return anAttrIter->second;
 }
 
+bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute)
+{
+  if (theAttribute->isInitialized())
+    return true;
+  myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+  return false;
+}
+
+
+void SketchSolver_Constraint::calculateMiddlePoint(
+    const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const
+{
+  if (theEntity.type == SLVS_E_LINE_SEGMENT) {
+    double aStartEndXY[2][2];
+    Slvs_Entity aPoint;
+    for (int i = 0; i < 2; i++) {
+      aPoint = myStorage->getEntity(theEntity.point[i]);
+      for (int j = 0; j < 2; j++)
+        aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+    }
+    theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0];
+    theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1];
+  } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) {
+    double anArcPoint[3][2];
+    Slvs_Entity aPoint;
+    for (int i = 0; i < 3; i++) {
+      aPoint = myStorage->getEntity(theEntity.point[i]);
+      for (int j = 0; j < 2; j++)
+        anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+    }
+    // project last point of arc on the arc
+    double x = anArcPoint[1][0] - anArcPoint[0][0];
+    double y = anArcPoint[1][1] - anArcPoint[0][1];
+    double aRad = sqrt(x*x + y*y);
+    x = anArcPoint[2][0] - anArcPoint[0][0];
+    y = anArcPoint[2][1] - anArcPoint[0][1];
+    double aNorm = sqrt(x*x + y*y);
+    if (aNorm >= tolerance) {
+      anArcPoint[2][0] = x * aRad / aNorm;
+      anArcPoint[2][1] = y * aRad / aNorm;
+    }
+    anArcPoint[1][0] -= anArcPoint[0][0];
+    anArcPoint[1][1] -= anArcPoint[0][1];
+    if (theCoeff < tolerance) {
+      theX = anArcPoint[0][0] + anArcPoint[1][0];
+      theY = anArcPoint[0][1] + anArcPoint[1][1];
+      return;
+    } else if (1 - theCoeff < tolerance) {
+      theX = anArcPoint[0][0] + anArcPoint[2][0];
+      theY = anArcPoint[0][1] + anArcPoint[2][1];
+      return;
+    }
+
+    double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad;
+    double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad;
+    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 (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 (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;
+  }
+}
+
index 3640d881dc89eb1d012caa6b278ba919f78cbbae..6cfe355f8aa159338b4e2d1b8a3c68a6beeafe92 100644 (file)
@@ -91,6 +91,14 @@ protected:
   /// \brief Create or change SlveSpace entity according to the given feature
   Slvs_hEntity changeEntity(FeaturePtr theFeature, int& theType);
 
+  /// \brief Calculate middle point on the specified entity
+  /// \param[in]  theEntity  arc or line
+  /// \param[in]  theCoeff   is a value in [0.0, 1.0] which shows the position of the point on the entity (0.0 - start point, 1.0 - end point)
+  /// \param[out] theX       X coordinate of middle point
+  /// \param[out] theY       Y coordinate of middle point
+  void calculateMiddlePoint(const Slvs_Entity& theEntity, double theCoeff,
+                            double& theX, double& theY) const;
+
   /// \brief Removes the links to unused entities
   void cleanRemovedEntities();
 
@@ -98,6 +106,10 @@ protected:
   void cleanErrorMsg()
   { myErrorMsg.clear(); }
 
+private:
+  /// \brief Sets error, if the attribute is not initialized
+  bool isInitialized(AttributePtr theAttribute);
+
 protected:
   SketchSolver_Group* myGroup; ///< the group which contains current constraint
   ConstraintPtr myBaseConstraint; ///< SketchPlugin constraint
diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.cpp b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp
new file mode 100644 (file)
index 0000000..a8b9bcf
--- /dev/null
@@ -0,0 +1,208 @@
+#include <SketchSolver_ConstraintFillet.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+
+void SketchSolver_ConstraintFillet::getAttributes(
+    double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+{
+  theAttributes.clear();
+
+  DataPtr aData = myBaseConstraint->data();
+  AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+    aData->attribute(SketchPlugin_Constraint::VALUE()));
+  theValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+  std::list<AttributePtr> aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
+  std::list<AttributePtr>::iterator anIter = aBaseAttrs.begin();
+  for (; anIter != aBaseAttrs.end(); anIter++) {
+    AttributeRefAttrPtr aRefAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+    if (!aRefAttr || !aRefAttr->isInitialized()) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+
+    int aType = SLVS_E_UNKNOWN; // type of created entity
+    Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
+    if (anEntity == SLVS_E_UNKNOWN)
+      anEntity = changeEntity(aRefAttr, aType);
+
+    if (aType == SLVS_E_UNKNOWN)
+      continue;
+    theAttributes.push_back(anEntity);
+  }
+
+  // Fillet objects
+  AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+    aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
+  if (!aFilletRefList || !aFilletRefList->isInitialized()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  std::list<ObjectPtr> aFilletList = aFilletRefList->list();
+  if (aFilletList.size() < theAttributes.size() + 1) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  FeaturePtr aFilletFeature;
+  ResultConstructionPtr aRC;
+  int aType;
+  std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
+  for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
+    aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
+    aFilletFeature = aRC ? aRC->document()->feature(aRC) :
+        std::dynamic_pointer_cast<ModelAPI_Feature>(*aFilIter);
+    if (!aFilletFeature) {
+      myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+      return;
+    }
+    Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType);
+    theAttributes.push_back(anEntity);
+  }
+}
+
+void SketchSolver_ConstraintFillet::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  double aValue;
+  std::vector<Slvs_hEntity> anEntID;
+  getAttributes(aValue, anEntID);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Obtain the entities itself:
+  // First two are base entities
+  // Second two are trimmed them
+  // Last one is a fillet arc
+  std::vector<Slvs_Entity> anEntities;
+  std::vector<Slvs_hEntity>::iterator anIt = anEntID.begin();
+  for (; anIt != anEntID.end(); anIt++)
+    anEntities.push_back(myStorage->getEntity(*anIt));
+
+  // Check the base entities have a coincident point
+  Slvs_hEntity aPointsToFind[4];
+  for (int i = 0; i < 2; i++) {
+    int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+    aPointsToFind[2*i]  = anEntities[i].point[aShift];
+    aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
+  }
+  // Search coincident points
+  int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last)
+  bool isPointFound = false;
+  for (int i = 0; i < 2 && !isPointFound; i++)
+    for (int j = 2; j < 4 && !isPointFound; j++)
+      if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) {
+        aCoincInd[0] = i;
+        aCoincInd[1] = j - 2;
+        isPointFound = true;
+      }
+  if (!isPointFound) {
+    // There is no coincident points between tangential objects. Generate error message
+    myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
+    return;
+  }
+
+  // For correct result, move floating points of fillet on the middle points of base objects
+  Slvs_Entity aPoint;
+  Slvs_Param aParam;
+  double anArcPoints[3][2];
+  for (int i = 0; i < 2; i++) {
+    calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]);
+    aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      aParam.val = anArcPoints[i+1][j];
+      aPoint.param[j] = myStorage->updateParameter(aParam);
+    }
+  }
+  anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]);
+  anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]);
+  // Check the arc is need to be reversed
+  double aSharedPoint[2];
+  aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]);
+  for (int j = 0; j < 2; j++)
+    aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val;
+  double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) -
+                  (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]);
+  if (aCross < 0.0) { // reverse fillet arc
+    double aTmp;
+    for (int j = 0; j < 2; j++) {
+      aTmp = anArcPoints[1][j];
+      anArcPoints[1][j] = anArcPoints[2][j];
+      anArcPoints[2][j] = aTmp;
+    }
+  }
+  // update fillet arc coordinates
+  for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
+    aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      aParam.val = anArcPoints[indArcPt][j];
+      aPoint.param[j] = myStorage->updateParameter(aParam);
+    }
+  }
+
+  for (int indEnt = 0; indEnt < 2; indEnt++) {
+    int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+    // one point of fillet object should be coincident with the point on base, non-coincident with another base object
+    Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift];
+    Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift];
+    Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+        0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aCoincConstr.h = myStorage->addConstraint(aCoincConstr);
+    mySlvsConstraints.push_back(aCoincConstr.h);
+
+    // another point of fillet object should be placed on the base object
+    Slvs_Constraint aPonCurveConstr;
+    if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) {
+      // centers of arcs should be coincident
+      aBaseID = anEntities[indEnt].point[0];
+      aFilletID = anEntities[2 + indEnt].point[0];
+      aPonCurveConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+          0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    } else {
+      aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]];
+      aPonCurveConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(),
+          0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN);
+    }
+    aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr);
+    mySlvsConstraints.push_back(aPonCurveConstr.h);
+  }
+}
+
+bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.h b/src/SketchSolver/SketchSolver_ConstraintFillet.h
new file mode 100644 (file)
index 0000000..126d46d
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintFillet.h
+// Created: 1 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintFillet_H_
+#define SketchSolver_ConstraintFillet_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintFillet
+ *  \ingroup Plugins
+ *  \brief   Convert fillet constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintFillet : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintFillet(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_FILLET; }
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  ///
+  /// Parameter theAttributes contains 5 elements:
+  /// Two first entities in theAttributes list correspond to base features of fillet,
+  /// the next two entities represent trimmed base features and the last one is a fillet arc.
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+};
+
+#endif
index 2dbd6c57d6b03452c0586d47521531eca5e24022..d6094199f576d0f12f44be87a050c514606b2051 100644 (file)
@@ -17,6 +17,9 @@
 
 #include <SketchPlugin_Constraint.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintFillet.h>
+#include <SketchPlugin_ConstraintMirror.h>
+#include <SketchPlugin_ConstraintTangent.h>
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
@@ -104,19 +107,27 @@ void SketchSolver_ConstraintManager::processEvent(
         }
       }
       // then get anything but not the sketch
-      // at first, add coincidence constraints, because they may be used by other constraints
+      std::set<ObjectPtr> aComplexConstraints;
+      // fillet and mirror an tangency constraints will be processed later
       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())
+        if (!aFeature)
+          continue;
+        if (aFeature->getKind() == SketchPlugin_ConstraintFillet::ID() ||
+            aFeature->getKind() == SketchPlugin_ConstraintMirror::ID() ||
+            aFeature->getKind() == SketchPlugin_ConstraintTangent::ID()) {
+          aComplexConstraints.insert(aFeature);
           continue;
+        }
         changeConstraintOrEntity(aFeature);
       }
-      // after that, add all features except coincidence
-      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+      // processing remain constraints
+      aFeatIter = aComplexConstraints.begin();
+      for (; aFeatIter != aComplexConstraints.end(); aFeatIter++) {
         std::shared_ptr<SketchPlugin_Feature> aFeature = 
           std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (!aFeature /*|| aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()*/)
+        if (!aFeature)
           continue;
         changeConstraintOrEntity(aFeature);
       }
@@ -226,7 +237,6 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
         // If the group is empty, the feature is not added (the constraint only)
         if (!aConstraint && !(*aGroupIter)->isEmpty())
           return (*aGroupIter)->updateFeature(theFeature);
-////          return (*aGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
         return (*aGroupIter)->changeConstraint(aConstraint);
       }
   } else if (aGroups.size() > 1) {  // Several groups applicable for this feature => need to merge them
@@ -263,7 +273,6 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
     if (aConstraint)
       return (*aFirstGroupIter)->changeConstraint(aConstraint);
     return (*aFirstGroupIter)->updateFeature(theFeature);
-////    return (*aFirstGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
   }
 
   // Something goes wrong
@@ -282,48 +291,6 @@ void SketchSolver_ConstraintManager::moveEntity(
   for (; aGroupIt != myGroups.end(); aGroupIt++)
     if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
       (*aGroupIt)->moveFeature(theFeature);
-
-////  // Create list of attributes depending on type of the feature
-////  std::vector<std::string> anAttrList;
-////  const std::string& aFeatureKind = theFeature->getKind();
-////  // Point
-////  if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0)
-////    anAttrList.push_back(SketchPlugin_Point::COORD_ID());
-////  // Line
-////  else if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
-////    anAttrList.push_back(SketchPlugin_Line::START_ID());
-////    anAttrList.push_back(SketchPlugin_Line::END_ID());
-////  }
-////  // Circle
-////  else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
-////    anAttrList.push_back(SketchPlugin_Circle::CENTER_ID());
-////    anAttrList.push_back(SketchPlugin_Circle::RADIUS_ID());
-////  }
-////  // Arc
-////  else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
-////    anAttrList.push_back(SketchPlugin_Arc::CENTER_ID());
-////    anAttrList.push_back(SketchPlugin_Arc::START_ID());
-////    anAttrList.push_back(SketchPlugin_Arc::END_ID());
-////  }
-////  /// \todo Other types of features should be implemented
-////
-////  // Check changing of feature's attributes (go through the groups and search usage of the attributes)
-////  std::vector<std::string>::const_iterator anAttrIter;
-////  for (anAttrIter = anAttrList.begin(); anAttrIter != anAttrList.end(); anAttrIter++) {
-////    std::vector<SketchSolver_Group*>::iterator aGroupIter;
-////    for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
-////      if ((*aGroupIter)->isEmpty())
-////        continue;
-////      std::shared_ptr<ModelAPI_Attribute> anAttribute = std::dynamic_pointer_cast<
-////          ModelAPI_Attribute>(theFeature->data()->attribute(*anAttrIter));
-////      (*aGroupIter)->updateEntityIfPossible(anAttribute);
-////    }
-////  }
-////
-////  std::vector<SketchSolver_Group*>::iterator aGroupIter;
-////  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
-////    if (!(*aGroupIter)->isEmpty())
-////      (*aGroupIter)->updateRelatedConstraintsFeature(theFeature);
 }
 
 // ============================================================================
diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp
new file mode 100644 (file)
index 0000000..6ea42d1
--- /dev/null
@@ -0,0 +1,269 @@
+#include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+
+void SketchSolver_ConstraintMirror::getAttributes(
+    Slvs_Entity& theMirrorLine,
+    std::vector<Slvs_Entity>& theBaseEntities,
+    std::vector<Slvs_Entity>& theMirrorEntities)
+{
+  DataPtr aData = myBaseConstraint->data();
+  AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntity = myGroup->getAttributeId(aMirLineAttr);
+  if (anEntity == SLVS_E_UNKNOWN)
+    anEntity = changeEntity(aMirLineAttr, aType);
+  theMirrorLine = myStorage->getEntity(anEntity);
+
+  // Create SolveSpace entity for all features
+  AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+  myNumberOfObjects = aMirroredRefList->size();
+  if (!aBaseRefList || !aMirroredRefList) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
+    return;
+  }
+
+  std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+  std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+
+  FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
+  for (int i = 0; i < 2; i++) {
+    std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
+    std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
+    std::vector<Slvs_Entity>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
+    for ( ; anIter != aEndIter; anIter++) {
+      aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIter);
+      aFeature = aRC ? aRC->document()->feature(aRC) :
+        std::dynamic_pointer_cast<ModelAPI_Feature>(*anIter);
+      if (!aFeature)
+        continue;
+
+      anEntity = changeEntity(aFeature, aType);
+      aList->push_back(myStorage->getEntity(anEntity));
+    }
+  }
+
+  if (theBaseEntities.size() > theMirrorEntities.size())
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+}
+
+void SketchSolver_ConstraintMirror::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  Slvs_Entity aMirrorLine;
+  std::vector<Slvs_Entity> aBaseList;
+  std::vector<Slvs_Entity> aMirrorList;
+  getAttributes(aMirrorLine, aBaseList, aMirrorList);
+  if (!myErrorMsg.empty())
+    return;
+
+  if (aBaseList.size() != aMirrorList.size()) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
+    return;
+  }
+
+  Slvs_Constraint aConstraint;
+  // Get coordinates of mirror line points for speed up
+  double aStartEnd[4];
+  for (int i = 0; i < 2; i++) {
+    Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
+    for (int j = 0; j < 2; j++)
+      aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
+  }
+
+  std::vector<Slvs_Entity>::iterator aBaseIter = aBaseList.begin();
+  std::vector<Slvs_Entity>::iterator aMirrorIter = aMirrorList.begin();
+  for (; aBaseIter != aBaseList.end(); aBaseIter++, aMirrorIter++) {
+    // Make aMirrorEnt parameters to be symmetric with aBaseEnt
+    makeMirrorEntity(*aBaseIter, *aMirrorIter, aStartEnd);
+
+    if (aBaseIter->type == SLVS_E_POINT_IN_2D) {
+      aConstraint = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+          0.0, aBaseIter->h, aMirrorIter->h, aMirrorLine.h, SLVS_E_UNKNOWN);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+    } else if (aBaseIter->type == SLVS_E_LINE_SEGMENT) {
+      for (int i = 0; i < 2; i++) {
+        aConstraint = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+            aBaseIter->point[i], aMirrorIter->point[i], aMirrorLine.h, SLVS_E_UNKNOWN);
+        aConstraint.h = myStorage->addConstraint(aConstraint);
+        mySlvsConstraints.push_back(aConstraint.h);
+      }
+    } else if (aBaseIter->type == SLVS_E_CIRCLE) {
+      aConstraint = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+          aBaseIter->point[0], aMirrorIter->point[0], aMirrorLine.h, SLVS_E_UNKNOWN);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+      // Additional constraint for equal radii
+      Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
+          SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(),
+          0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseIter->h, aMirrorIter->h);
+      anEqRadConstr.h = myStorage->addConstraint(anEqRadConstr);
+      mySlvsConstraints.push_back(anEqRadConstr.h);
+    } else if (aBaseIter->type == SLVS_E_ARC_OF_CIRCLE) {
+      // Workaround to avoid problems in SolveSpace.
+      // The symmetry of two arcs will be done using symmetry of three points on these arcs:
+      // start point, end point, and any other point on the arc
+      Slvs_hEntity aBaseArcPoints[3] = {
+          aBaseIter->point[1],
+          aBaseIter->point[2],
+          SLVS_E_UNKNOWN};
+      Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
+          aBaseIter->point[2],
+          aBaseIter->point[1],
+          SLVS_E_UNKNOWN};
+
+      Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter};
+      Slvs_hEntity aBothMiddlePoints[2];
+      for (int i = 0; i < 2; i++) {
+        double x, y;
+        calculateMiddlePoint(aBothArcs[i], 0.5, x, y);
+        Slvs_Param aParamX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), x);
+        Slvs_Param aParamY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), y);
+        aParamX.h = myStorage->addParameter(aParamX);
+        aParamY.h = myStorage->addParameter(aParamY);
+        Slvs_Entity aPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
+            myGroup->getWorkplaneId(), aParamX.h, aParamY.h);
+        aBothMiddlePoints[i] = myStorage->addEntity(aPoint);
+        // additional constraint point-on-curve
+        Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_CIRCLE, myGroup->getWorkplaneId(),
+            0.0, aBothMiddlePoints[i], SLVS_E_UNKNOWN, aBothArcs[i].h, SLVS_E_UNKNOWN);
+        aPonCircConstr.h = myStorage->addConstraint(aPonCircConstr);
+        mySlvsConstraints.push_back(aPonCircConstr.h);
+      }
+
+      aBaseArcPoints[2] = aBothMiddlePoints[0];
+      aMirrorArcPoints[2] = aBothMiddlePoints[1];
+      for (int ind = 0; ind < 3; ind++) {
+        Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+            SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+            aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLine.h, SLVS_E_UNKNOWN);
+        aConstraint.h = myStorage->addConstraint(aConstraint);
+        mySlvsConstraints.push_back(aConstraint.h);
+      }
+    }
+  }
+
+  // Set the mirror line unchanged during constraint recalculation
+  for (int i = 0; i < 2; i++) {
+    aConstraint = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+        aMirrorLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+  }
+}
+
+
+void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+    if (aMirroredRefList->size() != myNumberOfObjects) {
+      remove(myBaseConstraint);
+      process();
+    }
+  }
+  SketchSolver_Constraint::update();
+}
+
+bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
+void SketchSolver_ConstraintMirror::makeMirrorEntity(
+    const Slvs_Entity& theBase,
+    const Slvs_Entity& theMirror,
+    const double theMirrorLine[]) const
+{
+  Slvs_hEntity aBasePoint[4];
+  Slvs_hEntity aMirrorPoint[4];
+  for (int i = 0; i < 4; i++) {
+    aBasePoint[i] = theBase.point[i];
+    aMirrorPoint[i] = theMirror.point[i];
+  }
+  if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
+    Slvs_hEntity aTmp = aMirrorPoint[2];
+    aMirrorPoint[2] = aMirrorPoint[1];
+    aMirrorPoint[1] = aTmp;
+  }
+
+  // Mirror line parameters
+  std::shared_ptr<GeomAPI_XY> aLinePoints[2];
+  for (int i = 0; i < 2; i++)
+    aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
+        new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
+  // direction of a mirror line
+  std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
+    new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
+  // orthogonal direction
+  aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
+
+  for (int i = 0; i < 4; i++) {
+    if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
+      continue;
+    Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
+    double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
+    double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
+    std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
+
+    std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
+        new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
+    double aDist = aVec->dot(aDir->xy());
+    aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
+
+    Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
+    Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
+    myStorage->updateParameter(aParam);
+    aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
+    myStorage->updateParameter(aParam);
+  }
+}
+
diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.h b/src/SketchSolver/SketchSolver_ConstraintMirror.h
new file mode 100644 (file)
index 0000000..092e4df
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintMirror.h
+// Created: 1 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMirror_H_
+#define SketchSolver_ConstraintMirror_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintMirror
+ *  \ingroup Plugins
+ *  \brief   Convert fillet constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintMirror : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintMirror(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint),
+      myNumberOfObjects(0)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_SYMMETRIC_LINE; }
+
+  /// \brief Update constraint
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+  { /* do nothing here */ }
+
+  /// \brief Generate list of entities of mirror constraint
+  /// \param[out] theMirrorLine     entity corresponding to mirror line
+  /// \param[out] theBaseEntities   list of entities to mirror
+  /// \param[out] theMirrorEntities list of mirrored entities
+  void getAttributes(Slvs_Entity& theMirrorLine,
+                     std::vector<Slvs_Entity>& theBaseEntities,
+                     std::vector<Slvs_Entity>& theMirrorEntities);
+
+private:
+  /// \brief Change parameters of entities to be symmetric relative a line,
+  ///        given by array of parameters (coordinates of first and last points)
+  void makeMirrorEntity(const Slvs_Entity& theBase,
+                        const Slvs_Entity& theMirror,
+                        const double theMirrorLine[]) const;
+
+private:
+  size_t myNumberOfObjects; ///< number of previously mirrored objects
+};
+
+#endif
index 12815acf314300a61a83ba916b62af4bf7efe1a6..75cf0d0d0ec87f4f63e52dee18dcb9d9a086f2cf 100644 (file)
@@ -2,8 +2,15 @@
 #include <SketchSolver_Error.h>
 #include <SketchSolver_Group.h>
 
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
 #include <SketchPlugin_ConstraintRigid.h>
 
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+
 SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature)
   : SketchSolver_Constraint(),
     myBaseFeature(theFeature)
@@ -24,10 +31,22 @@ void SketchSolver_ConstraintRigid::process()
   double aValue;
   std::vector<Slvs_hEntity> anEntities;
   getAttributes(aValue, anEntities);
+  if (!myErrorMsg.empty())
+    return;
 
   Slvs_Constraint aConstraint;
   std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
   bool isEmpty = aConstrIter == mySlvsConstraints.end();
+
+  // Check the fixed entity is an arc
+  if (isEmpty) {
+    if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) {
+      Slvs_Entity anArc = myStorage->getEntity(myFeatureMap.begin()->second);
+      fixArc(anArc);
+      return;
+    }
+  }
+
   std::vector<Slvs_hEntity>::const_iterator anEntIter = anEntities.begin();
   for (; anEntIter != anEntities.end(); anEntIter++) {
     if (*anEntIter == SLVS_E_UNKNOWN)
@@ -37,7 +56,7 @@ void SketchSolver_ConstraintRigid::process()
     if (isEmpty && !isForceUpdate) { // create new constraint
       if (aConstrID != SLVS_E_UNKNOWN)
         continue; // the coincident point is already fixed
-      aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
           aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
       aConstraint.h = myStorage->addConstraint(aConstraint);
       mySlvsConstraints.push_back(aConstraint.h);
@@ -57,6 +76,18 @@ void SketchSolver_ConstraintRigid::process()
       }
     }
   }
+
+  if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) {
+    // Fix radius of a circle
+    AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+        myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
+    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(),
+      aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+    if (!myBaseConstraint)
+      myStorage->addTemporaryConstraint(aConstraint.h);
+  }
 }
 
 
@@ -93,6 +124,39 @@ void SketchSolver_ConstraintRigid::getAttributes(
     theAttributes.push_back(anEntityID);
 }
 
+void SketchSolver_ConstraintRigid::adjustConstraint()
+{
+  if (myFeatureMap.empty() || (
+      myFeatureMap.begin()->first->getKind() != SketchPlugin_Arc::ID() && 
+      myFeatureMap.begin()->first->getKind() != SketchPlugin_Circle::ID()))
+    return;
+  FeaturePtr aFeature = myFeatureMap.begin()->first;
+
+  // Search radius constraints and update them
+  Slvs_Constraint aConstraint;
+  std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+    aConstraint = myStorage->getConstraint(*aCIter);
+    if (aConstraint.type != SLVS_C_DIAMETER)
+      continue;
+    double aRadius = 0.0;
+    if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
+      std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+      std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+      aRadius = aCenter->distance(aStart);
+    } else {
+      aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+          aFeature->attribute(SketchPlugin_Circle::RADIUS_ID()))->value();
+    }
+
+    aConstraint.valA = aRadius * 2.0;
+    *aCIter = myStorage->updateConstraint(aConstraint);
+  }
+}
+
+
 bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint)
 {
   cleanErrorMsg();
@@ -112,3 +176,58 @@ bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint)
   return true;
 }
 
+
+void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
+{
+  Slvs_Constraint aConstraint;
+  Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]);
+  int aPointsToFix = 2; // number of fixed points for the arc
+  if (aConstrID != SLVS_E_UNKNOWN)
+    aPointsToFix--;
+
+  // Radius of the arc
+  FeaturePtr aFeature = myFeatureMap.begin()->first;
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+  std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+  double aRadius = aCenter->distance(aStart);
+
+  // Update end point of the arc to be on a curve
+  std::shared_ptr<GeomAPI_Pnt2d> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
+  double aDistance = anEnd->distance(aCenter);
+  std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
+  if (aDistance < tolerance)
+    aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
+  else
+    aDir = aDir->multiplied(aRadius / aDistance);
+  double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
+  Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]);
+    aParam.val = xy[i];
+    myStorage->updateParameter(aParam);
+  }
+
+  for (int i = 1; aPointsToFix > 0; i++, aPointsToFix--) {
+    aConstrID = myStorage->isPointFixed(theArc.point[i]);
+    if (aConstrID != SLVS_E_UNKNOWN)
+      continue; // the coincident point is already fixed
+    aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+        0.0, theArc.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+    if (!myBaseConstraint)
+      myStorage->addTemporaryConstraint(aConstraint.h);
+  }
+
+  // Fix radius of the arc
+  aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(),
+    aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+  aConstraint.h = myStorage->addConstraint(aConstraint);
+  mySlvsConstraints.push_back(aConstraint.h);
+  if (!myBaseConstraint)
+    myStorage->addTemporaryConstraint(aConstraint.h);
+}
+
index 66f58163897b1c5e0d309496f59cd8165ef87602..dd148778262f96732317f7b56cdf3c718f9c555e 100644 (file)
@@ -44,6 +44,16 @@ protected:
   /// \param[out] theAttributes list of attributes to be filled
   virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
 
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  ///        E.g. the distance between line and point may be signed.
+  virtual void adjustConstraint();
+
+private:
+  /// \brief The arc is fixed differently to avoid SolveSpace problems (overconstraint)
+  ///
+  /// There will be fixed start and end points and the radius of the arc.
+  void fixArc(const Slvs_Entity& theArc);
+
 protected:
   FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
 };
index b05cb554e79993a169246adacc891df6d4ab0136..1a5718a8d8548e24b02f7a37fe265e0a33b873c4 100644 (file)
@@ -47,6 +47,12 @@ class SketchSolver_Error
     static const std::string MY_ERROR_VALUE("An arc should be an attribute of tangency constraint");
     return MY_ERROR_VALUE;
   }
+  /// Mirror constraint has wrong attributes
+  inline static const std::string& INCORRECT_MIRROR_ATTRIBUTE()
+  {
+    static const std::string MY_ERROR_VALUE("Mirror constraint has wrong attributes");
+    return MY_ERROR_VALUE;
+  }
 };
 
 #endif
index 5e112078dc5162e54fc6ee49e41d521aaf0461ff..610993a74eb5ede2eb4f1e7a634577d43da5a945 100644 (file)
@@ -313,11 +313,6 @@ bool SketchSolver_FeatureStorage::isConsistent() const
   for (; aFIter != myFeatures.end(); aFIter++)
     if (!aFIter->first->data() || !aFIter->first->data()->isValid())
       return false;
-////  // Check the attributes are valid
-////  MapAttributeFeature::const_iterator aTIter = myAttributes.begin();
-////  for (; aTIter != myAttributes.end(); aTIter++)
-////    if (!aTIter->first->isInitialized())
-////      return false;
   return true;
 }
 
index 0a250d8c2d8dfea3340b93b3b473b37432526327..1ad3646ddd0e7be3536c77feaad4929c5a977588 100644 (file)
@@ -63,13 +63,6 @@ private:
 Slvs_hGroup GroupIndexer::myGroupIndex = 0;
 
 
-/** \brief Search the entity/parameter with specified ID in the list of elements
- *  \param[in] theEntityID unique ID of the element
- *  \param[in] theEntities list of elements
- *  \return position of the found element or -1 if the element is not found
- */
-template<typename T>
-static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
 
 // ========================================================
 // =========  SketchSolver_Group  ===============
@@ -127,15 +120,22 @@ bool SketchSolver_Group::isInteract(
 // ============================================================================
 Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const
 {
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
   if (!myFeatureStorage)
-    return SLVS_E_UNKNOWN;
+    return aResult;
   std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
   if (aConstraints.empty())
-    return SLVS_E_UNKNOWN;
-  ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin());
-  if (aCIter == myConstraints.end())
-    return SLVS_E_UNKNOWN;
-  return aCIter->second->getId(theFeature);
+    return aResult;
+  std::set<ConstraintPtr>::iterator aConstrIter = aConstraints.begin();
+  for (; aConstrIter != aConstraints.end(); aConstrIter++) {
+    ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter);
+    if (aCIter == myConstraints.end())
+      continue;
+    aResult = aCIter->second->getId(theFeature);
+    if (aResult != SLVS_E_UNKNOWN)
+      return aResult;
+  }
+  return SLVS_E_UNKNOWN;
 }
 
 // ============================================================================
@@ -145,15 +145,22 @@ Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const
 // ============================================================================
 Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const
 {
+  Slvs_hEntity aResult = SLVS_E_UNKNOWN;
   if (!myFeatureStorage)
-    return SLVS_E_UNKNOWN;
+    return aResult;
   std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theAttribute);
   if (aConstraints.empty())
-    return SLVS_E_UNKNOWN;
-  ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin());
-  if (aCIter == myConstraints.end())
-    return SLVS_E_UNKNOWN;
-  return aCIter->second->getId(theAttribute);
+    return aResult;
+  std::set<ConstraintPtr>::iterator aConstrIter = aConstraints.begin();
+  for (; aConstrIter != aConstraints.end(); aConstrIter++) {
+    ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter);
+    if (aCIter == myConstraints.end())
+      continue;
+    aResult = aCIter->second->getId(theAttribute);
+    if (aResult != SLVS_E_UNKNOWN)
+      return aResult;
+  }
+  return SLVS_E_UNKNOWN;
 }
 
 // ============================================================================
@@ -206,215 +213,31 @@ bool SketchSolver_Group::changeConstraint(
   else
     myConstraints[theConstraint]->update();
 
+  // Fix base features for fillet
+  if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+    std::list<AttributePtr> anAttrList =
+        theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+    std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+    for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+      AttributeRefAttrPtr aRefAttr =
+          std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+      if (!aRefAttr || !aRefAttr->isObject())
+        continue;
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      SolverConstraintPtr aConstraint =
+          SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+      if (!aConstraint)
+        continue;
+      aConstraint->setGroup(this);
+      aConstraint->setStorage(myStorage);
+      myTempConstraints.insert(aConstraint);
+    }
+  }
+
   if (!myFeatureStorage)
     myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
   myFeatureStorage->changeConstraint(theConstraint);
 
-////  if (theConstraint) {
-////    if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID())
-////      return changeRigidConstraint(theConstraint);
-////    if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID())
-////      return changeMirrorConstraint(theConstraint);
-////    if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID())
-////      return changeFilletConstraint(theConstraint);
-////  }
-////
-////  // Search this constraint in the current group to update it
-////  ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
-////  std::vector<Slvs_Constraint>::iterator aConstrIter;
-////  if (aConstrMapIter != myConstraintMap.end()) {
-////    int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
-////    aConstrIter = myConstraints.begin() + aConstrPos;
-////  }
-////
-////  // Get constraint type and verify the constraint parameters are correct
-////  SketchSolver_Constraint aConstraint(theConstraint);
-////  int aConstrType = aConstraint.getType();
-////  if (aConstrType == SLVS_C_UNKNOWN
-////      || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
-////    return false;
-////  const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
-////
-////  // Create constraint parameters
-////  double aDistance = 0.0;  // scalar value of the constraint
-////  AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-////      theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
-////  if (aDistAttr) {
-////    aDistance = aDistAttr->value();
-////    // Issue #196: checking the positivity of the distance constraint
-////    if (aDistance < tolerance &&
-////       (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE))
-////      return false;
-////    // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter
-////    if (aConstrType == SLVS_C_DIAMETER)
-////      aDistance *= 2.0;
-////    if (aConstrMapIter != myConstraintMap.end()
-////        && fabs(aConstrIter->valA - aDistance) > tolerance) {
-////      myNeedToSolve = true;
-////      aConstrIter->valA = aDistance;
-////    }
-////  }
-////
-////  size_t aNbTmpConstraints = myTempConstraints.size();
-////  Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE];  // parameters of the constraint
-////  for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
-////    aConstrEnt[indAttr] = SLVS_E_UNKNOWN;
-////    std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
-////        ModelAPI_AttributeRefAttr>(
-////        theConstraint->data()->attribute(aConstraintAttributes[indAttr]));
-////    if (!aConstrAttr)
-////      continue;
-////
-////    // Convert the object of the attribute to the feature
-////    FeaturePtr aFeature;
-////    if (aConstrAttr->isObject() && aConstrAttr->object()) {
-////      ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-////          aConstrAttr->object());
-////      if (!aRC)
-////        continue;
-////      std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-////      aFeature = aDoc->feature(aRC);
-////    }
-////
-////    // For the length constraint the start and end points of the line should be added to the entities list instead of line
-////    if (aConstrType == SLVS_C_PT_PT_DISTANCE
-////        && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) {
-////      Slvs_hEntity aLineEnt = changeEntityFeature(aFeature);
-////      int aEntPos = Search(aLineEnt, myEntities);
-////      aConstrEnt[indAttr++] = myEntities[aEntPos].point[0];
-////      aConstrEnt[indAttr++] = myEntities[aEntPos].point[1];
-////      while (indAttr < CONSTRAINT_ATTR_SIZE)
-////        aConstrEnt[indAttr++] = 0;
-////      break;  // there should be no other entities
-////    } else if (aConstrAttr->isObject())
-////      aConstrEnt[indAttr] = changeEntityFeature(aFeature);
-////    else
-////      aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr());
-////  }
-////
-////  if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
-////    // Several points may be coincident, it is not necessary to store all constraints between them.
-////    // Try to find sequence of coincident points which connects the points of new constraint
-////    if (aConstrType == SLVS_C_POINTS_COINCIDENT) {
-////      if (aConstrEnt[0] == aConstrEnt[1])  // no need to add self coincidence
-////        return false;
-////      if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) {
-////        myExtraCoincidence.insert(theConstraint);  // the constraint is stored for further purposes
-////        return false;
-////      }
-////      if (aNbTmpConstraints < myTempConstraints.size()) {
-////        // There was added temporary constraint. Check that there is no coincident points which already rigid.
-////
-////        // Get list of already fixed points
-////        std::set<Slvs_hEntity> anAlreadyFixed;
-////        std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
-////        for (; aCIter != myConstraints.end(); aCIter++)
-////          if (aCIter->type == SLVS_C_WHERE_DRAGGED) {
-////            std::list<Slvs_hConstraint>::const_iterator aTmpIt = myTempConstraints.begin();
-////            for (; aTmpIt != myTempConstraints.end(); aTmpIt++)
-////              if (*aTmpIt == aCIter->h)
-////                break;
-////            if (aTmpIt == myTempConstraints.end())
-////              anAlreadyFixed.insert(aCIter->ptA);
-////          }
-////
-////        std::set<Slvs_hConstraint> aTmpConstrToDelete;
-////        std::list<Slvs_hConstraint>::reverse_iterator aTmpIter = myTempConstraints.rbegin();
-////        size_t aCurSize = myTempConstraints.size();
-////        for (; aCurSize > aNbTmpConstraints && aTmpIter != myTempConstraints.rend();
-////            aTmpIter++, aCurSize--) {
-////          int aConstrPos = Search(*aTmpIter, myConstraints);
-////          std::vector<std::set<Slvs_hEntity> >::const_iterator
-////            aCoincIter = myCoincidentPoints.begin();
-////          for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
-////            if (aCoincIter->find(myConstraints[aConstrPos].ptA) != aCoincIter->end()) {
-////              std::set<Slvs_hEntity>::const_iterator anIt;
-////              for (anIt = aCoincIter->begin(); anIt != aCoincIter->end(); anIt++)
-////                if (anAlreadyFixed.find(*anIt) != anAlreadyFixed.end()) {
-////                  aTmpConstrToDelete.insert(*aTmpIter);
-////                  break;
-////                }
-////              break;
-////            }
-////        }
-////        if (!aTmpConstrToDelete.empty())
-////          removeTemporaryConstraints(aTmpConstrToDelete);
-////      }
-////    }
-////    // For the tangency constraints it is necessary to identify which points of entities are coincident
-////    int aSlvsOtherFlag = 0;
-////    int aSlvsOther2Flag = 0;
-////    if (aConstrType == SLVS_C_ARC_LINE_TANGENT || aConstrType == SLVS_C_CURVE_CURVE_TANGENT) {
-////      // Search entities used by constraint
-////      int anEnt1Pos = Search(aConstrEnt[2], myEntities);
-////      int anEnt2Pos = Search(aConstrEnt[3], myEntities);
-////      // Obtain start and end points of entities
-////      Slvs_hEntity aPointsToFind[4];
-////      aPointsToFind[0] = myEntities[anEnt1Pos].point[1];
-////      aPointsToFind[1]= myEntities[anEnt1Pos].point[2];
-////      bool hasLine = (myEntities[anEnt2Pos].type == SLVS_E_LINE_SEGMENT);
-////      aPointsToFind[2]= myEntities[anEnt2Pos].point[hasLine ? 0 : 1];
-////      aPointsToFind[3]= myEntities[anEnt2Pos].point[hasLine ? 1 : 2];
-////      // Search coincident points
-////      bool isPointFound[4];
-////      std::vector<std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
-////      for ( ; aCPIter != myCoincidentPoints.end(); aCPIter++) {
-////        for (int i = 0; i < 4; i++)
-////          isPointFound[i] = (aCPIter->find(aPointsToFind[i]) != aCPIter->end());
-////        if ((isPointFound[0] || isPointFound[1]) && (isPointFound[2] || isPointFound[3])) {
-////          // the arc is tangent by end point
-////          if (isPointFound[1]) aSlvsOtherFlag = 1;
-////          // the second item is an arc and it is tangent by end point too
-////          if (!hasLine && isPointFound[3]) aSlvsOther2Flag = 1;
-////          break;
-////        }
-////      }
-////      if (aCPIter == myCoincidentPoints.end()) {
-////        // There is no coincident points between tangential objects. Generate error message
-////        Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
-////        return false;
-////      }
-////    }
-////
-////    // Create SolveSpace constraint structure
-////    Slvs_Constraint aSlvsConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
-////                                                      myWorkplane.h, aDistance, aConstrEnt[0],
-////                                                      aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]);
-////    if (aSlvsOtherFlag != 0) aSlvsConstr.other = aSlvsOtherFlag;
-////    if (aSlvsOther2Flag != 0) aSlvsConstr.other2 = aSlvsOther2Flag;
-////    myConstraints.push_back(aSlvsConstr);
-////    myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aSlvsConstr.h);
-////    int aConstrPos = Search(aSlvsConstr.h, myConstraints);
-////    aConstrIter = myConstraints.begin() + aConstrPos;
-////    myNeedToSolve = true;
-////  } else { // Attributes of constraint may be changed => update constraint
-////    Slvs_hEntity* aCurrentAttr[] = {&aConstrIter->ptA, &aConstrIter->ptB,
-////                                   &aConstrIter->entityA, &aConstrIter->entityB,
-////                                   &aConstrIter->entityC, &aConstrIter->entityD};
-////    for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
-////      if (*(aCurrentAttr[indAttr]) != aConstrEnt[indAttr])
-////      {
-////        *(aCurrentAttr[indAttr]) = aConstrEnt[indAttr];
-////        myNeedToSolve = true;
-////      }
-////    }
-////  }
-////
-////  // Update flags of entities to be used by constraints
-////  for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
-////    if (aConstrEnt[indAttr] != 0) {
-////      int aPos = Search(aConstrEnt[indAttr], myEntities);
-////      myEntOfConstr[aPos] = true;
-////      // Sub-entities should be used implcitly
-////      Slvs_hEntity* aEntPtr = myEntities[aPos].point;
-////      while (*aEntPtr != 0) {
-////        aPos = Search(*aEntPtr, myEntities);
-////        myEntOfConstr[aPos] = true;
-////        aEntPtr++;
-////      }
-////    }
-////
-////  checkConstraintConsistence(*aConstrIter);
   return true;
 }
 
@@ -445,844 +268,6 @@ void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFe
   myTempConstraints.insert(aConstraint);
 }
 
-////// ============================================================================
-//////  Function: changeRigidConstraint
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update the "Rigid" constraint in the group
-////// ============================================================================
-////bool SketchSolver_Group::changeRigidConstraint(
-////    std::shared_ptr<SketchPlugin_Constraint> theConstraint)
-////{
-////  // Search this constraint in the current group to update it
-////  ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
-////  std::vector<Slvs_Constraint>::iterator aConstrIter;
-////  if (aConstrMapIter != myConstraintMap.end()) {
-////    int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
-////    aConstrIter = myConstraints.begin() + aConstrPos;
-////  }
-////
-////  // Get constraint type and verify the constraint parameters are correct
-////  SketchSolver_Constraint aConstraint(theConstraint);
-////  int aConstrType = aConstraint.getType();
-////  if (aConstrType == SLVS_C_UNKNOWN
-////      || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
-////    return false;
-////  const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
-////
-////  Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN;
-////  std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
-////      ModelAPI_AttributeRefAttr>(
-////      theConstraint->data()->attribute(aConstraintAttributes[0]));
-////  if (!aConstrAttr)
-////    return false;
-////
-////  // Convert the object of the attribute to the feature
-////  FeaturePtr aFeature;
-////  if (aConstrAttr->isObject() && aConstrAttr->object()) {
-////    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-////        aConstrAttr->object());
-////    if (!aRC)
-////      return false;
-////    std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-////    aFeature = aDoc->feature(aRC);
-////  }
-////
-////  aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr());
-////
-////  if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
-////    // Check the fixed entity is not a point.
-////    std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
-////        ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0]));
-////    std::shared_ptr<GeomDataAPI_Point> aPoint =
-////        std::dynamic_pointer_cast<GeomDataAPI_Point>(aConstrAttr->attr());
-////    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-////        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aConstrAttr->attr());
-////    if (aPoint || aPoint2D) {
-////      // Create SolveSpace constraint structure
-////      Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////          ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
-////          aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      myConstraints.push_back(aConstraint);
-////      myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aConstraint.h);
-////      int aConstrPos = Search(aConstraint.h, myConstraints);
-////      aConstrIter = myConstraints.begin() + aConstrPos;
-////      myNeedToSolve = true;
-////    } else {
-////      myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
-////
-////      // To avoid SolveSpace problems:
-////      // * if the circle is rigid, we will fix its center and radius;
-////      // * if the arc is rigid, we will fix its start and end points and radius.
-////      double aRadius = 0.0;
-////      bool isArc = false;
-////      bool isCircle = false;
-////      if (aFeature) {
-////        if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
-////          std::shared_ptr<GeomDataAPI_Point2D> aCenter =
-////              std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////              aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
-////          std::shared_ptr<GeomDataAPI_Point2D> aStart =
-////              std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////              aFeature->data()->attribute(SketchPlugin_Arc::START_ID()));
-////          aRadius = aStart->pnt()->distance(aCenter->pnt());
-////          isArc = true;
-////        } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
-////          aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-////              aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value();
-////          isCircle = true;
-////        }
-////      }
-////
-////      // Get list of already fixed points
-////      std::set<Slvs_hEntity> anAlreadyFixed;
-////      std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
-////      for (; aCIter != myConstraints.end(); aCIter++)
-////        if (aCIter->type == SLVS_C_WHERE_DRAGGED)
-////          anAlreadyFixed.insert(aCIter->ptA);
-////
-////      // Create constraints to fix the parameters of the entity
-////      int aEntPos = Search(aConstrEnt, myEntities);
-////      Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point;
-////      if (isArc) aPointsPtr++; // avoid to fix center of arc
-////      while (*aPointsPtr != 0) {
-////        // Avoid to create additional "Rigid" constraints for coincident points
-////        bool isCoincAlreadyFixed = false;
-////        if (!anAlreadyFixed.empty()) {
-////          if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end())
-////            isCoincAlreadyFixed = true;
-////
-////          std::vector<std::set<Slvs_hEntity> >::const_iterator aCoincIter =
-////              myCoincidentPoints.begin();
-////          for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) {
-////            if (aCoincIter->find(*aPointsPtr) == aCoincIter->end())
-////              continue;
-////            std::set<Slvs_hEntity>::const_iterator anIter = anAlreadyFixed.begin();
-////            for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++)
-////              if (aCoincIter->find(*anIter) != aCoincIter->end())
-////                isCoincAlreadyFixed = true;
-////          }
-////        }
-////
-////        if (!isCoincAlreadyFixed) {
-////          Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////              ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
-////              *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////          myConstraints.push_back(aConstraint);
-////          myConstraintMap[theConstraint].push_back(aConstraint.h);
-////        }
-////        aPointsPtr++;
-////      }
-////
-////      if (isArc || isCircle) { // add radius constraint
-////        Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////            ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius,
-////            SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN);
-////        myConstraints.push_back(aConstraint);
-////        myConstraintMap[theConstraint].push_back(aConstraint.h);
-////      }
-////
-////      // The object is already rigid, so there is no constraints added
-////      if (myConstraintMap[theConstraint].empty()) {
-////        myConstraintMap.erase(theConstraint);
-////        myNeedToSolve = false;
-////      }
-////      else
-////        myNeedToSolve = true;
-////    }
-////  }
-////  return true;
-////}
-////
-////// ============================================================================
-//////  Function: changeMirrorConstraint
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update the "Mirror" constraint in the group
-////// ============================================================================
-////bool SketchSolver_Group::changeMirrorConstraint(
-////    std::shared_ptr<SketchPlugin_Constraint> theConstraint)
-////{
-////  DataPtr aConstrData = theConstraint->data();
-////
-////  // Search this constraint in the current group to update it
-////  ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
-////  std::vector<Slvs_Constraint>::iterator aConstrIter;
-////  if (aConstrMapIter != myConstraintMap.end()) {
-////    int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
-////    aConstrIter = myConstraints.begin() + aConstrPos;
-////  }
-////
-////  // Get constraint type and verify the constraint parameters are correct
-////  SketchSolver_Constraint aConstraint(theConstraint);
-////  int aConstrType = aConstraint.getType();
-////  if (aConstrType == SLVS_C_UNKNOWN
-////      || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
-////    return false;
-////  const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
-////
-////  Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN;
-////  AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////      aConstrData->attribute(aConstraintAttributes[0]));
-////  if (!aConstrAttr)
-////    return false;
-////
-////  // Convert the object of the attribute to the feature
-////  FeaturePtr aMirrorLineFeat;
-////  if (aConstrAttr->isObject() && aConstrAttr->object()) {
-////    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-////        aConstrAttr->object());
-////    if (!aRC)
-////      return false;
-////    std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-////    aMirrorLineFeat = aDoc->feature(aRC);
-////  }
-////  aMirrorLineEnt = aConstrAttr->isObject() ?
-////      changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr());
-////
-////  if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
-////    // Append symmetric constraint for each point of mirroring features
-////    AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////        aConstrData->attribute(aConstraintAttributes[1]));
-////    AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////        aConstrData->attribute(aConstraintAttributes[2]));
-////    if (!aBaseRefList || !aMirroredRefList)
-////      return false;
-////
-////    std::list<ObjectPtr> aBaseList = aBaseRefList->list();
-////    std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
-////    if (aBaseList.size() != aMirroredList.size())
-////      return false;
-////
-////    myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
-////
-////    FeaturePtr aBaseFeature, aMirrorFeature;
-////    ResultConstructionPtr aRC;
-////    std::list<ObjectPtr>::iterator aBaseIter = aBaseList.begin();
-////    std::list<ObjectPtr>::iterator aMirIter = aMirroredList.begin();
-////    for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) {
-////      aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
-////      aBaseFeature = aRC ? aRC->document()->feature(aRC) :
-////          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
-////      aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirIter);
-////      aMirrorFeature = aRC ? aRC->document()->feature(aRC) :
-////          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirIter);
-////
-////      if (!aBaseFeature || !aMirrorFeature || 
-////          aBaseFeature->getKind() != aMirrorFeature->getKind())
-////        return false;
-////      Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature);
-////      Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature);
-////      // Make aMirrorEnt parameters to be symmetric with aBaseEnt
-////      makeMirrorEntity(aBaseEnt, aMirrorEnt, aMirrorLineEnt);
-////
-////      if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) {
-////        Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
-////            myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN);
-////        myConstraints.push_back(aConstraint);
-////        myConstraintMap[theConstraint].push_back(aConstraint.h);
-////      } else {
-////        int aBasePos = Search(aBaseEnt, myEntities);
-////        int aMirrorPos = Search(aMirrorEnt, myEntities);
-////        if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) {
-////          for (int ind = 0; ind < 2; ind++) {
-////            Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////                ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
-////                myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind],
-////                aMirrorLineEnt, SLVS_E_UNKNOWN);
-////            myConstraints.push_back(aConstraint);
-////            myConstraintMap[theConstraint].push_back(aConstraint.h);
-////          }
-////        } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
-////          Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////              ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
-////              myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0],
-////              aMirrorLineEnt, SLVS_E_UNKNOWN);
-////          myConstraints.push_back(aConstraint);
-////          myConstraintMap[theConstraint].push_back(aConstraint.h);
-////          // Additional constraint for equal radii
-////          Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
-////              ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0,
-////              SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt);
-////          myConstraints.push_back(anEqRadConstr);
-////          myConstraintMap[theConstraint].push_back(anEqRadConstr.h);
-////        } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
-////          // Workaround to avoid problems in SolveSpace.
-////          // The symmetry of two arcs will be done using symmetry of three points on these arcs:
-////          // start point, end point, and any other point on the arc
-////          Slvs_hEntity aBaseArcPoints[3] = {
-////              myEntities[aBasePos].point[1],
-////              myEntities[aBasePos].point[2],
-////              SLVS_E_UNKNOWN};
-////          Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
-////              myEntities[aMirrorPos].point[2],
-////              myEntities[aMirrorPos].point[1],
-////              SLVS_E_UNKNOWN};
-////          Slvs_hEntity aBothArcs[2] = {aBaseEnt, aMirrorEnt};
-////          Slvs_hEntity aBothMiddlePoints[2];
-////          for (int i = 0; i < 2; i++) {
-////            double x, y;
-////            calculateMiddlePoint(aBothArcs[i], x, y);
-////            std::vector<Slvs_Param>::iterator aParamIter = myParams.end();
-////            Slvs_hParam u = changeParameter(x, aParamIter);
-////            Slvs_hParam v = changeParameter(y, aParamIter);
-////            Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v);
-////            myEntities.push_back(aPoint);
-////            aBothMiddlePoints[i] = aPoint.h;
-////            // additional constraint point-on-curve
-////            Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
-////                ++myConstrMaxID, myID, SLVS_C_PT_ON_CIRCLE, myWorkplane.h, 0.0,
-////                aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN);
-////            myConstraints.push_back(aPonCircConstr);
-////            myConstraintMap[theConstraint].push_back(aPonCircConstr.h);
-////          }
-////
-////          aBaseArcPoints[2] = aBothMiddlePoints[0];
-////          aMirrorArcPoints[2] = aBothMiddlePoints[1];
-////          for (int ind = 0; ind < 3; ind++) {
-////            Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-////                ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
-////                aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLineEnt, SLVS_E_UNKNOWN);
-////            myConstraints.push_back(aConstraint);
-////            myConstraintMap[theConstraint].push_back(aConstraint.h);
-////          }
-////        }
-////      }
-////    }
-////
-////    // Set the mirror line unchanged during constraint recalculation
-////    int aMirrorLinePos = Search(aMirrorLineEnt, myEntities);
-////    Slvs_Constraint aRigidStart = Slvs_MakeConstraint(
-////        ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
-////        myEntities[aMirrorLinePos].point[0], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////    myConstraints.push_back(aRigidStart);
-////    myConstraintMap[theConstraint].push_back(aRigidStart.h);
-////    Slvs_Constraint aRigidEnd = Slvs_MakeConstraint(
-////        ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0,
-////        myEntities[aMirrorLinePos].point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////    myConstraints.push_back(aRigidEnd);
-////    myConstraintMap[theConstraint].push_back(aRigidEnd.h);
-////
-////    // Add temporary constraints for initial objects to be unchanged
-////    for (aBaseIter = aBaseList.begin(); aBaseIter != aBaseList.end(); aBaseIter++) {
-////      aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
-////      aBaseFeature = aRC ? aRC->document()->feature(aRC) :
-////          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
-////      if (!aBaseFeature) continue;
-////      std::list<AttributePtr> aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::type());
-////      std::list<AttributePtr>::iterator anIt = aPoints.begin();
-////      for ( ; anIt != aPoints.end(); anIt++) {
-////        // Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace)
-////        if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() &&
-////            (*anIt)->id() == SketchPlugin_Arc::END_ID())
-////          continue;
-////        addTemporaryConstraintWhereDragged(*anIt);
-////      }
-////    }
-////  }
-////  return true;
-////}
-////
-////// ============================================================================
-//////  Function: changeFilletConstraint
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update the "Fillet" constraint in the group
-////// ============================================================================
-////bool SketchSolver_Group::changeFilletConstraint(
-////    std::shared_ptr<SketchPlugin_Constraint> theConstraint)
-////{
-////  DataPtr aConstrData = theConstraint->data();
-////
-////  // Search this constraint in the current group to update it
-////  ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
-////  std::vector<Slvs_Constraint>::iterator aConstrIter;
-////  if (aConstrMapIter != myConstraintMap.end()) {
-////    int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
-////    aConstrIter = myConstraints.begin() + aConstrPos;
-////  }
-////
-////  // Get constraint type and verify the constraint parameters are correct
-////  SketchSolver_Constraint aConstraint(theConstraint);
-////  int aConstrType = aConstraint.getType();
-////  if (aConstrType == SLVS_C_UNKNOWN)
-////    return false;
-////  const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
-////
-////  // Obtain hEntity for basic objects of fillet
-////  Slvs_hEntity aBaseObject[2];
-////  FeaturePtr aBaseFeature[2];
-////  for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
-////    AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////        aConstrData->attribute(aConstraintAttributes[indAttr]));
-////    if (!aConstrAttr)
-////      return false;
-////    if (aConstrAttr->isObject() && aConstrAttr->object()) {
-////      ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-////          aConstrAttr->object());
-////      if (!aRC)
-////        return false;
-////      std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-////      aBaseFeature[indAttr] = aDoc->feature(aRC);
-////    }
-////    aBaseObject[indAttr] = aConstrAttr->isObject() ?
-////        changeEntityFeature(aBaseFeature[indAttr]) : changeEntity(aConstrAttr->attr());
-////  }
-////  // Check the base entities have a coincident point
-////  int aBaseObjInd[2] = {
-////      Search(aBaseObject[0], myEntities),
-////      Search(aBaseObject[1], myEntities)
-////    };
-////  int aShift[2] = { // shift for calculating correct start and end points for different types of objects
-////      myEntities[aBaseObjInd[0]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
-////      myEntities[aBaseObjInd[1]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0,
-////    };
-////  Slvs_hEntity aFirstObjPoints[2] = { // indices of start and end point of first object
-////      myEntities[aBaseObjInd[0]].point[aShift[0]],
-////      myEntities[aBaseObjInd[0]].point[1+aShift[0]]
-////    };
-////  Slvs_hEntity aSecondObjPoints[2] = { // indices of start and end point of second object
-////      myEntities[aBaseObjInd[1]].point[aShift[1]],
-////      myEntities[aBaseObjInd[1]].point[1+aShift[1]]
-////    };
-////  bool isCoincidentFound = false;
-////  int aBaseCoincInd[2] = {0, 0}; // indices in aFirstObjPoint and aSecondObjPoint identifying coincident points
-////  std::vector<std::set<Slvs_hEntity> >::iterator aCPIter = myCoincidentPoints.begin();
-////  for ( ; aCPIter != myCoincidentPoints.end() && !isCoincidentFound; aCPIter++)
-////    for (int ind1 = 0; ind1 < 2 && !isCoincidentFound; ind1++)
-////      for (int ind2 = 0; ind2 < 2 && !isCoincidentFound; ind2++)
-////        if (aCPIter->find(aFirstObjPoints[ind1]) != aCPIter->end() &&
-////            aCPIter->find(aSecondObjPoints[ind2]) != aCPIter->end()) {
-////          aBaseCoincInd[0] = ind1;
-////          aBaseCoincInd[1] = ind2;
-////          isCoincidentFound = true;
-////        }
-////  if (!isCoincidentFound) {
-////    // There is no coincident points between objects. Generate error message
-////    Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
-////    return false;
-////  }
-////
-////  // Create fillet entities
-////  // - first object is placed on the first base 
-////  // - second object is on the second base 
-////  // - third object is a filleting arc
-////  static const int aNbFilletEnt = 3;
-////  Slvs_hEntity aFilletEnt[aNbFilletEnt];
-////  int aFilletObjInd[aNbFilletEnt];
-////  AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////      aConstrData->attribute(aConstraintAttributes[2]));
-////  if (!aFilletRefList)
-////    return false;
-////  std::list<ObjectPtr> aFilletList = aFilletRefList->list();
-////  if (aFilletList.size() < aNbFilletEnt)
-////    return false;
-////  FeaturePtr aFilletFeature;
-////  ResultConstructionPtr aRC;
-////  std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
-////  for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
-////    aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
-////    aFilletFeature = aRC ? aRC->document()->feature(aRC) :
-////        std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFilIter);
-////    if (!aFilletFeature)
-////      return false;
-////    aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature);
-////    aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities);
-////  }
-////  // At first time, for correct result, move floating points of fillet on the middle points of base objects
-////  if (myConstraintMap.find(theConstraint) == myConstraintMap.end()) {
-////    double anArcPoints[6];
-////    for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
-////      int anIndShift = myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
-////      int aPointsPos[2] = {
-////          Search(myEntities[aFilletObjInd[indEnt]].point[anIndShift], myEntities),
-////          Search(myEntities[aFilletObjInd[indEnt]].point[1+anIndShift], myEntities)
-////        };
-////      int aParamPos[2] = {
-////          Search(myEntities[aPointsPos[0]].param[0], myParams),
-////          Search(myEntities[aPointsPos[1]].param[0], myParams)
-////        };
-////      int anIndex = aParamPos[aBaseCoincInd[indEnt]];
-////      if (anIndShift == 0) {
-////        myParams[anIndex].val =
-////            0.5 * (myParams[aParamPos[0]].val + myParams[aParamPos[1]].val);
-////        myParams[1 + anIndex].val =
-////            0.5 * (myParams[1 + aParamPos[0]].val + myParams[1 + aParamPos[1]].val);
-////      } else { // place the changed point on the arc
-////        double x = 0, y = 0;
-////        calculateMiddlePoint(aFilletEnt[indEnt], x, y);
-////        myParams[anIndex].val = x;
-////        myParams[1 + anIndex].val = y;
-////      }
-////      anArcPoints[indEnt*2+2] = myParams[anIndex].val;
-////      anArcPoints[indEnt*2+3] = myParams[1 + anIndex].val;
-////    }
-////    anArcPoints[0] = 0.5 * (anArcPoints[2] + anArcPoints[4]);
-////    anArcPoints[1] = 0.5 * (anArcPoints[3] + anArcPoints[5]);
-////    for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
-////      int aPtPos = Search(myEntities[aFilletObjInd[2]].point[indArcPt], myEntities);
-////      int aParamPos = Search(myEntities[aPtPos].param[0], myParams);
-////      myParams[aParamPos].val = anArcPoints[indArcPt * 2];
-////      myParams[aParamPos + 1].val = anArcPoints[indArcPt * 2 + 1];
-////    }
-////  }
-////
-////  // Check the fillet arc which point to be connected to
-////  bool isArcInversed = false; // indicates that start and end points of arc should be connected to second and first object respectively
-////  Slvs_hEntity hEnt = myEntities[aFilletObjInd[2]].point[1];
-////  int aPos = Search(hEnt, myEntities);
-////  Slvs_hParam anArcStartPoint = myEntities[aPos].param[0];
-////  aPos = Search(anArcStartPoint, myParams);
-////  double anArcPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
-////  double aSqDistances[2];
-////  int aPtInd;
-////  for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
-////    aPtInd = aBaseCoincInd[indEnt]+aShift[indEnt];
-////    hEnt = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
-////    aPos = Search(hEnt, myEntities);
-////    Slvs_hParam anObjectPoint = myEntities[aPos].param[0];
-////    aPos = Search(anObjectPoint, myParams);
-////    double aPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val};
-////    aSqDistances[indEnt] = 
-////        (anArcPtCoord[0] - aPtCoord[0]) * (anArcPtCoord[0] - aPtCoord[0]) +
-////        (anArcPtCoord[1] - aPtCoord[1]) * (anArcPtCoord[1] - aPtCoord[1]);
-////  }
-////  if (aSqDistances[1] < aSqDistances[0])
-////    isArcInversed = true;
-////
-////  // Create list of constraints to generate fillet
-////  std::vector<Slvs_hConstraint> aConstrList;
-////  bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists
-////  std::vector<Slvs_hConstraint>::iterator aCMapIter =
-////    isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin();
-////  int aCurConstrPos = isExists ? Search(*aCMapIter, myConstraints) : 0;
-////  for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) {
-////    // one point of fillet object should be coincident with the point on base, non-coincident with another base object
-////    aPtInd = 1-aBaseCoincInd[indEnt]+aShift[indEnt]; // (1-aBaseCoincInd[indEnt]) = index of non-coincident point, aShift is used to process all types of shapes
-////    Slvs_hEntity aPtBase = myEntities[aBaseObjInd[indEnt]].point[aPtInd];
-////    Slvs_hEntity aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
-////    if (isExists) {
-////      myConstraints[aCurConstrPos].ptA = aPtBase;
-////      myConstraints[aCurConstrPos].ptB = aPtFillet;
-////      aCMapIter++;
-////      aCurConstrPos = Search(*aCMapIter, myConstraints);
-////    } else {
-////      Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
-////          ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
-////          0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      myConstraints.push_back(aCoincConstr);
-////      aConstrList.push_back(aCoincConstr.h);
-////    }
-////
-////    // another point of fillet object should be placed on the base object
-////    Slvs_Constraint aPonCurveConstr;
-////    int aTangentType;
-////    if (myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE) {
-////      // centers of arcs should be coincident
-////      aPtBase = myEntities[aBaseObjInd[indEnt]].point[0];
-////      aPtFillet = myEntities[aFilletObjInd[indEnt]].point[0];
-////      if (isExists) {
-////        myConstraints[aCurConstrPos].ptA = aPtBase;
-////        myConstraints[aCurConstrPos].ptB = aPtFillet;
-////        aCMapIter++;
-////        aCurConstrPos = Search(*aCMapIter, myConstraints);
-////      } else {
-////        aPonCurveConstr = Slvs_MakeConstraint(
-////            ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
-////            0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      }
-////      aPtFillet = myEntities[aFilletObjInd[indEnt]].point[1+aBaseCoincInd[indEnt]]; // !!! will be used below
-////      aTangentType = SLVS_C_CURVE_CURVE_TANGENT;
-////    } else {
-////      aPtInd = aBaseCoincInd[indEnt];
-////      aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd];
-////      if (isExists) {
-////        myConstraints[aCurConstrPos].ptA = aPtFillet;
-////        aCMapIter++;
-////        aCurConstrPos = Search(*aCMapIter, myConstraints);
-////      } else {
-////        aPonCurveConstr = Slvs_MakeConstraint(
-////            ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h,
-////            0, aPtFillet, SLVS_E_UNKNOWN, aBaseObject[indEnt], SLVS_E_UNKNOWN);
-////      }
-////      aTangentType = SLVS_C_ARC_LINE_TANGENT;
-////    }
-////    if (!isExists) {
-////      myConstraints.push_back(aPonCurveConstr);
-////      aConstrList.push_back(aPonCurveConstr.h);
-////    }
-////
-////    // Bound point of fillet arc should be tangently coincident with a bound point of fillet object
-////    aPtInd = 1 + (isArcInversed ? 1-indEnt : indEnt);
-////    Slvs_hEntity aPtArc = myEntities[aFilletObjInd[2]].point[aPtInd];
-////    if (isExists) {
-////      myConstraints[aCurConstrPos].ptA = aPtArc;
-////      myConstraints[aCurConstrPos].ptB = aPtFillet;
-////      aCMapIter++;
-////      aCurConstrPos = Search(*aCMapIter, myConstraints);
-////      myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
-////      myConstraints[aCurConstrPos].entityB = aFilletEnt[indEnt];
-////      myConstraints[aCurConstrPos].other = (isArcInversed ? 1-indEnt : indEnt);
-////      aCMapIter++;
-////      aCurConstrPos = Search(*aCMapIter, myConstraints);
-////    } else {
-////      Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
-////          ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h,
-////          0, aPtArc, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-////      myConstraints.push_back(aCoincConstr);
-////      aConstrList.push_back(aCoincConstr.h);
-////      Slvs_Constraint aTangency = Slvs_MakeConstraint(
-////          ++myConstrMaxID, myID, aTangentType, myWorkplane.h,
-////          0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], aFilletEnt[indEnt]);
-////      aTangency.other = (isArcInversed ? 1-indEnt : indEnt);
-////      aTangency.other2 = aTangentType == SLVS_C_CURVE_CURVE_TANGENT ? aBaseCoincInd[indEnt] : 0;
-////      myConstraints.push_back(aTangency);
-////      aConstrList.push_back(aTangency.h);
-////    }
-////  }
-////
-////  // Additional constraint for fillet diameter
-////  double aRadius = 0.0;  // scalar value of the constraint
-////  AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-////      aConstrData->attribute(SketchPlugin_Constraint::VALUE()));
-////  aRadius = aDistAttr->value();
-////  if (isExists) {
-////    myConstraints[aCurConstrPos].entityA = aFilletEnt[2];
-////    myConstraints[aCurConstrPos].valA = aRadius * 2.0;
-////    aCMapIter++;
-////  } else {
-////    Slvs_Constraint aDiamConstr = Slvs_MakeConstraint(
-////        ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, aRadius * 2.0,
-////        SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], SLVS_E_UNKNOWN);
-////    myConstraints.push_back(aDiamConstr);
-////    aConstrList.push_back(aDiamConstr.h);
-////
-////    myConstraintMap[theConstraint] = aConstrList;
-////  }
-////
-////  // Additional temporary constraints for base objects to be fixed
-////  for (unsigned int indAttr = 0; indAttr < 2; indAttr++) {
-////    if (!aBaseFeature[indAttr]) {
-////      AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-////          aConstrData->attribute(aConstraintAttributes[indAttr]));
-////      addTemporaryConstraintWhereDragged(aConstrAttr->attr());
-////      continue;
-////    }
-////    std::list<AttributePtr> anAttributes =
-////        aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::type());
-////    std::list<AttributePtr>::iterator anIt = anAttributes.begin();
-////    for ( ; anIt != anAttributes.end(); anIt++) {
-////      // Arc should be fixed by center and start points only (to avoid "conflicting constraints" message)
-////      if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID() &&
-////          (*anIt)->id() == SketchPlugin_Arc::END_ID())
-////        continue;
-////      addTemporaryConstraintWhereDragged(*anIt);
-////    }
-////  }
-////  return true;
-////}
-////
-////// ============================================================================
-//////  Function: changeEntity
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update the element affected by any constraint
-////// ============================================================================
-////Slvs_hEntity SketchSolver_Group::changeEntity(
-////    std::shared_ptr<ModelAPI_Attribute> theEntity)
-////{
-////  // If the entity is already in the group, try to find it
-////  std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator aEntIter =
-////      myEntityAttrMap.find(theEntity);
-////  int aEntPos;
-////  std::vector<Slvs_Param>::const_iterator aParamIter;  // looks at first parameter of already existent entity or at the end of vector otherwise
-////  if (aEntIter == myEntityAttrMap.end())  // no such entity => should be created
-////    aParamIter = myParams.end();
-////  else {  // the entity already exists
-////    aEntPos = Search(aEntIter->second, myEntities);
-////    int aParamPos = Search(myEntities[aEntPos].param[0], myParams);
-////    aParamIter = myParams.begin() + aParamPos;
-////  }
-////  const bool isEntExists = (aEntIter != myEntityAttrMap.end());  // defines that the entity already exists
-////  const bool isNeedToSolve = myNeedToSolve;
-////  myNeedToSolve = false;
-////
-////  if (isEntExists) {
-////    // Verify that the entity is not used by "Rigid" constraint.
-////    // If it is used, the object should not move.
-////    std::vector<std::set<Slvs_hEntity> >::iterator aCoincIter = myCoincidentPoints.begin();
-////    for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++)
-////      if (aCoincIter->find(aEntIter->second) != aCoincIter->end())
-////        break;
-////    std::set<Slvs_hEntity> aCoincident;
-////    if (aCoincIter != myCoincidentPoints.end()) {
-////      aCoincident = *aCoincIter;
-////      aCoincident.erase(aEntIter->second);
-////
-////      std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-////      for (; aConstrIter != myConstraints.end(); aConstrIter++)
-////        if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
-////            aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
-////          myNeedToSolve = true;
-////          return aEntIter->second;
-////        }
-////    }
-////  }
-////
-////  // Look over supported types of entities
-////  Slvs_Entity aNewEntity;
-////  aNewEntity.h = SLVS_E_UNKNOWN;
-////
-////  // Point in 3D
-////  std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
-////      theEntity);
-////  if (aPoint) {
-////    Slvs_hParam aX = changeParameter(aPoint->x(), aParamIter);
-////    Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter);
-////    Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter);
-////    if (!isEntExists) // New entity
-////      aNewEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ);
-////  } else {
-////    // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
-////    if (myWorkplane.h == SLVS_E_UNKNOWN)
-////      return SLVS_E_UNKNOWN;
-////
-////    // Point in 2D
-////    std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-////        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
-////    if (aPoint2D) {
-////      Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter);
-////      Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter);
-////      if (!isEntExists) // New entity
-////        aNewEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV);
-////    } else {
-////      // Scalar value (used for the distance entities)
-////      AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
-////      if (aScalar) {
-////        Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter);
-////        if (!isEntExists) // New entity
-////          aNewEntity = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue);
-////      }
-////    }
-////  }
-////  /// \todo Other types of entities
-////
-////  Slvs_hEntity aResult = SLVS_E_UNKNOWN; // Unsupported or wrong entity type
-////
-////  if (isEntExists) {
-////    myNeedToSolve = myNeedToSolve || isNeedToSolve;
-////    aResult = aEntIter->second;
-////  } else if (aNewEntity.h != SLVS_E_UNKNOWN) {
-////    myEntities.push_back(aNewEntity);
-////    myEntOfConstr.push_back(false);
-////    myEntityAttrMap[theEntity] = aNewEntity.h;
-////    aResult = aNewEntity.h;
-////  }
-////
-////  // If the attribute was changed by the user, we need to fix it before solving
-////  if (myNeedToSolve && theEntity->isImmutable())
-////    addTemporaryConstraintWhereDragged(theEntity, false);
-////
-////  return aResult;
-////}
-////
-////// ============================================================================
-//////  Function: changeEntity
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update the element defined by the feature affected by any constraint
-////// ============================================================================
-////Slvs_hEntity SketchSolver_Group::changeEntityFeature(FeaturePtr theEntity)
-////{
-////  if (!theEntity->data()->isValid())
-////    return SLVS_E_UNKNOWN;
-////  // If the entity is already in the group, try to find it
-////  std::map<FeaturePtr, Slvs_hEntity>::const_iterator aEntIter = myEntityFeatMap.find(theEntity);
-////  // defines that the entity already exists
-////  const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end());
-////  
-////  Slvs_Entity aNewEntity;
-////  aNewEntity.h = SLVS_E_UNKNOWN;
-////
-////  // SketchPlugin features
-////  std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
-////      SketchPlugin_Feature>(theEntity);
-////  if (aFeature) {  // Verify the feature by its kind
-////    const std::string& aFeatureKind = aFeature->getKind();
-////    AttributePtr anAttribute;
-////
-////    // Line
-////    if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aStart = changeEntity(anAttribute);
-////
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aEnd = changeEntity(anAttribute);
-////
-////      if (!isEntExists) // New entity
-////        aNewEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd);
-////    }
-////    // Circle
-////    else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aCenter = changeEntity(anAttribute);
-////
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aRadius = changeEntity(anAttribute);
-////
-////      if (!isEntExists) // New entity
-////        aNewEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter,
-////                                     myWorkplane.normal, aRadius);
-////    }
-////    // Arc
-////    else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aCenter = changeEntity(anAttribute);
-////
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aStart = changeEntity(anAttribute);
-////
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aEnd = changeEntity(anAttribute);
-////
-////      if (!isEntExists)
-////        aNewEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h,
-////                                          myWorkplane.normal, aCenter, aStart, aEnd);
-////    }
-////    // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-////    else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
-////      anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
-////      if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
-////      Slvs_hEntity aPoint = changeEntity(anAttribute);
-////
-////      if (isEntExists)
-////        return aEntIter->second;
-////
-////      // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
-////      myEntityFeatMap[theEntity] = aPoint;
-////      myNeedToSolve = true;
-////      return aPoint;
-////    }
-////  }
-////  /// \todo Other types of features
-////
-////  if (isEntExists)
-////    return aEntIter->second;
-////
-////  if (aNewEntity.h != SLVS_E_UNKNOWN) {
-////    myEntities.push_back(aNewEntity);
-////    myEntOfConstr.push_back(false);
-////    myEntityFeatMap[theEntity] = aNewEntity.h;
-////    myNeedToSolve = true;
-////    return aNewEntity.h;
-////  }
-////
-////  // Unsupported or wrong entity type
-////  return SLVS_E_UNKNOWN;
-////}
-
 // ============================================================================
 //  Function: addWorkplane
 //  Class:    SketchSolver_Group
@@ -1356,33 +341,6 @@ bool SketchSolver_Group::updateWorkplane()
   return myWorkplaneID > 0;
 }
 
-////// ============================================================================
-//////  Function: changeParameter
-//////  Class:    SketchSolver_Group
-//////  Purpose:  create/update value of parameter
-////// ============================================================================
-////Slvs_hParam SketchSolver_Group::changeParameter(
-////    const double& theParam, std::vector<Slvs_Param>::const_iterator& thePrmIter)
-////{
-////  if (thePrmIter != myParams.end()) {  // Parameter should be updated
-////    int aParamPos = thePrmIter - myParams.begin();
-////    if (fabs(thePrmIter->val - theParam) > tolerance) {
-////      myNeedToSolve = true;  // parameter is changed, need to resolve constraints
-////      myParams[aParamPos].val = theParam;
-////    }
-////    thePrmIter++;
-////    return myParams[aParamPos].h;
-////  }
-////
-////  // Newly created parameter
-////  Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam);
-////  myParams.push_back(aParam);
-////  myNeedToSolve = true;
-////  // The list of parameters is changed, move iterator to the end of the list to avoid problems
-////  thePrmIter = myParams.end();
-////  return aParam.h;
-////}
-
 // ============================================================================
 //  Function: resolveConstraints
 //  Class:    SketchSolver_Group
@@ -1504,161 +462,6 @@ bool SketchSolver_Group::isConsistent()
   return aResult;
 }
 
-////// ============================================================================
-//////  Function: updateAttribute
-//////  Class:    SketchSolver_Group
-//////  Purpose:  update features of sketch after resolving constraints
-////// ============================================================================
-////bool SketchSolver_Group::updateAttribute(
-////    std::shared_ptr<ModelAPI_Attribute> theAttribute, const Slvs_hEntity& theEntityID)
-////{
-////  // Search the position of the first parameter of the entity
-////  int anEntPos = Search(theEntityID, myEntities);
-////  int aFirstParamPos = Search(myEntities[anEntPos].param[0], myParams);
-////
-////  // Look over supported types of entities
-////
-////  // Point in 3D
-////  std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
-////      theAttribute);
-////  if (aPoint) {
-////    if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance
-////        || fabs(aPoint->y() - myParams[aFirstParamPos + 1].val) > tolerance
-////        || fabs(aPoint->z() - myParams[aFirstParamPos + 2].val) > tolerance) {
-////      aPoint->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val,
-////                       myParams[aFirstParamPos + 2].val);
-////      return true;
-////    }
-////    return false;
-////  }
-////
-////  // Point in 2D
-////  std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-////      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
-////  if (aPoint2D) {
-////    if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance
-////        || fabs(aPoint2D->y() - myParams[aFirstParamPos + 1].val) > tolerance) {
-////      aPoint2D->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val);
-////      return true;
-////    }
-////    return false;
-////  }
-////
-////  // Scalar value
-////  AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-////  if (aScalar) {
-////    if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) {
-////      aScalar->setValue(myParams[aFirstParamPos].val);
-////      return true;
-////    }
-////    return false;
-////  }
-////
-////  /// \todo Support other types of entities
-////  return false;
-////}
-////
-////// ============================================================================
-//////  Function: updateEntityIfPossible
-//////  Class:    SketchSolver_Group
-//////  Purpose:  search the entity in this group and update it
-////// ============================================================================
-////void SketchSolver_Group::updateEntityIfPossible(
-////    std::shared_ptr<ModelAPI_Attribute> theEntity)
-////{
-////  if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) {
-////    // If the attribute is a point and it is changed (the group needs to rebuild),
-////    // probably user has dragged this point into this position,
-////    // so it is necessary to add constraint which will guarantee the point will not change
-////
-////    // Store myNeedToSolve flag to verify the entity is really changed
-////    bool aNeedToSolveCopy = myNeedToSolve;
-////    myNeedToSolve = false;
-////
-////    changeEntity(theEntity);
-////
-////    if (myNeedToSolve)  // the entity is changed
-////    {
-////      // Verify the entity is a point and add temporary constraint of permanency
-////      std::shared_ptr<GeomDataAPI_Point> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point>(
-////          theEntity);
-////      std::shared_ptr<GeomDataAPI_Point2D> aPoint2D = std::dynamic_pointer_cast<
-////          GeomDataAPI_Point2D>(theEntity);
-////      if (aPoint || aPoint2D)
-////        addTemporaryConstraintWhereDragged(theEntity);
-////    }
-////
-////    // Restore flag of changes
-////    myNeedToSolve = myNeedToSolve || aNeedToSolveCopy;
-////
-////    if (myNeedToSolve)
-////      updateRelatedConstraints(theEntity);
-////  }
-////}
-////
-////// ============================================================================
-//////  Function: addTemporaryConstraintWhereDragged
-//////  Class:    SketchSolver_Group
-//////  Purpose:  add transient constraint SLVS_C_WHERE_DRAGGED for the entity, 
-//////            which was moved by user
-////// ============================================================================
-////void SketchSolver_Group::addTemporaryConstraintWhereDragged(
-////    std::shared_ptr<ModelAPI_Attribute> theEntity,
-////    bool theAllowToFit)
-////{
-////  // Find identifier of the entity
-////  std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
-////      myEntityAttrMap.find(theEntity);
-////  if (anEntIter == myEntityAttrMap.end())
-////    return;
-////
-////  // Get identifiers of all dragged points
-////  std::set<Slvs_hEntity> aDraggedPntID;
-////  aDraggedPntID.insert(myTempPointWDrgdID);
-////  std::list<Slvs_hConstraint>::const_iterator aTmpCoIter = myTempConstraints.begin();
-////  for (; aTmpCoIter != myTempConstraints.end(); aTmpCoIter++) {
-////    unsigned int aConstrPos = Search(*aTmpCoIter, myConstraints);
-////    if (aConstrPos < myConstraints.size())
-////      aDraggedPntID.insert(myConstraints[aConstrPos].ptA);
-////  }
-////  std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
-////  for (; aConstrIter != myConstraints.end(); aConstrIter++)
-////    if (aConstrIter->type == SLVS_C_WHERE_DRAGGED)
-////      aDraggedPntID.insert(aConstrIter->ptA);
-////  // Find whether there is a point coincident with theEntity, which already has SLVS_C_WHERE_DRAGGED
-////  std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
-////  for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) {
-////    if (aCoPtIter->find(anEntIter->second) == aCoPtIter->end())
-////      continue;  // the entity was not found in current set
-////
-////    // Find one of already created SLVS_C_WHERE_DRAGGED constraints in current set of coincident points
-////    std::set<Slvs_hEntity>::const_iterator aDrgIter = aDraggedPntID.begin();
-////    for (; aDrgIter != aDraggedPntID.end(); aDrgIter++)
-////      if (aCoPtIter->find(*aDrgIter) != aCoPtIter->end())
-////        return;  // the SLVS_C_WHERE_DRAGGED constraint already exists
-////  }
-////  if (aDraggedPntID.find(anEntIter->second) != aDraggedPntID.end())
-////    return;
-////
-////  // If this is a first dragged point, its parameters should be placed 
-////  // into Slvs_System::dragged field to avoid system inconsistense
-////  if (myTempPointWhereDragged.empty() && theAllowToFit) {
-////    int anEntPos = Search(anEntIter->second, myEntities);
-////    Slvs_hParam* aDraggedParam = myEntities[anEntPos].param;
-////    for (int i = 0; i < 4; i++, aDraggedParam++)
-////      if (*aDraggedParam != 0)
-////        myTempPointWhereDragged.push_back(*aDraggedParam);
-////    myTempPointWDrgdID = myEntities[anEntPos].h;
-////    return;
-////  }
-////
-////  // Create additional SLVS_C_WHERE_DRAGGED constraint if myTempPointWhereDragged field is not empty
-////  Slvs_Constraint aWDConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED,
-////                                                  myWorkplane.h, 0.0, anEntIter->second, 0, 0, 0);
-////  myConstraints.push_back(aWDConstr);
-////  myTempConstraints.push_back(aWDConstr.h);
-////}
-
 // ============================================================================
 //  Function: removeTemporaryConstraints
 //  Class:    SketchSolver_Group
@@ -1673,6 +476,7 @@ void SketchSolver_Group::removeTemporaryConstraints()
   std::set<Slvs_hEntity> aRemEnt;
   std::set<Slvs_hConstraint> aRemCon;
   myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
+  myStorage->setNeedToResolve(false);
 }
 
 // ============================================================================
@@ -1693,289 +497,3 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
   if (aCIter != myConstraints.end())
     myConstraints.erase(aCIter);
 }
-
-////// ============================================================================
-//////  Function: removeEntitiesById
-//////  Class:    SketchSolver_Group
-//////  Purpose:  Removes specified entities and their parameters
-////// ============================================================================
-////void SketchSolver_Group::removeEntitiesById(const std::set<Slvs_hEntity>& theEntities)
-////{
-////  std::set<Slvs_hEntity>::const_reverse_iterator aRemIter = theEntities.rbegin();
-////  for (; aRemIter != theEntities.rend(); aRemIter++) {
-////    unsigned int anEntPos = Search(*aRemIter, myEntities);
-////    if (anEntPos >= myEntities.size())
-////      continue;
-////    if (myEntities[anEntPos].param[0] != 0) {
-////      unsigned int aParamPos = Search(myEntities[anEntPos].param[0], myParams);
-////      if (aParamPos >= myParams.size())
-////        continue;
-////      int aNbParams = 0;
-////      while (myEntities[anEntPos].param[aNbParams] != 0)
-////        aNbParams++;
-////      if (myEntities[anEntPos].param[aNbParams - 1] == myParamMaxID)
-////        myParamMaxID -= aNbParams;
-////      myParams.erase(myParams.begin() + aParamPos, myParams.begin() + aParamPos + aNbParams);
-////      if (*aRemIter == myEntityMaxID)
-////        myEntityMaxID--;
-////    }
-////    myEntities.erase(myEntities.begin() + anEntPos);
-////    myEntOfConstr.erase(myEntOfConstr.begin() + anEntPos);
-////
-////    // Remove entity's ID from the lists of conincident points
-////    std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
-////    for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++)
-////      aCoPtIter->erase(*aRemIter);
-////  }
-////}
-////
-////// ============================================================================
-//////  Function: addCoincidentPoints
-//////  Class:    SketchSolver_Group
-//////  Purpose:  add coincident point the appropriate list of such points
-////// ============================================================================
-////bool SketchSolver_Group::addCoincidentPoints(const Slvs_hEntity& thePoint1,
-////                                                       const Slvs_hEntity& thePoint2)
-////{
-////  std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
-////  std::vector<std::set<Slvs_hEntity> >::iterator aFirstFound = myCoincidentPoints.end();
-////  while (aCoPtIter != myCoincidentPoints.end()) {
-////    bool isFound[2] = {  // indicate which point ID was already in coincidence constraint
-////        aCoPtIter->find(thePoint1) != aCoPtIter->end(), aCoPtIter->find(thePoint2)
-////            != aCoPtIter->end(), };
-////    if (isFound[0] && isFound[1])  // points are already connected by coincidence constraints => no need additional one
-////      return false;
-////    if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) {
-////      if (aFirstFound != myCoincidentPoints.end()) {  // there are two groups of coincident points connected by created constraint => merge them
-////        int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin();
-////        int aCurrentShift = aCoPtIter - myCoincidentPoints.begin();
-////        aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end());
-////        myCoincidentPoints.erase(aCoPtIter);
-////        aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift;
-////        aCoPtIter = myCoincidentPoints.begin() + aCurrentShift;
-////        continue;
-////      } else {
-////        aCoPtIter->insert(isFound[0] ? thePoint2 : thePoint1);
-////        aFirstFound = aCoPtIter;
-////      }
-////    }
-////    aCoPtIter++;
-////  }
-////  // No points were found, need to create new set
-////  if (aFirstFound == myCoincidentPoints.end()) {
-////    std::set<Slvs_hEntity> aNewSet;
-////    aNewSet.insert(thePoint1);
-////    aNewSet.insert(thePoint2);
-////    myCoincidentPoints.push_back(aNewSet);
-////  }
-////
-////  return true;
-////}
-////
-////// ============================================================================
-//////  Function: updateRelatedConstraints
-//////  Class:    SketchSolver_Group
-//////  Purpose:  emit the signal to update constraints
-////// ============================================================================
-////void SketchSolver_Group::updateRelatedConstraints(
-////    std::shared_ptr<ModelAPI_Attribute> theEntity) const
-////{
-////  ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
-////  for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
-////    std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
-////        ->attributes(std::string());
-////
-////    std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
-////    for (; anAttrIter != anAttributes.end(); anAttrIter++) {
-////      bool isUpd = (*anAttrIter == theEntity);
-////      std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
-////          ModelAPI_AttributeRefAttr>(*anAttrIter);
-////      if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity)
-////        isUpd = true;
-////
-////      if (isUpd) {
-////        static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-////        ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
-////        break;
-////      }
-////    }
-////  }
-////}
-////
-////void SketchSolver_Group::updateRelatedConstraintsFeature(
-////    std::shared_ptr<ModelAPI_Feature> theFeature) const
-////{
-////  ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
-////  for (; aConstrIter != myConstraintMap.end(); aConstrIter++) {
-////    std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes = aConstrIter->first->data()
-////        ->attributes(std::string());
-////
-////    std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttributes.begin();
-////    for (; anAttrIter != anAttributes.end(); anAttrIter++) {
-////      std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = std::dynamic_pointer_cast<
-////          ModelAPI_AttributeRefAttr>(*anAttrIter);
-////      if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) {
-////        static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-////        ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent);
-////        break;
-////      }
-////    }
-////  }
-////}
-////
-////// ============================================================================
-//////  Function: updateFilletConstraints
-//////  Class:    SketchSolver_Group
-//////  Purpose:  change fillet arc to be less than 180 degree
-////// ============================================================================
-////void SketchSolver_Group::updateFilletConstraints()
-////{
-////  ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin();
-////  for (; aConstrIter != myConstraintMap.end(); aConstrIter++)
-////    if (aConstrIter->first->getKind() == SketchPlugin_ConstraintFillet::ID()) {
-////      AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-////          aConstrIter->first->data()->attribute(SketchPlugin_ConstraintFillet::ENTITY_C()));
-////      if (!aFilletRefList)
-////        return;
-////      ObjectPtr anArcObj = aFilletRefList->object(2);
-////      std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////          anArcObj->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
-////      std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////          anArcObj->data()->attribute(SketchPlugin_Arc::START_ID()));
-////      std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-////          anArcObj->data()->attribute(SketchPlugin_Arc::END_ID()));
-////      double aCosA = aStart->x() - aCenter->x();
-////      double aSinA = aStart->y() - aCenter->y();
-////      double aCosB = aEnd->x() - aCenter->x();
-////      double aSinB = aEnd->y() - aCenter->y();
-////      if (aCosA * aSinB - aSinA * aCosB <= 0.0) {
-////        anArcObj->data()->blockSendAttributeUpdated(true);
-////        double x = aStart->x();
-////        double y = aStart->y();
-////        aStart->setValue(aEnd->x(), aEnd->y());
-////        aEnd->setValue(x, y);
-////        // Update constraint data
-////        changeFilletConstraint(aConstrIter->first);
-////        anArcObj->data()->blockSendAttributeUpdated(false);
-////      }
-////    }
-////}
-////
-////// ============================================================================
-//////  Function: makeMirrorEntity
-//////  Class:    SketchSolver_Group
-//////  Purpose:  change entities parameters to make them symmetric relating to the mirror line
-////// ============================================================================
-////void SketchSolver_Group::makeMirrorEntity(const Slvs_hEntity& theBase,
-////                                                    const Slvs_hEntity& theMirror,
-////                                                    const Slvs_hEntity& theMirrorLine)
-////{
-////  Slvs_Entity aBase = myEntities[Search(theBase, myEntities)];
-////  Slvs_Entity aMirror = myEntities[Search(theMirror, myEntities)];
-////  int i = 0;
-////  while (aBase.point[i] != 0 && aMirror.point[i] != 0) {
-////    makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine);
-////    i++;
-////  }
-////  if (aBase.param[0] != 0 && aMirror.param[0] != 0) { // this is a point, copy it
-////    Slvs_Entity aMirrorLine = myEntities[Search(theMirrorLine, myEntities)];
-////    std::shared_ptr<GeomAPI_XY> aLinePoints[2];
-////    for (i = 0; i < 2; i++) {
-////      Slvs_Entity aPoint = myEntities[Search(aMirrorLine.point[i], myEntities)];
-////      int aParamPos = Search(aPoint.param[0], myParams);
-////      aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
-////          new GeomAPI_XY(myParams[aParamPos].val, myParams[1+aParamPos].val));
-////    }
-////    int aBaseParamPos = Search(aBase.param[0], myParams);
-////    int aMirrorParamPos = Search(aMirror.param[0], myParams);
-////    std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(
-////        new GeomAPI_XY(myParams[aBaseParamPos].val, myParams[1+aBaseParamPos].val));
-////
-////    // direction of a mirror line
-////    std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
-////        new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
-////    // orthogonal direction
-////    aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
-////
-////    std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
-////        new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
-////    double aDist = aVec->dot(aDir->xy());
-////    std::shared_ptr<GeomAPI_XY> aMirrorPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
-////
-////    myParams[aMirrorParamPos].val = aMirrorPoint->x();
-////    myParams[1+aMirrorParamPos].val = aMirrorPoint->y();
-////  }
-////}
-////
-////// ============================================================================
-//////  Function: calculateMiddlePoint
-//////  Class:    SketchSolver_Group
-//////  Purpose:  calculates middle point on line or arc
-////// ============================================================================
-////void SketchSolver_Group::calculateMiddlePoint(
-////    const Slvs_hEntity& theEntity,
-////    double& theX,
-////    double& theY) const
-////{
-////  int anInd = Search(theEntity, myEntities);
-////  if (myEntities[anInd].type == SLVS_E_LINE_SEGMENT) {
-////    int aLineParams[2];
-////    for (int i = 0; i < 2; i++) {
-////      int aPtPos = Search(myEntities[anInd].point[i], myEntities);
-////      aLineParams[i] = Search(myEntities[aPtPos].param[0], myParams);
-////    }
-////    theX = 0.5 * (myParams[aLineParams[0]].val + myParams[aLineParams[1]].val);
-////    theY = 0.5 * (myParams[1 + aLineParams[0]].val + myParams[1 + aLineParams[1]].val);
-////  } else if (myEntities[anInd].type == SLVS_E_ARC_OF_CIRCLE) {
-////    double anArcPoint[3][2];
-////    for (int i = 0; i < 3; i++) {
-////      int aPtPos = Search(myEntities[anInd].point[i], myEntities);
-////      int anArcParam = Search(myEntities[aPtPos].param[0], myParams);
-////      anArcPoint[i][0] = myParams[anArcParam].val;
-////      anArcPoint[i][1] = myParams[1 + anArcParam].val;
-////    }
-////    // project last point of arc on the arc
-////    double x = anArcPoint[1][0] - anArcPoint[0][0];
-////    double y = anArcPoint[1][1] - anArcPoint[0][1];
-////    double aRad = sqrt(x*x + y*y);
-////    x = anArcPoint[2][0] - anArcPoint[0][0];
-////    y = anArcPoint[2][1] - anArcPoint[0][1];
-////    double aNorm = sqrt(x*x + y*y);
-////    if (aNorm >= tolerance) {
-////      anArcPoint[2][0] = anArcPoint[0][0] + x * aRad / aNorm;
-////      anArcPoint[2][1] = anArcPoint[0][1] + y * aRad / aNorm;
-////    }
-////
-////    x = anArcPoint[1][0] + anArcPoint[2][0] - 2.0 * anArcPoint[0][0];
-////    y = anArcPoint[1][1] + anArcPoint[2][1] - 2.0 * anArcPoint[0][1];
-////    aNorm = sqrt(x*x + y*y);
-////    if (aNorm >= tolerance) {
-////      x *= aRad / aNorm;
-////      y *= aRad / aNorm;
-////    } else { // obtain orthogonal direction
-////      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;
-////  }
-////}
-
-
-// ========================================================
-// =========      Auxiliary functions       ===============
-// ========================================================
-
-template<typename T>
-int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
-{
-  int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
-  int aVecSize = theEntities.size();
-  while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
-    aResIndex--;
-  while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
-    aResIndex++;
-  if (aResIndex == -1)
-    aResIndex = aVecSize;
-  return aResIndex;
-}
index 6e53af522829e3cd5f19c5d541c075a0b114f46a..dceff0581bcc2cf69baa1080e1f6505fed21253e 100644 (file)
@@ -75,21 +75,6 @@ class SketchSolver_Group
    *  \return \c true if the constraint added or updated successfully
    */
   bool changeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
-////  /** \brief Adds or updates a rigid constraint in the group
-////   *  \param[in] theConstraint constraint to be changed
-////   *  \return \c true if the constraint added or updated successfully
-////   */
-////  bool changeRigidConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
-////  /** \brief Adds or updates a mirror constraint in the group
-////   *  \param[in] theConstraint constraint to be changed
-////   *  \return \c true if the constraint added or updated successfully
-////   */
-////  bool changeMirrorConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
-////  /** \brief Adds or updates a fillet constraint in the group
-////   *  \param[in] theConstraint constraint to be changed
-////   *  \return \c true if the constraint added or updated successfully
-////   */
-////  bool changeFilletConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
 
   /** \brief Updates the data corresponding the specified feature
    *  \param[in] theFeature the feature to be updated
@@ -124,11 +109,6 @@ class SketchSolver_Group
    *  \return \c true if workplane updated successfully, \c false if workplane parameters are not consistent
    */
   bool updateWorkplane();
-////
-////  /** \brief If the entity is in this group it will updated
-////   *  \param[in] theEntity attribute, which values should update SolveSpace entity
-////   */
-////  void updateEntityIfPossible(std::shared_ptr<ModelAPI_Attribute> theEntity);
 
   /** \brief Searches invalid features and constraints in the group and removes them
    *  \return \c false if the group several constraints were removed
@@ -149,81 +129,12 @@ class SketchSolver_Group
    *  \return \c false when no need to solve constraints
    */
   bool resolveConstraints();
-////
-////  /** \brief Searches the constraints built on the entity and emit the signal to update them
-////   *  \param[in] theEntity attribute of the constraint
-////   */
-////  void updateRelatedConstraints(std::shared_ptr<ModelAPI_Attribute> theEntity) const;
-////  /** \brief Searches the constraints built on the entity and emit the signal to update them
-////   *  \param[in] theFeature feature of the constraint
-////   */
-////  void updateRelatedConstraintsFeature(std::shared_ptr<ModelAPI_Feature> theFeature) const;
-////
-////  /** \brief Adds or updates an entity in the group
-////   *
-////   *  The parameters of entity will be parsed and added to the list of SolveSpace parameters.
-////   *  Parameters of certain entity will be placed sequentially in the list.
-////   *
-////   *  \param[in] theEntity the object of constraint
-////   *  \return identifier of changed entity or 0 if entity could not be changed
-////   */
-////  Slvs_hEntity changeEntity(std::shared_ptr<ModelAPI_Attribute> theEntity);
-////  Slvs_hEntity changeEntityFeature(std::shared_ptr<ModelAPI_Feature> theEntity);
 
 protected:
-////  /** \brief Adds or updates a normal in the group
-////   *
-////   *  Normal is a special entity in SolveSpace, which defines a direction in 3D and
-////   *  a rotation about this direction. So, SolveSpace represents normals as unit quaternions.
-////   *
-////   *  To define a normal there should be specified two coordinate axis
-////   *  on the plane transversed to created normal.
-////   *
-////   *  \param[in] theDirX first coordinate axis of the plane
-////   *  \param[in] theNorm attribute for the normal (used to identify newly created entity)
-////   *  \return identifier of created or updated normal
-////   */
-////  Slvs_hEntity changeNormal(std::shared_ptr<ModelAPI_Attribute> theDirX,
-////                            std::shared_ptr<ModelAPI_Attribute> theNorm);
-////
-////  /** \brief Adds or updates a parameter in the group
-////   *  \param[in] theParam   the value of parameter
-////   *  \param[in] thePrmIter the cell in the list of parameters which should be changed
-////   *                        (the iterator will be increased if it does not reach the end of the list)
-////   *  \return identifier of changed parameter; when the parameter cannot be created, returned ID is 0
-////   */
-////  Slvs_hParam changeParameter(const double& theParam,
-////                              std::vector<Slvs_Param>::const_iterator& thePrmIter);
-////
-////  /** \brief Removes specified entities and their parameters
-////   *  \param[in] theEntities  list of IDs of the entities to be removed
-////   */
-////  void removeEntitiesById(const std::set<Slvs_hEntity>& theEntities);
-
   /** \brief Removes constraints from the group
    *  \param[in] theConstraint constraint to be removed
    */
   void removeConstraint(ConstraintPtr theConstraint);
-////
-////  /** \brief Change values of attribute by parameters received from SolveSpace solver
-////   *  \param[in,out] theAttribute pointer to the attribute to be changed
-////   *  \param[in]     theEntityID  identifier of SolveSpace entity, which contains updated data
-////   *  \return \c true if the attribute's value has changed
-////   */
-////  bool updateAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute,
-////                       const Slvs_hEntity& theEntityID);
-////
-////  /// \brief Update arc of fillet to be less than 180 degree
-////  void updateFilletConstraints();
-////
-////  /** \brief Adds a constraint for a point which should not be changed during computations
-////   *  \param[in] theEntity     the base for the constraint
-////   *  \param[in] theAllowToFit this flag shows that the entity may be placed into 
-////   *                           the 'dragged' field of SolveSpace solver, so this entity 
-////   *                           may be changed a little during solution
-////   */
-////  void addTemporaryConstraintWhereDragged(std::shared_ptr<ModelAPI_Attribute> theEntity,
-////                                          bool theAllowToFit = true);
 
   /** \brief Remove all temporary constraint after computation finished
    *  \param[in] theRemoved  indexes of constraints to be removed. If empty, all temporary constraints should be deleted
@@ -236,61 +147,6 @@ private:
    *  \return \c true if success, \c false if workplane parameters are not consistent
    */
   bool addWorkplane(CompositeFeaturePtr theSketch);
-////
-////  /** \brief Add the entities of constraint for points coincidence into the appropriate list
-////   *  \param[in] thePoint1 identifier of the first point
-////   *  \param[in] thePoint2 identifier of the second point
-////   *  \return \c true if the points are added successfully, and 
-////   *          \c false if the constraint is the extra one (should not be created in SolveSpace)
-////   */
-////  bool addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
-////
-////  /** \brief Change entities parameters to make them symmetric relating to the mirror line
-////   *  \param[in] theBase        entity to be mirrored
-////   *  \param[in] theMirror      a mirrored object
-////   *  \param[in] theMirrorLine  a mirror line
-////   */
-////  void makeMirrorEntity(const Slvs_hEntity& theBase,
-////                        const Slvs_hEntity& theMirror,
-////                        const Slvs_hEntity& theMirrorLine);
-////
-////  /** \brief Calculates middle point on line or arc
-////   *  \param[in]  theEntity  identifier of line or arc
-////   *  \param[out] theX       X value of middle point
-////   *  \param[out] theY       Y value of middle point
-////   */
-////  void calculateMiddlePoint(const Slvs_hEntity& theEntity,
-////                            double& theX, double& theY) const;
-////
-//// private:
-////  // SolveSpace entities
-////  Slvs_hGroup myID;            ///< the index of the group
-////  Slvs_Entity myWorkplane;     ///< Workplane for the current group
-////  std::vector<Slvs_Param> myParams;        ///< List of parameters of the constraints
-////  Slvs_hParam myParamMaxID;    ///< Actual maximal ID of parameters (not equal to myParams size)
-////  std::vector<Slvs_Entity> myEntities;      ///< List of entities of the constaints
-////  std::vector<bool> myEntOfConstr; ///< Flags show that certain entity used in constraints
-////  Slvs_hEntity myEntityMaxID;   ///< Actual maximal ID of entities (not equal to myEntities size)
-////  std::vector<Slvs_Constraint> myConstraints;   ///< List of constraints in SolveSpace format
-////  Slvs_hConstraint myConstrMaxID;  ///< Actual maximal ID of constraints (not equal to myConstraints size)
-////  bool myNeedToSolve;  ///< Indicator that something changed in the group and constraint system need to be rebuilt
-////
-////  SketchSolver_Solver myConstrSolver;  ///< Solver for set of equations obtained by constraints
-////
-////  std::vector<Slvs_hParam> myTempPointWhereDragged;  ///< Parameters of one of the points which is moved by user
-////  Slvs_hEntity myTempPointWDrgdID;      ///< Identifier of such point
-////  std::list<Slvs_hConstraint> myTempConstraints;  ///< The list of identifiers of temporary constraints (SLVS_C_WHERE_DRAGGED) applied for all other points moved by user
-////
-////  // SketchPlugin entities
-////  std::shared_ptr<ModelAPI_CompositeFeature> mySketch;        ///< Equivalent to workplane
-////  ConstraintMap myConstraintMap;  ///< The map between SketchPlugin and SolveSpace constraints
-////  std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity> myEntityAttrMap;  ///< The map between "attribute" parameters of constraints and their equivalent SolveSpace entities
-////  std::map<FeaturePtr, Slvs_hEntity> myEntityFeatMap;  ///< The map between "feature" parameters of constraints and their equivalent SolveSpace entities
-////
-////  // Conincident items
-////  std::vector<std::set<Slvs_hEntity> > myCoincidentPoints;  ///< Stores the lists of identifiers of coincident points (to avoid unnecessary coincidence constraints)
-////  std::set<std::shared_ptr<SketchPlugin_Constraint> > myExtraCoincidence;  ///< Additional coincidence constraints which are not necessary (coincidence between points already done
-////                                                                             ///< by other constraints) but created by GUI tools. Useful when some coincidence constraints were removed
 
 private:
   Slvs_hGroup myID; ///< Index of the group
index eabf3a5fa05a4f44c493ef661f80db746f313e61..244bc1c7d839ce514462ae7286490bd63fb8c5cb 100644 (file)
@@ -403,6 +403,8 @@ int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
 {
   int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
   int aVecSize = theEntities.size();
+  if (theEntities.empty())
+    return 1;
   while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
     aResIndex--;
   while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)