diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 710e33e19..f2bea526c 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -78,7 +78,7 @@ use constant SCALING_FACTOR => 0.000001; use constant RESOLUTION => 0.0125; use constant SCALED_RESOLUTION => RESOLUTION / SCALING_FACTOR; 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 EXTERNAL_INFILL_MARGIN => 3; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 45508169f..c128d0eb3 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -168,7 +168,9 @@ sub make_fill { ); 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 push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new; diff --git a/lib/Slic3r/Fill/Concentric.pm b/lib/Slic3r/Fill/Concentric.pm index 5649a8aa7..0bb1f5061 100644 --- a/lib/Slic3r/Fill/Concentric.pm +++ b/lib/Slic3r/Fill/Concentric.pm @@ -15,16 +15,22 @@ sub fill_surface { my $expolygon = $surface->expolygon; 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 $flow_spacing = $params{flow_spacing}; + my $flow_spacing = $flow->spacing; if ($params{density} == 1 && !$params{dont_adjust}) { $distance = $self->adjust_solid_spacing( width => $bounding_box->size->[X], 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 @@ -48,11 +54,11 @@ sub fill_surface { } # 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; # 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; diff --git a/lib/Slic3r/Fill/PlanePath.pm b/lib/Slic3r/Fill/PlanePath.pm index 0797fd10e..d393f9049 100644 --- a/lib/Slic3r/Fill/PlanePath.pm +++ b/lib/Slic3r/Fill/PlanePath.pm @@ -27,7 +27,8 @@ sub fill_surface { my $rotate_vector = $self->infill_direction($surface); $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; (ref $self) =~ /::([^:]+)$/; @@ -54,7 +55,7 @@ sub fill_surface { # paths must be rotated back $self->rotate_points_back(\@paths, $rotate_vector); - return { flow_spacing => $params{flow_spacing} }, @paths; + return { flow => $flow }, @paths; } 1; diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm index 39fa5b941..acf7c1090 100644 --- a/lib/Slic3r/Fill/Rectilinear.pm +++ b/lib/Slic3r/Fill/Rectilinear.pm @@ -17,7 +17,7 @@ sub fill_surface { my $rotate_vector = $self->infill_direction($surface); $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 $line_spacing = $min_spacing / $params{density}; my $line_oscillation = $line_spacing - $min_spacing; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index a8f7526ad..b1c05d95d 100644 --- a/lib/Slic3r/GCode.pm +++ b/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; # 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($self->extruder->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER) if $self->enable_loop_clipping; return '' if !@{$extrusion_path->polyline}; @@ -251,7 +251,7 @@ sub extrude_loop { push @paths, map { $_->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, @@ -287,7 +287,7 @@ sub extrude_loop { # 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 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); $point->rotate($angle, $extrusion_path->first_point); diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index ebaba5ce1..f31e6665a 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -19,6 +19,8 @@ has 'extra_variables' => (is => 'rw', default => sub {{}}); has 'objects' => (is => 'rw', default => sub {[]}); has 'status_cb' => (is => 'rw'); 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 }); # ordered collection of extrusion paths to build skirt loops @@ -970,7 +972,13 @@ sub write_gcode { print $fh $gcodegen->set_fan(0); 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", $extruder->absolute_E, $extruder->extruded_volume/1000; } diff --git a/lib/Slic3r/Print/Simple.pm b/lib/Slic3r/Print/Simple.pm index a6f756343..ded003063 100644 --- a/lib/Slic3r/Print/Simple.pm +++ b/lib/Slic3r/Print/Simple.pm @@ -6,7 +6,8 @@ use Slic3r::Geometry qw(X Y); has '_print' => ( is => 'ro', 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' => ( diff --git a/slic3r.pl b/slic3r.pl index bb2f7280e..e27e7d323 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -163,9 +163,8 @@ if (@ARGV) { # slicing from command line printf "Done. Process took %d minutes and %.3f seconds\n", 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 { diff --git a/t/fill.t b/t/fill.t index 424b206df..8e112484a 100644 --- a/t/fill.t +++ b/t/fill.t @@ -43,9 +43,14 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } surface_type => S_TYPE_TOP, expolygon => $expolygon, ); + my $flow = Slic3r::Flow->new( + width => 0.69, + spacing => 0.69, + nozzle_diameter => 0.50, + ); foreach my $angle (0, 45) { $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'; } } @@ -62,14 +67,19 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } surface_type => S_TYPE_BOTTOM, expolygon => $expolygon, ); + my $flow = Slic3r::Flow->new( + width => $flow_spacing, + spacing => $flow_spacing, + nozzle_diameter => $flow_spacing, + ); my ($params, @paths) = $filler->fill_surface( $surface, - flow_spacing => $flow_spacing, + flow => $flow, density => $density // 1, ); # 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); # ignore very small dots