New spacing math. Speed optimizations
This commit is contained in:
parent
dd37867324
commit
77123ada7c
@ -725,8 +725,8 @@ sub validate {
|
|||||||
$Slic3r::support_material_flow = $Slic3r::extruders->[ $Slic3r::support_material_extruder-1 ]
|
$Slic3r::support_material_flow = $Slic3r::extruders->[ $Slic3r::support_material_extruder-1 ]
|
||||||
->make_flow(width => $Slic3r::support_material_extrusion_width || $Slic3r::extrusion_width);
|
->make_flow(width => $Slic3r::support_material_extrusion_width || $Slic3r::extrusion_width);
|
||||||
|
|
||||||
Slic3r::debugf "Default flow width = %s, spacing = %s, min_spacing = %s\n",
|
Slic3r::debugf "Default flow width = %s (spacing = %s)\n",
|
||||||
$Slic3r::flow->width, $Slic3r::flow->spacing, $Slic3r::flow->min_spacing;
|
$Slic3r::flow->width, $Slic3r::flow->spacing;
|
||||||
|
|
||||||
# --perimeters
|
# --perimeters
|
||||||
die "Invalid value for --perimeters\n"
|
die "Invalid value for --perimeters\n"
|
||||||
|
@ -3,21 +3,18 @@ use Moo;
|
|||||||
|
|
||||||
use Slic3r::Geometry qw(PI);
|
use Slic3r::Geometry qw(PI);
|
||||||
|
|
||||||
has 'nozzle_diameter' => (is => 'rw', required => 1);
|
has 'nozzle_diameter' => (is => 'ro', required => 1);
|
||||||
has 'filament_diameter' => (is => 'rw', required => 1);
|
has 'filament_diameter' => (is => 'ro', required => 1);
|
||||||
has 'extrusion_multiplier' => (is => 'rw', required => 1);
|
has 'extrusion_multiplier' => (is => 'ro', required => 1);
|
||||||
has 'temperature' => (is => 'rw', required => 1);
|
has 'temperature' => (is => 'ro', required => 1);
|
||||||
has 'first_layer_temperature' => (is => 'rw', required => 1);
|
has 'first_layer_temperature' => (is => 'rw', required => 1);
|
||||||
|
|
||||||
has 'e_per_mm3' => (is => 'rw');
|
has 'e_per_mm3' => (is => 'lazy');
|
||||||
|
has '_mm3_per_mm_cache' => (is => 'ro', default => sub {{}});
|
||||||
|
|
||||||
sub BUILD {
|
sub _build_e_per_mm3 {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$self->e_per_mm3(
|
return $self->extrusion_multiplier * (4 / (($self->filament_diameter ** 2) * PI));
|
||||||
$Slic3r::scaling_factor
|
|
||||||
* $self->extrusion_multiplier
|
|
||||||
* (4 / (($self->filament_diameter ** 2) * PI))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_flow {
|
sub make_flow {
|
||||||
@ -25,4 +22,26 @@ sub make_flow {
|
|||||||
return Slic3r::Flow->new(nozzle_diameter => $self->nozzle_diameter, @_);
|
return Slic3r::Flow->new(nozzle_diameter => $self->nozzle_diameter, @_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub mm3_per_mm {
|
||||||
|
my $self = shift;
|
||||||
|
my ($s, $h) = @_;
|
||||||
|
|
||||||
|
my $cache_key = "${s}_${h}";
|
||||||
|
if (!exists $self->_mm3_per_mm_cache->{$cache_key}) {
|
||||||
|
my $w_threshold = $h + $self->nozzle_diameter;
|
||||||
|
my $s_threshold = $w_threshold - $Slic3r::overlap_factor * ($w_threshold - ($w_threshold - $h * (1 - PI/4)));
|
||||||
|
|
||||||
|
if ($s >= $s_threshold) {
|
||||||
|
# rectangle with semicircles at the ends
|
||||||
|
my $w = $s + $Slic3r::overlap_factor * $h * (1 - PI/4);
|
||||||
|
$self->_mm3_per_mm_cache->{$cache_key} = $w * $h + ($h**2) / 4 * (PI - 4);
|
||||||
|
} else {
|
||||||
|
# rectangle with shrunk semicircles at the ends
|
||||||
|
my $w = ($s + $self->nozzle_diameter * $Slic3r::overlap_factor * (PI/4 - 1)) / (1 + $Slic3r::overlap_factor * (PI/4 - 1));
|
||||||
|
$self->_mm3_per_mm_cache->{$cache_key} = $self->nozzle_diameter * $h * (1 - PI/4) + $h * $w * PI/4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $self->_mm3_per_mm_cache->{$cache_key};
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -3,53 +3,56 @@ use Moo;
|
|||||||
|
|
||||||
use Slic3r::Geometry qw(PI);
|
use Slic3r::Geometry qw(PI);
|
||||||
|
|
||||||
has 'nozzle_diameter' => (is => 'rw', required => 1);
|
has 'nozzle_diameter' => (is => 'ro', required => 1);
|
||||||
has 'layer_height' => (is => 'rw', default => sub { $Slic3r::layer_height });
|
has 'layer_height' => (is => 'ro', default => sub { $Slic3r::layer_height });
|
||||||
|
|
||||||
has 'width' => (is => 'rw');
|
has 'width' => (is => 'rwp', builder => 1);
|
||||||
has 'min_spacing' => (is => 'rw');
|
has 'spacing' => (is => 'lazy');
|
||||||
has 'spacing' => (is => 'rw');
|
|
||||||
|
|
||||||
sub BUILD {
|
sub BUILD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
my ($flow_width, $min_flow_spacing, $flow_spacing);
|
if ($self->width =~ /^(\d+(?:\.\d+)?)%$/) {
|
||||||
if ($self->width) {
|
$self->_set_width($self->layer_height * $1 / 100);
|
||||||
$flow_width = $self->width =~ /^(\d+(?:\.\d+)?)%$/
|
}
|
||||||
? ($self->layer_height * $1 / 100)
|
$self->_set_width($self->_build_width) if $self->width == 0; # auto
|
||||||
: $self->width;
|
}
|
||||||
} else {
|
|
||||||
# here we calculate a sane default by matching the flow speed (at the nozzle)
|
|
||||||
# and the feed rate
|
|
||||||
my $volume = ($self->nozzle_diameter**2) * PI/4;
|
|
||||||
my $shape_threshold = $self->nozzle_diameter * $self->layer_height
|
|
||||||
+ ($self->layer_height**2) * PI/4;
|
|
||||||
if ($volume >= $shape_threshold) {
|
|
||||||
# rectangle with semicircles at the ends
|
|
||||||
$flow_width = (($self->nozzle_diameter**2) * PI + ($self->layer_height**2) * (4 - PI)) / (4 * $self->layer_height);
|
|
||||||
} else {
|
|
||||||
# rectangle with squished semicircles at the ends
|
|
||||||
$flow_width = $self->nozzle_diameter * ($self->nozzle_diameter/$self->layer_height - 4/PI + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
my $min_flow_width = $self->nozzle_diameter * 1.05;
|
sub _build_width {
|
||||||
my $max_flow_width = $self->nozzle_diameter * 1.4;
|
my $self = shift;
|
||||||
$flow_width = $max_flow_width if $flow_width > $max_flow_width;
|
|
||||||
$flow_width = $min_flow_width if $flow_width < $min_flow_width;
|
# here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate
|
||||||
|
my $volume = ($self->nozzle_diameter**2) * PI/4;
|
||||||
|
my $shape_threshold = $self->nozzle_diameter * $self->layer_height + ($self->layer_height**2) * PI/4;
|
||||||
|
my $width;
|
||||||
|
if ($volume >= $shape_threshold) {
|
||||||
|
# rectangle with semicircles at the ends
|
||||||
|
$width = (($self->nozzle_diameter**2) * PI + ($self->layer_height**2) * (4 - PI)) / (4 * $self->layer_height);
|
||||||
|
} else {
|
||||||
|
# rectangle with squished semicircles at the ends
|
||||||
|
$width = $self->nozzle_diameter * ($self->nozzle_diameter/$self->layer_height - 4/PI + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($flow_width >= ($self->nozzle_diameter + $self->layer_height)) {
|
my $min = $self->nozzle_diameter * 1.05;
|
||||||
|
my $max = $self->nozzle_diameter * 1.4;
|
||||||
|
$width = $max if $width > $max;
|
||||||
|
$width = $min if $width < $min;
|
||||||
|
|
||||||
|
return $width;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _build_spacing {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $min_flow_spacing;
|
||||||
|
if ($self->width >= ($self->nozzle_diameter + $self->layer_height)) {
|
||||||
# rectangle with semicircles at the ends
|
# rectangle with semicircles at the ends
|
||||||
$min_flow_spacing = $flow_width - $self->layer_height * (1 - PI/4);
|
$min_flow_spacing = $self->width - $self->layer_height * (1 - PI/4);
|
||||||
} else {
|
} else {
|
||||||
# rectangle with shrunk semicircles at the ends
|
# rectangle with shrunk semicircles at the ends
|
||||||
$min_flow_spacing = $self->nozzle_diameter * (1 - PI/4) + $flow_width * PI/4;
|
$min_flow_spacing = $self->nozzle_diameter * (1 - PI/4) + $self->width * PI/4;
|
||||||
}
|
}
|
||||||
$flow_spacing = $flow_width - $Slic3r::overlap_factor * ($flow_width - $min_flow_spacing);
|
return $self->width - $Slic3r::overlap_factor * ($self->width - $min_flow_spacing);
|
||||||
|
|
||||||
$self->width($flow_width);
|
|
||||||
$self->min_spacing($min_flow_spacing);
|
|
||||||
$self->spacing($flow_spacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -157,22 +157,17 @@ sub extrude_path {
|
|||||||
# compensate retraction
|
# compensate retraction
|
||||||
$gcode .= $self->unretract if $self->retracted;
|
$gcode .= $self->unretract if $self->retracted;
|
||||||
|
|
||||||
# calculate extrusion length per distance unit
|
my $area; # mm^3 of extrudate per mm of tool movement
|
||||||
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 - ($self->layer ? $self->layer->flow->min_spacing : $Slic3r::flow->min_spacing) * $Slic3r::overlap_factor) / (1 - $Slic3r::overlap_factor);
|
|
||||||
|
|
||||||
my $area; # = mm^3 of extrudate per mm of tool movement
|
|
||||||
if ($path->role == EXTR_ROLE_BRIDGE) {
|
if ($path->role == EXTR_ROLE_BRIDGE) {
|
||||||
|
my $s = $path->flow_spacing || $self->extruder->nozzle_diameter;
|
||||||
$area = ($s**2) * PI/4;
|
$area = ($s**2) * PI/4;
|
||||||
} elsif ($w >= ($self->extruder->nozzle_diameter + $h)) {
|
|
||||||
# rectangle with semicircles at the ends
|
|
||||||
$area = $w * $h + ($h**2) / 4 * (PI - 4);
|
|
||||||
} else {
|
} else {
|
||||||
# rectangle with shrunk semicircles at the ends
|
my $s = $path->flow_spacing || ($self->layer ? $self->layer->flow->spacing : $Slic3r::flow->spacing);
|
||||||
$area = $self->extruder->nozzle_diameter * $h * (1 - PI/4) + $h * $w * PI/4;
|
my $h = $path->depth_layers * $self->layer->height;
|
||||||
|
$area = $self->extruder->mm3_per_mm($s, $h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# calculate extrusion length per distance unit
|
||||||
my $e = $self->extruder->e_per_mm3 * $area;
|
my $e = $self->extruder->e_per_mm3 * $area;
|
||||||
|
|
||||||
# extrude arc or line
|
# extrude arc or line
|
||||||
@ -181,12 +176,12 @@ sub extrude_path {
|
|||||||
if ($path->isa('Slic3r::ExtrusionPath::Arc')) {
|
if ($path->isa('Slic3r::ExtrusionPath::Arc')) {
|
||||||
$path_length = $path->length;
|
$path_length = $path->length;
|
||||||
$gcode .= $self->G2_G3($path->points->[-1], $path->orientation,
|
$gcode .= $self->G2_G3($path->points->[-1], $path->orientation,
|
||||||
$path->center, $e * $path_length, $description);
|
$path->center, $e * unscale $path_length, $description);
|
||||||
} else {
|
} else {
|
||||||
foreach my $line ($path->lines) {
|
foreach my $line ($path->lines) {
|
||||||
my $line_length = $line->length;
|
my $line_length = $line->length;
|
||||||
$path_length += $line_length;
|
$path_length += $line_length;
|
||||||
$gcode .= $self->G1($line->b, undef, $e * $line_length, $description);
|
$gcode .= $self->G1($line->b, undef, $e * unscale $line_length, $description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user