Optimization of travel paths for fills
This commit is contained in:
parent
0cd10441a1
commit
415d1a5170
9 changed files with 230 additions and 136 deletions
|
@ -42,7 +42,6 @@ Roadmap includes the following goals:
|
||||||
* output some statistics;
|
* output some statistics;
|
||||||
* allow the user to customize initial and final GCODE commands;
|
* allow the user to customize initial and final GCODE commands;
|
||||||
* support material for internal perimeters;
|
* support material for internal perimeters;
|
||||||
* travel path optimization;
|
|
||||||
* ability to infill in the direction of bridges;
|
* ability to infill in the direction of bridges;
|
||||||
* input object transform (scale, rotate, multiply);
|
* input object transform (scale, rotate, multiply);
|
||||||
* cool;
|
* cool;
|
||||||
|
|
|
@ -10,6 +10,7 @@ sub debugf {
|
||||||
|
|
||||||
use Slic3r::ExtrusionLoop;
|
use Slic3r::ExtrusionLoop;
|
||||||
use Slic3r::ExtrusionPath;
|
use Slic3r::ExtrusionPath;
|
||||||
|
use Slic3r::ExtrusionPath::Collection;
|
||||||
use Slic3r::Fill;
|
use Slic3r::Fill;
|
||||||
use Slic3r::Geometry;
|
use Slic3r::Geometry;
|
||||||
use Slic3r::Layer;
|
use Slic3r::Layer;
|
||||||
|
@ -21,6 +22,7 @@ use Slic3r::Polyline::Closed;
|
||||||
use Slic3r::Print;
|
use Slic3r::Print;
|
||||||
use Slic3r::STL;
|
use Slic3r::STL;
|
||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
|
use Slic3r::Surface::Collection;
|
||||||
|
|
||||||
# printer options
|
# printer options
|
||||||
our $nozzle_diameter = 0.45;
|
our $nozzle_diameter = 0.45;
|
||||||
|
@ -33,7 +35,7 @@ our $filament_packing_density = 0.85;
|
||||||
|
|
||||||
# speed options
|
# speed options
|
||||||
our $print_feed_rate = 60; # mm/sec
|
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;
|
our $bottom_layer_speed_ratio = 0.6;
|
||||||
|
|
||||||
# accuracy options
|
# 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;
|
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;
|
printf "Filling layer %d:\n", $layer->id;
|
||||||
|
|
||||||
my $max_print_dimension = $print->max_length;
|
my $max_print_dimension = $print->max_length;
|
||||||
|
|
||||||
my $n = 1;
|
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;
|
Slic3r::debugf " Processing surface %s:\n", $surface->id;
|
||||||
my $polygon = $surface->mgp_polygon;
|
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;
|
@paths = map $self->_mgp_from_points_ref($_)->move(map -$_, @shift)->rotate(-$rotate[0], $rotate[1])->points, @paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
push @path_collection, @paths;
|
||||||
|
}
|
||||||
|
|
||||||
# save into layer
|
# 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) {
|
if (!defined $distance || $d < $distance) {
|
||||||
$nearest_point = $p;
|
$nearest_point = $p;
|
||||||
$distance = $d;
|
$distance = $d;
|
||||||
|
return $p if $distance < epsilon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $nearest_point;
|
return $nearest_point;
|
||||||
|
|
|
@ -48,7 +48,8 @@ sub make_perimeter {
|
||||||
}
|
}
|
||||||
|
|
||||||
# create one more offset to be used as boundary for fill
|
# 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(
|
map Slic3r::Surface->new(
|
||||||
surface_type => $surface->surface_type,
|
surface_type => $surface->surface_type,
|
||||||
contour => Slic3r::Polyline::Closed->cast($_->{outer}),
|
contour => Slic3r::Polyline::Closed->cast($_->{outer}),
|
||||||
|
@ -56,6 +57,8 @@ sub make_perimeter {
|
||||||
map Slic3r::Polyline::Closed->cast($_), @{$_->{holes}}
|
map Slic3r::Polyline::Closed->cast($_), @{$_->{holes}}
|
||||||
],
|
],
|
||||||
), $self->offset_polygon($perimeters[-1]),
|
), $self->offset_polygon($perimeters[-1]),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
# generate paths for holes:
|
# generate paths for holes:
|
||||||
|
|
|
@ -143,7 +143,7 @@ sub extrude_fills {
|
||||||
$fill_extruder->make_fill($self, $layer);
|
$fill_extruder->make_fill($self, $layer);
|
||||||
Slic3r::debugf " generated %d paths: %s\n",
|
Slic3r::debugf " generated %d paths: %s\n",
|
||||||
scalar @{ $layer->fills },
|
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 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
|
# 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 a new issue