diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7088a158d..34a252abd 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1,3 +1,4 @@ +#include "Config.hpp" #include "libslic3r.h" #include "GCode/ExtrusionProcessor.hpp" #include "I18N.hpp" @@ -2870,12 +2871,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de bool variable_speed = false; std::vector new_points{}; if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && path.role().is_perimeter()) { + std::vector> overhangs_with_speeds{ + {0, m_config.overhang_speed_0}, {20, m_config.overhang_speed_1}, {40, m_config.overhang_speed_2}, + {60, m_config.overhang_speed_3}, {80, m_config.overhang_speed_4}, + }; double external_perim_reference_speed = std::min(m_config.get_abs_value("external_perimeter_speed"), std::min(EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm, m_config.max_volumetric_speed.value / path.mm3_per_mm)); - new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_overlap_levels, - m_config.dynamic_overhang_speeds, - external_perim_reference_speed, speed); + new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhangs_with_speeds, external_perim_reference_speed, + speed); variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; }); } diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 7ce7a77f6..066f1acd1 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -257,26 +257,25 @@ public: next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf(layer->lslices)}; } - std::vector estimate_extrusion_quality(const ExtrusionPath &path, - const ConfigOptionPercents &overlaps, - const ConfigOptionFloatsOrPercents &speeds, - float ext_perimeter_speed, - float original_speed) + std::vector estimate_extrusion_quality(const ExtrusionPath &path, + const std::vector> overhangs_w_speeds, + float ext_perimeter_speed, + float original_speed) { - size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size()); - float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; + float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; std::vector> speed_sections; - for (size_t i = 0; i < speed_sections_count; i++) { - float distance = path.width * (1.0 - (overlaps.get_at(i) / 100.0)); - float speed = speeds.get_at(i).percent ? (speed_base * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value; + for (size_t i = 0; i < overhangs_w_speeds.size(); i++) { + float distance = path.width * (1.0 - (overhangs_w_speeds[i].first / 100.0)); + float speed = overhangs_w_speeds[i].second.percent ? (speed_base * overhangs_w_speeds[i].second.value / 100.0) : + overhangs_w_speeds[i].second.value; speed_sections.push_back({distance, speed}); } - std::sort(speed_sections.begin(), speed_sections.end(), - [](const std::pair &a, const std::pair &b) { - if (a.first == b.first) { - return a.second > b.second; - } - return a.first < b.first; }); + std::sort(speed_sections.begin(), speed_sections.end(), [](const std::pair &a, const std::pair &b) { + if (a.first == b.first) { + return a.second > b.second; + } + return a.first < b.first; + }); std::pair last_section{INFINITY, 0}; for (auto §ion : speed_sections) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 55a643ea1..60c415cf6 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -440,7 +440,7 @@ static std::vector s_Preset_print_options { "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_dist", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", - "enable_dynamic_overhang_speeds", "dynamic_overhang_speeds", "overhang_overlap_levels", + "enable_dynamic_overhang_speeds", "overhang_speed_0", "overhang_speed_1", "overhang_speed_2", "overhang_speed_3", "overhang_speed_4", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", "external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 76fddebc4..01dbfee16 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -534,36 +534,63 @@ void PrintConfigDef::init_fff_params() def = this->add("enable_dynamic_overhang_speeds", coBool); def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); - def->tooltip = L("This setting enables dynamic speed control on overhangs."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); - - def = this->add("overhang_overlap_levels", coPercents); - def->full_label = L("Overhang overlap levels"); - def->category = L("Speed"); - def->tooltip = L("Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " + def->tooltip = L("This setting enables dynamic speed control on overhangs." + "Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion). " "Each overhang level then corresponds with the overhang speed below. Speeds for overhang levels in between are " "calculated via linear interpolation." "If you set multiple different speeds for the same overhang level, only the largest speed is used. " - ); - def->sidetext = L("%"); - def->min = 0; - def->max = 100; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionPercents({60, 40, 20, 0})); - - def = this->add("dynamic_overhang_speeds", coFloatsOrPercents); - def->full_label = L("Dynamic speed on overhangs"); - def->category = L("Speed"); - def->tooltip = L("This setting controls the speed on the overhang with the overlap value set above. " + "This setting controls the speed on the overhang with the overlap value set above. " "The speed of the extrusion is calculated as a linear interpolation of the speeds for higher and lower overlap. " "If set as percentage, the speed is calculated over the external perimeter speed." - ); + ); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("overhang_speed_0", coFloatOrPercent); + def->full_label = L("speed for 0\% overlap (bridge)"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloatsOrPercents({{25, false}, {20, false}, {15, false}, {15, false}})); + def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); + + def = this->add("overhang_speed_1", coFloatOrPercent); + def->full_label = L("speed for 20\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); + + def = this->add("overhang_speed_2", coFloatOrPercent); + def->full_label = L("speed for 40\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + + def = this->add("overhang_speed_3", coFloatOrPercent); + def->full_label = L("speed for 60\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + + def = this->add("overhang_speed_4", coFloatOrPercent); + def->full_label = L("speed for 80\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); def = this->add("brim_width", coFloat); def->label = L("Brim width"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b89957149..d7889fa01 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -573,8 +573,11 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, external_perimeter_extrusion_width)) ((ConfigOptionFloatOrPercent, external_perimeter_speed)) ((ConfigOptionBool, enable_dynamic_overhang_speeds)) - ((ConfigOptionPercents, overhang_overlap_levels)) - ((ConfigOptionFloatsOrPercents, dynamic_overhang_speeds)) + ((ConfigOptionFloatOrPercent, overhang_speed_0)) + ((ConfigOptionFloatOrPercent, overhang_speed_1)) + ((ConfigOptionFloatOrPercent, overhang_speed_2)) + ((ConfigOptionFloatOrPercent, overhang_speed_3)) + ((ConfigOptionFloatOrPercent, overhang_speed_4)) ((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters_on_overhangs)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index efdcb4fc6..ad48efb6d 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -765,8 +765,11 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_interface_speed" || opt_key == "bridge_speed" || opt_key == "enable_dynamic_overhang_speeds" - || opt_key == "overhang_overlap_levels" - || opt_key == "dynamic_overhang_speeds" + || opt_key == "overhang_speed_0" + || opt_key == "overhang_speed_1" + || opt_key == "overhang_speed_2" + || opt_key == "overhang_speed_3" + || opt_key == "overhang_speed_4" || opt_key == "external_perimeter_speed" || opt_key == "infill_speed" || opt_key == "perimeter_speed" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 120aeecf3..e6316e913 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -221,12 +221,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_perimeters = config->opt_int("perimeters") > 0; for (auto el : { "extra_perimeters","extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", "seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width", - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds", "overhang_overlap_levels", "dynamic_overhang_speeds" }) + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds"}) toggle_field(el, have_perimeters); - for (size_t i = 0; i < 4; i++) { - toggle_field("overhang_overlap_levels#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); - toggle_field("dynamic_overhang_speeds#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); + for (size_t i = 0; i < 5; i++) { + toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); } bool have_infill = config->option("fill_density")->value > 0; diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index d63a46d16..02e322bca 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -98,10 +98,6 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty suffix_local = " " + _(suffix); suffix = " " + suffix; } - else if (gc.group == "Dynamic overhang speed" && id >= 0) { - suffix = " " + std::to_string(id+1); - suffix_local = suffix; - } if (!label.IsEmpty()) options.emplace_back(Option{ boost::nowide::widen(key), type, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 17ddd63ab..2d556471c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1549,18 +1549,12 @@ void TabPrint::build() optgroup->append_single_option_line("ironing_speed"); optgroup = page->new_optgroup(L("Dynamic overhang speed")); - auto append_option_line = [](ConfigOptionsGroupShp optgroup, std::string opt_key) { - auto option = optgroup->get_option(opt_key, 0); - auto line = Line{option.opt.full_label, ""}; - line.append_option(option); - line.append_option(optgroup->get_option(opt_key, 1)); - line.append_option(optgroup->get_option(opt_key, 2)); - line.append_option(optgroup->get_option(opt_key, 3)); - optgroup->append_line(line); - }; optgroup->append_single_option_line("enable_dynamic_overhang_speeds"); - append_option_line(optgroup,"overhang_overlap_levels"); - append_option_line(optgroup,"dynamic_overhang_speeds"); + optgroup->append_single_option_line("overhang_speed_0"); + optgroup->append_single_option_line("overhang_speed_1"); + optgroup->append_single_option_line("overhang_speed_2"); + optgroup->append_single_option_line("overhang_speed_3"); + optgroup->append_single_option_line("overhang_speed_4"); optgroup = page->new_optgroup(L("Speed for non-print moves")); optgroup->append_single_option_line("travel_speed");