From 74e21d7a04737b3e4000c8bd1202a41df5473233 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 10 Mar 2013 19:08:36 +0100 Subject: [PATCH 1/3] New implementation of extra perimeters - to test --- lib/Slic3r/Print/Object.pm | 53 +++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 8a914b9d25..6ba47f64ec 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -4,7 +4,7 @@ use Moo; use List::Util qw(min sum first); use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(Z PI scale unscale deg2rad rad2deg scaled_epsilon); -use Slic3r::Geometry::Clipper qw(diff_ex intersection_ex union_ex); +use Slic3r::Geometry::Clipper qw(diff_ex intersection_ex union_ex offset); use Slic3r::Surface ':types'; has 'print' => (is => 'ro', weak_ref => 1, required => 1); @@ -236,37 +236,42 @@ sub make_perimeters { my $overlap = $perimeter_spacing; # one perimeter - # compute the polygon used to trigger the additional perimeters: the hole represents - # the required overlap, while the contour represents how different should the slices be - # (thus how horizontal should the slope be) before extra perimeters are not generated, and - # normal solid infill is used - my $upper = diff_ex( - [ map @$_, map $_->expolygon->offset_ex($overlap), @{$upper_layerm->slices} ], - [ map @$_, map $_->expolygon->offset_ex(-$overlap), @{$upper_layerm->slices} ], + my $diff = diff_ex( + [ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ], + [ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)) ], ); - next if !@$upper; + next if !@$diff; + + # if we need more perimeters, $diff should contain a narrow region that we can collapse + + $diff = diff_ex( + [ map @$_, @$diff ], + [ offset( + [ offset([ map @$_, @$diff ], -$perimeter_spacing) ], + +$perimeter_spacing + ) ], + ); + next if !@$diff; + + # diff contains the collapsed area foreach my $slice (@{$layerm->slices}) { my $hypothetical_perimeter_num = $Slic3r::Config->perimeters + 1; CYCLE: while (1) { # compute polygons representing the thickness of the hypotetical new internal perimeter # of our slice - my $hypothetical_perimeter; - { - my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1) * $perimeter_spacing - scaled_epsilon) ]; - last CYCLE if !@$outer; - my $inner = [ map @$_, $slice->expolygon->offset_ex(- $hypothetical_perimeter_num * $perimeter_spacing) ]; - last CYCLE if !@$inner; - $hypothetical_perimeter = diff_ex($outer, $inner); - } - last CYCLE if !@$hypothetical_perimeter; + my $hypothetical_perimeter = diff_ex( + [ offset($slice->expolygon, -($perimeter_spacing * ($hypothetical_perimeter_num-1))) ], + [ offset($slice->expolygon, -($perimeter_spacing * $hypothetical_perimeter_num)) ], + ); + last CYCLE if !@$hypothetical_perimeter; # no extra perimeter is possible - # compute the area of the hypothetical perimeter - my $hp_area = sum(map $_->area, @$hypothetical_perimeter); - - # only add the perimeter if the intersection is at least 20%, otherwise we'd get no benefit - my $intersection = intersection_ex([ map @$_, @$upper ], [ map @$_, @$hypothetical_perimeter ]); - last CYCLE if (sum(map $_->area, @{ $intersection }) // 0) < $hp_area * 0.2; + # only add the perimeter if there's an intersection with the collapsed area + my $intersection = intersection_ex( + [ map @$_, @$diff ], + [ map @$_, @$hypothetical_perimeter ], + ); + last CYCLE if !@$intersection; Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id; $slice->additional_inner_perimeters(($slice->additional_inner_perimeters || 0) + 1); $hypothetical_perimeter_num++; From b7945ac790cb0cc2186bcc93ef29c868bbc1676b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 11 Mar 2013 14:23:16 +0100 Subject: [PATCH 2/3] Finished new extra perimeters implementation --- lib/Slic3r/Layer/Region.pm | 2 +- lib/Slic3r/Print/Object.pm | 14 ++++++-------- lib/Slic3r/Surface.pm | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index b130f7828a..a3b6abe064 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -216,7 +216,7 @@ sub make_perimeters { my @gaps = (); # generate perimeters inwards (loop 0 is the external one) - my $loop_number = $Slic3r::Config->perimeters + ($surface->additional_inner_perimeters || 0); + my $loop_number = $Slic3r::Config->perimeters + ($surface->extra_perimeters || 0); push @perimeters, [] if $loop_number > 0; # do one more loop (<= instead of <) so that we can detect gaps even after the desired diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 6ba47f64ec..80f5889f65 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -237,11 +237,10 @@ sub make_perimeters { my $overlap = $perimeter_spacing; # one perimeter my $diff = diff_ex( - [ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ], [ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)) ], + [ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ], ); next if !@$diff; - # if we need more perimeters, $diff should contain a narrow region that we can collapse $diff = diff_ex( @@ -252,17 +251,17 @@ sub make_perimeters { ) ], ); next if !@$diff; - # diff contains the collapsed area foreach my $slice (@{$layerm->slices}) { - my $hypothetical_perimeter_num = $Slic3r::Config->perimeters + 1; + my $extra_perimeters = 0; CYCLE: while (1) { # compute polygons representing the thickness of the hypotetical new internal perimeter # of our slice + $extra_perimeters++; my $hypothetical_perimeter = diff_ex( - [ offset($slice->expolygon, -($perimeter_spacing * ($hypothetical_perimeter_num-1))) ], - [ offset($slice->expolygon, -($perimeter_spacing * $hypothetical_perimeter_num)) ], + [ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters-1))) ], + [ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters))) ], ); last CYCLE if !@$hypothetical_perimeter; # no extra perimeter is possible @@ -273,8 +272,7 @@ sub make_perimeters { ); last CYCLE if !@$intersection; Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id; - $slice->additional_inner_perimeters(($slice->additional_inner_perimeters || 0) + 1); - $hypothetical_perimeter_num++; + $slice->extra_perimeters($extra_perimeters); } } } diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index d5ec9838e6..efa0f46a99 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -11,7 +11,7 @@ use constant S_EXPOLYGON => 0; use constant S_SURFACE_TYPE => 1; use constant S_DEPTH_LAYERS => 2; use constant S_BRIDGE_ANGLE => 3; -use constant S_ADDITIONAL_INNER_PERIMETERS => 4; +use constant S_EXTRA_PERIMETERS => 4; use constant S_TYPE_TOP => 0; use constant S_TYPE_BOTTOM => 1; @@ -24,7 +24,7 @@ sub new { my %args = @_; my $self = [ - map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle additional_inner_perimeters), + map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle extra_perimeters), ]; $self->[S_DEPTH_LAYERS] //= 1; #/ @@ -36,7 +36,7 @@ sub expolygon { $_[0][S_EXPOLYGON] } sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if defined $_[1]; $_[0][S_SURFACE_TYPE] } sub depth_layers { $_[0][S_DEPTH_LAYERS] } # this integer represents the thickness of the surface expressed in layers sub bridge_angle { $_[0][S_BRIDGE_ANGLE] = $_[1] if defined $_[1]; $_[0][S_BRIDGE_ANGLE] } -sub additional_inner_perimeters { $_[0][S_ADDITIONAL_INNER_PERIMETERS] = $_[1] if defined $_[1]; $_[0][S_ADDITIONAL_INNER_PERIMETERS] } +sub extra_perimeters { $_[0][S_EXTRA_PERIMETERS] = $_[1] if defined $_[1]; $_[0][S_EXTRA_PERIMETERS] } # delegate handles sub encloses_point { $_[0]->expolygon->encloses_point } From e809a5bdcc63020ae152abeb1471afc747d2a753 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 11 Mar 2013 14:23:45 +0100 Subject: [PATCH 3/3] Added support for expolygons in Slic3r::SVG --- lib/Slic3r/SVG.pm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/Slic3r/SVG.pm b/lib/Slic3r/SVG.pm index 0179ea7692..0ac2863951 100644 --- a/lib/Slic3r/SVG.pm +++ b/lib/Slic3r/SVG.pm @@ -7,6 +7,8 @@ use SVG; use constant X => 0; use constant Y => 1; +our $filltype = 'evenodd'; + sub factor { return &Slic3r::SCALING_FACTOR * 10; } @@ -36,6 +38,25 @@ sub output { my $svg = svg(); + foreach my $type (qw(expolygons red_expolygons green_expolygons)) { + next if !$things{$type}; + my ($colour) = $type =~ /^(red|green)_/; + my $g = $svg->group( + style => { + 'stroke-width' => 2, + 'stroke' => $colour || 'black', + 'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')), + 'fill-type' => $filltype, + }, + ); + foreach my $expolygon (@{$things{$type}}) { + my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon; + $g->path( + d => $points, + ); + } + } + foreach my $type (qw(polygons polylines white_polygons green_polygons red_polygons red_polylines)) { if ($things{$type}) { my $method = $type =~ /polygons/ ? 'polygon' : 'polyline';