Implemented adaptive layer height algorithm based on volumetric surface quality

This commit is contained in:
Florens Wasserfall 2017-03-07 12:51:58 +01:00
parent ece3a6e0ad
commit 22ffb76fb1
8 changed files with 103 additions and 319 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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{

View File

@ -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';

View File

@ -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.";

View File

@ -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);

View File

@ -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);