diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 5ba19be764..1d51ae7df5 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -227,6 +227,8 @@ public: /// get the Topo"sub"Shape with the given name TopoDS_Shape getSubShape(const char* Type, bool silent = false) const; TopoDS_Shape getSubShape(TopAbs_ShapeEnum type, int idx, bool silent = false) const; + TopoShape getSubTopoShape(const char* Type, bool silent = false) const; + TopoShape getSubTopoShape(TopAbs_ShapeEnum type, int idx, bool silent = false) const; std::vector getSubTopoShapes(TopAbs_ShapeEnum type = TopAbs_SHAPE) const; std::vector getSubShapes(TopAbs_ShapeEnum type = TopAbs_SHAPE) const; unsigned long countSubShapes(const char* Type) const; @@ -697,6 +699,7 @@ public: void mapSubElementsTo(std::vector& shapes, const char* op = nullptr) const; bool hasPendingElementMap() const; + /** Helper class to return the generated and modified shape given an input shape * * Shape history information is extracted using OCCT APIs diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 0aa0353e7f..c079726ef6 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -1291,6 +1291,89 @@ void addShapesToBuilder(const std::vector& shapes, } } // namespace +TopoShape TopoShape::getSubTopoShape(const char* Type, bool silent) const +{ + if (!Type || !Type[0]) { + switch (shapeType(true)) { + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + if (countSubShapes(TopAbs_SOLID) == 1) { + return getSubTopoShape(TopAbs_SOLID, 1); + } + if (countSubShapes(TopAbs_SHELL) == 1) { + return getSubTopoShape(TopAbs_SHELL, 1); + } + if (countSubShapes(TopAbs_FACE) == 1) { + return getSubTopoShape(TopAbs_FACE, 1); + } + if (countSubShapes(TopAbs_WIRE) == 1) { + return getSubTopoShape(TopAbs_WIRE, 1); + } + if (countSubShapes(TopAbs_EDGE) == 1) { + return getSubTopoShape(TopAbs_EDGE, 1); + } + if (countSubShapes(TopAbs_VERTEX) == 1) { + return getSubTopoShape(TopAbs_VERTEX, 1); + } + break; + default: + break; + } + return *this; + } + + Data::MappedElement mapped = getElementName(Type); + if (!mapped.index && boost::starts_with(Type, elementMapPrefix())) { + if (!silent) { + FC_THROWM(Base::CADKernelError, "Mapped element not found: " << Type); + } + return TopoShape(); + } + + auto res = shapeTypeAndIndex(Type); + if (res.second <= 0) { + if (!silent) { + FC_THROWM(Base::ValueError, "Invalid shape name " << (Type ? Type : "")); + } + return TopoShape(); + } + return getSubTopoShape(res.first, res.second, silent); +} + +TopoShape TopoShape::getSubTopoShape(TopAbs_ShapeEnum type, int idx, bool silent) const +{ + if (isNull()) { + if (!silent) { + FC_THROWM(NullShapeException, "null shape"); + } + return TopoShape(); + } + if (idx <= 0) { + if (!silent) { + FC_THROWM(Base::ValueError, "Invalid shape index " << idx); + } + return TopoShape(); + } + if (type < 0 || type > TopAbs_SHAPE) { + if (!silent) { + FC_THROWM(Base::ValueError, "Invalid shape type " << type); + } + return TopoShape(); + } + initCache(); + auto& shapeMap = _cache->getAncestry(type); + if (idx > shapeMap.count()) { + if (!silent) { + FC_THROWM(Base::IndexError, + "Shape index " << idx << " out of bound " << shapeMap.count()); + } + return TopoShape(); + } + + return shapeMap.getTopoShape(*this, idx); +} + + TopoShape& TopoShape::makeElementCompound(const std::vector& shapes, const char* op, SingleShapeCompoundCreationPolicy policy)