Browse Source

New --spiral-vase option to continously raise Z when printing single-walled vases. #997

Alessandro Ranellucci 12 years ago
parent
commit
ccdb29ddc9
8 changed files with 81 additions and 1 deletions
  1. 1 0
      MANIFEST
  2. 2 0
      README.markdown
  3. 1 0
      lib/Slic3r.pm
  4. 7 0
      lib/Slic3r/Config.pm
  5. 40 0
      lib/Slic3r/GCode/SpiralVase.pm
  6. 1 1
      lib/Slic3r/GUI/Tab.pm
  7. 27 0
      lib/Slic3r/Print.pm
  8. 2 0
      slic3r.pl

+ 1 - 0
MANIFEST

@@ -27,6 +27,7 @@ lib/Slic3r/GCode.pm
 lib/Slic3r/GCode/CoolingBuffer.pm
 lib/Slic3r/GCode/MotionPlanner.pm
 lib/Slic3r/GCode/Reader.pm
+lib/Slic3r/GCode/SpiralVase.pm
 lib/Slic3r/Geometry.pm
 lib/Slic3r/Geometry/Clipper.pm
 lib/Slic3r/GUI.pm

+ 2 - 0
README.markdown

@@ -198,6 +198,8 @@ The author of the Silk icon set is Mark James.
         --randomize-start   Randomize starting point across layers (default: yes)
         --avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no)
         --external-perimeters-first Reverse perimeter order. (default: no)
+        --spiral-vase       Experimental option to raise Z gradually when printing single-walled vases
+                            (default: no)
         --only-retract-when-crossing-perimeters
                             Disable retraction when travelling between infill paths inside the same island.
                             (default: yes)

+ 1 - 0
lib/Slic3r.pm

@@ -48,6 +48,7 @@ use Slic3r::GCode;
 use Slic3r::GCode::CoolingBuffer;
 use Slic3r::GCode::MotionPlanner;
 use Slic3r::GCode::Reader;
+use Slic3r::GCode::SpiralVase;
 use Slic3r::Geometry qw(PI);
 use Slic3r::Layer;
 use Slic3r::Layer::Region;

+ 7 - 0
lib/Slic3r/Config.pm

@@ -586,6 +586,13 @@ our $Options = {
         type    => 'bool',
         default => 0,
     },
+    'spiral_vase' => {
+        label   => 'Spiral vase',
+        tooltip => 'This experimental feature will raise Z gradually while printing a single-walled object in order to remove any visible seam. By enabling this option other settings will be overridden to enforce a single perimeter, no infill, no top solid layers, no support material. You can still set any number of bottom solid layers as well as skirt/brim loops. It won\'t work when printing more than an object.',
+        cli     => 'spiral-vase!',
+        type    => 'bool',
+        default => 0,
+    },
     'only_retract_when_crossing_perimeters' => {
         label   => 'Only retract when crossing perimeters',
         tooltip => 'Disables retraction when travelling between infill paths inside the same island.',

+ 40 - 0
lib/Slic3r/GCode/SpiralVase.pm

@@ -0,0 +1,40 @@
+package Slic3r::GCode::SpiralVase;
+use Moo;
+
+use Slic3r::Geometry qw(unscale);
+
+sub process_layer {
+    my $self = shift;
+    my ($gcode, $layer) = @_;
+    
+    my $total_layer_length = 0;
+    Slic3r::GCode::Reader->new(gcode => $gcode)->parse(sub {
+        my ($reader, $cmd, $args, $info) = @_;
+        $total_layer_length += $info->{dist_XY}
+            if $cmd eq 'G1' && $info->{extruding};
+    });
+    
+    my $new_gcode = "";
+    my $layer_height = $layer->height;
+    my $z = unscale($layer->print_z) - $layer_height;
+    Slic3r::GCode::Reader->new(gcode => $gcode)->parse(sub {
+        my ($reader, $cmd, $args, $info) = @_;
+        
+        if ($cmd eq 'G1' && exists $args->{Z}) {
+            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;
+            my $line = $info->{raw};
+            $line =~ s/^G1 /sprintf 'G1 Z%.3f ', $z/e;
+            $new_gcode .= "$line\n";
+        } else {
+            $new_gcode .= "$info->{raw}\n";
+        }
+    });
+    
+    return $new_gcode;
+}
+
+1;

+ 1 - 1
lib/Slic3r/GUI/Tab.pm

@@ -412,7 +412,7 @@ sub build {
         },
         {
             title => 'Advanced',
-            options => [qw(avoid_crossing_perimeters external_perimeters_first)],
+            options => [qw(avoid_crossing_perimeters external_perimeters_first spiral_vase)],
         },
     ]);
     

+ 27 - 0
lib/Slic3r/Print.pm

@@ -63,6 +63,14 @@ sub _trigger_config {
     # G-code flavors
     $self->config->set('extrusion_axis', 'A') if $self->config->gcode_flavor eq 'mach3';
     $self->config->set('extrusion_axis', '')  if $self->config->gcode_flavor eq 'no-extrusion';
+    
+    # enforce some settings when spiral_vase is set
+    if ($self->config->spiral_vase) {
+        $self->config->set('perimeters', 1);
+        $self->config->set('fill_density', 0);
+        $self->config->set('top_solid_layers', 0);
+        $self->config->set('support_material', 0);
+    }
 }
 
 sub _build_has_support_material {
@@ -184,6 +192,12 @@ sub validate {
             }
         }
     }
+    
+    if ($Slic3r::Config->spiral_vase) {
+        if ((map @{$_->copies}, @{$self->objects}) > 1) {
+            die "The Spiral Vase option can only be used when printing a single object.\n";
+        }
+    }
 }
 
 sub init_extruders {
@@ -794,6 +808,11 @@ sub write_gcode {
         ));
     }
     
+    # prepare the SpiralVase processor if it's possible
+    my $spiralvase = $Slic3r::Config->spiral_vase
+        ? Slic3r::GCode::SpiralVase->new
+        : undef;
+    
     # prepare the logic to print one layer
     my $skirt_done = 0;  # count of skirt layers done
     my $brim_done = 0;
@@ -956,6 +975,14 @@ sub write_gcode {
                 }
             }
         }
+        
+        # apply spiral vase post-processing if this layer contains suitable geometry
+        $gcode = $spiralvase->process_layer($gcode, $layer)
+            if defined $spiralvase
+            && ($layer->id > 0 || $Slic3r::Config->brim_width == 0)
+            && ($layer->id >= $Slic3r::Config->skirt_height)
+            && ($layer->id >= $Slic3r::Config->bottom_solid_layers);
+        
         return $gcode;
     };
     

+ 2 - 0
slic3r.pl

@@ -251,6 +251,8 @@ $j
     --randomize-start   Randomize starting point across layers (default: yes)
     --avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no)
     --external-perimeters-first Reverse perimeter order. (default: no)
+    --spiral-vase       Experimental option to raise Z gradually when printing single-walled vases
+                        (default: no)
     --only-retract-when-crossing-perimeters
                         Disable retraction when travelling between infill paths inside the same island.
                         (default: no)