diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 1271da121..ba6bb62b7 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -60,11 +60,13 @@ sub slice { $self->set_step_started(STEP_SLICE); $self->print->status_cb->(10, "Processing triangulated mesh"); + my $min_nozzle_diameter; { my @nozzle_diameters = map $self->print->config->get_at('nozzle_diameter', $_), @{$self->print->object_extruders}; - my $lh = min(@nozzle_diameters, $self->config->layer_height); + $min_nozzle_diameter = min(@nozzle_diameters); + my $lh = min($min_nozzle_diameter, $self->config->layer_height); $self->config->set('layer_height', $self->_adjust_layer_height($lh)); } @@ -142,7 +144,8 @@ sub slice { $print_z += $height; $slice_z += $height/2; - + last if $slice_z > $max_z; + ### Slic3r::debugf "Layer %d: height = %s; slice_z = %s; print_z = %s\n", $id, $height, $slice_z, $print_z; $self->add_layer($id, $height, $print_z, $slice_z); @@ -157,6 +160,32 @@ sub slice { } } + # Reduce or thicken the top layer in order to match the original object size. + # This is not actually related to z_steps_per_mm but we only enable it in case + # user provided that value, as it means they really care about the layer height + # accuracy and we don't provide unexpected result for people noticing the last + # layer has a different layer height. + if ($self->print->config->z_steps_per_mm > 0) { + my $first_object_layer = $self->get_layer(0); + my $last_object_layer = $self->get_layer($self->layer_count-1); + my $print_height = $last_object_layer->print_z - $first_object_layer->print_z + $first_object_layer->height; + my $diff = $print_height - unscale($self->size->z); + if ($diff < 0) { + # we need to thicken last layer + $diff = min(abs($diff), $min_nozzle_diameter - $last_object_layer->height); + $last_object_layer->set_height($last_object_layer->height + $diff); + $last_object_layer->set_print_z($last_object_layer->print_z + $diff); + } else { + # we need to reduce last layer + # prevent generation of a too small layer + my $new_height = $last_object_layer->height - $diff; + if ($new_height < $min_nozzle_diameter/2) { + $last_object_layer->set_height($new_height); + $last_object_layer->set_print_z($last_object_layer->print_z - $diff); + } + } + } + # make sure all layers contain layer region objects for all regions my $regions_count = $self->print->region_count; foreach my $layer (@{ $self->layers }) { diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 85035340e..f7c722265 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -166,7 +166,8 @@ Print::invalidate_state_by_config_options(const std::vector steps.insert(psBrim); steps.insert(psSkirt); } else if (*opt_key == "nozzle_diameter" - || *opt_key == "resolution") { + || *opt_key == "resolution" + || *opt_key == "z_steps_per_mm") { osteps.insert(posSlice); } else if (*opt_key == "avoid_crossing_perimeters" || *opt_key == "bed_shape" diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index 4be9feccf..97569854e 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -56,6 +56,10 @@ %code%{ RETVAL = THIS->print_z; %}; coordf_t height() %code%{ RETVAL = THIS->height; %}; + void set_print_z(coordf_t z) + %code%{ THIS->print_z = z; %}; + void set_height(coordf_t h) + %code%{ THIS->height = h; %}; void set_upper_layer(Layer *layer) %code%{ THIS->upper_layer = layer; %};