diff --git a/README.markdown b/README.markdown index 21093eeb5..3d708d722 100644 --- a/README.markdown +++ b/README.markdown @@ -227,6 +227,8 @@ The author of the Silk icon set is Mark James. --skirt-distance Distance in mm between innermost skirt and object (default: 6) --skirt-height Height of skirts to draw (expressed in layers, 0+, default: 1) + --min-skirt-length Generate no less than the number of loops required to consume this length + of filament on the first layer, for each extruder (mm, 0+, default: 0) --brim-width Width of the brim that will get added to each object to help adhesion (mm, default: 0) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 67dde2bdc..4ccb6bcab 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -760,6 +760,15 @@ END type => 'i', default => 1, }, + 'min_skirt_length' => { + label => 'Minimum extrusion length', + tooltip => 'Generate no less than the number of skirt loops required to consume the specified amount of filament on the bottom layer. For multi-extruder machines, this minimum applies to each extruder.', + sidetext => 'mm', + cli => 'min-skirt-length=f', + type => 'f', + default => 0, + min => 0, + }, 'skirt_distance' => { label => 'Distance from object', tooltip => 'Distance between skirt and object(s). Set this to zero to attach the skirt to the object(s) and get a brim for better adhesion.', diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index 3b77a3497..8bac9d0d9 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -55,4 +55,10 @@ sub mm3_per_mm { return $self->_mm3_per_mm_cache->{$cache_key}; } +sub e_per_mm { + my $self = shift; + my ($s, $h) = @_; + return $self->mm3_per_mm($s, $h) * $self->e_per_mm3; +} + 1; diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index d130799b3..e1469053c 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -435,7 +435,7 @@ sub build { $self->add_options_page('Skirt and brim', 'box.png', optgroups => [ { title => 'Skirt', - options => [qw(skirts skirt_distance skirt_height)], + options => [qw(skirts skirt_distance skirt_height min_skirt_length)], }, { title => 'Brim', diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 312cb3d44..05eef7479 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -3,7 +3,7 @@ use Moo; use File::Basename qw(basename fileparse); use File::Spec; -use List::Util qw(max); +use List::Util qw(max first); use Math::ConvexHull::MonotoneChain qw(convex_hull); use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN PI scale unscale move_points nearest_point); @@ -568,16 +568,40 @@ sub make_skirt { # find out convex hull my $convex_hull = convex_hull(\@points); + my @extruded_length = (); # for each extruder + my $spacing = $Slic3r::first_layer_flow->spacing; + my $first_layer_height = $Slic3r::Config->get_value('first_layer_height'); + my @extruders_e_per_mm = (); + my $extruder_idx = 0; + # draw outlines from outside to inside + # loop while we have less skirts than required or any extruder hasn't reached the min length if any + my $distance = scale $Slic3r::Config->skirt_distance; for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) { - my $distance = scale ($Slic3r::Config->skirt_distance + ($Slic3r::first_layer_flow->spacing * $i)); - my $outline = Math::Clipper::offset([$convex_hull], $distance, &Slic3r::SCALING_FACTOR * 100, JT_ROUND); + $distance += scale $spacing; + my $loop = Math::Clipper::offset([$convex_hull], $distance, &Slic3r::SCALING_FACTOR * 100, JT_ROUND)->[0]; push @{$self->skirt}, Slic3r::ExtrusionLoop->pack( - polygon => Slic3r::Polygon->new(@{$outline->[0]}), + polygon => Slic3r::Polygon->new(@$loop), role => EXTR_ROLE_SKIRT, - flow_spacing => $Slic3r::first_layer_flow->spacing, + flow_spacing => $spacing, ); + + if ($Slic3r::Config->min_skirt_length > 0) { + bless $loop, 'Slic3r::Polygon'; + $extruded_length[$extruder_idx] ||= 0; + $extruders_e_per_mm[$extruder_idx] ||= $self->extruders->[$extruder_idx]->e_per_mm($spacing, $first_layer_height); + $extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx]; + $i++ if defined first { ($extruded_length[$_] // 0) < $Slic3r::Config->min_skirt_length } 0 .. $#{$self->extruders}; + if ($extruded_length[$extruder_idx] >= $Slic3r::Config->min_skirt_length) { + if ($extruder_idx < $#{$self->extruders}) { + $extruder_idx++; + next; + } + } + } } + + @{$self->skirt} = reverse @{$self->skirt}; } sub make_brim { diff --git a/slic3r.pl b/slic3r.pl index f0b558133..d540fcae4 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -275,6 +275,8 @@ $j --skirt-distance Distance in mm between innermost skirt and object (default: $config->{skirt_distance}) --skirt-height Height of skirts to draw (expressed in layers, 0+, default: $config->{skirt_height}) + --min-skirt-length Generate no less than the number of loops required to consume this length + of filament on the first layer, for each extruder (mm, 0+, default: $config->{min_skirt_length}) --brim-width Width of the brim that will get added to each object to help adhesion (mm, default: $config->{brim_width})