diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 85c189cfec..1a76c6a670 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -13,7 +13,7 @@ use Slic3r::Fill::PlanePath; use Slic3r::Fill::Rectilinear; use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(X Y PI scale chained_path); -use Slic3r::Geometry::Clipper qw(union_ex diff_ex); +use Slic3r::Geometry::Clipper qw(union_ex diff_ex intersection_ex offset); use Slic3r::Surface ':types'; @@ -98,15 +98,40 @@ sub make_fill { } } - # add spacing between surfaces + # we need to detect any narrow surfaces that might collapse + # when adding spacing below + # such narrow surfaces are often generated in sloping walls + # by bridge_over_infill() and combine_infill() as a result of the + # subtraction of the combinable area from the layer infill area, + # which leaves small areas near the perimeters + # we are going to grow such regions by overlapping them with the void (if any) + # TODO: detect and investigate whether there could be narrow regions without + # any void neighbors + my $distance_between_surfaces = $layerm->infill_flow->scaled_spacing; { - my $distance = $layerm->infill_flow->scaled_spacing / 2; - @surfaces = map $_->offset(-$distance), @surfaces; + my $collapsed = diff_ex( + [ map @{$_->expolygon}, @surfaces ], + [ offset( + [ offset([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2) ], + +$distance_between_surfaces/2 + ) ], + ); + push @surfaces, map Slic3r::Surface->new( + expolygon => $_, + surface_type => S_TYPE_INTERNALSOLID, + ), @{intersection_ex( + [ offset([ map @$_, @$collapsed ], $distance_between_surfaces) ], + [ map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces ], + )}; } + # add spacing between surfaces + @surfaces = map $_->offset(-$distance_between_surfaces/2), @surfaces; + my @fills = (); my @fills_ordering_points = (); SURFACE: foreach my $surface (@surfaces) { + next if $surface->surface_type == S_TYPE_INTERNALVOID; my $filler = $Slic3r::Config->fill_pattern; my $density = $Slic3r::Config->fill_density; my $flow_spacing = ($surface->surface_type == S_TYPE_TOP) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 6008e02ebf..3e4c1fafc1 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -516,6 +516,13 @@ sub bridge_over_infill { [ map $_->p, @$group ], [ map @$_, @$to_bridge ], )}; + push @new_surfaces, map Slic3r::Surface->new( + expolygon => $_, + surface_type => S_TYPE_INTERNALVOID, + ), @{intersection_ex( + [ map $_->p, @$group ], + [ map @$_, @$to_bridge ], + )}; } @{$lower_layerm->fill_surfaces} = @new_surfaces; } @@ -713,7 +720,7 @@ sub combine_infill { my @this_type = grep $_->surface_type == $type, @{$layerm->fill_surfaces}; my @other_types = grep $_->surface_type != $type, @{$layerm->fill_surfaces}; - @this_type = map Slic3r::Surface->new(expolygon => $_, surface_type => $type), + my @new_this_type = map Slic3r::Surface->new(expolygon => $_, surface_type => $type), @{diff_ex( [ map @{$_->expolygon}, @this_type ], [ @intersection_with_clearance ], @@ -721,12 +728,20 @@ sub combine_infill { # apply surfaces back with adjusted depth to the uppermost layer if ($layerm->id == $layer_id) { - push @this_type, + push @new_this_type, map Slic3r::Surface->new(expolygon => $_, surface_type => $type, depth_layers => $every), @$intersection; + } else { + # save void surfaces + push @this_type, + map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNALVOID), + @{intersection_ex( + [ map @{$_->expolygon}, @this_type ], + [ @intersection_with_clearance ], + )}; } - @{$layerm->fill_surfaces} = (@this_type, @other_types); + @{$layerm->fill_surfaces} = (@new_this_type, @other_types); } } } diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index efa0f46a99..cb8aab3130 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -4,7 +4,7 @@ use warnings; require Exporter; our @ISA = qw(Exporter); -our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE); +our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE S_TYPE_INTERNALVOID); our %EXPORT_TAGS = (types => \@EXPORT_OK); use constant S_EXPOLYGON => 0; @@ -18,6 +18,7 @@ use constant S_TYPE_BOTTOM => 1; use constant S_TYPE_INTERNAL => 2; use constant S_TYPE_INTERNALSOLID => 3; use constant S_TYPE_INTERNALBRIDGE => 4; +use constant S_TYPE_INTERNALVOID => 5; sub new { my $class = shift; @@ -74,17 +75,6 @@ sub offset { } $self->expolygon->offset_ex(@_); } -sub clipper_polygon { - my $self = shift; - - return { - outer => $self->contour->p, - holes => [ - map $_->p, @{$self->holes} - ], - }; -} - sub p { my $self = shift; return @{$self->expolygon}; @@ -99,14 +89,6 @@ sub is_solid { || $type == S_TYPE_INTERNALSOLID; } -sub is_internal { - my $self = shift; - my $type = $self->surface_type; - return $type == S_TYPE_INTERNAL - || $type == S_TYPE_INTERNALSOLID - || $type == S_TYPE_INTERNALBRIDGE; -} - sub is_bridge { my $self = shift; my $type = $self->surface_type;