diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index 303bd2e6fd..b9a7acaad8 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -283,6 +283,13 @@ Return a list of sub-shapes that are direct children of this shape. + + + ancestorsOfType(shape, shape type) -> list +For a sub-shape of this shape get its ancestors of a type. + + + Removes internal wires (also holes) from the shape. diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 3ac01ac2a5..8f2aab8d40 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -1218,6 +1218,75 @@ PyObject* TopoShapePy::childShapes(PyObject *args) } } +namespace Part { +std::vector buildShapeEnumTypeMap() +{ + std::vector typeMap; + typeMap.push_back(&TopoShapeCompoundPy::Type); //TopAbs_COMPOUND + typeMap.push_back(&TopoShapeCompSolidPy::Type); //TopAbs_COMPSOLID + typeMap.push_back(&TopoShapeSolidPy::Type); //TopAbs_SOLID + typeMap.push_back(&TopoShapeShellPy::Type); //TopAbs_SHELL + typeMap.push_back(&TopoShapeFacePy::Type); //TopAbs_FACE + typeMap.push_back(&TopoShapeWirePy::Type); //TopAbs_WIRE + typeMap.push_back(&TopoShapeEdgePy::Type); //TopAbs_EDGE + typeMap.push_back(&TopoShapeVertexPy::Type); //TopAbs_VERTEX + typeMap.push_back(&TopoShapePy::Type); //TopAbs_SHAPE + return typeMap; +} +} + +PyObject* TopoShapePy::ancestorsOfType(PyObject *args) +{ + PyObject *pcObj; + PyObject *type; + if (!PyArg_ParseTuple(args, "O!O!", &(TopoShapePy::Type), &pcObj, &PyType_Type, &type)) + return NULL; + + try { + const TopoDS_Shape& model = getTopoShapePtr()->getShape(); + const TopoDS_Shape& shape = static_cast(pcObj)-> + getTopoShapePtr()->getShape(); + if (model.IsNull() || shape.IsNull()) { + PyErr_SetString(PyExc_ValueError, "Shape is null"); + return NULL; + } + + static std::vector typeMap = buildShapeEnumTypeMap(); + PyTypeObject* pyType = reinterpret_cast(type); + TopAbs_ShapeEnum shapetype = TopAbs_SHAPE; + for (auto it = typeMap.begin(); it != typeMap.end(); ++it) { + if (PyType_IsSubtype(pyType, *it)) { + auto index = std::distance(typeMap.begin(), it); + shapetype = static_cast(index); + break; + } + } + + TopTools_IndexedDataMapOfShapeListOfShape mapOfShapeShape; + TopExp::MapShapesAndAncestors(model, shape.ShapeType(), shapetype, mapOfShapeShape); + const TopTools_ListOfShape& ancestors = mapOfShapeShape.FindFromKey(shape); + + Py::List list; + std::set hashes; + TopTools_ListIteratorOfListOfShape it(ancestors); + for (; it.More(); it.Next()) { + // make sure to avoid duplicates + Standard_Integer code = it.Value().HashCode(INT_MAX); + if (hashes.find(code) == hashes.end()) { + list.append(shape2pyshape(it.Value())); + hashes.insert(code); + } + } + + return Py::new_reference_to(list); + } + catch (Standard_Failure) { + Handle(Standard_Failure) e = Standard_Failure::Caught(); + PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); + return NULL; + } +} + PyObject* TopoShapePy::removeInternalWires(PyObject *args) { double minArea;