mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-30 20:32:01 +08:00
Implemented adaptive layer height algorithm based on volumetric surface quality
This commit is contained in:
parent
ece3a6e0ad
commit
22ffb76fb1
@ -5,6 +5,15 @@ use List::Util qw(min max);
|
||||
use Math::Trig qw(asin acos deg2rad rad2deg);
|
||||
use Slic3r::Geometry qw(X Y Z triangle_normal scale unscale);
|
||||
|
||||
# This constant essentially describes the volumetric error at the surface which is induced
|
||||
# by stacking "elliptic" extrusion threads.
|
||||
# It is empirically determined by
|
||||
# 1. measuring the surface profile of printed parts to find
|
||||
# the ratio between layer height and profile height and then
|
||||
# 2. computing the geometric difference between the model-surface and the elliptic profile.
|
||||
# [Link to detailed description follows]
|
||||
use constant SURFACE_CONST => 0.18403;
|
||||
|
||||
# public
|
||||
has 'mesh' => (is => 'ro', required => 1);
|
||||
has 'size' => (is => 'ro', required => 1);
|
||||
@ -34,8 +43,8 @@ sub BUILD {
|
||||
$self->normal_z->[$facet_id] = $normal->[Z]/$normal_length;
|
||||
}else{ # facet with area = 0
|
||||
$self->normal_z->[$facet_id] = 0.01;#[0 ,0 ,0];
|
||||
print "facet with normal 0. p1: " . $vertices->[$facets->[$facet_id]->[0]]->[Z] . " p2: " . $vertices->[$facets->[$facet_id]->[1]]->[Z] . " p3: " . $vertices->[$facets->[$facet_id]->[2]]->[Z] . "\n";
|
||||
print "normal: " . $normal->[0] . ", " . $normal->[1] . ", " . $normal->[2] . "\n";
|
||||
#print "facet with normal 0. p1: " . $vertices->[$facets->[$facet_id]->[0]]->[Z] . " p2: " . $vertices->[$facets->[$facet_id]->[1]]->[Z] . " p3: " . $vertices->[$facets->[$facet_id]->[2]]->[Z] . "\n";
|
||||
#print "normal: " . $normal->[0] . ", " . $normal->[1] . ", " . $normal->[2] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,130 +64,25 @@ sub BUILD {
|
||||
for (my $i = 0; $i <= $#sort_facets; $i++) {
|
||||
$self->ordered_facets->[$i] = $sort_facets[$i];
|
||||
}
|
||||
# initialize pointer for cusp_height run
|
||||
# initialize pointer to iterate over the object
|
||||
$self->current_facet(0);
|
||||
}
|
||||
|
||||
|
||||
# Combined layer height, weighing between cusp and Ra factor
|
||||
sub next_layer_height_area {
|
||||
my $self = shift;
|
||||
my ($z, $factor, $min_height, $max_height) = @_;
|
||||
|
||||
# factor must be between 0-1, 0 is highest quality, 1 highest print speed
|
||||
if($factor < 0 or $factor > 1) {
|
||||
die "Speed / Quality factor must be in the interval [0:1]";
|
||||
}
|
||||
|
||||
my $volume_factor = 0.12263;
|
||||
my $delta_min = $volume_factor * $min_height * 2;
|
||||
my $delta_max = $volume_factor * $max_height * 2 + 0.5*$max_height;
|
||||
|
||||
my $area_value = $factor * ($delta_max-$delta_min) + $delta_min;
|
||||
|
||||
my $height = $max_height;
|
||||
my $first_hit = 0;
|
||||
|
||||
# find all facets intersecting the slice-layer
|
||||
my $ordered_id = $self->current_facet;
|
||||
while ($ordered_id <= $#{$self->ordered_facets}) {
|
||||
|
||||
# facet's minimum is higher than slice_z -> end loop
|
||||
if($self->ordered_facets->[$ordered_id]->[1] >= $z) {
|
||||
last;
|
||||
}
|
||||
|
||||
# facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
|
||||
if($self->ordered_facets->[$ordered_id]->[2] > $z) {
|
||||
# first event?
|
||||
if(!$first_hit) {
|
||||
$first_hit = 1;
|
||||
$self->current_facet($ordered_id);
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# compute cusp-height for this facet and store minimum of all heights
|
||||
my $area_h = $self->_facet_area_height($ordered_id, $area_value);
|
||||
$area_h = max($min_height, min($max_height, $area_h));
|
||||
$height = $area_h if($area_h < $height);
|
||||
}
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities
|
||||
$height = $min_height if($height < $min_height);
|
||||
|
||||
|
||||
# check for sloped facets inside the determined layer and correct height if necessary
|
||||
if($height > $min_height){
|
||||
while ($ordered_id <= $#{$self->ordered_facets}) {
|
||||
|
||||
# facet's minimum is higher than slice_z + height -> end loop
|
||||
if($self->ordered_facets->[$ordered_id]->[1] >= ($z + scale $height)) {
|
||||
last;
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# Compute cusp-height for this facet and check against height.
|
||||
my $area_h = $self->_facet_area_height($ordered_id, $area_value);
|
||||
$area_h = max($min_height, min($max_height, $area_h));
|
||||
|
||||
my $z_diff = unscale ($self->ordered_facets->[$ordered_id]->[1] - $z);
|
||||
|
||||
|
||||
# # handle horizontal facets
|
||||
# if ($self->normal_z->[$self->ordered_facets->[$ordered_id]->[0]] > 0.999) {
|
||||
# Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
# $height = $z_diff;
|
||||
# Slic3r::debugf "to %f due to near horizontal facet\n", $height;
|
||||
# }else{
|
||||
if( $area_h > $z_diff) {
|
||||
if($area_h < $height) {
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
$height = $area_h;
|
||||
Slic3r::debugf "to %f due to new cusp height\n", $height;
|
||||
}
|
||||
}else{
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
$height = $z_diff;
|
||||
Slic3r::debugf "to z-diff: %f\n", $height;
|
||||
}
|
||||
# }
|
||||
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities again
|
||||
$height = $min_height if($height < $min_height);
|
||||
}
|
||||
|
||||
Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $area_value, $height;
|
||||
|
||||
return $height;
|
||||
}
|
||||
|
||||
# Combined layer height, weighing between cusp and Ra factor
|
||||
# find height of the next layer by analyzing the angle of all facets intersecting the new layer
|
||||
sub next_layer_height {
|
||||
my $self = shift;
|
||||
my ($z, $factor, $min_height, $max_height) = @_;
|
||||
my ($z, $quality_factor, $min_height, $max_height) = @_;
|
||||
|
||||
# factor must be between 0-1, 0 is highest quality, 1 highest print speed
|
||||
if($factor < 0 or $factor > 1) {
|
||||
die "Speed / Quality factor must be in the interval [0:1]";
|
||||
if($quality_factor < 0 or $quality_factor > 1) {
|
||||
die "Speed / Quality factor must be in the interval [0:1]";
|
||||
}
|
||||
|
||||
my $delta_min = SURFACE_CONST * $min_height;
|
||||
my $delta_max = SURFACE_CONST * $max_height + 0.5*$max_height;
|
||||
|
||||
my $cusp_value = $factor * ($max_height-$min_height) + $min_height;
|
||||
my $ra_value = 2 * $factor * ($max_height-$min_height) + $min_height;
|
||||
my $scaled_quality_factor = $quality_factor * ($delta_max-$delta_min) + $delta_min;
|
||||
|
||||
my $height = $max_height;
|
||||
my $first_hit = 0;
|
||||
@ -192,7 +96,7 @@ sub next_layer_height {
|
||||
last;
|
||||
}
|
||||
|
||||
# facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
|
||||
# facet's maximum is higher than slice_z -> store the first event for next layer_height call to begin at this point
|
||||
if($self->ordered_facets->[$ordered_id]->[2] > $z) {
|
||||
# first event?
|
||||
if(!$first_hit) {
|
||||
@ -200,23 +104,20 @@ sub next_layer_height {
|
||||
$self->current_facet($ordered_id);
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
#skip touching facets which could otherwise cause small height values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# compute cusp-height for this facet and store minimum of all heights
|
||||
my $cusp = $self->_facet_cusp_height($ordered_id, $cusp_value);
|
||||
my $ra = $self->_facet_ra_height($ordered_id, $cusp_value);
|
||||
my $mixed_height = $self->_mixed_layer_height($ordered_id, $cusp_value, $ra_value, $min_height, $max_height, $factor);
|
||||
$height = $mixed_height if($mixed_height < $height);
|
||||
# compute layer-height for this facet and store minimum of all heights
|
||||
$height = min($height, $self->_facet_height($ordered_id, $scaled_quality_factor));
|
||||
}
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities
|
||||
$height = $min_height if($height < $min_height);
|
||||
$height = max($min_height, $height);
|
||||
|
||||
|
||||
# check for sloped facets inside the determined layer and correct height if necessary
|
||||
@ -228,16 +129,16 @@ sub next_layer_height {
|
||||
last;
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
#skip touching facets which could otherwise cause small height values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# Compute cusp-height for this facet and check against height.
|
||||
my $cusp = $self->_facet_cusp_height($ordered_id, $cusp_value);
|
||||
my $mixed_height = $self->_mixed_layer_height($ordered_id, $cusp_value, $ra_value, $min_height, $max_height, $factor);
|
||||
# Compute new height for this facet and check against height.
|
||||
my $reduced_height = $self->_facet_height($ordered_id, $scaled_quality_factor);
|
||||
#$area_h = max($min_height, min($max_height, $area_h));
|
||||
|
||||
my $z_diff = unscale ($self->ordered_facets->[$ordered_id]->[1] - $z);
|
||||
|
||||
@ -248,14 +149,14 @@ sub next_layer_height {
|
||||
# $height = $z_diff;
|
||||
# Slic3r::debugf "to %f due to near horizontal facet\n", $height;
|
||||
# }else{
|
||||
if( $mixed_height > $z_diff) {
|
||||
if($mixed_height < $height) {
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
$height = $mixed_height;
|
||||
Slic3r::debugf "to %f due to new cusp height\n", $height;
|
||||
if( $reduced_height > $z_diff) {
|
||||
if($reduced_height < $height) {
|
||||
Slic3r::debugf "adaptive layer computation: height is reduced from %f", $height;
|
||||
$height = $reduced_height;
|
||||
Slic3r::debugf "to %f due to higher facet\n", $height;
|
||||
}
|
||||
}else{
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
Slic3r::debugf "adaptive layer computation: height is reduced from %f", $height;
|
||||
$height = $z_diff;
|
||||
Slic3r::debugf "to z-diff: %f\n", $height;
|
||||
}
|
||||
@ -264,121 +165,16 @@ sub next_layer_height {
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities again
|
||||
$height = $min_height if($height < $min_height);
|
||||
$height = max($min_height, $height);
|
||||
}
|
||||
|
||||
Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height;
|
||||
Slic3r::debugf "adaptive layer computation, layer-bottom at z:%f, quality_factor:%f, resulting layer height:%f\n", unscale $z, $quality_factor, $height;
|
||||
|
||||
return $height;
|
||||
}
|
||||
|
||||
sub cusp_height {
|
||||
my $self = shift;
|
||||
my ($z, $cusp_value, $min_height, $max_height) = @_;
|
||||
|
||||
my $height = $max_height;
|
||||
my $first_hit = 0;
|
||||
|
||||
# find all facets intersecting the slice-layer
|
||||
my $ordered_id = $self->current_facet;
|
||||
while ($ordered_id <= $#{$self->ordered_facets}) {
|
||||
|
||||
# facet's minimum is higher than slice_z -> end loop
|
||||
if($self->ordered_facets->[$ordered_id]->[1] >= $z) {
|
||||
last;
|
||||
}
|
||||
|
||||
# facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
|
||||
if($self->ordered_facets->[$ordered_id]->[2] > $z) {
|
||||
# first event?
|
||||
if(!$first_hit) {
|
||||
$first_hit = 1;
|
||||
$self->current_facet($ordered_id);
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# compute cusp-height for this facet and store minimum of all heights
|
||||
my $cusp = $self->_facet_cusp_height($ordered_id, $cusp_value);
|
||||
$height = $cusp if($cusp < $height);
|
||||
}
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities
|
||||
$height = $min_height if($height < $min_height);
|
||||
|
||||
|
||||
# check for sloped facets inside the determined layer and correct height if necessary
|
||||
if($height > $min_height){
|
||||
while ($ordered_id <= $#{$self->ordered_facets}) {
|
||||
|
||||
# facet's minimum is higher than slice_z + height -> end loop
|
||||
if($self->ordered_facets->[$ordered_id]->[1] >= ($z + scale $height)) {
|
||||
last;
|
||||
}
|
||||
|
||||
#skip touching facets which could otherwise cause small cusp values
|
||||
if($self->ordered_facets->[$ordered_id]->[2] <= $z+1)
|
||||
{
|
||||
$ordered_id++;
|
||||
next;
|
||||
}
|
||||
|
||||
# Compute cusp-height for this facet and check against height.
|
||||
my $cusp = $self->_facet_cusp_height($ordered_id, $cusp_value);
|
||||
|
||||
my $z_diff = unscale ($self->ordered_facets->[$ordered_id]->[1] - $z);
|
||||
|
||||
|
||||
# # handle horizontal facets
|
||||
# if ($self->normal_z->[$self->ordered_facets->[$ordered_id]->[0]] > 0.999) {
|
||||
# Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
# $height = $z_diff;
|
||||
# Slic3r::debugf "to %f due to near horizontal facet\n", $height;
|
||||
# }else{
|
||||
if( $cusp > $z_diff) {
|
||||
if($cusp < $height) {
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
$height = $cusp;
|
||||
Slic3r::debugf "to %f due to new cusp height\n", $height;
|
||||
}
|
||||
}else{
|
||||
Slic3r::debugf "cusp computation, height is reduced from %f", $height;
|
||||
$height = $z_diff;
|
||||
Slic3r::debugf "to z-diff: %f\n", $height;
|
||||
}
|
||||
# }
|
||||
|
||||
$ordered_id++;
|
||||
}
|
||||
# lower height limit due to printer capabilities again
|
||||
$height = $min_height if($height < $min_height);
|
||||
}
|
||||
|
||||
Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height;
|
||||
|
||||
return $height;
|
||||
}
|
||||
|
||||
sub _mixed_layer_height {
|
||||
my ($self, $ordered_id, $cusp_value, $ra_value, $min_height, $max_height, $factor) = @_;
|
||||
|
||||
my $cusp = max($min_height, min($max_height, $self->_facet_cusp_height($ordered_id, $cusp_value)));
|
||||
my $ra = max($min_height, min($max_height, $self->_facet_ra_height($ordered_id, $ra_value)));
|
||||
|
||||
my $normal_z = abs($self->normal_z->[$self->ordered_facets->[$ordered_id]->[0]]);
|
||||
my $phi = asin($normal_z);
|
||||
print "facet phi: " . rad2deg($phi) . " cusp_value: $cusp_value, ra_value: $ra_value\n";
|
||||
print "ra: $ra, cusp: $cusp\n\n";
|
||||
|
||||
return $factor * $cusp + (1-$factor) * $ra;
|
||||
}
|
||||
|
||||
# computes the cusp height from a given facets normal and the cusp_value
|
||||
sub _facet_cusp_height {
|
||||
my $self = shift;
|
||||
@ -389,25 +185,13 @@ sub _facet_cusp_height {
|
||||
return $cusp;
|
||||
}
|
||||
|
||||
sub _facet_ra_height {
|
||||
my $self = shift;
|
||||
my ($ordered_id, $ra_value) = @_;
|
||||
|
||||
my $normal_z = abs($self->normal_z->[$self->ordered_facets->[$ordered_id]->[0]]);
|
||||
#print "ra_value: $ra_value, facet normal: $normal_z\n";
|
||||
my $phi = asin($normal_z);
|
||||
#print "phi: $phi\n";
|
||||
my $ra = $ra_value * cos($phi);
|
||||
#print "ra: $ra\n\n";
|
||||
return $ra;
|
||||
}
|
||||
|
||||
sub _facet_area_height {
|
||||
my ($self, $ordered_id, $area_value) = @_;
|
||||
sub _facet_height {
|
||||
my ($self, $ordered_id, $scaled_quality_factor) = @_;
|
||||
|
||||
my $normal_z = abs($self->normal_z->[$self->ordered_facets->[$ordered_id]->[0]]);
|
||||
my $area_h = 1/(2*0.12263/$area_value + ($normal_z/2)/$area_value);
|
||||
return $area_h;
|
||||
my $height = $scaled_quality_factor/(SURFACE_CONST + $normal_z/2);
|
||||
return ($normal_z == 0) ? 9999 : $height;
|
||||
}
|
||||
|
||||
# Returns the distance to the next horizontal facet in Z-dir
|
||||
|
@ -34,7 +34,7 @@ sub new {
|
||||
|
||||
$self->{splineControl} = Slic3r::GUI::Plater::SplineControl->new($self, Wx::Size->new(150, 200), $object);
|
||||
|
||||
my $cusp_slider = $self->{cusp_slider} = Wx::Slider->new(
|
||||
my $quality_slider = $self->{quality_slider} = Wx::Slider->new(
|
||||
$self, -1,
|
||||
0, # default
|
||||
0, # min
|
||||
@ -46,24 +46,24 @@ sub new {
|
||||
wxHORIZONTAL,
|
||||
);
|
||||
|
||||
my $cusp_label = $self->{cusp_label} = Wx::StaticText->new($self, -1, " <-Quality", wxDefaultPosition,
|
||||
my $quality_label = $self->{quality_label} = Wx::StaticText->new($self, -1, " <-Quality", wxDefaultPosition,
|
||||
[-1,-1], wxALIGN_LEFT);
|
||||
my $value_label = $self->{value_label} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
|
||||
[50,-1], wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE);
|
||||
my $speed_label = $self->{speed_label} = Wx::StaticText->new($self, -1, "Speed->", wxDefaultPosition,
|
||||
[-1,-1], wxST_NO_AUTORESIZE | wxALIGN_RIGHT);
|
||||
$cusp_label->SetFont($Slic3r::GUI::small_font);
|
||||
$quality_label->SetFont($Slic3r::GUI::small_font);
|
||||
$value_label->SetFont($Slic3r::GUI::small_font);
|
||||
$speed_label->SetFont($Slic3r::GUI::small_font);
|
||||
|
||||
my $quality_label_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
$quality_label_sizer->Add($cusp_label, 1, wxEXPAND | wxALL, 0);
|
||||
$quality_label_sizer->Add($quality_label, 1, wxEXPAND | wxALL, 0);
|
||||
$quality_label_sizer->Add($value_label, 1, wxEXPAND | wxALL, 0);
|
||||
$quality_label_sizer->Add($speed_label, 1, wxEXPAND | wxALL, 0);
|
||||
|
||||
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$right_sizer->Add($self->{splineControl}, 1, wxEXPAND | wxALL, 0);
|
||||
$right_sizer->Add($cusp_slider, 0, wxEXPAND | wxALL, 0);
|
||||
$right_sizer->Add($quality_slider, 0, wxEXPAND | wxALL, 0);
|
||||
$right_sizer->Add($quality_label_sizer, 0, wxEXPAND | wxALL, 0);
|
||||
|
||||
|
||||
@ -104,25 +104,25 @@ sub new {
|
||||
$self->{preview3D}->canvas->Render;
|
||||
});
|
||||
|
||||
# init cusp slider
|
||||
# init quality slider
|
||||
if($object->config->adaptive_slicing) {
|
||||
my $cusp_value = $object->config->get('cusp_value');
|
||||
$value_label->SetLabel(sprintf '%.2f mm', $cusp_value);
|
||||
$cusp_slider->SetRange(0, 100);
|
||||
$cusp_slider->SetValue($cusp_value*100);
|
||||
my $quality_value = $object->config->get('adaptive_slicing_quality');
|
||||
$value_label->SetLabel(sprintf '%.2f', $quality_value);
|
||||
$quality_slider->SetRange(0, 100);
|
||||
$quality_slider->SetValue($quality_value*100);
|
||||
}else{
|
||||
# disable slider
|
||||
$value_label->SetLabel("");
|
||||
$cusp_label->Enable(0);
|
||||
$cusp_slider->Enable(0);
|
||||
$quality_label->Enable(0);
|
||||
$quality_slider->Enable(0);
|
||||
}
|
||||
|
||||
EVT_SLIDER($self, $cusp_slider, sub {
|
||||
EVT_SLIDER($self, $quality_slider, sub {
|
||||
$self->{plater}->pause_background_process;
|
||||
my $cusp_value = $cusp_slider->GetValue/100;
|
||||
$value_label->SetLabel(sprintf '%.2f mm', $cusp_value);
|
||||
my $success = $object->config->set('cusp_value', $cusp_value);
|
||||
$object->layer_height_spline->setCuspValue($cusp_value);
|
||||
my $quality_value = $quality_slider->GetValue/100;
|
||||
$value_label->SetLabel(sprintf '%.2f', $quality_value);
|
||||
my $success = $object->config->set('adaptive_slicing_quality', $quality_value);
|
||||
$object->layer_height_spline->setCuspValue($quality_value);
|
||||
# trigger re-slicing
|
||||
$self->{plater}->stop_background_process;
|
||||
$self->{object}->invalidate_step(STEP_SLICE);
|
||||
|
@ -461,7 +461,7 @@ sub build {
|
||||
my $self = shift;
|
||||
|
||||
$self->init_config_options(qw(
|
||||
adaptive_slicing adaptive_slicing_z_gradation cusp_value match_horizontal_surfaces
|
||||
adaptive_slicing adaptive_slicing_quality adaptive_slicing_z_gradation match_horizontal_surfaces
|
||||
layer_height first_layer_height
|
||||
perimeters spiral_vase
|
||||
top_solid_layers bottom_solid_layers
|
||||
@ -509,7 +509,7 @@ sub build {
|
||||
$optgroup->append_single_option_line('layer_height');
|
||||
$optgroup->append_single_option_line('first_layer_height');
|
||||
$optgroup->append_single_option_line('adaptive_slicing');
|
||||
$optgroup->append_single_option_line('cusp_value');
|
||||
$optgroup->append_single_option_line('adaptive_slicing_quality');
|
||||
$optgroup->append_single_option_line('adaptive_slicing_z_gradation');
|
||||
$optgroup->append_single_option_line('match_horizontal_surfaces');
|
||||
}
|
||||
@ -827,7 +827,7 @@ sub _update {
|
||||
|
||||
my $have_adaptive_slicing = $config->adaptive_slicing;
|
||||
$self->get_field($_)->toggle($have_adaptive_slicing)
|
||||
for qw(cusp_value adaptive_slicing_z_gradation match_horizontal_surfaces);
|
||||
for qw(adaptive_slicing_quality adaptive_slicing_z_gradation match_horizontal_surfaces);
|
||||
$self->get_field($_)->toggle(!$have_adaptive_slicing)
|
||||
for qw(layer_height);
|
||||
|
||||
|
@ -103,7 +103,7 @@ sub slice {
|
||||
|
||||
my $slice_z = 0;
|
||||
my $height = 0;
|
||||
my $cusp_height = 0;
|
||||
my $adaptive_height = 0;
|
||||
my @layers = ();
|
||||
|
||||
# determine min and max layer height from extruder capabilities.
|
||||
@ -150,10 +150,10 @@ sub slice {
|
||||
|
||||
if ($self->config->adaptive_slicing) {
|
||||
$height = 999;
|
||||
my $cusp_value = $self->config->get_value('cusp_value');
|
||||
my $adaptive_quality = $self->config->get_value('adaptive_slicing_quality');
|
||||
if($self->layer_height_spline->getCuspValue >= 0) {
|
||||
$self->config->set('cusp_value', $self->layer_height_spline->getCuspValue);
|
||||
$cusp_value = $self->layer_height_spline->getCuspValue;
|
||||
$self->config->set('adaptive_slicing_quality', $self->layer_height_spline->getCuspValue);
|
||||
$adaptive_quality = $self->layer_height_spline->getCuspValue;
|
||||
}
|
||||
|
||||
Slic3r::debugf "\n Slice layer: %d\n", $id;
|
||||
@ -162,29 +162,29 @@ sub slice {
|
||||
for my $region_id (0 .. ($self->region_count - 1)) {
|
||||
# get cusp height
|
||||
next if(!defined $adaptive_slicing[$region_id]);
|
||||
my $cusp_height = $adaptive_slicing[$region_id]->next_layer_height_area(scale $slice_z, $cusp_value, $min_height, $max_height);
|
||||
my $adaptive_height = $adaptive_slicing[$region_id]->next_layer_height(scale $slice_z, $adaptive_quality, $min_height, $max_height);
|
||||
|
||||
# check for horizontal features and object size
|
||||
if($self->config->get_value('match_horizontal_surfaces')) {
|
||||
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height);
|
||||
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$adaptive_height, $min_height);
|
||||
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) {
|
||||
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist;
|
||||
# can we shrink the current layer a bit?
|
||||
if($cusp_height-($min_height-$horizontal_dist) > $min_height) {
|
||||
if($adaptive_height-($min_height-$horizontal_dist) > $min_height) {
|
||||
# yes we can
|
||||
$cusp_height = $cusp_height-($min_height-$horizontal_dist);
|
||||
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height;
|
||||
$adaptive_height = $adaptive_height-($min_height-$horizontal_dist);
|
||||
Slic3r::debugf "Shrink layer height to %f\n", $adaptive_height;
|
||||
}else{
|
||||
# no, current layer would become too thin
|
||||
$cusp_height = $cusp_height+$horizontal_dist;
|
||||
Slic3r::debugf "Widen layer height to %f\n", $cusp_height;
|
||||
$adaptive_height = $adaptive_height+$horizontal_dist;
|
||||
Slic3r::debugf "Widen layer height to %f\n", $adaptive_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$height = ($id == 0)
|
||||
? $self->config->get_value('first_layer_height')
|
||||
: min($cusp_height, $height);
|
||||
: min($adaptive_height, $height);
|
||||
}
|
||||
|
||||
}else{
|
||||
|
@ -71,38 +71,38 @@ my $adaptive_slicing = Slic3r::AdaptiveSlicing->new(
|
||||
);
|
||||
|
||||
|
||||
subtest 'max cusp_height limited by extruder capabilities' => sub {
|
||||
subtest 'max layer_height limited by extruder capabilities' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
is ($adaptive_slicing->cusp_height(scale 1, 0.2, 0.1, 0.15), 0.15, 'low');
|
||||
is ($adaptive_slicing->cusp_height(scale 1, 0.2, 0.1, 0.4), 0.4, 'higher');
|
||||
is ($adaptive_slicing->cusp_height(scale 1, 0.2, 0.1, 0.65), 0.65, 'highest');
|
||||
is ($adaptive_slicing->next_layer_height(scale 1, 0.2, 0.1, 0.15), 0.15, 'low');
|
||||
is ($adaptive_slicing->next_layer_height(scale 1, 0.2, 0.1, 0.4), 0.4, 'higher');
|
||||
is ($adaptive_slicing->next_layer_height(scale 1, 0.2, 0.1, 0.65), 0.65, 'highest');
|
||||
};
|
||||
|
||||
subtest 'min cusp_height limited by extruder capabilities' => sub {
|
||||
subtest 'min layer_height limited by extruder capabilities' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
is ($adaptive_slicing->cusp_height(scale 4, 0.01, 0.1, 0.15), 0.1, 'low');
|
||||
is ($adaptive_slicing->cusp_height(scale 4, 0.02, 0.2, 0.4), 0.2, 'higher');
|
||||
is ($adaptive_slicing->cusp_height(scale 4, 0.01, 0.3, 0.65), 0.3, 'highest');
|
||||
is ($adaptive_slicing->next_layer_height(scale 4, 0.01, 0.1, 0.15), 0.1, 'low');
|
||||
is ($adaptive_slicing->next_layer_height(scale 4, 0.02, 0.2, 0.4), 0.2, 'higher');
|
||||
is ($adaptive_slicing->next_layer_height(scale 4, 0.01, 0.3, 0.65), 0.3, 'highest');
|
||||
};
|
||||
|
||||
subtest 'correct cusp_height depending on the facet normals' => sub {
|
||||
subtest 'correct layer_height depending on the facet normals' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
ok (_eq($adaptive_slicing->cusp_height(scale 1, 0.1, 0.1, 0.5), 0.5), 'limit');
|
||||
ok (_eq($adaptive_slicing->cusp_height(scale 4, 0.1, 0.1, 0.5), 0.1414), '45deg facet, cusp_value: 0.1');
|
||||
ok (_eq($adaptive_slicing->cusp_height(scale 4, 0.15, 0.1, 0.5), 0.2121), '45deg facet, cusp_value: 0.15');
|
||||
ok (_eq($adaptive_slicing->next_layer_height(scale 1, 0.1, 0.1, 0.5), 0.5), 'limit');
|
||||
ok (_eq($adaptive_slicing->next_layer_height(scale 4, 0.2, 0.1, 0.5), 0.1546), '45deg facet, quality_value: 0.2');
|
||||
ok (_eq($adaptive_slicing->next_layer_height(scale 4, 0.5, 0.1, 0.5), 0.3352), '45deg facet, quality_value: 0.5');
|
||||
};
|
||||
|
||||
|
||||
# 2.92893 ist lower slope edge
|
||||
# distance to slope must be higher than min extruder cap.
|
||||
# slopes cusp height must be greater than the distance to the slope
|
||||
ok (_eq($adaptive_slicing->cusp_height(scale 2.798, 0.1, 0.1, 0.5), 0.1414), 'reducing cusp_height due to higher slopy facet');
|
||||
# slopes layer height must be greater than the distance to the slope
|
||||
ok (_eq($adaptive_slicing->next_layer_height(scale 2.798, 0.2, 0.1, 0.5), 0.1546), 'reducing layer_height due to higher slopy facet');
|
||||
|
||||
# slopes cusp height must be smaller than the distance to the slope
|
||||
ok (_eq($adaptive_slicing->cusp_height(scale 2.6289, 0.15, 0.1, 0.5), 0.3), 'reducing cusp_height to z-diff');
|
||||
# slopes layer height must be smaller than the distance to the slope
|
||||
ok (_eq($adaptive_slicing->next_layer_height(scale 2.6289, 0.15, 0.1, 0.5), 0.3), 'reducing layer_height to z-diff');
|
||||
|
||||
subtest 'horizontal planes' => sub {
|
||||
plan tests => 3;
|
||||
@ -122,7 +122,7 @@ $config->set('first_layer_height', 0.42893); # to catch lower slope edge
|
||||
$config->set('nozzle_diameter', [0.5]);
|
||||
$config->set('min_layer_height', [0.1]);
|
||||
$config->set('max_layer_height', [0.5]);
|
||||
$config->set('cusp_value', [0.19]);
|
||||
$config->set('adaptive_slicing_quality', [0.19]);
|
||||
# slope height: 7,07107 (2.92893 to 10)
|
||||
|
||||
subtest 'shrink to match horizontal facets' => sub {
|
||||
@ -132,7 +132,7 @@ subtest 'shrink to match horizontal facets' => sub {
|
||||
};
|
||||
|
||||
# widen current layer to match horizontal facet
|
||||
$config->set('cusp_value', [0.1]);
|
||||
$config->set('adaptive_slicing_quality', [0.1]);
|
||||
|
||||
subtest 'widen to match horizontal facets' => sub {
|
||||
plan skip_all => 'spline smoothing currently prevents exact horizontal facet matching';
|
||||
|
@ -13,6 +13,15 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->cli = "adaptive-slicing!";
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("adaptive_slicing_quality", coFloat);
|
||||
def->label = "Adaptive quality";
|
||||
def->tooltip = "Controls the quality / printing time tradeoff for adaptive layer generation. 1 -> fastest printing with max layer height, 0 -> highest quality, min layer height";
|
||||
def->sidetext = "";
|
||||
def->cli = "adaptive_slicing_quality=f";
|
||||
def->min = 0;
|
||||
def->max = 1;
|
||||
def->default_value = new ConfigOptionFloat(0.15);
|
||||
|
||||
def = this->add("adaptive_slicing_z_gradation", coFloat);
|
||||
def->label = "Min layer height gradation";
|
||||
def->tooltip = "Limit layer heights to a multiple of this value to avoid stepping inaccuracies at the Z-axis. Typical value for a Prusa i3, 1/16 micro-stepping is 0.004mm. Set zero do disable this option.";
|
||||
@ -133,15 +142,6 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->cli = "cooling!";
|
||||
def->default_value = new ConfigOptionBool(true);
|
||||
|
||||
def = this->add("cusp_value", coFloat);
|
||||
def->label = "Cusp value";
|
||||
def->tooltip = "This value determines the maximum deviaton from the objects original surface caused by the stair-stepping effect (approximation of the surface by discrete layers). Use a value between 0 (highest possible resolution) and [max_layer_height] (lowest possible resolution). Typical values are 0.1 - 0.2.";
|
||||
def->sidetext = "mm";
|
||||
def->cli = "cusp_value=f";
|
||||
def->min = 0;
|
||||
def->max = 1;
|
||||
def->default_value = new ConfigOptionFloat(0.15);
|
||||
|
||||
def = this->add("default_acceleration", coFloat);
|
||||
def->label = "Default";
|
||||
def->tooltip = "This is the acceleration your printer will be reset to after the role-specific acceleration values are used (perimeter/infill). Set zero to prevent resetting acceleration at all.";
|
||||
|
@ -141,7 +141,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
||||
public:
|
||||
ConfigOptionBool adaptive_slicing;
|
||||
ConfigOptionFloat adaptive_slicing_z_gradation;
|
||||
ConfigOptionFloat cusp_value;
|
||||
ConfigOptionFloat adaptive_slicing_quality;
|
||||
ConfigOptionBool dont_support_bridges;
|
||||
ConfigOptionFloatOrPercent extrusion_width;
|
||||
ConfigOptionFloatOrPercent first_layer_height;
|
||||
@ -175,7 +175,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
OPT_PTR(adaptive_slicing);
|
||||
OPT_PTR(adaptive_slicing_z_gradation);
|
||||
OPT_PTR(cusp_value);
|
||||
OPT_PTR(adaptive_slicing_quality);
|
||||
OPT_PTR(dont_support_bridges);
|
||||
OPT_PTR(extrusion_width);
|
||||
OPT_PTR(first_layer_height);
|
||||
|
@ -246,7 +246,7 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
|
||||
|| *opt_key == "xy_size_compensation"
|
||||
|| *opt_key == "adaptive_slicing"
|
||||
|| *opt_key == "adaptive_slicing_z_gradation"
|
||||
|| *opt_key == "cusp_value"
|
||||
|| *opt_key == "adaptive_slicing_quality"
|
||||
|| *opt_key == "match_horizontal_surfaces"
|
||||
|| *opt_key == "raft_layers") {
|
||||
steps.insert(posSlice);
|
||||
|
Loading…
x
Reference in New Issue
Block a user