Ported chained_path() to XS
This commit is contained in:
parent
4d5d003ba7
commit
0516aac715
9 changed files with 74 additions and 31 deletions
|
@ -195,7 +195,7 @@ sub make_fill {
|
|||
}
|
||||
|
||||
# organize infill paths using a nearest-neighbor search
|
||||
@fills = @fills[ chained_path(\@fills_ordering_points) ];
|
||||
@fills = @fills[ @{chained_path(\@fills_ordering_points)} ];
|
||||
|
||||
return @fills;
|
||||
}
|
||||
|
|
|
@ -565,28 +565,6 @@ sub polyline_remove_short_segments {
|
|||
}
|
||||
}
|
||||
|
||||
# accepts an arrayref of points; it returns a list of indices
|
||||
# according to a nearest-neighbor walk
|
||||
sub chained_path {
|
||||
my ($items, $start_near) = @_;
|
||||
|
||||
my @points = @$items;
|
||||
my %indices = map { $points[$_] => $_ } 0 .. $#points;
|
||||
|
||||
my @result = ();
|
||||
if (!$start_near && @points) {
|
||||
$start_near = shift @points;
|
||||
push @result, $indices{$start_near};
|
||||
}
|
||||
while (@points) {
|
||||
my $idx = $start_near->nearest_point_index(\@points);
|
||||
($start_near) = splice @points, $idx, 1;
|
||||
push @result, $indices{$start_near};
|
||||
}
|
||||
|
||||
return @result;
|
||||
}
|
||||
|
||||
# accepts an arrayref; each item should be an arrayref whose first
|
||||
# item is the point to be used for the shortest path, and the second
|
||||
# one is the value to be returned in output (if the second item
|
||||
|
@ -594,13 +572,15 @@ sub chained_path {
|
|||
sub chained_path_items {
|
||||
my ($items, $start_near) = @_;
|
||||
|
||||
my @indices = chained_path([ map $_->[0], @$items ], $start_near);
|
||||
my @indices = defined($start_near)
|
||||
? @{chained_path_from([ map $_->[0], @$items ], $start_near)}
|
||||
: @{chained_path([ map $_->[0], @$items ])};
|
||||
return [ map $_->[1], @$items[@indices] ];
|
||||
}
|
||||
|
||||
sub chained_path_points {
|
||||
my ($points, $start_near) = @_;
|
||||
return [ @$points[ chained_path($points, $start_near) ] ];
|
||||
return [ @$points[ @{chained_path_from($points, $start_near)} ] ];
|
||||
}
|
||||
|
||||
sub douglas_peucker {
|
||||
|
|
|
@ -862,7 +862,7 @@ sub write_gcode {
|
|||
}
|
||||
} else {
|
||||
# order objects using a nearest neighbor search
|
||||
my @obj_idx = chained_path([ map Slic3r::Point->new(@{$_->copies->[0]}), @{$self->objects} ]);
|
||||
my @obj_idx = @{chained_path([ map Slic3r::Point->new(@{$_->copies->[0]}), @{$self->objects} ])};
|
||||
|
||||
# sort layers by Z
|
||||
my %layers = (); # print_z => [ [layers], [layers], [layers] ] by obj_idx
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,4 +20,21 @@ convex_hull(points)
|
|||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
std::vector<Points::size_type>
|
||||
chained_path(points)
|
||||
Points points
|
||||
CODE:
|
||||
chained_path(points, RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
std::vector<Points::size_type>
|
||||
chained_path_from(points, start_from)
|
||||
Points points
|
||||
Point* start_from
|
||||
CODE:
|
||||
chained_path(points, RETVAL, *start_from);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
std::vector<Points::size_type> T_STD_VECTOR_INT
|
||||
|
||||
ZTable* O_OBJECT
|
||||
TriangleMesh* O_OBJECT
|
||||
Point* O_OBJECT
|
||||
|
|
Loading…
Reference in a new issue