Ported chained_path() to XS

This commit is contained in:
Alessandro Ranellucci 2013-11-23 21:39:05 +01:00
parent 4d5d003ba7
commit 0516aac715
9 changed files with 74 additions and 31 deletions

View file

@ -1,5 +1,6 @@
#include "Geometry.hpp"
#include <algorithm>
#include <map>
namespace Slic3r {
@ -50,4 +51,33 @@ convex_hull(Points points, Polygon &hull)
free(out_hull);
}
/* accepts an arrayref of points and returns a list of indices
according to a nearest-neighbor walk */
void
chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near)
{
PointPtrs my_points;
std::map<Point*,Points::size_type> indices;
my_points.reserve(points.size());
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
my_points.push_back(&*it);
indices[&*it] = it - points.begin();
}
retval.reserve(points.size());
while (!my_points.empty()) {
Points::size_type idx = start_near.nearest_point_index(my_points);
start_near = *my_points[idx];
retval.push_back(indices[ my_points[idx] ]);
my_points.erase(my_points.begin() + idx);
}
}
void
chained_path(Points &points, std::vector<Points::size_type> &retval)
{
if (points.empty()) return; // can't call front() on empty vector
chained_path(points, retval, points.front());
}
}

View file

@ -6,6 +6,8 @@
namespace Slic3r {
void convex_hull(Points points, Polygon &hull);
void chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near);
void chained_path(Points &points, std::vector<Points::size_type> &retval);
}

View file

@ -40,20 +40,30 @@ Point::coincides_with(const Point &point) const
}
int
Point::nearest_point_index(const Points points) const
Point::nearest_point_index(Points &points) const
{
PointPtrs p;
p.reserve(points.size());
for (Points::iterator it = points.begin(); it != points.end(); ++it)
p.push_back(&*it);
return this->nearest_point_index(p);
}
int
Point::nearest_point_index(PointPtrs &points) const
{
int idx = -1;
double distance = -1; // double because long is limited to 2147483647 on some platforms and it's not enough
for (Points::const_iterator it = points.begin(); it != points.end(); ++it) {
for (PointPtrs::const_iterator it = points.begin(); it != points.end(); ++it) {
/* If the X distance of the candidate is > than the total distance of the
best previous candidate, we know we don't want it */
double d = pow(this->x - (*it).x, 2);
double d = pow(this->x - (*it)->x, 2);
if (distance != -1 && d > distance) continue;
/* If the Y distance of the candidate is > than the total distance of the
best previous candidate, we know we don't want it */
d += pow(this->y - (*it).y, 2);
d += pow(this->y - (*it)->y, 2);
if (distance != -1 && d > distance) continue;
idx = it - points.begin();

View file

@ -10,6 +10,7 @@ namespace Slic3r {
class Line;
class Point;
typedef std::vector<Point> Points;
typedef std::vector<Point*> PointPtrs;
class Point
{
@ -22,7 +23,8 @@ class Point
void rotate(double angle, Point* center);
bool coincides_with(const Point &point) const;
bool coincides_with(const Point* point) const;
int nearest_point_index(const Points points) const;
int nearest_point_index(Points &points) const;
int nearest_point_index(PointPtrs &points) const;
Point* nearest_point(Points points) const;
double distance_to(const Point* point) const;
double distance_to(const Line* line) const;