diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index c965940..6b62fab 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -487,6 +487,8 @@ static std::vector s_Preset_print_options { ,"slow_down_layers" //w26 ,"elefant_foot_compensation_layers" + //w27 + ,"precise_z_height" }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 7753279..78eca15 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -578,7 +578,8 @@ std::string Print::validate(std::vector* warnings) const for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) { const PrintObject &print_object = *m_objects[print_object_idx]; //FIXME It is quite expensive to generate object layers just to get the print height! - if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx)); + //w27 + if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx),print_object.config().precise_z_height.value); ! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) { return // Test whether the last slicing plane is below or above the print volume. diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index cf3de64..e513452 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -321,6 +321,15 @@ void PrintConfigDef::init_common_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionInt(1)); + //w27 + def = this->add("precise_z_height", coBool); + def->label = L("Precise Z height"); + def->tooltip = L("Enable this to get precise z height of object after slicing. " + "It will get the precise object height by fine-tuning the layer heights of the last few layers. " + "Note that this is an experimental parameter."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(0)); + def = this->add("thumbnails", coString); def->label = L("G-code thumbnails"); def->tooltip = L("Picture sizes to be stored into a .gcode / .bgcode and .sl1 / .sl1s files, in the following format: \"XxY/EXT, XxY/EXT, ...\"\n" diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c6eece4..a1fccee 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -601,6 +601,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, filter_top_gap_infill)) //w23 ((ConfigOptionBool, only_one_wall_first_layer)) + //w27 + ((ConfigOptionBool, precise_z_height)) ) PRINT_CONFIG_CLASS_DEFINE( diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index c6c96e2..05ecb33 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -745,7 +745,9 @@ bool PrintObject::invalidate_state_by_config_options( //w12 || opt_key == "xy_size_compensation" || opt_key == "xy_hole_compensation" - || opt_key == "xy_contour_compensation") { + || opt_key == "xy_contour_compensation" + //w27 + || opt_key == "precise_z_height" ) { steps.emplace_back(posSlice); } else if (opt_key == "support_material") { steps.emplace_back(posSupportMaterial); diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index a67ea7a..f3cf7c3 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -521,7 +521,8 @@ void PrintObject::slice() m_print->throw_if_canceled(); m_typed_slices = false; this->clear_layers(); - m_layers = new_layers(this, generate_object_layers(m_slicing_params, layer_height_profile)); + //w27 + m_layers = new_layers(this, generate_object_layers(m_slicing_params, layer_height_profile, m_config.precise_z_height.value)); this->slice_volumes(); m_print->throw_if_canceled(); #if 0 diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index f6ad21e..f9120f2 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -591,10 +591,104 @@ void adjust_layer_height_profile( #endif /* _DEBUG */ } +//w27 +bool adjust_layer_series_to_align_object_height(const SlicingParameters &slicing_params, std::vector &layer_series) +{ + coordf_t object_height = slicing_params.object_print_z_height(); + if (is_approx(layer_series.back(), object_height)) + return true; + + // need at least 5 + 1(first_layer) layers to adjust the height + size_t layer_size = layer_series.size(); + if (layer_size < 12) + return false; + + std::vector last_5_layers_heght; + for (size_t i = 0; i < 5; ++i) { + last_5_layers_heght.emplace_back(layer_series[layer_size - 10 + 2 * i + 1] - layer_series[layer_size - 10 + 2 * i]); + } + + coordf_t gap = abs(layer_series.back() - object_height); + std::vector can_adjust(5, true); // to record whether every layer can adjust layer height + bool taller_than_object = layer_series.back() < object_height; + + auto get_valid_size = [&can_adjust]() -> int { + int valid_size = 0; + for (auto b_adjust : can_adjust) { + valid_size += b_adjust ? 1 : 0; + } + return valid_size; + }; + + auto adjust_layer_height = [&slicing_params, &last_5_layers_heght, &can_adjust, &get_valid_size, + &taller_than_object](coordf_t gap) -> coordf_t { + coordf_t delta_gap = gap / get_valid_size(); + coordf_t remain_gap = 0; + for (size_t i = 0; i < last_5_layers_heght.size(); ++i) { + coordf_t &l_height = last_5_layers_heght[i]; + if (taller_than_object) { + if (can_adjust[i] && is_approx(l_height, slicing_params.max_layer_height)) { + remain_gap += delta_gap; + can_adjust[i] = false; + continue; + } + + if (can_adjust[i] && l_height + delta_gap > slicing_params.max_layer_height) { + remain_gap += l_height + delta_gap - slicing_params.max_layer_height; + l_height = slicing_params.max_layer_height; + can_adjust[i] = false; + } else { + l_height += delta_gap; + } + } else { + if (can_adjust[i] && is_approx(l_height, slicing_params.min_layer_height)) { + remain_gap += delta_gap; + can_adjust[i] = false; + continue; + } + + if (can_adjust[i] && l_height - delta_gap < slicing_params.min_layer_height) { + remain_gap += slicing_params.min_layer_height + delta_gap - l_height; + l_height = slicing_params.min_layer_height; + can_adjust[i] = false; + } else { + l_height -= delta_gap; + } + } + } + return remain_gap; + }; + + while (gap > 0) { + int valid_size = get_valid_size(); + if (valid_size == 0) { + // 5 layers can not adjust z within valid layer height + return false; + } + + gap = adjust_layer_height(gap); + if (is_approx(gap, 0.0)) { + // adjust succeed + break; + } + } + + for (size_t i = 0; i < last_5_layers_heght.size(); ++i) { + if (i > 0) { + layer_series[layer_size - 10 + 2 * i] = layer_series[layer_size - 10 + 2 * i - 1]; + } + layer_series[layer_size - 10 + 2 * i + 1] = layer_series[layer_size - 10 + 2 * i] + last_5_layers_heght[i]; + } + + return true; +} + // Produce object layers as pairs of low / high layer boundaries, stored into a linear vector. std::vector generate_object_layers( const SlicingParameters &slicing_params, - const std::vector &layer_height_profile) + const std::vector &layer_height_profile, + //w27 + bool is_precise_z_height) { assert(! layer_height_profile.empty()); @@ -644,6 +738,9 @@ std::vector generate_object_layers( } //FIXME Adjust the last layer to align with the top object layer exactly? + //w27 + if (is_precise_z_height) + adjust_layer_series_to_align_object_height(slicing_params, out); return out; } diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 101976f..50a0d2b 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -167,9 +167,11 @@ void adjust_layer_height_profile( // Produce object layers as pairs of low / high layer boundaries, stored into a linear vector. // The object layers are based at z=0, ignoring the raft layers. +//w27 std::vector generate_object_layers( const SlicingParameters &slicing_params, - const std::vector &layer_height_profile); + const std::vector &layer_height_profile, + bool is_precise_z_height); // Check whether the layer height profile describes a fixed layer height profile. bool check_object_layers_fixed( diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 70af77f..ded95aa 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -619,10 +619,11 @@ void GLCanvas3D::LayersEditing::generate_layer_height_texture() m_layers_texture.data.assign(m_layers_texture.width * m_layers_texture.height * 5, 0); } + //w27 bool level_of_detail_2nd_level = true; m_layers_texture.cells = Slic3r::generate_layer_height_texture( *m_slicing_parameters, - Slic3r::generate_object_layers(*m_slicing_parameters, m_layer_height_profile), + Slic3r::generate_object_layers(*m_slicing_parameters, m_layer_height_profile,false), m_layers_texture.data.data(), m_layers_texture.height, m_layers_texture.width, level_of_detail_2nd_level); m_layers_texture.valid = true; } diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 0081c17..0453224 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1249,7 +1249,8 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume) // check whether the top layer exceeds the maximum height of the print volume // and, in case, reduce the scale accordingly const auto [slicing_parameters, profile] = wxGetApp().plater()->canvas3D()->get_layers_height_data(get_object_idx()); - auto layers = generate_object_layers(slicing_parameters, profile); + //w27 + auto layers = generate_object_layers(slicing_parameters, profile,false); auto layers_it = layers.rbegin(); while (layers_it != layers.rend() && *layers_it > volume.bounding_volume().max.z()) { ++layers_it; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7e6af00..f7dfb22 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1693,6 +1693,8 @@ void TabPrint::build() optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487"); //w26 optgroup->append_single_option_line("elefant_foot_compensation_layers"); + //w27 + optgroup->append_single_option_line("precise_z_height"); optgroup = page->new_optgroup(L("Arachne perimeter generator")); optgroup->append_single_option_line("wall_transition_angle"); @@ -3015,6 +3017,9 @@ void TabPrinter::build_sla() //w26 optgroup->append_single_option_line("elefant_foot_compensation_layers"); optgroup->append_single_option_line("elefant_foot_min_width"); + //w27 + optgroup->append_single_option_line("precise_z_height"); + optgroup->append_single_option_line("gamma_correction"); optgroup = page->new_optgroup(L("Exposure"));