diff --git a/lib/Slic3r/AdaptiveSlicing.pm b/lib/Slic3r/AdaptiveSlicing.pm index bc18a9ed6..da624edac 100644 --- a/lib/Slic3r/AdaptiveSlicing.pm +++ b/lib/Slic3r/AdaptiveSlicing.pm @@ -6,6 +6,7 @@ use Slic3r::Geometry qw(X Y Z triangle_normal scale unscale); # public has 'mesh' => (is => 'ro', required => 1); +has 'size' => (is => 'ro', required => 1); #private has 'normal_z' => (is => 'ro', default => sub { [] }); # facet_id => [normal]; @@ -158,5 +159,37 @@ sub _facet_cusp_height { return $cusp; } +# Returns the distance to the next horizontal facet in Z-dir +# to consider horizontal object features in slice thickness +sub horizontal_facet_distance { + my $self = shift; + my ($z, $max_height) = @_; + $max_height = scale $max_height; + + my $ordered_id = $self->current_facet; + while ($ordered_id <= $#{$self->ordered_facets}) { + + # facet's minimum is higher than max forward distance -> end loop + if($self->ordered_facets->[$ordered_id]->[1] > $z+$max_height) { + last; + } + + # min_z == max_z -> horizontal facet + if($self->ordered_facets->[$ordered_id]->[1] > $z) { + if($self->ordered_facets->[$ordered_id]->[1] == $self->ordered_facets->[$ordered_id]->[2]) { + return unscale $self->ordered_facets->[$ordered_id]->[1] - $z; + } + } + + $ordered_id++; + } + + # objects maximum? + if($z + $max_height > $self->size) { + return max(unscale $self->size - $z, 0); + } + return unscale $max_height; +} + 1; \ No newline at end of file diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 7325cb5ec..0b13c1e53 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -455,7 +455,7 @@ sub build { my $self = shift; $self->init_config_options(qw( - adaptive_slicing cusp_value + adaptive_slicing cusp_value match_horizontal_surfaces layer_height first_layer_height perimeters spiral_vase top_solid_layers bottom_solid_layers @@ -504,6 +504,7 @@ sub build { $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('match_horizontal_surfaces'); } { my $optgroup = $page->new_optgroup('Vertical shells'); @@ -787,7 +788,7 @@ sub _update { my $have_adaptive_slicing = $config->adaptive_slicing; $self->get_field($_)->toggle($have_adaptive_slicing) - for qw(cusp_value); + for qw(cusp_value match_horizontal_surfaces); $self->get_field($_)->toggle(!$have_adaptive_slicing) for qw(layer_height); diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 2fa90b4c6..a492b16be 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -108,7 +108,8 @@ sub slice { } $adaptive_slicing[$region_id] = Slic3r::AdaptiveSlicing->new( - mesh => $mesh + mesh => $mesh, + size => $self->size->z ); } @@ -136,6 +137,24 @@ sub slice { for my $region_id (0 .. ($self->region_count - 1)) { # get cusp height my $cusp_height = $adaptive_slicing[$region_id]->cusp_height(scale $slice_z, $cusp_value, $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); + 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) { + # yes we can + $cusp_height = $cusp_height-($min_height-$horizontal_dist); + Slic3r::debugf "Shrink layer height to %f\n", $cusp_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; + } + } + } $height = ($id == 0) ? $self->config->get_value('first_layer_height') diff --git a/t/adaptive_slicing.t b/t/adaptive_slicing.t index 9018d83f4..95c7df4e0 100644 --- a/t/adaptive_slicing.t +++ b/t/adaptive_slicing.t @@ -46,7 +46,8 @@ my $test = sub { my $print = Slic3r::Test::init_print('slopy_cube', config => $config); $print->models->[0]->mesh->repair(); my $adaptive_slicing = Slic3r::AdaptiveSlicing->new( - mesh => Slic3r::Test::mesh('slopy_cube') + mesh => Slic3r::Test::mesh('slopy_cube'), + size => 20 ); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index cb52955a8..533f24dc6 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -585,6 +585,12 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloat(0.3); + def = this->add("match_horizontal_surfaces", coBool); + def->label = "Match horizontal surfaces"; + def->tooltip = "Try to match horizontal surfaces during the slicing process. Matching is not guaranteed, very small surfaces and multiple surfaces with low vertical distance might cause bad results."; + def->cli = "match-horizontal-surfaces!"; + def->default_value = new ConfigOptionBool(true); + def = this->add("max_fan_speed", coInt); def->label = "Max"; def->tooltip = "This setting represents the maximum speed of your fan."; @@ -599,7 +605,7 @@ PrintConfigDef::PrintConfigDef() def->tooltip = "This is the highest printable layer height for this extruder and limits the resolution for adaptive slicing. Typical values are slightly smaller than nozzle_diameter."; def->sidetext = "mm"; def->cli = "max-layer-height=f@"; - //def->min = 0; + def->min = 0; { ConfigOptionFloats* opt = new ConfigOptionFloats(); opt->values.push_back(0.3); @@ -636,7 +642,7 @@ PrintConfigDef::PrintConfigDef() def->tooltip = "This is the lowest printable layer height for this extruder and limits the resolution for adaptive slicing. Typical values are 0.1 or 0.05."; def->sidetext = "mm"; def->cli = "min-layer-height=f@"; - //def->min = 0; + def->min = 0; { ConfigOptionFloats* opt = new ConfigOptionFloats(); opt->values.push_back(0.15); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 2521680a1..ed7a4fe5c 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -110,6 +110,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig ConfigOptionBool infill_only_where_needed; ConfigOptionBool interface_shells; ConfigOptionFloat layer_height; + ConfigOptionBool match_horizontal_surfaces; ConfigOptionInt raft_layers; ConfigOptionEnum seam_position; ConfigOptionBool support_material; @@ -141,6 +142,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig OPT_PTR(infill_only_where_needed); OPT_PTR(interface_shells); OPT_PTR(layer_height); + OPT_PTR(match_horizontal_surfaces); OPT_PTR(raft_layers); OPT_PTR(seam_position); OPT_PTR(support_material); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index fa5d3705c..eb744985e 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -229,6 +229,7 @@ PrintObject::invalidate_state_by_config_options(const std::vector