Download tests/src/Mod/Part/App/TopoShapeExpansion.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 133 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/tests/src/Mod/Part/App/TopoShapeExpansion.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/tests/src/Mod/Part/App/TopoShapeExpansion.cpp
-
curl -L -o TopoShapeExpansion.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/tests/src/Mod/Part/App/TopoShapeExpansion.cpp
133 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| // NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers) | |
| using namespace Part; | |
| using namespace PartTestHelpers; | |
| class TopoShapeExpansionTest: public ::testing::Test | |
| { | |
| protected: | |
| static void SetUpTestSuite() | |
| { | |
| tests::initApplication(); | |
| } | |
| void SetUp() override | |
| { | |
| Base::Interpreter().runString("import Part"); | |
| _docName = App::GetApplication().getUniqueDocumentName("test"); | |
| App::GetApplication().newDocument(_docName.c_str(), "testUser"); | |
| _hasher = Base::Reference<App::StringHasher>(new App::StringHasher); | |
| ASSERT_EQ(_hasher.getRefCount(), 1); | |
| } | |
| void TearDown() override | |
| { | |
| App::GetApplication().closeDocument(_docName.c_str()); | |
| } | |
| private: | |
| std::string _docName; | |
| Data::ElementIDRefs _sid; | |
| App::StringHasherRef _hasher; | |
| }; | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeReturnsShape) | |
| { | |
| // Arrange | |
| auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {edge}; | |
| std::vector<TopoShape> shapes {topoShape}; | |
| // Act | |
| topoShape.makeElementCompound(shapes, "C", TopoShape::SingleShapeCompoundCreationPolicy::returnShape); | |
| // Assert | |
| EXPECT_EQ(edge.ShapeType(), topoShape.getShape().ShapeType()); // NOT a Compound | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeForceReturnsCompound) | |
| { | |
| // Arrange | |
| auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {edge}; | |
| std::vector<TopoShape> shapes {topoShape}; | |
| // Act | |
| topoShape.makeElementCompound( | |
| shapes, | |
| "C", | |
| TopoShape::SingleShapeCompoundCreationPolicy::forceCompound | |
| ); | |
| // Assert | |
| EXPECT_NE(edge.ShapeType(), topoShape.getShape().ShapeType()); // No longer the same thing | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoShapesReturnsCompound) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {edge1}; | |
| std::vector<TopoShape> shapes {edge1, edge2}; | |
| // Act | |
| topoShape.makeElementCompound(shapes); | |
| // Assert | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_COMPOUND, topoShape.getShape().ShapeType()); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundEmptyShapesReturnsEmptyCompound) | |
| { | |
| // Arrange | |
| auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {edge}; | |
| std::vector<TopoShape> shapes; | |
| // Act | |
| topoShape.makeElementCompound(shapes); | |
| // Assert | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_COMPOUND, topoShape.getShape().ShapeType()); | |
| EXPECT_TRUE(topoShape.getMappedChildElements().empty()); | |
| EXPECT_EQ(0, topoShape.getShape().TShape()->NbChildren()); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoShapesGeneratesMap) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {1L}; | |
| std::vector<TopoShape> shapes {TopoShape(edge1, 2L), TopoShape(edge2, 3L)}; | |
| // Act | |
| topoShape.makeElementCompound(shapes); | |
| auto elements = elementMap((topoShape)); | |
| Base::BoundBox3d bb = topoShape.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getLength(topoShape.getShape()), 2); | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 0, 0))); | |
| // Assert map is correct | |
| EXPECT_FALSE(topoShape.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 6); | |
| EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge1;:H2,E")); | |
| EXPECT_EQ(elements[IndexedName("Edge", 2)], MappedName("Edge1;:H3,E")); | |
| EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;:H2,V")); | |
| EXPECT_EQ(elements[IndexedName("Vertex", 2)], MappedName("Vertex2;:H2,V")); | |
| EXPECT_EQ(elements[IndexedName("Vertex", 3)], MappedName("Vertex1;:H3,V")); | |
| EXPECT_EQ(elements[IndexedName("Vertex", 4)], MappedName("Vertex2;:H3,V")); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoCubes) | |
| { | |
| auto [cube1TS, cube2TS] = CreateTwoTopoShapeCubes(); | |
| // Act | |
| TopoShape topoShape {3L}; | |
| topoShape.makeElementCompound({cube1TS, cube2TS}); | |
| auto elementMap = cube1TS.getElementMap(); | |
| Base::BoundBox3d bb = topoShape.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_EQ( | |
| 22, | |
| topoShape.getMappedChildElements().size() | |
| ); // Changed with PR#12471. Probably will change again after importing | |
| // other TopoNaming logics | |
| EXPECT_FLOAT_EQ(getVolume(topoShape.getShape()), 2); | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 1, 1))); | |
| // Assert map is correct | |
| // Two cubes, each consisting of: | |
| // 8 Vertices | |
| // 12 Edges | |
| // 6 Faces | |
| // ---------- | |
| // 26 subshapes each | |
| EXPECT_TRUE(allElementsMatch( | |
| topoShape, | |
| { | |
| "Vertex1;:H1,V;:H7:6,V", "Vertex2;:H1,V;:H7:6,V", "Vertex3;:H1,V;:H7:6,V", | |
| "Vertex4;:H1,V;:H7:6,V", "Vertex1;:H2,V;:H7:6,V", "Vertex2;:H2,V;:H7:6,V", | |
| "Vertex3;:H2,V;:H7:6,V", "Vertex4;:H2,V;:H7:6,V", "Face1;:H8,F;:He:6,F", | |
| "Face1;:H9,F;:He:6,F", "Face1;:Ha,F;:He:6,F", "Face1;:Hb,F;:He:6,F", | |
| "Face1;:Hc,F;:He:6,F", "Face1;:Hd,F;:He:6,F", "Edge1;:H8,E;:He:6,E", | |
| "Edge2;:H8,E;:He:6,E", "Edge3;:H8,E;:He:6,E", "Edge4;:H8,E;:He:6,E", | |
| "Edge1;:H9,E;:He:6,E", "Edge2;:H9,E;:He:6,E", "Edge3;:H9,E;:He:6,E", | |
| "Edge4;:H9,E;:He:6,E", "Edge1;:Ha,E;:He:6,E", "Edge2;:Ha,E;:He:6,E", | |
| "Edge3;:Ha,E;:He:6,E", "Edge4;:Ha,E;:He:6,E", "Vertex1;:H8,V;:He:6,V", | |
| "Vertex2;:H8,V;:He:6,V", "Vertex3;:H8,V;:He:6,V", "Vertex4;:H8,V;:He:6,V", | |
| "Vertex1;:H9,V;:He:6,V", "Vertex2;:H9,V;:He:6,V", "Vertex3;:H9,V;:He:6,V", | |
| "Vertex4;:H9,V;:He:6,V", "Edge1;:H1,E;:H7:6,E", "Edge2;:H1,E;:H7:6,E", | |
| "Edge3;:H1,E;:H7:6,E", "Edge4;:H1,E;:H7:6,E", "Edge1;:H2,E;:H7:6,E", | |
| "Edge2;:H2,E;:H7:6,E", "Edge3;:H2,E;:H7:6,E", "Edge4;:H2,E;:H7:6,E", | |
| "Edge1;:H3,E;:H7:6,E", "Edge2;:H3,E;:H7:6,E", "Edge3;:H3,E;:H7:6,E", | |
| "Edge4;:H3,E;:H7:6,E", "Face1;:H1,F;:H7:6,F", "Face1;:H2,F;:H7:6,F", | |
| "Face1;:H3,F;:H7:6,F", "Face1;:H4,F;:H7:6,F", "Face1;:H5,F;:H7:6,F", | |
| "Face1;:H6,F;:H7:6,F", | |
| } | |
| )); // Changed with PR#12471. Probably will change again after importing | |
| // other TopoNaming logics | |
| } | |
| TEST_F(TopoShapeExpansionTest, MapperMakerModified) | |
| { | |
| // Arrange | |
| // Definition of all the objects needed for a Transformation | |
| // (https://dev.opencascade.org/doc/refman/html/class_b_rep_builder_a_p_i___transform.html) | |
| auto translation {gp_Trsf()}; | |
| auto transform {BRepBuilderAPI_Transform(translation)}; | |
| auto transformMprMkr {MapperMaker(transform)}; | |
| // Definition of all the objects needed for a Shape Splitting | |
| // (https://dev.opencascade.org/doc/refman/html/class_b_rep_feat___split_shape.html) | |
| auto splitMkr {BRepFeat_SplitShape()}; | |
| auto splitMprMkr {MapperMaker(splitMkr)}; | |
| // Creating a Wire, used later to create a Face | |
| auto wireMkr {BRepBuilderAPI_MakeWire( | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)), | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(1.0, 1.0, 0.0)), | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 1.0, 0.0), gp_Pnt(0.0, 0.0, 0.0)) | |
| )}; | |
| auto wire = wireMkr.Wire(); | |
| // Creating a Face using the Wire created before | |
| auto faceMkr {BRepBuilderAPI_MakeFace(wire)}; | |
| const auto& face = faceMkr.Face(); | |
| // Creating an Edge to split the Face and the Wire | |
| auto edgeMkr {BRepBuilderAPI_MakeEdge(gp_Pnt(0.5, 1.0, 0.0), gp_Pnt(0.5, -1.0, 0.0))}; | |
| auto edge = edgeMkr.Edge(); | |
| // Act | |
| // Performing the Transformation | |
| translation.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)); | |
| transform.Perform(wire); | |
| // Initializing and performing the Split | |
| splitMkr.Init(face); | |
| splitMkr.Add(edge, face); | |
| splitMkr.Build(); | |
| // Assert | |
| // Check that all the shapes and operations have been performed | |
| EXPECT_TRUE(wireMkr.IsDone()); | |
| EXPECT_TRUE(faceMkr.IsDone()); | |
| EXPECT_TRUE(edgeMkr.IsDone()); | |
| EXPECT_TRUE(splitMkr.IsDone()); | |
| EXPECT_TRUE(transform.IsDone()); | |
| // Check the result of the operations | |
| EXPECT_EQ(transformMprMkr.modified(wire).size(), 1); // The Transformation acts on the Wire... | |
| EXPECT_EQ( | |
| transformMprMkr.modified(face).size(), | |
| 1 | |
| ); // ... and therefore on the created Face... | |
| EXPECT_EQ(transformMprMkr.modified(edge).size(), 1); // ... and on the Edge added to the Face | |
| EXPECT_EQ(splitMprMkr.modified(edge).size(), 0); // The Split doesn't modify the Edge | |
| EXPECT_EQ(splitMprMkr.modified(wire).size(), 2); // The Split modifies the Wire into 2 Wires | |
| EXPECT_EQ(splitMprMkr.modified(face).size(), 2); // The Split modifies the Face into 2 Faces | |
| } | |
| TEST_F(TopoShapeExpansionTest, MapperMakerGenerated) | |
| { | |
| // Arrange | |
| // Creating tree Edges, used later in the Fuse operations | |
| auto edge1 {BRepBuilderAPI_MakeEdge(gp_Pnt(-1.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()}; | |
| auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, -1.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge()}; | |
| auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, -1.0), gp_Pnt(0.0, 0.0, 1.0)).Edge()}; | |
| // Definition of all the objects needed for the Fuses | |
| // (https://dev.opencascade.org/doc/refman/html/class_b_rep_algo_a_p_i___fuse.html) | |
| // The Fuse operation, like other Boolean operations derived from BRepAlgoAPI_BuilderAlgo, | |
| // supports the generation history | |
| // (https://dev.opencascade.org/doc/refman/html/class_b_rep_algo_a_p_i___builder_algo.html) | |
| auto fuse1Mkr {BRepAlgoAPI_Fuse(edge1, edge2)}; | |
| auto fuse1MprMkr {MapperMaker(fuse1Mkr)}; | |
| auto fuse2Mkr {BRepAlgoAPI_Fuse(edge1, edge3)}; | |
| auto fuse2MprMkr {MapperMaker(fuse2Mkr)}; | |
| // Act | |
| fuse1Mkr.Build(); | |
| fuse2Mkr.Build(); | |
| // Assert | |
| // Check that all the shapes and operations have been performed | |
| EXPECT_TRUE(fuse1Mkr.IsDone()); | |
| EXPECT_TRUE(fuse2Mkr.IsDone()); | |
| // Check the result of the operations | |
| EXPECT_EQ(fuse1MprMkr.generated(edge1).size(), 1); // fuse1 has a new vertex generated by edge1 | |
| EXPECT_EQ(fuse1MprMkr.generated(edge2).size(), 1); // fuse1 has a new vertex generated by edge2 | |
| EXPECT_EQ( | |
| fuse1MprMkr.generated(edge3).size(), | |
| 0 | |
| ); // fuse1 doesn't have a new vertex generated by edge3 | |
| EXPECT_EQ(fuse2MprMkr.generated(edge1).size(), 1); // fuse2 has a new vertex generated by edge1 | |
| EXPECT_EQ( | |
| fuse2MprMkr.generated(edge2).size(), | |
| 0 | |
| ); // fuse2 doesn't have a new vertex generated by edge2 | |
| EXPECT_EQ(fuse2MprMkr.generated(edge3).size(), 1); // fuse2 has a new vertex generated by edge3 | |
| } | |
| TEST_F(TopoShapeExpansionTest, MapperHistoryModified) | |
| { | |
| // Arrange | |
| // Creating a all the shapes needed for the operations that have a history | |
| auto vertex1 {BRepBuilderAPI_MakeVertex(gp_Pnt(-1.0, -1.0, 0.0)).Vertex()}; | |
| auto vertex2 {BRepBuilderAPI_MakeVertex(gp_Pnt(1.0, 0.0, 0.0)).Vertex()}; | |
| auto edge1 {BRepBuilderAPI_MakeEdge(vertex1, vertex2).Edge()}; | |
| auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(-1.0, 0.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge()}; | |
| auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 1.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()}; | |
| auto wire {BRepBuilderAPI_MakeWire(edge1, edge2, edge3).Wire()}; | |
| // Definition of a MapperHistory made with ShapeBuild_ReShape and of all the objects needed | |
| // (https://dev.opencascade.org/doc/refman/html/class_shape_build___re_shape.html) | |
| // (https://dev.opencascade.org/doc/overview/html/occt_user_guides__shape_healing.html#occt_shg_5_1) | |
| Handle(ShapeBuild_ReShape) reshape {new ShapeBuild_ReShape()}; | |
| // Recording all the shapes that will be modified | |
| vertex1 = reshape->CopyVertex(vertex1); | |
| vertex2 = reshape->CopyVertex(vertex2); | |
| reshape->Apply(edge1); | |
| auto reshapeMprHst {MapperHistory(reshape)}; | |
| // Definition a MapperHistory made with ShapeFix_Wireframe and of all the objects needed | |
| // (https://dev.opencascade.org/doc/refman/html/class_shape_fix___wireframe.html) | |
| // (https://dev.opencascade.org/doc/overview/html/occt_user_guides__shape_healing.html#occt_shg_2_1) | |
| Handle(ShapeFix_Wireframe) fix {new ShapeFix_Wireframe()}; | |
| fix->SetContext(reshape); | |
| fix->SetPrecision(0.0); | |
| auto fixMprHst {MapperHistory(*fix)}; | |
| // Definition of a MapperHistory made with the BRepTools_History of reshape | |
| // (https://dev.opencascade.org/doc/refman/html/class_b_rep_tools___history.html) | |
| auto historyMprHst {MapperHistory(reshape->History())}; | |
| // Act | |
| // Closing the wire | |
| fix->Load(wire); | |
| fix->FixWireGaps(); | |
| // Replacing the edge with the new one made with the modified Vertexes | |
| reshape->Replace(edge1, BRepBuilderAPI_MakeEdge(vertex1, vertex2).Edge()); | |
| reshape->Apply(edge1); | |
| // Assert | |
| // Check that all the shapes and operations have been performed | |
| EXPECT_TRUE(reshape->Status(ShapeExtend_DONE1)); | |
| EXPECT_TRUE(reshape->Status(ShapeExtend_DONE3)); | |
| EXPECT_TRUE(fix->StatusWireGaps(ShapeExtend_DONE)); | |
| // Check the results of the operations after the ShapeFix_Wireframe. | |
| // The history is in common so all the MapperHistory object defined previously will return the | |
| // same values | |
| EXPECT_EQ(historyMprHst.modified(edge1).size(), 1); | |
| EXPECT_EQ(reshapeMprHst.modified(edge1).size(), 1); | |
| EXPECT_EQ(fixMprHst.modified(edge1).size(), 1); | |
| } | |
| TEST_F(TopoShapeExpansionTest, MapperHistoryGenerated) | |
| { | |
| // Arrange | |
| // Creating a all the shapes needed for the operations that have a history | |
| auto edge1 {BRepBuilderAPI_MakeEdge(gp_Pnt(-1.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge()}; | |
| auto edge2 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, -1.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge()}; | |
| auto edge3 {BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, -1.0), gp_Pnt(0.0, 0.0, 1.0)).Edge()}; | |
| // Definition of a MapperHistory made with a BRepTools_History containing the Generated() shapes | |
| // of the Fuse operations, added manually to workaround a CI failure | |
| // (https://github.com/FreeCAD/FreeCAD/pull/12402#issuecomment-1946234571) | |
| auto fuse1Mkr {BRepAlgoAPI_Fuse(edge1, edge2)}; | |
| Handle(BRepTools_History) fuse1Hst {new BRepTools_History()}; | |
| auto fuse1MprHst {MapperHistory(fuse1Hst)}; | |
| auto fuse2Mkr {BRepAlgoAPI_Fuse(edge1, edge3)}; | |
| Handle(BRepTools_History) fuse2Hst {new BRepTools_History()}; | |
| auto fuse2MprHst {MapperHistory(fuse2Hst)}; | |
| // Act | |
| fuse1Mkr.Build(); | |
| fuse1Hst->AddGenerated(edge1, fuse1Mkr); | |
| fuse1Hst->AddGenerated(edge2, fuse1Mkr); | |
| fuse2Mkr.Build(); | |
| fuse2Hst->AddGenerated(edge1, fuse2Mkr); | |
| fuse2Hst->AddGenerated(edge3, fuse2Mkr); | |
| // Assert | |
| // Check that all the shapes and operations have been performed | |
| EXPECT_TRUE(fuse1Mkr.IsDone()); | |
| EXPECT_TRUE(fuse2Mkr.IsDone()); | |
| // Check the result of the operations | |
| EXPECT_EQ(fuse1MprHst.generated(edge1).size(), 1); // fuse1 has a new vertex generated by edge1 | |
| EXPECT_EQ(fuse1MprHst.generated(edge2).size(), 1); // fuse1 has a new vertex generated by edge2 | |
| EXPECT_EQ( | |
| fuse1MprHst.generated(edge3).size(), | |
| 0 | |
| ); // fuse1 doesn't have a new vertex generated by edge3 | |
| EXPECT_EQ(fuse2MprHst.generated(edge1).size(), 1); // fuse2 has a new vertex generated by edge1 | |
| EXPECT_EQ( | |
| fuse2MprHst.generated(edge2).size(), | |
| 0 | |
| ); // fuse2 doesn't have a new vertex generated by edge2 | |
| EXPECT_EQ(fuse2MprHst.generated(edge3).size(), 1); // fuse2 has a new vertex generated by edge3 | |
| } | |
| TEST_F(TopoShapeExpansionTest, resetElementMapTest) | |
| { | |
| // Arrange | |
| // Creating various TopoShapes to check different conditions | |
| // A TopoShape without a map | |
| auto shapeWithoutMap { | |
| TopoShape(BRepBuilderAPI_MakeEdge(gp_Pnt(-1.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(), 1) | |
| }; | |
| // A TopoShape without a map that will be replaced by another map | |
| auto shapeWithoutMapAfterReset {TopoShape(shapeWithoutMap)}; | |
| // A TopoShape with a map | |
| auto shapeWithMap { | |
| TopoShape(BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, -1.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge(), 3) | |
| }; | |
| shapeWithMap.makeShapeWithElementMap(shapeWithMap.getShape(), TopoShape::Mapper(), {shapeWithMap}); | |
| // A TopoShape with a map that will be replaced by another map | |
| auto shapeWithMapAfterReset {TopoShape(shapeWithMap)}; | |
| shapeWithMapAfterReset.makeShapeWithElementMap( | |
| shapeWithMapAfterReset.getShape(), | |
| TopoShape::Mapper(), | |
| {shapeWithMapAfterReset} | |
| ); | |
| // A TopoShape with a map that will be replaced by an empty map | |
| auto shapeWithMapAfterEmptyReset {TopoShape(shapeWithMap)}; | |
| shapeWithMapAfterEmptyReset.makeShapeWithElementMap( | |
| shapeWithMapAfterEmptyReset.getShape(), | |
| TopoShape::Mapper(), | |
| {shapeWithMapAfterEmptyReset} | |
| ); | |
| // A new map | |
| auto newElementMapPtr {std::make_shared<Data::ElementMap>()}; | |
| newElementMapPtr->setElementName(IndexedName("Edge", 2), MappedName("Edge2;:H,E"), 3, nullptr, true); | |
| // Act | |
| shapeWithoutMapAfterReset.resetElementMap(newElementMapPtr); | |
| shapeWithMapAfterReset.resetElementMap(newElementMapPtr); | |
| shapeWithMapAfterEmptyReset.resetElementMap(nullptr); | |
| // Assert | |
| // Check that the original maps haven't been modified | |
| EXPECT_EQ(shapeWithoutMap.getElementMapSize(false), 0); | |
| EXPECT_EQ(shapeWithMap.getElementMapSize(false), 3); | |
| // Check that the two shapes have the same map | |
| EXPECT_EQ(shapeWithoutMapAfterReset.getElementMap(), shapeWithMapAfterReset.getElementMap()); | |
| // Check that inside the shape's map there's the element of the new map (same result if | |
| // checking with the other shape) | |
| EXPECT_NE(shapeWithoutMapAfterReset.getElementMap()[0].name.find("Edge2"), -1); | |
| // Check that there aren't leftovers from the previous map | |
| EXPECT_EQ(shapeWithMapAfterReset.getElementMap()[0].name.find("Edge1"), -1); | |
| // Check that the map has been emptied | |
| EXPECT_EQ(shapeWithMapAfterEmptyReset.getElementMapSize(false), 0); | |
| } | |
| TEST_F(TopoShapeExpansionTest, flushElementMapTest) | |
| { | |
| // Arrange | |
| // Creating various TopoShapes to check different conditions | |
| // A TopoShape with a map that won't be flushed | |
| auto shapeWithMapNotFlushed { | |
| TopoShape(BRepBuilderAPI_MakeEdge(gp_Pnt(-1.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(), 1) | |
| }; | |
| shapeWithMapNotFlushed.makeShapeWithElementMap( | |
| shapeWithMapNotFlushed.getShape(), | |
| TopoShape::Mapper(), | |
| {shapeWithMapNotFlushed} | |
| ); | |
| // A TopoShape with a map that will be reset and then flushed | |
| auto shapeWithMapFlushed { | |
| TopoShape(BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, -1.0, 0.0), gp_Pnt(0.0, 1.0, 0.0)).Edge(), 2) | |
| }; | |
| shapeWithMapFlushed.makeShapeWithElementMap( | |
| shapeWithMapFlushed.getShape(), | |
| TopoShape::Mapper(), | |
| {shapeWithMapFlushed} | |
| ); | |
| // A child TopoShape that will be flushed | |
| auto childshapeWithMapFlushed {shapeWithMapFlushed.getSubTopoShape(TopAbs_VERTEX, 1)}; | |
| childshapeWithMapFlushed.Tag = 3; | |
| // A new map | |
| auto newElementMapPtr {std::make_shared<Data::ElementMap>()}; | |
| newElementMapPtr->setElementName(IndexedName("Edge", 2), MappedName("Edge2;:H,E"), 3, nullptr, true); | |
| // Setting a different element map and then resetting otherwise flush won't have effect | |
| shapeWithMapFlushed.resetElementMap(newElementMapPtr); | |
| shapeWithMapFlushed.resetElementMap(nullptr); | |
| // Act | |
| shapeWithMapNotFlushed.flushElementMap(); | |
| shapeWithMapFlushed.flushElementMap(); | |
| childshapeWithMapFlushed.flushElementMap(); | |
| // Assert | |
| // Check that the original map haven't been modified | |
| EXPECT_EQ(shapeWithMapNotFlushed.getElementMapSize(false), 3); | |
| // Check that the two maps have been flushed | |
| EXPECT_NE(shapeWithMapFlushed.getElementMap()[0].name.find("Edge2"), -1); | |
| EXPECT_NE(childshapeWithMapFlushed.getElementMap()[0].name.find("Vertex1"), -1); | |
| } | |
| TEST_F(TopoShapeExpansionTest, cacheRelatedElements) | |
| { | |
| // Arrange | |
| TopoShape topoShape {3L}; | |
| QVector<MappedElement> names { | |
| {MappedName {"Test1"}, IndexedName {"Test", 1}}, | |
| {MappedName {"Test2"}, IndexedName {"Test", 2}}, | |
| {MappedName {"OtherTest1"}, IndexedName {"OtherTest", 1}}, | |
| }; | |
| QVector<MappedElement> names2 { | |
| {MappedName {"Test3"}, IndexedName {"Test", 3}}, | |
| }; | |
| HistoryTraceType traceType = HistoryTraceType::followTypeChange; | |
| MappedName keyName {"Key1"}; | |
| MappedName keyName2 {"Key2"}; | |
| QVector<MappedElement> returnedNames; | |
| QVector<MappedElement> returnedNames2; | |
| QVector<MappedElement> returnedNames3; | |
| // Act | |
| topoShape.cacheRelatedElements(keyName, traceType, names); | |
| topoShape.cacheRelatedElements(keyName2, HistoryTraceType::stopOnTypeChange, names2); | |
| topoShape.getRelatedElementsCached(keyName, traceType, returnedNames); | |
| topoShape.getRelatedElementsCached(keyName, HistoryTraceType::stopOnTypeChange, returnedNames3); | |
| topoShape.getRelatedElementsCached(keyName2, HistoryTraceType::stopOnTypeChange, returnedNames2); | |
| // Assert | |
| EXPECT_EQ(returnedNames.size(), 3); | |
| EXPECT_STREQ(returnedNames[0].name.toString().c_str(), "Test1"); | |
| EXPECT_EQ(returnedNames2.size(), 1); | |
| EXPECT_STREQ(returnedNames2[0].name.toString().c_str(), "Test3"); | |
| EXPECT_EQ(returnedNames3.size(), 0); // No entries of this type. | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesAdjacent) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {3L}; | |
| std::vector<TopoShape> shapes {TopoShape(edge1, 1L), TopoShape(edge2, 2L)}; | |
| // std::vector<TopoShape> shapes {edge1, edge2}; | |
| // Act | |
| topoShape.makeElementWires(shapes); | |
| auto elementMap = topoShape.getElementMap(); | |
| // Assert | |
| EXPECT_EQ(6, elementMap.size()); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesWires) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge(); | |
| auto edge3 = BRepBuilderAPI_MakeEdge(gp_Pnt(3.0, 0.0, 0.0), gp_Pnt(2.0, 1.0, 0.0)).Edge(); | |
| auto edge4 = BRepBuilderAPI_MakeEdge(gp_Pnt(2.0, 1.0, 0.0), gp_Pnt(2.0, 2.0, 0.0)).Edge(); | |
| std::vector<TopoShape> shapes {TopoShape(edge1, 1L), TopoShape(edge2, 2L)}; | |
| std::vector<TopoShape> shapes2 {TopoShape(edge3, 4L), TopoShape(edge4, 4L)}; | |
| // std::vector<TopoShape> shapes {edge1, edge2}; | |
| // Act | |
| auto& wire1 = (new TopoShape {})->makeElementWires(shapes); | |
| auto& wire2 = (new TopoShape {})->makeElementWires(shapes2); | |
| auto& topoShape = (new TopoShape {})->makeElementWires({wire1, wire2}); | |
| auto elements = elementMap((topoShape)); | |
| Base::BoundBox3d bb = topoShape.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_NEAR(getLength(topoShape.getShape()), 4.4142137, 1e-6); | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 3, 2, 0))); | |
| // Assert map is correct | |
| EXPECT_TRUE(allElementsMatch( | |
| topoShape, | |
| { | |
| "Edge1;WIR;:H1:4,E;WIR;:H1:4,E", | |
| "Edge1;WIR;:H2:4,E;WIR;:H2:4,E", | |
| "Edge1;WIR;:H4:4,E;D1;:H4:3,E;WIR;:H4:4,E", | |
| "Edge1;WIR;:H4:4,E;WIR;:H4:4,E", | |
| "Vertex1;WIR;:H1:4,V;WIR;:H1:4,V", | |
| "Vertex1;WIR;:H4:4,V;WIR;:H4:4,V", | |
| "Vertex2;WIR;:H1:4,V;WIR;:H1:4,V", | |
| "Vertex2;WIR;:H2:4,V;WIR;:H2:4,V", | |
| "Vertex2;WIR;:H4:4,V;D1;:H4:3,V;WIR;:H4:4,V", | |
| "Vertex2;WIR;:H4:4,V;WIR;:H4:4,V", | |
| } | |
| )); // Changed with PR#12471. Probably will change again after | |
| // importing other TopoNaming logics | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceNull) | |
| { | |
| // Arrange | |
| const float Len = 3, Wid = 2, Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {face1}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(nullptr); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, Len * Wid - std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area3, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceSimple) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {face1}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(wire1); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, Len * Wid); | |
| EXPECT_DOUBLE_EQ(area3, Len * Wid); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceParams) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {face1, 1L}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", "Part::FaceMakerBullseye", nullptr); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, Len * Wid); | |
| EXPECT_DOUBLE_EQ(area3, Len * Wid); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceFromFace) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {face1, 1L}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(face1, "Cut", "Part::FaceMakerBullseye", nullptr); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, Len * Wid - std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area3, Len * Wid - std::numbers::pi * Rad * Rad); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceOpenWire) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {wire1, 1L}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", nullptr, nullptr); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, Len * Wid); | |
| EXPECT_DOUBLE_EQ(area3, Len * Wid); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {wire2, 1L}; | |
| double area = getArea(face1); | |
| double area1 = getArea(topoShape.getShape()); | |
| // Act | |
| TopoShape newFace = topoShape.makeElementFace(wire2, "Cut", "Part::FaceMakerBullseye", nullptr); | |
| double area2 = getArea(newFace.getShape()); | |
| double area3 = getArea(topoShape.getShape()); | |
| // Assert | |
| EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered | |
| EXPECT_FALSE(face1.IsEqual(newFace.getShape())); | |
| EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area2, std::numbers::pi * Rad * Rad); | |
| EXPECT_DOUBLE_EQ(area3, std::numbers::pi * Rad * Rad); | |
| EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); | |
| } | |
| // Possible future makeElementFace tests: | |
| // Overlapping wire | |
| // Compound of wires | |
| // Compound of faces | |
| // Compound of other shape types | |
| TEST_F(TopoShapeExpansionTest, setElementComboNameNothing) | |
| { | |
| // Arrange | |
| TopoShape topoShape {1L}; | |
| // Act | |
| Data::MappedName result = topoShape.setElementComboName(Data::IndexedName(), {}); | |
| // ASSERT | |
| EXPECT_STREQ(result.toString().c_str(), ""); | |
| } | |
| TEST_F(TopoShapeExpansionTest, setElementComboNameSimple) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| TopoShape topoShape {edge1, 1L}; | |
| topoShape.setElementMap({}); // Initialize the map to avoid a segfault. | |
| // Also, maybe the end of TopoShape::mapSubElementTypeForShape should enforce that elementMap() | |
| // isn't nullptr to eliminate the segfault. | |
| Data::MappedName edgeName("testname"); | |
| // Act | |
| Data::MappedName result | |
| = topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1), {edgeName}); | |
| // Assert | |
| EXPECT_STREQ(result.toString().c_str(), "testname;"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, setElementComboName) | |
| { | |
| // Arrange | |
| TopoShape topoShape {2L}; | |
| topoShape.setElementMap({}); | |
| Data::MappedName edgeName = topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true); | |
| Data::MappedName faceName = topoShape.getMappedName(Data::IndexedName::fromConst("Face", 7), true); | |
| Data::MappedName faceName2 = topoShape.getMappedName(Data::IndexedName::fromConst("Face", 8), true); | |
| const char* op = "Copy"; | |
| // Act | |
| Data::MappedName result = topoShape.setElementComboName( | |
| Data::IndexedName::fromConst("Edge", 1), | |
| {edgeName, faceName, faceName2}, | |
| OpCodes::Common, | |
| op | |
| ); | |
| // Assert | |
| EXPECT_STREQ(result.toString().c_str(), "Edge1;CMN(Face7|Face8);Copy"); | |
| // The detailed forms of names are covered in encodeElementName tests | |
| } | |
| TEST_F(TopoShapeExpansionTest, setElementComboNameCompound) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge(); | |
| auto wire1 = BRepBuilderAPI_MakeWire({edge1}).Wire(); | |
| auto wire2 = BRepBuilderAPI_MakeWire({edge1}).Wire(); | |
| TopoShape topoShape {2L}; | |
| topoShape.makeElementCompound({wire1, wire2}); // Quality of shape doesn't matter | |
| Data::MappedName edgeName = topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true); | |
| Data::MappedName faceName = topoShape.getMappedName(Data::IndexedName::fromConst("Face", 7), true); | |
| Data::MappedName faceName2 = topoShape.getMappedName(Data::IndexedName::fromConst("Face", 8), true); | |
| const char* op = "Copy"; | |
| // Act | |
| Data::MappedName result = topoShape.setElementComboName( | |
| Data::IndexedName::fromConst("Edge", 1), | |
| {edgeName, faceName, faceName2}, | |
| OpCodes::Common, | |
| op | |
| ); | |
| // ASSERT | |
| EXPECT_STREQ( | |
| result.toString().c_str(), | |
| "Edge1;:H,E;CMN(Face7|Face8);Copy" | |
| ); // Changed with PR#12471. Probably will change again | |
| // after importing other TopoNaming logics | |
| // The detailed forms of names are covered in encodeElementName tests | |
| } | |
| TEST_F(TopoShapeExpansionTest, splitWires) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| const float Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| TopoShape topoShape {face1, 1L}; | |
| std::vector<TopoShape> inner; | |
| // Act | |
| EXPECT_EQ(topoShape.getShape().Orientation(), TopAbs_FORWARD); | |
| TopoShape wire = topoShape.splitWires(&inner, TopoShape::SplitWireReorient::ReorientReversed); | |
| // Assert | |
| EXPECT_EQ(inner.size(), 1); | |
| EXPECT_DOUBLE_EQ(getLength(wire.getShape()), 2 + 2 + 3 + 3); | |
| EXPECT_DOUBLE_EQ(getLength(inner.front().getShape()), std::numbers::pi * Rad * 2); | |
| EXPECT_EQ(wire.getShape().Orientation(), TopAbs_REVERSED); | |
| for (TopoShape& shape : inner) { | |
| EXPECT_EQ(shape.getShape().Orientation(), TopAbs_FORWARD); | |
| } | |
| } | |
| // Possible future tests: | |
| // splitWires without inner Wires | |
| // splitWires with all four reorientation values NoReorient, ReOrient, ReorientForward, | |
| // ReorientReversed | |
| TEST_F(TopoShapeExpansionTest, getSubShapes) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| // Act | |
| auto subShapes = cube1.getSubShapes(); | |
| auto subShapes2 = cube1.getSubShapes(TopAbs_FACE); | |
| auto subShapes3 = cube1.getSubShapes(TopAbs_SHAPE, TopAbs_EDGE); | |
| // Assert | |
| EXPECT_EQ(subShapes.size(), 6); | |
| EXPECT_EQ(subShapes2.size(), 6); | |
| EXPECT_EQ(subShapes3.size(), 0); // TODO: Why doesn't this match the next test? | |
| } | |
| TEST_F(TopoShapeExpansionTest, getSubTopoShapes) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| // Act | |
| auto subShapes = cube1.getSubTopoShapes(); | |
| auto subShapes2 = cube1.getSubTopoShapes(TopAbs_FACE); | |
| auto subShapes3 = cube1.getSubTopoShapes(TopAbs_SHAPE, TopAbs_EDGE); | |
| // Assert | |
| EXPECT_EQ(subShapes.size(), 6); | |
| EXPECT_EQ(subShapes2.size(), 6); | |
| EXPECT_EQ(subShapes3.size(), 6); | |
| } | |
| TEST_F(TopoShapeExpansionTest, getOrderedEdges) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| // Act | |
| auto subShapes = cube1.getOrderedEdges(MapElement::noMap); | |
| // Assert | |
| EXPECT_EQ(subShapes.size(), 24); | |
| // EXPECT_THROW(cube1.getOrderedEdges(), NullShapeException); // No Map | |
| EXPECT_EQ(subShapes.front().getElementMap().size(), 0); | |
| // EXPECT_EQ(subShapes2.front().getElementMap().size(),2); | |
| } | |
| TEST_F(TopoShapeExpansionTest, getOrderedVertexes) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| // Act | |
| auto subShapes = cube1.getOrderedVertexes(MapElement::noMap); | |
| // Assert | |
| EXPECT_EQ(subShapes.size(), 24); | |
| // EXPECT_THROW(cube1.getOrderedEdges(), NullShapeException); // No Map | |
| } | |
| TEST_F(TopoShapeExpansionTest, getSubTopoShapeByEnum) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| // Act | |
| auto subShape = cube1TS.getSubTopoShape(TopAbs_FACE, 1); | |
| auto subShape2 = cube1TS.getSubTopoShape(TopAbs_FACE, 2); | |
| auto subShape3 = cube1TS.getSubTopoShape(TopAbs_FACE, 6); | |
| auto noshape1 = cube1TS.getSubTopoShape(TopAbs_FACE, 7, true); | |
| // Assert | |
| EXPECT_EQ(subShape.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_EQ(subShape2.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_EQ(subShape2.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_TRUE(noshape1.isNull()); | |
| EXPECT_THROW(cube1TS.getSubTopoShape(TopAbs_FACE, 7), Base::IndexError); // Out of range | |
| } | |
| TEST_F(TopoShapeExpansionTest, getSubTopoShapeByStringDefaults) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| Part::TopoShape cube1TS {cube1, 1L}; | |
| const float Len = 3; | |
| const float Wid = 2; | |
| auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(Len, Wid); | |
| TopoDS_Compound compound1; | |
| TopoDS_Builder builder {}; | |
| builder.MakeCompound(compound1); | |
| builder.Add(compound1, face1); | |
| TopoShape topoShape {compound1, 2L}; | |
| // Act | |
| auto subShape = cube1TS.getSubTopoShape(nullptr); | |
| auto subShape1 = cube1TS.getSubTopoShape(""); | |
| auto subShape2 = topoShape.getSubTopoShape(nullptr); | |
| // Assert | |
| EXPECT_TRUE(subShape.getShape().IsEqual(cube1TS.getShape())); | |
| EXPECT_EQ(subShape.getShape().ShapeType(), TopAbs_SOLID); | |
| EXPECT_TRUE(subShape1.getShape().IsEqual(cube1TS.getShape())); | |
| EXPECT_EQ(subShape1.getShape().ShapeType(), TopAbs_SOLID); | |
| EXPECT_TRUE(subShape2.getShape().IsEqual(face1)); | |
| EXPECT_EQ(subShape2.getShape().ShapeType(), TopAbs_FACE); | |
| } | |
| TEST_F(TopoShapeExpansionTest, getSubTopoShapeByStringNames) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| // Act | |
| auto subShape = cube1TS.getSubTopoShape("Face1"); | |
| auto subShape2 = cube1TS.getSubTopoShape("Face2"); | |
| auto subShape3 = cube1TS.getSubTopoShape("Face3"); | |
| auto noshape1 = cube1TS.getSubTopoShape("Face7", true); // Out of range | |
| // Assert | |
| EXPECT_EQ(subShape.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_EQ(subShape2.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_EQ(subShape3.getShape().ShapeType(), TopAbs_FACE); | |
| EXPECT_TRUE(noshape1.isNull()); | |
| EXPECT_THROW(cube1TS.getSubTopoShape("Face7"), Base::IndexError); // Out of range | |
| EXPECT_THROW(cube1TS.getSubTopoShape("WOOHOO", false), Base::ValueError); // Invalid | |
| } | |
| TEST_F(TopoShapeExpansionTest, mapSubElementInvalidParm) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| TopoShape cube2TS {cube2, 2L}; | |
| // Act | |
| std::vector<TopoShape> subShapes = cube1TS.getSubTopoShapes(TopAbs_FACE); | |
| TopoShape face1 = subShapes.front(); | |
| face1.Tag = 3; | |
| cube1TS.mapSubElement(face1); | |
| cube2TS.mapSubElement(face1); | |
| // Assert | |
| EXPECT_EQ(cube1TS.getElementMap().size(), 9); // Valid, the face is in Cube1 | |
| EXPECT_EQ(cube2TS.getElementMap().size(), 0); // Invalid, the face is not in Cube2 | |
| } | |
| TEST_F(TopoShapeExpansionTest, mapSubElementFindShapeByNames) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1}; | |
| TopoShape cube2TS {cube2}; | |
| cube1TS.Tag = 1; | |
| cube2TS.Tag = 2; | |
| TopoShape topoShape; | |
| TopoShape topoShape1; | |
| // Act | |
| int fs1 = topoShape1.findShape(cube1); | |
| topoShape.setShape(cube2TS); | |
| topoShape1.makeElementCompound({cube1TS, cube2TS}); | |
| int fs2 = topoShape1.findShape(cube1); | |
| TopoDS_Shape tds1 = topoShape.findShape("SubShape1"); | |
| TopoDS_Shape tds2 = topoShape.findShape("SubShape2"); // Nonexistent | |
| TopoDS_Shape tds3 = topoShape1.findShape("SubShape1"); | |
| TopoDS_Shape tds4 = topoShape1.findShape("SubShape2"); | |
| TopoDS_Shape tds5 = topoShape1.findShape("NonExistentName"); // Invalid Name | |
| // Assert | |
| EXPECT_EQ(fs1, 0); | |
| EXPECT_EQ(fs2, 1); | |
| EXPECT_FALSE(tds1.IsNull()); | |
| EXPECT_TRUE(tds2.IsNull()); | |
| EXPECT_FALSE(tds3.IsNull()); | |
| EXPECT_FALSE(tds4.IsNull()); | |
| EXPECT_TRUE(tds5.IsNull()); | |
| } | |
| TEST_F(TopoShapeExpansionTest, mapSubElementFindShapeByType) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1}; | |
| TopoShape cube2TS {cube2}; | |
| cube1TS.Tag = 1; | |
| cube2TS.Tag = 2; | |
| TopoShape topoShape; | |
| topoShape.makeElementCompound({cube1TS, cube2TS}); | |
| topoShape.mapSubElement(cube2TS, "Name", false); | |
| // Act, Assert | |
| for (int i = 1; i <= 12; i++) { | |
| TopoDS_Shape dshape1 = topoShape.findShape(TopAbs_FACE, i); | |
| EXPECT_FALSE(dshape1.IsNull()) << "Face num " << i; | |
| } | |
| TopoDS_Shape dshape1 = topoShape.findShape(TopAbs_FACE, 13); | |
| EXPECT_TRUE(dshape1.IsNull()); | |
| } | |
| TEST_F(TopoShapeExpansionTest, mapSubElementFindAncestor) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1}; | |
| TopoShape cube2TS {cube2}; | |
| cube1TS.Tag = 1; | |
| cube2TS.Tag = 2; | |
| TopoShape topoShape; | |
| topoShape.makeElementCompound({cube1TS, cube2TS}); | |
| topoShape.mapSubElement(cube2TS, "Name", false); | |
| // Act | |
| int fa1 = topoShape.findAncestor(cube2, TopAbs_COMPOUND); | |
| TopoDS_Shape tds1 = topoShape.findAncestorShape(cube1, TopAbs_COMPOUND); | |
| // Assert | |
| EXPECT_EQ(fa1, 1); | |
| EXPECT_TRUE(tds1.IsEqual(topoShape.getShape())); | |
| } | |
| TEST_F(TopoShapeExpansionTest, mapSubElementFindAncestors) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto [cube3, cube4] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(0, 1, 0))); | |
| cube3.Move(TopLoc_Location(tr)); | |
| cube4.Move(TopLoc_Location(tr)); | |
| TopoShape cube1TS {cube1}; | |
| TopoShape cube2TS {cube2}; | |
| TopoShape cube3TS {cube3}; | |
| TopoShape cube4TS {cube4}; | |
| cube1TS.Tag = 1; | |
| cube2TS.Tag = 2; | |
| cube3TS.Tag = 3; | |
| cube4TS.Tag = 4; | |
| TopoShape topoShape; | |
| TopoShape topoShape1; | |
| TopoShape topoShape2; | |
| TopoShape topoShape3; | |
| TopoShape topoShape4; | |
| TopoShape topoShape5; | |
| TopoShape topoShape6; | |
| topoShape.makeElementCompound({cube1TS, cube2TS}); | |
| topoShape1.makeElementCompound({cube3TS, cube4TS}); | |
| topoShape2.makeElementCompound({cube1TS, cube3TS}); | |
| topoShape3.makeElementCompound({cube2TS, cube4TS}); | |
| topoShape4.makeElementCompound({topoShape, topoShape1}); | |
| topoShape5.makeElementCompound({topoShape2, topoShape3}); | |
| topoShape6.makeElementCompound({topoShape4, topoShape5}); | |
| topoShape6.mapSubElement(cube2TS, nullptr, false); | |
| // Act | |
| auto ancestorList = topoShape6.findAncestors(cube3, TopAbs_COMPOUND); | |
| auto ancestorShapeList = topoShape6.findAncestorsShapes(cube3, TopAbs_COMPOUND); | |
| // FIXME: It seems very strange that both of these ancestors calls return lists of two items | |
| // that contain the same thing twice. What I expect is that the ancestors of cube3 would be | |
| // topoShape6 topoShape5, topoShape3, topoShape2, and topoShape1. | |
| // | |
| // This is a very convoluted hierarchy, and the only way I could get more than one result from | |
| // findAncestors. I guess it's possible that it's only intended to return a single result in | |
| // almost all cases; that would mean that what it returns is the shape at the top of the tree. | |
| // But that's exactly the shape we use to call it in the first place, so we already have it. | |
| // | |
| // Note that in the RT branch, findAncestorsShapes is called by GenericShapeMapper::init, | |
| // TopoShape::makEChamfer and MapperPrism | |
| // findAncestors is used in a dozen places. | |
| // | |
| // Assert | |
| EXPECT_EQ(ancestorList.size(), 2); | |
| EXPECT_EQ(ancestorList.front(), 1); | |
| EXPECT_EQ(ancestorList.back(), 1); | |
| EXPECT_EQ(ancestorShapeList.size(), 2); | |
| EXPECT_TRUE(ancestorShapeList.front().IsEqual(topoShape6.getShape())); | |
| EXPECT_TRUE(ancestorShapeList.back().IsEqual(topoShape6.getShape())); | |
| } | |
| TEST_F(TopoShapeExpansionTest, findSubShapesWithSharedVertexEverything) | |
| { | |
| // Arrange | |
| auto [box1, box2] = CreateTwoCubes(); | |
| TopoShape box1TS {box1}; | |
| std::vector<std::string> names; | |
| std::vector<std::string> names1; | |
| std::vector<std::string> names2; | |
| double tol {2}; // Silly big tolerance to get everything | |
| double atol {2}; | |
| TopExp_Explorer exp(box1, TopAbs_FACE); | |
| auto face = exp.Current(); | |
| exp.Init(box1, TopAbs_EDGE); | |
| auto edge = exp.Current(); | |
| exp.Init(box1, TopAbs_VERTEX); | |
| auto vertex = exp.Current(); | |
| // Act | |
| auto shapes = box1TS.findSubShapesWithSharedVertex( | |
| face, | |
| &names, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes1 = box1TS.findSubShapesWithSharedVertex( | |
| edge, | |
| &names1, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes2 = box1TS.findSubShapesWithSharedVertex( | |
| vertex, | |
| &names2, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| // Assert | |
| EXPECT_EQ(shapes.size(), 6); | |
| EXPECT_EQ(names.size(), 6); | |
| EXPECT_STREQ(names[0].c_str(), "Face1"); | |
| EXPECT_STREQ(names[1].c_str(), "Face3"); | |
| EXPECT_STREQ(names[2].c_str(), "Face6"); | |
| EXPECT_STREQ(names[3].c_str(), "Face5"); | |
| EXPECT_STREQ(names[4].c_str(), "Face4"); | |
| EXPECT_STREQ(names[5].c_str(), "Face2"); | |
| EXPECT_EQ(shapes1.size(), 12); | |
| EXPECT_EQ(names1.size(), 12); | |
| EXPECT_EQ(shapes2.size(), 8); | |
| EXPECT_EQ(names2.size(), 8); | |
| } | |
| TEST_F(TopoShapeExpansionTest, findSubShapesWithSharedVertexMid) | |
| { | |
| // Arrange | |
| auto [box1, box2] = CreateTwoCubes(); | |
| TopoShape box1TS {box1}; | |
| std::vector<std::string> names; | |
| std::vector<std::string> names1; | |
| std::vector<std::string> names2; | |
| double tol {1e-0}; | |
| double atol {1e-04}; | |
| TopExp_Explorer exp(box1, TopAbs_FACE); | |
| auto face = exp.Current(); | |
| exp.Init(box1, TopAbs_EDGE); | |
| auto edge = exp.Current(); | |
| exp.Init(box1, TopAbs_VERTEX); | |
| auto vertex = exp.Current(); | |
| // Act | |
| auto shapes = box1TS.findSubShapesWithSharedVertex( | |
| face, | |
| &names, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes1 = box1TS.findSubShapesWithSharedVertex( | |
| edge, | |
| &names1, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes2 = box1TS.findSubShapesWithSharedVertex( | |
| vertex, | |
| &names2, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| // Assert | |
| EXPECT_EQ(shapes.size(), 6); | |
| EXPECT_EQ(names.size(), 6); | |
| EXPECT_EQ(shapes1.size(), 7); | |
| EXPECT_EQ(names1.size(), 7); | |
| EXPECT_EQ(shapes2.size(), 4); | |
| EXPECT_EQ(names2.size(), 4); | |
| } | |
| TEST_F(TopoShapeExpansionTest, findSubShapesWithSharedVertexClose) | |
| { | |
| // Arrange | |
| auto [box1, box2] = CreateTwoCubes(); | |
| TopoShape box1TS {box1}; | |
| std::vector<std::string> names; | |
| std::vector<std::string> names1; | |
| std::vector<std::string> names2; | |
| double tol {1e-02}; | |
| double atol {1e-04}; | |
| TopExp_Explorer exp(box1, TopAbs_FACE); | |
| auto face = exp.Current(); | |
| exp.Init(box1, TopAbs_EDGE); | |
| auto edge = exp.Current(); | |
| exp.Init(box1, TopAbs_VERTEX); | |
| auto vertex = exp.Current(); | |
| // Act | |
| auto shapes = box1TS.findSubShapesWithSharedVertex( | |
| face, | |
| &names, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes1 = box1TS.findSubShapesWithSharedVertex( | |
| edge, | |
| &names1, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| auto shapes2 = box1TS.findSubShapesWithSharedVertex( | |
| vertex, | |
| &names2, | |
| Data::SearchOption::CheckGeometry, | |
| tol, | |
| atol | |
| ); | |
| // Assert | |
| EXPECT_EQ(shapes.size(), 1); | |
| EXPECT_EQ(names.size(), 1); | |
| EXPECT_EQ(shapes1.size(), 1); | |
| EXPECT_EQ(names1.size(), 1); | |
| EXPECT_EQ(shapes2.size(), 1); | |
| EXPECT_EQ(names2.size(), 1); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellInvalid) | |
| { | |
| // Arrange | |
| TopoShape topoShape {1L}; | |
| // Act / Assert | |
| EXPECT_THROW(topoShape.makeElementShell(false, nullptr), Base::CADKernelError); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellSingle) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| auto [face1, wire1, edge1, edge2, edge3, _] = CreateRectFace(Len, Wid); | |
| TopoShape topoShape {face1, 1L}; | |
| // Act | |
| TopoShape result = topoShape.makeElementShell(false, nullptr); | |
| // Assert | |
| EXPECT_EQ(result.getShape().NbChildren(), 1); | |
| EXPECT_EQ(result.countSubElements("Vertex"), 4); | |
| EXPECT_EQ(result.countSubElements("Edge"), 4); | |
| EXPECT_EQ(result.countSubElements("Face"), 1); | |
| EXPECT_STREQ(result.shapeName().c_str(), "Shell"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellOpen) | |
| { | |
| // Arrange | |
| const float Len = 3; | |
| const float Wid = 2; | |
| auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(Len, Wid); | |
| auto transform {gp_Trsf()}; | |
| transform.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), std::numbers::pi / 2); | |
| auto face2 = face1; // Shallow copy | |
| face2.Move(TopLoc_Location(transform)); | |
| TopoDS_Compound compound1; | |
| TopoDS_Builder builder {}; | |
| builder.MakeCompound(compound1); | |
| builder.Add(compound1, face1); | |
| builder.Add(compound1, face2); | |
| TopoShape topoShape {compound1, 1L}; | |
| // Act | |
| TopoShape result = topoShape.makeElementShell(true, nullptr); | |
| // Assert | |
| EXPECT_EQ(result.getShape().NbChildren(), 2); | |
| EXPECT_EQ(result.countSubElements("Vertex"), 6); | |
| EXPECT_EQ(result.countSubElements("Edge"), 7); | |
| EXPECT_EQ(result.countSubElements("Face"), 2); | |
| EXPECT_STREQ(result.shapeName().c_str(), "Shell"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellClosed) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape {cube1}; | |
| std::vector<TopoShape> shapes; | |
| for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) { | |
| shapes.emplace_back(face); | |
| } | |
| // Act | |
| TopoShape topoShape1 {1L}; | |
| topoShape1.makeElementCompound(shapes, "D"); | |
| // Assert | |
| TopoShape result = topoShape1.makeElementShell(false, "SH1"); | |
| EXPECT_EQ(result.getShape().NbChildren(), 6); | |
| EXPECT_EQ(result.countSubElements("Vertex"), 8); | |
| EXPECT_EQ(result.countSubElements("Edge"), 12); | |
| EXPECT_EQ(result.countSubElements("Face"), 6); | |
| EXPECT_STREQ(result.shapeName().c_str(), "Shell"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellIntersecting) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto transform {gp_Trsf()}; | |
| transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.5, 0.5, 0.0)); | |
| cube2.Move(TopLoc_Location(transform)); | |
| TopoShape topoShape {cube1}; | |
| std::vector<TopoShape> shapes; | |
| for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) { | |
| shapes.emplace_back(face); | |
| } | |
| topoShape.setShape(cube2); | |
| for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) { | |
| shapes.emplace_back(face); | |
| } | |
| // Act | |
| TopoShape topoShape1 {1L}; | |
| topoShape1.makeElementCompound(shapes, "D"); | |
| // Assert | |
| EXPECT_THROW(topoShape1.makeElementShell(false, nullptr), Base::CADKernelError); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementShellFromWires) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape {cube1}; | |
| std::vector<TopoShape> shapes; | |
| for (const auto& face : topoShape.getSubShapes(TopAbs_WIRE)) { | |
| shapes.emplace_back(face); | |
| } | |
| // Act | |
| TopoShape topoShape1 {1L}; | |
| topoShape1.makeElementCompound(shapes, "D"); | |
| // Assert | |
| TopoShape result = topoShape1.makeElementShellFromWires(shapes); | |
| EXPECT_EQ(result.getShape().NbChildren(), 20); // Have a NbChildren method? | |
| EXPECT_EQ(result.countSubElements("Vertex"), 8); | |
| EXPECT_EQ(result.countSubElements("Edge"), 32); | |
| EXPECT_EQ(result.countSubElements("Face"), 20); | |
| EXPECT_STREQ(result.shapeName().c_str(), "Shell"); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementBooleanImpossibleCommon) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementBoolean(Part::OpCodes::Common, {topoShape1, topoShape2}); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 0); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementBooleanCommon) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementBoolean(Part::OpCodes::Common, {topoShape1, topoShape2}); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.25); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 26); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face3;:M;CMN;:H1:7,F")); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementBooleanCut) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementBoolean(Part::OpCodes::Cut, {topoShape1, topoShape2}); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 38); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge10;:M;CUT;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M;CUT;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M;CUT;:H2:7,E", | |
| "Edge2", | |
| "Edge2;:M;CUT;:H2:7,E", | |
| "Edge3", | |
| "Edge3;:M;CUT;:H2:7,E", | |
| "Edge4", | |
| "Edge4;:M;CUT;:H2:7,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge6;:M;CUT;:H1:7,E", | |
| "Edge7", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge8;:M;CUT;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge9;:M;CUT;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;CUT;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face2;:M;CUT;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face3;:M;CUT;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;CUT;:H2:7,F", | |
| "Face5;:M;CUT;:H1:7,F", | |
| "Face6;:M;CUT;:H1:7,F", | |
| "Vertex1", | |
| "Vertex2", | |
| "Vertex3", | |
| "Vertex3;:M;CUT;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;CUT;:H2:7,V", | |
| "Vertex7", | |
| "Vertex8", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementBoolean(Part::OpCodes::Fuse, {topoShape1, topoShape2}); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75); | |
| // Assert element map is correct | |
| EXPECT_EQ(elements.size(), 66); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge10;:H2,E", | |
| "Edge10;:M2;FUS;:H1:8,E", | |
| "Edge10;:M;FUS;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M2;FUS;:H2:8,E", | |
| "Edge11;:M;FUS;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M2;FUS;:H2:8,E", | |
| "Edge12;:M;FUS;:H2:7,E", | |
| "Edge1;:H2,E", | |
| "Edge2", | |
| "Edge2;:M2;FUS;:H2:8,E", | |
| "Edge2;:M;FUS;:H2:7,E", | |
| "Edge3", | |
| "Edge4", | |
| "Edge4;:M2;FUS;:H2:8,E", | |
| "Edge4;:M;FUS;:H2:7,E", | |
| "Edge5;:H2,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge6;:H2,E", | |
| "Edge6;:M2;FUS;:H1:8,E", | |
| "Edge6;:M;FUS;:H1:7,E", | |
| "Edge7", | |
| "Edge7;:H2,E", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge8;:H2,E", | |
| "Edge8;:M2;FUS;:H1:8,E", | |
| "Edge8;:M;FUS;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge9;:H2,E", | |
| "Edge9;:M2;FUS;:H1:8,E", | |
| "Edge9;:M;FUS;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;FUS;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face2;:H2,F", | |
| "Face2;:M;FUS;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face3;:H2,F", | |
| "Face3;:M;FUS;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;FUS;:H2:7,F", | |
| "Face5;:M2(Face5;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face5;:M;FUS;:H1:7,F", | |
| "Face5;:M;FUS;:H2:7,F", | |
| "Face6;:M2(Face6;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face6;:M;FUS;:H1:7,F", | |
| "Face6;:M;FUS;:H2:7,F", | |
| "Vertex1", | |
| "Vertex1;:H2,V", | |
| "Vertex2", | |
| "Vertex2;:H2,V", | |
| "Vertex3", | |
| "Vertex3;:M;FUS;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;FUS;:H2:7,V", | |
| "Vertex5;:H2,V", | |
| "Vertex5;:M;FUS;:H1:7,V", | |
| "Vertex6;:H2,V", | |
| "Vertex6;:M;FUS;:H1:7,V", | |
| "Vertex7", | |
| "Vertex7;:H2,V", | |
| "Vertex8", | |
| "Vertex8;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementDraft) | |
| { // Draft as in Draft Angle or sloped sides for removing shapes from a mold. | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| std::vector<TopoShape> subShapes = cube1TS.getSubTopoShapes(TopAbs_FACE); | |
| std::vector<TopoShape> faces {subShapes[0], subShapes[1], subShapes[2], subShapes[3]}; | |
| const gp_Dir pullDirection {0, 0, 1}; | |
| double angle {std::numbers::pi * 10 / 8}; // Angle should be between Pi and Pi * 1.5 ( 180 and | |
| // 270 degrees ) | |
| const gp_Pln plane {}; | |
| // Act | |
| TopoShape& result = cube1TS.makeElementDraft(cube1TS, faces, pullDirection, angle, plane); | |
| auto elements = elementMap(result); | |
| // Assert | |
| EXPECT_NEAR(getVolume(result.getShape()), 4.3333333333, 1e-06); // Truncated pyramid | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 26); // Cubes have 6 Faces, 12 Edges, 8 Vertexes | |
| EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Face1;:G;DFT;:H1:7,F;:U;DFT;:H1:7,E")); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementDraftTopoShapes) | |
| { | |
| // Arrange | |
| auto [cube1TS, cube2TS] = CreateTwoTopoShapeCubes(); | |
| const gp_Dir pullDirection {0, 0, 1}; | |
| double angle {std::numbers::pi * 10 / 8}; // Angle should be between Pi and Pi * 1.5 ( 180 and | |
| // 270 degrees ) | |
| const gp_Pln plane {}; | |
| // Act | |
| TopoShape result3 = cube1TS.makeElementDraft( | |
| cube1TS.getSubTopoShapes(TopAbs_FACE), | |
| pullDirection, | |
| angle, | |
| plane | |
| ); // Non Reference call type | |
| TopoShape result2 = cube1TS.makeElementDraft( | |
| cube1TS, | |
| cube1TS.getSubTopoShapes(TopAbs_FACE), | |
| pullDirection, | |
| angle, | |
| plane | |
| ); // Bad use of Reference call | |
| TopoShape& result = cube1TS.makeElementDraft( | |
| cube2TS, | |
| cube2TS.getSubTopoShapes(TopAbs_FACE), | |
| pullDirection, | |
| angle, | |
| plane | |
| ); // Correct usage | |
| auto elements = elementMap((result)); | |
| // Assert | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 26); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;:H8,F;:G;DFT;:He:7,F")); | |
| EXPECT_NEAR(getVolume(result.getShape()), 4.3333333333, 1e-06); // Truncated pyramid | |
| EXPECT_EQ(result2.getElementMap().size(), 26); | |
| EXPECT_EQ(result3.getElementMap().size(), 26); | |
| } | |
| TEST_F(TopoShapeExpansionTest, linearizeEdge) | |
| { | |
| // Arrange | |
| TColgp_Array1OfPnt points {1, 2}; | |
| points.SetValue(1, gp_Pnt(0.0, 0.0, 0.0)); | |
| points.SetValue(2, gp_Pnt(1.0, 0.0, 0.0)); | |
| auto line1 = new Geom_BezierCurve(points); | |
| auto edge1 = BRepBuilderAPI_MakeEdge(line1).Edge(); | |
| TopoShape topoShape1 {edge1, 1L}; | |
| // Act | |
| auto edges = topoShape1.getSubTopoShapes(TopAbs_EDGE); | |
| BRepAdaptor_Curve curve(TopoDS::Edge(edges.front().getShape())); | |
| topoShape1.linearize(LinearizeFace::noFaces, LinearizeEdge::linearizeEdges); | |
| auto edges2 = topoShape1.getSubTopoShapes(TopAbs_EDGE); | |
| BRepAdaptor_Curve curve2(TopoDS::Edge(edges2.front().getShape())); | |
| // Assert | |
| EXPECT_EQ(curve.GetType(), GeomAbs_BezierCurve); | |
| EXPECT_EQ(curve2.GetType(), GeomAbs_Line); | |
| } | |
| TEST_F(TopoShapeExpansionTest, linearizeFace) | |
| { | |
| TColgp_Array2OfPnt points2 {1, 2, 1, 2}; | |
| points2.SetValue(1, 1, gp_Pnt(0.0, 0.0, 0.0)); | |
| points2.SetValue(2, 1, gp_Pnt(1.0, 0.0, 0.0)); | |
| points2.SetValue(1, 2, gp_Pnt(0.0, 1.0, 0.0)); | |
| points2.SetValue(2, 2, gp_Pnt(1.0, 1.0, 0.0)); | |
| auto face1 = new Geom_BezierSurface(points2); | |
| auto surf1 = BRepBuilderAPI_MakeFace(face1, 0.1).Face(); | |
| TopoShape topoShape2 {surf1, 2L}; | |
| // Act | |
| auto faces = topoShape2.getSubTopoShapes(TopAbs_FACE); | |
| BRepAdaptor_Surface surface(TopoDS::Face(faces.front().getShape())); | |
| topoShape2.linearize(LinearizeFace::linearizeFaces, LinearizeEdge::noEdges); | |
| auto faces2 = topoShape2.getSubTopoShapes(TopAbs_FACE); | |
| BRepAdaptor_Surface surface2(TopoDS::Face(faces.front().getShape())); | |
| // Assert | |
| EXPECT_EQ(surface.GetType(), GeomAbs_BezierSurface); | |
| EXPECT_EQ(surface2.GetType(), GeomAbs_Plane); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementRuledSurfaceEdges) | |
| { | |
| // Arrange | |
| auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, 8.0)).Edge(); | |
| auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(2.5, 0.0, 0.0), gp_Pnt(2.5, 0.0, 8.0)).Edge(); | |
| TopoShape edge1ts {edge1, 2L}; | |
| TopoShape edge2ts {edge2, 3L}; | |
| TopoShape topoShape {1L}; | |
| // Act | |
| topoShape.makeElementRuledSurface({edge1ts, edge2ts}, 0); // TODO: orientation as enum? | |
| auto elements = elementMap(topoShape); | |
| // Assert shape is correct | |
| EXPECT_EQ(topoShape.countSubElements("Wire"), 1); | |
| EXPECT_FLOAT_EQ(getArea(topoShape.getShape()), 20); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(topoShape.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 9); | |
| EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| topoShape, | |
| { | |
| "Edge1", | |
| "Edge1;:L(Edge1;D1|Vertex1;:L(Vertex1;D1);RSF|Vertex2;:L(Vertex2;D1);RSF);RSF", | |
| "Edge1;D1", | |
| "Vertex1", | |
| "Vertex1;:L(Vertex1;D1);RSF", | |
| "Vertex1;D1", | |
| "Vertex2", | |
| "Vertex2;:L(Vertex2;D1);RSF", | |
| "Vertex2;D1", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementRuledSurfaceWires) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| std::vector<TopoShape> subWires = cube1TS.getSubTopoShapes(TopAbs_WIRE); | |
| // Act | |
| auto surface = cube1TS.makeElementRuledSurface( | |
| {subWires[0], subWires[1]}, | |
| 0 | |
| ); // TODO: orientation as enum? | |
| auto elements = elementMap(surface); | |
| // Assert | |
| EXPECT_EQ(surface.countSubElements("Wire"), 4); | |
| EXPECT_NEAR(getArea(surface.getShape()), 4, 1e-7); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(surface.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 24); | |
| EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1); | |
| EXPECT_TRUE(elementsMatch( // Depending on OCCT versions can get 24 or 28 entries here. | |
| surface, | |
| { | |
| "Edge1", | |
| "Edge1;:L(Edge1;D1|Vertex1;:L(Vertex1;D1);RSF|Vertex2;:L(Vertex2;D1);RSF);RSF", | |
| "Edge1;D1", | |
| "Edge2", | |
| "Edge2;:L(Edge2;D1|Vertex1;:L(Vertex1;D1);RSF|Vertex3;:L(Vertex3;D1);RSF);RSF", | |
| "Edge2;D1", | |
| "Edge3", | |
| "Edge3;:L(Edge3;D1|Vertex3;:L(Vertex3;D1);RSF|Vertex4;:L(Vertex4;D1);RSF);RSF", | |
| "Edge3;D1", | |
| "Edge4", | |
| "Edge4;:L(Edge4;D1|Vertex2;:L(Vertex2;D1);RSF|Vertex4;:L(Vertex4;D1);RSF);RSF", | |
| "Edge4;D1", | |
| "Vertex1", | |
| "Vertex1;:L(Vertex1;D1);RSF", | |
| "Vertex1;D1", | |
| "Vertex2", | |
| "Vertex2;:L(Vertex2;D1);RSF", | |
| "Vertex2;D1", | |
| "Vertex3", | |
| "Vertex3;:L(Vertex3;D1);RSF", | |
| "Vertex3;D1", | |
| "Vertex4", | |
| "Vertex4;:L(Vertex4;D1);RSF", | |
| "Vertex4;D1", | |
| })); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementLoft) | |
| { | |
| // Loft must have either all open or all closed sections to work, we'll do two closed. | |
| // Arrange | |
| const float Len = 5; | |
| const float Wid = 5; | |
| auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(Len, Wid); | |
| auto transform {gp_Trsf()}; | |
| transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, 10.0)); | |
| auto wire2 = wire1; // Shallow copy | |
| wire2.Move(TopLoc_Location(transform)); | |
| TopoShape wire1ts {wire1, 1L}; // One of these shapes should have a tag or else we won't get an | |
| // Element Map | |
| TopoShape wire2ts {wire2, 2L}; // If you change either tag or eliminate one it changes the | |
| // resulting name. | |
| std::vector<TopoShape> shapes = {wire1ts, wire2ts}; | |
| // Act | |
| auto& topoShape = (new TopoShape())->makeElementLoft(shapes, IsSolid::notSolid, IsRuled::notRuled); | |
| auto& topoShape2 = (new TopoShape())->makeElementLoft(shapes, IsSolid::solid, IsRuled::notRuled); | |
| auto& topoShape3 = (new TopoShape())->makeElementLoft(shapes, IsSolid::notSolid, IsRuled::ruled); | |
| auto& topoShape4 = (new TopoShape())->makeElementLoft(shapes, IsSolid::solid, IsRuled::ruled); | |
| auto& topoShape5 | |
| = (new TopoShape()) | |
| ->makeElementLoft(shapes, IsSolid::notSolid, IsRuled::notRuled, IsClosed::closed); | |
| auto elements = elementMap((topoShape)); | |
| // Assert that we haven't broken the basic Loft functionality | |
| EXPECT_EQ(topoShape.countSubElements("Wire"), 4); | |
| EXPECT_DOUBLE_EQ(getArea(topoShape.getShape()), 200); | |
| EXPECT_NEAR(getVolume(topoShape.getShape()), 166.66667, 1e-5); | |
| EXPECT_DOUBLE_EQ(getVolume(topoShape2.getShape()), 250); | |
| EXPECT_NEAR(getVolume(topoShape3.getShape()), 166.66667, 1e-5); | |
| EXPECT_DOUBLE_EQ(getVolume(topoShape4.getShape()), 250); | |
| EXPECT_NEAR(getVolume(topoShape5.getShape()), 0, 1e-07); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(topoShape.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 24); | |
| EXPECT_TRUE(allElementsMatch( | |
| topoShape, | |
| { | |
| "Edge1;:G(Edge1;K-1;:H2:4,E);LFT;:H1:1a,F", "Edge1;:H1,E", "Edge1;:H2,E", | |
| "Edge2;:G(Edge2;K-1;:H2:4,E);LFT;:H1:1a,F", "Edge2;:H1,E", "Edge2;:H2,E", | |
| "Edge3;:G(Edge3;K-1;:H2:4,E);LFT;:H1:1a,F", "Edge3;:H1,E", "Edge3;:H2,E", | |
| "Edge4;:G(Edge4;K-1;:H2:4,E);LFT;:H1:1a,F", "Edge4;:H1,E", "Edge4;:H2,E", | |
| "Vertex1;:G(Vertex1;K-1;:H2:4,V);LFT;:H1:1c,E", "Vertex1;:H1,V", "Vertex1;:H2,V", | |
| "Vertex2;:G(Vertex2;K-1;:H2:4,V);LFT;:H1:1c,E", "Vertex2;:H1,V", "Vertex2;:H2,V", | |
| "Vertex3;:G(Vertex3;K-1;:H2:4,V);LFT;:H1:1c,E", "Vertex3;:H1,V", "Vertex3;:H2,V", | |
| "Vertex4;:G(Vertex4;K-1;:H2:4,V);LFT;:H1:1c,E", "Vertex4;:H1,V", "Vertex4;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementPipeShell) | |
| { | |
| // Arrange | |
| const float Len = 5; | |
| const float Wid = 5; | |
| auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(Len, Wid); | |
| auto edge5 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, -8.0)).Edge(); | |
| auto wire2 = BRepBuilderAPI_MakeWire({edge5}).Wire(); | |
| TopoShape face1ts {face1, 1L}; | |
| TopoShape edge5ts {edge5, 2L}; | |
| std::vector<TopoShape> shapes = {face1ts, edge5ts}; | |
| // Act | |
| auto& topoShape = (new TopoShape())->makeElementPipeShell(shapes, MakeSolid::noSolid, false); | |
| auto elements = elementMap((topoShape)); | |
| // Assert that we haven't broken the basic Loft functionality | |
| EXPECT_EQ(topoShape.countSubElements("Wire"), 4); | |
| EXPECT_DOUBLE_EQ(getArea(topoShape.getShape()), 160); | |
| EXPECT_NEAR(getVolume(topoShape.getShape()), 133.33334, 1e-5); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(topoShape.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 24); | |
| EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1); | |
| EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Vertex1;:G;PSH;:H2:7,E")); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementThickSolid) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| std::vector<TopoShape> subFaces = cube1TS.getSubTopoShapes(TopAbs_FACE); | |
| subFaces[0].Tag = 2L; | |
| subFaces[1].Tag = 3L; | |
| std::vector<TopoShape> shapes = {subFaces[0], subFaces[1]}; | |
| // Act | |
| TopoShape& result = cube1TS.makeElementThickSolid(cube1TS, shapes, 0.1, 1e-07); | |
| (void)result; | |
| auto elements = elementMap(cube1TS); | |
| // Assert | |
| EXPECT_EQ(cube1TS.countSubElements("Wire"), 16); | |
| EXPECT_NEAR(getArea(cube1TS.getShape()), 9.4911509, 1e-6); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(cube1TS.getMappedChildElements().empty()); | |
| EXPECT_EQ(elements.size(), 74); | |
| EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1); | |
| // Note: Cannot do an elementsMatch here because the oldest OCCT treats ThickSolid a little | |
| // differently. So, just mae sure the size is right, and something has a THK in it. | |
| for (auto& element : elements) { | |
| if (element.second.find("THK") > 0) { | |
| EXPECT_TRUE(1); | |
| break; | |
| }; | |
| } | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementGeneralFuse) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| std::vector<std::vector<TopoShape>> modified {{}}; | |
| TopoShape& result = topoShape1.makeElementGeneralFuse({topoShape1, topoShape2}, modified); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 72); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);GFS;:H1:1a,V", | |
| "Edge10;:H2,E", | |
| "Edge10;:M2;GFS;:H1:8,E", | |
| "Edge10;:M;GFS;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M2;GFS;:H2:8,E", | |
| "Edge11;:M;GFS;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M2;GFS;:H2:8,E", | |
| "Edge12;:M;GFS;:H2:7,E", | |
| "Edge1;:H2,E", | |
| "Edge2", | |
| "Edge2;:M2;GFS;:H2:8,E", | |
| "Edge2;:M;GFS;:H2:7,E", | |
| "Edge3", | |
| "Edge3;:M;GFS;:H2:7,E", | |
| "Edge4", | |
| "Edge4;:M2;GFS;:H2:8,E", | |
| "Edge4;:M;GFS;:H2:7,E", | |
| "Edge5;:H2,E", | |
| "Edge5;:M;GFS;:H1:7,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);GFS;:H1:1b,V", | |
| "Edge6;:H2,E", | |
| "Edge6;:M2;GFS;:H1:8,E", | |
| "Edge6;:M;GFS;:H1:7,E", | |
| "Edge7", | |
| "Edge7;:H2,E", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);GFS;:H1:1b,V", | |
| "Edge8;:H2,E", | |
| "Edge8;:M2;GFS;:H1:8,E", | |
| "Edge8;:M;GFS;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);GFS;:H1:1a,V", | |
| "Edge9;:H2,E", | |
| "Edge9;:M2;GFS;:H1:8,E", | |
| "Edge9;:M;GFS;:H1:7,E", | |
| "Face1", | |
| "Face1;:M2;GFS;:H2:8,F", | |
| "Face1;:M;GFS;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);GFS;:H1:1a,E", | |
| "Face2;:H2,F", | |
| "Face2;:M2;GFS;:H1:8,F", | |
| "Face2;:M;GFS;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);GFS;:H1:1a,E", | |
| "Face3;:H2,F", | |
| "Face3;:M2;GFS;:H1:8,F", | |
| "Face3;:M;GFS;:H1:7,F", | |
| "Face4", | |
| "Face4;:M2;GFS;:H2:8,F", | |
| "Face4;:M;GFS;:H2:7,F", | |
| "Face5;:M2(Face5;K2;:H2:3,F);GFS;:H1:1a,F", | |
| "Face5;:M;GFS;:H1:7,F", | |
| "Face5;:M;GFS;:H2:7,F", | |
| "Face6;:M2(Face6;K2;:H2:3,F);GFS;:H1:1a,F", | |
| "Face6;:M;GFS;:H1:7,F", | |
| "Face6;:M;GFS;:H2:7,F", | |
| "Vertex1", | |
| "Vertex1;:H2,V", | |
| "Vertex2", | |
| "Vertex2;:H2,V", | |
| "Vertex3", | |
| "Vertex3;:M;GFS;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;GFS;:H2:7,V", | |
| "Vertex5;:H2,V", | |
| "Vertex5;:M;GFS;:H1:7,V", | |
| "Vertex6;:H2,V", | |
| "Vertex6;:M;GFS;:H1:7,V", | |
| "Vertex7", | |
| "Vertex7;:H2,V", | |
| "Vertex8", | |
| "Vertex8;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFuse) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementFuse({topoShape1, topoShape2}); // op, tolerance | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 66); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge10;:H2,E", | |
| "Edge10;:M2;FUS;:H1:8,E", | |
| "Edge10;:M;FUS;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M2;FUS;:H2:8,E", | |
| "Edge11;:M;FUS;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M2;FUS;:H2:8,E", | |
| "Edge12;:M;FUS;:H2:7,E", | |
| "Edge1;:H2,E", | |
| "Edge2", | |
| "Edge2;:M2;FUS;:H2:8,E", | |
| "Edge2;:M;FUS;:H2:7,E", | |
| "Edge3", | |
| "Edge4", | |
| "Edge4;:M2;FUS;:H2:8,E", | |
| "Edge4;:M;FUS;:H2:7,E", | |
| "Edge5;:H2,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge6;:H2,E", | |
| "Edge6;:M2;FUS;:H1:8,E", | |
| "Edge6;:M;FUS;:H1:7,E", | |
| "Edge7", | |
| "Edge7;:H2,E", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge8;:H2,E", | |
| "Edge8;:M2;FUS;:H1:8,E", | |
| "Edge8;:M;FUS;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge9;:H2,E", | |
| "Edge9;:M2;FUS;:H1:8,E", | |
| "Edge9;:M;FUS;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;FUS;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face2;:H2,F", | |
| "Face2;:M;FUS;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face3;:H2,F", | |
| "Face3;:M;FUS;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;FUS;:H2:7,F", | |
| "Face5;:M2(Face5;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face5;:M;FUS;:H1:7,F", | |
| "Face5;:M;FUS;:H2:7,F", | |
| "Face6;:M2(Face6;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face6;:M;FUS;:H1:7,F", | |
| "Face6;:M;FUS;:H2:7,F", | |
| "Vertex1", | |
| "Vertex1;:H2,V", | |
| "Vertex2", | |
| "Vertex2;:H2,V", | |
| "Vertex3", | |
| "Vertex3;:M;FUS;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;FUS;:H2:7,V", | |
| "Vertex5;:H2,V", | |
| "Vertex5;:M;FUS;:H1:7,V", | |
| "Vertex6;:H2,V", | |
| "Vertex6;:M;FUS;:H1:7,V", | |
| "Vertex7", | |
| "Vertex7;:H2,V", | |
| "Vertex8", | |
| "Vertex8;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementCut) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementCut( | |
| {topoShape1, topoShape2} | |
| ); //, const char* op = nullptr, double tol = 0); | |
| auto elements = elementMap(result); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 38); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge10;:M;CUT;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M;CUT;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M;CUT;:H2:7,E", | |
| "Edge2", | |
| "Edge2;:M;CUT;:H2:7,E", | |
| "Edge3", | |
| "Edge3;:M;CUT;:H2:7,E", | |
| "Edge4", | |
| "Edge4;:M;CUT;:H2:7,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge6;:M;CUT;:H1:7,E", | |
| "Edge7", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge8;:M;CUT;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge9;:M;CUT;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;CUT;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face2;:M;CUT;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face3;:M;CUT;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;CUT;:H2:7,F", | |
| "Face5;:M;CUT;:H1:7,F", | |
| "Face6;:M;CUT;:H1:7,F", | |
| "Vertex1", | |
| "Vertex2", | |
| "Vertex3", | |
| "Vertex3;:M;CUT;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;CUT;:H2:7,V", | |
| "Vertex7", | |
| "Vertex8", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementChamfer) | |
| { | |
| // Arrange | |
| // Fillets / Chamfers do not work on compounds of faces, so use complete boxes ( Solids ) here. | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE); | |
| // Act | |
| cube1TS.makeElementChamfer({cube1TS}, edges, Part::ChamferType::equalDistance, .05, .05); | |
| auto elements = elementMap(cube1TS); | |
| // Assert shape is correct | |
| EXPECT_EQ(cube1TS.countSubElements("Wire"), 26); | |
| EXPECT_NEAR(getArea(cube1TS.getShape()), 5.640996, 1e-6); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(cube1TS.getMappedChildElements().empty()); | |
| EXPECT_TRUE(allElementsMatch( | |
| cube1TS, | |
| { | |
| "Edge10;:G;CHF;:H1:7,F", | |
| "Edge10;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge10;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge10;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge10;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge11;:G;CHF;:H1:7,F", | |
| "Edge11;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge11;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge11;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge11;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge12;:G;CHF;:H1:7,F", | |
| "Edge12;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge12;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge12;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge12;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge1;:G;CHF;:H1:7,F", | |
| "Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge1;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge1;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge2;:G;CHF;:H1:7,F", | |
| "Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge2;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge2;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge2;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge2;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge3;:G;CHF;:H1:7,F", | |
| "Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge3;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge3;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge3;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge3;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge4;:G;CHF;:H1:7,F", | |
| "Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge4;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge4;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge4;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge5;:G;CHF;:H1:7,F", | |
| "Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge5;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge5;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge6;:G;CHF;:H1:7,F", | |
| "Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge6;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge6;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge6;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge6;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge7;:G;CHF;:H1:7,F", | |
| "Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge7;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge7;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge7;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge7;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge8;:G;CHF;:H1:7,F", | |
| "Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V", | |
| "Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V", | |
| "Edge8;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge8;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge8;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Edge9;:G;CHF;:H1:7,F", | |
| "Edge9;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E", | |
| "Edge9;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E", | |
| "Edge9;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E", | |
| "Edge9;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E", | |
| "Face1;:M;CHF;:H1:7,F", | |
| "Face2;:M;CHF;:H1:7,F", | |
| "Face3;:M;CHF;:H1:7,F", | |
| "Face4;:M;CHF;:H1:7,F", | |
| "Face5;:M;CHF;:H1:7,F", | |
| "Face6;:M;CHF;:H1:7,F", | |
| "Vertex1;:G;CHF;:H1:7,F", | |
| "Vertex2;:G;CHF;:H1:7,F", | |
| "Vertex3;:G;CHF;:H1:7,F", | |
| "Vertex4;:G;CHF;:H1:7,F", | |
| "Vertex5;:G;CHF;:H1:7,F", | |
| "Vertex6;:G;CHF;:H1:7,F", | |
| "Vertex7;:G;CHF;:H1:7,F", | |
| "Vertex8;:G;CHF;:H1:7,F", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFillet) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE); | |
| // Act | |
| cube1TS.makeElementFillet({cube1TS}, edges, .05, .05); | |
| auto elements = elementMap(cube1TS); | |
| // Assert shape is correct | |
| EXPECT_EQ(cube1TS.countSubElements("Wire"), 26); | |
| EXPECT_NEAR(getArea(cube1TS.getShape()), 5.739646, 1e-6); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(cube1TS.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| cube1TS, | |
| { | |
| "Edge10;:G;FLT;:H1:7,F", | |
| "Edge10;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge10;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge10;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge10;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge11;:G;FLT;:H1:7,F", | |
| "Edge11;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge11;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge11;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge11;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge12;:G;FLT;:H1:7,F", | |
| "Edge12;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge12;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge12;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge12;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge1;:G;FLT;:H1:7,F", | |
| "Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge1;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge1;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge2;:G;FLT;:H1:7,F", | |
| "Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge2;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge2;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge2;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge2;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge3;:G;FLT;:H1:7,F", | |
| "Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge3;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge3;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge3;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge3;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge4;:G;FLT;:H1:7,F", | |
| "Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge4;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge4;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge4;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge5;:G;FLT;:H1:7,F", | |
| "Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge5;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge5;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge6;:G;FLT;:H1:7,F", | |
| "Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge6;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge6;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge6;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge6;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge7;:G;FLT;:H1:7,F", | |
| "Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge7;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge7;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge7;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge7;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge8;:G;FLT;:H1:7,F", | |
| "Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V", | |
| "Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V", | |
| "Edge8;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge8;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge8;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Edge9;:G;FLT;:H1:7,F", | |
| "Edge9;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Edge9;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E", | |
| "Edge9;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E", | |
| "Edge9;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E", | |
| "Face1;:M;FLT;:H1:7,F", | |
| "Face2;:M;FLT;:H1:7,F", | |
| "Face3;:M;FLT;:H1:7,F", | |
| "Face4;:M;FLT;:H1:7,F", | |
| "Face5;:M;FLT;:H1:7,F", | |
| "Face6;:M;FLT;:H1:7,F", | |
| "Vertex1;:G;FLT;:H1:7,F", | |
| "Vertex1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex2;:G;FLT;:H1:7,F", | |
| "Vertex2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex3;:G;FLT;:H1:7,F", | |
| "Vertex3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex4;:G;FLT;:H1:7,F", | |
| "Vertex4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex5;:G;FLT;:H1:7,F", | |
| "Vertex5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex6;:G;FLT;:H1:7,F", | |
| "Vertex6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex7;:G;FLT;:H1:7,F", | |
| "Vertex7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| "Vertex8;:G;FLT;:H1:7,F", | |
| "Vertex8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementSlice) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); // TopoShape version works too | |
| TopoShape cube1TS {cube1}; // Adding a tag here only adds text in each mapped name | |
| auto faces = cube1TS.getSubShapes(TopAbs_FACE); | |
| TopoShape slicer {faces[0]}; | |
| Base::Vector3d direction {1.0, 0.0, 0.0}; | |
| // Act | |
| auto& result = slicer.makeElementSlice(cube1TS, direction, 0.5); | |
| // Assert shape is correct | |
| EXPECT_FLOAT_EQ(getLength(result.getShape()), 4); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, result.getShape().ShapeType()); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Face1;:G2;SLC;:H1:8,V;SLC;:H1:4,V", | |
| "Face1;:G3;SLC;:H1:8,V;SLC;:H1:4,V", | |
| "Face1;:G4;SLC;:H1:8,V;SLC;:H1:4,V", | |
| "Face1;:G5;SLC;:H1:8,E;SLC;:H1:4,E", | |
| "Face1;:G6;SLC;:H1:8,E;SLC;:H1:4,E", | |
| "Face1;:G7;SLC;:H1:8,E;SLC;:H1:4,E", | |
| "Face1;:G8;SLC;:H1:8,E;SLC;:H1:4,E", | |
| "Face1;:G;SLC;:H1:7,V;SLC;:H1:4,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementSlices) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| auto faces = cube1TS.getSubShapes(TopAbs_FACE); | |
| TopoShape slicer {faces[0]}; | |
| Base::Vector3d direction {1.0, 0.0, 0.0}; | |
| // Act | |
| auto& result = slicer.makeElementSlices(cube1TS, direction, {0.25, 0.5, 0.75}); | |
| auto subTopoShapes = result.getSubTopoShapes(TopAbs_WIRE); | |
| // Assert shape is correct | |
| EXPECT_EQ(result.countSubElements("Wire"), 3); | |
| EXPECT_FLOAT_EQ(getLength(result.getShape()), 12); | |
| EXPECT_FLOAT_EQ(getLength(subTopoShapes[0].getShape()), 4); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_COMPOUND, result.getShape().ShapeType()); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[0].getShape().ShapeType()); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[1].getShape().ShapeType()); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[2].getShape().ShapeType()); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge10;:G(Face1;K-2;:H1:4,F);SLC;:H1:1a,V;SLC;:H1:4,V", | |
| "Edge10;:G(Face1;K-2;:H2:4,F);SLC_2;:H1:1c,V;SLC_2;:H1:6,V", | |
| "Edge10;:G(Face1;K-2;:H3:4,F);SLC_3;:H1:1c,V;SLC_3;:H1:6,V", | |
| "Edge11;:G(Face1;K-3;:H1:4,F);SLC;:H1:1a,V;SLC;:H1:4,V", | |
| "Edge11;:G(Face1;K-3;:H2:4,F);SLC_2;:H1:1c,V;SLC_2;:H1:6,V", | |
| "Edge11;:G(Face1;K-3;:H3:4,F);SLC_3;:H1:1c,V;SLC_3;:H1:6,V", | |
| "Edge12;:G(Face1;K-4;:H1:4,F);SLC;:H1:1a,V;SLC;:H1:4,V", | |
| "Edge12;:G(Face1;K-4;:H2:4,F);SLC_2;:H1:1c,V;SLC_2;:H1:6,V", | |
| "Edge12;:G(Face1;K-4;:H3:4,F);SLC_3;:H1:1c,V;SLC_3;:H1:6,V", | |
| "Edge9;:G(Face1;K-1;:H1:4,F);SLC;:H1:1a,V;SLC;:H1:4,V", | |
| "Edge9;:G(Face1;K-1;:H2:4,F);SLC_2;:H1:1c,V;SLC_2;:H1:6,V", | |
| "Edge9;:G(Face1;K-1;:H3:4,F);SLC_3;:H1:1c,V;SLC_3;:H1:6,V", | |
| "Face1;:G5(Face3;K-1;:H1:4,F);SLC;:H1:1b,E;SLC;:H1:4,E", | |
| "Face1;:G6(Face4;K-1;:H1:4,F);SLC;:H1:1b,E;SLC;:H1:4,E", | |
| "Face1;:G7(Face5;K-1;:H1:4,F);SLC;:H1:1b,E;SLC;:H1:4,E", | |
| "Face1;:G8(Face6;K-1;:H1:4,F);SLC;:H1:1b,E;SLC;:H1:4,E", | |
| "Face3;:G(Face1;K-5;:H2:4,F);SLC_2;:H1:1c,E;SLC_2;:H1:6,E", | |
| "Face3;:G(Face1;K-5;:H3:4,F);SLC_3;:H1:1c,E;SLC_3;:H1:6,E", | |
| "Face4;:G(Face1;K-6;:H2:4,F);SLC_2;:H1:1c,E;SLC_2;:H1:6,E", | |
| "Face4;:G(Face1;K-6;:H3:4,F);SLC_3;:H1:1c,E;SLC_3;:H1:6,E", | |
| "Face5;:G(Face1;K-7;:H2:4,F);SLC_2;:H1:1c,E;SLC_2;:H1:6,E", | |
| "Face5;:G(Face1;K-7;:H3:4,F);SLC_3;:H1:1c,E;SLC_3;:H1:6,E", | |
| "Face6;:G(Face1;K-8;:H2:4,F);SLC_2;:H1:1c,E;SLC_2;:H1:6,E", | |
| "Face6;:G(Face1;K-8;:H3:4,F);SLC_3;:H1:1c,E;SLC_3;:H1:6,E", | |
| } | |
| )); | |
| EXPECT_FALSE(subTopoShapes[0].getElementMap().empty()); // Changed with PR#12471. Probably will | |
| // change again after importing other | |
| // TopoNaming logics | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementMirror) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE); | |
| gp_Ax2 axis {gp_Pnt {0, 0, 0}, gp_Dir {1, 0, 0}}; | |
| // Act | |
| auto& result = cube1TS.makeElementMirror(cube1TS, axis); | |
| auto elements = elementMap(cube1TS); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-1, 0, 0, 0, 1, 1))); | |
| EXPECT_EQ(result.countSubElements("Wire"), 6); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1); | |
| EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_SOLID, result.getShape().ShapeType()); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| {"Edge10;:M;MIR;:H1:7,E", "Edge11;:M;MIR;:H1:7,E", "Edge12;:M;MIR;:H1:7,E", | |
| "Edge1;:M;MIR;:H1:7,E", "Edge2;:M;MIR;:H1:7,E", "Edge3;:M;MIR;:H1:7,E", | |
| "Edge4;:M;MIR;:H1:7,E", "Edge5;:M;MIR;:H1:7,E", "Edge6;:M;MIR;:H1:7,E", | |
| "Edge7;:M;MIR;:H1:7,E", "Edge8;:M;MIR;:H1:7,E", "Edge9;:M;MIR;:H1:7,E", | |
| "Face1;:M;MIR;:H1:7,F", "Face2;:M;MIR;:H1:7,F", "Face3;:M;MIR;:H1:7,F", | |
| "Face4;:M;MIR;:H1:7,F", "Face5;:M;MIR;:H1:7,F", "Face6;:M;MIR;:H1:7,F", | |
| "Vertex1;:M;MIR;:H1:7,V", "Vertex2;:M;MIR;:H1:7,V", "Vertex3;:M;MIR;:H1:7,V", | |
| "Vertex4;:M;MIR;:H1:7,V", "Vertex5;:M;MIR;:H1:7,V", "Vertex6;:M;MIR;:H1:7,V", | |
| "Vertex7;:M;MIR;:H1:7,V", "Vertex8;:M;MIR;:H1:7,V"} | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementTransformWithoutMap) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementTransform(topoShape1, tr); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -0.5, 0.0, 0.5, 0.5, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 0); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementTransformWithMap) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementFuse({topoShape1, topoShape2}); // op, tolerance | |
| topoShape1.makeElementTransform(result, tr); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -1.0, 0.0, 1.0, 0.5, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 66); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge10;:H2,E", | |
| "Edge10;:M2;FUS;:H1:8,E", | |
| "Edge10;:M;FUS;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M2;FUS;:H2:8,E", | |
| "Edge11;:M;FUS;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M2;FUS;:H2:8,E", | |
| "Edge12;:M;FUS;:H2:7,E", | |
| "Edge1;:H2,E", | |
| "Edge2", | |
| "Edge2;:M2;FUS;:H2:8,E", | |
| "Edge2;:M;FUS;:H2:7,E", | |
| "Edge3", | |
| "Edge4", | |
| "Edge4;:M2;FUS;:H2:8,E", | |
| "Edge4;:M;FUS;:H2:7,E", | |
| "Edge5;:H2,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge6;:H2,E", | |
| "Edge6;:M2;FUS;:H1:8,E", | |
| "Edge6;:M;FUS;:H1:7,E", | |
| "Edge7", | |
| "Edge7;:H2,E", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge8;:H2,E", | |
| "Edge8;:M2;FUS;:H1:8,E", | |
| "Edge8;:M;FUS;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge9;:H2,E", | |
| "Edge9;:M2;FUS;:H1:8,E", | |
| "Edge9;:M;FUS;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;FUS;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face2;:H2,F", | |
| "Face2;:M;FUS;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face3;:H2,F", | |
| "Face3;:M;FUS;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;FUS;:H2:7,F", | |
| "Face5;:M2(Face5;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face5;:M;FUS;:H1:7,F", | |
| "Face5;:M;FUS;:H2:7,F", | |
| "Face6;:M2(Face6;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face6;:M;FUS;:H1:7,F", | |
| "Face6;:M;FUS;:H2:7,F", | |
| "Vertex1", | |
| "Vertex1;:H2,V", | |
| "Vertex2", | |
| "Vertex2;:H2,V", | |
| "Vertex3", | |
| "Vertex3;:M;FUS;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;FUS;:H2:7,V", | |
| "Vertex5;:H2,V", | |
| "Vertex5;:M;FUS;:H1:7,V", | |
| "Vertex6;:H2,V", | |
| "Vertex6;:M;FUS;:H1:7,V", | |
| "Vertex7", | |
| "Vertex7;:H2,V", | |
| "Vertex8", | |
| "Vertex8;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementGTransformWithoutMap) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementGTransform(topoShape1, TopoShape::convert(tr)); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -0.5, 0.0, 0.5, 0.5, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 0); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementFuse({topoShape1, topoShape2}); // op, tolerance | |
| topoShape1.makeElementGTransform(result, TopoShape::convert(tr)); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -1.0, 0.0, 1.0, 0.5, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 66); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge10;:H2,E", | |
| "Edge10;:M2;FUS;:H1:8,E", | |
| "Edge10;:M;FUS;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M2;FUS;:H2:8,E", | |
| "Edge11;:M;FUS;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M2;FUS;:H2:8,E", | |
| "Edge12;:M;FUS;:H2:7,E", | |
| "Edge1;:H2,E", | |
| "Edge2", | |
| "Edge2;:M2;FUS;:H2:8,E", | |
| "Edge2;:M;FUS;:H2:7,E", | |
| "Edge3", | |
| "Edge4", | |
| "Edge4;:M2;FUS;:H2:8,E", | |
| "Edge4;:M;FUS;:H2:7,E", | |
| "Edge5;:H2,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge6;:H2,E", | |
| "Edge6;:M2;FUS;:H1:8,E", | |
| "Edge6;:M;FUS;:H1:7,E", | |
| "Edge7", | |
| "Edge7;:H2,E", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);FUS;:H1:1b,V", | |
| "Edge8;:H2,E", | |
| "Edge8;:M2;FUS;:H1:8,E", | |
| "Edge8;:M;FUS;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);FUS;:H1:1a,V", | |
| "Edge9;:H2,E", | |
| "Edge9;:M2;FUS;:H1:8,E", | |
| "Edge9;:M;FUS;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;FUS;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face2;:H2,F", | |
| "Face2;:M;FUS;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);FUS;:H1:1a,E", | |
| "Face3;:H2,F", | |
| "Face3;:M;FUS;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;FUS;:H2:7,F", | |
| "Face5;:M2(Face5;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face5;:M;FUS;:H1:7,F", | |
| "Face5;:M;FUS;:H2:7,F", | |
| "Face6;:M2(Face6;K2;:H2:3,F);FUS;:H1:1a,F", | |
| "Face6;:M;FUS;:H1:7,F", | |
| "Face6;:M;FUS;:H2:7,F", | |
| "Vertex1", | |
| "Vertex1;:H2,V", | |
| "Vertex2", | |
| "Vertex2;:H2,V", | |
| "Vertex3", | |
| "Vertex3;:M;FUS;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;FUS;:H2:7,V", | |
| "Vertex5;:H2,V", | |
| "Vertex5;:M;FUS;:H1:7,V", | |
| "Vertex6;:H2,V", | |
| "Vertex6;:M;FUS;:H1:7,V", | |
| "Vertex7", | |
| "Vertex7;:H2,V", | |
| "Vertex8", | |
| "Vertex8;:H2,V", | |
| } | |
| )); | |
| } | |
| // Not testing _makeElementTransform as it is a thin wrapper that calls the same places as the four | |
| // preceding tests. | |
| TEST_F(TopoShapeExpansionTest, makeElementSolid) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopExp_Explorer exp(topoShape1.getShape(), TopAbs_SHELL); | |
| auto shell1 = exp.Current(); | |
| exp.Init(topoShape2.getShape(), TopAbs_SHELL); | |
| auto shell2 = exp.Current(); | |
| TopoShape& topoShape3 = topoShape1.makeElementCompound({shell1, shell2}); | |
| TopoShape& result = topoShape1.makeElementSolid(topoShape3); // Need the single parm form | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, -0.5, 0.0, 1.5, 1.0, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 2); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(elements.size(), 52); | |
| EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge10;:C1;:H:4,E", "Edge10;:H,E", "Edge11;:C1;:H:4,E", "Edge11;:H,E", | |
| "Edge12;:C1;:H:4,E", "Edge12;:H,E", "Edge1;:C1;:H:4,E", "Edge1;:H,E", | |
| "Edge2;:C1;:H:4,E", "Edge2;:H,E", "Edge3;:C1;:H:4,E", "Edge3;:H,E", | |
| "Edge4;:C1;:H:4,E", "Edge4;:H,E", "Edge5;:C1;:H:4,E", "Edge5;:H,E", | |
| "Edge6;:C1;:H:4,E", "Edge6;:H,E", "Edge7;:C1;:H:4,E", "Edge7;:H,E", | |
| "Edge8;:C1;:H:4,E", "Edge8;:H,E", "Edge9;:C1;:H:4,E", "Edge9;:H,E", | |
| "Face1;:C1;:H:4,F", "Face1;:H,F", "Face2;:C1;:H:4,F", "Face2;:H,F", | |
| "Face3;:C1;:H:4,F", "Face3;:H,F", "Face4;:C1;:H:4,F", "Face4;:H,F", | |
| "Face5;:C1;:H:4,F", "Face5;:H,F", "Face6;:C1;:H:4,F", "Face6;:H,F", | |
| "Vertex1;:C1;:H:4,V", "Vertex1;:H,V", "Vertex2;:C1;:H:4,V", "Vertex2;:H,V", | |
| "Vertex3;:C1;:H:4,V", "Vertex3;:H,V", "Vertex4;:C1;:H:4,V", "Vertex4;:H,V", | |
| "Vertex5;:C1;:H:4,V", "Vertex5;:H,V", "Vertex6;:C1;:H:4,V", "Vertex6;:H,V", | |
| "Vertex7;:C1;:H:4,V", "Vertex7;:H,V", "Vertex8;:C1;:H:4,V", "Vertex8;:H,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementRevolve) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| gp_Ax1 axis {gp_Pnt {0, 0, 0}, gp_Dir {0, 1, 0}}; | |
| double angle = 45; | |
| auto subTopoFaces = topoShape1.getSubTopoShapes(TopAbs_FACE); | |
| subTopoFaces[0].Tag = 2L; | |
| // Act | |
| TopoShape result = subTopoFaces[0].makeElementRevolve(axis, angle); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE( | |
| PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 0.85090352453411933, 1.0, 1.0)) | |
| ); | |
| EXPECT_NEAR(getVolume(result.getShape()), 0.50885141, 1e-6); | |
| // Assert elementMap is correct | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:G;RVL;:H2:7,F", | |
| "Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E", | |
| "Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:L(Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:" | |
| "7,E|Edge3;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E|Edge4;:H2,E);RVL;:H2:5c,F", | |
| "Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:U;RVL;:H2:7,V", | |
| "Edge1;:H2,E", | |
| "Edge2;:G;RVL;:H2:7,F", | |
| "Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E", | |
| "Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:U;RVL;:H2:7,V", | |
| "Edge2;:H2,E", | |
| "Edge3;:G;RVL;:H2:7,F", | |
| "Edge3;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E", | |
| "Edge3;:H2,E", | |
| "Edge4;:H2,E", | |
| "Face1;:H2,F", | |
| "Vertex1;:G;RVL;:H2:7,E", | |
| "Vertex1;:H2,V", | |
| "Vertex2;:H2,V", | |
| "Vertex3;:G;RVL;:H2:7,E", | |
| "Vertex3;:H2,V", | |
| "Vertex4;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementPrism) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| auto subTopoFaces = topoShape1.getSubTopoShapes(TopAbs_FACE); | |
| subTopoFaces[0].Tag = 2L; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementPrism(subTopoFaces[0], {0.75, 0, 0}); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 0.75, 1.0, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.75); | |
| // Assert elementMap is correct | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:G;XTR;:H2:7,F", | |
| "Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E", | |
| "Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U2;XTR;:H2:8,V", | |
| "Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U;XTR;:H2:7,V", | |
| "Edge1;:H2,E", | |
| "Edge2;:G;XTR;:H2:7,F", | |
| "Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E", | |
| "Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U;XTR;:H2:7,V", | |
| "Edge2;:H2,E", | |
| "Edge3;:G;XTR;:H2:7,F", | |
| "Edge3;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E", | |
| "Edge3;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U2;XTR;:H2:8,V", | |
| "Edge3;:H2,E", | |
| "Edge4;:G;XTR;:H2:7,F", | |
| "Edge4;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E", | |
| "Edge4;:H2,E", | |
| "Face1;:H2,F", | |
| "Vertex1;:G;XTR;:H2:7,E", | |
| "Vertex1;:H2,V", | |
| "Vertex2;:G;XTR;:H2:7,E", | |
| "Vertex2;:H2,V", | |
| "Vertex3;:G;XTR;:H2:7,E", | |
| "Vertex3;:H2,V", | |
| "Vertex4;:G;XTR;:H2:7,E", | |
| "Vertex4;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementPrismUntil) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape cube1TS {cube1, 1L}; | |
| auto subTopoFaces = cube1TS.getSubTopoShapes(TopAbs_FACE); | |
| auto direction = gp_Vec(gp_XYZ(0.0, 0.0, 1)); | |
| // Act | |
| TopoShape result = cube1TS.makeElementPrismUntil( | |
| subTopoFaces[4], | |
| subTopoFaces[4], | |
| subTopoFaces[5], | |
| direction, | |
| TopoShape::PrismMode::FuseWithBase | |
| ); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 1.0, 1.0, 1.0))); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1); | |
| // Assert elementMap is correct | |
| // EXPECT_EQ(result.getElementMapSize(),26); // Todo: Sometimes too big in TNP code. Why? | |
| EXPECT_EQ(result.countSubElements("Edge"), 12); | |
| EXPECT_EQ(result.countSubElements("Face"), 6); | |
| EXPECT_EQ(result.countSubElements("Vertex"), 8); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementFilledFace) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| auto wires = topoShape1.getSubShapes(TopAbs_WIRE); | |
| TopoShape topoShape2 {wires[0], 2L}; | |
| // Act | |
| auto params = TopoShape::BRepFillingParams(); | |
| TopoShape& result = topoShape1.makeElementFilledFace({topoShape2}, params); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, -0.6, -0.6, 0, 1.6, 1.6))); | |
| EXPECT_FLOAT_EQ(getArea(result.getShape()), 1); | |
| // Assert elementMap is correct | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:G;FFC;:H2:7,E", | |
| "Edge1;:G;FFC;:H2:7,E;:L(Edge2;:G;FFC;:H2:7,E|Edge3;:G;FFC;:" | |
| "H2:7,E|Edge4;:G;FFC;:H2:7,E);FFC;:H2:47,F", | |
| "Edge2;:G;FFC;:H2:7,E", | |
| "Edge3;:G;FFC;:H2:7,E", | |
| "Edge4;:G;FFC;:H2:7,E", | |
| // TODO: Prove that this difference is not a problem. | |
| // The next elements vary according to platform / OCCT version | |
| // and thus can't be absolutely tested. | |
| // "Vertex1;:G;FFC;:H2:7,V", | |
| // "Vertex2;:G;FFC;:H2:7,V", | |
| // "Vertex3;:G;FFC;:H2:7,V", | |
| // "Vertex4;:G;FFC;:H2:7,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementBSplineFace) | |
| { | |
| // Arrange | |
| TColgp_Array1OfPnt array1(1, 3); // sizing array | |
| array1.SetValue(1, gp_Pnt(-4, 0, 2)); | |
| array1.SetValue(2, gp_Pnt(-7, 2, 2)); | |
| array1.SetValue(3, gp_Pnt(-10, 0, 2)); | |
| Handle(Geom_BSplineCurve) curve1 = GeomAPI_PointsToBSpline(array1).Curve(); | |
| TColgp_Array1OfPnt array2(1, 3); // sizing array | |
| array2.SetValue(1, gp_Pnt(-4, 0, 2)); | |
| array2.SetValue(2, gp_Pnt(-7, -2, 2)); | |
| array2.SetValue(3, gp_Pnt(-9, 0, 2)); | |
| Handle(Geom_BSplineCurve) curve2 = GeomAPI_PointsToBSpline(array2).Curve(); | |
| auto edge = BRepBuilderAPI_MakeEdge(curve1); | |
| auto edge1 = BRepBuilderAPI_MakeEdge(curve2); | |
| TopoShape topoShape {1L}; | |
| TopoShape topoShape2 {edge, 2L}; | |
| TopoShape topoShape3 {edge1, 3L}; | |
| // Act | |
| TopoShape& result = topoShape.makeElementBSplineFace({topoShape2, topoShape3}); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE( | |
| PartTestHelpers::boxesMatch( | |
| bb, | |
| Base::BoundBox3d(-10, -2.0597998470594132, 2, -4, 2.1254369627132599, 2) | |
| ) | |
| ); | |
| EXPECT_NEAR(getArea(result.getShape()), 14.677052, 1e-6); | |
| // Assert elementMap is correct | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge1;BSF", | |
| "Edge1;D1", | |
| "Edge1;D2", | |
| "Edge1;D3", | |
| "Vertex1", | |
| "Vertex1;D1", | |
| "Vertex2", | |
| "Vertex2;D1", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, replaceElementShape) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| // We can't use a compound in replaceElementShape, so we'll make a replacement wire and a shell | |
| auto wire {BRepBuilderAPI_MakeWire( | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)), | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(1.0, 1.0, 0.0)), | |
| BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 1.0, 0.0), gp_Pnt(0.0, 0.0, 0.0)) | |
| ) | |
| .Wire()}; | |
| auto shell = cube1.makeElementShell(); | |
| auto wires = shell.getSubTopoShapes(TopAbs_WIRE); | |
| // Act | |
| TopoShape& result = shell.replaceElementShape(shell, {{wires[0], wire}}); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 1.0, 1.0, 1.0))); | |
| EXPECT_FLOAT_EQ(getArea(result.getShape()), 5); | |
| EXPECT_EQ(result.countSubElements("Wire"), 6); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:H1,E", "Edge1;:H2,E", "Edge1;:H3,E", "Edge2;:H1,E", "Edge2;:H2,E", | |
| "Edge2;:H3,E", "Edge3;:H1,E", "Edge3;:H2,E", "Edge3;:H3,E", "Edge4;:H1,E", | |
| "Edge4;:H2,E", "Edge4;:H3,E", "Face1;:H2,F", "Face1;:H3,F", "Face1;:H4,F", | |
| "Face1;:H5,F", "Face1;:H6,F", "Vertex1;:H1,V", "Vertex1;:H2,V", "Vertex2;:H1,V", | |
| "Vertex2;:H2,V", "Vertex3;:H1,V", "Vertex3;:H2,V", "Vertex4;:H1,V", "Vertex4;:H2,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, removeElementShape) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoTopoShapeCubes(); | |
| auto faces = cube1.getSubTopoShapes(TopAbs_FACE); | |
| // Act | |
| TopoShape result = cube1.removeElementShape({faces[0]}); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 1.0, 1.0, 1.0))); | |
| EXPECT_FLOAT_EQ(getArea(result.getShape()), 5); | |
| EXPECT_EQ(result.countSubShapes("Compound"), 1); | |
| EXPECT_EQ(result.countSubShapes("Face"), 5); | |
| // Assert that we're creating a correct element map | |
| EXPECT_TRUE(result.getMappedChildElements().empty()); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:H1,E;:H7,E", "Edge1;:H2,E;:H7,E", "Edge1;:H3,E;:H7,E", | |
| "Edge2;:H1,E;:H7,E", "Edge2;:H2,E;:H7,E", "Edge2;:H3,E;:H7,E", | |
| "Edge3;:H1,E;:H7,E", "Edge3;:H2,E;:H7,E", "Edge3;:H3,E;:H7,E", | |
| "Edge4;:H1,E;:H7,E", "Edge4;:H2,E;:H7,E", "Edge4;:H3,E;:H7,E", | |
| "Face1;:H2,F;:H7,F", "Face1;:H3,F;:H7,F", "Face1;:H4,F;:H7,F", | |
| "Face1;:H5,F;:H7,F", "Face1;:H6,F;:H7,F", "Vertex1;:H1,V;:H7,V", | |
| "Vertex1;:H2,V;:H7,V", "Vertex2;:H1,V;:H7,V", "Vertex2;:H2,V;:H7,V", | |
| "Vertex3;:H1,V;:H7,V", "Vertex3;:H2,V;:H7,V", "Vertex4;:H1,V;:H7,V", | |
| "Vertex4;:H2,V;:H7,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementEvolve) | |
| { | |
| BRepBuilderAPI_MakePolygon polygon( | |
| gp_Pnt(0.0, 0.0, 0.0), | |
| gp_Pnt(200.0, 0.0, 0.0), | |
| gp_Pnt(200.0, 200.0, 0.0), | |
| gp_Pnt(0.0, 200.0, 0.0) | |
| ); | |
| polygon.Close(); | |
| TopoShape spine {polygon.Wire(), 1L}; | |
| // Alternative: | |
| // auto face {BRepBuilderAPI_MakeFace(polygon.Wire()).Face()}; | |
| // TopoShape spine {face, 11L}; | |
| BRepBuilderAPI_MakePolygon polygon2(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(-60.0, -60.0, -200.0)); | |
| TopoShape profile {polygon2.Wire(), 2L}; | |
| // Alternative: | |
| // TopoShape profile { | |
| // BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(-60.0, -60.0, -200.0)).Edge(), | |
| // 10L}; | |
| // Act | |
| TopoShape topoShape {3L}; | |
| auto& result = topoShape.makeElementEvolve(spine, profile); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE( | |
| PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-60.0, -60.0, -200.0, 260.0, 260.0, 0)) | |
| ); | |
| EXPECT_FLOAT_EQ(getVolume(result.getShape()), 8910324); | |
| // Assert elementMap is correct | |
| EXPECT_EQ(topoShape.getElementMap().size(), 0); | |
| // Neither the Spine nor the Profile have an elementMap, because they are simple wires or faces. | |
| // The resulting Evolved also does not populate the elementMap, but that might be a bug in | |
| // underutilized code. | |
| EXPECT_EQ(spine.getElementMap().size(), 0); | |
| } | |
| TEST_F(TopoShapeExpansionTest, traceElement) | |
| { | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| TopoShape& result = topoShape1.makeElementCut( | |
| {topoShape1, topoShape2} | |
| ); //, const char* op = nullptr, double tol = 0); | |
| std::string name {"Face2;:M;CUT;:H1:7,F"}; | |
| // auto faces = result.getSubTopoShapes(TopAbs_FACE); | |
| Data::MappedName mappedName(name); | |
| // Arrange | |
| Data::TraceCallback cb = | |
| [name](const Data::MappedName& elementname, int offset, long encodedTag, long tag) { | |
| boost::ignore_unused(offset); | |
| boost::ignore_unused(tag); | |
| // TODO: This is likely a flawed way to address testing a callback. | |
| // Also, it isn't clear exactly what the correct results are, although as soon as | |
| // we start addressing History, we will quickly discover that, and likely the right | |
| // things to test. | |
| if (encodedTag == 1) { | |
| EXPECT_STREQ(elementname.toString().c_str(), name.c_str()); | |
| } | |
| else { | |
| EXPECT_STREQ(elementname.toString().c_str(), name.substr(0, 5).c_str()); | |
| } | |
| return false; | |
| }; | |
| // Act | |
| result.traceElement(mappedName, cb); | |
| // Assert we have the element map we think we do. | |
| EXPECT_TRUE(allElementsMatch( | |
| result, | |
| { | |
| "Edge1", | |
| "Edge10;:G(Edge2;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge10;:M;CUT;:H1:7,E", | |
| "Edge11", | |
| "Edge11;:M;CUT;:H2:7,E", | |
| "Edge12", | |
| "Edge12;:M;CUT;:H2:7,E", | |
| "Edge2", | |
| "Edge2;:M;CUT;:H2:7,E", | |
| "Edge3", | |
| "Edge3;:M;CUT;:H2:7,E", | |
| "Edge4", | |
| "Edge4;:M;CUT;:H2:7,E", | |
| "Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge6;:M;CUT;:H1:7,E", | |
| "Edge7", | |
| "Edge8;:G(Edge11;K-1;:H2:4,E);CUT;:H1:1b,V", | |
| "Edge8;:M;CUT;:H1:7,E", | |
| "Edge9;:G(Edge4;K-1;:H2:4,E);CUT;:H1:1a,V", | |
| "Edge9;:M;CUT;:H1:7,E", | |
| "Face1", | |
| "Face1;:M;CUT;:H2:7,F", | |
| "Face2;:G(Face4;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face2;:M;CUT;:H1:7,F", | |
| "Face3;:G(Face1;K-1;:H2:4,F);CUT;:H1:1a,E", | |
| "Face3;:M;CUT;:H1:7,F", | |
| "Face4", | |
| "Face4;:M;CUT;:H2:7,F", | |
| "Face5;:M;CUT;:H1:7,F", | |
| "Face6;:M;CUT;:H1:7,F", | |
| "Vertex1", | |
| "Vertex2", | |
| "Vertex3", | |
| "Vertex3;:M;CUT;:H2:7,V", | |
| "Vertex4", | |
| "Vertex4;:M;CUT;:H2:7,V", | |
| "Vertex7", | |
| "Vertex8", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementOffset) | |
| { | |
| // Arrange | |
| // Arrange | |
| auto [cube1, cube2] = CreateTwoCubes(); | |
| auto tr {gp_Trsf()}; | |
| tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0))); | |
| cube2.Move(TopLoc_Location(tr)); | |
| TopoShape topoShape1 {cube1, 1L}; | |
| TopoShape topoShape2 {cube2, 2L}; | |
| // Act | |
| // TopoShape topoShape3 {6L}; | |
| TopoShape result {3L}; | |
| // topoShape1.makeElementFuse({topoShape2,topoShape2}); // op, tolerance | |
| result.makeElementOffset(topoShape1, 0.25, 1e-07); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE( | |
| PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.25, -0.25, -0.25, 1.25, 1.25, 1.25)) | |
| ); | |
| EXPECT_NEAR(getVolume(result.getShape()), 3.1544986, 1e-6); | |
| // Assert elementMap is correct | |
| // EXPECT_EQ(elements.size(), 98); | |
| // EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| // EXPECT_EQ( | |
| // elements[IndexedName("Face", 1)], | |
| // MappedName("Face2;:G;OFS;:H1:7,F")); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge10;:G;OFS;:H1:7,F", | |
| "Edge10;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge10;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge10;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge10;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge11;:G;OFS;:H1:7,F", | |
| "Edge11;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge11;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge11;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge11;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge12;:G;OFS;:H1:7,F", | |
| "Edge12;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge12;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge12;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge12;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge1;:G;OFS;:H1:7,F", | |
| "Edge1;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge1;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge1;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge1;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge1;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge1;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge1;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge1;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge2;:G;OFS;:H1:7,F", | |
| "Edge2;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge2;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge2;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge2;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge2;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge2;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge2;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge3;:G;OFS;:H1:7,F", | |
| "Edge3;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge3;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge3;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge3;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge3;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge3;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge3;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge4;:G;OFS;:H1:7,F", | |
| "Edge4;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge4;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge4;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge4;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge4;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge4;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge5;:G;OFS;:H1:7,F", | |
| "Edge5;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge5;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge5;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge5;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge5;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge5;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge5;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge5;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge6;:G;OFS;:H1:7,F", | |
| "Edge6;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge6;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge6;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge6;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge6;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge6;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge6;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge7;:G;OFS;:H1:7,F", | |
| "Edge7;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge7;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge7;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge7;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge7;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge7;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge7;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge8;:G;OFS;:H1:7,F", | |
| "Edge8;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge8;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U2;OFS;:H1:8,V", | |
| "Edge8;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E;:U;OFS;:H1:7,V", | |
| "Edge8;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge8;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge8;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Edge9;:G;OFS;:H1:7,F", | |
| "Edge9;:G;OFS;:H1:7,F;:U2;OFS;:H1:8,E", | |
| "Edge9;:G;OFS;:H1:7,F;:U3;OFS;:H1:8,E", | |
| "Edge9;:G;OFS;:H1:7,F;:U4;OFS;:H1:8,E", | |
| "Edge9;:G;OFS;:H1:7,F;:U;OFS;:H1:7,E", | |
| "Face1;:G;OFS;:H1:7,F", | |
| "Face2;:G;OFS;:H1:7,F", | |
| "Face3;:G;OFS;:H1:7,F", | |
| "Face4;:G;OFS;:H1:7,F", | |
| "Face5;:G;OFS;:H1:7,F", | |
| "Face6;:G;OFS;:H1:7,F", | |
| "Vertex1;:G;OFS;:H1:7,F", | |
| "Vertex2;:G;OFS;:H1:7,F", | |
| "Vertex3;:G;OFS;:H1:7,F", | |
| "Vertex4;:G;OFS;:H1:7,F", | |
| "Vertex5;:G;OFS;:H1:7,F", | |
| "Vertex6;:G;OFS;:H1:7,F", | |
| "Vertex7;:G;OFS;:H1:7,F", | |
| "Vertex8;:G;OFS;:H1:7,F", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementOffsetFace) | |
| { | |
| // Arrange | |
| const float Len = 3, Wid = 2, Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| // Act | |
| TopoShape result {face1, 1L}; | |
| result.makeElementOffsetFace(result, 0.25, 0); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.25, -0.25, 0.0, 3.25, 2.25, 0.0))); | |
| // Assert elementMap is correct | |
| // EXPECT_EQ(elements.size(), 19); | |
| // EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1); | |
| // EXPECT_EQ( | |
| // elements[IndexedName("Face", 1)], | |
| // MappedName("Edge1;:G;OFF;:H1:7,E;FAC;:H1:4,F")); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:G;OFF;:H1:7,E", | |
| "Edge1;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V", | |
| "Edge1;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V", | |
| "Edge1;:G;OFF;:H1:7,E;FAC;:H1:4,F", | |
| "Edge2;:G;OFF;:H1:7,E", | |
| "Edge2;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V", | |
| "Edge2;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V", | |
| "Edge3;:G;OFF;:H1:7,E", | |
| "Edge3;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V", | |
| "Edge3;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V", | |
| "Edge4;:G;OFF;:H1:7,E", | |
| "Edge4;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V", | |
| "Edge4;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V", | |
| "Edge5;:H1,E", | |
| "Vertex1;:G;OFF;:H1:7,E", | |
| "Vertex2;:G;OFF;:H1:7,E", | |
| "Vertex3;:G;OFF;:H1:7,E", | |
| "Vertex4;:G;OFF;:H1:7,E", | |
| "Vertex5;:H1,V", | |
| } | |
| )); | |
| } | |
| TEST_F(TopoShapeExpansionTest, makeElementOffset2D) | |
| { | |
| // Arrange | |
| const float Len = 3, Wid = 2, Rad = 1; | |
| auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad); | |
| // Act | |
| TopoShape result {wire1, 1L}; | |
| result.makeElementOffset2D(result, 0.25); | |
| auto elements = elementMap(result); | |
| Base::BoundBox3d bb = result.getBoundBox(); | |
| // Assert shape is correct | |
| EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.25, -0.25, 0.0, 3.25, 2.25, 0.0))); | |
| // Assert elementMap is correct | |
| // EXPECT_EQ(elements.size(), 10); | |
| // EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1); | |
| // EXPECT_EQ( | |
| // elements[IndexedName("Edge", 1)], | |
| // MappedName("Edge1;:G;OFF;:H1:7,E;OFF;:H1:4,E")); | |
| EXPECT_TRUE(elementsMatch( | |
| result, | |
| { | |
| "Edge1;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V;OFF;:H1:4,V", | |
| "Edge1;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V;OFF;:H1:4,V", | |
| "Edge1;:G;OFF;:H1:7,E;OFF;:H1:4,E", | |
| "Edge2;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V;OFF;:H1:4,V", | |
| "Edge2;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V;OFF;:H1:4,V", | |
| "Edge2;:G;OFF;:H1:7,E;OFF;:H1:4,E", | |
| "Vertex1;:G;OFF;:H1:7,E;:U2;OFF;:H1:8,V;OFF;:H1:4,V", | |
| "Vertex1;:G;OFF;:H1:7,E;OFF;:H1:4,E", | |
| "Vertex3;:G;OFF;:H1:7,E;:U;OFF;:H1:7,V;OFF;:H1:4,V", | |
| "Vertex3;:G;OFF;:H1:7,E;OFF;:H1:4,E", | |
| } | |
| )); | |
| } | |
| // NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers) | |