From 6c4e803061682cbb1423fe65cd2c1b232e7a95e6 Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 22 Nov 2019 10:47:22 +0300 Subject: [PATCH] Task 3.5 Build/Vertex on a whole Sketch (issue #3079) --- src/BuildPlugin/BuildPlugin_Validators.cpp | 35 ++- src/BuildPlugin/BuildPlugin_Vertex.cpp | 264 +++++------------- src/BuildPlugin/BuildPlugin_Vertex.h | 10 +- src/BuildPlugin/CMakeLists.txt | 4 + src/BuildPlugin/Test/TestVertex.py | 23 +- .../Test/TestVertex_WholeSketch_1.py | 43 +++ .../Test/TestVertex_WholeSketch_2.py | 43 +++ src/GeomAPI/GeomAPI_Vertex.cpp | 20 ++ src/GeomAPI/GeomAPI_Vertex.h | 18 ++ 9 files changed, 231 insertions(+), 229 deletions(-) create mode 100644 src/BuildPlugin/Test/TestVertex_WholeSketch_1.py create mode 100644 src/BuildPlugin/Test/TestVertex_WholeSketch_2.py diff --git a/src/BuildPlugin/BuildPlugin_Validators.cpp b/src/BuildPlugin/BuildPlugin_Validators.cpp index 6b44423f8..99ba50ccb 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.cpp +++ b/src/BuildPlugin/BuildPlugin_Validators.cpp @@ -39,6 +39,8 @@ #include #include +#include + #include //================================================================================================= @@ -519,30 +521,33 @@ bool BuildPlugin_ValidatorBaseForVertex::isValid(const AttributePtr& theAttribut // Vertex? bool isVertex = false; - GeomShapePtr aShapeInList = aSelectionAttr->value(); - if (aShapeInList.get()) { - isVertex = (aShapeInList->shapeType() == GeomAPI_Shape::VERTEX); - } + GeomShapePtr aShape = aSelectionAttr->value(); + ResultPtr aContext = aSelectionAttr->context(); + if (!aShape.get() && aContext.get()) + aShape = aContext->shape(); + if (aShape.get()) + isVertex = (aShape->shapeType() == GeomAPI_Shape::VERTEX); if (!isVertex) { // Sketch? FeaturePtr aFeature = aSelectionAttr->contextFeature(); if (!aFeature.get()) { - ResultPtr aContext = aSelectionAttr->context(); - if (aContext.get()) { + GeomShapePtr aValue = aSelectionAttr->value(); + // whole sketch is allowed only + if (aContext.get() && !aValue.get()) { aFeature = ModelAPI_Feature::feature(aContext); } } - if (aFeature.get()) { - std::string aFeatureKind = aFeature->getKind(); - if (aFeatureKind != "Sketch" && - aFeatureKind != "Point" && - aFeatureKind != "Vertex") { - theError = "Error: %1 shape is not allowed for selection."; - theError.arg(aFeatureKind); - return false; - } + if (!aFeature.get()) { + theError = "Error: Incorrect selection."; + return false; + } + + if (aFeature->getKind() != SketchPlugin_Sketch::ID()) { + theError = "Error: %1 shape is not allowed for selection."; + theError.arg(aFeature->getKind()); + return false; } } } diff --git a/src/BuildPlugin/BuildPlugin_Vertex.cpp b/src/BuildPlugin/BuildPlugin_Vertex.cpp index f2b206177..caed091a2 100644 --- a/src/BuildPlugin/BuildPlugin_Vertex.cpp +++ b/src/BuildPlugin/BuildPlugin_Vertex.cpp @@ -26,7 +26,9 @@ #include #include +#include #include +#include #include #include #include @@ -47,177 +49,88 @@ void BuildPlugin_Vertex::initAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID()); } -//================================================================================================= -bool BuildPlugin_Vertex::buildVertices(GeomShapePtr theShape, - bool isIntersect, - int& theResultIndex) +void BuildPlugin_Vertex::buildVertices(const ListOfShape& theShapes, bool isIntersect) { - if (!theShape.get()) { - setError("Error: Empty shape selected."); - return false; - } - - if (theShape->shapeType() == GeomAPI_Shape::VERTEX) { - // Copy shape. - std::shared_ptr aCopyAlgo(new GeomAlgoAPI_Copy(theShape)); + GeomShapePtr aResult; + std::shared_ptr aPartitionAlgo; + if (isIntersect) { + aPartitionAlgo.reset(new GeomAlgoAPI_Partition(theShapes, ListOfShape())); std::string anError; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) { + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) { setError(anError); - return false; + return; } - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeModified(theShape, aCopyAlgo->shape()); - setResult(aResultBody, theResultIndex); - ++theResultIndex; - } else { - // Sketch - GeomAPI_DataMapOfShapeShape alreadyProcessed; - - // 1. Explode on Vertices - for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); - anExp.more(); anExp.next()) { - GeomShapePtr aSubShape = anExp.current(); + aResult = aPartitionAlgo->shape(); + } + else + aResult = GeomAlgoAPI_CompoundBuilder::compound(theShapes); - if (alreadyProcessed.bind(aSubShape, aSubShape)) { - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeModified(theShape, aSubShape); - setResult(aResultBody, theResultIndex); - ++theResultIndex; - } - } + int aResultIndex = 0; - // 2. If need intersection points, perform Partition - if (isIntersect) { - // Partition - ListOfShape anObjList, aTools; - anObjList.push_back(theShape); - std::shared_ptr aPartitionAlgo ( - new GeomAlgoAPI_Partition(anObjList, aTools)); + // Explode on vertices + std::set aProcessed; + for (GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) { + GeomVertexPtr aVertex(new GeomAPI_Vertex(anExp.current())); + if (aProcessed.find(aVertex) != aProcessed.end()) + continue; // vertex is already processed + aProcessed.insert(aVertex); - std::string anError; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) { - setError(anError); - return false; - } - GeomShapePtr aSplittedSketch = aPartitionAlgo->shape(); + std::shared_ptr aCopy(new GeomAlgoAPI_Copy(aVertex)); + aVertex.reset(new GeomAPI_Vertex(aCopy->shape())); - // Explode on Vertices, skip vertices of initial sketch - for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); - anExp.more(); anExp.next()) { - GeomShapePtr aSubShape = anExp.current(); + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList); + if (aPartitionAlgo) + aMakeShapeList->appendAlgo(aPartitionAlgo); + aMakeShapeList->appendAlgo(aCopy); - //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch - if (alreadyProcessed.bind(aSubShape, aSubShape)) { - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo); - setResult(aResultBody, theResultIndex); - ++theResultIndex; - } - } - } + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + aResultBody->storeModified(theShapes, aVertex, aMakeShapeList); + setResult(aResultBody, aResultIndex); + ++aResultIndex; } - return true; + removeResults(aResultIndex); } -//================================================================================================= -bool BuildPlugin_Vertex::buildVertices(FeaturePtr theFeature, - bool isIntersect, - int& theResultIndex) +static void collectEdgesAndVertices(AttributeSelectionPtr theSelection, ListOfShape& thePrimitives) { - if (theFeature->getKind() != "Sketch") return false; - - // Sub-features - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(theFeature); - if (!aComposite) return false; - int nbSubs = aComposite->numberOfSubs(); - if (nbSubs < 1) return false; - - // The whole sketch shape - ResultPtr aContext = theFeature->firstResult(); - GeomShapePtr theShape = aContext->shape(); - - GeomAPI_DataMapOfShapeShape alreadyProcessed; - - // 1. Explode on Vertices - for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) { - GeomShapePtr aSubShape = anExp.current(); - - if (alreadyProcessed.bind(aSubShape, aSubShape)) { - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeModified(theShape, aSubShape); - setResult(aResultBody, theResultIndex); - ++theResultIndex; - } - } - - // 2. If need intersection points, perform Partition - if (isIntersect) { - // Partition - ListOfShape anObjList, aTools; - anObjList.push_back(theShape); - std::shared_ptr aPartitionAlgo ( - new GeomAlgoAPI_Partition(anObjList, aTools)); - - std::string anError; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) { - setError(anError); - return false; - } - GeomShapePtr aSplittedSketch = aPartitionAlgo->shape(); - - // Explode on Vertices, skip vertices of initial sketch - for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); - anExp.more(); anExp.next()) { - GeomShapePtr aSubShape = anExp.current(); - - //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch - if (alreadyProcessed.bind(aSubShape, aSubShape)) { - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo); - setResult(aResultBody, theResultIndex); - ++theResultIndex; + FeaturePtr aFeature = theSelection->contextFeature(); + ResultPtr aContext = theSelection->context(); + GeomShapePtr aShape = theSelection->value(); + if (aShape) + thePrimitives.push_back(aShape); + else { + if (aContext && !aFeature) + aFeature = ModelAPI_Feature::feature(aContext); + if (!aFeature) + return; + + // process results of the feature + const std::list& aResults = aFeature->results(); + std::list::const_iterator anIt = aResults.begin(); + for (; anIt != aResults.end(); ++anIt) + thePrimitives.push_back((*anIt)->shape()); + + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aFeature); + if (!aComposite) + return; + + // add construction points (centers of circles, etc.) + for (int i = 0, nbSubs = aComposite->numberOfSubs(); i < nbSubs; ++i) { + FeaturePtr aSubFeature = aComposite->subFeature(i); + const std::list& aSubResults = aSubFeature->results(); + // find all points + for (anIt = aSubResults.begin(); anIt != aSubResults.cend(); ++anIt) { + GeomShapePtr aSubResShape = (*anIt)->shape(); + if (aSubResShape->isVertex()) + thePrimitives.push_back(aSubResShape); } } } - - // 3. Add construction points (centers of circles, etc.) - for (int i = 0; i < nbSubs; i++) { - FeaturePtr aSubFeature = aComposite->subFeature(i); - const std::list& aSubResults = aSubFeature->results(); - std::list::const_iterator anItRes = aSubResults.cbegin(); - // Iterate on all sub-results - for (; anItRes != aSubResults.cend(); anItRes++) { - ResultPtr aRes = *anItRes; - if (aRes.get()) { - // Sub-result i - GeomShapePtr aSubResShape = aRes->shape(); - - for (GeomAPI_ShapeExplorer anExp (aSubResShape, GeomAPI_Shape::VERTEX); - anExp.more(); anExp.next()) { - GeomShapePtr aSubShape = anExp.current(); - - if (alreadyProcessed.bind(aSubShape, aSubShape)) { - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - aResultBody->storeModified(theShape, aSubShape); - setResult(aResultBody, theResultIndex); - ++theResultIndex; - } - } - } - } - } - - return true; } void BuildPlugin_Vertex::execute() @@ -239,51 +152,12 @@ void BuildPlugin_Vertex::execute() isIntersect = boolean(INTERSECT_ID())->value(); } - // Iterate arguments and build results - int aResultIndex = 0; + // Iterate arguments and collect shapes + ListOfShape aShapes; for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); - GeomShapePtr aShape = aSelection->value(); - if (aShape.get()) { - // A shape selected - if (!buildVertices(aShape, isIntersect, aResultIndex)) return; - } else { - ResultPtr aContext = aSelection->context(); - if (aContext.get()) { // Result selected - FeaturePtr aFeature = ModelAPI_Feature::feature(aContext); - if (aFeature.get()) { - if (aFeature->getKind() == "Sketch") { - // Special processing for sketch to build center vertices etc. - if (!buildVertices(aFeature, isIntersect, aResultIndex)) return; - } else { - aShape = aContext->shape(); - if (!buildVertices(aShape, isIntersect, aResultIndex)) return; - } - } - } else { - FeaturePtr aFeature = aSelection->contextFeature(); - if (aFeature.get()) { // Feature selected - if (aFeature->getKind() == "Sketch") { - // Special processing for sketch to build center vertices etc. - if (!buildVertices(aFeature, isIntersect, aResultIndex)) return; - } else { - const std::list& anArgResults = aFeature->results(); - std::list::const_iterator anItRes = anArgResults.cbegin(); - // Iterate on all its results - for (; anItRes != anArgResults.cend(); anItRes++) { - ResultPtr aRes = *anItRes; - if (aRes.get()) { - // Result i - aShape = aRes->shape(); - if (!buildVertices(aShape, isIntersect, aResultIndex)) return; - } - } - } - } - } - } + collectEdgesAndVertices(aSelection, aShapes); } - // Remove extra results from previous execution - removeResults(aResultIndex); + buildVertices(aShapes, isIntersect); } diff --git a/src/BuildPlugin/BuildPlugin_Vertex.h b/src/BuildPlugin/BuildPlugin_Vertex.h index d6dfa9c78..980dd8201 100644 --- a/src/BuildPlugin/BuildPlugin_Vertex.h +++ b/src/BuildPlugin/BuildPlugin_Vertex.h @@ -68,14 +68,8 @@ public: /// Creates a new part document if needed. BUILDPLUGIN_EXPORT virtual void execute(); - protected: - bool buildVertices(GeomShapePtr theShape, - bool isIntersect, - int& theResultIndex); - - bool buildVertices(FeaturePtr theFeature, - bool isIntersect, - int& theResultIndex); +protected: + void buildVertices(const ListOfShape& theShapes, bool isIntersect); }; #endif diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index 1d1bf847c..121f992cf 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -25,7 +25,9 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/ModelAPI ${PROJECT_SOURCE_DIR}/src/GeomAPI ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI + ${PROJECT_SOURCE_DIR}/src/GeomDataAPI ${PROJECT_SOURCE_DIR}/src/GeomValidators + ${PROJECT_SOURCE_DIR}/src/SketchPlugin ) SET(PROJECT_HEADERS @@ -108,6 +110,8 @@ INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Build ADD_UNIT_TESTS(TestVertex.py TestVertex_ErrorMsg.py + TestVertex_WholeSketch_1.py + TestVertex_WholeSketch_2.py TestEdge.py TestEdge_ByPoints.py TestEdge_ErrorMsg.py diff --git a/src/BuildPlugin/Test/TestVertex.py b/src/BuildPlugin/Test/TestVertex.py index e2b936990..8f086716c 100644 --- a/src/BuildPlugin/Test/TestVertex.py +++ b/src/BuildPlugin/Test/TestVertex.py @@ -75,33 +75,34 @@ aSession.finishOperation() # Test results assert (len(aVertexFeature.results()) == aNumOfPoints) -# Check Vertex feature failed on incorrect input +# Check Vertex feature correct on a whole sketch aSession.startOperation() aVertexFeature2 = aPart.addFeature("Vertex") aBaseObjectsList = aVertexFeature2.selectionList("base_objects") aBaseObjectsList.append(aSketchResult, None) aSession.finishOperation() -assert (len(aVertexFeature2.results()) == 10) +assert (len(aVertexFeature2.results()) == aNumOfPoints) +# Check Vertex feature failed on incorrect input aSession.startOperation() aLine = aSketchFeature.addFeature("SketchLine") geomDataAPI_Point2D(aLine.attribute("StartPoint")).setValue(0, 0) geomDataAPI_Point2D(aLine.attribute("EndPoint")).setValue(100, 100) aSession.finishOperation() aSession.startOperation() -aBaseObjectsList.clear() +aPart.setCurrentFeature(aVertexFeature2, False) +aSession.finishOperation() +aSession.startOperation() +aVertexFeature3 = aPart.addFeature("Vertex") +aBaseObjectsList = aVertexFeature3.selectionList("base_objects") aBaseObjectsList.append(aSketchResult, aLine.lastResult().shape()) aSession.finishOperation() -assert (len(aVertexFeature2.results()) == 0) - -# Check Vertex feature failed on incorrect input -# TODO +assert (len(aVertexFeature3.results()) == 0) # remove failed feature -#aSession.startOperation() -#aPart.removeFeature(aVertexFeature2) -#aPart.setCurrentFeature(aVertexFeature, True) -#aSession.finishOperation() +aSession.startOperation() +aPart.removeFeature(aVertexFeature3) +aSession.finishOperation() from salome.shaper import model assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestVertex_WholeSketch_1.py b/src/BuildPlugin/Test/TestVertex_WholeSketch_1.py new file mode 100644 index 000000000..1bc8fde66 --- /dev/null +++ b/src/BuildPlugin/Test/TestVertex_WholeSketch_1.py @@ -0,0 +1,43 @@ +# 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 +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Vertex_1 = model.addVertex(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False) +model.end() + +model.testNbResults(Vertex_1, 7) +model.testNbSubShapes(Vertex_1, GeomAPI_Shape.VERTEX, [1, 1, 1, 1, 1, 1, 1]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestVertex_WholeSketch_2.py b/src/BuildPlugin/Test/TestVertex_WholeSketch_2.py new file mode 100644 index 000000000..b79a7d90f --- /dev/null +++ b/src/BuildPlugin/Test/TestVertex_WholeSketch_2.py @@ -0,0 +1,43 @@ +# 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 +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Vertex_1 = model.addVertex(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True) +model.end() + +model.testNbResults(Vertex_1, 9) +model.testNbSubShapes(Vertex_1, GeomAPI_Shape.VERTEX, [1, 1, 1, 1, 1, 1, 1, 1, 1]) + +assert(model.checkPythonDump()) diff --git a/src/GeomAPI/GeomAPI_Vertex.cpp b/src/GeomAPI/GeomAPI_Vertex.cpp index 683413c63..5025a6aaa 100644 --- a/src/GeomAPI/GeomAPI_Vertex.cpp +++ b/src/GeomAPI/GeomAPI_Vertex.cpp @@ -75,3 +75,23 @@ bool GeomAPI_Vertex::isEqual(const std::shared_ptr theVert) const return aPoint1.IsEqual(aPoint2, Precision::Confusion()) == Standard_True; } + + + +bool GeomAPI_Vertex::GeometricComparator::operator()(const GeomVertexPtr& theVertex1, + const GeomVertexPtr& theVertex2) const +{ + const TopoDS_Vertex& aVertex1 = theVertex1->impl(); + const TopoDS_Vertex& aVertex2 = theVertex2->impl(); + + gp_Pnt aPnt1 = BRep_Tool::Pnt(aVertex1); + gp_Pnt aPnt2 = BRep_Tool::Pnt(aVertex2); + + bool isLess = aPnt1.X() + myTolerance < aPnt2.X(); + if (!isLess && aPnt1.X() <= aPnt2.X() + myTolerance) { + isLess = aPnt1.Y() + myTolerance < aPnt2.Y(); + if (!isLess && aPnt1.Y() <= aPnt2.Y() + myTolerance) + isLess = aPnt1.Z() + myTolerance < aPnt2.Z(); + } + return isLess; +} diff --git a/src/GeomAPI/GeomAPI_Vertex.h b/src/GeomAPI/GeomAPI_Vertex.h index 13668b6af..5c564f842 100644 --- a/src/GeomAPI/GeomAPI_Vertex.h +++ b/src/GeomAPI/GeomAPI_Vertex.h @@ -49,6 +49,24 @@ public: /// Returns true if the current edge is geometrically equal to the given edge. GEOMAPI_EXPORT virtual bool isEqual(const std::shared_ptr theVert) const; + +public: + /// \brief Compare vertices geometrically + class GeometricComparator + { + public: + GEOMAPI_EXPORT + GeometricComparator(const double theTolerance = 1.e-7) : myTolerance(theTolerance) + {} + + /// Return \c true if the first vertex is less than the second + GEOMAPI_EXPORT + bool operator ()(const std::shared_ptr& theVertex1, + const std::shared_ptr& theVertex2) const; + private: + double myTolerance; + }; + }; //! Pointer on the object -- 2.39.2