From 1fa89ea4c1395410bce1288513b4a7557836eb45 Mon Sep 17 00:00:00 2001 From: bgbsww Date: Fri, 23 Feb 2024 14:51:27 -0500 Subject: [PATCH] Toponaming/Part: Cleaning and tests for makeElementRevolve, makeElementPrism, makeElementPrismUntil --- src/Mod/Part/App/TopoShape.h | 54 +-- src/Mod/Part/App/TopoShapeExpansion.cpp | 391 ++++++++++-------- tests/src/Mod/Part/App/TopoShapeExpansion.cpp | 129 ++++++ 3 files changed, 368 insertions(+), 206 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 26f1245e0c..3c9a54202a 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -957,14 +957,16 @@ public: * a self reference so that multiple operations can be carried out * for the same shape in the same line of code. */ - TopoShape &makeElementPrismUntil(const TopoShape &base, - const TopoShape& profile, - const TopoShape& supportFace, - const TopoShape& upToFace, - const gp_Dir& direction, - PrismMode mode, - Standard_Boolean checkLimits = Standard_True, - const char *op=nullptr); + // TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be + // unused. It is potentially useful if debugged. +// TopoShape &makeElementPrismUntil(const TopoShape &base, +// const TopoShape& profile, +// const TopoShape& supportFace, +// const TopoShape& upToFace, +// const gp_Dir& direction, +// PrismMode mode, +// Standard_Boolean checkLimits = Standard_True, +// const char *op=nullptr); /** Make a prism based on this shape that is either depression or protrusion of a profile shape up to a given face * @@ -983,23 +985,25 @@ public: * * @return Return the generated new shape. The TopoShape itself is not modified. */ - TopoShape makeElementPrismUntil(const TopoShape& profile, - const TopoShape& supportFace, - const TopoShape& upToFace, - const gp_Dir& direction, - PrismMode mode, - Standard_Boolean checkLimits = Standard_True, - const char *op=nullptr) const - { - return TopoShape(0,Hasher).makeElementPrismUntil(*this, - profile, - supportFace, - upToFace, - direction, - mode, - checkLimits, - op); - } + // TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be + // unused. It is potentially useful if debugged. +// TopoShape makeElementPrismUntil(const TopoShape& profile, +// const TopoShape& supportFace, +// const TopoShape& upToFace, +// const gp_Dir& direction, +// PrismMode mode, +// Standard_Boolean checkLimits = Standard_True, +// const char *op=nullptr) const +// { +// return TopoShape(0,Hasher).makeElementPrismUntil(*this, +// profile, +// supportFace, +// upToFace, +// direction, +// mode, +// checkLimits, +// op); +// } /* Make a shell or solid by sweeping profile wire along a spine diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index ff52f8edbc..7b5171dd61 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -3097,198 +3097,227 @@ TopoShape& TopoShape::makeElementLoft(const std::vector& shapes, op); } -TopoShape &TopoShape::makeElementPrism(const TopoShape &base, const gp_Vec& vec, const char *op) { - if(!op) op = Part::OpCodes::Extrude; - if(base.isNull()) - FC_THROWM(NullShapeException, "Null shape"); - BRepPrimAPI_MakePrism mkPrism(base.getShape(), vec); - return makeElementShape(mkPrism,base,op); -} - -TopoShape &TopoShape::makeElementPrismUntil(const TopoShape &_base, - const TopoShape& profile, - const TopoShape& supportFace, - const TopoShape& __uptoface, - const gp_Dir& direction, - PrismMode Mode, - Standard_Boolean checkLimits, - const char *op) +TopoShape& TopoShape::makeElementPrism(const TopoShape& base, const gp_Vec& vec, const char* op) { - if(!op) op = Part::OpCodes::Prism; - - BRepFeat_MakePrism PrismMaker; - - TopoShape _uptoface(__uptoface); - if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE - && !BRep_Tool::NaturalRestriction(TopoDS::Face(_uptoface.getShape()))) { - // When using the face with BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until) - // then the algorithm expects that the 'NaturalRestriction' flag is set in order - // to work as expected. - BRep_Builder builder; - _uptoface = _uptoface.makeElementCopy(); - builder.NaturalRestriction(TopoDS::Face(_uptoface.getShape()), Standard_True); + if (!op) { + op = Part::OpCodes::Extrude; } - - TopoShape uptoface(_uptoface); - TopoShape base(_base); - if (base.isNull()) { - Mode = PrismMode::None; - base = profile; + FC_THROWM(NullShapeException, "Null shape"); } - - // Check whether the face has limits or not. Unlimited faces have no wire - // Note: Datum planes are always unlimited - if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) { - TopoDS_Face face = TopoDS::Face(uptoface.getShape()); - bool remove_limits = false; - // Remove the limits of the upToFace so that the extrusion works even if profile is larger - // than the upToFace - for (auto &sketchface : profile.getSubTopoShapes(TopAbs_FACE)) { - // Get outermost wire of sketch face - TopoShape outerWire = sketchface.splitWires(); - BRepProj_Projection proj(TopoDS::Wire(outerWire.getShape()), face, direction); - if (!proj.More() || !proj.Current().Closed()) { - remove_limits = true; - break; - } - } - - // It must also be checked that all projected inner wires of the upToFace - // lie outside the sketch shape. If this is not the case then the sketch - // shape is not completely covered by the upToFace. See #0003141 - if (!remove_limits) { - std::vector wires; - uptoface.splitWires(&wires); - for (auto & w : wires) { - BRepProj_Projection proj(TopoDS::Wire(w.getShape()), profile.getShape(), -direction); - if (proj.More()) { - remove_limits = true; - break; - } - } - } - - if (remove_limits) { - // Note: Using an unlimited face every time gives unnecessary failures for concave faces - TopLoc_Location loc = face.Location(); - BRepAdaptor_Surface adapt(face, Standard_False); - // use the placement of the adapter, not of the upToFace - loc = TopLoc_Location(adapt.Trsf()); - BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() -#if OCC_VERSION_HEX >= 0x060502 - , Precision::Confusion() -#endif - ); - if (!mkFace.IsDone()) - remove_limits = false; - else - uptoface.setShape(located(mkFace.Shape(),loc), false); - } - } - - TopoShape uptofaceCopy = uptoface; - bool checkBase = false; - auto retry = [&]() { - if (!uptoface.isSame(_uptoface)) { - // retry using the original up to face in case unnecessary failure - // due to removing the limits - uptoface = _uptoface; - return true; - } - if ((!_base.isNull() && base.isSame(_base)) - || (_base.isNull() && base.isSame(profile))) { - // It is unclear under exactly what condition extrude up to face - // can fail. Either the support face or the up to face must be part - // of the base, or maybe some thing else. - // - // To deal with it, we retry again by disregard the supplied base, - // and use up to face to extrude our own base. Later on, use the - // supplied base (i.e. _base) to calculate the final shape if the - // mode is FuseWithBase or CutWithBase. - checkBase = true; - uptoface = uptofaceCopy; - base.makeElementPrism(_uptoface, direction); - return true; - } - return false; - }; - - std::vector srcShapes; - TopoShape result; - for (;;) { - try { - result = base; - - // We do not rely on BRepFeat_MakePrism to perform fuse or cut for - // us because of its poor support of shape history. - auto mode = PrismMode::None; - - for (auto &face : profile.getSubTopoShapes( - profile.hasSubShape(TopAbs_FACE)?TopAbs_FACE:TopAbs_WIRE)) { - srcShapes.clear(); - if (!profile.isNull() && !result.findShape(profile.getShape())) - srcShapes.push_back(profile); - if (!supportFace.isNull() && !result.findShape(supportFace.getShape())) - srcShapes.push_back(supportFace); - - // DO NOT include uptoface for element mapping. Because OCCT - // BRepFeat_MakePrism will report all top extruded face being - // modified by the uptoface. If there are more than one face in - // the profile, this will cause uncessary duplicated element - // mapped name. And will also disrupte element history tracing - // back to the profile sketch. - // - // if (!uptoface.isNull() && !this->findShape(uptoface.getShape())) - // srcShapes.push_back(uptoface); - - srcShapes.push_back(result); - - PrismMaker.Init(result.getShape(), face.getShape(), - TopoDS::Face(supportFace.getShape()), direction, mode, Standard_False); - mode = PrismMode::FuseWithBase; - - PrismMaker.Perform(uptoface.getShape()); - - if (!PrismMaker.IsDone() || PrismMaker.Shape().IsNull()) - FC_THROWM(Base::CADKernelError,"BRepFeat_MakePrism: extrusion failed"); - - result.makeElementShape(PrismMaker, srcShapes, uptoface, op); - } - break; - } catch (Base::Exception &) { - if (!retry()) throw; - } catch (Standard_Failure &) { - if (!retry()) throw; - } - } - - if (!_base.isNull() && Mode != PrismMode::None) { - if (Mode == PrismMode::FuseWithBase) - result.makeElementFuse({_base, result}); - else - result.makeElementCut({_base, result}); - } - - *this = result; - return *this; + BRepPrimAPI_MakePrism mkPrism(base.getShape(), vec); + return makeElementShape(mkPrism, base, op); } -TopoShape &TopoShape::makeElementRevolve(const TopoShape &_base, const gp_Ax1& axis, - double d, const char *face_maker, const char *op) +// TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be +// unused. It is potentially useful if debugged. +//TopoShape& TopoShape::makeElementPrismUntil(const TopoShape& _base, +// const TopoShape& profile, +// const TopoShape& supportFace, +// const TopoShape& __uptoface, +// const gp_Dir& direction, +// PrismMode Mode, +// Standard_Boolean checkLimits, +// const char* op) +//{ +// if (!op) { +// op = Part::OpCodes::Prism; +// } +// +// BRepFeat_MakePrism PrismMaker; +// +// TopoShape _uptoface(__uptoface); +// if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE +// && !BRep_Tool::NaturalRestriction(TopoDS::Face(_uptoface.getShape()))) { +// // When using the face with BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until) +// // then the algorithm expects that the 'NaturalRestriction' flag is set in order +// // to work as expected. +// BRep_Builder builder; +// _uptoface = _uptoface.makeElementCopy(); +// builder.NaturalRestriction(TopoDS::Face(_uptoface.getShape()), Standard_True); +// } +// +// TopoShape uptoface(_uptoface); +// TopoShape base(_base); +// +// if (base.isNull()) { +// Mode = PrismMode::None; +// base = profile; +// } +// +// // Check whether the face has limits or not. Unlimited faces have no wire +// // Note: Datum planes are always unlimited +// if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) { +// TopoDS_Face face = TopoDS::Face(uptoface.getShape()); +// bool remove_limits = false; +// // Remove the limits of the upToFace so that the extrusion works even if profile is larger +// // than the upToFace +// for (auto& sketchface : profile.getSubTopoShapes(TopAbs_FACE)) { +// // Get outermost wire of sketch face +// TopoShape outerWire = sketchface.splitWires(); +// BRepProj_Projection proj(TopoDS::Wire(outerWire.getShape()), face, direction); +// if (!proj.More() || !proj.Current().Closed()) { +// remove_limits = true; +// break; +// } +// } +// +// // It must also be checked that all projected inner wires of the upToFace +// // lie outside the sketch shape. If this is not the case then the sketch +// // shape is not completely covered by the upToFace. See #0003141 +// if (!remove_limits) { +// std::vector wires; +// uptoface.splitWires(&wires); +// for (auto& w : wires) { +// BRepProj_Projection proj(TopoDS::Wire(w.getShape()), +// profile.getShape(), +// -direction); +// if (proj.More()) { +// remove_limits = true; +// break; +// } +// } +// } +// +// if (remove_limits) { +// // Note: Using an unlimited face every time gives unnecessary failures for concave faces +// TopLoc_Location loc = face.Location(); +// BRepAdaptor_Surface adapt(face, Standard_False); +// // use the placement of the adapter, not of the upToFace +// loc = TopLoc_Location(adapt.Trsf()); +// BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface(), Precision::Confusion()); +// if (!mkFace.IsDone()) { +// remove_limits = false; +// } +// else { +// uptoface.setShape(located(mkFace.Shape(), loc), false); +// } +// } +// } +// +// TopoShape uptofaceCopy = uptoface; +// bool checkBase = false; +// auto retry = [&]() { +// if (!uptoface.isSame(_uptoface)) { +// // retry using the original up to face in case unnecessary failure +// // due to removing the limits +// uptoface = _uptoface; +// return true; +// } +// if ((!_base.isNull() && base.isSame(_base)) || (_base.isNull() && base.isSame(profile))) { +// // It is unclear under exactly what condition extrude up to face +// // can fail. Either the support face or the up to face must be part +// // of the base, or maybe some thing else. +// // +// // To deal with it, we retry again by disregard the supplied base, +// // and use up to face to extrude our own base. Later on, use the +// // supplied base (i.e. _base) to calculate the final shape if the +// // mode is FuseWithBase or CutWithBase. +// checkBase = true; +// uptoface = uptofaceCopy; +// base.makeElementPrism(_uptoface, direction); +// return true; +// } +// return false; +// }; +// +// std::vector srcShapes; +// TopoShape result; +// for (;;) { +// try { +// result = base; +// +// // We do not rely on BRepFeat_MakePrism to perform fuse or cut for +// // us because of its poor support of shape history. +// auto mode = PrismMode::None; +// +// for (auto& face : profile.getSubTopoShapes( +// profile.hasSubShape(TopAbs_FACE) ? TopAbs_FACE : TopAbs_WIRE)) { +// srcShapes.clear(); +// if (!profile.isNull() && !result.findShape(profile.getShape())) { +// srcShapes.push_back(profile); +// } +// if (!supportFace.isNull() && !result.findShape(supportFace.getShape())) { +// srcShapes.push_back(supportFace); +// } +// +// // DO NOT include uptoface for element mapping. Because OCCT +// // BRepFeat_MakePrism will report all top extruded face being +// // modified by the uptoface. If there are more than one face in +// // the profile, this will cause uncessary duplicated element +// // mapped name. And will also disrupte element history tracing +// // back to the profile sketch. +// // +// // if (!uptoface.isNull() && !this->findShape(uptoface.getShape())) +// // srcShapes.push_back(uptoface); +// +// srcShapes.push_back(result); +// +// PrismMaker.Init(result.getShape(), +// face.getShape(), +// TopoDS::Face(supportFace.getShape()), +// direction, +// mode, +// Standard_False); +// mode = PrismMode::FuseWithBase; +// +// PrismMaker.Perform(uptoface.getShape()); +// +// if (!PrismMaker.IsDone() || PrismMaker.Shape().IsNull()) { +// FC_THROWM(Base::CADKernelError, "BRepFeat_MakePrism: extrusion failed"); +// } +// +// result.makeElementShape(PrismMaker, srcShapes, uptoface, op); +// } +// break; +// } +// catch (Base::Exception&) { +// if (!retry()) { +// throw; +// } +// } +// catch (Standard_Failure&) { +// if (!retry()) { +// throw; +// } +// } +// } +// +// if (!_base.isNull() && Mode != PrismMode::None) { +// if (Mode == PrismMode::FuseWithBase) { +// result.makeElementFuse({_base, result}); +// } +// else { +// result.makeElementCut({_base, result}); +// } +// } +// +// *this = result; +// return *this; +//} + +TopoShape& TopoShape::makeElementRevolve(const TopoShape& _base, + const gp_Ax1& axis, + double d, + const char* face_maker, + const char* op) { - if(!op) op = Part::OpCodes::Revolve; + if (!op) { + op = Part::OpCodes::Revolve; + } TopoShape base(_base); - if(base.isNull()) + if (base.isNull()) { FC_THROWM(NullShapeException, "Null shape"); - if(face_maker && !base.hasSubShape(TopAbs_FACE)) { - if(!base.hasSubShape(TopAbs_WIRE)) - base = base.makeElementWires(); - base = base.makeElementFace(nullptr,face_maker, nullptr); } - BRepPrimAPI_MakeRevol mkRevol(base.getShape(), axis,d); - return makeElementShape(mkRevol,base,op); + if (face_maker && !base.hasSubShape(TopAbs_FACE)) { + if (!base.hasSubShape(TopAbs_WIRE)) { + base = base.makeElementWires(); + } + base = base.makeElementFace(nullptr, face_maker, nullptr); + } + BRepPrimAPI_MakeRevol mkRevol(base.getShape(), axis, d); + return makeElementShape(mkRevol, base, op); } TopoShape& TopoShape::makeElementDraft(const TopoShape& shape, diff --git a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp index c57363806d..399312f483 100644 --- a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -1966,4 +1966,133 @@ TEST_F(TopoShapeExpansionTest, makeElementSolid) EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;SLD;:H1:4,F")); } +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_FLOAT_EQ(getVolume(result.getShape()), 0.50885141); + // 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;RVL;:H2:4,E);RVL;:H2:62,F", + "Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:U;RVL;:H2:7,V", + "Edge1;RVL;:H2:4,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;RVL;:H2:4,E", + "Edge3;:G;RVL;:H2:7,F", + "Edge3;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E", + "Edge3;RVL;:H2:4,E", + "Edge4;RVL;:H2:4,E", + "Face1;RVL;:H2:4,F", + "Vertex1;:G;RVL;:H2:7,E", + "Vertex1;RVL;:H2:4,V", + "Vertex2;RVL;:H2:4,V", + "Vertex3;:G;RVL;:H2:7,E", + "Vertex3;RVL;:H2:4,V", + "Vertex4;RVL;:H2:4,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;:L(Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E|Edge3;:G;" + "XTR;:H2:7,F;:U;XTR;:H2:7,E|Edge4;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E);XTR;:H2:74,F", + "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;XTR;:H2:4,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;XTR;:H2:4,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;XTR;:H2:4,E", + "Edge4;:G;XTR;:H2:7,F", + "Edge4;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E", + "Edge4;XTR;:H2:4,E", + "Face1;XTR;:H2:4,F", + "Vertex1;:G;XTR;:H2:7,E", + "Vertex1;XTR;:H2:4,V", + "Vertex2;:G;XTR;:H2:7,E", + "Vertex2;XTR;:H2:4,V", + "Vertex3;:G;XTR;:H2:7,E", + "Vertex3;XTR;:H2:4,V", + "Vertex4;:G;XTR;:H2:7,E", + "Vertex4;XTR;:H2:4,V", + }) + + ); +} + +// TODO: This code was written in Feb 2024 as part of the toponaming project, but appears to be +// unused. It is potentially useful if debugged. +// +// TEST_F(TopoShapeExpansionTest, makeElementPrismUntil) +//{ +// // Arrange +// auto [cube1, cube2] = CreateTwoCubes(); +// TopoShape cube1TS {cube1, 1L}; +// auto subFaces = cube1TS.getSubShapes(TopAbs_FACE); +// auto subTopoFaces = cube1TS.getSubTopoShapes(TopAbs_FACE); +// subTopoFaces[0].Tag = 2L; +// subTopoFaces[1].Tag = 3L; +// auto tr {gp_Trsf()}; +// auto direction = gp_Vec(gp_XYZ(0.0, 0.0, 0.25)); +// tr.SetTranslation(direction); +// auto support = subFaces[0].Moved(TopLoc_Location(tr)); +// auto upto = support.Moved(TopLoc_Location(tr)); +// // Act +// TopoShape result = cube1TS.makeElementPrismUntil(subTopoFaces[0], +// TopoShape(support, 4L), +// TopoShape(upto, 5L), +// direction, +// TopoShape::PrismMode::CutFromBase); +// 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_TRUE(elementsMatch(result, +// {"Edge1;:G;XTR;:H2:7,F",})); +//} + // NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)