diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 84622b80f..ae2ae7aa2 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -163,10 +163,11 @@ sub extrude_path { my $gcode = ""; # skip retract for support material - if ($path->role != EXTR_ROLE_SUPPORTMATERIAL) { + { # retract if distance from previous position is greater or equal to the one specified by the user my $travel = Slic3r::Line->new($self->last_pos->clone, $path->points->[0]->clone); - if ($travel->length >= scale $self->extruder->retract_before_travel) { + if ($travel->length >= scale $self->extruder->retract_before_travel + && ($path->role != EXTR_ROLE_SUPPORTMATERIAL || !$self->layer->support_islands_enclose_line($travel))) { # move travel back to original layer coordinates. # note that we're only considering the current object's islands, while we should # build a more complete configuration space diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 0a0213a0b..80b712a64 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -1,6 +1,7 @@ package Slic3r::Layer; use Moo; +use List::Util qw(first); use Slic3r::Geometry::Clipper qw(union_ex); has 'id' => (is => 'rw', required => 1, trigger => 1); # sequential number of layer, 0-based @@ -18,6 +19,7 @@ has 'flow' => (is => 'ro', default => sub { $Slic3r::flow }); has 'slices' => (is => 'rw'); # ordered collection of extrusion paths to fill surfaces for support material +has 'support_islands' => (is => 'rw'); has 'support_fills' => (is => 'rw'); has 'support_interface_fills' => (is => 'rw'); @@ -102,4 +104,10 @@ sub make_perimeters { $_->make_perimeters for @{$self->regions}; } +sub support_islands_enclose_line { + my $self = shift; + my ($line) = @_; + return (first { $_->encloses_line($line) } @{$self->support_islands}) ? 1 : 0; +} + 1; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index ba04c6005..a860c625d 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -626,39 +626,40 @@ sub generate_support_material { }; return @paths; }; - my %layer_paths = (); - my %layer_interface_paths = (); + my %layer_paths = (); + my %layer_interface_paths = (); + my %layer_islands = (); my $process_layer = sub { my ($layer_id) = @_; my $layer = $self->layers->[$layer_id]; my $paths = [ $clip_pattern->($layer_id, $layers{$layer_id}, $layer->height) ]; my $interface_paths = [ $clip_pattern->($layer_id, $layers_interfaces{$layer_id}, $layer->support_material_interface_height) ]; - return ($paths, $interface_paths); + my $islands = union_ex([ map @$_, map @$_, $layers{$layer_id}, $layers_interfaces{$layer_id} ]); + return ($paths, $interface_paths, $islands); }; Slic3r::parallelize( items => [ keys %layers ], thread_cb => sub { my $q = shift; - my $paths = {}; - my $interface_paths = {}; + my $result = {}; while (defined (my $layer_id = $q->dequeue)) { - ($paths->{$layer_id}, $interface_paths->{$layer_id}) = $process_layer->($layer_id); + $result->{$layer_id} = [ $process_layer->($layer_id) ]; } - return [ $paths, $interface_paths ]; + return $result; }, collect_cb => sub { - my $paths = shift; - $layer_paths{$_} = $paths->[0]{$_} for keys %{$paths->[0]}; - $layer_interface_paths{$_} = $paths->[1]{$_} for keys %{$paths->[1]}; + my $result = shift; + ($layer_paths{$_}, $layer_interface_paths{$_}, $layer_islands{$_}) = @{$result->{$_}} for keys %$result; }, no_threads_cb => sub { - ($layer_paths{$_}, $layer_interface_paths{$_}) = $process_layer->($_) for keys %layers; + ($layer_paths{$_}, $layer_interface_paths{$_}, $layer_islands{$_}) = $process_layer->($_) for keys %layers; }, ); foreach my $layer_id (keys %layer_paths) { my $layer = $self->layers->[$layer_id]; + $layer->support_islands($layer_islands{$layer_id}); $layer->support_fills(Slic3r::ExtrusionPath::Collection->new); $layer->support_interface_fills(Slic3r::ExtrusionPath::Collection->new); push @{$layer->support_fills->paths}, @{$layer_paths{$layer_id}};