From 729c24b0f1c8bb6a0fcebe740731b4c334fd67ea Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Fri, 29 Jul 2022 16:20:48 -0700 Subject: [PATCH] Moved voronoi classes into Path.Voronoi module. --- src/Mod/Path/App/AppPath.cpp | 14 +- src/Mod/Path/App/AppPathPy.cpp | 624 +++++++++++----------- src/Mod/Path/App/VoronoiCellPy.xml | 1 + src/Mod/Path/App/VoronoiEdgePy.xml | 1 + src/Mod/Path/App/VoronoiPy.xml | 2 +- src/Mod/Path/App/VoronoiVertexPy.xml | 1 + src/Mod/Path/PathScripts/PathVcarve.py | 2 +- src/Mod/Path/PathTests/TestPathVoronoi.py | 2 +- 8 files changed, 333 insertions(+), 314 deletions(-) diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp index a973840cef..1e7a055943 100644 --- a/src/Mod/Path/App/AppPath.cpp +++ b/src/Mod/Path/App/AppPath.cpp @@ -53,7 +53,7 @@ namespace Path { -extern PyObject* initModule(); + extern PyObject* initModule(); } /* Python entry */ @@ -71,16 +71,20 @@ PyMOD_INIT_FUNC(Path) PyObject* pathModule = Path::initModule(); Base::Console().Log("Loading Path module... done\n"); + Py::Object module(pathModule); + // Add Types to module Base::Interpreter().addType(&Path::CommandPy ::Type, pathModule, "Command"); Base::Interpreter().addType(&Path::PathPy ::Type, pathModule, "Path"); Base::Interpreter().addType(&Path::ToolPy ::Type, pathModule, "Tool"); Base::Interpreter().addType(&Path::TooltablePy ::Type, pathModule, "Tooltable"); Base::Interpreter().addType(&Path::AreaPy ::Type, pathModule, "Area"); - Base::Interpreter().addType(&Path::VoronoiPy ::Type, pathModule, "VoronoiDiagram"); - Base::Interpreter().addType(&Path::VoronoiCellPy ::Type, pathModule, "VoronoiCell"); - Base::Interpreter().addType(&Path::VoronoiEdgePy ::Type, pathModule, "VoronoiEdge"); - Base::Interpreter().addType(&Path::VoronoiVertexPy ::Type, pathModule, "VoronoiVertex"); + + PyObject* voronoiModule(module.getAttr("Voronoi").ptr()); + Base::Interpreter().addType(&Path::VoronoiPy ::Type, voronoiModule, "Diagram"); + Base::Interpreter().addType(&Path::VoronoiCellPy ::Type, voronoiModule, "Cell"); + Base::Interpreter().addType(&Path::VoronoiEdgePy ::Type, voronoiModule, "Edge"); + Base::Interpreter().addType(&Path::VoronoiVertexPy ::Type, voronoiModule, "Vertex"); // NOTE: To finish the initialization of our own type objects we must // call PyType_Ready, otherwise we run into a segmentation fault, later on. diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index 44e0177596..37e0fe5e0f 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -90,344 +90,356 @@ } throw Py::Exception(); namespace Path { -class Module : public Py::ExtensionModule -{ + class VoronoiModule : public Py::ExtensionModule + { + public: + VoronoiModule() : Py::ExtensionModule("Voronoi") + { + initialize("Working with Voronoi diagrams and data structures"); + } + virtual ~VoronoiModule() {} + }; -public: + class Module : public Py::ExtensionModule + { + VoronoiModule voronoi; + public: - Module() : Py::ExtensionModule("Path") - { - add_varargs_method("write",&Module::write, - "write(object,filename): Exports a given path object to a GCode file" - ); - add_varargs_method("read",&Module::read, - "read(filename,[document]): Imports a GCode file into the given document" - ); - add_varargs_method("show",&Module::show, - "show(path,[string]): Add the path to the active document or create one if no document exists" - ); - add_varargs_method("fromShape",&Module::fromShape, - "fromShape(Shape): Returns a Path object from a Part Shape (deprecated - use fromShapes() instead)" - ); - add_keyword_method("fromShapes",&Module::fromShapes, - "fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_PATH) ")\n" - "\nReturns a Path object from a list of shapes\n" - "\n* shapes: input list of shapes.\n" - "\n* start (Vector()): feed start position, and also serves as a hint of path entry.\n" - "\n* return_end (False): if True, returns tuple (path, endPosition).\n" - PARAM_PY_DOC(ARG, AREA_PARAMS_PATH) - ); - add_keyword_method("sortWires",&Module::sortWires, - "sortWires(shapes, start=Vector(), " - PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_ARC_PLANE) - PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) ")\n" - "\nReturns (wires,end), where 'wires' is sorted across Z value and with optimized travel distance,\n" - "and 'end' is the ending position of the whole wires. If arc_plane==1, it returns (wires,end,arc_plane),\n" - "where arc_plane is the found plane if any, or unchanged.\n" - "\n* shapes: input shape list\n" - "\n* start (Vector()): optional start position.\n" - PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE) - PARAM_PY_DOC(ARG, AREA_PARAMS_SORT) - ); - initialize("This module is the Path module."); // register with Python - } + Module() : Py::ExtensionModule("Path") + { + add_varargs_method("write",&Module::write, + "write(object,filename): Exports a given path object to a GCode file" + ); + add_varargs_method("read",&Module::read, + "read(filename,[document]): Imports a GCode file into the given document" + ); + add_varargs_method("show",&Module::show, + "show(path,[string]): Add the path to the active document or create one if no document exists" + ); + add_varargs_method("fromShape",&Module::fromShape, + "fromShape(Shape): Returns a Path object from a Part Shape (deprecated - use fromShapes() instead)" + ); + add_keyword_method("fromShapes",&Module::fromShapes, + "fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_PATH) ")\n" + "\nReturns a Path object from a list of shapes\n" + "\n* shapes: input list of shapes.\n" + "\n* start (Vector()): feed start position, and also serves as a hint of path entry.\n" + "\n* return_end (False): if True, returns tuple (path, endPosition).\n" + PARAM_PY_DOC(ARG, AREA_PARAMS_PATH) + ); + add_keyword_method("sortWires",&Module::sortWires, + "sortWires(shapes, start=Vector(), " + PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_ARC_PLANE) + PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) ")\n" + "\nReturns (wires,end), where 'wires' is sorted across Z value and with optimized travel distance,\n" + "and 'end' is the ending position of the whole wires. If arc_plane==1, it returns (wires,end,arc_plane),\n" + "where arc_plane is the found plane if any, or unchanged.\n" + "\n* shapes: input shape list\n" + "\n* start (Vector()): optional start position.\n" + PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE) + PARAM_PY_DOC(ARG, AREA_PARAMS_SORT) + ); + initialize("This module is the Path module."); // register with Python - virtual ~Module() {} + PyModule_AddObject(m_module, "Voronoi", voronoi.module().ptr()); + } -private: + virtual ~Module() {} - Py::Object write(const Py::Tuple& args) - { - char* Name; - PyObject* pObj; - if (!PyArg_ParseTuple(args.ptr(), "Oet",&pObj,"utf-8",&Name)) - throw Py::Exception(); - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - Base::FileInfo file(EncodedName.c_str()); + private: - if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(pObj)->getDocumentObjectPtr(); - if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { - const Toolpath& path = static_cast(obj)->Path.getValue(); - std::string gcode = path.toGCode(); - std::ofstream ofile(EncodedName.c_str()); - ofile << gcode; - ofile.close(); - } - else { - throw Py::RuntimeError("The given file is not a path"); - } - } + Py::Object write(const Py::Tuple& args) + { + char* Name; + PyObject* pObj; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&pObj,"utf-8",&Name)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + Base::FileInfo file(EncodedName.c_str()); - return Py::None(); - } + if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = static_cast(pObj)->getDocumentObjectPtr(); + if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { + const Toolpath& path = static_cast(obj)->Path.getValue(); + std::string gcode = path.toGCode(); + std::ofstream ofile(EncodedName.c_str()); + ofile << gcode; + ofile.close(); + } + else { + throw Py::RuntimeError("The given file is not a path"); + } + } + + return Py::None(); + } - Py::Object read(const Py::Tuple& args) - { - char* Name; - const char* DocName=nullptr; - if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) - throw Py::Exception(); - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + Py::Object read(const Py::Tuple& args) + { + char* Name; + const char* DocName=nullptr; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - Base::FileInfo file(EncodedName.c_str()); - if (!file.exists()) - throw Py::RuntimeError("File doesn't exist"); + Base::FileInfo file(EncodedName.c_str()); + if (!file.exists()) + throw Py::RuntimeError("File doesn't exist"); - App::Document *pcDoc; - if (DocName) - pcDoc = App::GetApplication().getDocument(DocName); - else - pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(DocName); + App::Document *pcDoc; + if (DocName) + pcDoc = App::GetApplication().getDocument(DocName); + else + pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(DocName); - try { - // read the gcode file - std::ifstream filestr(file.filePath().c_str()); - std::stringstream buffer; - buffer << filestr.rdbuf(); - std::string gcode = buffer.str(); - Toolpath path; - path.setFromGCode(gcode); - Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); - object->Path.setValue(path); - pcDoc->recompute(); - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } + try { + // read the gcode file + std::ifstream filestr(file.filePath().c_str()); + std::stringstream buffer; + buffer << filestr.rdbuf(); + std::string gcode = buffer.str(); + Toolpath path; + path.setFromGCode(gcode); + Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); + object->Path.setValue(path); + pcDoc->recompute(); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } - return Py::None(); - } + return Py::None(); + } - Py::Object show(const Py::Tuple& args) - { - PyObject *pcObj; - char *name = "Path"; - if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(PathPy::Type), &pcObj, &name)) - throw Py::Exception(); + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + char *name = "Path"; + if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(PathPy::Type), &pcObj, &name)) + throw Py::Exception(); - try { - App::Document *pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(); - PathPy* pPath = static_cast(pcObj); - Path::Feature *pcFeature = static_cast(pcDoc->addObject("Path::Feature", name)); - Path::Toolpath* pa = pPath->getToolpathPtr(); - if (!pa) { - throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid path"); - } + try { + App::Document *pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(); + PathPy* pPath = static_cast(pcObj); + Path::Feature *pcFeature = static_cast(pcDoc->addObject("Path::Feature", name)); + Path::Toolpath* pa = pPath->getToolpathPtr(); + if (!pa) { + throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid path"); + } - // copy the data - pcFeature->Path.setValue(*pa); - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } + // copy the data + pcFeature->Path.setValue(*pa); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } - return Py::None(); - } + return Py::None(); + } - Py::Object fromShape(const Py::Tuple& args) - { - PyObject *pcObj; - if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) - throw Py::Exception(); - TopoDS_Shape shape; - try { - if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) { - shape = static_cast(pcObj)->getTopoShapePtr()->getShape(); - } else { - throw Py::TypeError("the given object is not a shape"); - } - if (!shape.IsNull()) { - if (shape.ShapeType() == TopAbs_WIRE) { - Path::Toolpath result; - bool first = true; - Base::Placement last; + Py::Object fromShape(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) + throw Py::Exception(); + TopoDS_Shape shape; + try { + if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) { + shape = static_cast(pcObj)->getTopoShapePtr()->getShape(); + } else { + throw Py::TypeError("the given object is not a shape"); + } + if (!shape.IsNull()) { + if (shape.ShapeType() == TopAbs_WIRE) { + Path::Toolpath result; + bool first = true; + Base::Placement last; - TopExp_Explorer ExpEdges (shape,TopAbs_EDGE); - while (ExpEdges.More()) { - const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current()); - TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX); - bool vfirst = true; - while (ExpVerts.More()) { - const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current()); - gp_Pnt pnt = BRep_Tool::Pnt(vert); - Base::Placement tpl; - tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z())); - if (first) { - // add first point as a G0 move - Path::Command cmd; - std::ostringstream ctxt; - ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z; - cmd.setFromGCode(ctxt.str()); - result.addCommand(cmd); - first = false; - vfirst = false; - } else { - if (vfirst) - vfirst = false; - else { - Path::Command cmd; - cmd.setFromPlacement(tpl); + TopExp_Explorer ExpEdges (shape,TopAbs_EDGE); + while (ExpEdges.More()) { + const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current()); + TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX); + bool vfirst = true; + while (ExpVerts.More()) { + const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current()); + gp_Pnt pnt = BRep_Tool::Pnt(vert); + Base::Placement tpl; + tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z())); + if (first) { + // add first point as a G0 move + Path::Command cmd; + std::ostringstream ctxt; + ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z; + cmd.setFromGCode(ctxt.str()); + result.addCommand(cmd); + first = false; + vfirst = false; + } else { + if (vfirst) + vfirst = false; + else { + Path::Command cmd; + cmd.setFromPlacement(tpl); - // write arc data if needed - BRepAdaptor_Curve adapt(edge); - if (adapt.GetType() == GeomAbs_Circle) { - gp_Circ circ = adapt.Circle(); - gp_Pnt c = circ.Location(); - bool clockwise = false; - gp_Dir n = circ.Axis().Direction(); - if (n.Z() < 0) - clockwise = true; - Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z()); - // center coords must be relative to last point - center -= last.getPosition(); - cmd.setCenter(center,clockwise); - } - result.addCommand(cmd); - } - } - ExpVerts.Next(); - last = tpl; - } - ExpEdges.Next(); - } - return Py::asObject(new PathPy(new Path::Toolpath(result))); - } else { - throw Py::TypeError("the given shape must be a wire"); - } - } else { - throw Py::TypeError("the given shape is empty"); - } - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } - } + // write arc data if needed + BRepAdaptor_Curve adapt(edge); + if (adapt.GetType() == GeomAbs_Circle) { + gp_Circ circ = adapt.Circle(); + gp_Pnt c = circ.Location(); + bool clockwise = false; + gp_Dir n = circ.Axis().Direction(); + if (n.Z() < 0) + clockwise = true; + Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z()); + // center coords must be relative to last point + center -= last.getPosition(); + cmd.setCenter(center,clockwise); + } + result.addCommand(cmd); + } + } + ExpVerts.Next(); + last = tpl; + } + ExpEdges.Next(); + } + return Py::asObject(new PathPy(new Path::Toolpath(result))); + } else { + throw Py::TypeError("the given shape must be a wire"); + } + } else { + throw Py::TypeError("the given shape is empty"); + } + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + } - Py::Object fromShapes(const Py::Tuple& args, const Py::Dict &kwds) - { - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_PATH) - PyObject *pShapes=nullptr; - PyObject *start=nullptr; - PyObject *return_end=Py_False; - static char* kwd_list[] = {"shapes", "start", "return_end", - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_PATH), nullptr}; - if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), - "O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH), - kwd_list, &pShapes, &(Base::VectorPy::Type), &start, &PyBool_Type, &return_end, - PARAM_REF(PARAM_FARG,AREA_PARAMS_PATH))) - throw Py::Exception(); + Py::Object fromShapes(const Py::Tuple& args, const Py::Dict &kwds) + { + PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_PATH) + PyObject *pShapes=nullptr; + PyObject *start=nullptr; + PyObject *return_end=Py_False; + static char* kwd_list[] = {"shapes", "start", "return_end", + PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_PATH), nullptr}; + if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), + "O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH), + kwd_list, &pShapes, &(Base::VectorPy::Type), &start, &PyBool_Type, &return_end, + PARAM_REF(PARAM_FARG,AREA_PARAMS_PATH))) + throw Py::Exception(); - std::list shapes; - if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) - shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); - else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || - PyObject_TypeCheck(pShapes, &(PyTuple_Type))) - { - Py::Sequence shapeSeq(pShapes); - for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { - PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { - PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); - throw Py::Exception(); - } - shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); - } - } + std::list shapes; + if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) + shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); + else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || + PyObject_TypeCheck(pShapes, &(PyTuple_Type))) + { + Py::Sequence shapeSeq(pShapes); + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + throw Py::Exception(); + } + shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); + } + } - gp_Pnt pstart; - if(start) { - Base::Vector3d vec = static_cast(start)->value(); - pstart.SetCoord(vec.x, vec.y, vec.z); - } + gp_Pnt pstart; + if(start) { + Base::Vector3d vec = static_cast(start)->value(); + pstart.SetCoord(vec.x, vec.y, vec.z); + } - try { - gp_Pnt pend; - std::unique_ptr path(new Toolpath); - Area::toPath(*path,shapes,start?&pstart:nullptr, &pend, - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_PATH)); - if (!Base::asBoolean(return_end)) - return Py::asObject(new PathPy(path.release())); - Py::Tuple tuple(2); - tuple.setItem(0, Py::asObject(new PathPy(path.release()))); - tuple.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); - return tuple; - } PATH_CATCH - } + try { + gp_Pnt pend; + std::unique_ptr path(new Toolpath); + Area::toPath(*path,shapes,start?&pstart:nullptr, &pend, + PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_PATH)); + if (!Base::asBoolean(return_end)) + return Py::asObject(new PathPy(path.release())); + Py::Tuple tuple(2); + tuple.setItem(0, Py::asObject(new PathPy(path.release()))); + tuple.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); + return tuple; + } PATH_CATCH + } - Py::Object sortWires(const Py::Tuple& args, const Py::Dict &kwds) - { - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_ARC_PLANE) - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SORT) - PyObject *pShapes=nullptr; - PyObject *start=nullptr; - static char* kwd_list[] = {"shapes", "start", - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_ARC_PLANE), - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SORT), nullptr}; - if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), - "O|O!" - PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE) - PARAM_PY_KWDS(AREA_PARAMS_SORT), - kwd_list, &pShapes, &(Base::VectorPy::Type), &start, - PARAM_REF(PARAM_FARG,AREA_PARAMS_ARC_PLANE), - PARAM_REF(PARAM_FARG,AREA_PARAMS_SORT))) - throw Py::Exception(); + Py::Object sortWires(const Py::Tuple& args, const Py::Dict &kwds) + { + PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_ARC_PLANE) + PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SORT) + PyObject *pShapes=nullptr; + PyObject *start=nullptr; + static char* kwd_list[] = {"shapes", "start", + PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_ARC_PLANE), + PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SORT), nullptr}; + if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), + "O|O!" + PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE) + PARAM_PY_KWDS(AREA_PARAMS_SORT), + kwd_list, &pShapes, &(Base::VectorPy::Type), &start, + PARAM_REF(PARAM_FARG,AREA_PARAMS_ARC_PLANE), + PARAM_REF(PARAM_FARG,AREA_PARAMS_SORT))) + throw Py::Exception(); - std::list shapes; - if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) { - shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); - } - else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || - PyObject_TypeCheck(pShapes, &(PyTuple_Type))) { - Py::Sequence shapeSeq(pShapes); - for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { - PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { - PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); - throw Py::Exception(); - } - shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); - } - } + std::list shapes; + if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) { + shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); + } + else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || + PyObject_TypeCheck(pShapes, &(PyTuple_Type))) { + Py::Sequence shapeSeq(pShapes); + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + throw Py::Exception(); + } + shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); + } + } - gp_Pnt pstart,pend; - if(start) { - Base::Vector3d vec = static_cast(start)->value(); - pstart.SetCoord(vec.x, vec.y, vec.z); - } + gp_Pnt pstart,pend; + if(start) { + Base::Vector3d vec = static_cast(start)->value(); + pstart.SetCoord(vec.x, vec.y, vec.z); + } - try { - bool need_arc_plane = arc_plane==Area::ArcPlaneAuto; - std::list wires = Area::sortWires(shapes, start != nullptr, &pstart, - &pend, nullptr, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT)); - Py::List list; - for(auto &wire : wires) { - list.append(Part::shape2pyshape(TopoDS::Wire(wire))); - } + try { + bool need_arc_plane = arc_plane==Area::ArcPlaneAuto; + std::list wires = Area::sortWires(shapes, start != nullptr, &pstart, + &pend, nullptr, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT)); + Py::List list; + for(auto &wire : wires) { + list.append(Part::shape2pyshape(TopoDS::Wire(wire))); + } - Py::Tuple ret(need_arc_plane ? 3 : 2); - ret.setItem(0, list); - ret.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); - if (need_arc_plane) - ret.setItem(2, Py::Long(arc_plane)); + Py::Tuple ret(need_arc_plane ? 3 : 2); + ret.setItem(0, list); + ret.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); + if (need_arc_plane) + ret.setItem(2, Py::Long(arc_plane)); - return ret; - } PATH_CATCH - } -}; + return ret; + } PATH_CATCH + } + }; -PyObject* initModule() -{ - return Base::Interpreter().addModule(new Module); -} + PyObject* initModule() + { + return Base::Interpreter().addModule(new Module); + } } // namespace Path diff --git a/src/Mod/Path/App/VoronoiCellPy.xml b/src/Mod/Path/App/VoronoiCellPy.xml index 8a317a91bf..49fcdf33f2 100644 --- a/src/Mod/Path/App/VoronoiCellPy.xml +++ b/src/Mod/Path/App/VoronoiCellPy.xml @@ -3,6 +3,7 @@