From 309010fff2d65f4cdc79ae3414f396c515ce5d39 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Thu, 28 Mar 2024 20:56:20 +0800 Subject: [PATCH] ENH: add precise_z_height jira: none Change-Id: Idb9fcf0063e773f1531a49961478460b91ded10f --- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 4 +- src/libslic3r/PrintConfig.cpp | 9 +++ src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/PrintObjectSlice.cpp | 2 +- src/libslic3r/Slicing.cpp | 99 +++++++++++++++++++++++++++++- src/libslic3r/Slicing.hpp | 3 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GUI_Factories.cpp | 4 +- src/slic3r/GUI/Tab.cpp | 1 + 10 files changed, 119 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 97d46a166..84ca29e5d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -832,7 +832,7 @@ static std::vector s_Preset_print_options { "tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter","tree_support_brim_width", "detect_narrow_internal_solid_infill", - "gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/ + "gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination", /*"adaptive_layer_height",*/ "support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed", "initial_layer_infill_speed", "top_one_wall_type", "top_area_threshold", "only_one_wall_first_layer", "timelapse_type", "internal_bridge_support_thickness", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 5011765ea..26d1ef026 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -209,6 +209,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n opt_key == "initial_layer_print_height" || opt_key == "nozzle_diameter" || opt_key == "resolution" + || opt_key == "precise_z_height" // Spiral Vase forces different kind of slicing than the normal model: // In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer. // Therefore toggling the Spiral Vase on / off requires complete reslicing. @@ -1143,8 +1144,9 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* if (has_custom_layering) { std::vector> layer_z_series; layer_z_series.assign(m_objects.size(), std::vector()); + for (size_t idx_object = 0; idx_object < m_objects.size(); ++idx_object) { - layer_z_series[idx_object] = generate_object_layers(m_objects[idx_object]->slicing_parameters(), layer_height_profiles[idx_object]); + layer_z_series[idx_object] = generate_object_layers(m_objects[idx_object]->slicing_parameters(), layer_height_profiles[idx_object], m_objects[idx_object]->config().precise_z_height.value); } for (size_t idx_object = 0; idx_object < m_objects.size(); ++idx_object) { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a3aa70966..90cee472a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1846,6 +1846,15 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(30)); + // BBS + 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)); + // BBS def = this->add("enable_arc_fitting", coBool); def->label = L("Arc fitting"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c22b093d2..1379a7f30 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -760,6 +760,7 @@ PRINT_CONFIG_CLASS_DEFINE( // OrcaSlicer ((ConfigOptionPercent, seam_gap)) ((ConfigOptionPercent, wipe_speed)) + ((ConfigOptionBool, precise_z_height)) // BBS ) // This object is mapped to Perl as Slic3r::Config::PrintRegion. diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index f9622a6ed..4a680a9c8 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -790,7 +790,7 @@ 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)); + 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(); int firstLayerReplacedBy = 0; diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index b7e159316..d81684e46 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -629,10 +629,104 @@ void adjust_layer_height_profile( #endif /* _DEBUG */ } +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, + bool is_precise_z_height) { assert(! layer_height_profile.empty()); @@ -681,7 +775,8 @@ std::vector generate_object_layers( out.push_back(print_z); } - //FIXME Adjust the last layer to align with the top object layer exactly? + 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 00ea608e6..540754877 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -173,7 +173,8 @@ extern void adjust_layer_height_profile( // The object layers are based at z=0, ignoring the raft layers. extern 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 b79ef7010..fa3965690 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -591,7 +591,7 @@ void GLCanvas3D::LayersEditing::generate_layer_height_texture() 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/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 712140e7e..8c16b75d3 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -77,7 +77,9 @@ std::map> SettingsFactory::OBJECT_C {"wall_sequence","",2}, {"seam_position", "",3}, {"seam_gap", "",4}, {"wipe_speed", "",5}, {"slice_closing_radius", "",6}, {"resolution", "",7}, - {"xy_hole_compensation", "",8}, {"xy_contour_compensation", "",9}, {"elefant_foot_compensation", "",10} + {"xy_hole_compensation", "",8}, {"xy_contour_compensation", "",9}, {"elefant_foot_compensation", "",10}, + {"precise_z_height", "",10} + }}, { L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3}, {"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7}, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 87708b879..6845abfd5 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1967,6 +1967,7 @@ void TabPrint::build() optgroup->append_single_option_line("xy_hole_compensation", "xy-hole-contour-compensation"); optgroup->append_single_option_line("xy_contour_compensation", "xy-hole-contour-compensation"); optgroup->append_single_option_line("elefant_foot_compensation", "parameter/elephant-foot"); + optgroup->append_single_option_line("precise_z_height"); optgroup = page->new_optgroup(L("Ironing"), L"param_ironing"); optgroup->append_single_option_line("ironing_type", "parameter/ironing");