From d9fc10f5d909dd97f687466d026eb7ece3f13b0e Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 29 Jun 2017 15:48:00 +0300 Subject: [PATCH] Set the orientation of the Distance constraint --- src/ModelHighAPI/ModelHighAPI.i | 7 + src/PythonAPI/model/sketcher/tools.py | 7 +- src/SketchAPI/SketchAPI_Constraint.cpp | 5 + src/SketchAPI/SketchAPI_Sketch.cpp | 20 ++- src/SketchAPI/SketchAPI_Sketch.h | 15 ++ src/SketchPlugin/CMakeLists.txt | 7 + .../SketchPlugin_ConstraintDistance.cpp | 1 + .../SketchPlugin_ConstraintDistance.h | 7 + .../Test/TestDistanceSignedVsUnsigned01.py | 66 +++++++++ .../Test/TestDistanceSignedVsUnsigned02.py | 68 +++++++++ .../Test/TestDistanceSignedVsUnsigned03.py | 67 +++++++++ .../Test/TestDistanceSignedVsUnsigned04.py | 69 +++++++++ .../Test/TestDistanceSignedVsUnsigned05.py | 80 ++++++++++ .../Test/TestSignedDistancePointLine.py | 129 +++++++++++++++++ .../Test/TestSignedDistancePointPoint.py | 108 ++++++++++++++ src/SketchPlugin/plugin-Sketch.xml | 1 + .../PlaneGCSSolver/PlaneGCSSolver_Solver.cpp | 24 +++ .../SketchSolver_ConstraintDistance.cpp | 137 ++++++++++++------ .../SketchSolver_ConstraintDistance.h | 13 +- 19 files changed, 779 insertions(+), 52 deletions(-) create mode 100644 src/SketchPlugin/Test/TestDistanceSignedVsUnsigned01.py create mode 100644 src/SketchPlugin/Test/TestDistanceSignedVsUnsigned02.py create mode 100644 src/SketchPlugin/Test/TestDistanceSignedVsUnsigned03.py create mode 100644 src/SketchPlugin/Test/TestDistanceSignedVsUnsigned04.py create mode 100644 src/SketchPlugin/Test/TestDistanceSignedVsUnsigned05.py create mode 100644 src/SketchPlugin/Test/TestSignedDistancePointLine.py create mode 100644 src/SketchPlugin/Test/TestSignedDistancePointPoint.py diff --git a/src/ModelHighAPI/ModelHighAPI.i b/src/ModelHighAPI/ModelHighAPI.i index 5b09cc980..7010d8481 100644 --- a/src/ModelHighAPI/ModelHighAPI.i +++ b/src/ModelHighAPI/ModelHighAPI.i @@ -143,6 +143,7 @@ std::shared_ptr * temp_attribute; std::shared_ptr * temp_object; std::shared_ptr * temp_interface; + ModelHighAPI_Selection* temp_selection; int newmem = 0; if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_attribute, $descriptor(std::shared_ptr *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { if (temp_attribute) { @@ -162,6 +163,12 @@ } else { $1 = 0; } + } else if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { + if (temp_selection) { + $1 = 1; + } else { + $1 = 0; + } } else { $1 = 0; } diff --git a/src/PythonAPI/model/sketcher/tools.py b/src/PythonAPI/model/sketcher/tools.py index e93fec49c..f3dcdb37a 100644 --- a/src/PythonAPI/model/sketcher/tools.py +++ b/src/PythonAPI/model/sketcher/tools.py @@ -75,7 +75,7 @@ def distancePointPoint(thePoint1, thePoint2): aPnt2 = toList(thePoint2) return math.hypot(aPnt1[0] - aPnt2[0], aPnt1[1] - aPnt2[1]) -def distancePointLine(thePoint, theLine): +def signedDistancePointLine(thePoint, theLine): aPoint = toList(thePoint) aLine = toSketchFeature(theLine) @@ -84,7 +84,10 @@ def distancePointLine(thePoint, theLine): aLineDir = aLineEnd.decreased(aLineStart) aLineLen = aLineEnd.distance(aLineStart) aCross = (aPoint[0] - aLineStart.x()) * aLineDir.y() - (aPoint[1] - aLineStart.y()) * aLineDir.x() - return math.fabs(aCross / aLineLen) + return aCross / aLineLen + +def distancePointLine(thePoint, theLine): + return math.fabs(signedDistancePointLine(thePoint, theLine)) def lastSubFeature(theSketch, theKind): """ diff --git a/src/SketchAPI/SketchAPI_Constraint.cpp b/src/SketchAPI/SketchAPI_Constraint.cpp index d655ff2af..c5a75fef3 100644 --- a/src/SketchAPI/SketchAPI_Constraint.cpp +++ b/src/SketchAPI/SketchAPI_Constraint.cpp @@ -192,5 +192,10 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const if (aValueAttr && aValueAttr->isInitialized()) theDumper << ", " << aValueAttr; + if (aBase->getKind() == SketchPlugin_ConstraintDistance::ID()) { + AttributeBooleanPtr isSigned = aBase->boolean(SketchPlugin_ConstraintDistance::SIGNED()); + theDumper << ", " << isSigned->value(); + } + theDumper << ")" << std::endl; } diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index daefc491e..b20782376 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -627,17 +627,35 @@ std::shared_ptr SketchAPI_Sketch::setCollinear( std::shared_ptr SketchAPI_Sketch::setDistance( const ModelHighAPI_RefAttr & thePoint, const ModelHighAPI_RefAttr & thePointOrLine, - const ModelHighAPI_Double & theValue) + const ModelHighAPI_Double & theValue, + bool isSigned) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintDistance::ID()); fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(thePointOrLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE())); + fillAttribute(isSigned, aFeature->boolean(SketchPlugin_ConstraintDistance::SIGNED())); aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } +std::shared_ptr SketchAPI_Sketch::setSignedDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue) +{ + return setDistance(thePoint, thePointOrLine, theValue, true); +} + +std::shared_ptr SketchAPI_Sketch::setUnsignedDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue) +{ + return setDistance(thePoint, thePointOrLine, theValue, false); +} + std::shared_ptr SketchAPI_Sketch::setHorizontalDistance( const ModelHighAPI_RefAttr & thePoint1, const ModelHighAPI_RefAttr & thePoint2, diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index f17851444..107ec5b85 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -329,6 +329,21 @@ public: /// Set distance SKETCHAPI_EXPORT std::shared_ptr setDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue, + bool isSigned = false); + + /// Set signed distance + SKETCHAPI_EXPORT + std::shared_ptr setSignedDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue); + + /// Set unsigned distance + SKETCHAPI_EXPORT + std::shared_ptr setUnsignedDistance( const ModelHighAPI_RefAttr & thePoint, const ModelHighAPI_RefAttr & thePointOrLine, const ModelHighAPI_Double & theValue); diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index bacf4249a..152367cb5 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -216,4 +216,11 @@ ADD_UNIT_TESTS(TestSketchPointLine.py TestMoveCircle.py TestMoveArc.py TestMovementComplex.py + TestDistanceSignedVsUnsigned01.py + TestDistanceSignedVsUnsigned02.py + TestDistanceSignedVsUnsigned03.py + TestDistanceSignedVsUnsigned04.py + TestDistanceSignedVsUnsigned05.py + TestSignedDistancePointPoint.py + TestSignedDistancePointLine.py ) diff --git a/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp b/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp index f4a02ca41..b541a3bc1 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp @@ -54,6 +54,7 @@ void SketchPlugin_ConstraintDistance::initAttributes() data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SIGNED(), ModelAPI_AttributeBoolean::typeId()); } void SketchPlugin_ConstraintDistance::colorConfigInfo(std::string& theSection, std::string& theName, diff --git a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h index c2dc3ee40..3c433e974 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h @@ -58,6 +58,13 @@ class SketchPlugin_ConstraintDistance : public SketchPlugin_ConstraintBase return MY_KIND; } + /// \brief Shows whether the point-line distance should keep its sign + inline static const std::string& SIGNED() + { + static const std::string MY_SIGNED("SignedDistance"); + return MY_SIGNED; + } + /// \brief Creates a new part document if needed SKETCHPLUGIN_EXPORT virtual void execute(); diff --git a/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned01.py b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned01.py new file mode 100644 index 000000000..6ab1c23cd --- /dev/null +++ b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned01.py @@ -0,0 +1,66 @@ +## Copyright (C) 2017 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 +## + +from salome.shaper import model +from SketchAPI import * +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +widthParam = model.addParameter(partSet, "w", "200") +distParam = model.addParameter(partSet, "d", "30") +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100) +[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines() +Origin = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Origin.result()) +Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w") +Point_1 = Sketch_1.addPoint(230, 40) +Sketch_1.setSignedDistance(Point_1.result(), SketchAPI_Line(Line_4).result(), "d") +Point_2 = Sketch_1.addPoint(230, 80) +Sketch_1.setUnsignedDistance(Point_2.result(), SketchAPI_Line(Line_4).result(), "d") +model.do() +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +line = model.toSketchFeature(Line_4) +signedDist1 = model.signedDistancePointLine(Point_1, line) +signedDist2 = model.signedDistancePointLine(Point_2, line) + +# change rectangle width and check distances +widthParam.setValue(2000) +model.do() +curDist = model.signedDistancePointLine(Point_1, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(Point_2, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +# revert rectangle width and check distances again +widthParam.setValue(200) +model.do() +curDist = model.signedDistancePointLine(Point_1, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(Point_2, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +model.end() diff --git a/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned02.py b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned02.py new file mode 100644 index 000000000..f518caab7 --- /dev/null +++ b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned02.py @@ -0,0 +1,68 @@ +## Copyright (C) 2017 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 +## + +from salome.shaper import model +from SketchAPI import * +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +widthParam = model.addParameter(partSet, "w", "200") +distParam = model.addParameter(partSet, "d", "30") +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100) +[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines() +Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result()) +Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w") +Circle_1 = Sketch_1.addCircle(230, 40, 20) +Sketch_1.setSignedDistance(Circle_1.center(), SketchAPI_Line(Line_4).result(), "d") +Circle_2 = Sketch_1.addCircle(230, 80, 20) +Sketch_1.setUnsignedDistance(Circle_2.center(), SketchAPI_Line(Line_4).result(), "d") +model.do() +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +center1 = Circle_1.center() +center2 = Circle_2.center() +line = model.toSketchFeature(Line_4) +signedDist1 = model.signedDistancePointLine(center1, line) +signedDist2 = model.signedDistancePointLine(center2, line) + +# change rectangle width and check distances +widthParam.setValue(2000) +model.do() +curDist = model.signedDistancePointLine(center1, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(center2, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +# revert rectangle width and check distances again +widthParam.setValue(200) +model.do() +curDist = model.signedDistancePointLine(center1, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(center2, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +model.end() diff --git a/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned03.py b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned03.py new file mode 100644 index 000000000..f05990017 --- /dev/null +++ b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned03.py @@ -0,0 +1,67 @@ +## Copyright (C) 2017 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 +## + +from salome.shaper import model +from SketchAPI import * +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +widthParam = model.addParameter(partSet, "w", "200") +distParam = model.addParameter(partSet, "d", "30") +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100) +[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines() +Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result()) +Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w") +Line_5 = Sketch_1.addLine(230, 40, 230, 80) +Sketch_1.setSignedDistance(Line_5.startPoint(), SketchAPI_Line(Line_4).result(), "d") +Sketch_1.setUnsignedDistance(Line_5.endPoint(), SketchAPI_Line(Line_4).result(), "d") +model.do() +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +start = Line_5.startPoint() +end = Line_5.endPoint() +line = model.toSketchFeature(Line_4) +signedDist1 = model.signedDistancePointLine(start, line) +signedDist2 = model.signedDistancePointLine(end, line) + +# change rectangle width and check distances +widthParam.setValue(2000) +model.do() +curDist = model.signedDistancePointLine(start, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(end, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +# revert rectangle width and check distances again +widthParam.setValue(200) +model.do() +curDist = model.signedDistancePointLine(start, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(end, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +model.end() diff --git a/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned04.py b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned04.py new file mode 100644 index 000000000..e26fd4221 --- /dev/null +++ b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned04.py @@ -0,0 +1,69 @@ +## Copyright (C) 2017 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 +## + +from salome.shaper import model +from SketchAPI import * +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +widthParam = model.addParameter(partSet, "w", "200") +distParam = model.addParameter(partSet, "d", "30") +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100) +[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines() +Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result()) +Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w") +Arc_1 = Sketch_1.addArc(250, 60, 230, 40, 230, 80, False) +Sketch_1.setSignedDistance(Arc_1.startPoint(), SketchAPI_Line(Line_4).result(), "d") +Sketch_1.setUnsignedDistance(Arc_1.endPoint(), SketchAPI_Line(Line_4).result(), "d") +model.do() +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +start = Arc_1.startPoint() +end = Arc_1.endPoint() +line = model.toSketchFeature(Line_4) +signedDist1 = model.signedDistancePointLine(start, line) +signedDist2 = model.signedDistancePointLine(end, line) + +# change rectangle width and check distances +widthParam.setValue(1000) +model.do() +curDist = model.signedDistancePointLine(start, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(end, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +model.assertArcValidity(Arc_1) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +# revert rectangle width and check distances again +widthParam.setValue(200) +model.do() +curDist = model.signedDistancePointLine(start, line) +assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist) +curDist = model.signedDistancePointLine(end, line) +assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist) +model.assertArcValidity(Arc_1) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +model.end() diff --git a/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned05.py b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned05.py new file mode 100644 index 000000000..3d476c35d --- /dev/null +++ b/src/SketchPlugin/Test/TestDistanceSignedVsUnsigned05.py @@ -0,0 +1,80 @@ +## Copyright (C) 2017 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 +## + +from salome.shaper import model +from SketchAPI import * +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +widthParam = model.addParameter(partSet, "w", "200") +distParam = model.addParameter(partSet, "d", "30") +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100) +[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines() +Origin = Sketch_1.addPoint(model.selection("VERTEX", "Origin")) +Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Origin.result()) +Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w") +Point_1 = Sketch_1.addPoint(230, 40) +Sketch_1.setSignedDistance(Point_1.result(), SketchAPI_Line(Line_4).result(), "d") +Point_2 = Sketch_1.addPoint(230, 80) +Sketch_1.setUnsignedDistance(Point_2.result(), SketchAPI_Line(Line_4).result(), "d") +Line_5 = Sketch_1.addLine(260, 0, 260, 100) +Sketch_1.setSignedDistance(Point_1.result(), Line_5.result(), "d") +Sketch_1.setUnsignedDistance(Point_2.result(), Line_5.result(), "d") +model.do() +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +line4 = model.toSketchFeature(Line_4) +line5 = model.toSketchFeature(Line_5) +signedDist14 = model.signedDistancePointLine(Point_1, line4) +signedDist15 = model.signedDistancePointLine(Point_1, line5) +signedDist24 = model.signedDistancePointLine(Point_2, line4) +signedDist25 = model.signedDistancePointLine(Point_2, line5) + +# change rectangle width and check distances +widthParam.setValue(2000) +model.do() +curDist = model.signedDistancePointLine(Point_1, line4) +assert(math.fabs(signedDist14 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist14, curDist) +curDist = model.signedDistancePointLine(Point_2, line4) +assert(math.fabs(math.fabs(signedDist24) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist24, -curDist) +curDist = model.signedDistancePointLine(Point_1, line5) +assert(math.fabs(signedDist15 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist15, curDist) +curDist = model.signedDistancePointLine(Point_2, line5) +assert(math.fabs(math.fabs(signedDist25) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist25, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +# revert rectangle width and check distances again +widthParam.setValue(200) +model.do() +curDist = model.signedDistancePointLine(Point_1, line4) +assert(math.fabs(signedDist14 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist14, curDist) +curDist = model.signedDistancePointLine(Point_2, line4) +assert(math.fabs(math.fabs(signedDist24) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist24, -curDist) +curDist = model.signedDistancePointLine(Point_1, line5) +assert(math.fabs(signedDist15 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist15, curDist) +curDist = model.signedDistancePointLine(Point_2, line5) +assert(math.fabs(math.fabs(signedDist25) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist25, -curDist) +assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation" + +model.end() diff --git a/src/SketchPlugin/Test/TestSignedDistancePointLine.py b/src/SketchPlugin/Test/TestSignedDistancePointLine.py new file mode 100644 index 000000000..5339a7aa6 --- /dev/null +++ b/src/SketchPlugin/Test/TestSignedDistancePointLine.py @@ -0,0 +1,129 @@ +from salome.shaper import model +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "clearance", "210") +model.addParameter(Part_1_doc, "wheel_R", "203") +model.addParameter(Part_1_doc, "arc_R", "wheel_R+70") +model.addParameter(Part_1_doc, "hood_height", "290") +HeightParam = model.addParameter(Part_1_doc, "height", "900") +LengthParam = model.addParameter(Part_1_doc, "length", "1460") +PosParam = model.addParameter(Part_1_doc, "position", "71.99905090248758") +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-281.378739745974, 78.99909999999998, -98.87873974597397, 78.99909999999998) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchArc_1 = Sketch_1.addArc(174.031501908677, 71.9991, -98.87873974597397, 78.99909999999998, 446.941743563328, 78.9991, True) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchArc_1.startPoint()) +SketchArc_2 = Sketch_1.addArc(-554.288981400625, 71.9991, -281.378739745974, 78.99909999999998, -827.1992230552759, 78.9991, False) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_1.result()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result()) +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_1.result(), "clearance-wheel_R", True) +SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), "clearance-wheel_R", True) +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchArc_2.results()[1], SketchArc_1.results()[1]) +SketchCircle_1 = Sketch_1.addCircle(-554.288981400625, 71.9991, 203) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.center(), SketchCircle_1.center()) +SketchCircle_2 = Sketch_1.addCircle(174.031501908677, 71.9991, 203) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.center(), SketchCircle_2.center()) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "wheel_R") +SketchConstraintEqual_2 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1]) +SketchLine_2 = Sketch_1.addLine(-827.1992230552759, 78.9991, -960.4001854579536, 78.9991) +SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(-960.4001854579536, 78.9991, -960.4001854579536, 368.9991) +SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-891.6236641114499, 437.7756213465037, -540.5628729569305, 437.7756213465037) +SketchLine_5 = Sketch_1.addLine(-540.5628729569305, 437.7756213465037, -349.330908394406, 768.9991) +SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-349.330908394406, 768.9991, 308.3678499795216, 768.9991) +SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchLine_7 = Sketch_1.addLine(308.3678499795216, 768.9991, 499.5998145420464, 437.7756213465038) +SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchLine_8 = Sketch_1.addLine(499.5998145420464, 437.7756213465038, 499.5998145420464, 78.9991) +SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchLine_9 = Sketch_1.addLine(499.5998145420464, 78.9991, 446.941743563328, 78.9991) +SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint()) +SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_9.endPoint()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result()) +SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_4.result()) +SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result()) +SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_9.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_8.result()) +SketchArc_3 = Sketch_1.addArc(-891.6236641114499, 368.9991, -891.6236641114499, 437.7756213465037, -960.4001854579536, 368.9991, False) +SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_3.endPoint()) +SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_3.result()) +SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_4.result()) +SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_5.result(), SketchLine_4.result(), 120.0000000000006) +SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.result()) +SketchConstraintAngle_2 = Sketch_1.setAngleBackward(SketchLine_7.result(), SketchLine_6.result(), 120.0000000000006) +SketchConstraintDistance_3 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_2.startPoint(), "arc_R", True) +SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchLine_5.endPoint(), "height-clearance") +SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_2.endPoint(), SketchLine_9.startPoint(), "length", True) +SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_2.result(), "hood_height", True) +SketchLine_10 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX")) +SketchConstraintDistance_6 = Sketch_1.setDistance(SketchCircle_2.center(), SketchLine_10.result(), "position", True) +SketchPoint_1 = Sketch_1.addPoint(-910.4001854579535, 347.7756213465037) +SketchPoint_2 = Sketch_1.addPoint(-910.9041532173604, 297.7781612460398) +SketchConstraintDistance_7 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_3.result(), 50, True) +SketchConstraintDistance_8 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_4.result(), 90, True) +SketchConstraintDistance_9 = Sketch_1.setDistance(SketchPoint_2.coordinates(), SketchPoint_1.coordinates(), 50, True) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "length/8") +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchArc_1_2r-SketchArc_2_2r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchArc_3_2f")], model.selection(), 500, 0) +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 500, -400) +Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 100, 0) +model.do() + +# Verify point-line signed distance +dist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1) +dist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1) +dist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2) +dist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3) +dist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4) + +PosParam.setValue(300) +model.do() +curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1) +curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1) +curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2) +curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3) +curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) +assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3) +assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4) +assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5) + +LengthParam.setValue(2000) +model.do() +curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1) +curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1) +curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2) +curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3) +curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) +assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3) +assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4) +assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5) + +HeightParam.setValue(1200) +model.do() +curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1) +curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1) +curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2) +curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3) +curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) +assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3) +assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4) +assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5) + +model.end() diff --git a/src/SketchPlugin/Test/TestSignedDistancePointPoint.py b/src/SketchPlugin/Test/TestSignedDistancePointPoint.py new file mode 100644 index 000000000..d2bca85b4 --- /dev/null +++ b/src/SketchPlugin/Test/TestSignedDistancePointPoint.py @@ -0,0 +1,108 @@ +from salome.shaper import model +import math + +TOLERANCE = 1.e-5 + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "clearance", "210") +model.addParameter(Part_1_doc, "wheel_R", "203") +model.addParameter(Part_1_doc, "arc_R", "wheel_R+70") +model.addParameter(Part_1_doc, "hood_height", "290") +HeightParam = model.addParameter(Part_1_doc, "height", "900") +LengthParam = model.addParameter(Part_1_doc, "length", "1460") +PosParam = model.addParameter(Part_1_doc, "position", "71.99905090248758") +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-281.378739745974, 78.99909999999998, -98.87873974597397, 78.99909999999998) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchArc_1 = Sketch_1.addArc(174.031501908677, 71.9991, -98.87873974597397, 78.99909999999998, 446.941743563328, 78.9991, True) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchArc_1.startPoint()) +SketchArc_2 = Sketch_1.addArc(-554.288981400625, 71.9991, -281.378739745974, 78.99909999999998, -827.1992230552759, 78.9991, False) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_1.result()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result()) +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_1.result(), "clearance-wheel_R", True) +SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), "clearance-wheel_R", True) +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchArc_2.results()[1], SketchArc_1.results()[1]) +SketchCircle_1 = Sketch_1.addCircle(-554.288981400625, 71.9991, 203) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.center(), SketchCircle_1.center()) +SketchCircle_2 = Sketch_1.addCircle(174.031501908677, 71.9991, 203) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.center(), SketchCircle_2.center()) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "wheel_R") +SketchConstraintEqual_2 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1]) +SketchLine_2 = Sketch_1.addLine(-827.1992230552759, 78.9991, -960.4001854579536, 78.9991) +SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(-960.4001854579536, 78.9991, -960.4001854579536, 368.9991) +SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-891.6236641114499, 437.7756213465037, -540.5628729569305, 437.7756213465037) +SketchLine_5 = Sketch_1.addLine(-540.5628729569305, 437.7756213465037, -349.330908394406, 768.9991) +SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-349.330908394406, 768.9991, 308.3678499795216, 768.9991) +SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchLine_7 = Sketch_1.addLine(308.3678499795216, 768.9991, 499.5998145420464, 437.7756213465038) +SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchLine_8 = Sketch_1.addLine(499.5998145420464, 437.7756213465038, 499.5998145420464, 78.9991) +SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchLine_9 = Sketch_1.addLine(499.5998145420464, 78.9991, 446.941743563328, 78.9991) +SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint()) +SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_9.endPoint()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result()) +SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_4.result()) +SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result()) +SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_9.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_8.result()) +SketchArc_3 = Sketch_1.addArc(-891.6236641114499, 368.9991, -891.6236641114499, 437.7756213465037, -960.4001854579536, 368.9991, False) +SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_3.endPoint()) +SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_3.result()) +SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_4.result()) +SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_5.result(), SketchLine_4.result(), 120.0000000000006) +SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.result()) +SketchConstraintAngle_2 = Sketch_1.setAngleBackward(SketchLine_7.result(), SketchLine_6.result(), 120.0000000000006) +SketchConstraintDistance_3 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_2.startPoint(), "arc_R", True) +SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchLine_5.endPoint(), "height-clearance") +SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_2.endPoint(), SketchLine_9.startPoint(), "length", True) +SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_2.result(), "hood_height", True) +SketchLine_10 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX")) +SketchConstraintDistance_6 = Sketch_1.setDistance(SketchCircle_2.center(), SketchLine_10.result(), "position", True) +SketchPoint_1 = Sketch_1.addPoint(-910.4001854579535, 347.7756213465037) +SketchPoint_2 = Sketch_1.addPoint(-910.9041532173604, 297.7781612460398) +SketchConstraintDistance_7 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_3.result(), 50, True) +SketchConstraintDistance_8 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_4.result(), 90, True) +SketchConstraintDistance_9 = Sketch_1.setDistance(SketchPoint_2.coordinates(), SketchPoint_1.coordinates(), 50, True) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "length/8") +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchArc_1_2r-SketchArc_2_2r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchArc_3_2f")], model.selection(), 500, 0) +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 500, -400) +Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 100, 0) +model.do() + +# Verify point-point distance +dist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint()) +dist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2) + +PosParam.setValue(300) +model.do() +curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint()) +curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) + +LengthParam.setValue(2000) +model.do() +curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint()) +curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) + +HeightParam.setValue(1200) +model.do() +curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint()) +curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2) +assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1) +assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2) + +model.end() diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index b6c74bff6..2adc38330 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -653,6 +653,7 @@ email : webmaster.salome@opencascade.com + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index 9c4cad57d..75919af5f 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -152,6 +152,30 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve() collectConflicting(); if (!myConflictingIDs.empty()) aResult = GCS::Failed; + else if (aResult == GCS::Failed) { + // DogLeg solver failed without conflicting constraints, try to use Levenberg-Marquardt solver + // if there are point-line distance constraints + ConstraintMap::iterator aCIt = myConstraints.begin(); + for (; aCIt != myConstraints.end(); ++aCIt) { + if (aCIt->second.size() <= 1) + continue; + std::set::const_iterator anIt = aCIt->second.begin(); + for (; anIt != aCIt->second.end(); ++anIt) + if ((*anIt)->getTypeId() == GCS::P2LDistance) + break; + if (anIt != aCIt->second.end()) + break; + } + + if (aCIt != myConstraints.end()) { + aResult = (GCS::SolveStatus)myEquationSystem->solve( + myParameters, true, GCS::LevenbergMarquardt); + myConfCollected = false; + collectConflicting(); + if (!myConflictingIDs.empty()) + aResult = GCS::Failed; + } + } SolveStatus aStatus; if (aResult == GCS::Failed) diff --git a/src/SketchSolver/SketchSolver_ConstraintDistance.cpp b/src/SketchSolver/SketchSolver_ConstraintDistance.cpp index 901053c6d..4aa15648d 100644 --- a/src/SketchSolver/SketchSolver_ConstraintDistance.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintDistance.cpp @@ -22,6 +22,11 @@ #include #include +#include +#include +#include +#include + #include #include @@ -60,53 +65,18 @@ void SketchSolver_ConstraintDistance::getAttributes( void SketchSolver_ConstraintDistance::adjustConstraint() { - ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint); + 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-point distance if the points are equal - if (getType() == CONSTRAINT_PT_PT_DISTANCE) { -//// AttributePtr aPt1 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()); -//// AttributePtr aPt2 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()); -//// -//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); -//// std::shared_ptr aPoint1 = aBuilder->point(myStorage->entity(aPt1)); -//// EntityWrapperPtr anEntity2 = myStorage->entity(aPt2); -//// std::shared_ptr aPoint2 = aBuilder->point(anEntity2); -//// -//////// if (aPoint1->distance(aPoint2) < tolerance) { -//////// // Change X coordinate of second point to eliminate coincidence -//////// ParameterWrapperPtr aX = aSubs.back()->parameters().front(); -//////// aX->setValue(aX->value() + 1.0); -//////// myStorage->update(aX); -//////// } - return; - } - - // Adjust point-line distance - if (fabs(myPrevValue) == fabs(aConstraint->value())) { - // sign of distance is not changed -//// aConstraint->setValue(myPrevValue); -//// myStorage->addConstraint(myBaseConstraint, aConstraint); - return; + // Adjust point-line distance by setting/removing additional constraints + if (isSigned) + addConstraintsToKeepSign(); + else + removeConstraintsKeepingSign(); + myIsSigned = isSigned; } - -//// // Adjust the sign of constraint value -//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); -//// -//// std::shared_ptr aLine; -//// std::shared_ptr aPoint; -//// 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) -//// aPoint = aBuilder->point(anEntity); -//// else if (anEntity->type() == ENTITY_LINE) -//// aLine = aBuilder->line(anEntity); -//// } -//// -//// std::shared_ptr aLineVec = aLine->direction()->xy(); -//// std::shared_ptr aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy()); -//// if (aLineVec->cross(aPtLineVec) * aConstraint->value() < 0.0) -//// aConstraint->setValue(aConstraint->value() * (-1.0)); } void SketchSolver_ConstraintDistance::update() @@ -116,3 +86,80 @@ void SketchSolver_ConstraintDistance::update() SketchSolver_Constraint::update(); } + +void SketchSolver_ConstraintDistance::addConstraintsToKeepSign() +{ + std::shared_ptr aStorage = + std::dynamic_pointer_cast(myStorage); + + ConstraintWrapperPtr aConstraint = aStorage->constraint(myBaseConstraint); + std::list aGCSConstraints = aConstraint->constraints(); + + // 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; + } + std::shared_ptr aLine = PlaneGCSSolver_Tools::line(aDistLine); + std::shared_ptr aPoint = PlaneGCSSolver_Tools::point(aDistPoint); + + std::shared_ptr aLineVec = aLine->direction()->xy(); + std::shared_ptr aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy()); + if (aLineVec->cross(aPtLineVec) >= 0.) + mySignValue = PI/2.0; + else + mySignValue = - PI/2.0; + double aDot = aPtLineVec->dot(aLineVec); + std::shared_ptr 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(); + + PointWrapperPtr aPointWr = std::dynamic_pointer_cast(aDistPoint); + EdgeWrapperPtr anEdgeWr = std::dynamic_pointer_cast(aDistLine); + std::shared_ptr aGCSLine = std::dynamic_pointer_cast(anEdgeWr->entity()); + // point-on-line + GCSConstraintPtr aNewConstraint(new GCS::ConstraintPointOnLine(*myOddPoint, *aGCSLine)); + aGCSConstraints.push_back(aNewConstraint); + // angle which keep orientation + aNewConstraint = GCSConstraintPtr(new GCS::ConstraintL2LAngle( + aGCSLine->p1, aGCSLine->p2, *myOddPoint, *(aPointWr->point()), &mySignValue)); + aGCSConstraints.push_back(aNewConstraint); + + aConstraint->setConstraints(aGCSConstraints); + + aStorage->removeConstraint(myBaseConstraint); + aStorage->addConstraint(myBaseConstraint, aConstraint); +} + +void SketchSolver_ConstraintDistance::removeConstraintsKeepingSign() +{ + std::shared_ptr aStorage = + std::dynamic_pointer_cast(myStorage); + + ConstraintWrapperPtr aConstraint = aStorage->constraint(myBaseConstraint); + std::list aGCSConstraints = aConstraint->constraints(); + + aStorage->removeConstraint(myBaseConstraint); + + // remove parameters related to auxiliary point + GCS::SET_pD aParams; + aParams.insert(myOddPoint->x); + aParams.insert(myOddPoint->y); + aStorage->removeParameters(aParams); + + aGCSConstraints.pop_back(); + aGCSConstraints.pop_back(); + aConstraint->setConstraints(aGCSConstraints); + aStorage->addConstraint(myBaseConstraint, aConstraint); +} diff --git a/src/SketchSolver/SketchSolver_ConstraintDistance.h b/src/SketchSolver/SketchSolver_ConstraintDistance.h index ec7cbd3b6..b11ab1ea3 100644 --- a/src/SketchSolver/SketchSolver_ConstraintDistance.h +++ b/src/SketchSolver/SketchSolver_ConstraintDistance.h @@ -33,7 +33,8 @@ public: /// Constructor based on SketchPlugin constraint SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) : SketchSolver_Constraint(theConstraint), - myIsNegative(false) + myIsSigned(false), + mySignValue(0.0) {} /// \brief Update constraint @@ -51,10 +52,14 @@ protected: virtual void adjustConstraint(); private: - double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign) + void addConstraintsToKeepSign(); + void removeConstraintsKeepingSign(); - /// \c true, if the point if placed rightside of line direction (SLVS_C_PT_LINE_DISTANCE only) - bool myIsNegative; +private: + double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign) + bool myIsSigned; ///< true if the sign of point-line distance should be kept everytime + GCSPointPtr myOddPoint; ///< auxiliary point to keep sign of distance + double mySignValue; }; #endif -- 2.39.2