Added toGeom for curved edges.
This commit is contained in:
committed by
sliptonic
parent
8f16b94669
commit
42b074c0dd
@@ -47,6 +47,8 @@ namespace Path
|
||||
~Voronoi();
|
||||
|
||||
static const int InvalidIndex = INT_MAX;
|
||||
static const int ColorMask = 0x07FFFFFF; // top 5 bits reserved internally
|
||||
|
||||
// types
|
||||
typedef double coordinate_type;
|
||||
typedef boost::polygon::point_data<coordinate_type> point_type;
|
||||
|
||||
@@ -115,13 +115,13 @@ VoronoiCell* getVoronoiCellFromPy(const VoronoiCellPy *c, PyObject *args = 0) {
|
||||
Py::Int VoronoiCellPy::getColor(void) const {
|
||||
VoronoiCell *c = getVoronoiCellPtr();
|
||||
if (c->isBound()) {
|
||||
return Py::Int(c->dia->cells()[c->index].color());
|
||||
return Py::Int(c->ptr->color() & Voronoi::ColorMask);
|
||||
}
|
||||
return Py::Int(0);
|
||||
}
|
||||
|
||||
void VoronoiCellPy::setColor(Py::Int color) {
|
||||
getCellFromPy(this)->color(int(color) & 0x0FFFFFFF);
|
||||
getCellFromPy(this)->color(int(color) & Voronoi::ColorMask);
|
||||
}
|
||||
|
||||
Py::Int VoronoiCellPy::getSourceIndex(void) const
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
<UserDocu>Returns true if edge goes through endpoint of the segment site</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getGeom" Const="true">
|
||||
<Methode Name="toGeom" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns true if edge goes through endpoint of the segment site</UserDocu>
|
||||
</Documentation>
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Base/VectorPy.h>
|
||||
#include <Mod/Part/App/LineSegmentPy.h>
|
||||
#include <Mod/Part/App/ArcOfParabolaPy.h>
|
||||
|
||||
// files generated out of VoronoiEdgePy.xml
|
||||
#include "VoronoiEdgePy.cpp"
|
||||
@@ -132,13 +133,13 @@ VoronoiEdge* getVoronoiEdgeFromPy(const VoronoiEdgePy *e, PyObject *args = 0) {
|
||||
Py::Int VoronoiEdgePy::getColor(void) const {
|
||||
VoronoiEdge *e = getVoronoiEdgePtr();
|
||||
if (e->isBound()) {
|
||||
return Py::Int(e->dia->edges()[e->index].color());
|
||||
return Py::Int(e->ptr->color() & Voronoi::ColorMask);
|
||||
}
|
||||
return Py::Int(0);
|
||||
}
|
||||
|
||||
void VoronoiEdgePy::setColor(Py::Int color) {
|
||||
getEdgeFromPy(this)->color(int(color) & 0x0FFFFFFF);
|
||||
getEdgeFromPy(this)->color(int(color) & Voronoi::ColorMask);
|
||||
}
|
||||
|
||||
Py::List VoronoiEdgePy::getVertices(void) const
|
||||
@@ -250,7 +251,7 @@ PyObject* VoronoiEdgePy::isSecondary(PyObject *args)
|
||||
}
|
||||
|
||||
namespace {
|
||||
Voronoi::point_type retrievPoint(Voronoi::diagram_type *dia, const Voronoi::diagram_type::cell_type *cell) {
|
||||
Voronoi::point_type retrievePoint(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) {
|
||||
@@ -270,7 +271,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* VoronoiEdgePy::getGeom(PyObject *args)
|
||||
PyObject* VoronoiEdgePy::toGeom(PyObject *args)
|
||||
{
|
||||
double z = 0.0;
|
||||
if (!PyArg_ParseTuple(args, "|d", &z)) {
|
||||
@@ -283,7 +284,7 @@ PyObject* VoronoiEdgePy::getGeom(PyObject *args)
|
||||
auto v0 = e->ptr->vertex0();
|
||||
auto v1 = e->ptr->vertex1();
|
||||
if (v0 && v1) {
|
||||
auto p = new Part::GeomLineSegment();
|
||||
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);
|
||||
}
|
||||
@@ -294,14 +295,14 @@ PyObject* VoronoiEdgePy::getGeom(PyObject *args)
|
||||
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);
|
||||
Voronoi::point_type p0 = retrievePoint(e->dia, c0);
|
||||
Voronoi::point_type p1 = retrievePoint(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);
|
||||
origin = c0->contains_segment() ? retrievePoint(e->dia, c1) : retrievePoint(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();
|
||||
@@ -330,10 +331,78 @@ PyObject* VoronoiEdgePy::getGeom(PyObject *args)
|
||||
end.x(origin.x() + direction.x() * k);
|
||||
end.y(origin.y() + direction.y() * k);
|
||||
}
|
||||
auto p = new Part::GeomLineSegment();
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
// parabolic curve, which is always formed by a point and an edge
|
||||
Voronoi::point_type point = e->ptr->cell()->contains_point() ? retrievePoint(e->dia, e->ptr->cell()) : retrievePoint(e->dia, e->ptr->twin()->cell());
|
||||
Voronoi::segment_type segment = e->ptr->cell()->contains_point() ? retrieveSegment(e->dia, e->ptr->twin()->cell()) : retrieveSegment(e->dia, e->ptr->cell());
|
||||
// the location is the mid point betwenn the normal on the segment through point
|
||||
// this is only the mid point of the segment if the parabola is symmetric
|
||||
Voronoi::point_type loc;
|
||||
{
|
||||
// move segment so it goes through the origin (s)
|
||||
Voronoi::point_type offset;
|
||||
{
|
||||
offset.x(low(segment).x());
|
||||
offset.y(low(segment).y());
|
||||
}
|
||||
Voronoi::point_type s;
|
||||
{
|
||||
s.x(high(segment).x() - offset.x());
|
||||
s.y(high(segment).y() - offset.y());
|
||||
}
|
||||
// move point accordingly so it maintains it's relation to s (p)
|
||||
Voronoi::point_type p;
|
||||
{
|
||||
p.x(point.x() - offset.x());
|
||||
p.y(point.y() - offset.y());
|
||||
}
|
||||
// calculate the orthogonal projection of p onto s
|
||||
// ((p dot s) / (s dot s)) * s (https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line)
|
||||
double proj = (p.x() * s.x() + p.y() * s.y()) / (s.x() * s.x() + s.y() * s.y());
|
||||
Voronoi::point_type p1;
|
||||
{
|
||||
p1.x(proj * s.x());
|
||||
p1.y(proj * s.y());
|
||||
}
|
||||
// finally ...
|
||||
// the location is the mid point between the projection on the segment and the point
|
||||
loc.x(((offset.x() + p1.x()) + point.x()) / 2);
|
||||
loc.y(((offset.y() + p1.y()) + point.y()) / 2);
|
||||
}
|
||||
Voronoi::point_type axis;
|
||||
{
|
||||
axis.x(point.x() - loc.x());
|
||||
axis.y(point.y() - loc.y());
|
||||
}
|
||||
auto p = new Part::GeomParabola;
|
||||
{
|
||||
p->setCenter(Base::Vector3d(point.x(), point.y(), z));
|
||||
p->setLocation(Base::Vector3d(loc.x(), loc.y(), z));
|
||||
p->setAngleXU(atan2(axis.y(), axis.x()));
|
||||
p->setFocal(sqrt(axis.x() * axis.x() + axis.y() * axis.y()));
|
||||
}
|
||||
auto a = new Part::GeomArcOfParabola;
|
||||
{
|
||||
a->setHandle(Handle(Geom_Parabola)::DownCast(p->handle()));
|
||||
|
||||
// figure out the arc parameters
|
||||
auto v0 = e->ptr->vertex0();
|
||||
auto v1 = e->ptr->vertex1();
|
||||
double param0 = 0;
|
||||
double param1 = 0;
|
||||
if (!p->closestParameter(Base::Vector3d(v0->x(), v0->y(), z), param0)) {
|
||||
std::cerr << "closestParameter(v0) failed" << std::endl;
|
||||
}
|
||||
if (!p->closestParameter(Base::Vector3d(v1->x(), v1->y(), z), param1)) {
|
||||
std::cerr << "closestParameter(v0) failed" << std::endl;
|
||||
}
|
||||
a->setRange(param0, param1, false);
|
||||
}
|
||||
return new Part::ArcOfParabolaPy(a);
|
||||
}
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</Documentation>
|
||||
<Parameter Name="IncidentEdge" Type="Object"/>
|
||||
</Attribute>
|
||||
<Methode Name="getGeom" Const="true">
|
||||
<Methode Name="toGeom" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns a Vertex - or None if not possible</UserDocu>
|
||||
</Documentation>
|
||||
|
||||
@@ -116,13 +116,13 @@ VoronoiVertex* getVoronoiVertexFromPy(const VoronoiVertexPy *v, PyObject *args =
|
||||
Py::Int VoronoiVertexPy::getColor(void) const {
|
||||
VoronoiVertex *v = getVoronoiVertexPtr();
|
||||
if (v->isBound()) {
|
||||
return Py::Int(v->ptr->color());
|
||||
return Py::Int(v->ptr->color() & Voronoi::ColorMask);
|
||||
}
|
||||
return Py::Int(0);
|
||||
}
|
||||
|
||||
void VoronoiVertexPy::setColor(Py::Int color) {
|
||||
getVertexFromPy(this)->color(int(color) & 0x0FFFFFFF);
|
||||
getVertexFromPy(this)->color(int(color) & Voronoi::ColorMask);
|
||||
}
|
||||
|
||||
Py::Float VoronoiVertexPy::getX(void) const
|
||||
@@ -140,7 +140,7 @@ Py::Object VoronoiVertexPy::getIncidentEdge() const {
|
||||
return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(v->dia, v->ptr->incident_edge())));
|
||||
}
|
||||
|
||||
PyObject* VoronoiVertexPy::getGeom(PyObject *args)
|
||||
PyObject* VoronoiVertexPy::toGeom(PyObject *args)
|
||||
{
|
||||
double z = 0.0;
|
||||
if (!PyArg_ParseTuple(args, "|d", &z)) {
|
||||
|
||||
Reference in New Issue
Block a user