]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Fix the problem with unexpected movement of features during Mirror constraint execution
authorazv <azv@opencascade.com>
Fri, 24 Apr 2015 08:20:18 +0000 (11:20 +0300)
committerazv <azv@opencascade.com>
Fri, 24 Apr 2015 08:20:18 +0000 (11:20 +0300)
src/SketchSolver/SketchSolver.h
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.h
src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp
src/SketchSolver/SketchSolver_Group.cpp

index 77bb4029a701f8a8faa5e6174cad5cdba5e0195b..cc5013f6ed163cf32b89d7b19ac2f346652ab826 100644 (file)
@@ -20,4 +20,6 @@
 /// Tolerance for value of parameters
 const double tolerance = 1.e-10;
 
+#define PI 3.1415926535897932
+
 #endif
index 918a8026b8f1e6639146d24724e088dd0b493d2c..efd447ab793487449238d027536ebb96ab5a681f 100644 (file)
@@ -7,6 +7,7 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
+#include <GeomAPI_Dir2d.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeDouble.h>
@@ -677,61 +678,16 @@ void SketchSolver_Constraint::calculateMiddlePoint(
       return;
     }
 
-    double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad;
-    double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad;
-    double aTanStart = abs(xStart) < tolerance ? yStart : yStart / xStart;
-    double aTanEnd   = abs(xEnd) < tolerance   ? yEnd   : yEnd / xEnd;
-    double aCotStart = abs(yStart) < tolerance ? xStart : xStart / yStart;
-    double aCotEnd   = abs(yEnd) < tolerance   ? xEnd   : xEnd / yEnd;
-    if (anArcPoint[1][0] * anArcPoint[2][0] < 0.0) {
-      if (anArcPoint[1][0] > 0.0)
-        yEnd = 2.0 - yEnd;
-      else
-        yStart = -2.0 - yStart;
-    } else {
-      if (aTanStart > aTanEnd) {
-        if (yStart > yEnd) {
-          yStart = 2.0 - yStart;
-          yEnd = -2.0 - yEnd;
-        } else {
-          yStart = -2.0 - yStart;
-          yEnd = 2.0 - yEnd;
-        }
-      }
-    }
-    if (anArcPoint[1][1] * anArcPoint[2][1] < 0.0) {
-      if (anArcPoint[1][1] > 0.0)
-        xEnd = 2.0 - xEnd;
-      else
-        xStart = -2.0 - xStart;
-    } else {
-      if (aCotStart < aCotEnd) {
-        if (xStart > xEnd) {
-          xStart = 2.0 - xStart;
-          xEnd = -2.0 - xEnd;
-        } else {
-          xStart = -2.0 - xStart;
-          xEnd = 2.0 - xEnd;
-        }
-      }
-    }
-    x = (1.0 - theCoeff) * xStart + theCoeff * xEnd;
-    y = (1.0 - theCoeff) * yStart + theCoeff * yEnd;
-    if (x > 1.0) x = 2.0 - x;
-    if (x < -1.0) x = -2.0 - x;
-    if (y > 1.0) y = 2.0 - y;
-    if (y < -1.0) y = -2.0 - y;
-
-    aNorm = sqrt(x*x + y*y);
-    if (aNorm >= tolerance) {
-      x *= aRad / aNorm;
-      y *= aRad / aNorm;
-    } else {
-      x = -0.5 * (anArcPoint[2][1] + anArcPoint[1][1]);
-      y = -0.5 * (anArcPoint[2][0] + anArcPoint[1][0]);
-    }
-    theX = anArcPoint[0][0] + x;
-    theY = anArcPoint[0][1] + y;
+    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+    double anAngle = aStartDir->angle(aEndDir);
+    if (anAngle < 0)
+      anAngle += 2.0 * PI;
+    anAngle *= theCoeff;
+    double aCos = cos(anAngle);
+    double aSin = sin(anAngle);
+    theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+    theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
   }
 }
 
index 50d578a668826c4350b8cc690afa629b087117b6..e76afd2ca40f34495c189481a0bf463e4b769343 100644 (file)
@@ -192,17 +192,6 @@ void SketchSolver_ConstraintMirror::process()
       }
     }
   }
-
-  // Set the mirror line unchanged during constraint recalculation
-  for (int i = 0; i < 2; i++) {
-    if (myStorage->isPointFixed(aMirrorLine.point[i], aConstraint.h, true))
-      continue;
-    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);
-  }
 }
 
 
@@ -293,6 +282,7 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
     Slvs_hEntity aTmp = aMirrorPoint[2];
     aMirrorPoint[2] = aMirrorPoint[1];
     aMirrorPoint[1] = aTmp;
+    adjustArcPoints(theBase);
   }
   if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
     aBasePoint[0] = theBase.h;
@@ -310,9 +300,14 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
   // orthogonal direction
   aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
 
+  Slvs_hConstraint aFixed; // transient variable
   for (int i = 0; i < 4; i++) {
     if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
       continue;
+    // check the mirror point is not fixed
+    if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
+      continue;
+
     Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
     double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
     double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
@@ -331,13 +326,41 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
   }
 }
 
-void SketchSolver_ConstraintMirror::adjustConstraint()
+void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
 {
-  // Search mirror between middle points on the arcs and recompute their coordinates
-  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
-  if (aPonCirc.empty())
-    return;
+  Slvs_Param aParam;
+  Slvs_Entity aPoint;
+  double anArcParams[3][2];
+  for (int i = 0; i < 3; i++) {
+    aPoint = myStorage->getEntity(theArc.point[i]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      anArcParams[i][j] = aParam.val;
+      if (i > 0)
+        anArcParams[i][j] -= anArcParams[0][j];
+    }
+  }
+  double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
+  double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
+  if (fabs(aRad2 - aDist2) < tolerance)
+    return; // nothing to update (last point already on the arc)
+  if (aDist2 < tolerance)
+    return; // unable to update
+  double aCoeff = sqrt(aRad2 / aDist2);
+  anArcParams[2][0] *= aCoeff;
+  anArcParams[2][1] *= aCoeff;
+
+  // Update last point
+  aPoint = myStorage->getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
+        anArcParams[0][i] + anArcParams[2][i]);
+    myStorage->updateParameter(aParam);
+  }
+}
 
+void SketchSolver_ConstraintMirror::adjustConstraint()
+{
   AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
   if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
@@ -353,6 +376,7 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     return;
   Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
 
+  Slvs_Constraint aMirror;
   double aStartEnd[4];
   for (int i = 0; i < 2; i++) {
     Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
@@ -360,7 +384,10 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
       aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
   }
 
-  Slvs_Constraint aMirror;
+  // Search mirror between middle points on the arcs and recompute their coordinates
+  std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
+  std::list<Slvs_Constraint> aMirrorPonCirc;
+  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
   std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
   for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
     aMirror = myStorage->getConstraint(*aConstrIter);
@@ -378,24 +405,45 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     }
     if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
       continue;
+    aMirrorPonCirc.push_back(aMirror);
+    // Store point IDs to avoid their recalculation twice
+    aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
+    aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
+  }
+
+  // Recalculate positions of mirroring points
+  std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
+  std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
+  for (; aMirIter != aMirrorList.end(); aMirIter++) {
+    if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
+      continue; // Avoid mirroring points on circles
+    Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
+    Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
+    makeMirrorEntity(aBase, aMirror, aStartEnd);
+  }
 
-    bool aNeedToResolve = myStorage->isNeedToResolve();
+  bool aNeedToResolve = myStorage->isNeedToResolve();
+  for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
     // Calculate middle point for base arc and mirrored point on mirror arc
-    Slvs_Entity aBaseArc = myStorage->getEntity(aPonCircA.entityA);
-    Slvs_Entity aBasePoint = myStorage->getEntity(aPonCircA.ptA);
+    Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
+    Slvs_Entity aBasePoint = myStorage->getEntity(aMirIter->ptA);
     Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
     Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
     calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
     myStorage->updateParameter(aParamX);
     myStorage->updateParameter(aParamY);
-    Slvs_Entity aMirrorArc = myStorage->getEntity(aPonCircB.entityA);
-    Slvs_Entity aMirrorPoint = myStorage->getEntity(aPonCircB.ptA);
+    Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
+    Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
     aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
     aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
     calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
     myStorage->updateParameter(aParamX);
     myStorage->updateParameter(aParamY);
-    // To avoid looped recalculations of sketch
-    myStorage->setNeedToResolve(aNeedToResolve);
+    // make centers of arcs symmetric
+    aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
+    aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
+    makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
   }
+  // Restore previous value to avoid looped recalculations of sketch
+  myStorage->setNeedToResolve(aNeedToResolve);
 }
index e65dcb90bc77363098636fda0ef710fb3c07a52b..26d97ff983889e358e457f29d523839ad979b19a 100644 (file)
@@ -66,6 +66,9 @@ private:
                         const Slvs_Entity& theMirror,
                         const double theMirrorLine[]) const;
 
+  /// \brief Precisely update last point to be on arc
+  void adjustArcPoints(const Slvs_Entity& theArc) const;
+
 private:
   size_t myNumberOfObjects; ///< number of previously mirrored objects
 };
index b9682f22d0ba2e966f0acb8c7dbac6b607d8e250..2d439b2d11c19ac97739dac54ddf4acc713a7d27 100644 (file)
@@ -15,8 +15,6 @@
 
 #include <math.h>
 
-#define PI 3.1415926535897932
-
 void SketchSolver_ConstraintMultiRotation::getAttributes(
     Slvs_hEntity& theCenter, double& theAngle,
     std::vector<std::vector<Slvs_hEntity> >& thePoints,
index 41d5522f44a0196b70541bde542160eea8cbf730..419cc3e87b51241c5d45d1db49fd0020d4c70aac 100644 (file)
@@ -236,12 +236,21 @@ bool SketchSolver_Group::changeConstraint(
       setTemporary(aConstraint);
     }
   }
-  //// Fix base features for mirror
-  //if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
-  //  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-  //      theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B()));
-  //  fixFeaturesList(aRefList);
-  //}
+  // Fix mirror line
+  if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+        theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
+    if (aRefAttr && aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      SolverConstraintPtr aConstraint =
+          SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+      if (aConstraint) {
+        aConstraint->setGroup(this);
+        aConstraint->setStorage(myStorage);
+        setTemporary(aConstraint);
+      }
+    }
+  }
 
   if (!myFeatureStorage)
     myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);