From b60ce2a70225781dbb35bd810337ed2e81880608 Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Sat, 25 Apr 2020 14:43:00 +0300 Subject: [PATCH] Issue #3222: 1d fillet * Additional test cases for filleting several wires at once. * Stabilize the sequence of fillet results. --- src/FeaturesPlugin/CMakeLists.txt | 2 + .../FeaturesPlugin_Fillet1D.cpp | 23 ++++-- src/FeaturesPlugin/FeaturesPlugin_Fillet1D.h | 2 +- .../Test/TestFillet1D_Vertices_2.py | 4 +- .../Test/TestFillet1D_Vertices_3.py | 2 +- .../Test/TestFillet1D_Vertices_9.py | 70 +++++++++++++++++++ .../Test/TestFillet1D_Wire_5.py | 59 ++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp | 9 +++ 8 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestFillet1D_Vertices_9.py create mode 100644 src/FeaturesPlugin/Test/TestFillet1D_Wire_5.py diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index b75a1a17e..761c60350 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -670,8 +670,10 @@ ADD_UNIT_TESTS(TestExtrusion.py TestFillet1D_Vertices_6.py TestFillet1D_Vertices_7.py TestFillet1D_Vertices_8.py + TestFillet1D_Vertices_9.py TestFillet1D_Wire_1.py TestFillet1D_Wire_2.py TestFillet1D_Wire_3.py TestFillet1D_Wire_4.py + TestFillet1D_Wire_5.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.cpp b/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.cpp index d62f6acf4..ee83fad20 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.cpp @@ -47,24 +47,25 @@ void FeaturesPlugin_Fillet1D::initAttributes() void FeaturesPlugin_Fillet1D::execute() { - MapShapeSubs aWireVertices; - if (!baseShapes(aWireVertices)) + ListOfShape aWires; + MapShapeSubs aVertices; + if (!baseShapes(aWires, aVertices)) return; int aResultIndex = 0; - for (MapShapeSubs::iterator anIt = aWireVertices.begin(); anIt != aWireVertices.end(); ++anIt) - if (!performFillet(anIt->first, anIt->second, aResultIndex++)) + for (ListOfShape::iterator anIt = aWires.begin(); anIt != aWires.end(); ++anIt) + if (!performFillet(*anIt, aVertices[*anIt], aResultIndex++)) break; removeResults(aResultIndex); } -bool FeaturesPlugin_Fillet1D::baseShapes(MapShapeSubs& theWireVertices) +bool FeaturesPlugin_Fillet1D::baseShapes(ListOfShape& theWires, MapShapeSubs& theWireVertices) { + std::set aProcessedWires; std::string aMethod = string(CREATION_METHOD())->value(); if (aMethod == CREATION_BY_WIRES()) { AttributeSelectionListPtr aSelList = selectionList(WIRE_LIST_ID()); - std::set aProcessedWires; int aNbSel = aSelList->size(); for (int ind = 0; ind < aNbSel; ++ind) { AttributeSelectionPtr aCurSel = aSelList->value(ind); @@ -106,7 +107,8 @@ bool FeaturesPlugin_Fillet1D::baseShapes(MapShapeSubs& theWireVertices) } - // keep the sequence of fillet vertices stable + // keep the sequence of wires and fillet vertices stable + theWires.push_back(aWire); for (GeomAPI_WireExplorer anExp(aWire->wire()); anExp.more(); anExp.next()) { GeomShapePtr aVertex = anExp.currentVertex(); if (aFilletVertices.find(aVertex) != aFilletVertices.end()) @@ -121,6 +123,13 @@ bool FeaturesPlugin_Fillet1D::baseShapes(MapShapeSubs& theWireVertices) AttributeSelectionPtr aCurSel = aSelList->value(ind); GeomShapePtr aWire = aCurSel->context()->shape(); GeomShapePtr aVertex = aCurSel->value(); + + // keep the sequence of wires stable + if (aProcessedWires.find(aWire) == aProcessedWires.end()) { + theWires.push_back(aWire); + aProcessedWires.insert(aWire); + } + theWireVertices[aWire].push_back(aVertex); } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.h b/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.h index de2a38024..961d69ee4 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Fillet1D.h @@ -100,7 +100,7 @@ public: private: /// Get the list of wires and fillet vertices /// \retun \c false if errors occured - bool baseShapes(MapShapeSubs& theWireVertices); + bool baseShapes(ListOfShape& theWires, MapShapeSubs& theWireVertices); /// Run fillet operation and store result. /// \return \c false if fillet failed. diff --git a/src/FeaturesPlugin/Test/TestFillet1D_Vertices_2.py b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_2.py index 8bd49a151..295f22663 100644 --- a/src/FeaturesPlugin/Test/TestFillet1D_Vertices_2.py +++ b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_2.py @@ -46,7 +46,7 @@ model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.VERTEX, [18]) model.testResultsVolumes(Fillet1D_1, [0]) ### Create Fillet1D -Fillet1D_2 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Wire_1_1/Edge_1]e[Wire_1_1/Edge_3]e")], 1) +Fillet1D_2 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_1]e[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_3]e")], 1) model.testNbResults(Fillet1D_2, 1) model.testNbSubResults(Fillet1D_2, [0]) @@ -57,7 +57,7 @@ model.testNbSubShapes(Fillet1D_2, GeomAPI_Shape.VERTEX, [20]) model.testResultsVolumes(Fillet1D_2, [0]) ### Create Fillet1D -Fillet1D_3 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[(Wire_1_1/Edge_8)4(Wire_1_1/Edge_5)4_Fillet1D_2_1]e[(Wire_1_1/Edge_8)3(Wire_1_1/Edge_7)4_Fillet1D_2_1]e")], 5) +Fillet1D_3 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Fillet1D_2_1/ME:Fillet1D&Wire_1_1/Edge_2]e[Fillet1D_2_1/ME:Fillet1D&Wire_1_1/Edge_4]e")], 5) model.testHaveNamingByType(Fillet1D_3, model, Part_1_doc, GeomAPI_Shape.VERTEX) model.testHaveNamingByType(Fillet1D_3, model, Part_1_doc, GeomAPI_Shape.EDGE) diff --git a/src/FeaturesPlugin/Test/TestFillet1D_Vertices_3.py b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_3.py index 37e0ee235..2d1a78b7a 100644 --- a/src/FeaturesPlugin/Test/TestFillet1D_Vertices_3.py +++ b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_3.py @@ -46,7 +46,7 @@ model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.VERTEX, [12]) model.testResultsVolumes(Fillet1D_1, [0]) ### Create Fillet1D -Fillet1D_2 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Wire_1_1/Edge_4]e[Wire_1_1/Edge_3]e")], 3) +Fillet1D_2 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_4]e[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_3]e")], 3) model.testHaveNamingByType(Fillet1D_2, model, Part_1_doc, GeomAPI_Shape.VERTEX) model.testHaveNamingByType(Fillet1D_2, model, Part_1_doc, GeomAPI_Shape.EDGE) diff --git a/src/FeaturesPlugin/Test/TestFillet1D_Vertices_9.py b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_9.py new file mode 100644 index 000000000..2305d0cc3 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestFillet1D_Vertices_9.py @@ -0,0 +1,70 @@ +# Copyright (C) 2020 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() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Box +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Wire_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")] + +### Create Wire +Wire_1 = model.addWire(Part_1_doc, Wire_1_objects, False) + +### Create Recover +Recover_1 = model.addRecover(Part_1_doc, Wire_1, [Box_1.result()]) + +### Create Wire +Wire_2_objects = [model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Right][Recover_1_1/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Back][Recover_1_1/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Back][Recover_1_1/Modified_Face&Box_1_1/Top]")] +Wire_2 = model.addWire(Part_1_doc, Wire_2_objects, False) + +### Create Fillet1D +Fillet1D_1 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Wire_1_1/Edge_1]e[Wire_1_1/Edge_2]e"), model.selection("VERTEX", "[Wire_2_1/Edge_2]e[Wire_2_1/Edge_3]e")], 2) + +model.testNbResults(Fillet1D_1, 2) +model.testNbSubResults(Fillet1D_1, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.SOLID, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.FACE, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.EDGE, [4, 4]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.VERTEX, [8, 8]) +model.testResultsVolumes(Fillet1D_1, [0, 0]) + +### Create Fillet1D +Fillet1D_2 = model.addFillet(Part_1_doc, [model.selection("VERTEX", "[Fillet1D_1_2/ME:Fillet1D&Wire_2_1/Edge_1]e[Fillet1D_1_2/ME:Fillet1D&Wire_2_1/Edge_2]e"), model.selection("VERTEX", "[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_2]e[Fillet1D_1_1/ME:Fillet1D&Wire_1_1/Edge_3]e")], 5) + +model.testHaveNamingByType(Fillet1D_2, model, Part_1_doc, GeomAPI_Shape.VERTEX) +model.testHaveNamingByType(Fillet1D_2, model, Part_1_doc, GeomAPI_Shape.EDGE) +model.end() + +model.testNbResults(Fillet1D_2, 2) +model.testNbSubResults(Fillet1D_2, [0, 0]) +model.testNbSubShapes(Fillet1D_2, GeomAPI_Shape.SOLID, [0, 0]) +model.testNbSubShapes(Fillet1D_2, GeomAPI_Shape.FACE, [0, 0]) +model.testNbSubShapes(Fillet1D_2, GeomAPI_Shape.EDGE, [5, 5]) +model.testNbSubShapes(Fillet1D_2, GeomAPI_Shape.VERTEX, [10, 10]) +model.testResultsVolumes(Fillet1D_2, [0, 0]) + +assert(model.checkPythonDump(model.ModelHighAPI.CHECK_NAMING)) diff --git a/src/FeaturesPlugin/Test/TestFillet1D_Wire_5.py b/src/FeaturesPlugin/Test/TestFillet1D_Wire_5.py new file mode 100644 index 000000000..b05c0c685 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestFillet1D_Wire_5.py @@ -0,0 +1,59 @@ +# Copyright (C) 2020 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() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Box +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Wire_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")] + +### Create Wire +Wire_1 = model.addWire(Part_1_doc, Wire_1_objects, False) + +### Create Recover +Recover_1 = model.addRecover(Part_1_doc, Wire_1, [Box_1.result()]) + +### Create Wire +Wire_2_objects = [model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Right][Recover_1_1/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Back][Recover_1_1/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "[Recover_1_1/Modified_Face&Box_1_1/Back][Recover_1_1/Modified_Face&Box_1_1/Top]")] +Wire_2 = model.addWire(Part_1_doc, Wire_2_objects, False) + +### Create Fillet1D +Fillet1D_1 = model.addFillet(Part_1_doc, [model.selection("WIRE", "Wire_1_1"), model.selection("WIRE", "Wire_2_1")], 2) + +model.testHaveNamingByType(Fillet1D_1, model, Part_1_doc, GeomAPI_Shape.VERTEX) +model.testHaveNamingByType(Fillet1D_1, model, Part_1_doc, GeomAPI_Shape.EDGE) +model.end() + +model.testNbResults(Fillet1D_1, 2) +model.testNbSubResults(Fillet1D_1, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.SOLID, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.FACE, [0, 0]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.EDGE, [5, 5]) +model.testNbSubShapes(Fillet1D_1, GeomAPI_Shape.VERTEX, [10, 10]) +model.testResultsVolumes(Fillet1D_1, [0, 0]) + +assert(model.checkPythonDump(model.ModelHighAPI.CHECK_NAMING)) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp index 5eca5b879..344ac9415 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp @@ -18,6 +18,8 @@ // #include + +#include #include #include @@ -71,6 +73,13 @@ void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, if (!theBaseWire || theFilletVertices.empty() || theRadius < 0.) return; + // store all edges of a base wire as modified, because they will be rebuild by ShapeFix + for (GeomAPI_WireExplorer aWExp(theBaseWire->wire()); aWExp.more(); aWExp.next()) { + GeomShapePtr aCurrent = aWExp.current(); + GeomAlgoAPI_Copy aCopy(aCurrent); + myModified[aCurrent].push_back(aCopy.shape()); + } + GeomAlgoAPI_MapShapesAndAncestors aMapVE(theBaseWire, GeomAPI_Shape::VERTEX, GeomAPI_Shape::EDGE); -- 2.39.2