diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index 5771fcc66..1cb6b4188 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -66,6 +66,10 @@ sub generate { $self->clip_with_object($base, $support_z, $object); $self->clip_with_shape($base, $shape) if @$shape; + # Detect what part of base support layers are "reverse interfaces" because they + # lie above object's top surfaces. + $self->generate_bottom_interface_layers($support_z, $base, $top, $interface); + # Install support layers into object. for my $i (0 .. $#$support_z) { $object->add_support_layer( @@ -415,6 +419,48 @@ sub generate_interface_layers { return \%interface; } +sub generate_bottom_interface_layers { + my ($self, $support_z, $base, $top, $interface) = @_; + + my $area_threshold = $self->interface_flow->scaled_spacing ** 2; + + # loop through object's top surfaces + foreach my $top_z (sort keys %$top) { + my $this = $top->{$top_z}; + + # keep a count of the interface layers we generated for this top surface + my $interface_layers = 0; + + # loop through support layers until we find the one(s) right above the top + # surface + foreach my $layer_id (0 .. $#$support_z) { + my $z = $support_z->[$layer_id]; + next unless $z > $top_z; + + # get the support material area that should be considered interface + my $interface_area = intersection( + $base->{$layer_id}, + $this, + ); + + # discard too small areas + $interface_area = [ grep abs($_->area) >= $area_threshold, @$interface_area ]; + + # subtract new interface area from base + $base->{$layer_id} = diff( + $base->{$layer_id}, + $interface_area, + ); + + # add new interface area to interface + push @{$interface->{$layer_id}}, @$interface_area; + + $interface_layers++; + last if $interface_layers == $self->object_config->support_material_interface_layers; + } + } +} + sub generate_base_layers { my ($self, $support_z, $contact, $interface, $top) = @_; @@ -620,6 +666,7 @@ sub generate_toolpaths { # interface and contact infill if (@$interface || @$contact_infill) { $fillers{interface}->angle($interface_angle); + $fillers{interface}->spacing($_interface_flow->spacing); # find centerline of the external loop $interface = offset2($interface, +scaled_epsilon, -(scaled_epsilon + $_interface_flow->scaled_width/2)); @@ -645,20 +692,19 @@ sub generate_toolpaths { my @paths = (); foreach my $expolygon (@{union_ex($interface)}) { - my ($params, @p) = $fillers{interface}->fill_surface( + my @p = $fillers{interface}->fill_surface( Slic3r::Surface->new(expolygon => $expolygon, surface_type => S_TYPE_INTERNAL), - density => $interface_density, - flow => $_interface_flow, + density => $interface_density, layer_height => $layer->height, - complete => 1, + complete => 1, ); - my $mm3_per_mm = $params->{flow}->mm3_per_mm; + my $mm3_per_mm = $_interface_flow->mm3_per_mm; push @paths, map Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$_), role => EXTR_ROLE_SUPPORTMATERIAL_INTERFACE, mm3_per_mm => $mm3_per_mm, - width => $params->{flow}->width, + width => $_interface_flow->width, height => $layer->height, ), @p; } @@ -699,22 +745,22 @@ sub generate_toolpaths { # TODO: use offset2_ex() $to_infill = offset_ex([ map @$_, @$to_infill ], -$_flow->scaled_spacing); } + $filler->spacing($base_flow->spacing); foreach my $expolygon (@$to_infill) { - my ($params, @p) = $filler->fill_surface( + my @p = $filler->fill_surface( Slic3r::Surface->new(expolygon => $expolygon, surface_type => S_TYPE_INTERNAL), density => $density, - flow => $base_flow, layer_height => $layer->height, complete => 1, ); - my $mm3_per_mm = $params->{flow}->mm3_per_mm; + my $mm3_per_mm = $base_flow->mm3_per_mm; push @paths, map Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$_), role => EXTR_ROLE_SUPPORTMATERIAL, mm3_per_mm => $mm3_per_mm, - width => $params->{flow}->width, + width => $base_flow->width, height => $layer->height, ), @p; }