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, ""))