From daa80087c6017c6a7c6d75a735566a9eb88e0e0f Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 18 Jul 2017 13:38:34 +0300 Subject: [PATCH] Fix for the issue #2197 : additional cases where full revolution consists of 3 and 4 faces. --- src/FeaturesPlugin/CMakeLists.txt | 2 + .../FeaturesPlugin_CompositeSketch.cpp | 42 +++++++++++- src/FeaturesPlugin/Test/Test2197_3.py | 51 ++++++++++++++ src/FeaturesPlugin/Test/Test2197_4.py | 67 +++++++++++++++++++ src/GeomAPI/GeomAPI_Edge.cpp | 8 +++ src/GeomAPI/GeomAPI_Edge.h | 4 ++ 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/FeaturesPlugin/Test/Test2197_3.py create mode 100644 src/FeaturesPlugin/Test/Test2197_4.py diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 07d22019c..6a6519bdd 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -171,5 +171,7 @@ ADD_UNIT_TESTS(TestExtrusion.py Test2194.py Test2197_1.py Test2197_2.py + Test2197_3.py + Test2197_4.py Test2215.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index 676023d31..fa7772205 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -344,7 +344,12 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes theMakeShape->generated(anEdgeExp.current(), aGenerated); ListOfShape::iterator aGenIter = aGenerated.begin(); for(; aGenIter != aGenerated.end(); aGenIter++) { - aFacesFromFromEdges.bind(*aGenIter, anEdgeExp.current()); + GeomShapePtr aGen = *aGenIter; + if (aGen.get() && !aGen->isNull()) { + if ((*aGenIter)->shapeType() == GeomAPI_Shape::FACE) { // normal case + aFacesFromFromEdges.bind(aGen, anEdgeExp.current()); + } + } } } @@ -383,6 +388,41 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes } } } + } else { // issue #2197, test case 4 : edges that produce fully-revolved face, + // but contain only 2 edges (on apex of revolution) + GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE); + for(int anIndex = 1; anEdgeExp.more(); anEdgeExp.next()) { + ListOfShape aGenerated; + theMakeShape->generated(anEdgeExp.current(), aGenerated); + ListOfShape::iterator aGenIter = aGenerated.begin(); + for(; aGenIter != aGenerated.end(); aGenIter++) { + GeomShapePtr aGen = (*aGenIter); + if (aGen.get() && !aGen->isNull()) { + GeomAPI_ShapeExplorer aFaceEdgeExp(aGen, GeomAPI_Shape::EDGE); + int aNumEdges = 0; + int aNumClosed = 0; + GeomShapePtr aNotClosedEdge; + GeomAPI_DataMapOfShapeShape alreadyIterated; + for(; aFaceEdgeExp.more(); aFaceEdgeExp.next()) { + std::shared_ptr anEdge(new GeomAPI_Edge(aFaceEdgeExp.current())); + if (anEdge->isDegenerated() || alreadyIterated.isBound(anEdge)) + continue; + alreadyIterated.bind(anEdge, anEdge); + aNumEdges++; + if (anEdge->isClosed()) { + aNumClosed++; + } else { + aNotClosedEdge = anEdge; + } + } + if (aNumEdges == 2 && aNumClosed == 1) { + std::ostringstream aStream; + aStream<<"Base_Edge_"<generated(aNotClosedEdge, aStream.str(), theTag++); + } + } + } + } } } diff --git a/src/FeaturesPlugin/Test/Test2197_3.py b/src/FeaturesPlugin/Test/Test2197_3.py new file mode 100644 index 000000000..e07e3e154 --- /dev/null +++ b/src/FeaturesPlugin/Test/Test2197_3.py @@ -0,0 +1,51 @@ +## Copyright (C) 2014-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 +## + +# revolution of 3-edges contour (4th is used as axis of rotation) is checking for naming of edges +from salome.shaper import model + +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("XOZ")) +SketchLine_1 = Sketch_1.addLine(138, 47, 265, 35) +SketchLine_2 = Sketch_1.addLine(265, 35, 248, 186) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(248, 186, 138, 234) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(138, 234, 138, 47) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint()) +model.do() +Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), 360, 0) +Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_4"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_1_1/Lateral_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Base_Edge_3")]) +model.end() + +# check that resulting group selection is valid +from ModelAPI import * +aFactory = ModelAPI_Session.get().validators() +assert(aFactory.validate(Group_1.feature())) +assert(Group_1.groupList().size() == 5) +for a in range(5): + assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE") + assert(len(Group_1.groupList().value(a).namingName()) > 0) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/Test2197_4.py b/src/FeaturesPlugin/Test/Test2197_4.py new file mode 100644 index 000000000..9ebe471a7 --- /dev/null +++ b/src/FeaturesPlugin/Test/Test2197_4.py @@ -0,0 +1,67 @@ +## Copyright (C) 2014-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 +## + +# revolution of 4-edges contour (5th is used as axis of rotation) is checking for naming of edges + +from salome.shaper import model + +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("XOZ")) +SketchLine_1 = Sketch_1.addLine(138.1074168797953, 47.3145780051151, 265.9846547314579, 35.80562659846547) +SketchLine_2 = Sketch_1.addLine(248.0818414322251, 186.7007672634271, 138.1074168797954, 234.0153452685422) +SketchLine_2.setName("SketchLine_3") +SketchLine_2.result().setName("SketchLine_3") +SketchLine_3 = Sketch_1.addLine(138.1074168797954, 234.0153452685422, 138.1074168797953, 47.3145780051151) +SketchLine_3.setName("SketchLine_4") +SketchLine_3.result().setName("SketchLine_4") +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_1.setName("SketchConstraintCoincidence_3") +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint()) +SketchConstraintCoincidence_2.setName("SketchConstraintCoincidence_4") +SketchLine_4 = Sketch_1.addLine(248.0818414322251, 186.7007672634271, 215.8394027534853, 111.2328618876045) +SketchLine_4.setName("SketchLine_5") +SketchLine_4.result().setName("SketchLine_5") +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_3.setName("SketchConstraintCoincidence_5") +SketchLine_5 = Sketch_1.addLine(215.8394027534853, 111.2328618876045, 265.9846547314579, 35.80562659846547) +SketchLine_5.setName("SketchLine_6") +SketchLine_5.result().setName("SketchLine_6") +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_4.setName("SketchConstraintCoincidence_6") +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_5.endPoint()) +SketchConstraintCoincidence_5.setName("SketchConstraintCoincidence_7") +model.do() +Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5r-SketchLine_6r")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), 360, 0) +Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Generated_Face_5&Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_3&Revolution_1_1/Generated_Face_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_2")]) +model.end() + +# check that resulting group selection is valid +from ModelAPI import * +aFactory = ModelAPI_Session.get().validators() +assert(aFactory.validate(Group_1.feature())) +assert(Group_1.groupList().size() == 7) +for a in range(7): + assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE") + assert(len(Group_1.groupList().value(a).namingName()) > 0) + +assert(model.checkPythonDump()) diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp index 1fd744fd4..b0ee1e009 100644 --- a/src/GeomAPI/GeomAPI_Edge.cpp +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -261,3 +261,11 @@ bool GeomAPI_Edge::isClosed() const return fabs(aFirst - aLast) < 1.e-9; } + +bool GeomAPI_Edge::isDegenerated() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + if (aShape.IsNull() || aShape.ShapeType() != TopAbs_EDGE) + return false; + return BRep_Tool::Degenerated(TopoDS::Edge(aShape)); +} diff --git a/src/GeomAPI/GeomAPI_Edge.h b/src/GeomAPI/GeomAPI_Edge.h index c1a0c1eaa..f4fd1add6 100644 --- a/src/GeomAPI/GeomAPI_Edge.h +++ b/src/GeomAPI/GeomAPI_Edge.h @@ -91,6 +91,10 @@ public: /// Returns true if the edge is closed (like full circle) GEOMAPI_EXPORT bool isClosed() const; + + /// Returns true if the edge is degenerated (has no 3D curve) + GEOMAPI_EXPORT + bool isDegenerated() const; }; #endif -- 2.39.2