diff --git a/src/Mod/Path/App/Voronoi.cpp b/src/Mod/Path/App/Voronoi.cpp index 96442ede5e..ddde461c7d 100644 --- a/src/Mod/Path/App/Voronoi.cpp +++ b/src/Mod/Path/App/Voronoi.cpp @@ -62,7 +62,33 @@ static void colorExterior(const Voronoi::diagram_type::edge_type *edge, std::siz } while (e != v->incident_edge()); } -// Constructors & destructors +// Voronoi::diagram_type + +Voronoi::diagram_type::diagram_type() + :scale(1000) +{ +} + +double Voronoi::diagram_type::getScale() const { + return scale; +} + +void Voronoi::diagram_type::setScale(double s) { + scale = s; +} + +Base::Vector3d Voronoi::diagram_type::scaledVector(double x, double y, double z) const { + return Base::Vector3d(x / scale, y / scale, z); +} + +Base::Vector3d Voronoi::diagram_type::scaledVector(const point_type &p, double z) const { + return scaledVector(p.x(), p.y(), z); +} + +Base::Vector3d Voronoi::diagram_type::scaledVector(const vertex_type &v, double z) const { + return scaledVector(v.x(), v.y(), z); +} + int Voronoi::diagram_type::index(const Voronoi::diagram_type::cell_type *cell) const { auto it = cell_index.find(intptr_t(cell)); @@ -106,6 +132,8 @@ void Voronoi::diagram_type::reIndex() { } } +// Voronoi + Voronoi::Voronoi() :vd(new diagram_type) { @@ -117,11 +145,27 @@ Voronoi::~Voronoi() void Voronoi::addPoint(const Voronoi::point_type &p) { - vd->points.push_back(p); + Voronoi::point_type pi; + pi.x(p.x() * vd->getScale()); + pi.y(p.y() * vd->getScale()); + vd->points.push_back(pi); } void Voronoi::addSegment(const Voronoi::segment_type &s) { - vd->segments.push_back(s); + Voronoi::point_type pil, pih; + pil.x(low(s).x() * vd->getScale()); + pil.y(low(s).y() * vd->getScale()); + pih.x(high(s).x() * vd->getScale()); + pih.y(high(s).y() * vd->getScale()); + vd->segments.push_back(segment_type(pil, pih)); +} + +long Voronoi::numPoints() const { + return vd->points.size(); +} + +long Voronoi::numSegments() const { + return vd->segments.size(); } diff --git a/src/Mod/Path/App/Voronoi.h b/src/Mod/Path/App/Voronoi.h index 586d8e0b23..7dec32604f 100644 --- a/src/Mod/Path/App/Voronoi.h +++ b/src/Mod/Path/App/Voronoi.h @@ -53,13 +53,21 @@ namespace Path 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; + typedef boost::polygon::voronoi_diagram voronoi_diagram_type; class diagram_type : public voronoi_diagram_type , public Base::Handled { public: + diagram_type(); + + double getScale() const; + void setScale(double s); + + Base::Vector3d scaledVector(double x, double y, double z) const; + Base::Vector3d scaledVector(const point_type &p, double z) const; + Base::Vector3d scaledVector(const vertex_type &v, double z) const; typedef std::map cell_map_type; typedef std::map edge_map_type; @@ -75,14 +83,16 @@ namespace Path std::vector segments; private: + double scale; cell_map_type cell_index; edge_map_type edge_index; vertex_map_type vertex_index; }; - // specific methods void addPoint(const point_type &p); void addSegment(const segment_type &p); + long numPoints() const; + long numSegments() const; void construct(); long numCells() const; @@ -92,10 +102,13 @@ namespace Path void colorExterior(int color); void colorTwins(int color); + template + T* create(int index) { + return new T(vd, index); + } + private: - // attributes Base::Reference vd; - friend class VoronoiPy; }; } //namespace Path diff --git a/src/Mod/Path/App/VoronoiEdgePyImp.cpp b/src/Mod/Path/App/VoronoiEdgePyImp.cpp index 0a3e062db5..4b3a2449a1 100644 --- a/src/Mod/Path/App/VoronoiEdgePyImp.cpp +++ b/src/Mod/Path/App/VoronoiEdgePyImp.cpp @@ -59,13 +59,13 @@ std::string VoronoiEdgePy::representation(void) const const Voronoi::diagram_type::vertex_type *v0 = e->ptr->vertex0(); const Voronoi::diagram_type::vertex_type *v1 = e->ptr->vertex1(); if (v0) { - ss << "[" << v0->x() << ", " << v0->y() << "]"; + ss << "[" << (v0->x() / e->dia->getScale()) << ", " << (v0->y() / e->dia->getScale()) << "]"; } else { ss << "[~]"; } ss << ", "; if (v1) { - ss << "[" << v1->x() << ", " << v1->y() << "]"; + ss << "[" << (v1->x() / e->dia->getScale()) << ", " << (v1->y() / e->dia->getScale()) << "]"; } else { ss << "[~]"; } @@ -315,7 +315,7 @@ PyObject* VoronoiEdgePy::toGeom(PyObject *args) 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)); + p->setPoints(e->dia->scaledVector(*v0, z), e->dia->scaledVector(*v1, z)); return new Part::LineSegmentPy(p); } } else { @@ -362,7 +362,7 @@ PyObject* VoronoiEdgePy::toGeom(PyObject *args) 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())); + p->setPoints(e->dia->scaledVector(begin, z), e->dia->scaledVector(end, z)); return new Part::LineSegmentPy(p); } } else { @@ -385,10 +385,10 @@ PyObject* VoronoiEdgePy::toGeom(PyObject *args) } auto p = new Part::GeomParabola; { - p->setCenter(Base::Vector3d(point.x(), point.y(), z)); - p->setLocation(Base::Vector3d(loc.x(), loc.y(), z)); + p->setCenter(e->dia->scaledVector(point, z)); + p->setLocation(e->dia->scaledVector(loc, z)); p->setAngleXU(atan2(axis.y(), axis.x())); - p->setFocal(sqrt(axis.x() * axis.x() + axis.y() * axis.y())); + p->setFocal(sqrt(axis.x() * axis.x() + axis.y() * axis.y()) / e->dia->getScale()); } auto a = new Part::GeomArcOfParabola; { @@ -399,10 +399,10 @@ PyObject* VoronoiEdgePy::toGeom(PyObject *args) auto v1 = e->ptr->vertex1(); double param0 = 0; double param1 = 0; - if (!p->closestParameter(Base::Vector3d(v0->x(), v0->y(), z), param0)) { + if (!p->closestParameter(e->dia->scaledVector(*v0, z), param0)) { std::cerr << "closestParameter(v0) failed" << std::endl; } - if (!p->closestParameter(Base::Vector3d(v1->x(), v1->y(), z), param1)) { + if (!p->closestParameter(e->dia->scaledVector(*v1, z), param1)) { std::cerr << "closestParameter(v0) failed" << std::endl; } a->setRange(param0, param1, false); @@ -417,22 +417,22 @@ PyObject* VoronoiEdgePy::toGeom(PyObject *args) namespace { - double distanceBetween(const Voronoi::diagram_type::vertex_type &v0, const Voronoi::point_type &p1) { + double distanceBetween(const Voronoi::diagram_type::vertex_type &v0, const Voronoi::point_type &p1, double scale) { double x = v0.x() - p1.x(); double y = v0.y() - p1.y(); - return sqrt(x * x + y * y); + return sqrt(x * x + y * y) / scale; } - void addDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::point_type &p1, Py::List *list) { + void addDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::point_type &p1, Py::List *list, double scale) { if (v0) { - list->append(Py::Float(distanceBetween(*v0, p1))); + list->append(Py::Float(distanceBetween(*v0, p1, scale))); } else { Py_INCREF(Py_None); list->append(Py::asObject(Py_None)); } } - void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::segment_type &segment, Py::List *list) { + void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::segment_type &segment, Py::List *list, double scale) { if (v0) { Voronoi::point_type p0; { @@ -440,32 +440,32 @@ namespace { p0.y(v0->y()); } Voronoi::point_type p1 = orthognalProjection(p0, segment); - list->append(Py::Float(distanceBetween(*v0, p1))); + list->append(Py::Float(distanceBetween(*v0, p1, scale))); } else { Py_INCREF(Py_None); list->append(Py::asObject(Py_None)); } } - bool addDistancesToPoint(const VoronoiEdge *edge, Voronoi::point_type p, Py::List *list) { - addDistanceBetween(edge->ptr->vertex0(), p, list); - addDistanceBetween(edge->ptr->vertex1(), p, list); + bool addDistancesToPoint(const VoronoiEdge *edge, Voronoi::point_type p, Py::List *list, double scale) { + addDistanceBetween(edge->ptr->vertex0(), p, list, scale); + addDistanceBetween(edge->ptr->vertex1(), p, list, scale); return true; } bool retrieveDistances(const VoronoiEdge *edge, Py::List *list) { const Voronoi::diagram_type::cell_type *c0 = edge->ptr->cell(); if (c0->contains_point()) { - return addDistancesToPoint(edge, retrievePoint(edge->dia, c0), list); + return addDistancesToPoint(edge, retrievePoint(edge->dia, c0), list, edge->dia->getScale()); } const Voronoi::diagram_type::cell_type *c1 = edge->ptr->twin()->cell(); if (c1->contains_point()) { - return addDistancesToPoint(edge, retrievePoint(edge->dia, c1), list); + return addDistancesToPoint(edge, retrievePoint(edge->dia, c1), list, edge->dia->getScale()); } // at this point both cells are sourced from segments and it does not matter which one we use Voronoi::segment_type segment = retrieveSegment(edge->dia, c0); - addProjectedDistanceBetween(edge->ptr->vertex0(), segment, list); - addProjectedDistanceBetween(edge->ptr->vertex1(), segment, list); + addProjectedDistanceBetween(edge->ptr->vertex0(), segment, list, edge->dia->getScale()); + addProjectedDistanceBetween(edge->ptr->vertex1(), segment, list, edge->dia->getScale()); return false; } } diff --git a/src/Mod/Path/App/VoronoiPyImp.cpp b/src/Mod/Path/App/VoronoiPyImp.cpp index 6c0bd9eafd..9ee460fdc8 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()->vd->segments.size() << ", " << getVoronoiPtr()->vd->points.size() << "}" + << "{" << getVoronoiPtr()->numSegments() << ", " << getVoronoiPtr()->numPoints() << "}" << " -> " << "{" << 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()->vd->points.push_back(getPointFromPy(obj)); + getVoronoiPtr()->addPoint(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()->vd->segments.push_back(Voronoi::segment_type(p0, p1)); + getVoronoiPtr()->addSegment(Voronoi::segment_type(p0, p1)); } Py_INCREF(Py_None); return Py_None; @@ -148,7 +148,7 @@ PyObject* VoronoiPy::numVertices(PyObject *args) 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)))); + list.append(Py::asObject(new VoronoiVertexPy(getVoronoiPtr()->create(i)))); } return list; } @@ -156,7 +156,7 @@ Py::List VoronoiPy::getVertices(void) const { Py::List VoronoiPy::getEdges(void) const { Py::List list; for (int i=0; inumEdges(); ++i) { - list.append(Py::asObject(new VoronoiEdgePy(new VoronoiEdge(getVoronoiPtr()->vd, i)))); + list.append(Py::asObject(new VoronoiEdgePy(getVoronoiPtr()->create(i)))); } return list; } @@ -164,7 +164,7 @@ Py::List VoronoiPy::getEdges(void) const { Py::List VoronoiPy::getCells(void) const { Py::List list; for (int i=0; inumCells(); ++i) { - list.append(Py::asObject(new VoronoiCellPy(new VoronoiCell(getVoronoiPtr()->vd, i)))); + list.append(Py::asObject(new VoronoiCellPy(getVoronoiPtr()->create(i)))); } return list; } diff --git a/src/Mod/Path/App/VoronoiVertexPyImp.cpp b/src/Mod/Path/App/VoronoiVertexPyImp.cpp index 7c14477fab..edd99a0d50 100644 --- a/src/Mod/Path/App/VoronoiVertexPyImp.cpp +++ b/src/Mod/Path/App/VoronoiVertexPyImp.cpp @@ -52,7 +52,7 @@ std::string VoronoiVertexPy::representation(void) const ss << "VoronoiVertex("; VoronoiVertex *v = getVoronoiVertexPtr(); if (v->isBound()) { - ss << "[" << v->ptr->x() << ", " << v->ptr->y() << "]"; + ss << "[" << (v->ptr->x() / v->dia->getScale()) << ", " << (v->ptr->y() / v->dia->getScale()) << "]"; } ss << ")"; return ss.str(); @@ -127,12 +127,14 @@ void VoronoiVertexPy::setColor(Py::Int color) { Py::Float VoronoiVertexPy::getX(void) const { - return Py::Float(getVoronoiVertexFromPy(this)->ptr->x()); + VoronoiVertex *v = getVoronoiVertexFromPy(this); + return Py::Float(v->ptr->x() / v->dia->getScale()); } Py::Float VoronoiVertexPy::getY(void) const { - return Py::Float(getVoronoiVertexFromPy(this)->ptr->y()); + VoronoiVertex *v = getVoronoiVertexFromPy(this); + return Py::Float(v->ptr->y() / v->dia->getScale()); } Py::Object VoronoiVertexPy::getIncidentEdge() const { @@ -148,7 +150,7 @@ PyObject* VoronoiVertexPy::toGeom(PyObject *args) } VoronoiVertex *v = getVoronoiVertexPtr(); if (v->isBound()) { - return new Base::VectorPy(new Base::Vector3d(v->ptr->x(), v->ptr->y(), z)); + return new Base::VectorPy(new Base::Vector3d(v->ptr->x() / v->dia->getScale(), v->ptr->y() / v->dia->getScale(), z)); } Py_INCREF(Py_None); return Py_None;