From 68fd2934cfcdb7b31d235d562412a5c04f55682e Mon Sep 17 00:00:00 2001 From: bgbsww Date: Fri, 23 Feb 2024 17:36:11 -0500 Subject: [PATCH] Testing for makeElementEvolve --- src/Mod/Part/App/TopoShape.h | 39 ++++++-- src/Mod/Part/App/TopoShapeExpansion.cpp | 97 +++++++++++-------- tests/src/Mod/Part/App/PartFeatures.cpp | 2 +- tests/src/Mod/Part/App/PartTestHelpers.cpp | 6 +- tests/src/Mod/Part/App/TopoShapeExpansion.cpp | 35 +++++++ 5 files changed, 128 insertions(+), 51 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 655c449372..9d4c5f70d7 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -227,7 +227,8 @@ enum class Copy }; /// Filling style when making a BSpline face -enum FillingStyle { +enum FillingStyle +{ /// The style with the flattest patches stretch, /// A rounded style of patch with less depth than those of Curved @@ -236,6 +237,18 @@ enum FillingStyle { curved, }; +enum class CoordinateSystem +{ + relativeToSpine, + global +}; + +enum class Spine +{ + notOn, + on +}; + /** The representation for a CAD Shape */ // NOLINTNEXTLINE cppcoreguidelines-special-member-functions @@ -1262,6 +1275,8 @@ public: * An evolved shape is built from a planar spine (face or wire) and a * profile (wire). The evolved shape is the unlooped sweep (pipe) of the * profile along the spine. Self-intersections are removed. + * Note that the underlying OCCT method is very finicky about parameters and + * make throw "Unimplemented" exceptions for various types. * * @param spine: the spine shape, must be planar face or wire * @param profile: the profile wire, must be planar, or a line segment @@ -1277,8 +1292,14 @@ public: * a self reference so that multiple operations can be carried out * for the same shape in the same line of code. */ - TopoShape &makEEvolve(const TopoShape &spine, const TopoShape &profile, JoinType join=JoinType::Arc, - bool axeProf=true, bool solid=false, bool profOnSpine=false, double tol=0.0, const char *op=nullptr); + TopoShape& makeElementEvolve(const TopoShape& spine, + const TopoShape& profile, + JoinType join = JoinType::arc, + CoordinateSystem = CoordinateSystem::global, + MakeSolid solid = MakeSolid::noSolid, + Spine profOnSpine = Spine::notOn, + double tol = 0.0, + const char* op = nullptr); /** Make an evolved shape using this shape as spine * @@ -1296,10 +1317,16 @@ public: * * @return Return the new shape. The TopoShape itself is not modified. */ - TopoShape makEEvolve(const TopoShape &profile, JoinType join=JoinType::Arc, - bool axeProf=true, bool solid=false, bool profOnSpine=false, double tol=0.0, const char *op=nullptr) + TopoShape makeElementEvolve(const TopoShape& profile, + JoinType join = JoinType::arc, + CoordinateSystem axeProf = CoordinateSystem::global, + MakeSolid solid = MakeSolid::noSolid, + Spine profOnSpine = Spine::notOn, + double tol = 0.0, + const char* op = nullptr) { - return TopoShape(0,Hasher).makEEvolve(*this, profile, join, axeProf, solid, profOnSpine, tol, op); + return TopoShape(0, Hasher) + .makeElementEvolve(*this, profile, join, axeProf, solid, profOnSpine, tol, op); } /** Make an loft that is a shell or solid passing through a set of sections in a given sequence diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 5c7ebff853..9f7661d59c 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -55,13 +56,14 @@ #include #include #include +#include #include #include -#include #include #include #include #include +#include #include #include #include @@ -1857,26 +1859,28 @@ TopoShape TopoShape::getSubTopoShape(TopAbs_ShapeEnum type, int idx, bool silent return shapeMap.getTopoShape(*this, idx); } -TopoShape &TopoShape::makEEvolve(const TopoShape &spine, - const TopoShape &profile, - JoinType join, - bool axeProf, - bool solid, - bool profOnSpine, - double tol, - const char *op) +TopoShape& TopoShape::makeElementEvolve(const TopoShape& spine, + const TopoShape& profile, + JoinType join, + CoordinateSystem axeProf, + MakeSolid solid, + Spine profOnSpine, + double tol, + const char* op) { - if (!op) + if (!op) { op = Part::OpCodes::Evolve; - if (tol == 0.0) + } + if (tol == 0.0) { tol = 1e-6; + } GeomAbs_JoinType joinType; switch (join) { - case JoinType::Arc: + case JoinType::tangent: joinType = GeomAbs_Tangent; break; - case JoinType::Intersection: + case JoinType::intersection: joinType = GeomAbs_Intersection; break; default: @@ -1885,45 +1889,56 @@ TopoShape &TopoShape::makEEvolve(const TopoShape &spine, } TopoDS_Shape spineShape; - if (spine.countSubShapes(TopAbs_FACE) > 0) + if (spine.countSubShapes(TopAbs_FACE) > 0) { spineShape = spine.getSubShape(TopAbs_FACE, 1); - else if (spine.countSubShapes(TopAbs_WIRE) > 0) + } + else if (spine.countSubShapes(TopAbs_WIRE) > 0) { spineShape = spine.getSubShape(TopAbs_WIRE, 1); - else if (spine.countSubShapes(TopAbs_EDGE) > 0) - spineShape = BRepBuilderAPI_MakeWire(TopoDS::Edge(spine.getSubShape(TopAbs_EDGE, 1))).Wire(); - if (spineShape.IsNull() || !BRepBuilderAPI_FindPlane(spineShape).Found()) - FC_THROWM(Base::CADKernelError, "Expect the the spine to be a planar wire or face"); + } + else if (spine.countSubShapes(TopAbs_EDGE) > 0) { + spineShape = + BRepBuilderAPI_MakeWire(TopoDS::Edge(spine.getSubShape(TopAbs_EDGE, 1))).Wire(); + } + if (spineShape.IsNull() || !BRepBuilderAPI_FindPlane(spineShape).Found()) { + FC_THROWM(Base::CADKernelError, "Expect the spine to be a planar wire or face"); + } TopoDS_Shape profileShape; - if (profile.countSubShapes(TopAbs_FACE) > 0 || profile.countSubShapes(TopAbs_WIRE) > 0) + if (profile.countSubShapes(TopAbs_FACE) > 0 || profile.countSubShapes(TopAbs_WIRE) > 0) { profileShape = profile.getSubShape(TopAbs_WIRE, 1); - else if (profile.countSubShapes(TopAbs_EDGE) > 0) - profileShape = BRepBuilderAPI_MakeWire(TopoDS::Edge(profile.getSubShape(TopAbs_EDGE, 1))).Wire(); + } + else if (profile.countSubShapes(TopAbs_EDGE) > 0) { + profileShape = + BRepBuilderAPI_MakeWire(TopoDS::Edge(profile.getSubShape(TopAbs_EDGE, 1))).Wire(); + } if (profileShape.IsNull() || !BRepBuilderAPI_FindPlane(profileShape).Found()) { - if (profileShape.IsNull() - || profile.countSubShapes(TopAbs_EDGE) > 1 - || !profile.getSubTopoShape(TopAbs_EDGE, 1).isLinearEdge()) - { - FC_THROWM(Base::CADKernelError, "Expect the the profile to be a planar wire or face or a line"); + if (profileShape.IsNull() || profile.countSubShapes(TopAbs_EDGE) > 1 + || !profile.getSubTopoShape(TopAbs_EDGE, 1).isLinearEdge()) { + FC_THROWM(Base::CADKernelError, + "Expect the the profile to be a planar wire or a face or a line"); } } if (spineShape.ShapeType() == TopAbs_FACE) { - BRepOffsetAPI_MakeEvolved maker(TopoDS::Face(spineShape), - TopoDS::Wire(profileShape), joinType, - axeProf ? Standard_True : Standard_False, - solid ? Standard_True : Standard_False, - profOnSpine ? Standard_True : Standard_False, - tol); - return makEShape(maker, {spine, profile}, op); + BRepOffsetAPI_MakeEvolved maker( + TopoDS::Face(spineShape), + TopoDS::Wire(profileShape), + joinType, + axeProf == CoordinateSystem::global ? Standard_True : Standard_False, + solid == MakeSolid::makeSolid ? Standard_True : Standard_False, + profOnSpine == Spine::on ? Standard_True : Standard_False, + tol); + return makeElementShape(maker, {spine, profile}, op); } else { - BRepOffsetAPI_MakeEvolved maker(TopoDS::Wire(spineShape), - TopoDS::Wire(profileShape), joinType, - axeProf ? Standard_True : Standard_False, - solid ? Standard_True : Standard_False, - profOnSpine ? Standard_True : Standard_False, - tol); - return makEShape(maker, {spine, profile}, op); + BRepOffsetAPI_MakeEvolved maker( + TopoDS::Wire(spineShape), + TopoDS::Wire(profileShape), + joinType, + axeProf == CoordinateSystem::global ? Standard_True : Standard_False, + solid == MakeSolid::makeSolid ? Standard_True : Standard_False, + profOnSpine == Spine::on ? Standard_True : Standard_False, + tol); + return makeElementShape(maker, {spine, profile}, op); } } diff --git a/tests/src/Mod/Part/App/PartFeatures.cpp b/tests/src/Mod/Part/App/PartFeatures.cpp index 059b8865ad..2ec5c96bed 100644 --- a/tests/src/Mod/Part/App/PartFeatures.cpp +++ b/tests/src/Mod/Part/App/PartFeatures.cpp @@ -201,7 +201,7 @@ TEST_F(PartFeaturesTest, testReverse) EXPECT_EQ(originalFaces[3].getShape().Orientation(), TopAbs_FORWARD); EXPECT_EQ(originalFaces[4].getShape().Orientation(), TopAbs_REVERSED); EXPECT_EQ(originalFaces[5].getShape().Orientation(), TopAbs_FORWARD); - EXPECT_DOUBLE_EQ(volume, -6.0); + EXPECT_DOUBLE_EQ(volume, 6.0); EXPECT_DOUBLE_EQ(area, 22.0); EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 1, 2, 3))); // Assert element map is correct diff --git a/tests/src/Mod/Part/App/PartTestHelpers.cpp b/tests/src/Mod/Part/App/PartTestHelpers.cpp index 1b7e665b0f..5e0bc48f82 100644 --- a/tests/src/Mod/Part/App/PartTestHelpers.cpp +++ b/tests/src/Mod/Part/App/PartTestHelpers.cpp @@ -12,21 +12,21 @@ double getVolume(const TopoDS_Shape& shape) { GProp_GProps prop; BRepGProp::VolumeProperties(shape, prop); - return prop.Mass(); + return abs(prop.Mass()); } double getArea(const TopoDS_Shape& shape) { GProp_GProps prop; BRepGProp::SurfaceProperties(shape, prop); - return prop.Mass(); + return abs(prop.Mass()); } double getLength(const TopoDS_Shape& shape) { GProp_GProps prop; BRepGProp::LinearProperties(shape, prop); - return prop.Mass(); + return abs(prop.Mass()); } diff --git a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp index 6ffdd86d69..8e1ea06a21 100644 --- a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -12,9 +12,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -2346,4 +2348,37 @@ TEST_F(TopoShapeExpansionTest, removeElementShape) })); } +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); +} + // NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)