From: mpv Date: Tue, 17 Sep 2019 09:48:10 +0000 (+0300) Subject: Task #3005 : To be able to create a group on a whole result X-Git-Tag: V9_4_0a2~4^2~90 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=2cb4458b35ae6c9561a35b3b18dbdb673d0c12c9;p=modules%2Fshaper.git Task #3005 : To be able to create a group on a whole result Implementation of move in the history of the whole objects. --- diff --git a/src/CollectionPlugin/CMakeLists.txt b/src/CollectionPlugin/CMakeLists.txt index fa72858f4..611fbc3d7 100644 --- a/src/CollectionPlugin/CMakeLists.txt +++ b/src/CollectionPlugin/CMakeLists.txt @@ -138,6 +138,11 @@ ADD_UNIT_TESTS( TestGroupMove18.py TestGroupMove19.py TestGroupMove20.py + TestGroupMove21.py + TestGroupMove22.py + TestGroupMove23.py + TestGroupMove24.py + TestGroupMove25.py TestGroupShareTopology.py TestGroupAddition.py TestGroupAddition_Error.py diff --git a/src/CollectionPlugin/Test/TestGroupMove21.py b/src/CollectionPlugin/Test/TestGroupMove21.py new file mode 100644 index 000000000..4dda28f9c --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove21.py @@ -0,0 +1,60 @@ +# Copyright (C) 2014-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 move the group in history for selection of a whole result + +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(35.07635467980296, 23.01108374384237, -25.74753694581282, 23.01108374384237) +SketchLine_2 = Sketch_1.addLine(-25.74753694581282, 23.01108374384237, -25.74753694581282, -23.13546798029557) +SketchLine_3 = Sketch_1.addLine(-25.74753694581282, -23.13546798029557, 35.07635467980296, -23.13546798029557) +SketchLine_4 = Sketch_1.addLine(35.07635467980296, -23.13546798029557, 35.07635467980296, 23.01108374384237) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 80, 0) +# selection of a whole result: 6 faces of a box +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_1")]) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [6]) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3")) +SketchCircle_1 = Sketch_2.addCircle(-7.736745115674536, 52.14422040986419, 6.760003867274182) +ExtrusionCut_1.setNestedSketch(Sketch_2) +model.do() +# move group after the extrusion-cut, so, it refers to it +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature()) +model.end() + +# check that there is a hole appeared in the group-results +assert(len(Group_1.feature().results())==1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [8]) + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMove22.py b/src/CollectionPlugin/Test/TestGroupMove22.py new file mode 100644 index 000000000..40802c631 --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove22.py @@ -0,0 +1,62 @@ +# Copyright (C) 2014-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 move the group in history for selection of a whole result of a compsolid + +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(-25.00123152709361, 27.48891625615764, 27.86206896551725, 27.48891625615764) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchLine_2 = Sketch_1.addLine(27.86206896551725, 27.48891625615764, -23.88177339901478, -20.02586206896552) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(-23.88177339901478, -20.02586206896552, 28.73275862068966, -20.02586206896552) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchLine_4 = Sketch_1.addLine(28.73275862068966, -20.02586206896552, 27.86206896551725, 27.48891625615764) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.endPoint()) +SketchLine_5 = Sketch_1.addLine(-25.00123152709361, 27.48891625615764, 28.73275862068966, -20.02586206896552) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint()) +model.do() +Extrusion_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchLine_5f-SketchLine_2r-SketchLine_1r"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_5f-SketchLine_4f"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_3f-SketchLine_5r")] +Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection(), 10, 0) +# selection of a whole result: 5x3-2 faces (2 faces are shared) +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPSOLID", "Extrusion_1_1")]) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [13]) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("COMPSOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1_1/To_Face")) +SketchCircle_1 = Sketch_2.addCircle(13.4282260278248, 11.79859034244854, 3.718064241992405) +ExtrusionCut_1.setNestedSketch(Sketch_2) +model.do() +# move group after the extrusion-cut, so, it refers to it +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature()) +model.end() + +# check that there is a hole appeared in two solids: +4 faces (1 splitted planar, 3 faces of cylinder, divided by seam) +assert(len(Group_1.feature().results())==1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [17]) + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMove23.py b/src/CollectionPlugin/Test/TestGroupMove23.py new file mode 100644 index 000000000..50d347f2e --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove23.py @@ -0,0 +1,60 @@ +# Copyright (C) 2014-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 move the group in history for selection of a whole feature + +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(35.07635467980296, 23.01108374384237, -25.74753694581282, 23.01108374384237) +SketchLine_2 = Sketch_1.addLine(-25.74753694581282, 23.01108374384237, -25.74753694581282, -23.13546798029557) +SketchLine_3 = Sketch_1.addLine(-25.74753694581282, -23.13546798029557, 35.07635467980296, -23.13546798029557) +SketchLine_4 = Sketch_1.addLine(35.07635467980296, -23.13546798029557, 35.07635467980296, 23.01108374384237) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 80, 0) +# selection of a whole feature: 6 faces of a box +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1")]) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [6]) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3")) +SketchCircle_1 = Sketch_2.addCircle(-7.736745115674536, 52.14422040986419, 6.760003867274182) +ExtrusionCut_1.setNestedSketch(Sketch_2) +model.do() +# move group after the extrusion-cut, so, it refers to it +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature()) +model.end() + +# check that there is a hole appeared in the group-results +assert(len(Group_1.feature().results())==1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [8]) + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMove24.py b/src/CollectionPlugin/Test/TestGroupMove24.py new file mode 100644 index 000000000..8b37ce289 --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove24.py @@ -0,0 +1,62 @@ +# Copyright (C) 2014-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 move the group in history for selection of a whole feature that produces compsolid + +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(-25.00123152709361, 27.48891625615764, 27.86206896551725, 27.48891625615764) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchLine_2 = Sketch_1.addLine(27.86206896551725, 27.48891625615764, -23.88177339901478, -20.02586206896552) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(-23.88177339901478, -20.02586206896552, 28.73275862068966, -20.02586206896552) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchLine_4 = Sketch_1.addLine(28.73275862068966, -20.02586206896552, 27.86206896551725, 27.48891625615764) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.endPoint()) +SketchLine_5 = Sketch_1.addLine(-25.00123152709361, 27.48891625615764, 28.73275862068966, -20.02586206896552) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint()) +model.do() +Extrusion_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchLine_5f-SketchLine_2r-SketchLine_1r"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_5f-SketchLine_4f"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_3f-SketchLine_5r")] +Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection(), 10, 0) +# selection of a whole result: 5x3-2 faces (2 faces are shared) +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1")]) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [13]) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("COMPSOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1_1/To_Face")) +SketchCircle_1 = Sketch_2.addCircle(13.4282260278248, 11.79859034244854, 3.718064241992405) +ExtrusionCut_1.setNestedSketch(Sketch_2) +model.do() +# move group after the extrusion-cut, so, it refers to it +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature()) +model.end() + +# check that there is a hole appeared in two solids: +4 faces (1 splitted planar, 3 faces of cylinder, divided by seam) +assert(len(Group_1.feature().results())==1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [17]) + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMove25.py b/src/CollectionPlugin/Test/TestGroupMove25.py new file mode 100644 index 000000000..24255be20 --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove25.py @@ -0,0 +1,91 @@ +# Copyright (C) 2014-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 move the group in history for selection of a whole features +# with many modifications of this feature, and joining them in one. + +from SketchAPI import * + +from salome.shaper import model +from ModelAPI 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(-20, 9.999999999999998, -40, 10) +SketchLine_2 = Sketch_1.addLine(-40, 10, -40, -10) +SketchLine_3 = Sketch_1.addLine(-40, -10, -20, -9.999999999999998) +SketchLine_4 = Sketch_1.addLine(-20, -9.999999999999998, -20, 9.999999999999998) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchCircle_1 = Sketch_1.addCircle(0, 0, 10) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center()) +SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1]) +SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_3.result(), SketchCircle_1.results()[1]) +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), 20, True) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10) +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_4.result()) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 30, 0) +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 15, 0) +Group_1 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_1")]) +Group_2 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_2")]) +Group_3 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1"), model.selection("COMPOUND", "all-in-Extrusion_2")]) +ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [], model.selection(), 12, 0, [model.selection("SOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4")) +SketchCircle_2 = Sketch_2.addCircle(-2.3396523840492e-15, 15, 7) +SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_2.results()[1], 7) +SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4]"), False) +SketchLine_5 = SketchProjection_2.createdFeature() +SketchConstraintDistance_2 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_5.result(), 10, True) +SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/To_Face]"), False) +SketchLine_6 = SketchProjection_3.createdFeature() +SketchConstraintDistance_3 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_6.result(), 15, True) +ExtrusionFuse_1.setNestedSketch(Sketch_2) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 50, 50, [model.selection("SOLID", "ExtrusionFuse_1_1"), model.selection("SOLID", "Extrusion_2_1")]) +Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_1_1/To_Face")) +SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "[ExtrusionFuse_1_1/Generated_Face&Sketch_2/SketchCircle_2_2][ExtrusionFuse_1_1/To_Face]__cc"), False) +SketchPoint_2 = SketchProjection_4.createdFeature() +SketchCircle_3 = Sketch_3.addCircle(-2.3396523840492e-15, 15, 5) +SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchPoint_2.result(), SketchCircle_3.center()) +SketchConstraintRadius_3 = Sketch_3.setRadius(SketchCircle_3.results()[1], 5) +ExtrusionCut_1.setNestedSketch(Sketch_3) +Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_1_1"), model.selection("SOLID", "ExtrusionCut_1_2")], True, 20190506) +model.do() +# move groups after the final fuse +Part_1_doc.moveFeature(Group_1.feature(), Fuse_1.feature()) +Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature()) +Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature()) +model.end() + +aFactory = ModelAPI_Session.get().validators() +for group in [Group_1, Group_2, Group_3]: + selectionList = group.feature().selectionList("group_list") + assert(selectionList.size() == 1) + assert(aFactory.validate(group.feature())) diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp index f38b1c605..bf677c743 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp @@ -297,21 +297,6 @@ static bool isInResults(AttributeSelectionListPtr theSelection, return false; } -/// Returns all sub-shapes of the given shape in theResult -static void allSubShapes(const GeomShapePtr theShape, GeomAPI_Shape::ShapeType theType, - std::list& theResult) -{ - if (theShape->shapeType() == theType) { - theResult.push_back(theShape); - } else { - GeomAPI_DataMapOfShapeShape aUnique; // to keep only unique shapes - for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) { - if (aUnique.bind(anExp.current(), anExp.current())) - theResult.push_back(anExp.current()); - } - } -} - void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) { try { diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index bd6a4fb7d..496f1e2af 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1281,6 +1281,56 @@ void Model_AttributeSelection::computeValues( } } + +void Model_AttributeSelection::concealedFeature( + const FeaturePtr theFeature, const FeaturePtr theStop, std::list& theConcealers) +{ + std::set alreadyProcessed; + alreadyProcessed.insert(theFeature); + if (theStop.get()) + alreadyProcessed.insert(theStop); + /// iterate all results to find the concealment-attribute + const std::list& aRootRes = theFeature->results(); + std::list::const_iterator aRootIter = aRootRes.cbegin(); + for(; aRootIter != aRootRes.cend(); aRootIter++) { + std::list allRes; + allRes.push_back(*aRootIter); + ResultBodyPtr aRootBody = ModelAPI_Tools::bodyOwner(*aRootIter, true); + if (aRootBody.get()) { + ModelAPI_Tools::allSubs(aRootBody, allRes); + } + for(std::list::iterator aRIter = allRes.begin(); aRIter != allRes.end(); aRIter++) { + const std::set& aRefs = (*aRIter)->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.cbegin(); + for (; aRef != aRefs.cend(); aRef++) { + if (!aRef->get() || !(*aRef)->owner().get()) + continue; + // concealed attribute only + FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); + if (alreadyProcessed.find(aRefFeat) != alreadyProcessed.end()) // optimization + continue; + alreadyProcessed.insert(aRefFeat); + if (ModelAPI_Session::get()->validators()->isConcealed(aRefFeat->getKind(), (*aRef)->id())) + { + // for extrusion cut in python script the nested sketch reference may be concealed before + // it is nested, so, check this composite feature is valid + static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); + // need to be validated to update the "Apply" state if not previewed + if (aFactory->validate(aRefFeat)) { + if (theStop.get()) { + std::shared_ptr aDoc = + std::dynamic_pointer_cast(theStop->document()); + if (!aDoc->isLaterByDep(theStop, aRefFeat)) // skip feature later than stop + continue; + } + theConcealers.push_back(aRefFeat); + } + } + } + } + } +} + bool Model_AttributeSelection::searchNewContext(std::shared_ptr theDoc, const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape, TDF_Label theAccessLabel, @@ -1344,59 +1394,29 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr if (aResults.empty()) { // check the context become concealed by operation which is earlier than this selection - std::list allRes; - ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theContext, true); - if (!aRoot.get()) - aRoot = theContext; - ResultBodyPtr aRootBody = std::dynamic_pointer_cast(aRoot); - if (aRootBody.get()) { - ModelAPI_Tools::allSubs(aRootBody, allRes); - allRes.push_back(aRootBody); - } else - allRes.push_back(aRoot); - FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); - for (std::list::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) { - ResultPtr aResCont = *aSub; - const std::set& aRefs = aResCont->data()->refsToMe(); - std::set::const_iterator aRef = aRefs.begin(); - for (; aRef != aRefs.end(); aRef++) { - if (!aRef->get() || !(*aRef)->owner().get()) - continue; - // concealed attribute only - FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); - if (aRefFeat == aThisFeature) + FeaturePtr aContextOwner = theDoc->feature(theContext); + std::list aConcealers; + concealedFeature(aContextOwner, aThisFeature, aConcealers); + std::list::iterator aConcealer = aConcealers.begin(); + for(; aConcealer != aConcealers.end(); aConcealer++) { + std::list aRefResults; + ModelAPI_Tools::allResults(*aConcealer, aRefResults); + std::list::iterator aRefIter = aRefResults.begin(); + for(; aRefIter != aRefResults.end(); aRefIter++) { + ResultBodyPtr aRefBody = std::dynamic_pointer_cast(*aRefIter); + if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs continue; - if (!ModelAPI_Session::get()->validators()->isConcealed( - aRefFeat->getKind(), (*aRef)->id())) + GeomShapePtr aRefShape = aRefBody->shape(); + if (!aRefShape.get() || aRefShape->isNull()) continue; - if (theDoc->isLaterByDep(aThisFeature, aRefFeat)) { - // for extrusion cut in python script the nested sketch reference may be concealed before - // it is nested, so, check this composite feature is valid - static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); - // need to be validated to update the "Apply" state if not previewed - if (aFactory->validate(aRefFeat)) { - // there could be a reference to unmodified object, check result contain same shape - std::list aRefResults; - ModelAPI_Tools::allResults(aRefFeat, aRefResults); - std::list::iterator aRefIter = aRefResults.begin(); - for(; aRefIter != aRefResults.end(); aRefIter++) { - ResultBodyPtr aRefBody = std::dynamic_pointer_cast(*aRefIter); - if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs - continue; - GeomShapePtr aRefShape = aRefBody->shape(); - if (!aRefShape.get() || aRefShape->isNull()) - continue; - if (aRefShape->impl().IsSame(theContShape)) { - // add the new context result with the same shape - aResults.insert(aRefBody); - } - } - if (aResults.empty()) - return true; // feature conceals result, return true, so the context will be removed - } + if (aRefShape->impl().IsSame(theContShape)) { + // add the new context result with the same shape + aResults.insert(aRefBody); } } + if (aResults.empty()) + return true; // feature conceals result, return true, so the context will be removed } if (aResults.empty()) return false; // no modifications found, must stay the same @@ -1439,11 +1459,42 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr void Model_AttributeSelection::updateInHistory(bool& theRemove) { + static std::shared_ptr anEmptyShape; + ResultPtr aContext = std::dynamic_pointer_cast(myRef.value()); - // only bodies and parts may be modified later in the history, don't do anything otherwise if (!aContext.get() || (aContext->groupName() != ModelAPI_ResultBody::group() && - aContext->groupName() != ModelAPI_ResultPart::group())) - return; + aContext->groupName() != ModelAPI_ResultPart::group())) { + // but check the case the whole results are allowed: whole features may be selected + if (myParent && myParent->isWholeResultAllowed()) { + FeaturePtr aFeature = std::dynamic_pointer_cast(myRef.value()); + if (aFeature.get()) { + FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); + std::list aConcealers; + concealedFeature(aFeature, aThisFeature, aConcealers); + if (aConcealers.empty()) + return; + bool aChanged = false; + std::list::iterator aConcealer = aConcealers.begin(); + for(; aConcealer != aConcealers.end(); aConcealer++) + if (!myParent->isInList(*aConcealer, anEmptyShape)) {// avoid addition of duplicates + setValue(*aConcealer, anEmptyShape); + aChanged = true; + } + if (aConcealer == aConcealers.end()) { + if (!aChanged) // remove this + theRemove = true; + } else { // append new + for(aConcealer++; aConcealer != aConcealers.end(); aConcealer++) + if (!myParent->isInList(*aConcealer, anEmptyShape)) // avoid addition of duplicates + myParent->append(*aConcealer, anEmptyShape); + } + if (aChanged) // searching for the further modifications + updateInHistory(theRemove); + } + } + return;// only bodies and parts may be modified later in the history, skip otherwise + } + std::shared_ptr aDoc = std::dynamic_pointer_cast(aContext->document()); std::shared_ptr aContData = std::dynamic_pointer_cast(aContext->data()); @@ -1566,7 +1617,10 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) aShapeShapeType = (*aNewCont)->shape()->shapeType(); } if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) { - continue; + // exception is for whole results selected + if (!myParent || !myParent->isWholeResultAllowed() || aSubShape.get()) { + continue; + } } ResultPtr aNewContext = *aNewCont; @@ -1601,8 +1655,7 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) if (myParent) { theRemove = true; } else { - ResultPtr anEmptyContext; - std::shared_ptr anEmptyShape; + static ResultPtr anEmptyContext; setValue(anEmptyContext, anEmptyShape); // nullify the selection return; } diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index c3721e994..ce9872768 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -202,6 +202,10 @@ protected: /// Returns null label otherwise. TDF_Label baseDocumentLab(); + /// Returns features that conceals theFeature and located in history before theStop + void Model_AttributeSelection::concealedFeature( + const FeaturePtr theFeature, const FeaturePtr theStop, std::list& theConcealers); + friend class Model_Data; friend class Model_AttributeSelectionList; }; diff --git a/src/Model/Model_AttributeSelectionList.cpp b/src/Model/Model_AttributeSelectionList.cpp index 56ce94f9d..170190ef6 100644 --- a/src/Model/Model_AttributeSelectionList.cpp +++ b/src/Model/Model_AttributeSelectionList.cpp @@ -293,17 +293,19 @@ bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily) { - ResultPtr aResCont = std::dynamic_pointer_cast(theContext); if (myIsCashed) { // the cashing is active - if (aResCont.get()) { - std::map > >::iterator aContext = - myCash.find(aResCont); + if (theContext.get()) { + std::map > >::iterator aContext = + myCash.find(theContext); if (aContext != myCash.end()) { // iterate shapes because "isSame" method must be called for each shape std::list >::iterator aShapes = aContext->second.begin(); for(; aShapes != aContext->second.end(); aShapes++) { if (!theSubShape.get()) { - if (!aShapes->get() || (*aShapes)->isSame(aContext->first->shape())) + if (!aShapes->get()) + return true; + ResultPtr aRes = std::dynamic_pointer_cast(aContext->first); + if (aRes.get() && (*aShapes)->isSame(aRes->shape())) return true; } else { // we need to call here isSame instead of isEqual to do not check shapes orientation @@ -316,15 +318,21 @@ bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext, } } // no-cash method + bool isFeature = std::dynamic_pointer_cast(theContext).get() != NULL; + ResultPtr aRes; + if (!isFeature) + aRes = std::dynamic_pointer_cast(theContext); for(int anIndex = size() - 1; anIndex >= 0; anIndex--) { AttributeSelectionPtr anAttr = value(anIndex); if (anAttr.get()) { - if (anAttr->context() == theContext) { // contexts are equal, so, check that values are also + if (isFeature && anAttr->contextFeature() == theContext) + return true; // for the feature value should not be compared + if (!isFeature && anAttr->context() == theContext) { + // contexts are equal, so, check that values are also std::shared_ptr aValue = anAttr->value(); if (!theSubShape.get()) { - if (!aValue.get() || (aResCont.get() && aValue->isSame(aResCont->shape()))) {// both null + if (!aValue.get() || (aRes.get() && aValue->isSame(aRes->shape()))) return true; - } } else { // we need to call here isSame instead of isEqual to do not check shapes orientation if (isIn(aValue, theSubShape)) // shapes are equal diff --git a/src/Model/Model_AttributeSelectionList.h b/src/Model/Model_AttributeSelectionList.h index ca797e623..3ed3e2804 100644 --- a/src/Model/Model_AttributeSelectionList.h +++ b/src/Model/Model_AttributeSelectionList.h @@ -42,7 +42,7 @@ class Model_AttributeSelectionList : public ModelAPI_AttributeSelectionList Handle(TDataStd_Comment) mySelectionType; std::shared_ptr myTmpAttr; ///< temporary attribute (the last one) /// the cashed shapes to optimize isInList method: from context to set of shapes in this context - std::map > > myCash; + std::map > > myCash; bool myIsCashed; ///< true if cashing is performed public: /// Adds the new reference to the end of the list