Implemented retraction and fixed extrusion math

This commit is contained in:
Alessandro Ranellucci 2011-09-05 18:52:09 +02:00
parent 5595839b31
commit d8b848a67f
5 changed files with 87 additions and 29 deletions

View File

@ -33,6 +33,7 @@ Slic3r is able to:
* read binary and ASCII STL files;
* generate multiple perimeters (skins);
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
* retraction;
* use relative or absolute extrusion commands;
* center print around bed center point;
* use different speed for bottom layer;
@ -42,10 +43,10 @@ Roadmap includes the following goals:
* output some statistics;
* allow the user to customize initial and final GCODE commands;
* retraction;
* option for filling multiple solid layers near external surfaces;
* support material for internal perimeters;
* ability to infill in the direction of bridges;
* extra perimeters on alternate layers;
* skirt;
* cool;
* nice packaging for cross-platform deployment.

View File

@ -24,15 +24,20 @@ use Slic3r::Surface;
our $layer_height = 0.4;
our $resolution = 0.1;
our $perimeter_offsets = 3;
our $fill_density = 0.2; # 1 = 100%
our $flow_width = 0.4;
our $fill_density = 0.4; # 1 = 100%
our $filament_diameter = 3; # mm
our $filament_packing_density = 0.85;
our $flow_width = 0.50;
our $temperature = 195;
our $flow_rate = 60; # mm/sec
our $print_feed_rate = 60; # mm/sec
our $travel_feed_rate = 80; # mm/sec
our $bottom_layer_speed_ratio = 0.6;
our $retract_length = 2; # mm
our $retract_restart_extra = 0; # mm
our $retract_speed = 40; # mm/sec
our $use_relative_e_distances = 0;
our $print_center = [100,100]; # object will be centered around this point

View File

@ -19,7 +19,7 @@ sub make_fill {
# let's alternate fill direction
my @axes = $layer->id % 2 == 0 ? (0,1) : (1,0);
foreach my $surface (@{ $layer->fill_surfaces }) {
SURFACE: foreach my $surface (@{ $layer->fill_surfaces }) {
Slic3r::debugf " Processing surface %s:\n", $surface->id;
my $polygon = $surface->mgp_polygon;
@ -30,6 +30,7 @@ sub make_fill {
# force 100% density for external surfaces
my $density = $surface->surface_type eq 'internal' ? $Slic3r::fill_density : 1;
next SURFACE unless $density > 0;
my $distance_between_lines = $Slic3r::flow_width / $Slic3r::resolution / $density;
my $number_of_lines = ($axes[0] == 0 ? $print->x_length : $print->y_length) / $distance_between_lines;
@ -96,7 +97,7 @@ sub make_fill {
# loop through rows
ROW: for (my $i = 0; $i < $number_of_lines; $i++) {
my $row = $points->[$i];
my $row = $points->[$i] or next ROW;
Slic3r::debugf "Processing row %d...\n", $i;
if (!@$row) {
Slic3r::debugf " no points\n";

View File

@ -1,6 +1,7 @@
package Slic3r::Print;
use Moose;
use constant PI => 4 * atan2(1, 1);
use constant X => 0;
use constant Y => 1;
@ -75,10 +76,10 @@ sub export_gcode {
# calculate speed for gcode commands
my $travel_feed_rate = $Slic3r::travel_feed_rate * 60; # mm/min
my $print_feed_rate = $Slic3r::print_feed_rate * 60; # mm/min
my $extrusion_speed_ratio = ($Slic3r::flow_rate / $Slic3r::print_feed_rate);
my $retract_speed = $Slic3r::retract_speed * 60; # mm/min
# calculate number of decimals
my $dec = length((1 / $Slic3r::resolution) - 1);
my $dec = length((1 / $Slic3r::resolution) - 1) + 1;
# calculate X,Y shift to center print around specified origin
my @shift = (
@ -103,17 +104,33 @@ sub export_gcode {
}
# make up a subroutine to generate G1 commands
my $extrusion_distance = 0;
my $G1 = sub {
my ($point, $z, $extrusion_distance, $comment) = @_;
printf $fh "G1 X%.${dec}f Y%.${dec}f Z%.${dec}f",
($point->x * $Slic3r::resolution) + $shift[X],
($point->y * $Slic3r::resolution) + $shift[Y], #**
$z;
my $speed_multiplier = $z == 0 ? $Slic3r::bottom_layer_speed_ratio : 1;
if ($extrusion_distance) {
printf $fh " F%.${dec}f E%.${dec}f",
($print_feed_rate * $speed_multiplier),
($extrusion_distance * $extrusion_speed_ratio * $Slic3r::resolution);
my ($point, $z, $e, $comment) = @_;
printf $fh "G1";
if ($point) {
printf $fh " X%.${dec}f Y%.${dec}f",
($point->x * $Slic3r::resolution) + $shift[X],
($point->y * $Slic3r::resolution) + $shift[Y]; #**
}
if ($z) {
printf $fh " Z%.${dec}f", $z;
}
# apply the speed reduction for print moves on bottom layer
my $speed_multiplier = defined $z && $z == 0 && $point
? $Slic3r::bottom_layer_speed_ratio
: 1;
if ($e) {
$extrusion_distance = 0 if $Slic3r::use_relative_e_distances;
$extrusion_distance += $e;
printf $fh " F%.${dec}f E%.5f",
$e < 0
? $retract_speed
: ($print_feed_rate * $speed_multiplier),
$extrusion_distance;
} else {
printf $fh " F%.${dec}f", ($travel_feed_rate * $speed_multiplier);
}
@ -122,26 +139,41 @@ sub export_gcode {
};
my $z;
my $retracted = 0;
my $Extrude = sub {
my ($path, $description) = @_;
# reset extrusion distance counter
my $extrusion_distance = 0;
if (!$Slic3r::use_relative_e_distances) {
$extrusion_distance = 0;
print $fh "G92 E0 ; reset extrusion distance\n";
}
# go to first point (without extruding)
$G1->($path->lines->[0]->a, $z, 0, "move to first $description point");
# go to first point while compensating retraction
$G1->($path->lines->[0]->a, $z,
$retracted
? ($Slic3r::retract_length + $Slic3r::retract_restart_extra)
: 0,
"move to first $description point");
# extrude while going to next points
foreach my $line (@{ $path->lines }) {
$extrusion_distance = 0 if $Slic3r::use_relative_e_distances;
$extrusion_distance += $line->a->distance_to($line->b);
$G1->($line->b, $z, $extrusion_distance, $description);
# calculate how much filament to drive into the extruder
# to get the desired amount of extruded plastic
my $e = $line->a->distance_to($line->b) * $Slic3r::resolution
* $Slic3r::flow_width
* $Slic3r::layer_height
/ (($Slic3r::filament_diameter ** 2) * PI)
/ $Slic3r::filament_packing_density;
$G1->($line->b, $z, $e, $description);
}
# TODO: retraction
# retract
if ($Slic3r::retract_length > 0) {
$G1->(undef, undef, -$Slic3r::retract_length, "retract");
$retracted = 1;
}
};
# write gcode commands layer by layer

View File

@ -10,6 +10,7 @@ BEGIN {
use Getopt::Long;
use Slic3r;
use Time::HiRes qw(gettimeofday tv_interval);
use XXX;
my %opt;
@ -23,15 +24,16 @@ GetOptions(
'resolution=f' => \$Slic3r::resolution,
'perimeters=i' => \$Slic3r::perimeter_offsets,
'fill-density=f' => \$Slic3r::fill_density,
'filament-diameter=f' => \$Slic3r::filament_diameter,
'flow-width=f' => \$Slic3r::flow_width,
'temperature=i' => \$Slic3r::temperature,
'flow-rate=i' => \$Slic3r::flow_rate,
'print-feed-rate=i' => \$Slic3r::print_feed_rate,
'travel-feed-rate=i' => \$Slic3r::travel_feed_rate,
'bottom-layer-speed-ratio=f' => \$Slic3r::bottom_layer_speed_ratio,
'use-relative-e-distances' => \$Slic3r::use_relative_e_distances,
'print-center=s' => \$Slic3r::print_center,
'',
'retract-length=f' => \$Slic3r::retract_length,
'retract-restart-extra=f' => \$Slic3r::retract_restart_extra,
);
# validate configuration
@ -42,6 +44,10 @@ GetOptions(
die "--layer-height must be a multiple of print resolution\n"
if $Slic3r::layer_height / $Slic3r::resolution % 1 != 0;
# --filament-diameter
die "Invalid value for --filament-diameter\n"
if $Slic3r::filament_diameter < 1;
# --flow-width
die "Invalid value for --flow-width\n"
if $Slic3r::flow_width < 0;
@ -72,6 +78,7 @@ if ($action eq 'skein') {
die "Input file must have .stl extension\n"
if $input_file !~ /\.stl$/i;
my $t0 = [gettimeofday];
my $print = $stl_parser->parse_file($input_file);
$print->extrude_perimeters;
$print->extrude_fills;
@ -79,6 +86,10 @@ if ($action eq 'skein') {
my $output_file = $input_file;
$output_file =~ s/\.stl$/.gcode/i;
$print->export_gcode($opt{output} || $output_file);
my $processing_time = tv_interval($t0);
printf "Done. Process took %d minutes and %.3f seconds\n",
int($processing_time/60), $processing_time - int($processing_time/60);
}
sub usage {
@ -93,14 +104,22 @@ Usage: slic3r.pl [ OPTIONS ] file.stl
--perimeters Number of perimeters/horizontal skins
(range: 1+, default: $Slic3r::perimeter_offsets)
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density)
--filament-diameter Diameter of your raw filament (default: $Slic3r::filament_diameter)
--filament-packing-density
Ratio of the extruded volume over volume pushed into
the extruder (default: $Slic3r::filament_packing_density)
--flow-width Width of extruded flow in mm (default: $Slic3r::flow_width)
--flow-rate Speed of extrusion in mm/sec; should be equal to
--print-feed-rate (default: $Slic3r::flow_rate)
--print-feed-rate Speed of print moves in mm/sec (default: $Slic3r::print_feed_rate)
--travel-feed-rate Speed of non-print moves in mm/sec (default: $Slic3r::travel_feed_rate)
--bottom-layer-speed-ratio
Factor to increase/decrease speeds on bottom layer by
(default: $Slic3r::bottom_layer_speed_ratio)
--retract-length Length of retraction in mm when pausing extrusion
(default: $Slic3r::retract_length)
--retract-speed Speed for retraction in mm/sec (default: $Slic3r::retract_speed)
--retract-restart-extra
Additional amount of filament in mm to push after compensating
retraction (default: $Slic3r::retract_restart_extra)
--use-relative-e-distances
Use relative distances for extrusion in GCODE output
--print-center Coordinates of the point to center the print around