]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #600: Problem with multi-rotation when one of points of selected objects is...
authorazv <azv@opencascade.com>
Mon, 15 Jun 2015 11:57:18 +0000 (14:57 +0300)
committerazv <azv@opencascade.com>
Mon, 15 Jun 2015 11:58:36 +0000 (14:58 +0300)
src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp
src/SketchSolver/SketchSolver_ConstraintMultiRotation.h

index ab3a4e570b761d6a5c6477e0729459b8db9855a5..0e8ec23d6584d6c5efd5bbabdda41437362466c4 100644 (file)
 
 #include <math.h>
 
+static double squareDistance(
+    StoragePtr theStorage, const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
+{
+  Slvs_Entity aPoint1 = theStorage->getEntity(thePoint1);
+  Slvs_Entity aPoint2 = theStorage->getEntity(thePoint2);
+  double x1 = theStorage->getParameter(aPoint1.param[0]).val;
+  double y1 = theStorage->getParameter(aPoint1.param[1]).val;
+  double x2 = theStorage->getParameter(aPoint2.param[0]).val;
+  double y2 = theStorage->getParameter(aPoint2.param[1]).val;
+  return (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2);
+}
+
 void SketchSolver_ConstraintMultiRotation::getAttributes(
     Slvs_hEntity& theCenter, double& theAngle,
     std::vector<std::vector<Slvs_hEntity> >& thePoints,
@@ -118,6 +130,8 @@ void SketchSolver_ConstraintMultiRotation::process()
   if (!myErrorMsg.empty())
     return;
 
+  myAuxLines.clear();
+
   // Create lines between neighbor rotated points and make angle between them equal to anAngle.
   // Also these lines should have equal lengths.
   Slvs_Constraint aConstraint;
@@ -131,6 +145,7 @@ void SketchSolver_ConstraintMultiRotation::process()
     aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
           myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]);
     aPrevLine.h = myStorage->addEntity(aPrevLine);
+    std::vector<Slvs_hEntity> anEqualLines(1, aPrevLine.h);
     for (size_t i = 1; i < aSize; i++) {
       Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
           myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]);
@@ -151,7 +166,10 @@ void SketchSolver_ConstraintMultiRotation::process()
       mySlvsConstraints.push_back(aConstraint.h);
 
       aPrevLine = aLine;
+      anEqualLines.push_back(aPrevLine.h);
     }
+
+    myAuxLines.push_back(anEqualLines);
   }
   // Equal radii constraints
   for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
@@ -229,6 +247,63 @@ void SketchSolver_ConstraintMultiRotation::adjustConstraint()
     return;
   }
 
+  // Check the lengths of auxiliary lines are zero.
+  // If they become zero, remove corresponding Angle constraints.
+  // It they become non-zero (but were zero recently), add Angle constraint.
+  std::vector<Slvs_hConstraint>::iterator aConstr = mySlvsConstraints.begin();
+  std::map<Slvs_hEntity, Slvs_hEntity> anEqualLines;
+  bool isFirstRemoved = false;
+  for (; aConstr != mySlvsConstraints.end();
+       isFirstRemoved ? aConstr = mySlvsConstraints.begin() : ++aConstr) {
+    isFirstRemoved = false;
+    Slvs_Constraint aConstraint = myStorage->getConstraint(*aConstr);
+    if (aConstraint.type == SLVS_C_ANGLE || aConstraint.type == SLVS_C_EQUAL_LENGTH_LINES) {
+      Slvs_Entity aLine = myStorage->getEntity(aConstraint.entityA);
+      // Line length became zero => remove constraint
+      if (squareDistance(myStorage, aLine.point[0], aLine.point[1]) < tolerance * tolerance) {
+        myStorage->removeConstraint(aConstraint.h);
+        isFirstRemoved = aConstr == mySlvsConstraints.begin();
+        std::vector<Slvs_hConstraint>::iterator aTmpIter = aConstr--;
+        mySlvsConstraints.erase(aTmpIter);
+      }
+      // Store the lines into the map
+      anEqualLines[aConstraint.entityB] = aConstraint.entityA;
+    }
+  }
+  // Create Angle and Equal constraints for non-degenerated lines
+  AuxLinesList::iterator anIt = myAuxLines.begin();
+  for (; anIt != myAuxLines.end(); ++anIt) {
+    if (anEqualLines.find(anIt->back()) != anEqualLines.end())
+      continue;
+
+    std::vector<Slvs_hEntity>::iterator anEqLinesIt = anIt->begin();
+    Slvs_hEntity aPrevLine = (*anEqLinesIt);
+    // Check the length of the line
+    Slvs_Entity aLine = myStorage->getEntity(aPrevLine);
+    if (squareDistance(myStorage, aLine.point[0], aLine.point[1]) < tolerance * tolerance)
+      continue;
+
+    for (++anEqLinesIt; anEqLinesIt != anIt->end(); ++anEqLinesIt) {
+      Slvs_hEntity aLine = (*anEqLinesIt);
+      // Equal length constraint
+      Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
+          SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine, aLine);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+      // Angle constraint
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          aPrevLine, aLine);
+      if (myAngle < 0.0) // clockwise rotation
+        aConstraint.other = true;
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+
+      aPrevLine = aLine;
+    }
+  }
+
   // Obtain coordinates of rotation center
   Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
   double aCenterXY[2];
index e9d0bd14798726ae9362be3826538cbfd502a263..df01392f5624acb19ad080cc5d740e4c308bd2d3 100644 (file)
 #include "SketchSolver.h"
 #include <SketchSolver_Constraint.h>
 
+#include <vector>
+
+typedef std::vector< std::vector<Slvs_hEntity> > AuxLinesList;
+
 /** \class   SketchSolver_ConstraintMultiRotation
  *  \ingroup Plugins
  *  \brief   Convert rotated features to the list of SolveSpace constraints
@@ -60,6 +64,7 @@ private:
   size_t myNumberOfCopies;  ///< number of previous copies of initial objects
   Slvs_hEntity myRotationCenter; ///< ID of center of rotation
   double myAngle;           ///< angle of rotation
+  AuxLinesList myAuxLines;  ///< list of auxiliary lines, created to make clear rotation
 };
 
 #endif