Optimization of travel paths for fills
This commit is contained in:
parent
0cd10441a1
commit
415d1a5170
@ -42,7 +42,6 @@ Roadmap includes the following goals:
|
||||
* output some statistics;
|
||||
* allow the user to customize initial and final GCODE commands;
|
||||
* support material for internal perimeters;
|
||||
* travel path optimization;
|
||||
* ability to infill in the direction of bridges;
|
||||
* input object transform (scale, rotate, multiply);
|
||||
* cool;
|
||||
|
@ -10,6 +10,7 @@ sub debugf {
|
||||
|
||||
use Slic3r::ExtrusionLoop;
|
||||
use Slic3r::ExtrusionPath;
|
||||
use Slic3r::ExtrusionPath::Collection;
|
||||
use Slic3r::Fill;
|
||||
use Slic3r::Geometry;
|
||||
use Slic3r::Layer;
|
||||
@ -21,6 +22,7 @@ use Slic3r::Polyline::Closed;
|
||||
use Slic3r::Print;
|
||||
use Slic3r::STL;
|
||||
use Slic3r::Surface;
|
||||
use Slic3r::Surface::Collection;
|
||||
|
||||
# printer options
|
||||
our $nozzle_diameter = 0.45;
|
||||
@ -33,7 +35,7 @@ our $filament_packing_density = 0.85;
|
||||
|
||||
# speed options
|
||||
our $print_feed_rate = 60; # mm/sec
|
||||
our $travel_feed_rate = 80; # mm/sec
|
||||
our $travel_feed_rate = 130; # mm/sec
|
||||
our $bottom_layer_speed_ratio = 0.6;
|
||||
|
||||
# accuracy options
|
||||
|
@ -22,4 +22,16 @@ sub clip_end {
|
||||
}
|
||||
}
|
||||
|
||||
sub endpoints {
|
||||
my $self = shift;
|
||||
my ($as_arrayref) = @_;
|
||||
my @points = ($self->points->[0], $self->points->[-1]);
|
||||
return $as_arrayref ? map($_->p, @points) : @points;
|
||||
}
|
||||
|
||||
sub reverse {
|
||||
my $self = shift;
|
||||
@{$self->points} = reverse @{$self->points};
|
||||
}
|
||||
|
||||
1;
|
||||
|
55
lib/Slic3r/ExtrusionPath/Collection.pm
Normal file
55
lib/Slic3r/ExtrusionPath/Collection.pm
Normal file
@ -0,0 +1,55 @@
|
||||
package Slic3r::ExtrusionPath::Collection;
|
||||
use Moo;
|
||||
|
||||
use XXX;
|
||||
|
||||
has 'paths' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::ExtrusionPath]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
sub add {
|
||||
my $self = shift;
|
||||
my ($path) = @_;
|
||||
|
||||
push @{$self->paths}, $path;
|
||||
}
|
||||
|
||||
sub endpoints {
|
||||
my $self = shift;
|
||||
my ($as_arrayref) = @_;
|
||||
return map $_->endpoints($as_arrayref), @{$self->paths};
|
||||
}
|
||||
|
||||
sub shortest_path {
|
||||
my $self = shift;
|
||||
my ($start_near) = @_;
|
||||
|
||||
# get point as arrayref
|
||||
$start_near = $start_near->p if $start_near && ref $start_near ne 'ARRAY';
|
||||
|
||||
my @paths = ();
|
||||
my $start_at;
|
||||
CYCLE: while (@{$self->paths}) {
|
||||
# find nearest point
|
||||
$start_at = Slic3r::Point->cast(Slic3r::Geometry::nearest_point($start_near, [ $self->endpoints(1) ]));
|
||||
|
||||
# loop through paths to find the one that starts or ends at the point found
|
||||
PATH: for (my $i = 0; $i <= $#{$self->paths}; $i++) {
|
||||
if ($start_at->id eq $self->paths->[$i]->points->[0]->id) {
|
||||
push @paths, splice @{$self->paths}, $i, 1;
|
||||
} elsif ($start_at->id eq $self->paths->[$i]->points->[-1]->id) {
|
||||
$self->paths->[$i]->reverse;
|
||||
push @paths, splice @{$self->paths}, $i, 1;
|
||||
} else {
|
||||
next PATH;
|
||||
}
|
||||
$start_near = $paths[-1]->points->[-1]->p;
|
||||
next CYCLE;
|
||||
}
|
||||
}
|
||||
return @paths;
|
||||
}
|
||||
|
||||
1;
|
@ -21,8 +21,12 @@ sub make_fill {
|
||||
printf "Filling layer %d:\n", $layer->id;
|
||||
|
||||
my $max_print_dimension = $print->max_length;
|
||||
|
||||
my $n = 1;
|
||||
SURFACE: foreach my $surface (@{ $layer->fill_surfaces }) {
|
||||
foreach my $surface_collection (@{ $layer->fill_surfaces }) {
|
||||
my @path_collection = ();
|
||||
|
||||
SURFACE: foreach my $surface (@{ $surface_collection->surfaces }) {
|
||||
Slic3r::debugf " Processing surface %s:\n", $surface->id;
|
||||
my $polygon = $surface->mgp_polygon;
|
||||
|
||||
@ -158,8 +162,13 @@ sub make_fill {
|
||||
@paths = map $self->_mgp_from_points_ref($_)->move(map -$_, @shift)->rotate(-$rotate[0], $rotate[1])->points, @paths;
|
||||
}
|
||||
|
||||
push @path_collection, @paths;
|
||||
}
|
||||
|
||||
# save into layer
|
||||
FINISH: push @{ $layer->fills }, map Slic3r::ExtrusionPath->cast([ @$_ ]), @paths;
|
||||
FINISH: push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new(
|
||||
paths => [ map Slic3r::ExtrusionPath->cast([ @$_ ]), @path_collection ],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,7 @@ sub nearest_point {
|
||||
if (!defined $distance || $d < $distance) {
|
||||
$nearest_point = $p;
|
||||
$distance = $d;
|
||||
return $p if $distance < epsilon;
|
||||
}
|
||||
}
|
||||
return $nearest_point;
|
||||
|
@ -48,7 +48,8 @@ sub make_perimeter {
|
||||
}
|
||||
|
||||
# create one more offset to be used as boundary for fill
|
||||
push @{ $layer->fill_surfaces },
|
||||
push @{ $layer->fill_surfaces }, Slic3r::Surface::Collection->new(
|
||||
surfaces => [
|
||||
map Slic3r::Surface->new(
|
||||
surface_type => $surface->surface_type,
|
||||
contour => Slic3r::Polyline::Closed->cast($_->{outer}),
|
||||
@ -56,6 +57,8 @@ sub make_perimeter {
|
||||
map Slic3r::Polyline::Closed->cast($_), @{$_->{holes}}
|
||||
],
|
||||
), $self->offset_polygon($perimeters[-1]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
# generate paths for holes:
|
||||
|
@ -143,7 +143,7 @@ sub extrude_fills {
|
||||
$fill_extruder->make_fill($self, $layer);
|
||||
Slic3r::debugf " generated %d paths: %s\n",
|
||||
scalar @{ $layer->fills },
|
||||
join ' ', map $_->id, @{ $layer->fills } if $Slic3r::debug;
|
||||
join ' ', map $_->id, map @{$_->paths}, @{ $layer->fills } if $Slic3r::debug;
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,7 +286,10 @@ sub export_gcode {
|
||||
}
|
||||
|
||||
# extrude fills
|
||||
$Extrude->($_, 'fill') for @{ $layer->fills };
|
||||
for my $fill (@{ $layer->fills }) {
|
||||
my @paths = $fill->shortest_path($last_pos);
|
||||
$Extrude->($_, 'fill') for @paths;
|
||||
}
|
||||
}
|
||||
|
||||
# write end commands to file
|
||||
|
10
lib/Slic3r/Surface/Collection.pm
Normal file
10
lib/Slic3r/Surface/Collection.pm
Normal file
@ -0,0 +1,10 @@
|
||||
package Slic3r::Surface::Collection;
|
||||
use Moo;
|
||||
|
||||
has 'surfaces' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user