From 91cade7e8f0b1b4c160bde4df77c1c785923632b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 28 Jul 2013 13:39:15 +0200 Subject: [PATCH] Make sure there are no gaps in spiral vase. Includes regression test. #1251 --- lib/Slic3r/GCode.pm | 4 +++- lib/Slic3r/GCode/Layer.pm | 14 ++++++++++---- lib/Slic3r/GCode/SpiralVase.pm | 19 +++++++++++++++---- t/shells.t | 25 ++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 71a9afbe8..d2710af43 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -10,6 +10,7 @@ use Slic3r::Surface ':types'; has 'config' => (is => 'ro', required => 1); has 'extruders' => (is => 'ro', default => sub {0}, required => 1); has 'multiple_extruders' => (is => 'lazy'); +has 'enable_loop_clipping' => (is => 'rw', default => sub {1}); has 'enable_wipe' => (is => 'lazy'); # at least one extruder has wipe enabled has 'layer_count' => (is => 'ro', required => 1 ); has 'layer' => (is => 'rw'); @@ -195,7 +196,8 @@ sub extrude_loop { # clip the path to avoid the extruder to get exactly on the first point of the loop; # if polyline was shorter than the clipping distance we'd get a null polyline, so # we discard it in that case - $extrusion_path->clip_end(scale $extrusion_path->flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING); + $extrusion_path->clip_end(scale $extrusion_path->flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING) + if $self->enable_loop_clipping; return '' if !@{$extrusion_path->polyline}; my @paths = (); diff --git a/lib/Slic3r/GCode/Layer.pm b/lib/Slic3r/GCode/Layer.pm index 26db9fc06..df3e85b94 100644 --- a/lib/Slic3r/GCode/Layer.pm +++ b/lib/Slic3r/GCode/Layer.pm @@ -27,6 +27,15 @@ sub process_layer { my ($layer, $object_copies) = @_; my $gcode = ""; + # check whether we're going to apply spiralvase logic + my $spiralvase = defined $self->spiralvase + && ($layer->id > 0 || $Slic3r::Config->brim_width == 0) + && ($layer->id >= $Slic3r::Config->skirt_height) + && ($layer->id >= $Slic3r::Config->bottom_solid_layers); + + # if we're going to apply spiralvase to this layer, disable loop clipping + $self->gcodegen->enable_loop_clipping(!$spiralvase); + if (!$self->second_layer_things_done && $layer->id == 1) { for my $t (grep $self->extruders->[$_], 0 .. $#{$Slic3r::Config->temperature}) { $gcode .= $self->gcodegen->set_temperature($self->extruders->[$t]->temperature, 0, $t) @@ -167,10 +176,7 @@ sub process_layer { # apply spiral vase post-processing if this layer contains suitable geometry $gcode = $self->spiralvase->process_layer($gcode, $layer) - if defined $self->spiralvase - && ($layer->id > 0 || $Slic3r::Config->brim_width == 0) - && ($layer->id >= $Slic3r::Config->skirt_height) - && ($layer->id >= $Slic3r::Config->bottom_solid_layers); + if $spiralvase; return $gcode; } diff --git a/lib/Slic3r/GCode/SpiralVase.pm b/lib/Slic3r/GCode/SpiralVase.pm index 5c0a50fd3..dc67aafc4 100644 --- a/lib/Slic3r/GCode/SpiralVase.pm +++ b/lib/Slic3r/GCode/SpiralVase.pm @@ -17,6 +17,7 @@ sub process_layer { my $new_gcode = ""; my $layer_height = $layer->height; my $z = unscale($layer->print_z) - $layer_height; + my $newlayer = 0; Slic3r::GCode::Reader->new(gcode => $gcode)->parse(sub { my ($reader, $cmd, $args, $info) = @_; @@ -24,11 +25,21 @@ sub process_layer { my $line = $info->{raw}; $line =~ s/Z([^ ]+)/Z$z/; $new_gcode .= "$line\n"; - } elsif ($cmd eq 'G1' && !exists $args->{Z} && $info->{extruding} && $info->{dist_XY}) { - $z += $info->{dist_XY} * $layer_height / $total_layer_length; + $newlayer = 1; + } elsif ($cmd eq 'G1' && !exists $args->{Z} && $info->{dist_XY}) { my $line = $info->{raw}; - $line =~ s/^G1 /sprintf 'G1 Z%.3f ', $z/e; - $new_gcode .= "$line\n"; + if ($info->{extruding}) { + $z += $info->{dist_XY} * $layer_height / $total_layer_length; + $line =~ s/^G1 /sprintf 'G1 Z%.3f ', $z/e; + $new_gcode .= "$line\n"; + } elsif ($newlayer) { + # remove the first travel move after layer change; extrusion + # will just blend to the first loop vertex + # TODO: should we adjust (stretch) E for the first loop segment? + $newlayer = 0; + } else { + $new_gcode .= "$line\n"; + } } else { $new_gcode .= "$info->{raw}\n"; } diff --git a/t/shells.t b/t/shells.t index d84adb3e1..0da0099ea 100644 --- a/t/shells.t +++ b/t/shells.t @@ -1,4 +1,4 @@ -use Test::More tests => 4; +use Test::More tests => 5; use strict; use warnings; @@ -99,4 +99,27 @@ use Slic3r::Test; "shells are not propagated across perimeters of the neighbor layer"; } +{ + my $config = Slic3r::Config->new_from_defaults; + $config->set('spiral_vase', 1); + $config->set('bottom_solid_layers', 0); + $config->set('skirts', 0); + + # TODO: this needs to be tested with a model with sloping edges, where starting + # points of each layer are not aligned - in that case we would test that no + # travel moves are left to move to the new starting point - in a cube, end + # points coincide with next layer starting points (provided there's no clipping) + my $print = Slic3r::Test::init_print('20mm_cube', config => $config); + my $travel_moves_after_first_extrusion = 0; + my $started_extruding = 0; + Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub { + my ($self, $cmd, $args, $info) = @_; + + $started_extruding = 1 if $info->{extruding}; + $travel_moves_after_first_extrusion++ + if $info->{travel} && $started_extruding && !exists $args->{Z}; + }); + is $travel_moves_after_first_extrusion, 0, "no gaps in spiral vase"; +} + __END__