From a930200bbf92c778fc684a3db477064f85f9cafe Mon Sep 17 00:00:00 2001 From: mbs Date: Thu, 15 Dec 2022 10:45:13 +0000 Subject: [PATCH] fixed bug where "Always create result" was required to get a sewing result; added new testcase --- src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp | 6 +- src/FeaturesPlugin/Test/TestSewing_Groups.py | 186 ++++++++++++++++++ .../Test/TestSewing_Manifold.py | 72 +++++-- src/FeaturesPlugin/tests.set | 1 + 4 files changed, 250 insertions(+), 15 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestSewing_Groups.py diff --git a/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp b/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp index c8319e6fc..10694b995 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Sewing.cpp @@ -115,9 +115,9 @@ bool FeaturesPlugin_Sewing::isSewn(const ListOfShape& theInputs, ++anIt) { GeomShapePtr aShape = *anIt; - if (aShape.get() && aShape->isShell()) + if (aShape.get()) { - nbInputShells++; + if (aShape->isShell()) nbInputShells++; nbInputFaces += aShape->subShapes(GeomAPI_Shape::FACE, true).size(); } } @@ -144,5 +144,5 @@ bool FeaturesPlugin_Sewing::isSewn(const ListOfShape& theInputs, nbResultFaces = theResult->subShapes(GeomAPI_Shape::FACE, true).size(); } - return (nbResultShells > nbInputShells || (nbResultShells == nbInputShells && nbResultFaces > nbInputFaces)); + return ((nbInputShells == 0 && nbResultShells > 0) || (nbResultShells < nbInputShells) || (nbResultShells == nbInputShells && nbResultFaces > nbInputFaces)); } diff --git a/src/FeaturesPlugin/Test/TestSewing_Groups.py b/src/FeaturesPlugin/Test/TestSewing_Groups.py new file mode 100644 index 000000000..5536a5317 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestSewing_Groups.py @@ -0,0 +1,186 @@ +import sys +import salome + +salome.salome_init() + +from SketchAPI import * +from GeomAPI import GeomAPI_Shape + +from salome.shaper import model + +aShapeTypes = { + GeomAPI_Shape.SOLID: "GeomAPI_Shape.SOLID", + GeomAPI_Shape.FACE: "GeomAPI_Shape.FACE", + GeomAPI_Shape.EDGE: "GeomAPI_Shape.EDGE", + GeomAPI_Shape.VERTEX: "GeomAPI_Shape.VERTEX"} + +def testNbUniqueSubShapes(theFeature, theShapeType, theExpectedNbSubShapes): + """ Tests number of unique feature sub-shapes of passed type for each result. + :param theFeature: feature to test. + :param theShapeType: shape type of sub-shapes to test. + :param theExpectedNbSubShapes: list of sub-shapes numbers. Size of list should be equal to len(theFeature.results()). + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + aListSize = len(theExpectedNbSubShapes) + assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize) + for anIndex in range(0, aNbResults): + aNbResultSubShapes = 0 + anExpectedNbSubShapes = theExpectedNbSubShapes[anIndex] + aNbResultSubShapes = aResults[anIndex].shape().subShapes(theShapeType, True).size() + assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes) + +def testResults(theFeature,theModel,NbRes,NbSubRes,NbShell,NbFace,NbEdge,NbVertex): + """ Tests numbers of unique sub-shapes in the results + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + assert (aNbResults == NbRes), "Number of results: {} not equal to {}}.".format(aNbResults, NbRes) + theModel.testNbSubResults(theFeature, NbSubRes) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SHELL, NbShell) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex) + + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +### Create SketchLine +SketchLine_1 = Sketch_1.addLine(60, 0, 0, 0) + +### Create SketchProjection +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result()) + +### Create SketchLine +SketchLine_2 = Sketch_1.addLine(0, 0, 0, 75) + +### Create SketchLine +SketchLine_3 = Sketch_1.addLine(0, 75, 60, 75) + +### Create SketchLine +SketchLine_4 = Sketch_1.addLine(60, 75, 60, 0) +Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +Sketch_1.setHorizontal(SketchLine_1.result()) +Sketch_1.setVertical(SketchLine_2.result()) +Sketch_1.setHorizontal(SketchLine_3.result()) +Sketch_1.setVertical(SketchLine_4.result()) +model.do() + +### Create Face +Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")]) + +### Create Sketch +Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("YOZ")) + +### Create SketchLine +SketchLine_5 = Sketch_2.addLine(75, 0.0001, 0, 0) + +### Create SketchProjection +SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/SketchLine_1_EndVertex"), False) +SketchPoint_2 = SketchProjection_2.createdFeature() +Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchPoint_2.result()) + +### Create SketchLine +SketchLine_6 = Sketch_2.addLine(0, 0, 0, 50) + +### Create SketchLine +SketchLine_7 = Sketch_2.addLine(0, 50, 75, 50) + +### Create SketchLine +SketchLine_8 = Sketch_2.addLine(75, 50, 75, 0.0001) +Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint()) +Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +Sketch_2.setVertical(SketchLine_6.result()) +Sketch_2.setHorizontal(SketchLine_7.result()) +Sketch_2.setVertical(SketchLine_8.result()) + +### Create SketchProjection +SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False) +SketchLine_9 = SketchProjection_3.createdFeature() +Sketch_2.setDistance(SketchLine_5.startPoint(), SketchLine_9.result(), 0.0001, True) + +### Create SketchProjection +SketchProjection_4 = Sketch_2.addProjection(model.selection("VERTEX", "Face_1_1/Modified_Vertex&Sketch_1/SketchLine_2_EndVertex&Sketch_1/SketchLine_3_StartVertex"), False) +SketchPoint_3 = SketchProjection_4.createdFeature() +Sketch_2.setHorizontalDistance(SketchLine_8.endPoint(), SketchAPI_Point(SketchPoint_3).coordinates(), 0) +model.do() + +### Create Face +Face_2 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_8r-SketchLine_7r-SketchLine_6r-SketchLine_5r")]) + +### Create Group +Group_1_objects = [model.selection("EDGE", "Face_1_1/Modified_Edge&Sketch_1/SketchLine_4"), + model.selection("EDGE", "Face_1_1/Modified_Edge&Sketch_1/SketchLine_1"), + model.selection("EDGE", "Face_1_1/Modified_Edge&Sketch_1/SketchLine_3"), + model.selection("EDGE", "Face_1_1/Modified_Edge&Sketch_1/SketchLine_2")] +Group_1 = model.addGroup(Part_1_doc, "Edges", Group_1_objects) +model.do() + +model.testNbResults(Group_1, 1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.EDGE, [4]) + +### Create Group +Group_2_objects = [model.selection("EDGE", "Face_2_1/Modified_Edge&Sketch_2/SketchLine_6"), + model.selection("EDGE", "Face_2_1/Modified_Edge&Sketch_2/SketchLine_5"), + model.selection("EDGE", "Face_2_1/Modified_Edge&Sketch_2/SketchLine_7"), + model.selection("EDGE", "Face_2_1/Modified_Edge&Sketch_2/SketchLine_8")] +Group_2 = model.addGroup(Part_1_doc, "Edges", Group_2_objects) +model.do() + +model.testNbResults(Group_2, 1) +model.testNbSubShapes(Group_2, GeomAPI_Shape.EDGE, [4]) + +### Create Sewing +Sewing_1 = model.addSewing(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")], 0.0001, allowNonManifold = True, alwaysCreateResult = False) +model.do() + +testResults(Sewing_1, model, 1, [0], [1], [2], [7], [6]) + +# Move the groups after Sewing (move to the end) +Part_1_doc.moveFeature(Group_1.feature(), Sewing_1.feature()) +Part_1_doc.moveFeature(Group_2.feature(), Sewing_1.feature()) +model.end() + +model.testNbResults(Group_1, 1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.EDGE, [4]) +model.testNbResults(Group_2, 1) +model.testNbSubShapes(Group_2, GeomAPI_Shape.EDGE, [4]) + +# Perform same test, but moving groups after Shell feature +model.undo() +model.undo() +model.testNbSubShapes(Group_1, GeomAPI_Shape.EDGE, [4]) +model.testNbSubShapes(Group_2, GeomAPI_Shape.EDGE, [4]) + +### Build Shell +model.begin() +Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")]) +model.do() + +testResults(Shell_1, model, 2, [0,0], [1,1], [1,1], [4,4], [4,4]) +model.testNbSubShapes(Shell_1, GeomAPI_Shape.EDGE, [4,4]) + +# Move the groups after Shell (move to the end) +Part_1_doc.moveFeature(Group_1.feature(), Shell_1.feature()) +Part_1_doc.moveFeature(Group_2.feature(), Shell_1.feature()) +model.end() + +model.testNbResults(Group_1, 1) +model.testNbSubShapes(Group_1, GeomAPI_Shape.EDGE, [4]) +model.testNbResults(Group_2, 1) +model.testNbSubShapes(Group_2, GeomAPI_Shape.EDGE, [4]) diff --git a/src/FeaturesPlugin/Test/TestSewing_Manifold.py b/src/FeaturesPlugin/Test/TestSewing_Manifold.py index 0f9835b3b..c73f522f2 100644 --- a/src/FeaturesPlugin/Test/TestSewing_Manifold.py +++ b/src/FeaturesPlugin/Test/TestSewing_Manifold.py @@ -63,7 +63,7 @@ Param_dx = model.addParameter(Part_1_doc, "dx", '10') Param_alfa = model.addParameter(Part_1_doc, "alfa", '90') # ============================================================================= -# Test 1. Sew two shells with a single common edge +# Test 1a. Sew two shells with a single common edge (create result) # ============================================================================= Box_1 = model.addBox(Part_1_doc, 10, 10, 10) Box_2 = model.addBox(Part_1_doc, 10, 10, 10) @@ -85,50 +85,98 @@ Shell_2_objects = [model.selection("FACE", "Rotation_1_1/MF:Rotated&Box_2_1/Top" Shell_2 = model.addShell(Part_1_doc, Shell_2_objects) model.do() -Sewing_1 = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) +Sewing_1a = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) model.end() # sewing successful -testResults(Sewing_1, model, 1, [0], [1], [10], [23], [14]) +testResults(Sewing_1a, model, 1, [0], [1], [10], [23], [14]) # ============================================================================= -# Test 2. Sew two shells with four common edges +# Test 1b. Sew two shells with a single common edge (do not create result) +# ============================================================================= +model.undo() +model.begin() + +Sewing_1b = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = False) +model.end() + +# sewing successful +testResults(Sewing_1b, model, 1, [0], [1], [10], [23], [14]) + +# ============================================================================= +# Test 2a. Sew two shells with four common edges (create result) # ============================================================================= model.undo() model.begin() Param_alfa.setValue(0) model.do() -Sewing_2 = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) +Sewing_2a = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) +model.end() + +# sewing successful +testResults(Sewing_2a, model, 1, [0], [1], [10], [20], [12]) + +# ============================================================================= +# Test 2b. Sew two shells with four common edges (do not create result) +# ============================================================================= +model.undo() +model.begin() + +Sewing_2b = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = False) model.end() # sewing successful -testResults(Sewing_2, model, 1, [0], [1], [10], [20], [12]) +testResults(Sewing_2b, model, 1, [0], [1], [10], [20], [12]) # ============================================================================= -# Test 3. Sew two slightly disconnected shells +# Test 3a. Sew two slightly disconnected shells (create result) # ============================================================================= model.undo() model.begin() Param_dx.setValue(10.0001) model.do() -Sewing_3 = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) +Sewing_3a = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = True) model.end() # no sewing done (result is a compound with the two input shells) -testResults(Sewing_3, model, 1, [2], [2], [10], [24], [16]) +testResults(Sewing_3a, model, 1, [2], [2], [10], [24], [16]) # ============================================================================= -# Test 4. Sew two slightly disconnected shells with larger tolerance +# Test 3b. Sew two slightly disconnected shells (do not create result) +# ============================================================================= +model.undo() +model.begin() + +Sewing_3b = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-07, allowNonManifold = False, alwaysCreateResult = False) +model.end() + +# no sewing done (no result was created) +model.testNbResults(Sewing_3b, 0) + +# ============================================================================= +# Test 4a. Sew two slightly disconnected shells with larger tolerance (create result) # ============================================================================= model.undo() model.begin() Param_dx.setValue(10.0001) model.do() -Sewing_4 = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-04, allowNonManifold = False, alwaysCreateResult = True) +Sewing_4a = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-04, allowNonManifold = False, alwaysCreateResult = True) +model.end() + +# sewing successful +testResults(Sewing_4a, model, 1, [0], [1], [10], [20], [12]) + +# ============================================================================= +# Test 4b. Sew two slightly disconnected shells with larger tolerance (do not create result) +# ============================================================================= +model.undo() +model.begin() + +Sewing_4b = model.addSewing(Part_1_doc, [model.selection("SHELL", "Shell_2_1"), model.selection("SHELL", "Shell_1_1")], 1e-04, allowNonManifold = False, alwaysCreateResult = False) model.end() # sewing successful -testResults(Sewing_4, model, 1, [0], [1], [10], [20], [12]) +testResults(Sewing_4b, model, 1, [0], [1], [10], [20], [12]) diff --git a/src/FeaturesPlugin/tests.set b/src/FeaturesPlugin/tests.set index e6544e29e..2ca98bd85 100644 --- a/src/FeaturesPlugin/tests.set +++ b/src/FeaturesPlugin/tests.set @@ -531,6 +531,7 @@ SET(TEST_NAMES_PARA TestLoft.py TestSewing_Manifold.py TestSewing_NonManifold.py + TestSewing_Groups.py ) SET(TEST_NAMES_SEQ -- 2.39.2