From 04cf9c2e4630ba84d9fabdd1a39e9e3f9d528bc7 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Wed, 2 Sep 2020 19:23:11 -0700 Subject: [PATCH] Added python bindings for voronoi diagram construction and accessing the resulting vertices. --- src/Mod/Path/App/AppPath.cpp | 8 ++ src/Mod/Path/App/CMakeLists.txt | 10 ++ src/Mod/Path/App/Voronoi.cpp | 106 +++++++++++++++ src/Mod/Path/App/Voronoi.h | 76 +++++++++++ src/Mod/Path/App/VoronoiPy.xml | 69 ++++++++++ src/Mod/Path/App/VoronoiPyImp.cpp | 164 ++++++++++++++++++++++++ src/Mod/Path/App/VoronoiVertex.cpp | 52 ++++++++ src/Mod/Path/App/VoronoiVertex.h | 52 ++++++++ src/Mod/Path/App/VoronoiVertexPy.xml | 46 +++++++ src/Mod/Path/App/VoronoiVertexPyImp.cpp | 151 ++++++++++++++++++++++ 10 files changed, 734 insertions(+) create mode 100644 src/Mod/Path/App/Voronoi.cpp create mode 100644 src/Mod/Path/App/Voronoi.h create mode 100644 src/Mod/Path/App/VoronoiPy.xml create mode 100644 src/Mod/Path/App/VoronoiPyImp.cpp create mode 100644 src/Mod/Path/App/VoronoiVertex.cpp create mode 100644 src/Mod/Path/App/VoronoiVertex.h create mode 100644 src/Mod/Path/App/VoronoiVertexPy.xml create mode 100644 src/Mod/Path/App/VoronoiVertexPyImp.cpp diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp index 3e08c68046..e5de2bb0ad 100644 --- a/src/Mod/Path/App/AppPath.cpp +++ b/src/Mod/Path/App/AppPath.cpp @@ -46,6 +46,10 @@ #include "FeaturePathShape.h" #include "AreaPy.h" #include "FeatureArea.h" +#include "Voronoi.h" +#include "VoronoiPy.h" +#include "VoronoiVertex.h" +#include "VoronoiVertexPy.h" namespace Path { extern PyObject* initModule(); @@ -72,6 +76,8 @@ PyMOD_INIT_FUNC(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, "Voronoi"); + Base::Interpreter().addType(&Path::VoronoiVertexPy ::Type, pathModule, "VoronoiVertex"); // NOTE: To finish the initialization of our own type objects we must // call PyType_Ready, otherwise we run into a segmentation fault, later on. @@ -94,6 +100,8 @@ PyMOD_INIT_FUNC(Path) Path::FeatureAreaPython ::init(); Path::FeatureAreaView ::init(); Path::FeatureAreaViewPython ::init(); + Path::Voronoi ::init(); + Path::VoronoiVertex ::init(); PyMOD_Return(pathModule); } diff --git a/src/Mod/Path/App/CMakeLists.txt b/src/Mod/Path/App/CMakeLists.txt index 2cee9a3a3a..0ede609c42 100644 --- a/src/Mod/Path/App/CMakeLists.txt +++ b/src/Mod/Path/App/CMakeLists.txt @@ -36,6 +36,8 @@ generate_from_xml(TooltablePy) generate_from_xml(FeaturePathCompoundPy) generate_from_xml(AreaPy) generate_from_xml(FeatureAreaPy) +generate_from_xml(VoronoiPy) +generate_from_xml(VoronoiVertexPy) SET(Python_SRCS CommandPy.xml @@ -52,6 +54,10 @@ SET(Python_SRCS AreaPyImp.cpp FeatureAreaPy.xml FeatureAreaPyImp.cpp + VoronoiPy.xml + VoronoiPyImp.cpp + VoronoiVertexPy.xml + VoronoiVertexPyImp.cpp ) SET(Mod_SRCS @@ -90,6 +96,10 @@ SET(Path_SRCS FeatureArea.h PathSegmentWalker.h PathSegmentWalker.cpp + Voronoi.cpp + Voronoi.h + VoronoiVertex.cpp + VoronoiVertex.h ${Mod_SRCS} ${Python_SRCS} ) diff --git a/src/Mod/Path/App/Voronoi.cpp b/src/Mod/Path/App/Voronoi.cpp new file mode 100644 index 0000000000..19558034c9 --- /dev/null +++ b/src/Mod/Path/App/Voronoi.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +#endif + +#include +#include +#include +#include +#include "Voronoi.h" + +using namespace Base; +using namespace Path; + +TYPESYSTEM_SOURCE(Path::Voronoi , Base::BaseClass); + +// Helpers + +#if 0 +static const std::size_t EXTERNAL_COLOR = 1; + +static void color_exterior(const Voronoi::diagram_type::edge_type *edge) { + if (edge->color() == EXTERNAL_COLOR) { + // end recursion + return; + } + edge->color(EXTERNAL_COLOR); + edge->twin()->color(EXTERNAL_COLOR); + auto v = edge->vertex1(); + if (v == NULL || !edge->is_primary()) { + return; + } + v->color(EXTERNAL_COLOR); + auto e = v->incident_edge(); + do { + color_exterior(e); + e = e->rot_next(); + } while (e != v->incident_edge()); +} +#endif + +// Constructors & destructors + +Voronoi::Voronoi() + :vd(new diagram_type) +{ +} + +Voronoi::~Voronoi() +{ +} + + +void Voronoi::addPoint(const Voronoi::point_type &p) { + points.push_back(p); +} + +void Voronoi::addSegment(const Voronoi::segment_type &s) { + segments.push_back(s); +} + + +long Voronoi::numCells() const { + return vd->num_cells(); +} + +long Voronoi::numEdges() const { + return vd->num_edges(); +} + +long Voronoi::numVertices() const { + return vd->num_vertices(); +} + +void Voronoi::construct() +{ + vd->clear(); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), (voronoi_diagram_type*)vd); +} diff --git a/src/Mod/Path/App/Voronoi.h b/src/Mod/Path/App/Voronoi.h new file mode 100644 index 0000000000..716256db68 --- /dev/null +++ b/src/Mod/Path/App/Voronoi.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ +#ifndef PATH_VORONOI_H +#define PATH_VORONOI_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace Path +{ + class PathExport Voronoi + : public Base::BaseClass + { + TYPESYSTEM_HEADER(); + + public: + //constructors + Voronoi(); + ~Voronoi(); + + // types + typedef double coordinate_type; + typedef boost::polygon::point_data point_type; + typedef boost::polygon::segment_data segment_type; + typedef boost::polygon::voronoi_diagram voronoi_diagram_type; + class diagram_type + : public voronoi_diagram_type + , public Base::Handled + { }; + + // specific methods + void addPoint(const point_type &p); + void addSegment(const segment_type &p); + + void construct(); + long numCells() const; + long numEdges() const; + long numVertices() const; + + // attributes + std::vector points; + std::vector segments; + Base::Reference vd; + }; + +} //namespace Path + +#endif // PATH_VORONOI_H diff --git a/src/Mod/Path/App/VoronoiPy.xml b/src/Mod/Path/App/VoronoiPy.xml new file mode 100644 index 0000000000..f6e46a37de --- /dev/null +++ b/src/Mod/Path/App/VoronoiPy.xml @@ -0,0 +1,69 @@ + + + + + + Voronoi([segments]): Create voronoi for given collection of line segments + + + + + List of all vertices of the voronoi diagram + + + + + + Return number of cells + + + + + Return number of edges + + + + + Return number of vertices + + + + + addPoint(vector|vector2d) add given point to input collection + + + + + addSegment(vector|vector2d, vector|vector2d) add given segment to input collection + + + + + constructs the voronoi diagram from the input collections + + + + diff --git a/src/Mod/Path/App/VoronoiPyImp.cpp b/src/Mod/Path/App/VoronoiPyImp.cpp new file mode 100644 index 0000000000..95d4dd2902 --- /dev/null +++ b/src/Mod/Path/App/VoronoiPyImp.cpp @@ -0,0 +1,164 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + + +#ifndef _PreComp_ +# include +#endif + +#include "Mod/Path/App/Voronoi.h" +#include "Mod/Path/App/VoronoiVertex.h" +#include +#include +#include +#include + +// files generated out of VoronoiPy.xml +#include "VoronoiPy.h" +#include "VoronoiPy.cpp" +#include "VoronoiVertexPy.h" + +using namespace Path; + +// returns a string which represents the object e.g. when printed in python +std::string VoronoiPy::representation(void) const +{ + std::stringstream ss; + ss.precision(5); + ss << "Voronoi(" + << "{" << getVoronoiPtr()->segments.size() << ", " << getVoronoiPtr()->points.size() << "}" + << " -> " + << "{" << getVoronoiPtr()->numCells() << ", " << getVoronoiPtr()->numEdges() << ", " << getVoronoiPtr()->numVertices() << "}" + << ")"; + return ss.str(); +} + + +PyObject *VoronoiPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of VoronoiPy and its twin object + return new VoronoiPy(new Voronoi); +} + +// constructor +int VoronoiPy::PyInit(PyObject* args, PyObject* /*kwds*/) +{ + if (!PyArg_ParseTuple(args, "")) { + PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); + return -1; + } + return 0; +} + +Voronoi::point_type getPointFromPy(PyObject *obj) { + if (obj) { + if (PyObject_TypeCheck(obj, &Base::VectorPy::Type)) { + Base::Vector3d *vect = (static_cast(obj))->getVectorPtr(); + return Voronoi::point_type(vect->x, vect->y); + } else if (PyObject_TypeCheck(obj, Base::Vector2dPy::type_object())) { + Base::Vector2d vect = Py::toVector2d(obj); + return Voronoi::point_type(vect.x, vect.y); + } + } + throw Py::TypeError("Points must be Base::Vector or Base::Vector2d"); + return Voronoi::point_type(); +} + +PyObject* VoronoiPy::addPoint(PyObject *args) { + PyObject *obj = 0; + if (PyArg_ParseTuple(args, "O", &obj)) { + getVoronoiPtr()->points.push_back(getPointFromPy(obj)); + } + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::addSegment(PyObject *args) { + PyObject *objBegin = 0; + PyObject *objEnd = 0; + + if (PyArg_ParseTuple(args, "OO", &objBegin, &objEnd)) { + auto p0 = getPointFromPy(objBegin); + auto p1 = getPointFromPy(objEnd); + getVoronoiPtr()->segments.push_back(Voronoi::segment_type(p0, p1)); + } + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::construct(PyObject *args) { + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + getVoronoiPtr()->construct(); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::numCells(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numCells()); +} + +PyObject* VoronoiPy::numEdges(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numEdges()); +} + +PyObject* VoronoiPy::numVertices(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numVertices()); +} + +Py::List VoronoiPy::getVertices(void) const { + Py::List list; + for (int i=0; inumVertices(); ++i) { + list.append(Py::asObject(new VoronoiVertexPy(new VoronoiVertex(getVoronoiPtr()->vd, i)))); + } + return list; +} + +// custom attributes get/set + +PyObject *VoronoiPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int VoronoiPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + + diff --git a/src/Mod/Path/App/VoronoiVertex.cpp b/src/Mod/Path/App/VoronoiVertex.cpp new file mode 100644 index 0000000000..ce1f69164c --- /dev/null +++ b/src/Mod/Path/App/VoronoiVertex.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +#endif + +#include +#include +#include +#include +#include "Voronoi.h" +#include "VoronoiVertex.h" + +using namespace Base; +using namespace Path; + +TYPESYSTEM_SOURCE(Path::VoronoiVertex , Base::Persistence) + +VoronoiVertex::VoronoiVertex(Voronoi::diagram_type *d, long index) + : dia(d) + , index(index) +{ +} + +VoronoiVertex::~VoronoiVertex() { +} diff --git a/src/Mod/Path/App/VoronoiVertex.h b/src/Mod/Path/App/VoronoiVertex.h new file mode 100644 index 0000000000..ab9083dd67 --- /dev/null +++ b/src/Mod/Path/App/VoronoiVertex.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ +#ifndef PATH_VORONOIVERTEX_H +#define PATH_VORONOIVERTEX_H + +#include +#include +#include +#include +#include "Voronoi.h" + +namespace Path +{ + +class Voronoi; + +class PathExport VoronoiVertex + : public Base::BaseClass +{ + TYPESYSTEM_HEADER(); +public: + + VoronoiVertex(Voronoi::diagram_type* dia = 0, long index = INT_MAX); + ~VoronoiVertex(); + + bool isBound(void) const { return dia.isValid() && index != INT_MAX; } + + Base::Reference dia; + long index; +}; + +} +#endif diff --git a/src/Mod/Path/App/VoronoiVertexPy.xml b/src/Mod/Path/App/VoronoiVertexPy.xml new file mode 100644 index 0000000000..515d849b32 --- /dev/null +++ b/src/Mod/Path/App/VoronoiVertexPy.xml @@ -0,0 +1,46 @@ + + + + + + Vertex of a Voronoi diagram + + + + Assigned color of the receiver. + + + + + + X position + + + + + + Y position + + + + + + diff --git a/src/Mod/Path/App/VoronoiVertexPyImp.cpp b/src/Mod/Path/App/VoronoiVertexPyImp.cpp new file mode 100644 index 0000000000..1dc3c71751 --- /dev/null +++ b/src/Mod/Path/App/VoronoiVertexPyImp.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (c) sliptonic (shopinthewoods@gmail.com) 2020 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + + +#ifndef _PreComp_ +# include +#endif + +#include "Mod/Path/App/Voronoi.h" +#include "Mod/Path/App/VoronoiVertex.h" +#include +#include +#include +#include +#include + +// files generated out of VoronoiVertexPy.xml +#include "VoronoiPy.h" +#include "VoronoiVertexPy.h" +#include "VoronoiVertexPy.cpp" + +using namespace Path; + +// returns a string which represents the object e.g. when printed in python +std::string VoronoiVertexPy::representation(void) const +{ + std::stringstream ss; + ss.precision(5); + ss << "VoronoiVertex("; + VoronoiVertex *v = getVoronoiVertexPtr(); + if (v->isBound()) { + Voronoi::diagram_type::vertex_type pt = v->dia->vertices()[v->index]; + ss << "[" << pt.x() << ", " << pt.y() << "]"; + } + ss << ")"; + return ss.str(); +} + +PyObject *VoronoiVertexPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of VoronoiVertexPy and the Twin object + return new VoronoiVertexPy(new VoronoiVertex); +} + +// constructor method +int VoronoiVertexPy::PyInit(PyObject* args, PyObject* /*kwd*/) +{ + if (!PyArg_ParseTuple(args, "")) { + PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); + return -1; + } + return 0; +} + + +PyObject* VoronoiVertexPy::richCompare(PyObject *lhs, PyObject *rhs, int op) { + PyObject *cmp = Py_False; + if ( PyObject_TypeCheck(lhs, &VoronoiVertexPy::Type) + && PyObject_TypeCheck(rhs, &VoronoiVertexPy::Type) + && op == Py_EQ) { + const VoronoiVertex *vl = static_cast(lhs)->getVoronoiVertexPtr(); + const VoronoiVertex *vr = static_cast(rhs)->getVoronoiVertexPtr(); + if (vl->index == vr->index && &(*vl->dia) == &(*vr->dia)) { + cmp = Py_True; + } + } + Py_INCREF(cmp); + return cmp; +} + +const Voronoi::voronoi_diagram_type::vertex_type* getVertexFromPy(VoronoiVertexPy *v, bool throwIfNotBound = true) { + auto self = v->getVoronoiVertexPtr(); + if (self->isBound()) { + return &self->dia->vertices()[self->index]; + } + if (throwIfNotBound) { + throw Py::TypeError("Vertex not bound to voronoi diagram"); + } + return 0; +} + +Py::Int VoronoiVertexPy::getColor(void) const { + VoronoiVertex *v = getVoronoiVertexPtr(); + if (v->isBound()) { + return Py::Int(v->dia->vertices()[v->index].color()); + } + return Py::Int(0); +} + +void VoronoiVertexPy::setColor(Py::Int color) { + getVertexFromPy(this)->color(int(color) & 0x0FFFFFFF); +} + +Py::Float VoronoiVertexPy::getX(void) const +{ + VoronoiVertex *v = getVoronoiVertexPtr(); + if (!v->isBound()) { + throw Py::FloatingPointError("Cannot get coordinates of unbound voronoi vertex"); + } + return Py::Float(v->dia->vertices()[v->index].x()); +} + +Py::Float VoronoiVertexPy::getY(void) const +{ + VoronoiVertex *v = getVoronoiVertexPtr(); + if (!v->isBound()) { + throw Py::FloatingPointError("Cannot get coordinates of unbound voronoi vertex"); + } + return Py::Float(v->dia->vertices()[v->index].y()); +} + +#if 0 +Py::Object VoronoiVertexPy::getIncidentEdge() const { + Py_INCREF(Py_None); + return Py_None; +} +#endif + +// custom attributes get/set + +PyObject* VoronoiVertexPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int VoronoiVertexPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} +