From 5a78111efa6766f49f2291e37ca407ffbd2dc9ab Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 23 May 2012 11:47:52 +0200 Subject: [PATCH] Options to set extruder clearance for sequential printing and graphical preview of collisions --- README.markdown | 12 ++++++--- lib/Slic3r.pm | 6 ++++- lib/Slic3r/Config.pm | 30 ++++++++++++++++++----- lib/Slic3r/GUI/Plater.pm | 12 ++++++++- lib/Slic3r/GUI/SkeinPanel.pm | 9 +++++-- lib/Slic3r/Polygon.pm | 2 +- lib/Slic3r/Print.pm | 47 +++++++++++++++++++++++++++++++++++- slic3r.pl | 13 +++++++--- 8 files changed, 113 insertions(+), 18 deletions(-) diff --git a/README.markdown b/README.markdown index 985fc489e..96d2c2e1b 100644 --- a/README.markdown +++ b/README.markdown @@ -159,8 +159,6 @@ The author is Alessandro Ranellucci. --layer-gcode Load layer-change G-code from the supplied file (default: nothing). --support-material Generate support material for overhangs --randomize-start Randomize starting point across layers (default: yes) - --complete-objects When printing multiple objects and/or copies, complete each one before - starting the next one; watch out for extruder collisions (default: no) Retraction options: --retract-length Length of retraction in mm when pausing extrusion @@ -199,7 +197,15 @@ The author is Alessandro Ranellucci. --duplicate Number of items with auto-arrange (1+, default: 1) --bed-size Bed size, only used for auto-arrange (mm, default: 200,200) --duplicate-grid Number of items with grid arrangement (default: 1,1) - --duplicate-distance Distance in mm between copies (default: 6) + --duplicate-distance Distance in mm between copies (default: 6) + + Sequential printing options: + --complete-objects When printing multiple objects and/or copies, complete each one before + starting the next one; watch out for extruder collisions (default: no) + --extruder-clearance-radius Radius in mm above which extruder won't collide with anything + (default: 20) + --extruder-clearance-height Maximum vertical extruder depth; i.e. vertical distance from + extruder tip and carriage bottom (default: 20) Miscellaneous options: --notes Notes to be added as comments to the output file diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 4cea239b0..1773f6970 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -112,7 +112,6 @@ our $fill_angle = 45; our $randomize_start = 1; our $support_material = 0; our $support_material_tool = 0; -our $complete_objects = 0; our $start_gcode = "G28 ; home all axes"; our $end_gcode = <<"END"; M104 S0 ; turn off temperature @@ -153,6 +152,11 @@ our $bed_size = [200,200]; our $duplicate_grid = [1,1]; our $duplicate_distance = 6; # mm +# sequential printing +our $complete_objects = 0; +our $extruder_clearance_radius = 20; # mm +our $extruder_clearance_height = 20; # mm + sub parallelize { my %params = @_; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 25580a23a..582a42228 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -262,11 +262,6 @@ our $Options = { values => [0,1], labels => [qw(Primary Secondary)], }, - 'complete_objects' => { - label => 'Complete individual objects (watch out for extruder collisions if you enable this)', - cli => 'complete-objects', - type => 'bool', - }, 'start_gcode' => { label => 'Start G-code', cli => 'start-gcode=s', @@ -442,6 +437,23 @@ our $Options = { type => 'i', aliases => [qw(multiply_distance)], }, + + # sequential printing options + 'complete_objects' => { + label => 'Complete individual objects (watch out for extruder collisions)', + cli => 'complete-objects', + type => 'bool', + }, + 'extruder_clearance_radius' => { + label => 'Extruder clearance radius (mm)', + cli => 'extruder-clearance-radius=f', + type => 'i', + }, + 'extruder_clearance_height' => { + label => 'Extruder clearance height (mm)', + cli => 'extruder-clearance-height=f', + type => 'i', + }, }; sub get { @@ -671,7 +683,13 @@ sub validate { # --bridge-flow-ratio die "Invalid value for --bridge-flow-ratio\n" if $Slic3r::bridge_flow_ratio <= 0; - + + # extruder clearance + die "Invalid value for --extruder-clearance-radius\n" + if $Slic3r::extruder_clearance_radius <= 0; + die "Invalid value for --extruder-clearance-height\n" + if $Slic3r::extruder_clearance_height <= 0; + $Slic3r::first_layer_temperature //= $Slic3r::temperature; #/ $Slic3r::first_layer_bed_temperature //= $Slic3r::bed_temperature; #/ diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 1da4fe755..4f5e799ea 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -43,6 +43,7 @@ sub new { $self->{transparent_brush} = Wx::Brush->new(Wx::Colour->new(0,0,0), &Wx::wxTRANSPARENT); $self->{grid_pen} = Wx::Pen->new(Wx::Colour->new(230,230,230), 1, &Wx::wxSOLID); $self->{print_center_pen} = Wx::Pen->new(Wx::Colour->new(200,200,200), 1, &Wx::wxSOLID); + $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, &Wx::wxSOLID); $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, &Wx::wxSOLID); $self->{list} = Wx::ListView->new($self, -1, [-1, -1], [-1, 180], &Wx::wxLC_SINGLE_SEL | &Wx::wxLC_REPORT | &Wx::wxBORDER_DEFAULT); @@ -470,7 +471,7 @@ sub export_gcode { }, message_dialog => sub { Wx::MessageDialog->new($self, @_)->ShowModal }, on_completed => sub { $self->on_export_completed(@_) }, - catch_error => sub { Slic3r::GUI::catch_error($self, @_) }, + catch_error => sub { Slic3r::GUI::catch_error($self, @_) && $self->on_export_failed }, ); } } @@ -489,6 +490,7 @@ sub export_gcode2 { Slic3r::Config->validate; my $print = $self->{print}; + $print->validate; { my @warnings = (); @@ -704,6 +706,14 @@ sub repaint { $dc->SetBrush($parent->{objects_brush}); } $dc->DrawPolygon($parent->_y($parent->{object_previews}->[-1][2]), 0, 0); + + # if sequential printing is enabled and we have more than one object + if ($Slic3r::complete_objects && (map @$_, @{$print->copies}) > 1) { + my $clearance = +($parent->{object_previews}->[-1][2]->offset($Slic3r::extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0]; + $dc->SetPen($parent->{clearance_pen}); + $dc->SetBrush($parent->{transparent_brush}); + $dc->DrawPolygon($parent->_y($clearance), 0, 0); + } } } diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 03b334df3..8c5ff1d35 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -61,9 +61,13 @@ sub new { }, gcode => { title => 'G-code', - options => [qw(start_gcode end_gcode layer_gcode complete_objects gcode_comments post_process)], + options => [qw(start_gcode end_gcode layer_gcode gcode_comments post_process)], label_width => 260, }, + sequential_printing => { + title => 'Sequential printing', + options => [qw(complete_objects extruder_clearance_radius extruder_clearance_height)], + }, extrusion => { title => 'Extrusion', options => [qw(extrusion_width_ratio bridge_flow_ratio)], @@ -116,7 +120,7 @@ sub new { $make_tab->([qw(cooling)]), $make_tab->([qw(printer filament)], [qw(print_speed speed)]), $make_tab->([qw(gcode)]), - $make_tab->([qw(extrusion other)], [qw(output)]), + $make_tab->([qw(extrusion other sequential_printing)], [qw(output)]), ); $tabpanel->AddPage(Slic3r::GUI::Plater->new($tabpanel), "Plater"); @@ -215,6 +219,7 @@ sub do_slice { my $print = Slic3r::Print->new; $print->add_object_from_file($input_file); + $print->validate; # select output file my $output_file = $main::opt{output}; diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 22f1fef25..a0416e8d4 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -100,7 +100,7 @@ sub offset { $miterLimit ||= 2; my $offsets = Math::Clipper::offset([$self], $distance, $scale, $joinType, $miterLimit); - return @$offsets; + return map Slic3r::Polygon->new($_), @$offsets; } # this method subdivides the polygon segments to that no one of them diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 894676867..18a117209 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -5,7 +5,7 @@ use File::Basename qw(basename fileparse); use Math::ConvexHull 1.0.4 qw(convex_hull); use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 PI scale unscale move_points); -use Slic3r::Geometry::Clipper qw(diff_ex union_ex offset JT_ROUND); +use Slic3r::Geometry::Clipper qw(diff_ex union_ex intersection_ex offset JT_ROUND); use Time::HiRes qw(gettimeofday tv_interval); has 'objects' => (is => 'rw', default => sub {[]}); @@ -65,6 +65,51 @@ sub add_object_from_mesh { return $object; } +sub validate { + my $self = shift; + + if ($Slic3r::complete_objects) { + # check horizontal clearance + { + my @a = (); + for my $obj_idx (0 .. $#{$self->objects}) { + my $clearance; + { + my @points = map [ @$_[X,Y] ], @{$self->objects->[$obj_idx]->mesh->vertices}; + my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points)); + $clearance = +($convex_hull->offset(scale $Slic3r::extruder_clearance_radius / 2, 1, JT_ROUND))[0]; + } + for my $copy (@{$self->copies->[$obj_idx]}) { + my $copy_clearance = $clearance->clone; + $copy_clearance->translate(@$copy); + if (@{ intersection_ex(\@a, [$copy_clearance]) }) { + die "Some objects are too close; your extruder will collide with them.\n"; + } + @a = map @$_, @{union_ex([ @a, $copy_clearance ])}; + } + } + } + + # check vertical clearance + { + my @obj_copies = $self->object_copies; + pop @obj_copies; # ignore the last copy: its height doesn't matter + if (grep { +($self->objects->[$_->[0]]->mesh->size)[Z] > scale $Slic3r::extruder_clearance_height } @obj_copies) { + die "Some objects are too tall and cannot be printed without extruder collisions.\n"; + } + } + } +} + +sub object_copies { + my $self = shift; + my @oc = (); + for my $obj_idx (0 .. $#{$self->objects}) { + push @oc, map [ $obj_idx, $_ ], @{$self->copies->[$obj_idx]}; + } + return @oc; +} + sub cleanup { my $self = shift; $_->cleanup for @{$self->objects}; diff --git a/slic3r.pl b/slic3r.pl index 470a44468..6ea7f7822 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -86,6 +86,7 @@ if (@ARGV) { } $print->duplicate; $print->arrange_objects if @{$print->objects} > 1; + $print->validate; my %params = ( output_file => $opt{output}, status_cb => sub { @@ -202,8 +203,6 @@ $j --layer-gcode Load layer-change G-code from the supplied file (default: nothing). --support-material Generate support material for overhangs --randomize-start Randomize starting point across layers (default: yes) - --complete-objects When printing multiple objects and/or copies, complete each one before - starting the next one; watch out for extruder collisions (default: no) Retraction options: --retract-length Length of retraction in mm when pausing extrusion @@ -243,7 +242,15 @@ $j --bed-size Bed size, only used for auto-arrange (mm, default: $Slic3r::bed_size->[0],$Slic3r::bed_size->[1]) --duplicate-grid Number of items with grid arrangement (default: $Slic3r::duplicate_grid->[0],$Slic3r::duplicate_grid->[1]) --duplicate-distance Distance in mm between copies (default: $Slic3r::duplicate_distance) - + + Sequential printing options: + --complete-objects When printing multiple objects and/or copies, complete each one before + starting the next one; watch out for extruder collisions (default: no) + --extruder-clearance-radius Radius in mm above which extruder won't collide with anything + (default: $Slic3r::extruder_clearance_radius) + --extruder-clearance-height Maximum vertical extruder depth; i.e. vertical distance from + extruder tip and carriage bottom (default: $Slic3r::extruder_clearance_height) + Miscellaneous options: --notes Notes to be added as comments to the output file