From 5ef1bee9097c46f0d8effbac12cd5f179b542d0f Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 19 Sep 2019 14:55:29 +0300 Subject: [PATCH] Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003) Constraint Equal for ellipses --- src/GeomAPI/GeomAPI_Curve.cpp | 6 +++ src/GeomAPI/GeomAPI_Curve.h | 4 ++ src/PartSet/PartSet_Validators.cpp | 4 +- src/SketchPlugin/CMakeLists.txt | 1 + src/SketchPlugin/SketchPlugin_Validators.cpp | 22 +++++++-- .../Test/TestConstraintEqualEllipse.py | 48 +++++++++++++++++++ src/SketchPlugin/plugin-Sketch.xml | 4 +- .../PlaneGCSSolver/PlaneGCSSolver_Defs.h | 2 +- .../PlaneGCSSolver/PlaneGCSSolver_Solver.cpp | 17 ++++--- .../SketchSolver_ConstraintEqual.cpp | 7 ++- src/SketcherPrs/SketcherPrs_PositionMgr.cpp | 2 +- 11 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 src/SketchPlugin/Test/TestConstraintEqualEllipse.py diff --git a/src/GeomAPI/GeomAPI_Curve.cpp b/src/GeomAPI/GeomAPI_Curve.cpp index 7276c8485..46635b0a8 100644 --- a/src/GeomAPI/GeomAPI_Curve.cpp +++ b/src/GeomAPI/GeomAPI_Curve.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,11 @@ bool GeomAPI_Curve::isCircle() const return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_Circle); } +bool GeomAPI_Curve::isEllipse() const +{ + return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_Ellipse); +} + std::shared_ptr GeomAPI_Curve::getPoint(double theParam) { GeomAdaptor_Curve aAdaptor(MY_CURVE, myStart, myEnd); diff --git a/src/GeomAPI/GeomAPI_Curve.h b/src/GeomAPI/GeomAPI_Curve.h index 30b9bd998..65ba0d5b7 100644 --- a/src/GeomAPI/GeomAPI_Curve.h +++ b/src/GeomAPI/GeomAPI_Curve.h @@ -57,6 +57,10 @@ class GeomAPI_Curve : public GeomAPI_Interface GEOMAPI_EXPORT virtual bool isCircle() const; + /// Returns whether the curve is elliptic + GEOMAPI_EXPORT + virtual bool isEllipse() const; + /// Returns start parameter of the curve GEOMAPI_EXPORT double startParam() const { return myStart; } diff --git a/src/PartSet/PartSet_Validators.cpp b/src/PartSet/PartSet_Validators.cpp index 4b72de198..0b5a42bd5 100644 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@ -335,12 +335,12 @@ bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection, aType = 1; else if (aType != 1) return false; - } else if (aEdge.isCircle()) { + } else if (aEdge.isCircle() || aEdge.isArc()) { if (aCount == 1) aType = 2; else if (aType != 2) return false; - } else if (aEdge.isArc()) { + } else if (aEdge.isEllipse()) { if (aCount == 1) aType = 3; else if (aType != 3) diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 3476cd275..55a9aa143 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -214,6 +214,7 @@ ADD_UNIT_TESTS( TestConstraintDistanceHorizontal.py TestConstraintDistanceVertical.py TestConstraintEqual.py + TestConstraintEqualEllipse.py TestConstraintFixed.py TestConstraintHorizontal.py TestConstraintHorizontalValidator.py diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index c248e7dc7..af85ea6f1 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -25,6 +25,7 @@ #include "SketchPlugin_ConstraintDistance.h" #include "SketchPlugin_ConstraintRigid.h" #include "SketchPlugin_ConstraintTangent.h" +#include "SketchPlugin_Ellipse.h" #include "SketchPlugin_Fillet.h" #include "SketchPlugin_Line.h" #include "SketchPlugin_MacroArc.h" @@ -326,17 +327,28 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, aType[i] = aFeature->getKind(); if (aFeature->getKind() != SketchPlugin_Line::ID() && aFeature->getKind() != SketchPlugin_Circle::ID() && - aFeature->getKind() != SketchPlugin_Arc::ID()) { - theError = "The %1 feature kind of attribute is wrong. It should be %2 or %3 or %4"; + aFeature->getKind() != SketchPlugin_Arc::ID() && + aFeature->getKind() != SketchPlugin_Ellipse::ID()) { + theError = "The %1 feature kind of attribute is wrong. It should be %2 or %3 or %4 or %5"; theError.arg(aFeature->getKind()).arg(SketchPlugin_Line::ID()) - .arg(SketchPlugin_Circle::ID()).arg(SketchPlugin_Arc::ID()); + .arg(SketchPlugin_Circle::ID()).arg(SketchPlugin_Arc::ID()) + .arg(SketchPlugin_Ellipse::ID()); // wrong type of attribute return false; } } - if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) && - aType[0] != aType[1]) { + bool isOk = aType[0] == aType[1]; + if (!isOk) { + // circle and arc may be equal + isOk = (aType[0] == SketchPlugin_Arc::ID() && aType[1] == SketchPlugin_Circle::ID()) + || (aType[0] == SketchPlugin_Circle::ID() && aType[1] == SketchPlugin_Arc::ID()); + } + if (!isOk) { + // ellipse and elliptic arc may be equal + // TODO + } + if (!isOk) { theError = "Feature with kinds %1 and %2 can not be equal."; theError.arg(aType[0]).arg(aType[1]); return false; diff --git a/src/SketchPlugin/Test/TestConstraintEqualEllipse.py b/src/SketchPlugin/Test/TestConstraintEqualEllipse.py new file mode 100644 index 000000000..006d18d2d --- /dev/null +++ b/src/SketchPlugin/Test/TestConstraintEqualEllipse.py @@ -0,0 +1,48 @@ +# Copyright (C) 2019 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 +# + +""" + Test constraint "Equal" applied to the pair of ellipses +""" + +from salome.shaper import model +import math + +model.begin() +partSet = model.moduleDocument() +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +SketchEllipse_1 = Sketch_1.addEllipse(-27.88698315421018, 6.197107367602265, -8.725072906579975, 15.87998754592604, 11.10896680773502) +[SketchPoint_1, SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchLine_1, SketchLine_2] = SketchEllipse_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux") +SketchEllipse_2 = Sketch_1.addEllipse(15.14848467636108, -15.95181340919842, 21.12194589112931, -20.27742325437541, 9.877448119278471) +[SketchPoint_8, SketchPoint_9, SketchPoint_10, SketchPoint_11, SketchPoint_12, SketchPoint_13, SketchPoint_14, SketchLine_3, SketchLine_4] = SketchEllipse_2.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux") +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchEllipse_1.result(), SketchEllipse_2.result()) +model.do() +model.end() + +TOLERANCE = 1.e-7 + +dist1 = model.distancePointPoint(SketchEllipse_1.majorAxisNegative(), SketchEllipse_1.majorAxisPositive()) +dist2 = model.distancePointPoint(SketchEllipse_2.majorAxisNegative(), SketchEllipse_2.majorAxisPositive()) +assert(math.fabs(dist1 - dist2) < TOLERANCE) + +dist1 = model.distancePointPoint(SketchEllipse_1.minorAxisNegative(), SketchEllipse_1.minorAxisPositive()) +dist2 = model.distancePointPoint(SketchEllipse_2.minorAxisNegative(), SketchEllipse_2.minorAxisPositive()) +assert(math.fabs(dist1 - dist2) < TOLERANCE) + +assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 319ddd271..8b1c3db31 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -1087,13 +1087,13 @@ icon="icons/Sketch/equal.png" helpfile="equalFeature.html"> + label="First object" tooltip="Select edge" shape_types="edge"> + label="Second object" tooltip="Select edge" shape_types="edge"> diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h index 37aba1bd8..c2893b1f8 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h @@ -39,7 +39,7 @@ typedef int ConstraintID; // Predefined values for identifiers const ConstraintID CID_UNKNOWN = 0; const ConstraintID CID_MOVEMENT = -1; -const ConstraintID CID_FICTIVE = 1024; +const ConstraintID CID_FICTIVE = 99; /// Types of entities enum SketchSolver_EntityType { diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index e3d8f790a..416b338b0 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -245,9 +245,12 @@ void PlaneGCSSolver_Solver::diagnose(const GCS::Algorithm& theAlgo) void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary() { - if (!myConstraints.empty() && - myConstraints.find(CID_MOVEMENT) == myConstraints.end()) - return; + bool hasOnlyMovement = true; + for (ConstraintMap::iterator anIt = myConstraints.begin(); + anIt != myConstraints.end() && hasOnlyMovement; ++anIt) + hasOnlyMovement = anIt->first == CID_MOVEMENT; + if (!hasOnlyMovement) + return; // regular constraints are available too if (myFictiveConstraint) return; // no need several fictive constraints @@ -266,12 +269,14 @@ void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary() void PlaneGCSSolver_Solver::removeFictiveConstraint() { if (myFictiveConstraint) { - myEquationSystem->removeConstraint(myFictiveConstraint); + myEquationSystem->clearByTag(myFictiveConstraint->getTag()); myParameters.pop_back(); GCS::VEC_pD aParams = myFictiveConstraint->params(); - for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++ anIt) - delete *anIt; + for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++anIt) { + double* aPar = *anIt; + delete aPar; + } delete myFictiveConstraint; myFictiveConstraint = 0; } diff --git a/src/SketchSolver/SketchSolver_ConstraintEqual.cpp b/src/SketchSolver/SketchSolver_ConstraintEqual.cpp index 2cb98d4a5..31fcca4a3 100644 --- a/src/SketchSolver/SketchSolver_ConstraintEqual.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintEqual.cpp @@ -38,6 +38,7 @@ void SketchSolver_ConstraintEqual::getAttributes( int aNbLines = 0; int aNbArcs = 0; int aNbCircs = 0; + int aNbEllipses = 0; bool isArcFirst = false; // in line-arc equivalence, the line should be first std::vector::iterator anAttrIt = theAttributes.begin() + 2; for (; anAttrIt != theAttributes.end(); ++anAttrIt) { @@ -50,10 +51,12 @@ void SketchSolver_ConstraintEqual::getAttributes( ++aNbArcs; isArcFirst = (aNbLines == 0); } + else if (aType == ENTITY_ELLIPSE || aType == ENTITY_ELLIPTICAL_ARC) + ++aNbEllipses; } - if (aNbLines + aNbArcs + aNbCircs != 2 || - (aNbLines == aNbCircs && aNbArcs == 0)) { + if (aNbLines + aNbArcs + aNbCircs + aNbEllipses != 2 || + (aNbArcs == 1 && aNbEllipses != 0) || aNbEllipses == 1) { myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); return; } diff --git a/src/SketcherPrs/SketcherPrs_PositionMgr.cpp b/src/SketcherPrs/SketcherPrs_PositionMgr.cpp index 0a546233d..d803256d8 100644 --- a/src/SketcherPrs/SketcherPrs_PositionMgr.cpp +++ b/src/SketcherPrs/SketcherPrs_PositionMgr.cpp @@ -189,7 +189,7 @@ gp_Vec getVector(ObjectPtr theShape, GeomDirPtr theDir, gp_Pnt theP) std::shared_ptr aCurve = std::shared_ptr(new GeomAPI_Curve(aShape)); - if (aCurve->isCircle()) { + if (aCurve->isCircle() || aCurve->isEllipse()) { Handle(Geom_Curve) aCurv = aCurve->impl(); GeomAPI_ProjectPointOnCurve anExtr(theP, aCurv); double aParam = anExtr.LowerDistanceParameter(); -- 2.39.2