diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index b95734d2e..6f3d24b02 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -180,6 +180,33 @@ Beginning from OCCT 6.8.1 a tolerance value can be specified Difference of this and a given topo shape. + + + generalFuse(list_of_other_shapes, fuzzy_value = 0.0): Run general fuse algorithm (GFA) between this and given shapes. + +list_of_other_shapes: shapes to run the algorithm against (the list is +effectively prepended by 'self'). + +fuzzy_value: extra tolerance to apply when searching for interferences, in +addition to tolerances of the input shapes. + +Returns a tuple of 2: (result, map). + +result is a compound containing all the pieces generated by the algorithm +(e.g., for two spheres, the pieces are three touching solids). Pieces that +touch share elements. + +map is a list of lists of shapes, providing the info on which children of +result came from which argument. The length of list is equal to length of +list_of_other_shapes + 1. First element is a list of pieces that came from +shape of this, and the rest are those that come from corresponding shapes in +list_of_other_shapes. +hint: use isSame method to test shape equality + +OCC 6.9.0 or later is required. + + + Sew the shape if there is a gap. @@ -190,11 +217,11 @@ Beginning from OCCT 6.8.1 a tolerance value can be specified childShapes([cumOri=True, cumLoc=True]) -> list Return a list of sub-shapes that are direct children of this shape. - * If cumOri is true, the function composes all - sub-shapes with the orientation of this shape. - * If cumLoc is true, the function multiplies all - sub-shapes by the location of this shape, i.e. it applies to - each sub-shape the transformation that is associated with this shape. + * If cumOri is true, the function composes all + sub-shapes with the orientation of this shape. + * If cumLoc is true, the function multiplies all + sub-shapes by the location of this shape, i.e. it applies to + each sub-shape the transformation that is associated with this shape. diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index f25fc12db..32661ec8f 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -49,6 +49,8 @@ # include # include # include +# include +# include # include # include # include @@ -153,6 +155,54 @@ int TopoShapePy::PyInit(PyObject* args, PyObject*) return 0; } +//common code.. maybe put somewhere else? +Py::Object shape2pyshape(const TopoDS_Shape &shape) +{ + PyObject* ret = 0; + if (!shape.IsNull()) { + TopAbs_ShapeEnum type = shape.ShapeType(); + switch (type) + { + case TopAbs_COMPOUND: + ret = new TopoShapeCompoundPy(new TopoShape(shape)); + break; + case TopAbs_COMPSOLID: + ret = new TopoShapeCompSolidPy(new TopoShape(shape)); + break; + case TopAbs_SOLID: + ret = new TopoShapeSolidPy(new TopoShape(shape)); + break; + case TopAbs_SHELL: + ret = new TopoShapeShellPy(new TopoShape(shape)); + break; + case TopAbs_FACE: + ret = new TopoShapeFacePy(new TopoShape(shape)); + break; + case TopAbs_WIRE: + ret = new TopoShapeWirePy(new TopoShape(shape)); + break; + case TopAbs_EDGE: + ret = new TopoShapeEdgePy(new TopoShape(shape)); + break; + case TopAbs_VERTEX: + ret = new TopoShapeVertexPy(new TopoShape(shape)); + break; + case TopAbs_SHAPE: + ret = new TopoShapePy(new TopoShape(shape)); + break; + default: + //shouldn't happen + ret = new TopoShapePy(new TopoShape(shape)); + break; + } + } else { + ret = new TopoShapePy(new TopoShape(shape)); + } + assert(ret); + + return Py::asObject(ret); +} + PyObject* TopoShapePy::copy(PyObject *args) { if (!PyArg_ParseTuple(args, "")) @@ -907,6 +957,54 @@ PyObject* TopoShapePy::cut(PyObject *args) } } +PyObject* TopoShapePy::generalFuse(PyObject *args) +{ + double tolerance = 0.0; + PyObject *pcObj; + if (!PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance)) + return NULL; + std::vector shapeVec; + Py::Sequence shapeSeq(pcObj); + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + shapeVec.push_back(static_cast(item)->getTopoShapePtr()->_Shape); + } + else { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + return 0; + } + } + try { + std::vector map; + TopoDS_Shape gfaResultShape = this->getTopoShapePtr()->generalFuse(shapeVec,tolerance,&map); + + Py::Object shapePy = shape2pyshape(gfaResultShape); + + Py::List mapPy; + for(TopTools_ListOfShape &shapes: map){ + Py::List shapesPy; + for(TopTools_ListIteratorOfListOfShape it(shapes); it.More(); it.Next()){ + shapesPy.append(shape2pyshape(it.Value())); + } + mapPy.append(shapesPy); + } + Py::Tuple ret(2); + ret[0] = shapePy; + ret[1] = mapPy; + return Py::new_reference_to(ret); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); + return NULL; + } + catch (const std::exception& e) { + PyErr_SetString(PartExceptionOCCError, e.what()); + return NULL; + } +} + PyObject* TopoShapePy::sewShape(PyObject *args) { if (!PyArg_ParseTuple(args, ""))