Organize perimeters with a nearest point search to avoid unnecessary travel moves. #21

This commit is contained in:
Alessandro Ranellucci 2011-11-07 15:40:09 +01:00
parent e860254780
commit 279bfbb10d
3 changed files with 35 additions and 1 deletions

View File

@ -29,7 +29,9 @@ sub shortest_path {
my $start_at;
CYCLE: while (@{$self->paths}) {
# find nearest point
$start_at = Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, [ $self->endpoints ]));
$start_at = $start_near
? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, [ $self->endpoints ]))
: $self->endpoints->[0];
# loop through paths to find the one that starts or ends at the point found
PATH: for (my $i = 0; $i <= $#{$self->paths}; $i++) {

View File

@ -17,6 +17,7 @@ our @EXPORT_OK = qw(
clip_segment_complex_polygon longest_segment angle3points
polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
polygon_remove_acute_vertices polygon_remove_parallel_continuous_edges
shortest_path
);
use Slic3r::Geometry::DouglasPeucker qw(Douglas_Peucker);
@ -611,4 +612,29 @@ sub polygon_remove_acute_vertices {
return polyline_remove_acute_vertices($points, 1);
}
# 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
# is not provided, the point will be returned)
sub shortest_path {
my ($items, $start_near) = @_;
my %values = map +($_->[0] => $_->[1] || $_->[0]), @$items;
my @points = map $_->[0], @$items;
my $result = [];
my $last_point;
if (!$start_near) {
$start_near = shift @points;
push @$result, $values{$start_near} if $start_near;
}
while (@points) {
$start_near = nearest_point($start_near, [@points]);
@points = grep $_ ne $start_near, @points;
push @$result, $values{$start_near};
}
return $result;
}
1;

View File

@ -3,6 +3,7 @@ use Moo;
use Math::Clipper ':all';
use Math::ConvexHull 1.0.4 qw(convex_hull);
use Slic3r::Geometry qw(shortest_path);
use XXX;
use constant X => 0;
@ -31,6 +32,11 @@ sub make_perimeter {
# )
my @perimeters = (); # one item per depth; each item
# organize $layer->perimeter_surfaces using a shortest path search
@{ $layer->perimeter_surfaces } = @{shortest_path([
map [ $_->contour->points->[0], $_ ], @{ $layer->perimeter_surfaces },
])};
foreach my $surface (@{ $layer->perimeter_surfaces }) {
# the outer loop must be offsetted by half extrusion width inwards
my @last_offsets = ($surface->expolygon);