diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index b0894fb8..b85826dd 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -93,13 +93,8 @@ sub change_layer { $self->layer($layer); # avoid computing islands and overhangs if they're not needed - if ($self->config->only_retract_when_crossing_perimeters) { - $self->_layer_islands([ $layer->islands ]); - $self->_upper_layer_islands([ $layer->upper_layer_islands ]); - } else { - $self->_layer_islands([]); - $self->_upper_layer_islands([]); - } + $self->_layer_islands($layer->islands); + $self->_upper_layer_islands($layer->upper_layer ? $layer->upper_layer->islands : []); $self->_layer_overhangs_pp( # clone ExPolygons because they come from Surface objects but will be used outside here ($layer->id > 0 && ($layer->config->overhangs || $Slic3r::Config->start_perimeters_at_non_overhang)) @@ -437,7 +432,7 @@ sub _plan { my $need_retract = !$self->config->only_retract_when_crossing_perimeters; if (!$need_retract) { $need_retract = 1; - foreach my $island ($self->layer->upper_layer_islands) { + foreach my $island (@{$self->_upper_layer_islands}) { # discard the island if at any line is not enclosed in it next if first { !$island->encloses_line($_, scaled_epsilon) } @travel; # okay, this island encloses the full travel path diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 49d48216..3dbddda7 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -7,6 +7,7 @@ use Slic3r::Geometry::Clipper qw(union_ex); has 'id' => (is => 'rw', required => 1, trigger => 1); # sequential number of layer, 0-based has 'object' => (is => 'ro', weak_ref => 1, required => 1, handles => [qw(print config)]); +has 'upper_layer' => (is => 'rw', weak_ref => 1); has 'regions' => (is => 'ro', default => sub { [] }); has 'slicing_errors' => (is => 'rw'); @@ -23,16 +24,10 @@ sub _trigger_id { $_->_trigger_layer for @{$self->regions || []}; } +# the purpose of this method is to be overridden for ::Support layers sub islands { my $self = shift; - return @{$self->slices}; -} - -sub upper_layer_islands { - my $self = shift; - - my $upper_layer = $self->object->layers->[ $self->id + 1 ] or return (); - return $upper_layer->islands; + return $self->slices; } sub region { @@ -75,7 +70,7 @@ has 'support_interface_fills' => (is => 'rw', default => sub { Slic3r::Extrusi sub islands { my $self = shift; - return @{$self->slices}, @{$self->support_islands}; + return [ @{$self->slices}, @{$self->support_islands} ]; } 1; diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index f6519d17..48a7cc2a 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -14,7 +14,7 @@ has 'layer' => ( weak_ref => 1, required => 1, trigger => 1, - handles => [qw(id slice_z print_z height flow object print config)], + handles => [qw(id slice_z print_z height flow config)], ); has 'region' => (is => 'ro', required => 1, handles => [qw(extruders)]); has 'perimeter_flow' => (is => 'rw'); @@ -182,7 +182,7 @@ sub make_perimeters { # where offset2() collapses the expolygon, then there's no room for an inner loop # and we can extract the gap for later processing - if ($Slic3r::Config->gap_fill_speed > 0 && $self->object->config->fill_density > 0) { + if ($Slic3r::Config->gap_fill_speed > 0 && $self->config->fill_density > 0) { my $diff = diff( offset(\@last, -0.5*$spacing), # +2 on the offset here makes sure that Clipper float truncation @@ -434,7 +434,7 @@ sub prepare_fill_surfaces { } sub process_external_surfaces { - my $self = shift; + my ($self, $lower_layer) = @_; my @surfaces = @{$self->fill_surfaces}; my $margin = scale &Slic3r::EXTERNAL_INFILL_MARGIN; @@ -447,8 +447,8 @@ sub process_external_surfaces { # would get merged into a single one while they need different directions # also, supply the original expolygon instead of the grown one, because in case # of very thin (but still working) anchors, the grown expolygon would go beyond them - my $angle = $self->id > 0 - ? $self->_detect_bridge_direction($surface->expolygon) + my $angle = $lower_layer + ? $self->_detect_bridge_direction($surface->expolygon, $lower_layer) : undef; push @bottom, map $surface->clone(expolygon => $_, bridge_angle => $angle), @$grown; @@ -466,7 +466,7 @@ sub process_external_surfaces { # if we're slicing with no infill, we can't extend external surfaces # over non-existent infill - my @fill_boundaries = $self->object->config->fill_density > 0 + my @fill_boundaries = $self->config->fill_density > 0 ? @surfaces : grep $_->surface_type != S_TYPE_INTERNAL, @surfaces; @@ -495,11 +495,10 @@ sub process_external_surfaces { } sub _detect_bridge_direction { - my $self = shift; - my ($expolygon) = @_; + my ($self, $expolygon, $lower_layer) = @_; my $grown = $expolygon->offset_ex(+$self->perimeter_flow->scaled_width); - my @lower = @{$self->layer->object->layers->[ $self->id - 1 ]->slices}; # expolygons + my @lower = @{$lower_layer->slices}; # expolygons # detect what edges lie on lower slices my @edges = (); # polylines diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 50fc0351..99ed3724 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -376,7 +376,7 @@ sub export_gcode { # this will detect bridges and reverse bridges # and rearrange top/bottom/internal surfaces $status_cb->(45, "Detect bridges"); - $_->process_external_surfaces for map @{$_->regions}, map @{$_->layers}, @{$self->objects}; + $_->process_external_surfaces for @{$self->objects}; # detect which fill surfaces are near external layers # they will be split in internal and internal-solid surfaces diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index b0ffbf93..c504ed57 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -65,6 +65,9 @@ sub BUILD { print_z => $print_z, slice_z => scale $slice_z, ); + if ($id > 0) { + $self->layers->[-2]->upper_layer($self->layers->[-1]); + } $id++; $slice_z += $height/2; # add the other half layer @@ -508,6 +511,17 @@ sub bridge_over_infill { } } +sub process_external_surfaces { + my ($self) = @_; + + for my $region_id (0 .. ($self->print->regions_count-1)) { + $self->layers->[0]->regions->[$region_id]->process_external_surfaces(undef); + for my $layer_id (1 .. ($self->layer_count-1)) { + $self->layers->[$layer_id]->regions->[$region_id]->process_external_surfaces($self->layers->[$layer_id-1]); + } + } +} + sub discover_horizontal_shells { my $self = shift;