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
|
# organize infill paths using a nearest-neighbor search
|
||||||
@fills = @fills[ chained_path(\@fills_ordering_points) ];
|
@fills = @fills[ @{chained_path(\@fills_ordering_points)} ];
|
||||||
|
|
||||||
return @fills;
|
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
|
# 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
|
# 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
|
# one is the value to be returned in output (if the second item
|
||||||
|
@ -594,13 +572,15 @@ sub chained_path {
|
||||||
sub chained_path_items {
|
sub chained_path_items {
|
||||||
my ($items, $start_near) = @_;
|
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] ];
|
return [ map $_->[1], @$items[@indices] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub chained_path_points {
|
sub chained_path_points {
|
||||||
my ($points, $start_near) = @_;
|
my ($points, $start_near) = @_;
|
||||||
return [ @$points[ chained_path($points, $start_near) ] ];
|
return [ @$points[ @{chained_path_from($points, $start_near)} ] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub douglas_peucker {
|
sub douglas_peucker {
|
||||||
|
|
|
@ -862,7 +862,7 @@ sub write_gcode {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
# order objects using a nearest neighbor search
|
# 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
|
# sort layers by Z
|
||||||
my %layers = (); # print_z => [ [layers], [layers], [layers] ] by obj_idx
|
my %layers = (); # print_z => [ [layers], [layers], [layers] ] by obj_idx
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
@ -50,4 +51,33 @@ convex_hull(Points points, Polygon &hull)
|
||||||
free(out_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 {
|
namespace Slic3r {
|
||||||
|
|
||||||
void convex_hull(Points points, Polygon &hull);
|
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
|
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;
|
int idx = -1;
|
||||||
double distance = -1; // double because long is limited to 2147483647 on some platforms and it's not enough
|
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
|
/* If the X distance of the candidate is > than the total distance of the
|
||||||
best previous candidate, we know we don't want it */
|
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 (distance != -1 && d > distance) continue;
|
||||||
|
|
||||||
/* If the Y distance of the candidate is > than the total distance of the
|
/* If the Y distance of the candidate is > than the total distance of the
|
||||||
best previous candidate, we know we don't want it */
|
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;
|
if (distance != -1 && d > distance) continue;
|
||||||
|
|
||||||
idx = it - points.begin();
|
idx = it - points.begin();
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace Slic3r {
|
||||||
class Line;
|
class Line;
|
||||||
class Point;
|
class Point;
|
||||||
typedef std::vector<Point> Points;
|
typedef std::vector<Point> Points;
|
||||||
|
typedef std::vector<Point*> PointPtrs;
|
||||||
|
|
||||||
class Point
|
class Point
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,8 @@ class Point
|
||||||
void rotate(double angle, Point* center);
|
void rotate(double angle, Point* center);
|
||||||
bool coincides_with(const Point &point) const;
|
bool coincides_with(const Point &point) const;
|
||||||
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;
|
Point* nearest_point(Points points) const;
|
||||||
double distance_to(const Point* point) const;
|
double distance_to(const Point* point) const;
|
||||||
double distance_to(const Line* line) const;
|
double distance_to(const Line* line) const;
|
||||||
|
|
|
@ -20,4 +20,21 @@ convex_hull(points)
|
||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
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
|
ZTable* O_OBJECT
|
||||||
TriangleMesh* O_OBJECT
|
TriangleMesh* O_OBJECT
|
||||||
Point* O_OBJECT
|
Point* O_OBJECT
|
||||||
|
|
Loading…
Add table
Reference in a new issue