diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index 325593cb5..d84942448 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -60,6 +60,11 @@ sub split_at_first_point { return $self->split_at_index(0); } +sub first_point { + my $self = shift; + return $self->polygon->[0]; +} + package Slic3r::ExtrusionLoop::Packed; sub unpack { my $self = shift; diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 588e8fbb7..825d23e6e 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -86,9 +86,9 @@ sub points { return $self->polyline; } -sub endpoints { +sub first_point { my $self = shift; - return ($self->points->[0], $self->points->[-1]); + return $self->polyline->[0]; } sub is_printable { 1 } diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index c6bfe37a9..f523a3076 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -3,9 +3,12 @@ use Moo; has 'paths' => (is => 'rw', default => sub { [] }); -sub endpoints { +# no-op +sub unpack { $_[0] } + +sub first_point { my $self = shift; - return [ map $_->endpoints, @{$self->paths} ]; + return $self->paths->[0]->unpack->polyline->[0]; } sub chained_path { diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index e1f407402..afd352431 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -850,21 +850,53 @@ sub write_gcode { my $layerm = $layer->regions->[$region_id]; my $region = $self->regions->[$region_id]; - # extrude perimeters - if (@{ $layerm->perimeters }) { - $gcode .= $gcodegen->set_extruder($region->extruders->{perimeter}); - $gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $layerm->perimeters }; + my @islands = (); + if ($Slic3r::Config->avoid_crossing_perimeters) { + push @islands, map +{ perimeters => [], fills => [] }, @{$layer->slices}; + PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) { + $perimeter = $perimeter->unpack; + for my $i (0 .. $#{$layer->slices}-1) { + if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) { + push @{ $islands[$i]{perimeters} }, $perimeter; + next PERIMETER; + } + } + push @{ $islands[-1]{perimeters} }, $perimeter; # optimization + } + FILL: foreach my $fill (@{$layerm->fills}) { + for my $i (0 .. $#{$layer->slices}-1) { + $fill = $fill->unpack; + if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) { + push @{ $islands[$i]{fills} }, $fill; + next FILL; + } + } + push @{ $islands[-1]{fills} }, $fill; # optimization + } + } else { + push @islands, { + perimeters => $layerm->perimeters, + fills => $layerm->fills, + }; } - # extrude fills - if (@{ $layerm->fills }) { - $gcode .= $gcodegen->set_extruder($region->extruders->{infill}); - for my $fill (@{ $layerm->fills }) { - if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { - $gcode .= $gcodegen->extrude($_, 'fill') - for $fill->chained_path($gcodegen->last_pos); - } else { - $gcode .= $gcodegen->extrude($fill, 'fill') ; + foreach my $island (@islands) { + # extrude perimeters + if (@{ $island->{perimeters} }) { + $gcode .= $gcodegen->set_extruder($region->extruders->{perimeter}); + $gcode .= $gcodegen->extrude($_, 'perimeter') for @{ $island->{perimeters} }; + } + + # extrude fills + if (@{ $island->{fills} }) { + $gcode .= $gcodegen->set_extruder($region->extruders->{infill}); + for my $fill (@{ $island->{fills} }) { + if ($fill->isa('Slic3r::ExtrusionPath::Collection')) { + $gcode .= $gcodegen->extrude($_, 'fill') + for $fill->chained_path($gcodegen->last_pos); + } else { + $gcode .= $gcodegen->extrude($fill, 'fill') ; + } } } }