Salome HOME
Make the copies fixed in multi-rotation, multi-translation (issue #1471)
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMirror.cpp
index 6ea42d13ef6ef4d5c475443f36152f2851f2c9ad..509404940e2f6942b78494e952784e9a028461a8 100644 (file)
@@ -1,33 +1,25 @@
 #include <SketchSolver_ConstraintMirror.h>
-#include <SketchSolver_Group.h>
 #include <SketchSolver_Error.h>
+#include <SketchSolver_Manager.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)
+    EntityWrapperPtr& theMirrorLine,
+    std::vector<EntityWrapperPtr>& theBaseEntities,
+    std::vector<EntityWrapperPtr>& 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()) {
+  AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
+  AttributeRefAttrPtr aMirLineRefAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aMirLineAttr);
+  if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->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);
+
+  myType = TYPE(myBaseConstraint);
+  myStorage->update(aMirLineAttr/*, myGroupID*/);
+  theMirrorLine = myStorage->entity(aMirLineAttr);
 
   // Create SolveSpace entity for all features
   AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
@@ -44,20 +36,17 @@ void SketchSolver_ConstraintMirror::getAttributes(
   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;
+    std::vector<EntityWrapperPtr>* 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);
+      aFeature = ModelAPI_Feature::feature(*anIter);
       if (!aFeature)
         continue;
 
-      anEntity = changeEntity(aFeature, aType);
-      aList->push_back(myStorage->getEntity(anEntity));
+      myStorage->update(aFeature/*, myGroupID*/);
+      aList->push_back(myStorage->entity(aFeature));
     }
   }
 
@@ -68,16 +57,14 @@ void SketchSolver_ConstraintMirror::getAttributes(
 void SketchSolver_ConstraintMirror::process()
 {
   cleanErrorMsg();
-  if (!myBaseConstraint || !myStorage || myGroup == 0) {
-    /// TODO: Put error message here
+  if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+    // Not enough parameters are assigned
     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;
+  EntityWrapperPtr aMirrorLine;
+  std::vector<EntityWrapperPtr> aBaseList;
+  std::vector<EntityWrapperPtr> aMirrorList;
   getAttributes(aMirrorLine, aBaseList, aMirrorList);
   if (!myErrorMsg.empty())
     return;
@@ -87,183 +74,61 @@ void SketchSolver_ConstraintMirror::process()
     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);
-      }
+  std::list<ConstraintWrapperPtr> aNewConstraints;
+  SketchSolver_ConstraintType aConstrType = getType();
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+  std::list<ConstraintWrapperPtr> aMirConstrList;
+
+  std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
+  std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
+  for (; aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
+    if ((*aBIt)->type() == ENTITY_ARC) {
+      // add new points on arcs and mirror them
+      EntityWrapperPtr aBasePnt = myStorage->calculateMiddlePoint(*aBIt, 0.5);
+      EntityWrapperPtr aMirrPnt = myStorage->calculateMiddlePoint(*aMIt, 0.5);
+      // point on base arc
+      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
+          CONSTRAINT_PT_ON_CIRCLE, 0.0, aBasePnt, EntityWrapperPtr(), *aBIt);
+      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
+      // point on mirrored arc
+      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
+          CONSTRAINT_PT_ON_CIRCLE, 0.0, aMirrPnt, EntityWrapperPtr(), *aMIt);
+      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
+      // mirror these points
+      aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
+          aConstrType, 0.0, aBasePnt, aMirrPnt, aMirrorLine);
+      aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
     }
+    aNewConstraints = aBuilder->createConstraint(
+        myBaseConstraint, myGroupID, mySketchID, aConstrType,
+        0.0, *aBIt, *aMIt, aMirrorLine);
+    aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
   }
 
-  // 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);
-  }
+  myStorage->addConstraint(myBaseConstraint, aMirConstrList);
 }
 
 
-void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
+void SketchSolver_ConstraintMirror::update()
 {
   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();
-    }
+  AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+    myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+  if (aMirroredRefList->size() != myNumberOfObjects) {
+    remove();
+    process();
+    return;
   }
-  SketchSolver_Constraint::update();
+  adjustConstraint();
 }
 
-bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
+void SketchSolver_ConstraintMirror::adjustConstraint()
 {
-  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();
+  BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
 
-  if (isFullyRemoved) {
-    myFeatureMap.clear();
-    myAttributeMap.clear();
-    myValueMap.clear();
-  } else
-    cleanRemovedEntities();
-  return true;
+  const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
+  std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
+  for (; aCIt != aConstraints.end(); ++aCIt)
+    if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC)
+      aBuilder->adjustConstraint(*aCIt);
 }
-
-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);
-  }
-}
-