Browse Source

New --perimeters-extrusion-width and --infill-extrusion-width options. #302

Alessandro Ranellucci 12 years ago
parent
commit
82dd3c7a3e

+ 1 - 0
MANIFEST

@@ -18,6 +18,7 @@ lib/Slic3r/Fill/Line.pm
 lib/Slic3r/Fill/OctagramSpiral.pm
 lib/Slic3r/Fill/PlanePath.pm
 lib/Slic3r/Fill/Rectilinear.pm
+lib/Slic3r/Flow.pm
 lib/Slic3r/Format/AMF.pm
 lib/Slic3r/Format/AMF/Parser.pm
 lib/Slic3r/Format/OBJ.pm

+ 4 - 0
README.markdown

@@ -210,6 +210,10 @@ The author is Alessandro Ranellucci.
        Flow options (advanced):
         --extrusion-width   Set extrusion width manually; it accepts either an absolute value in mm
                             (like 0.65) or a percentage over layer height (like 200%)
+        --perimeters-extrusion-width
+                        Set a different extrusion width for perimeters
+        --infill-extrusion-width
+                        Set a different extrusion width for infill
         --bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: 1)
         
 

+ 11 - 10
lib/Slic3r.pm

@@ -33,6 +33,7 @@ use Slic3r::ExtrusionPath;
 use Slic3r::ExtrusionPath::Arc;
 use Slic3r::ExtrusionPath::Collection;
 use Slic3r::Fill;
+use Slic3r::Flow;
 use Slic3r::Format::AMF;
 use Slic3r::Format::OBJ;
 use Slic3r::Format::STL;
@@ -100,16 +101,16 @@ our $_first_layer_height    = undef;   # mm (computed)
 our $infill_every_layers    = 1;
 
 # flow options
-our $extrusion_width        = 0;
-our $first_layer_extrusion_width = 0;
-our $bridge_flow_ratio      = 1;
-our $overlap_factor         = 0.5;
-our $flow_width;
-our $min_flow_spacing;
-our $flow_spacing;
-our $first_layer_flow_width;
-our $first_layer_min_flow_spacing;
-our $first_layer_flow_spacing;
+our $extrusion_width                = 0;
+our $first_layer_extrusion_width    = 0;
+our $perimeters_extrusion_width     = 0;
+our $infill_extrusion_width         = 0;
+our $bridge_flow_ratio              = 1;
+our $overlap_factor                 = 0.5;
+our $flow                           = Slic3r::Flow->new;
+our $first_layer_flow               = undef;
+our $perimeters_flow                = Slic3r::Flow->new;
+our $infill_flow                    = Slic3r::Flow->new;
 
 # print options
 our $perimeters         = 3;

+ 18 - 51
lib/Slic3r/Config.pm

@@ -204,10 +204,20 @@ our $Options = {
         type    => 'f',
     },
     'first_layer_extrusion_width' => {
-        label   => 'First layer extrusion width (mm or %; leave zero to use default)',
+        label   => 'First layer extrusion width (mm or % or 0 for default)',
         cli     => 'first-layer-extrusion-width=s',
         type    => 'f',
     },
+    'perimeters_extrusion_width' => {
+        label   => 'Perimeters extrusion width (mm or % or 0 for default)',
+        cli     => 'perimeters-extrusion-width=s',
+        type    => 'f',
+    },
+    'infill_extrusion_width' => {
+        label   => 'Infill extrusion width (mm or % or 0 for default)',
+        cli     => 'infill-extrusion-width=s',
+        type    => 'f',
+    },
     'bridge_flow_ratio' => {
         label   => 'Bridge flow ratio',
         cli     => 'bridge-flow-ratio=f',
@@ -596,16 +606,13 @@ sub validate {
         if $Slic3r::_first_layer_height > $Slic3r::nozzle_diameter;
     
     # calculate flow
-    ($Slic3r::flow_width, $Slic3r::min_flow_spacing, $Slic3r::flow_spacing) = calculate_flow($Slic3r::extrusion_width);
-    Slic3r::debugf "Flow width = $Slic3r::flow_width\n";
-    Slic3r::debugf "Flow spacing = $Slic3r::flow_spacing\n";
-    Slic3r::debugf "Min flow spacing = $Slic3r::min_flow_spacing\n";
-    
-    # calculate first layer flow
-    ($Slic3r::first_layer_flow_width, $Slic3r::first_layer_min_flow_spacing, $Slic3r::first_layer_flow_spacing) = calculate_flow($Slic3r::first_layer_extrusion_width || $Slic3r::extrusion_width);
-    Slic3r::debugf "First Layer Flow width = $Slic3r::first_layer_flow_width\n";
-    Slic3r::debugf "First Layer Flow spacing = $Slic3r::first_layer_flow_spacing\n";
-    Slic3r::debugf "First Layer Min flow spacing = $Slic3r::first_layer_min_flow_spacing\n";
+    $Slic3r::flow->calculate($Slic3r::extrusion_width);
+    $Slic3r::first_layer_flow->calculate($Slic3r::first_layer_extrusion_width)
+        if $Slic3r::first_layer_extrusion_width;
+    $Slic3r::perimeters_flow->calculate($Slic3r::perimeters_extrusion_width || $Slic3r::extrusion_width);
+    $Slic3r::infill_flow->calculate($Slic3r::infill_extrusion_width || $Slic3r::extrusion_width);
+    Slic3r::debugf "Default flow width = %s, spacing = %s, min_spacing = %d\n",
+        $Slic3r::flow->width, $Slic3r::flow->spacing, $Slic3r::flow->min_spacing;
     
     # --perimeters
     die "Invalid value for --perimeters\n"
@@ -723,44 +730,4 @@ sub replace_options {
     return $string;
 }
 
-sub calculate_flow {
-    my ($extrusion_width) = @_;
-    
-    my ($flow_width, $min_flow_spacing, $flow_spacing);
-    if ($extrusion_width) {
-        $flow_width = $extrusion_width =~ /^(\d+(?:\.\d+)?)%$/
-            ? ($Slic3r::layer_height * $1 / 100)
-            : $extrusion_width;
-    } else {
-        # here we calculate a sane default by matching the flow speed (at the nozzle)
-        # and the feed rate
-        my $volume = ($Slic3r::nozzle_diameter**2) * PI/4;
-        my $shape_threshold = $Slic3r::nozzle_diameter * $Slic3r::layer_height
-            + ($Slic3r::layer_height**2) * PI/4;
-        if ($volume >= $shape_threshold) {
-            # rectangle with semicircles at the ends
-            $flow_width = (($Slic3r::nozzle_diameter**2) * PI + ($Slic3r::layer_height**2) * (4 - PI)) / (4 * $Slic3r::layer_height);
-        } else {
-            # rectangle with squished semicircles at the ends
-            $flow_width = $Slic3r::nozzle_diameter * ($Slic3r::nozzle_diameter/$Slic3r::layer_height - 4/PI + 1);
-        }
-        
-        my $min_flow_width = $Slic3r::nozzle_diameter * 1.05;
-        my $max_flow_width = $Slic3r::nozzle_diameter * 1.4;
-        $flow_width = $max_flow_width if $flow_width > $max_flow_width;
-        $flow_width = $min_flow_width if $flow_width < $min_flow_width;
-    }
-    
-    if ($flow_width >= ($Slic3r::nozzle_diameter + $Slic3r::layer_height)) {
-        # rectangle with semicircles at the ends
-        $min_flow_spacing = $flow_width - $Slic3r::layer_height * (1 - PI/4);
-    } else {
-        # rectangle with shrunk semicircles at the ends
-        $min_flow_spacing = $flow_width * (1 - PI/4) + $Slic3r::nozzle_diameter * PI/4;
-    }
-    $flow_spacing = $flow_width - $Slic3r::overlap_factor * ($flow_width - $min_flow_spacing);
-    
-    return ($flow_width, $min_flow_spacing, $flow_spacing);
-}
-
 1;

+ 4 - 4
lib/Slic3r/Extruder.pm

@@ -102,7 +102,7 @@ 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($self->layer->flow_width || $Slic3r::flow_width) * 0.15);
+    $extrusion_path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15);
     return '' if !@{$extrusion_path->polyline};
     
     # extrude along the path
@@ -129,7 +129,7 @@ sub extrude_path {
     {
         my $distance_from_last_pos = $self->last_pos->distance_to($path->points->[0]) * $Slic3r::scaling_factor;
         my $distance_threshold = $Slic3r::retract_before_travel;
-        $distance_threshold = 2 * ($self->layer->flow_width || $Slic3r::flow_width) / $Slic3r::fill_density * sqrt(2)
+        $distance_threshold = 2 * ($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) / $Slic3r::fill_density * sqrt(2)
             if $Slic3r::fill_density > 0 && $description =~ /fill/;
     
         if ($distance_from_last_pos >= $distance_threshold) {
@@ -145,9 +145,9 @@ sub extrude_path {
     $gcode .= $self->unretract if $self->retracted;
     
     # calculate extrusion length per distance unit
-    my $s = $path->flow_spacing || $self->layer->flow_spacing || $Slic3r::flow_spacing;
+    my $s = $path->flow_spacing || $self->layer ? $self->layer->flow->spacing : $Slic3r::flow->spacing;
     my $h = $path->depth_layers * $self->layer->height;
-    my $w = ($s - $Slic3r::min_flow_spacing * $Slic3r::overlap_factor) / (1 - $Slic3r::overlap_factor);
+    my $w = ($s - ($self->layer ? $self->layer->flow->min_spacing : $Slic3r::flow->min_spacing) * $Slic3r::overlap_factor) / (1 - $Slic3r::overlap_factor);
     
     my $area;
     if ($path->role == EXTR_ROLE_BRIDGE) {

+ 2 - 2
lib/Slic3r/Fill.pm

@@ -99,7 +99,7 @@ sub make_fill {
     
     # add spacing between adjacent surfaces
     {
-        my $distance = scale $layer->flow_spacing / 2;
+        my $distance = scale $layer->flow->spacing / 2;
         my @offsets = ();
         foreach my $surface (@surfaces) {
             my $expolygon = $surface->expolygon;
@@ -137,7 +137,7 @@ sub make_fill {
     SURFACE: foreach my $surface (@surfaces) {
         my $filler          = $Slic3r::fill_pattern;
         my $density         = $Slic3r::fill_density;
-        my $flow_spacing    = $layer->flow_spacing;
+        my $flow_spacing    = $layer->flow->spacing;
         my $is_bridge       = $layer->id > 0 && $surface->surface_type == S_TYPE_BOTTOM;
         my $is_solid        = (grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID) ? 1 : 0;
         

+ 1 - 1
lib/Slic3r/Fill/Concentric.pm

@@ -64,7 +64,7 @@ sub fill_surface {
         $path->deserialize;
         
         # clip the path to avoid the extruder to get exactly on the first point of the loop
-        $path->clip_end(scale($self->layer->flow_width || $Slic3r::flow_width) * 0.15);
+        $path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15);
         
         push @paths, $path->points if @{$path->points};
     }

+ 1 - 1
lib/Slic3r/Fill/Honeycomb.pm

@@ -21,7 +21,7 @@ sub fill_surface {
     # infill math
     my $min_spacing = scale $params{flow_spacing};
     my $distance = $min_spacing / $params{density};
-    my $overlap_distance = scale($self->layer->flow_width || $Slic3r::flow_width) * 0.4;
+    my $overlap_distance = scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.4;
     
     my $cache_id = sprintf "d%s_s%s_a%s",
         $params{density}, $params{flow_spacing}, $rotate_vector->[0][0];

+ 1 - 1
lib/Slic3r/Fill/Rectilinear.pm

@@ -32,7 +32,7 @@ sub fill_surface {
         $flow_spacing = unscale $distance_between_lines;
     }
     
-    my $overlap_distance = scale($self->layer->flow_width || $Slic3r::flow_width) * 0.4;
+    my $overlap_distance = scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.4;
     
     my $x = $bounding_box->[X1];
     my $is_line_pattern = $self->isa('Slic3r::Fill::Line');

+ 53 - 0
lib/Slic3r/Flow.pm

@@ -0,0 +1,53 @@
+package Slic3r::Flow;
+use Moo;
+
+use Slic3r::Geometry qw(PI);
+
+has 'width' => (is => 'rw');
+has 'min_spacing' => (is => 'rw');
+has 'spacing' => (is => 'rw');
+
+sub calculate {
+    my $self = shift;
+    my ($extrusion_width) = @_;
+    
+    my ($flow_width, $min_flow_spacing, $flow_spacing);
+    if ($extrusion_width) {
+        $flow_width = $extrusion_width =~ /^(\d+(?:\.\d+)?)%$/
+            ? ($Slic3r::layer_height * $1 / 100)
+            : $extrusion_width;
+    } else {
+        # here we calculate a sane default by matching the flow speed (at the nozzle)
+        # and the feed rate
+        my $volume = ($Slic3r::nozzle_diameter**2) * PI/4;
+        my $shape_threshold = $Slic3r::nozzle_diameter * $Slic3r::layer_height
+            + ($Slic3r::layer_height**2) * PI/4;
+        if ($volume >= $shape_threshold) {
+            # rectangle with semicircles at the ends
+            $flow_width = (($Slic3r::nozzle_diameter**2) * PI + ($Slic3r::layer_height**2) * (4 - PI)) / (4 * $Slic3r::layer_height);
+        } else {
+            # rectangle with squished semicircles at the ends
+            $flow_width = $Slic3r::nozzle_diameter * ($Slic3r::nozzle_diameter/$Slic3r::layer_height - 4/PI + 1);
+        }
+        
+        my $min_flow_width = $Slic3r::nozzle_diameter * 1.05;
+        my $max_flow_width = $Slic3r::nozzle_diameter * 1.4;
+        $flow_width = $max_flow_width if $flow_width > $max_flow_width;
+        $flow_width = $min_flow_width if $flow_width < $min_flow_width;
+    }
+    
+    if ($flow_width >= ($Slic3r::nozzle_diameter + $Slic3r::layer_height)) {
+        # rectangle with semicircles at the ends
+        $min_flow_spacing = $flow_width - $Slic3r::layer_height * (1 - PI/4);
+    } else {
+        # rectangle with shrunk semicircles at the ends
+        $min_flow_spacing = $flow_width * (1 - PI/4) + $Slic3r::nozzle_diameter * PI/4;
+    }
+    $flow_spacing = $flow_width - $Slic3r::overlap_factor * ($flow_width - $min_flow_spacing);
+    
+    $self->width($flow_width);
+    $self->min_spacing($min_flow_spacing);
+    $self->spacing($flow_spacing);
+}
+
+1;

Some files were not shown because too many files changed in this diff