Browse Source

More work for refactoring Flow/Extruder

Alessandro Ranellucci 11 years ago
parent
commit
a2cbb261cb

+ 1 - 1
lib/Slic3r.pm

@@ -78,7 +78,7 @@ use constant SCALING_FACTOR         => 0.000001;
 use constant RESOLUTION             => 0.0125;
 use constant RESOLUTION             => 0.0125;
 use constant SCALED_RESOLUTION      => RESOLUTION / SCALING_FACTOR;
 use constant SCALED_RESOLUTION      => RESOLUTION / SCALING_FACTOR;
 use constant SMALL_PERIMETER_LENGTH => (6.5 / SCALING_FACTOR) * 2 * PI;
 use constant SMALL_PERIMETER_LENGTH => (6.5 / SCALING_FACTOR) * 2 * PI;
-use constant LOOP_CLIPPING_LENGTH_OVER_SPACING      => 0.15;
+use constant LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER => 0.15;
 use constant INFILL_OVERLAP_OVER_SPACING  => 0.45;
 use constant INFILL_OVERLAP_OVER_SPACING  => 0.45;
 use constant EXTERNAL_INFILL_MARGIN => 3;
 use constant EXTERNAL_INFILL_MARGIN => 3;
 
 

+ 3 - 1
lib/Slic3r/Fill.pm

@@ -168,7 +168,9 @@ sub make_fill {
         );
         );
         next unless @polylines;
         next unless @polylines;
         
         
-        my $mm3_per_mm = $params->{flow}->mm3_per_mm($surface->thickness);
+        my $h = $surface->thickness;
+        $h = $layerm->height if $h == -1;
+        my $mm3_per_mm = $params->{flow}->mm3_per_mm($h);
         
         
         # save into layer
         # save into layer
         push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new;
         push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new;

+ 11 - 5
lib/Slic3r/Fill/Concentric.pm

@@ -15,16 +15,22 @@ sub fill_surface {
     my $expolygon = $surface->expolygon;
     my $expolygon = $surface->expolygon;
     my $bounding_box = $expolygon->bounding_box;
     my $bounding_box = $expolygon->bounding_box;
     
     
-    my $min_spacing = scale $params{flow_spacing};
+    my $flow = $params{flow};
+    my $min_spacing = $flow->scaled_spacing;
     my $distance = $min_spacing / $params{density};
     my $distance = $min_spacing / $params{density};
     
     
-    my $flow_spacing = $params{flow_spacing};
+    my $flow_spacing = $flow->spacing;
     if ($params{density} == 1 && !$params{dont_adjust}) {
     if ($params{density} == 1 && !$params{dont_adjust}) {
         $distance = $self->adjust_solid_spacing(
         $distance = $self->adjust_solid_spacing(
             width       => $bounding_box->size->[X],
             width       => $bounding_box->size->[X],
             distance    => $distance,
             distance    => $distance,
         );
         );
-        $flow_spacing = unscale $distance;
+        $flow = Slic3r::Flow->new_from_spacing(
+            spacing             => unscale($distance),
+            nozzle_diameter     => $flow->nozzle_diameter,
+            layer_height        => $surface->thickness,
+            bridge              => $flow->bridge,
+        );
     }
     }
     
     
     # compensate the overlap which is good for rectilinear but harmful for concentric
     # compensate the overlap which is good for rectilinear but harmful for concentric
@@ -48,11 +54,11 @@ sub fill_surface {
     }
     }
     
     
     # clip the paths to avoid the extruder to get exactly on the first point of the loop
     # clip the paths to avoid the extruder to get exactly on the first point of the loop
-    my $clip_length = scale $flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING;
+    my $clip_length = scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
     $_->clip_end($clip_length) for @paths;
     $_->clip_end($clip_length) for @paths;
     
     
     # TODO: return ExtrusionLoop objects to get better chained paths
     # TODO: return ExtrusionLoop objects to get better chained paths
-    return { flow_spacing => $flow_spacing, no_sort => 1 }, @paths;
+    return { flow => $flow, no_sort => 1 }, @paths;
 }
 }
 
 
 1;
 1;

+ 3 - 2
lib/Slic3r/Fill/PlanePath.pm

@@ -27,7 +27,8 @@ sub fill_surface {
     my $rotate_vector = $self->infill_direction($surface);
     my $rotate_vector = $self->infill_direction($surface);
     $self->rotate_points($expolygon, $rotate_vector);
     $self->rotate_points($expolygon, $rotate_vector);
     
     
-    my $distance_between_lines = scale $params{flow_spacing} / $params{density} * $self->multiplier;
+    my $flow = $params{flow};
+    my $distance_between_lines = $flow->scaled_spacing / $params{density} * $self->multiplier;
     my $bounding_box = $expolygon->bounding_box;
     my $bounding_box = $expolygon->bounding_box;
     
     
     (ref $self) =~ /::([^:]+)$/;
     (ref $self) =~ /::([^:]+)$/;
@@ -54,7 +55,7 @@ sub fill_surface {
     # paths must be rotated back
     # paths must be rotated back
     $self->rotate_points_back(\@paths, $rotate_vector);
     $self->rotate_points_back(\@paths, $rotate_vector);
     
     
-    return { flow_spacing => $params{flow_spacing} }, @paths;
+    return { flow => $flow }, @paths;
 }
 }
 
 
 1;
 1;

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

@@ -17,7 +17,7 @@ sub fill_surface {
     my $rotate_vector = $self->infill_direction($surface);
     my $rotate_vector = $self->infill_direction($surface);
     $self->rotate_points($expolygon, $rotate_vector);
     $self->rotate_points($expolygon, $rotate_vector);
     
     
-    my $flow                = $params{flow};
+    my $flow                = $params{flow} or die "No flow supplied to fill_surface()";
     my $min_spacing         = $flow->scaled_spacing;
     my $min_spacing         = $flow->scaled_spacing;
     my $line_spacing        = $min_spacing / $params{density};
     my $line_spacing        = $min_spacing / $params{density};
     my $line_oscillation    = $line_spacing - $min_spacing;
     my $line_oscillation    = $line_spacing - $min_spacing;

+ 3 - 3
lib/Slic3r/GCode.pm

@@ -235,7 +235,7 @@ sub extrude_loop {
     # clip the path to avoid the extruder to get exactly on the first point of the 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
     # if polyline was shorter than the clipping distance we'd get a null polyline, so
     # we discard it in that case
     # 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($self->extruder->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER)
         if $self->enable_loop_clipping;
         if $self->enable_loop_clipping;
     return '' if !@{$extrusion_path->polyline};
     return '' if !@{$extrusion_path->polyline};
     
     
@@ -251,7 +251,7 @@ sub extrude_loop {
         push @paths,
         push @paths,
             map {
             map {
                 $_->role(EXTR_ROLE_OVERHANG_PERIMETER);
                 $_->role(EXTR_ROLE_OVERHANG_PERIMETER);
-                $_->flow_spacing($self->region->flow(FLOW_ROLE_PERIMETER, undef, 1)->width);
+                $_->mm3_per_mm($self->region->flow(FLOW_ROLE_PERIMETER, undef, 1)->mm3_per_mm(undef));
                 $_
                 $_
             }
             }
             map $_->clone,
             map $_->clone,
@@ -287,7 +287,7 @@ sub extrude_loop {
         # we make sure we don't exceed the segment length because we don't know
         # we make sure we don't exceed the segment length because we don't know
         # the rotation of the second segment so we might cross the object boundary
         # the rotation of the second segment so we might cross the object boundary
         my $first_segment = Slic3r::Line->new(@{$extrusion_path->polyline}[0,1]);
         my $first_segment = Slic3r::Line->new(@{$extrusion_path->polyline}[0,1]);
-        my $distance = min(scale $extrusion_path->flow_spacing, $first_segment->length);
+        my $distance = min(scale($self->extruder->nozzle_diameter), $first_segment->length);
         my $point = $first_segment->point_at($distance);
         my $point = $first_segment->point_at($distance);
         $point->rotate($angle, $extrusion_path->first_point);
         $point->rotate($angle, $extrusion_path->first_point);
         
         

+ 9 - 1
lib/Slic3r/Print.pm

@@ -19,6 +19,8 @@ has 'extra_variables'        => (is => 'rw', default => sub {{}});
 has 'objects'                => (is => 'rw', default => sub {[]});
 has 'objects'                => (is => 'rw', default => sub {[]});
 has 'status_cb'              => (is => 'rw');
 has 'status_cb'              => (is => 'rw');
 has 'regions'                => (is => 'rw', default => sub {[]});
 has 'regions'                => (is => 'rw', default => sub {[]});
+has 'total_used_filament'    => (is => 'rw');
+has 'total_extruded_volume'  => (is => 'rw');
 has '_state'                 => (is => 'ro', default => sub { Slic3r::Print::State->new });
 has '_state'                 => (is => 'ro', default => sub { Slic3r::Print::State->new });
 
 
 # ordered collection of extrusion paths to build skirt loops
 # ordered collection of extrusion paths to build skirt loops
@@ -970,7 +972,13 @@ sub write_gcode {
     print $fh $gcodegen->set_fan(0);
     print $fh $gcodegen->set_fan(0);
     printf $fh "%s\n", $gcodegen->replace_variables($self->config->end_gcode);
     printf $fh "%s\n", $gcodegen->replace_variables($self->config->end_gcode);
     
     
-    foreach my $extruder (@{$self->extruders}) {
+    $self->total_used_filament(0);
+    $self->total_extruded_volume(0);
+    foreach my $extruder_id (@{$self->extruders}) {
+        my $extruder = $gcodegen->extruders->[$extruder_id];
+        $self->total_used_filament($self->total_used_filament + $extruder->absolute_E);
+        $self->total_extruded_volume($self->total_extruded_volume + $extruder->extruded_volume);
+        
         printf $fh "; filament used = %.1fmm (%.1fcm3)\n",
         printf $fh "; filament used = %.1fmm (%.1fcm3)\n",
             $extruder->absolute_E, $extruder->extruded_volume/1000;
             $extruder->absolute_E, $extruder->extruded_volume/1000;
     }
     }

+ 2 - 1
lib/Slic3r/Print/Simple.pm

@@ -6,7 +6,8 @@ use Slic3r::Geometry qw(X Y);
 has '_print' => (
 has '_print' => (
     is      => 'ro',
     is      => 'ro',
     default => sub { Slic3r::Print->new },
     default => sub { Slic3r::Print->new },
-    handles => [qw(apply_config extruders expanded_output_filepath)],
+    handles => [qw(apply_config extruders expanded_output_filepath
+                    total_used_filament total_extruded_volume)],
 );
 );
 
 
 has 'duplicate' => (
 has 'duplicate' => (

+ 2 - 3
slic3r.pl

@@ -163,9 +163,8 @@ if (@ARGV) {  # slicing from command line
                 printf "Done. Process took %d minutes and %.3f seconds\n", 
                 printf "Done. Process took %d minutes and %.3f seconds\n", 
                     int($duration/60), ($duration - int($duration/60)*60);  # % truncates to integer
                     int($duration/60), ($duration - int($duration/60)*60);  # % truncates to integer
             }
             }
-            print map sprintf("Filament required: %.1fmm (%.1fcm3)\n",
-                $_->absolute_E, $_->extruded_volume/1000),
-                @{$sprint->extruders};
+            printf "Filament required: %.1fmm (%.1fcm3)\n",
+                $sprint->total_used_filament, $sprint->total_extruded_volume/1000;
         }
         }
     }
     }
 } else {
 } else {

+ 13 - 3
t/fill.t

@@ -43,9 +43,14 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
         surface_type    => S_TYPE_TOP,
         surface_type    => S_TYPE_TOP,
         expolygon       => $expolygon,
         expolygon       => $expolygon,
     );
     );
+    my $flow = Slic3r::Flow->new(
+        width           => 0.69,
+        spacing         => 0.69,
+        nozzle_diameter => 0.50,
+    );
     foreach my $angle (0, 45) {
     foreach my $angle (0, 45) {
         $surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]);
         $surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]);
-        my ($params, @paths) = $filler->fill_surface($surface, flow_spacing => 0.69, density => 0.4);
+        my ($params, @paths) = $filler->fill_surface($surface, flow => $flow, density => 0.4);
         is scalar @paths, 1, 'one continuous path';
         is scalar @paths, 1, 'one continuous path';
     }
     }
 }
 }
@@ -62,14 +67,19 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
             surface_type    => S_TYPE_BOTTOM,
             surface_type    => S_TYPE_BOTTOM,
             expolygon       => $expolygon,
             expolygon       => $expolygon,
         );
         );
+        my $flow = Slic3r::Flow->new(
+            width           => $flow_spacing,
+            spacing         => $flow_spacing,
+            nozzle_diameter => $flow_spacing,
+        );
         my ($params, @paths) = $filler->fill_surface(
         my ($params, @paths) = $filler->fill_surface(
             $surface,
             $surface,
-            flow_spacing    => $flow_spacing,
+            flow            => $flow,
             density         => $density // 1,
             density         => $density // 1,
         );
         );
         
         
         # check whether any part was left uncovered
         # check whether any part was left uncovered
-        my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2)}, @paths;
+        my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $params->{flow}->spacing/2)}, @paths;
         my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
         my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
         
         
         # ignore very small dots
         # ignore very small dots