diff --git a/src/Mod/Path/App/Voronoi.cpp b/src/Mod/Path/App/Voronoi.cpp index 23b4895290..b24191d401 100644 --- a/src/Mod/Path/App/Voronoi.cpp +++ b/src/Mod/Path/App/Voronoi.cpp @@ -121,11 +121,11 @@ Voronoi::~Voronoi() void Voronoi::addPoint(const Voronoi::point_type &p) { - points.push_back(p); + vd->points.push_back(p); } void Voronoi::addSegment(const Voronoi::segment_type &s) { - segments.push_back(s); + vd->segments.push_back(s); } @@ -144,6 +144,6 @@ long Voronoi::numVertices() const { void Voronoi::construct() { vd->clear(); - construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), (voronoi_diagram_type*)vd); + construct_voronoi(vd->points.begin(), vd->points.end(), vd->segments.begin(), vd->segments.end(), (voronoi_diagram_type*)vd); vd->reIndex(); } diff --git a/src/Mod/Path/App/Voronoi.h b/src/Mod/Path/App/Voronoi.h index 76bdd9d506..4824948475 100644 --- a/src/Mod/Path/App/Voronoi.h +++ b/src/Mod/Path/App/Voronoi.h @@ -52,6 +52,7 @@ namespace Path 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 @@ -68,6 +69,9 @@ namespace Path void reIndex(); + std::vector points; + std::vector segments; + private: cell_map_type cell_index; edge_map_type edge_index; @@ -84,8 +88,6 @@ namespace Path long numVertices() const; // attributes - std::vector points; - std::vector segments; Base::Reference vd; }; diff --git a/src/Mod/Path/App/VoronoiCell.cpp b/src/Mod/Path/App/VoronoiCell.cpp index 37a2760737..9fef6eca9b 100644 --- a/src/Mod/Path/App/VoronoiCell.cpp +++ b/src/Mod/Path/App/VoronoiCell.cpp @@ -74,3 +74,21 @@ bool VoronoiCell::isBound(void) const { ptr = 0; return false; } + +Voronoi::point_type VoronoiCell::sourcePoint() const { + int index = ptr->source_index(); + int category = ptr->source_category(); + if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + return dia->points[index]; + } + if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + return low(dia->segments[index - dia->points.size()]); + } else { + return high(dia->segments[index - dia->points.size()]); + } +} + +Voronoi::segment_type VoronoiCell::sourceSegment() const { + return dia->segments[ptr->source_index() - dia->points.size()]; +} + diff --git a/src/Mod/Path/App/VoronoiCell.h b/src/Mod/Path/App/VoronoiCell.h index d45cf4c6bd..743538c71c 100644 --- a/src/Mod/Path/App/VoronoiCell.h +++ b/src/Mod/Path/App/VoronoiCell.h @@ -45,6 +45,9 @@ public: bool isBound(void) const; + Voronoi::point_type sourcePoint() const; + Voronoi::segment_type sourceSegment() const; + Base::Reference dia; long index; mutable const Voronoi::diagram_type::cell_type *ptr; diff --git a/src/Mod/Path/App/VoronoiEdgePy.xml b/src/Mod/Path/App/VoronoiEdgePy.xml index f6496e8edb..a43d0257c8 100644 --- a/src/Mod/Path/App/VoronoiEdgePy.xml +++ b/src/Mod/Path/App/VoronoiEdgePy.xml @@ -94,6 +94,10 @@ Returns true if edge goes through endpoint of the segment site - --> + + + Returns true if edge goes through endpoint of the segment site + + diff --git a/src/Mod/Path/App/VoronoiEdgePyImp.cpp b/src/Mod/Path/App/VoronoiEdgePyImp.cpp index 73ae0b65a1..4b4a6867bc 100644 --- a/src/Mod/Path/App/VoronoiEdgePyImp.cpp +++ b/src/Mod/Path/App/VoronoiEdgePyImp.cpp @@ -40,6 +40,7 @@ #include #include #include +#include // files generated out of VoronoiEdgePy.xml #include "VoronoiEdgePy.cpp" @@ -248,6 +249,96 @@ PyObject* VoronoiEdgePy::isSecondary(PyObject *args) return chk; } +namespace { + Voronoi::point_type retrievPoint(Voronoi::diagram_type *dia, const Voronoi::diagram_type::cell_type *cell) { + Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index(); + Voronoi::diagram_type::cell_type::source_category_type category = cell->source_category(); + if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + return dia->points[index]; + } + index -= dia->points.size(); + if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + return low(dia->segments[index]); + } else { + return high(dia->segments[index]); + } + } + + Voronoi::segment_type retrieveSegment(Voronoi::diagram_type *dia, const Voronoi::diagram_type::cell_type *cell) { + Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index() - dia->points.size(); + return dia->segments[index]; + } +} + +PyObject* VoronoiEdgePy::getGeom(PyObject *args) +{ + double z = 0.0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::RuntimeError("single argument of type double accepted"); + } + VoronoiEdge *e = getVoronoiEdgePtr(); + if (e->isBound()) { + if (e->ptr->is_linear()) { + if (e->ptr->is_finite()) { + auto v0 = e->ptr->vertex0(); + auto v1 = e->ptr->vertex1(); + if (v0 && v1) { + auto p = new Part::GeomLineSegment(); + p->setPoints(Base::Vector3d(v0->x(), v0->y(), z), Base::Vector3d(v1->x(), v1->y(), z)); + return new Part::LineSegmentPy(p); + } + } else { + // infinite linear, need to clip somehow + const Voronoi::diagram_type::cell_type *c0 = e->ptr->cell(); + const Voronoi::diagram_type::cell_type *c1 = e->ptr->twin()->cell(); + Voronoi::point_type origin; + Voronoi::point_type direction; + if (c0->contains_point() && c1->contains_point()) { + Voronoi::point_type p0 = retrievPoint(e->dia, c0); + Voronoi::point_type p1 = retrievPoint(e->dia, c1); + origin.x((p0.x() + p1.x()) / 2.); + origin.y((p0.y() + p1.y()) / 2.); + direction.x(p0.y() - p1.y()); + direction.y(p1.x() - p0.x()); + } else { + origin = c0->contains_segment() ? retrievPoint(e->dia, c1) : retrievPoint(e->dia, c0); + Voronoi::segment_type segment = c0->contains_segment() ? retrieveSegment(e->dia, c0) : retrieveSegment(e->dia, c1); + Voronoi::coordinate_type dx = high(segment).x() - low(segment).x(); + Voronoi::coordinate_type dy = high(segment).y() - low(segment).y(); + if ((low(segment) == origin) ^ c0->contains_point()) { + direction.x(dy); + direction.y(-dx); + } else { + direction.x(-dy); + direction.y(dx); + } + } + double k = 10.0; + Voronoi::point_type begin; + Voronoi::point_type end; + if (e->ptr->vertex0()) { + begin.x(e->ptr->vertex0()->x()); + begin.y(e->ptr->vertex0()->y()); + } else { + begin.x(origin.x() - direction.x() * k); + begin.y(origin.y() - direction.y() * k); + } + if (e->ptr->vertex1()) { + end.x(e->ptr->vertex1()->x()); + end.y(e->ptr->vertex1()->y()); + } else { + end.x(origin.x() + direction.x() * k); + end.y(origin.y() + direction.y() * k); + } + auto p = new Part::GeomLineSegment(); + p->setPoints(Base::Vector3d(begin.x(), begin.y(), z), Base::Vector3d(end.x(), end.y())); + return new Part::LineSegmentPy(p); + } + } + } + Py_INCREF(Py_None); + return Py_None; +} // custom attributes get/set diff --git a/src/Mod/Path/App/VoronoiPyImp.cpp b/src/Mod/Path/App/VoronoiPyImp.cpp index d90b4c7257..403961fc2e 100644 --- a/src/Mod/Path/App/VoronoiPyImp.cpp +++ b/src/Mod/Path/App/VoronoiPyImp.cpp @@ -51,7 +51,7 @@ std::string VoronoiPy::representation(void) const std::stringstream ss; ss.precision(5); ss << "Voronoi(" - << "{" << getVoronoiPtr()->segments.size() << ", " << getVoronoiPtr()->points.size() << "}" + << "{" << getVoronoiPtr()->vd->segments.size() << ", " << getVoronoiPtr()->vd->points.size() << "}" << " -> " << "{" << getVoronoiPtr()->numCells() << ", " << getVoronoiPtr()->numEdges() << ", " << getVoronoiPtr()->numVertices() << "}" << ")"; @@ -92,7 +92,7 @@ Voronoi::point_type getPointFromPy(PyObject *obj) { PyObject* VoronoiPy::addPoint(PyObject *args) { PyObject *obj = 0; if (PyArg_ParseTuple(args, "O", &obj)) { - getVoronoiPtr()->points.push_back(getPointFromPy(obj)); + getVoronoiPtr()->vd->points.push_back(getPointFromPy(obj)); } Py_INCREF(Py_None); return Py_None; @@ -105,7 +105,7 @@ PyObject* VoronoiPy::addSegment(PyObject *args) { if (PyArg_ParseTuple(args, "OO", &objBegin, &objEnd)) { auto p0 = getPointFromPy(objBegin); auto p1 = getPointFromPy(objEnd); - getVoronoiPtr()->segments.push_back(Voronoi::segment_type(p0, p1)); + getVoronoiPtr()->vd->segments.push_back(Voronoi::segment_type(p0, p1)); } Py_INCREF(Py_None); return Py_None; diff --git a/src/Mod/Path/App/VoronoiVertexPy.xml b/src/Mod/Path/App/VoronoiVertexPy.xml index 3f90b8b9fa..fa6917c4c5 100644 --- a/src/Mod/Path/App/VoronoiVertexPy.xml +++ b/src/Mod/Path/App/VoronoiVertexPy.xml @@ -40,5 +40,10 @@ + + + Returns a Vertex - or None if not possible + + diff --git a/src/Mod/Path/App/VoronoiVertexPyImp.cpp b/src/Mod/Path/App/VoronoiVertexPyImp.cpp index a26ab482fb..1d9f307735 100644 --- a/src/Mod/Path/App/VoronoiVertexPyImp.cpp +++ b/src/Mod/Path/App/VoronoiVertexPyImp.cpp @@ -140,6 +140,20 @@ Py::Object VoronoiVertexPy::getIncidentEdge() const { return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(v->dia, v->ptr->incident_edge()))); } +PyObject* VoronoiVertexPy::getGeom(PyObject *args) +{ + double z = 0.0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::RuntimeError("single argument of type double accepted"); + } + VoronoiVertex *v = getVoronoiVertexPtr(); + if (v->isBound()) { + return new Base::VectorPy(new Base::Vector3d(v->ptr->x(), v->ptr->y(), z)); + } + Py_INCREF(Py_None); + return Py_None; +} + // custom attributes get/set PyObject* VoronoiVertexPy::getCustomAttributes(const char* /*attr*/) const