From 43ad429734ff44990ef05b4b2674a817348a21f0 Mon Sep 17 00:00:00 2001 From: triplus Date: Mon, 7 Nov 2016 16:35:14 +0100 Subject: [PATCH] Add Part BOA multiCut, multiCommon and multiSection methods --- src/Mod/Part/App/TopoShape.cpp | 102 ++++++++++++++++++++++++++++ src/Mod/Part/App/TopoShape.h | 3 + src/Mod/Part/App/TopoShapePy.xml | 53 ++++++++++++++- src/Mod/Part/App/TopoShapePyImp.cpp | 99 +++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 29f761cdf..884ec6de7 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1306,6 +1306,74 @@ TopoDS_Shape TopoShape::fuse(TopoDS_Shape shape) const return mkFuse.Shape(); } +TopoDS_Shape TopoShape::multiCut(const std::vector& shapes, Standard_Real tolerance) const +{ + if (this->_Shape.IsNull()) + Standard_Failure::Raise("Base shape is null"); +#if OCC_VERSION_HEX < 0x060900 + (void)shapes; + (void)tolerance; + throw Base::AttributeError("multiCut is available only in OCC 6.9.0 and up."); +#else + BRepAlgoAPI_Cut mkCut; + mkCut.SetRunParallel(true); + TopTools_ListOfShape shapeArguments,shapeTools; + shapeArguments.Append(this->_Shape); + for (std::vector::const_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); + } + mkCut.SetArguments(shapeArguments); + mkCut.SetTools(shapeTools); + if (tolerance > 0.0) + mkCut.SetFuzzyValue(tolerance); + mkCut.Build(); + if (!mkCut.IsDone()) + throw Base::Exception("MultiCut failed"); + TopoDS_Shape resShape = mkCut.Shape(); + return resShape; +#endif +} + +TopoDS_Shape TopoShape::multiCommon(const std::vector& shapes, Standard_Real tolerance) const +{ + if (this->_Shape.IsNull()) + Standard_Failure::Raise("Base shape is null"); +#if OCC_VERSION_HEX < 0x060900 + (void)shapes; + (void)tolerance; + throw Base::AttributeError("multiCommon is available only in OCC 6.9.0 and up."); +#else + BRepAlgoAPI_Common mkCommon; + mkCommon.SetRunParallel(true); + TopTools_ListOfShape shapeArguments,shapeTools; + shapeArguments.Append(this->_Shape); + for (std::vector::const_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); + } + mkCommon.SetArguments(shapeArguments); + mkCommon.SetTools(shapeTools); + if (tolerance > 0.0) + mkCommon.SetFuzzyValue(tolerance); + mkCommon.Build(); + if (!mkCommon.IsDone()) + throw Base::Exception("MultiCommon failed"); + TopoDS_Shape resShape = mkCommon.Shape(); + return resShape; +#endif +} + TopoDS_Shape TopoShape::multiFuse(const std::vector& shapes, Standard_Real tolerance) const { if (this->_Shape.IsNull()) @@ -1354,6 +1422,40 @@ TopoDS_Shape TopoShape::multiFuse(const std::vector& shapes, Stand return resShape; } +TopoDS_Shape TopoShape::multiSection(const std::vector& shapes, Standard_Real tolerance) const +{ + if (this->_Shape.IsNull()) + Standard_Failure::Raise("Base shape is null"); +#if OCC_VERSION_HEX < 0x060900 + (void)shapes; + (void)tolerance; + throw Base::AttributeError("multiSection is available only in OCC 6.9.0 and up."); +#else + BRepAlgoAPI_Section mkSection; + mkSection.SetRunParallel(true); + TopTools_ListOfShape shapeArguments,shapeTools; + shapeArguments.Append(this->_Shape); + for (std::vector::const_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); + } + mkSection.SetArguments(shapeArguments); + mkSection.SetTools(shapeTools); + if (tolerance > 0.0) + mkSection.SetFuzzyValue(tolerance); + mkSection.Build(); + if (!mkSection.IsDone()) + throw Base::Exception("MultiSection failed"); + TopoDS_Shape resShape = mkSection.Shape(); + return resShape; +#endif +} + 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 d1ae2c882..3dad2df8b 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -156,7 +156,10 @@ public: TopoDS_Shape cut(TopoDS_Shape) const; TopoDS_Shape common(TopoDS_Shape) const; TopoDS_Shape fuse(TopoDS_Shape) const; + TopoDS_Shape multiCut(const std::vector&, Standard_Real tolerance = 0.0) const; + TopoDS_Shape multiCommon(const std::vector&, Standard_Real tolerance = 0.0) const; TopoDS_Shape multiFuse(const std::vector&, Standard_Real tolerance = 0.0) const; + TopoDS_Shape multiSection(const 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 d2a0f23be..c19f61d99 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -143,11 +143,60 @@ This is a more detailed check as done in isValid(). Union of this and a given topo shape. + + + multiCut((tool1,tool2,...),[tolerance=0.0]) -> Shape + +Substraction of this and a given list of topo shapes. + +Supports: +- Fuzzy Boolean operations (global tolerance for a Boolean operation) +- Support of multiple arguments for a single Boolean operation +- Parallelization of Boolean Operations algorithm + +OCC 6.9.0 or later is required. + + + + + multiCommon((tool1,tool2,...),[tolerance=0.0]) -> Shape + +Intersection of this and a given list of topo shapes. + +Supports: +- Fuzzy Boolean operations (global tolerance for a Boolean operation) +- Support of multiple arguments for a single Boolean operation (s1 AND (s2 OR s2)) +- Parallelization of Boolean Operations algorithm + +OCC 6.9.0 or later is required. + + 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 + +Supports (OCCT 6.9.0 and above): +- Fuzzy Boolean operations (global tolerance for a Boolean operation) +- Support of multiple arguments for a single Boolean operation +- Parallelization of Boolean Operations algorithm + +Beginning from OCCT 6.8.1 a tolerance value can be specified. + + + + + multiSection((tool1,tool2,...),[tolerance=0.0]) -> Shape + +Section of this and a given list of topo shapes. + +Supports: +- Fuzzy Boolean operations (global tolerance for a Boolean operation) +- Support of multiple arguments for a single Boolean operation +- Parallelization of Boolean Operations algorithm + +OCC 6.9.0 or later is required. @@ -203,6 +252,8 @@ 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 +Parallelization of Boolean Operations algorithm + OCC 6.9.0 or later is required. diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 0414b4460..232c306b0 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -779,6 +779,72 @@ PyObject* TopoShapePy::fuse(PyObject *args) } } +PyObject* TopoShapePy::multiCut(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()->getShape()); + } + else { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + return 0; + } + } + try { + TopoDS_Shape multiCutShape = this->getTopoShapePtr()->multiCut(shapeVec,tolerance); + return new TopoShapePy(new TopoShape(multiCutShape)); + } + 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::multiCommon(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()->getShape()); + } + else { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + return 0; + } + } + try { + TopoDS_Shape multiCommonShape = this->getTopoShapePtr()->multiCommon(shapeVec,tolerance); + return new TopoShapePy(new TopoShape(multiCommonShape)); + } + 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::multiFuse(PyObject *args) { double tolerance = 0.0; @@ -812,6 +878,39 @@ PyObject* TopoShapePy::multiFuse(PyObject *args) } } +PyObject* TopoShapePy::multiSection(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()->getShape()); + } + else { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + return 0; + } + } + try { + TopoDS_Shape multiSectionShape = this->getTopoShapePtr()->multiSection(shapeVec,tolerance); + return new TopoShapePy(new TopoShape(multiSectionShape)); + } + 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;