Salome HOME
Issue #2824: Constraints at wrong positions when editing the sketch
authorazv <azv@opencascade.com>
Tue, 15 Jan 2019 05:34:26 +0000 (08:34 +0300)
committerazv <azv@opencascade.com>
Tue, 15 Jan 2019 05:35:04 +0000 (08:35 +0300)
Improve updating the position of the odd point, which is used to keep the sign of a point-line distance constraint. There is also changed the order of the features to be updated by the SketchSolver: sketch features updated before constraints.

src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/Test/Test2824.py [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_Manager.cpp

index 86fc7c4adc53c4963fc7f593d49f0eb982524365..a608c992c0574153549b9f27b67253f893d79d62 100644 (file)
@@ -192,6 +192,7 @@ ADD_UNIT_TESTS(
   Test2711.py
   Test2741.py
   Test2810.py
+  Test2824.py
   TestArcBehavior.py
   TestConstraintAngle.py
   TestConstraintCoincidence.py
diff --git a/src/SketchPlugin/Test/Test2824.py b/src/SketchPlugin/Test/Test2824.py
new file mode 100644 (file)
index 0000000..585af5a
--- /dev/null
@@ -0,0 +1,65 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    Test2824.py
+    Test case for issue #2824 "Constraints at wrong positions when editing the sketch (BARCOM)"
+"""
+
+from salome.shaper import model
+from GeomAPI import *
+from GeomDataAPI import *
+
+import math
+
+TOLERANCE = 1.e-6
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOZ"))
+SketchArc_1 = Sketch_1.addArc(7.554548355024374, 9.322927740745062, 20, 30.60489708262655, 31.5458454490763, 15, True)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "OZ"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.startPoint(), SketchLine_1.result(), 20, True)
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "OX"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.endPoint(), SketchLine_2.result(), 15, True)
+model.do()
+# move the arc like the user does
+for i in range(0, 10):
+    Sketch_1.move(SketchArc_1.startPoint(), SketchArc_1.startPoint().x(), SketchArc_1.startPoint().y() + 5)
+model.end()
+model.undo()
+
+# compare the arc arguments and the resulting shape
+aStartAttrY = SketchArc_1.startPoint().y()
+aEndAttrX = SketchArc_1.endPoint().x()
+
+anArcShape = SketchArc_1.feature().lastResult().shape()
+aShapeExplorer = GeomAPI_ShapeExplorer(anArcShape, GeomAPI_Shape.VERTEX)
+
+aPoint = aShapeExplorer.current().vertex().point()
+aEndShapeX = aPoint.x()
+assert(math.fabs(aEndAttrX - aEndShapeX) < TOLERANCE)
+
+aShapeExplorer.next()
+aPoint = aShapeExplorer.current().vertex().point()
+aStartShapeY = aPoint.z() # in 3D sketch y iz Z
+assert(math.fabs(aStartAttrY - aStartShapeY) < TOLERANCE)
index 1f827a3c637b279b4b2ea6bfa56a99ea96897757..b9468ef4a9a3c1f1cf8f8c575744d8283aa082a3 100644 (file)
 #include <math.h>
 
 
+static void getPointAndLine(const ConstraintPtr& theConstraint, const StoragePtr& theStorage,
+                            EntityWrapperPtr& thePoint, EntityWrapperPtr& theLine)
+{
+  for (int i = 0; i < 2; ++i) {
+    AttributePtr anAttr = theConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
+    EntityWrapperPtr anEntity = theStorage->entity(anAttr);
+    if (anEntity->type() == ENTITY_POINT)
+      thePoint = anEntity;
+    else if (anEntity->type() == ENTITY_LINE)
+      theLine = anEntity;
+  }
+}
+
+static void adjustOddPoint(const EntityWrapperPtr& theDistPoint,
+                           const EntityWrapperPtr& theDistLine,
+                           GCSPointPtr& theOddPoint)
+{
+  if (!theOddPoint)
+    return;
+
+  std::shared_ptr<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(theDistLine);
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint = PlaneGCSSolver_Tools::point(theDistPoint);
+
+  std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+  std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+
+  double aDot = aPtLineVec->dot(aLineVec);
+  std::shared_ptr<GeomAPI_XY> aProjectedPnt =
+    aLine->location()->xy()->added(aLineVec->multiplied(aDot));
+
+  *(theOddPoint->x) = aProjectedPnt->x();
+  *(theOddPoint->y) = aProjectedPnt->y();
+}
+
+
 void SketchSolver_ConstraintDistance::getAttributes(
     EntityWrapperPtr& theValue,
     std::vector<EntityWrapperPtr>& theAttributes)
@@ -67,14 +102,21 @@ void SketchSolver_ConstraintDistance::adjustConstraint()
 {
   if (getType() == CONSTRAINT_PT_LINE_DISTANCE) {
     bool isSigned = myBaseConstraint->boolean(SketchPlugin_ConstraintDistance::SIGNED())->value();
-    if (myIsSigned == isSigned)
-      return; // distance type is not changed => nothing to adjust
-
-    // Adjust point-line distance by setting/removing additional constraints
-    if (isSigned)
-      addConstraintsToKeepSign();
-    else
-      removeConstraintsKeepingSign();
+    if (myIsSigned == isSigned) {
+      // adjust auxiliary point for sign-keeping
+      if (isSigned) {
+        EntityWrapperPtr aDistPoint, aDistLine;
+        getPointAndLine(myBaseConstraint, myStorage, aDistPoint, aDistLine);
+        adjustOddPoint(aDistPoint, aDistLine, myOddPoint);
+      }
+    }
+    else {
+      // Adjust point-line distance by setting/removing additional constraints
+      if (isSigned)
+        addConstraintsToKeepSign();
+      else
+        removeConstraintsKeepingSign();
+    }
     myIsSigned = isSigned;
   }
 }
@@ -103,14 +145,8 @@ void SketchSolver_ConstraintDistance::addConstraintsToKeepSign()
 
   // calculate projection of the point on the line and find a sign of a distance
   EntityWrapperPtr aDistPoint, aDistLine;
-  for (int i = 0; i < 2; ++i) {
-    AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
-    EntityWrapperPtr anEntity = myStorage->entity(anAttr);
-    if (anEntity->type() == ENTITY_POINT)
-      aDistPoint = anEntity;
-    else if (anEntity->type() == ENTITY_LINE)
-      aDistLine = anEntity;
-  }
+  getPointAndLine(myBaseConstraint, myStorage, aDistPoint, aDistLine);
+
   std::shared_ptr<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(aDistLine);
   std::shared_ptr<GeomAPI_Pnt2d> aPoint = PlaneGCSSolver_Tools::point(aDistPoint);
 
@@ -120,16 +156,12 @@ void SketchSolver_ConstraintDistance::addConstraintsToKeepSign()
     mySignValue = PI/2.0;
   else
     mySignValue = - PI/2.0;
-  double aDot = aPtLineVec->dot(aLineVec);
-  std::shared_ptr<GeomAPI_XY> aProjectedPnt =
-      aLine->location()->xy()->added(aLineVec->multiplied(aDot));
 
   // create auxiliary point on the line and set auxiliary constraints
   myOddPoint = GCSPointPtr(new GCS::Point);
   myOddPoint->x = aStorage->createParameter();
   myOddPoint->y = aStorage->createParameter();
-  *(myOddPoint->x) = aProjectedPnt->x();
-  *(myOddPoint->y) = aProjectedPnt->y();
+  adjustOddPoint(aDistPoint, aDistLine, myOddPoint);
 
   PointWrapperPtr aPointWr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aDistPoint);
   EdgeWrapperPtr anEdgeWr = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aDistLine);
index 8e976d02b9dd8d370fc3f515ddd47be4e2c30900..144fe6c546e6d069396005b7ce7dac7df8c3e74a 100644 (file)
@@ -43,6 +43,42 @@ static bool isFeatureValid(FeaturePtr theFeature)
   return aFactory->validate(theFeature);
 }
 
+typedef std::map<int, std::shared_ptr<SketchPlugin_Feature>> IndexedFeatureMap;
+
+static void featuresOrderedByCreation(const std::set<ObjectPtr>& theOriginalFeatures,
+                                      IndexedFeatureMap& theOrderedFeatures)
+{
+  std::set<ObjectPtr>::iterator aFeatIter = theOriginalFeatures.begin();
+  for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) {
+    std::shared_ptr<SketchPlugin_Feature> aFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+    if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
+      theOrderedFeatures[aFeature->data()->featureId()] = aFeature;
+    }
+  }
+}
+
+static void featuresOrderedByType(const std::set<ObjectPtr>& theOriginalFeatures,
+                                  IndexedFeatureMap& theOrderedFeatures)
+{
+  int aFeatureIndex = 0;
+  int aConstraintIndex = (int)theOriginalFeatures.size();
+
+  std::set<ObjectPtr>::iterator aFeatIter = theOriginalFeatures.begin();
+  for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) {
+    std::shared_ptr<SketchPlugin_Feature> aFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+    if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
+      std::shared_ptr<SketchPlugin_Constraint> aConstraint =
+          std::dynamic_pointer_cast<SketchPlugin_Constraint>(aFeature);
+      if (aConstraint)
+        theOrderedFeatures[++aConstraintIndex] = aFeature;
+      else
+        theOrderedFeatures[++aFeatureIndex] = aFeature;
+    }
+  }
+}
+
 
 
 // ========================================================
@@ -115,29 +151,17 @@ void SketchSolver_Manager::processEvent(
 
     // update sketch features only
     const std::set<ObjectPtr>& aFeatures = anUpdateMsg->objects();
+    IndexedFeatureMap anOrderedFeatures;
     // try to keep order as features were created if there are several created features: #2229
     if (theMessage->eventID() == aCreatedEvent && aFeatures.size() > 1) {
-      std::map<int, std::shared_ptr<SketchPlugin_Feature>> anOrderedFeatures;
-      std::set<ObjectPtr>::iterator aFeatIter;
-      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
-        std::shared_ptr<SketchPlugin_Feature> aFeature =
-            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
-          anOrderedFeatures[aFeature->data()->featureId()] = aFeature;
-        }
-      }
-      std::map<int, std::shared_ptr<SketchPlugin_Feature>>::iterator aFeat;
-      for(aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) {
-        updateFeature(aFeat->second);
-      }
-    } else { // order is not important
-      std::set<ObjectPtr>::iterator aFeatIter;
-      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
-        std::shared_ptr<SketchPlugin_Feature> aFeature =
-            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-        if (aFeature && !aFeature->isMacro())
-          updateFeature(aFeature);
-      }
+      featuresOrderedByCreation(aFeatures, anOrderedFeatures);
+    } else { // order is not important, just process features before constraints
+      featuresOrderedByType(aFeatures, anOrderedFeatures);
+    }
+
+    IndexedFeatureMap::iterator aFeat;
+    for (aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) {
+      updateFeature(aFeat->second);
     }
 
   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {