Implemented retraction and fixed extrusion math
This commit is contained in:
parent
5595839b31
commit
d8b848a67f
@ -33,6 +33,7 @@ Slic3r is able to:
|
|||||||
* read binary and ASCII STL files;
|
* read binary and ASCII STL files;
|
||||||
* generate multiple perimeters (skins);
|
* generate multiple perimeters (skins);
|
||||||
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
|
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
|
||||||
|
* retraction;
|
||||||
* use relative or absolute extrusion commands;
|
* use relative or absolute extrusion commands;
|
||||||
* center print around bed center point;
|
* center print around bed center point;
|
||||||
* use different speed for bottom layer;
|
* use different speed for bottom layer;
|
||||||
@ -42,10 +43,10 @@ Roadmap includes the following goals:
|
|||||||
|
|
||||||
* output some statistics;
|
* output some statistics;
|
||||||
* allow the user to customize initial and final GCODE commands;
|
* allow the user to customize initial and final GCODE commands;
|
||||||
* retraction;
|
|
||||||
* option for filling multiple solid layers near external surfaces;
|
* option for filling multiple solid layers near external surfaces;
|
||||||
* support material for internal perimeters;
|
* support material for internal perimeters;
|
||||||
* ability to infill in the direction of bridges;
|
* ability to infill in the direction of bridges;
|
||||||
|
* extra perimeters on alternate layers;
|
||||||
* skirt;
|
* skirt;
|
||||||
* cool;
|
* cool;
|
||||||
* nice packaging for cross-platform deployment.
|
* nice packaging for cross-platform deployment.
|
||||||
|
@ -24,15 +24,20 @@ use Slic3r::Surface;
|
|||||||
our $layer_height = 0.4;
|
our $layer_height = 0.4;
|
||||||
our $resolution = 0.1;
|
our $resolution = 0.1;
|
||||||
our $perimeter_offsets = 3;
|
our $perimeter_offsets = 3;
|
||||||
our $fill_density = 0.2; # 1 = 100%
|
our $fill_density = 0.4; # 1 = 100%
|
||||||
our $flow_width = 0.4;
|
our $filament_diameter = 3; # mm
|
||||||
|
our $filament_packing_density = 0.85;
|
||||||
|
our $flow_width = 0.50;
|
||||||
our $temperature = 195;
|
our $temperature = 195;
|
||||||
|
|
||||||
our $flow_rate = 60; # mm/sec
|
|
||||||
our $print_feed_rate = 60; # mm/sec
|
our $print_feed_rate = 60; # mm/sec
|
||||||
our $travel_feed_rate = 80; # mm/sec
|
our $travel_feed_rate = 80; # mm/sec
|
||||||
our $bottom_layer_speed_ratio = 0.6;
|
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 $use_relative_e_distances = 0;
|
||||||
|
|
||||||
our $print_center = [100,100]; # object will be centered around this point
|
our $print_center = [100,100]; # object will be centered around this point
|
||||||
|
@ -19,7 +19,7 @@ sub make_fill {
|
|||||||
# let's alternate fill direction
|
# let's alternate fill direction
|
||||||
my @axes = $layer->id % 2 == 0 ? (0,1) : (1,0);
|
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;
|
Slic3r::debugf " Processing surface %s:\n", $surface->id;
|
||||||
my $polygon = $surface->mgp_polygon;
|
my $polygon = $surface->mgp_polygon;
|
||||||
|
|
||||||
@ -30,6 +30,7 @@ sub make_fill {
|
|||||||
|
|
||||||
# force 100% density for external surfaces
|
# force 100% density for external surfaces
|
||||||
my $density = $surface->surface_type eq 'internal' ? $Slic3r::fill_density : 1;
|
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 $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;
|
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
|
# loop through rows
|
||||||
ROW: for (my $i = 0; $i < $number_of_lines; $i++) {
|
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;
|
Slic3r::debugf "Processing row %d...\n", $i;
|
||||||
if (!@$row) {
|
if (!@$row) {
|
||||||
Slic3r::debugf " no points\n";
|
Slic3r::debugf " no points\n";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package Slic3r::Print;
|
package Slic3r::Print;
|
||||||
use Moose;
|
use Moose;
|
||||||
|
|
||||||
|
use constant PI => 4 * atan2(1, 1);
|
||||||
use constant X => 0;
|
use constant X => 0;
|
||||||
use constant Y => 1;
|
use constant Y => 1;
|
||||||
|
|
||||||
@ -75,10 +76,10 @@ sub export_gcode {
|
|||||||
# calculate speed for gcode commands
|
# calculate speed for gcode commands
|
||||||
my $travel_feed_rate = $Slic3r::travel_feed_rate * 60; # mm/min
|
my $travel_feed_rate = $Slic3r::travel_feed_rate * 60; # mm/min
|
||||||
my $print_feed_rate = $Slic3r::print_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
|
# 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
|
# calculate X,Y shift to center print around specified origin
|
||||||
my @shift = (
|
my @shift = (
|
||||||
@ -103,17 +104,33 @@ sub export_gcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# make up a subroutine to generate G1 commands
|
# make up a subroutine to generate G1 commands
|
||||||
|
my $extrusion_distance = 0;
|
||||||
my $G1 = sub {
|
my $G1 = sub {
|
||||||
my ($point, $z, $extrusion_distance, $comment) = @_;
|
my ($point, $z, $e, $comment) = @_;
|
||||||
printf $fh "G1 X%.${dec}f Y%.${dec}f Z%.${dec}f",
|
printf $fh "G1";
|
||||||
|
|
||||||
|
if ($point) {
|
||||||
|
printf $fh " X%.${dec}f Y%.${dec}f",
|
||||||
($point->x * $Slic3r::resolution) + $shift[X],
|
($point->x * $Slic3r::resolution) + $shift[X],
|
||||||
($point->y * $Slic3r::resolution) + $shift[Y], #**
|
($point->y * $Slic3r::resolution) + $shift[Y]; #**
|
||||||
$z;
|
}
|
||||||
my $speed_multiplier = $z == 0 ? $Slic3r::bottom_layer_speed_ratio : 1;
|
if ($z) {
|
||||||
if ($extrusion_distance) {
|
printf $fh " Z%.${dec}f", $z;
|
||||||
printf $fh " F%.${dec}f E%.${dec}f",
|
}
|
||||||
($print_feed_rate * $speed_multiplier),
|
|
||||||
($extrusion_distance * $extrusion_speed_ratio * $Slic3r::resolution);
|
# 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 {
|
} else {
|
||||||
printf $fh " F%.${dec}f", ($travel_feed_rate * $speed_multiplier);
|
printf $fh " F%.${dec}f", ($travel_feed_rate * $speed_multiplier);
|
||||||
}
|
}
|
||||||
@ -122,26 +139,41 @@ sub export_gcode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
my $z;
|
my $z;
|
||||||
|
my $retracted = 0;
|
||||||
my $Extrude = sub {
|
my $Extrude = sub {
|
||||||
my ($path, $description) = @_;
|
my ($path, $description) = @_;
|
||||||
|
|
||||||
# reset extrusion distance counter
|
# reset extrusion distance counter
|
||||||
my $extrusion_distance = 0;
|
|
||||||
if (!$Slic3r::use_relative_e_distances) {
|
if (!$Slic3r::use_relative_e_distances) {
|
||||||
|
$extrusion_distance = 0;
|
||||||
print $fh "G92 E0 ; reset extrusion distance\n";
|
print $fh "G92 E0 ; reset extrusion distance\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
# go to first point (without extruding)
|
# go to first point while compensating retraction
|
||||||
$G1->($path->lines->[0]->a, $z, 0, "move to first $description point");
|
$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
|
# extrude while going to next points
|
||||||
foreach my $line (@{ $path->lines }) {
|
foreach my $line (@{ $path->lines }) {
|
||||||
$extrusion_distance = 0 if $Slic3r::use_relative_e_distances;
|
# calculate how much filament to drive into the extruder
|
||||||
$extrusion_distance += $line->a->distance_to($line->b);
|
# to get the desired amount of extruded plastic
|
||||||
$G1->($line->b, $z, $extrusion_distance, $description);
|
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
|
# write gcode commands layer by layer
|
||||||
|
27
slic3r.pl
27
slic3r.pl
@ -10,6 +10,7 @@ BEGIN {
|
|||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Slic3r;
|
use Slic3r;
|
||||||
|
use Time::HiRes qw(gettimeofday tv_interval);
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
my %opt;
|
my %opt;
|
||||||
@ -23,15 +24,16 @@ GetOptions(
|
|||||||
'resolution=f' => \$Slic3r::resolution,
|
'resolution=f' => \$Slic3r::resolution,
|
||||||
'perimeters=i' => \$Slic3r::perimeter_offsets,
|
'perimeters=i' => \$Slic3r::perimeter_offsets,
|
||||||
'fill-density=f' => \$Slic3r::fill_density,
|
'fill-density=f' => \$Slic3r::fill_density,
|
||||||
|
'filament-diameter=f' => \$Slic3r::filament_diameter,
|
||||||
'flow-width=f' => \$Slic3r::flow_width,
|
'flow-width=f' => \$Slic3r::flow_width,
|
||||||
'temperature=i' => \$Slic3r::temperature,
|
'temperature=i' => \$Slic3r::temperature,
|
||||||
'flow-rate=i' => \$Slic3r::flow_rate,
|
|
||||||
'print-feed-rate=i' => \$Slic3r::print_feed_rate,
|
'print-feed-rate=i' => \$Slic3r::print_feed_rate,
|
||||||
'travel-feed-rate=i' => \$Slic3r::travel_feed_rate,
|
'travel-feed-rate=i' => \$Slic3r::travel_feed_rate,
|
||||||
'bottom-layer-speed-ratio=f' => \$Slic3r::bottom_layer_speed_ratio,
|
'bottom-layer-speed-ratio=f' => \$Slic3r::bottom_layer_speed_ratio,
|
||||||
'use-relative-e-distances' => \$Slic3r::use_relative_e_distances,
|
'use-relative-e-distances' => \$Slic3r::use_relative_e_distances,
|
||||||
'print-center=s' => \$Slic3r::print_center,
|
'print-center=s' => \$Slic3r::print_center,
|
||||||
'',
|
'retract-length=f' => \$Slic3r::retract_length,
|
||||||
|
'retract-restart-extra=f' => \$Slic3r::retract_restart_extra,
|
||||||
);
|
);
|
||||||
|
|
||||||
# validate configuration
|
# validate configuration
|
||||||
@ -42,6 +44,10 @@ GetOptions(
|
|||||||
die "--layer-height must be a multiple of print resolution\n"
|
die "--layer-height must be a multiple of print resolution\n"
|
||||||
if $Slic3r::layer_height / $Slic3r::resolution % 1 != 0;
|
if $Slic3r::layer_height / $Slic3r::resolution % 1 != 0;
|
||||||
|
|
||||||
|
# --filament-diameter
|
||||||
|
die "Invalid value for --filament-diameter\n"
|
||||||
|
if $Slic3r::filament_diameter < 1;
|
||||||
|
|
||||||
# --flow-width
|
# --flow-width
|
||||||
die "Invalid value for --flow-width\n"
|
die "Invalid value for --flow-width\n"
|
||||||
if $Slic3r::flow_width < 0;
|
if $Slic3r::flow_width < 0;
|
||||||
@ -72,6 +78,7 @@ if ($action eq 'skein') {
|
|||||||
die "Input file must have .stl extension\n"
|
die "Input file must have .stl extension\n"
|
||||||
if $input_file !~ /\.stl$/i;
|
if $input_file !~ /\.stl$/i;
|
||||||
|
|
||||||
|
my $t0 = [gettimeofday];
|
||||||
my $print = $stl_parser->parse_file($input_file);
|
my $print = $stl_parser->parse_file($input_file);
|
||||||
$print->extrude_perimeters;
|
$print->extrude_perimeters;
|
||||||
$print->extrude_fills;
|
$print->extrude_fills;
|
||||||
@ -79,6 +86,10 @@ if ($action eq 'skein') {
|
|||||||
my $output_file = $input_file;
|
my $output_file = $input_file;
|
||||||
$output_file =~ s/\.stl$/.gcode/i;
|
$output_file =~ s/\.stl$/.gcode/i;
|
||||||
$print->export_gcode($opt{output} || $output_file);
|
$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 {
|
sub usage {
|
||||||
@ -93,14 +104,22 @@ Usage: slic3r.pl [ OPTIONS ] file.stl
|
|||||||
--perimeters Number of perimeters/horizontal skins
|
--perimeters Number of perimeters/horizontal skins
|
||||||
(range: 1+, default: $Slic3r::perimeter_offsets)
|
(range: 1+, default: $Slic3r::perimeter_offsets)
|
||||||
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density)
|
--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-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)
|
--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)
|
--travel-feed-rate Speed of non-print moves in mm/sec (default: $Slic3r::travel_feed_rate)
|
||||||
--bottom-layer-speed-ratio
|
--bottom-layer-speed-ratio
|
||||||
Factor to increase/decrease speeds on bottom layer by
|
Factor to increase/decrease speeds on bottom layer by
|
||||||
(default: $Slic3r::bottom_layer_speed_ratio)
|
(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-e-distances
|
||||||
Use relative distances for extrusion in GCODE output
|
Use relative distances for extrusion in GCODE output
|
||||||
--print-center Coordinates of the point to center the print around
|
--print-center Coordinates of the point to center the print around
|
||||||
|
Loading…
Reference in New Issue
Block a user