From d9b82c79da5c22a21a911d636137394d703246af Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 13 Mar 2013 01:03:54 +0100 Subject: [PATCH 01/11] Grow narrow infill regions into void - to be tested more --- lib/Slic3r/Fill.pm | 33 +++++++++++++++++++++++++++++---- lib/Slic3r/Print/Object.pm | 21 ++++++++++++++++++--- lib/Slic3r/Surface.pm | 22 ++-------------------- 3 files changed, 49 insertions(+), 27 deletions(-) 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; From 9713b9f524da2fc7c8cd63f9013f311633cb047a Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 13 Mar 2013 14:55:58 +0100 Subject: [PATCH 02/11] Fix narrow fills growing --- lib/Slic3r/Fill.pm | 14 ++++++++++---- lib/Slic3r/Geometry/Clipper.pm | 10 +++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 1a76c6a670..f954c0599f 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 intersection_ex offset); +use Slic3r::Geometry::Clipper qw(union_ex diff diff_ex intersection_ex offset); use Slic3r::Surface ':types'; @@ -109,19 +109,25 @@ sub make_fill { # any void neighbors my $distance_between_surfaces = $layerm->infill_flow->scaled_spacing; { - my $collapsed = diff_ex( + my $collapsed = diff( [ map @{$_->expolygon}, @surfaces ], [ offset( [ offset([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2) ], +$distance_between_surfaces/2 ) ], + 1, ); 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 ], + [ offset($collapsed, $distance_between_surfaces) ], + [ + (map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces), + (@$collapsed), + ], + undef, + 1, )}; } diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index 292e88f27f..724f6994ea 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -45,7 +45,15 @@ sub diff_ex { } sub diff { - return [ map @$_, diff_ex(@_) ]; + my ($subject, $clip, $safety_offset) = @_; + + $clipper->clear; + $clipper->add_subject_polygons($subject); + $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); + return [ + map Slic3r::Polygon->new($_), + @{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, + ]; } sub union_ex { From 8d2c651ef2bbbcdc046cbd0a598594549add36da Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Mar 2013 14:58:10 +0100 Subject: [PATCH 03/11] $surface->thickness was erroneously defaulting to 1 mm --- lib/Slic3r/Surface.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index 8849448a20..966dcde41c 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -28,7 +28,7 @@ sub new { my $self = [ map delete $args{$_}, qw(expolygon surface_type thickness thickness_layers bridge_angle extra_perimeters), ]; - $self->[$_] //= 1 for S_THICKNESS, S_THICKNESS_LAYERS; + $self->[S_THICKNESS_LAYERS] = 1; bless $self, $class; $self; @@ -73,8 +73,8 @@ sub group { foreach my $surface (@surfaces) { my $type = join '_', ($params->{merge_solid} && $surface->is_solid) ? 'solid' : $surface->surface_type, - ($surface->bridge_angle // ''), - $surface->thickness, + $surface->bridge_angle // '', + $surface->thickness // '', $surface->thickness_layers; $unique_types{$type} ||= []; push @{ $unique_types{$type} }, $surface; From 442fb0e82a6cc442e06dd3117916960d19a7e746 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Mar 2013 14:58:10 +0100 Subject: [PATCH 04/11] $surface->thickness was erroneously defaulting to 1 mm --- lib/Slic3r/Surface.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index 139daf5f51..0b0ad14651 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -27,7 +27,7 @@ sub new { my $self = [ map delete $args{$_}, qw(expolygon surface_type thickness thickness_layers bridge_angle extra_perimeters), ]; - $self->[$_] //= 1 for S_THICKNESS, S_THICKNESS_LAYERS; + $self->[S_THICKNESS_LAYERS] = 1; bless $self, $class; $self; @@ -72,8 +72,8 @@ sub group { foreach my $surface (@surfaces) { my $type = join '_', ($params->{merge_solid} && $surface->is_solid) ? 'solid' : $surface->surface_type, - ($surface->bridge_angle // ''), - $surface->thickness, + $surface->bridge_angle // '', + $surface->thickness // '', $surface->thickness_layers; $unique_types{$type} ||= []; push @{ $unique_types{$type} }, $surface; From 7f917671ab9c4ccf998049ffd72cc62e2b785587 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Mar 2013 15:39:51 +0100 Subject: [PATCH 05/11] Bugfix: horizontal projection for high-res models might show corrupted result --- lib/Slic3r/TriangleMesh.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index ea9e664e53..74efc39db3 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -585,8 +585,8 @@ sub horizontal_projection { push @f, Slic3r::Polygon->new([ map [ @{$self->vertices->[$_]}[X,Y] ], @$facet ]); } - $_->make_counter_clockwise for @f; my $scale_vector = Math::Clipper::integerize_coordinate_sets({ bits => 32 }, @f); + $_->make_counter_clockwise for @f; # do this after scaling, as winding order might change while doing that my $union = union_ex([ Slic3r::Geometry::Clipper::offset(\@f, 10000) ]); Math::Clipper::unscale_coordinate_sets($scale_vector, $_) for @$union; return $union; From b04e4f839bdbbcf33388aa3e74ea2a0317b9cc0b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Mar 2013 15:39:51 +0100 Subject: [PATCH 06/11] Bugfix: horizontal projection for high-res models might show corrupted result --- lib/Slic3r/TriangleMesh.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index ea9e664e53..74efc39db3 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -585,8 +585,8 @@ sub horizontal_projection { push @f, Slic3r::Polygon->new([ map [ @{$self->vertices->[$_]}[X,Y] ], @$facet ]); } - $_->make_counter_clockwise for @f; my $scale_vector = Math::Clipper::integerize_coordinate_sets({ bits => 32 }, @f); + $_->make_counter_clockwise for @f; # do this after scaling, as winding order might change while doing that my $union = union_ex([ Slic3r::Geometry::Clipper::offset(\@f, 10000) ]); Math::Clipper::unscale_coordinate_sets($scale_vector, $_) for @$union; return $union; From 8ce31c2a2bbaf9b984ce87e3234a599fa0e0d3ec Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 13:32:19 +0100 Subject: [PATCH 07/11] Don't exclude any infill under internal bridges; revert infill pattern to rectilinear for internal bridges. #240 --- lib/Slic3r/Fill.pm | 4 +--- lib/Slic3r/Print/Object.pm | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 6fbb14b7b7..e08bc2e705 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -155,9 +155,7 @@ sub make_fill { $density = 1; $filler = $Slic3r::Config->solid_fill_pattern; if ($is_bridge) { - $filler = $surface->surface_type == S_TYPE_INTERNALBRIDGE - ? 'concentric' - : 'rectilinear'; + $filler = 'rectilinear'; $flow_spacing = $layerm->extruders->{infill}->bridge_flow->spacing; } elsif ($surface->surface_type == S_TYPE_INTERNALSOLID) { $filler = 'rectilinear'; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 01c4980260..dcca260962 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -509,7 +509,8 @@ sub bridge_over_infill { # exclude infill from the layers below if needed # see discussion at https://github.com/alexrj/Slic3r/issues/240 - { + # Update: do not exclude any infill. Sparse infill is able to absorb the excess material. + if (0) { my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height; for (my $i = $layer_id-1; $excess >= $self->layers->[$i]->height; $i--) { Slic3r::debugf " skipping infill below those areas at layer %d\n", $i; From 0b81911cff793ea8ac81539a60278977e47befe9 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 17:55:16 +0100 Subject: [PATCH 08/11] Bugfix: artifacts near walls. #1049 --- lib/Slic3r/Print/Object.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index dcca260962..ffac1e1e1f 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -593,6 +593,7 @@ sub discover_horizontal_shells { my $too_narrow = diff_ex( [ map @$_, @$new_internal_solid ], [ offset([ offset([ map @$_, @$new_internal_solid ], -$margin) ], +$margin) ], + 1, ); # if some parts are going to collapse, let's grow them and add the extra area to the neighbor layer From f0ac1c704ea30eb9c9437ece018bb80764c47422 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 18:01:01 +0100 Subject: [PATCH 09/11] Fix test framework detecting dE=0 as retraction --- lib/Slic3r/Test.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index 672c8af4bd..0884fd3089 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -119,9 +119,11 @@ sub parse { } $info{dist_XY} = Slic3r::Line->new([0,0], [@info{qw(dist_X dist_Y)}])->length; if (exists $args{E}) { - ($info{dist_E} > 0) - ? ($info{extruding} = 1) - : ($info{retracting} = 1); + if ($info{dist_E} > 0) { + $info{extruding} = 1; + } elsif ($info{dist_E} < 0) { + $info{retracting} = 1 + } } } From 1abd8c9a9e0d68bec691f95c1232d27e82a41393 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 18:03:14 +0100 Subject: [PATCH 10/11] Remove the 'simplify' handle in ExtrusionPath after the recent refactoring. #1054 --- lib/Slic3r/ExtrusionPath.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 95a65c709f..a150a9c724 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -15,7 +15,7 @@ use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); has 'polyline' => ( is => 'rw', required => 1, - handles => [qw(merge_continuous_lines lines length reverse clip_end simplify)], + handles => [qw(merge_continuous_lines lines length reverse clip_end)], ); # height is the vertical thickness of the extrusion expressed in mm From 4fdcd188015f175c1d3fe163920387bc810c1487 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 18:11:25 +0100 Subject: [PATCH 11/11] Fix t/retraction.t after the recent change to the first_layer_height default --- t/retraction.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/retraction.t b/t/retraction.t index f89700e945..a23e6f8181 100644 --- a/t/retraction.t +++ b/t/retraction.t @@ -88,6 +88,7 @@ my $test = sub { 1; }; +$config->set('first_layer_height', $config->layer_height); $config->set('start_gcode', ''); # to avoid dealing with the nozzle lift in start G-code $config->set('retract_length', [1.5]); $config->set('retract_before_travel', [3]);