From c2ce8f5eba10e1dccdf9a9e9ac68813ae1738477 Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Thu, 19 Feb 2015 13:14:18 +0100 Subject: [PATCH] add TopoShape::multiFuse method to fuse multiple shapes at once. --- src/Mod/Part/App/TopoShape.cpp | 45 +++++++++++++++++++++++++++++ src/Mod/Part/App/TopoShape.h | 1 + src/Mod/Part/App/TopoShapePy.xml | 7 +++++ src/Mod/Part/App/TopoShapePyImp.cpp | 33 +++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 23f34c5dec..012e1301ce 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1331,6 +1331,51 @@ TopoDS_Shape TopoShape::fuse(TopoDS_Shape shape) const return mkFuse.Shape(); } +TopoDS_Shape TopoShape::multiFuse(std::vector shapes, Standard_Real tolerance) const +{ + if (this->_Shape.IsNull()) + Standard_Failure::Raise("Base shape is null"); +#if OCC_VERSION_HEX <= 0x060800 + if (tolerance > 0.0) + Standard_Failure::Raise("Fuzzy Booleans are not supported in this version of OCCT"); + TopoDS_Shape resShape = this->_Shape; + if (resShape.IsNull()) + throw Base::Exception("Object shape is null"); + for (std::vector::iterator it = shapes.begin(); it != shapes.end(); ++it) { + if (it->IsNull()) + throw Base::Exception("Input shape is null"); + // Let's call algorithm computing a fuse operation: + BRepAlgoAPI_Fuse mkFuse(resShape, *it); + // Let's check if the fusion has been successful + if (!mkFuse.IsDone()) + throw Base::Exception("Fusion failed"); + resShape = mkFuse.Shape(); + } +#else + BRepAlgoAPI_Fuse mkFuse; + TopTools_ListOfShape shapeArguments,shapeTools; + shapeArguments.Append(this->_Shape); + for (std::vector::iterator it = shapes.begin(); it != shapes.end(); ++it) { + if (it->IsNull()) + throw Base::Exception("Tool shape is null"); + if (tolerance > 0.0) + // workaround for http://dev.opencascade.org/index.php?q=node/1056#comment-520 + shapeTools.Append(BRepBuilderAPI_Copy(*it).Shape()); + else + shapeTools.Append(*it); + } + mkFuse.SetArguments(shapeArguments); + mkFuse.SetTools(shapeTools); + if (tolerance > 0.0) + mkFuse.SetFuzzyValue(tolerance); + mkFuse.Build(); + if (!mkFuse.IsDone()) + throw Base::Exception("MultiFusion failed"); + TopoDS_Shape resShape = mkFuse.Shape(); +#endif + return resShape; +} + TopoDS_Shape TopoShape::oldFuse(TopoDS_Shape shape) const { if (this->_Shape.IsNull()) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index fdf2dca74d..145e02b06c 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -146,6 +146,7 @@ public: TopoDS_Shape cut(TopoDS_Shape) const; TopoDS_Shape common(TopoDS_Shape) const; TopoDS_Shape fuse(TopoDS_Shape) const; + TopoDS_Shape multiFuse(std::vector, Standard_Real tolerance = 0.0) const; TopoDS_Shape oldFuse(TopoDS_Shape) const; TopoDS_Shape section(TopoDS_Shape) const; std::list slice(const Base::Vector3d&, double) const; diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index 6b5ee6224e..5a812748f9 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -133,6 +133,13 @@ This is a more detailed check as done in isValid(). Union of this and a given topo shape. + + + multiFuse((tool1,tool2,...),[tolerance=0.0]) -> Shape +Union of this and a given list of topo shapes. +Beginning from OCCT 6.8.1 a tolerance value can be specified + + Union of this and a given topo shape (old algorithm). diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 5a965f5ec2..c014d45e21 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -645,6 +645,39 @@ PyObject* TopoShapePy::fuse(PyObject *args) } } +PyObject* TopoShapePy::multiFuse(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 { + TopoDS_Shape multiFusedShape = this->getTopoShapePtr()->multiFuse(shapeVec,tolerance); + return new TopoShapePy(new TopoShape(multiFusedShape)); + } + 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::oldFuse(PyObject *args) { PyObject *pcObj;