diff --git a/README.markdown b/README.markdown index 9523f8ec6..cb385e08d 100644 --- a/README.markdown +++ b/README.markdown @@ -193,6 +193,8 @@ The author is Alessandro Ranellucci. --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) + --brim-thickness Thickness of the brim that will get added to each object to help adhesion + (mm, default: 0) Transform options: --scale Factor for scaling input object (default: 1) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 350cccf78..72732c250 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -150,10 +150,11 @@ our $min_print_speed = 10; our $disable_fan_first_layers = 1; our $fan_always_on = 0; -# skirt options +# skirt/brim options our $skirts = 1; our $skirt_distance = 6; # mm our $skirt_height = 1; # layers +our $brim_thickness = 0; # mm # transform options our $scale = 1; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 5cd0e38a8..41cdd72a7 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -406,7 +406,7 @@ our $Options = { type => 'bool', }, - # skirt options + # skirt/brim options 'skirts' => { label => 'Loops', cli => 'skirts=i', @@ -415,13 +415,18 @@ our $Options = { 'skirt_distance' => { label => 'Distance from object (mm)', cli => 'skirt-distance=f', - type => 'i', + type => 'f', }, 'skirt_height' => { label => 'Skirt height (layers)', cli => 'skirt-height=i', type => 'i', }, + 'brim_thickness' => { + label => 'Brim thickness (mm)', + cli => 'brim-thickness=f', + type => 'f', + }, # transform options 'scale' => { diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 4975b4b1e..e5a9f5ce0 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -44,7 +44,7 @@ sub new { }, print => { title => 'Print settings', - options => [qw(perimeters solid_layers fill_density fill_angle fill_pattern solid_fill_pattern randomize_start support_material support_material_tool)], + options => [qw(perimeters solid_layers fill_density fill_angle fill_pattern solid_fill_pattern randomize_start support_material)], }, retract => { title => 'Retraction', @@ -57,7 +57,7 @@ sub new { }, skirt => { title => 'Skirt', - options => [qw(skirts skirt_distance skirt_height)], + options => [qw(skirts skirt_distance skirt_height brim_thickness)], }, gcode => { title => 'G-code', @@ -78,7 +78,7 @@ sub new { }, other => { title => 'Other', - options => [ ($Slic3r::have_threads ? qw(threads) : ()), qw(extra_perimeters) ], + options => [ ($Slic3r::have_threads ? qw(threads) : ()), qw(extra_perimeters support_material_tool) ], }, notes => { title => 'Notes', diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 5962a2140..6d257ff9f 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -147,12 +147,14 @@ sub rotate { my $self = shift; my ($angle, $center) = @_; @$self = Slic3r::Geometry::rotate_points($angle, $center, @$self); + return $self; } sub translate { my $self = shift; my ($x, $y) = @_; @$self = Slic3r::Geometry::move_points([$x, $y], @$self); + return $self; } 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 19b33a370..9d4221cca 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -20,6 +20,13 @@ has 'skirt' => ( default => sub { [] }, ); +# ordered collection of extrusion paths to build a brim +has 'brim' => ( + is => 'rw', + #isa => 'ArrayRef[Slic3r::ExtrusionLoop]', + default => sub { [] }, +); + sub add_object_from_file { my $self = shift; my ($input_file) = @_; @@ -306,6 +313,7 @@ sub export_gcode { # make skirt $status_cb->(88, "Generating skirt"); $self->make_skirt; + $self->make_brim; # output everything to a G-code file my $output_file = $self->expanded_output_filepath($params{output_file}); @@ -438,9 +446,10 @@ sub make_skirt { my $convex_hull = convex_hull(\@points); # draw outlines from outside to inside + my $flow = $Slic3r::first_layer_flow || $Slic3r::flow; my @skirt = (); for (my $i = $Slic3r::skirts; $i > 0; $i--) { - my $distance = scale ($Slic3r::skirt_distance + ($Slic3r::flow->spacing * $i)); + my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i)); my $outline = offset([$convex_hull], $distance, $Slic3r::scaling_factor * 100, JT_ROUND); push @skirt, Slic3r::ExtrusionLoop->new( polygon => Slic3r::Polygon->new(@{$outline->[0]}), @@ -450,6 +459,28 @@ sub make_skirt { unshift @{$self->skirt}, @skirt; } +sub make_brim { + my $self = shift; + return unless $Slic3r::brim_thickness > 0; + + my @islands = (); # array of polygons + foreach my $obj_idx (0 .. $#{$self->objects}) { + my @object_islands = map $_->contour, @{ $self->objects->[$obj_idx]->layers->[0]->slices }; + foreach my $copy (@{$self->copies->[$obj_idx]}) { + push @islands, map $_->clone->translate(@$copy), @object_islands; + } + } + + my $flow = $Slic3r::first_layer_flow || $Slic3r::flow; + my $num_loops = sprintf "%.0f", $Slic3r::brim_thickness / $flow->width; + for my $i (reverse 1 .. $num_loops) { + push @{$self->brim}, Slic3r::ExtrusionLoop->new( + polygon => Slic3r::Polygon->new($_), + role => EXTR_ROLE_SKIRT, + ) for @{Math::Clipper::offset(\@islands, $i * scale $flow->spacing)}; + } +} + sub write_gcode { my $self = shift; my ($file) = @_; @@ -535,12 +566,18 @@ sub write_gcode { $extruder->shift_x($shift[X]); $extruder->shift_y($shift[Y]); $gcode .= $extruder->set_acceleration($Slic3r::perimeter_acceleration); - if ($layer_id < $Slic3r::skirt_height) { + # skip skirt if we have a large brim + if ($layer_id < $Slic3r::skirt_height && ($layer_id != 0 || $Slic3r::skirt_distance + ($Slic3r::skirts * $Slic3r::flow->width) > $Slic3r::brim_thickness)) { $gcode .= $extruder->extrude_loop($_, 'skirt') for @{$self->skirt}; } $skirt_done++; } + # extrude brim + if ($layer_id == 0) { + $gcode .= $extruder->extrude_loop($_, 'brim') for @{$self->brim}; + } + for my $obj_copy (@$object_copies) { my ($obj_idx, $copy) = @$obj_copy; my $layer = $self->objects->[$obj_idx]->layers->[$layer_id]; diff --git a/slic3r.pl b/slic3r.pl index f388acb01..2ee61fae4 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -238,6 +238,8 @@ $j --skirt-distance Distance in mm between innermost skirt and object (default: $Slic3r::skirt_distance) --skirt-height Height of skirts to draw (expressed in layers, 0+, default: $Slic3r::skirt_height) + --brim-thickness Thickness of the brim that will get added to each object to help adhesion + (mm, default: $Slic3r::brim_thickness) Transform options: --scale Factor for scaling input object (default: $Slic3r::scale)