diff --git a/README.markdown b/README.markdown index 764fe8ce8..86adce256 100644 --- a/README.markdown +++ b/README.markdown @@ -149,6 +149,7 @@ The author is Alessandro Ranellucci (me). --skirts Number of skirts to draw (default: 1) --skirt-distance Distance in mm between innermost skirt and object (default: 6) + --skirt-height Height of skirts to draw (expressed in layers, default: 1) Transform options: --scale Factor for scaling input object (default: 1) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index e59f97947..061ab1ce6 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -82,6 +82,7 @@ our $retract_lift = 0; # mm # skirt options our $skirts = 1; our $skirt_distance = 6; # mm +our $skirt_height = 1; # layers # transform options our $scale = 1; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 581ebb305..732df6ac6 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -144,6 +144,10 @@ our $Options = { label => 'Distance from object (mm)', type => 'i', }, + 'skirt_height' => { + label => 'Skirt height (layers)', + type => 'i', + }, # transform options 'scale' => { @@ -313,6 +317,10 @@ sub validate { # --duplicate-distance die "Invalid value for --duplicate-distance\n" if $Slic3r::duplicate_distance < 1; + + # --skirt-height + die "Invalid value for --skirt-height\n" + if $Slic3r::skirt_height < 1; } 1; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 77d2973c9..fa89ee18d 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -41,7 +41,7 @@ sub new { ), skirt => Slic3r::GUI::OptionsGroup->new($self, title => 'Skirt', - options => [qw(skirts skirt_distance)], + options => [qw(skirts skirt_distance skirt_height)], ), transform => Slic3r::GUI::OptionsGroup->new($self, title => 'Transform', diff --git a/lib/Slic3r/Perimeter.pm b/lib/Slic3r/Perimeter.pm index 0c31f18bd..2ffa44640 100644 --- a/lib/Slic3r/Perimeter.pm +++ b/lib/Slic3r/Perimeter.pm @@ -2,7 +2,6 @@ package Slic3r::Perimeter; use Moo; use Math::Clipper ':all'; -use Math::ConvexHull 1.0.4 qw(convex_hull); use Slic3r::Geometry qw(X Y shortest_path); use XXX; @@ -72,19 +71,6 @@ sub make_perimeter { push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($contour); } } - - # generate skirt on bottom layer - if ($layer->id == 0 && $Slic3r::skirts > 0 && @{ $layer->surfaces }) { - # find out convex hull - my $convex_hull = convex_hull([ map @$_, map $_->p, @{ $layer->surfaces } ]); - - # draw outlines from outside to inside - for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) { - my $distance = ($Slic3r::skirt_distance + ($Slic3r::flow_width * $i)) / $Slic3r::resolution; - my $outline = offset([$convex_hull], $distance, $Slic3r::resolution * 100, JT_ROUND); - push @{ $layer->skirts }, Slic3r::ExtrusionLoop->cast([ @{$outline->[0]} ]); - } - } } 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index c33f16b11..5a5b22206 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -2,6 +2,7 @@ package Slic3r::Print; use Moo; use Math::Clipper ':all'; +use Math::ConvexHull 1.0.4 qw(convex_hull); use Slic3r::Geometry qw(X Y); use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex); use XXX; @@ -289,6 +290,30 @@ sub process_bridges { $_->process_bridges for @{ $self->layers }; } +sub extrude_skirt { + my $self = shift; + return unless $Slic3r::skirts > 0; + + # collect points from all layers contained in skirt height + my @points = (); + my @layers = map $self->layer($_), 0..($Slic3r::skirt_height-1); + push @points, map @$_, map $_->p, map @{ $_->surfaces }, @layers; + + # find out convex hull + my $convex_hull = convex_hull(\@points); + + # draw outlines from outside to inside + my @skirts = (); + for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) { + my $distance = ($Slic3r::skirt_distance + ($Slic3r::flow_width * $i)) / $Slic3r::resolution; + my $outline = offset([$convex_hull], $distance, $Slic3r::resolution * 100, JT_ROUND); + push @skirts, Slic3r::ExtrusionLoop->cast([ @{$outline->[0]} ]); + } + + # apply skirts to all layers + push @{$_->skirts}, @skirts for @layers; +} + sub extrude_perimeters { my $self = shift; diff --git a/lib/Slic3r/Skein.pm b/lib/Slic3r/Skein.pm index a9790ce32..e17f30190 100644 --- a/lib/Slic3r/Skein.pm +++ b/lib/Slic3r/Skein.pm @@ -31,6 +31,9 @@ sub go { # this will add a set of bridges to each layer $print->process_bridges; + # make skirt + $print->extrude_skirt; + # make perimeters # this will add a set of extrusion loops to each layer # as well as a set of surfaces to be filled diff --git a/slic3r.pl b/slic3r.pl index 7333d7061..b81284d58 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -65,6 +65,7 @@ GetOptions( # skirt options 'skirts=i' => \$Slic3r::skirts, 'skirt-distance=i' => \$Slic3r::skirt_distance, + 'skirt-height=i' => \$Slic3r::skirt_height, # transform options 'scale=f' => \$Slic3r::scale, @@ -187,6 +188,7 @@ Usage: slic3r.pl [ OPTIONS ] file.stl --skirts Number of skirts to draw (default: $Slic3r::skirts) --skirt-distance Distance in mm between innermost skirt and object (default: $Slic3r::skirt_distance) + --skirt-height Height of skirts to draw (expressed in layers, default: $Slic3r::skirt_height) Transform options: --scale Factor for scaling input object (default: $Slic3r::scale)