]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Make Mirror constraint visible in GUI
authorazv <azv@opencascade.com>
Thu, 26 Mar 2015 13:14:20 +0000 (16:14 +0300)
committerazv <azv@opencascade.com>
Fri, 27 Mar 2015 07:42:14 +0000 (10:42 +0300)
src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp
src/SketchPlugin/SketchPlugin_ConstraintMirror.h
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/SketchSolver_ConstraintGroup.cpp
src/SketchSolver/SketchSolver_ConstraintGroup.h

index f0da5515fa7a63ee32484a78dcfb5d5f2437f3bd..fde907d815e9e9616819398e4e1263cd4b610fa1 100644 (file)
@@ -10,7 +10,9 @@
 #include <ModelAPI_Data.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Sketch.h>
@@ -28,33 +30,96 @@ void SketchPlugin_ConstraintMirror::initAttributes()
   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
   data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId());
+  AttributeSelectionListPtr aSelection = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    SketchPlugin_ConstraintMirror::MIRROR_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+  aSelection->setSelectionType("EDGE");
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C());
 }
 
 void SketchPlugin_ConstraintMirror::execute()
 {
-  // Objects to be mirrored will be created here
+  AttributeSelectionListPtr aMirrorObjectRefs =
+      selectionList(SketchPlugin_ConstraintMirror::MIRROR_LIST_ID());
+  if (!aMirrorObjectRefs->isInitialized())
+    return;
+
   std::shared_ptr<ModelAPI_Data> aData = data();
   AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
       aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
-  if (!aRefListOfShapes->isInitialized())
-    return ;
-
   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
       aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
-  // Check consistency of initial list and mirrored list
   std::list<ObjectPtr> anInitialList =  aRefListOfShapes->list();
   std::list<ObjectPtr> aMirroredList =  aRefListOfMirrored->list();
+  std::vector<bool> isUsed(anInitialList.size(), false);
+  // add new items to the list
+  for(int anInd = 0; anInd < aMirrorObjectRefs->size(); anInd++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aMirrorObjectRefs->value(anInd);
+    std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
+    std::vector<bool>::iterator aUsedIt = isUsed.begin();
+    for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
+      if (*anIt == aSelect->context()) {
+        *aUsedIt = true;
+        break;
+      }
+    if (anIt == anInitialList.end())
+      aRefListOfShapes->append(aSelect->context());
+  }
+  // remove unused items
   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
   std::list<ObjectPtr>::iterator aMirrorIter = aMirroredList.begin();
+  std::vector<bool>::iterator aUsedIter = isUsed.begin();
+  for (; aUsedIter != isUsed.end(); aUsedIter++) {
+    if (!(*aUsedIter)) {
+      aRefListOfShapes->remove(*anInitIter);
+      if (aMirrorIter != aMirroredList.end()) {
+        aRefListOfMirrored->remove(*aMirrorIter);
+        // remove the corresponding feature from the sketch
+        ResultConstructionPtr aRC =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirrorIter);
+        DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+        FeaturePtr aFeature =  aDoc ? std::dynamic_pointer_cast<SketchPlugin_Feature>(
+              aDoc->feature(aRC)) : FeaturePtr();
+        if (aFeature)
+          aDoc->removeFeature(aFeature);
+      }
+    }
+    if (anInitIter != anInitialList.end())
+      anInitIter++;
+    if (aMirrorIter != aMirroredList.end())
+      aMirrorIter++;
+  }
+
+  // Check consistency of initial list and mirrored list
+  anInitialList =  aRefListOfShapes->list();
+  anInitIter = anInitialList.begin();
+  aMirrorIter = aMirroredList.begin();
   int indFirstWrong = 0; // index of element starts difference in the lists
   std::set<int> anInvalidInd; // list of indices of removed features
   std::shared_ptr<SketchPlugin_Feature> aFeatureIn, aFeatureOut;
   for ( ; anInitIter != anInitialList.end(); anInitIter++, indFirstWrong++) {
     // Add features and store indices of objects to remove
     aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anInitIter);
-    aFeatureOut = aMirrorIter != aMirroredList.end() ? 
-        std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter) :
-        std::shared_ptr<SketchPlugin_Feature>();
+    ResultConstructionPtr aRCIn;
+    if (!aFeatureIn) {
+      aRCIn = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
+      if (aRCIn)
+        aFeatureIn = std::dynamic_pointer_cast<SketchPlugin_Feature>(
+            aRCIn->document()->feature(aRCIn));
+    }
+    if (aMirrorIter == aMirroredList.end())
+      aFeatureOut = std::shared_ptr<SketchPlugin_Feature>();
+    else {
+      aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirrorIter);
+      if (!aFeatureOut) {
+        ResultConstructionPtr aRC =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anInitIter);
+        if (aRC)
+          aFeatureOut = std::dynamic_pointer_cast<SketchPlugin_Feature>(
+              aRC->document()->feature(aRC));
+      }
+    }
     if (!aFeatureIn) {
       if (aFeatureOut)
         break; // the lists are inconsistent
@@ -66,7 +131,20 @@ void SketchPlugin_ConstraintMirror::execute()
       // There is no mirrored object yet, create it
       FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind());
       aFeatureIn->data()->copyTo(aNewFeature->data());
-      aRefListOfMirrored->append(aNewFeature);
+      aNewFeature->execute();
+
+      std::shared_ptr<GeomAPI_Shape> aShapeIn = aRCIn->shape();
+      const std::list<ResultPtr>& aResults = aNewFeature->results();
+      std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+      for (; anIt != aResults.end(); anIt++) {
+        ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
+        if (!aRC) continue;
+        std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
+        if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
+            (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
+            (aShapeIn->isFace() && aShapeOut->isFace()))
+          aRefListOfMirrored->append(aRC);
+      }
       continue;
     }
     if (aFeatureIn->getKind() != aFeatureOut->getKind())
index 841f11abd37718358f0249307d0fd857ac7b3994..69a26ea8f0f51e0b00a36934d5d67e7b56185c57 100644 (file)
@@ -38,6 +38,13 @@ class SketchPlugin_ConstraintMirror : public SketchPlugin_ConstraintBase
     return MY_KIND;
   }
 
+  /// List of objects to be mirrored
+  inline static const std::string& MIRROR_LIST_ID()
+  {
+    static const std::string MY_MIRROR_LIST_ID("ConstraintMirrorList");
+    return MY_MIRROR_LIST_ID;
+  }
+
   /// \brief Creates a new part document if needed
   SKETCHPLUGIN_EXPORT virtual void execute();
 
index 391738b8c3145b36b7813a8fbb8b2afc41863889..114692336bc5e3fe379d4bd20bbb7a0c1832e3ac 100644 (file)
@@ -5,7 +5,7 @@
     <group id="Basic">
       <feature
         id="Sketch"
-        nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence"
+        nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror"
         when_nested="accept abort"
         title="Sketch"
         tooltip="Create a new sketch"
       <feature
         id="SketchConstraintMirror"
         title="Mirror"
-        tooltip="Create constraint mirroring group of objects"
-        internal="1" />
+        tooltip="Create constraint, mirroring group of objects">
+        <sketch_constraint_shape_selector id="ConstraintEntityA" 
+            label="Mirror line" tooltip="Select mirror line" shape_types="edge">
+            <validator id="GeomValidators_Edge" parameters="line"/>
+        </sketch_constraint_shape_selector>
+        <multi_selector id="ConstraintMirrorList" 
+            label="List of objects"
+            tooltip="Select list of mirroring objects"
+            type_choice="Edges">
+        </multi_selector>
+      </feature>
     </group>
     
     <group id="Edit">
index 776be57bdb13a3605bd908e99eff3ba9f50746be..d7f2409d1d05bebc8737beddcd53243020abc71a 100644 (file)
@@ -616,9 +616,11 @@ bool SketchSolver_ConstraintGroup::changeMirrorConstraint(
   // Search this constraint in the current group to update it
   ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
   std::vector<Slvs_Constraint>::iterator aConstrIter;
+  bool isExists = false;
   if (aConstrMapIter != myConstraintMap.end()) {
     int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
     aConstrIter = myConstraints.begin() + aConstrPos;
+    isExists = true;
   }
 
   // Get constraint type and verify the constraint parameters are correct
@@ -648,128 +650,155 @@ bool SketchSolver_ConstraintGroup::changeMirrorConstraint(
   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;
+  // 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;
 
-    myConstraintMap[theConstraint] = std::vector<Slvs_hConstraint>();
+  std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+  std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+  if (aBaseList.empty() || aBaseList.size() != aMirroredList.size())
+    return false;
 
-    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);
+  std::vector<Slvs_hConstraint> aNewConstraints;
+  // Fill the list of already mirrored points
+  std::vector<Slvs_Constraint> anOldConstraints;
+  std::map<Slvs_hEntity, Slvs_hEntity> aMirroredPoints;
+  if (isExists) {
+    std::vector<Slvs_hConstraint>::const_iterator aCIter = aConstrMapIter->second.begin();
+    for (; aCIter != aConstrMapIter->second.end(); aCIter++) {
+      int anInd = Search(*aCIter, myConstraints);
+      if (myConstraints[anInd].type != aConstrType)
+        continue;
+      aMirroredPoints[myConstraints[anInd].ptA] = myConstraints[anInd].ptB;
+      anOldConstraints.push_back(myConstraints[anInd]);
+    }
+  }
 
-      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);
-          }
+  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_hConstraint anID = changeMirrorPoints(aBaseEnt, aMirrorEnt,
+          aMirrorLineEnt, anOldConstraints, aMirroredPoints);
+      aNewConstraints.push_back(anID);
+    } 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_hConstraint anID = changeMirrorPoints(myEntities[aBasePos].point[ind],
+              myEntities[aMirrorPos].point[ind], aMirrorLineEnt, anOldConstraints, aMirroredPoints);
+          aNewConstraints.push_back(anID);
+        }
+      } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+        Slvs_hConstraint anID = changeMirrorPoints(myEntities[aBasePos].point[0],
+            myEntities[aMirrorPos].point[0], aMirrorLineEnt, anOldConstraints, aMirroredPoints);
+        aNewConstraints.push_back(anID);
+        // 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);
-          }
+        aBaseArcPoints[2] = aBothMiddlePoints[0];
+        aMirrorArcPoints[2] = aBothMiddlePoints[1];
+        for (int ind = 0; ind < 3; ind++) {
+          Slvs_hConstraint anID = changeMirrorPoints(aBaseArcPoints[ind], aMirrorArcPoints[ind],
+              aMirrorLineEnt, anOldConstraints, aMirroredPoints);
+          aNewConstraints.push_back(anID);
         }
       }
     }
+  }
 
+  // Remove unused constraints
+  std::vector<Slvs_Constraint>::const_iterator anOldCIter = anOldConstraints.begin();
+  for (; anOldCIter != anOldConstraints.end(); anOldCIter++) {
+    int anInd = Search(anOldCIter->h, myConstraints);
+    myConstraints.erase(myConstraints.begin() + anInd);
+  }
+  myConstraintMap[theConstraint] = aNewConstraints;
+
+  if (!isExists) {
     // 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);
+    // firstly check the line is not fixed yet
+    bool isFixed[2] = {false, false};
+    std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+    for (; aConstrIter != myConstraints.end() && !(isFixed[0] && isFixed[1]); aConstrIter++)
+      if (aConstrIter->type == SLVS_C_WHERE_DRAGGED) {
+        if (aConstrIter->ptA == myEntities[aMirrorLinePos].point[0])
+          isFixed[0] = true;
+        else if (aConstrIter->ptA == myEntities[aMirrorLinePos].point[1])
+          isFixed[1] = true;
+      }
+    // add new rigid constraints
+    if (!isFixed[0]) {
+      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);
+    }
+    if (!isFixed[1]) {
+      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++) {
@@ -2146,6 +2175,44 @@ void SketchSolver_ConstraintGroup::makeMirrorEntity(const Slvs_hEntity& theBase,
   }
 }
 
+// ============================================================================
+//  Function: changeMirrorPoints
+//  Class:    SketchSolver_ConstraintGroup
+//  Purpose:  creates/updates mirror constraint for two points
+// ============================================================================
+Slvs_hConstraint SketchSolver_ConstraintGroup::changeMirrorPoints(
+    const Slvs_hEntity& theBasePoint,
+    const Slvs_hEntity& theMirrorPoint,
+    const Slvs_hEntity& theMirrorLine,
+    std::vector<Slvs_Constraint>&  thePrevConstr,
+    std::map<Slvs_hEntity, Slvs_hEntity>& thePrevMirror)
+{
+  std::map<Slvs_hEntity, Slvs_hEntity>::iterator aMapIter = thePrevMirror.find(theBasePoint);
+  if (aMapIter != thePrevMirror.end()) {
+    thePrevMirror.erase(aMapIter);
+    std::vector<Slvs_Constraint>::const_iterator anIter = thePrevConstr.begin();
+    for (; anIter != thePrevConstr.end(); anIter++)
+      if (anIter->ptA == theBasePoint) {
+        if (anIter->ptB != theMirrorPoint) {
+          int aConstrInd = Search(anIter->h, myConstraints);
+          myConstraints[aConstrInd].ptB = theMirrorPoint;
+          myConstraints[aConstrInd].entityA = theMirrorLine;
+        }
+        Slvs_hConstraint aResult = anIter->h;
+        thePrevConstr.erase(anIter);
+        return aResult;
+      }
+  }
+
+  // Newly created constraint
+  Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+      ++myConstrMaxID, myID, SLVS_C_SYMMETRIC_LINE, myWorkplane.h, 0.0,
+      theBasePoint, theMirrorPoint, theMirrorLine, SLVS_E_UNKNOWN);
+  myConstraints.push_back(aConstraint);
+  return aConstraint.h;
+}
+
+
 // ============================================================================
 //  Function: calculateMiddlePoint
 //  Class:    SketchSolver_ConstraintGroup
index e24d93a7d2bf0e6814e89de8e5cbebe7e24a4e28..73dc23d633c878c870d9fe8113f4d63c223af8f4 100644 (file)
@@ -237,6 +237,20 @@ protected:
                         const Slvs_hEntity& theMirror,
                         const Slvs_hEntity& theMirrorLine);
 
+  /** \brief Creates/updates mirror constraint for two points
+   *  \param[in]     theBasePoint   ID of initial point
+   *  \param[in]     theMirrorPoint ID of the mirroring point
+   *  \param[in]     theMirrorLine  ID of the mirror line
+   *  \param[in]     thePrevConstr  list of previous constraints (the items will be deleted from the list if they are updated)
+   *  \param[in,out] thePrevMirror  list of previously mirrored points (the items will be deleted from the list if they are updated)
+   *  \return ID of created/updated constraint
+   */
+  Slvs_hConstraint changeMirrorPoints(const Slvs_hEntity& theBasePoint,
+                                      const Slvs_hEntity& theMirrorPoint,
+                                      const Slvs_hEntity& theMirrorLine,
+                                      std::vector<Slvs_Constraint>&  thePrevConstr,
+                                      std::map<Slvs_hEntity, Slvs_hEntity>& thePrevMirror);
+
   /** \brief Calculates middle point on line or arc
    *  \param[in]  theEntity  identifier of line or arc
    *  \param[out] theX       X value of middle point