From 070b2af3fd02f8b68ef8dd61b609f5f40e2faa52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 24 Jun 2024 10:19:02 +0200 Subject: [PATCH] Refactoring of the dynamic speed on overhangs. --- src/libslic3r/GCode.cpp | 33 +++--- src/libslic3r/GCode/ExtrusionProcessor.cpp | 125 +++++++++++++-------- src/libslic3r/GCode/ExtrusionProcessor.hpp | 20 ++-- src/slic3r/GUI/Tab.cpp | 2 +- 4 files changed, 110 insertions(+), 70 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index cd12ad34cb..86279de57c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3217,21 +3217,20 @@ std::string GCodeGenerator::_extrude( else if (this->object_layer_over_raft()) speed = m_config.get_abs_value("first_layer_speed_over_raft", speed); - std::pair dynamic_speed_and_fan_speed{-1, -1}; + ExtrusionProcessor::OverhangSpeeds dynamic_print_and_fan_speeds = {-1.f, -1.f}; if (path_attr.overhang_attributes.has_value()) { - double external_perim_reference_speed = m_config.get_abs_value("external_perimeter_speed"); - if (external_perim_reference_speed == 0) - external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm; - external_perim_reference_speed = cap_speed( - external_perim_reference_speed, m_config, m_writer.extruder()->id(), path_attr - ); + double external_perimeter_reference_speed = m_config.get_abs_value("external_perimeter_speed"); + if (external_perimeter_reference_speed == 0) { + external_perimeter_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm; + } - dynamic_speed_and_fan_speed = ExtrusionProcessor::calculate_overhang_speed(path_attr, this->m_config, m_writer.extruder()->id(), - external_perim_reference_speed, speed); + external_perimeter_reference_speed = cap_speed(external_perimeter_reference_speed, m_config, m_writer.extruder()->id(), path_attr); + dynamic_print_and_fan_speeds = ExtrusionProcessor::calculate_overhang_speed(path_attr, this->m_config, m_writer.extruder()->id(), + float(external_perimeter_reference_speed), float(speed)); } - if (dynamic_speed_and_fan_speed.first > -1) { - speed = dynamic_speed_and_fan_speed.first; + if (dynamic_print_and_fan_speeds.print_speed > -1) { + speed = dynamic_print_and_fan_speeds.print_speed; } // cap speed with max_volumetric_speed anyway (even if user is not using autospeed) @@ -3292,8 +3291,10 @@ std::string GCodeGenerator::_extrude( // F is mm per minute. gcode += m_writer.set_speed(F, "", cooling_marker_setspeed_comments); - if (dynamic_speed_and_fan_speed.second >= 0) - gcode += ";_SET_FAN_SPEED" + std::to_string(int(dynamic_speed_and_fan_speed.second)) + "\n"; + + if (dynamic_print_and_fan_speeds.fan_speed >= 0) { + gcode += ";_SET_FAN_SPEED" + std::to_string(int(dynamic_print_and_fan_speeds.fan_speed)) + "\n"; + } std::string comment; if (m_config.gcode_comments) { @@ -3343,11 +3344,13 @@ std::string GCodeGenerator::_extrude( } } - if (m_enable_cooling_markers) + if (m_enable_cooling_markers) { gcode += path_attr.role.is_bridge() ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n"; + } - if (dynamic_speed_and_fan_speed.second >= 0) + if (dynamic_print_and_fan_speeds.fan_speed >= 0) { gcode += ";_RESET_FAN_SPEED\n"; + } this->last_position = path.back().point; return gcode; diff --git a/src/libslic3r/GCode/ExtrusionProcessor.cpp b/src/libslic3r/GCode/ExtrusionProcessor.cpp index 51acead1cc..d818581e8f 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.cpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.cpp @@ -11,7 +11,7 @@ #include "libslic3r/Line.hpp" #include "libslic3r/Polygon.hpp" -namespace Slic3r { namespace ExtrusionProcessor { +namespace Slic3r::ExtrusionProcessor { ExtrusionPaths calculate_and_split_overhanging_extrusions(const ExtrusionPath &path, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, @@ -146,57 +146,84 @@ ExtrusionEntityCollection calculate_and_split_overhanging_extrusions(const Extru return result; }; - -std::pair calculate_overhang_speed(const ExtrusionAttributes &attributes, - const FullPrintConfig &config, - size_t extruder_id, - float external_perim_reference_speed, - float default_speed) +static std::map calc_print_speed_sections(const ExtrusionAttributes &attributes, + const FullPrintConfig &config, + const float external_perimeter_reference_speed, + const float default_speed) { - assert(attributes.overhang_attributes.has_value()); - std::vector> overhangs_with_speeds = { - {100, ConfigOptionFloatOrPercent{default_speed, false}}}; + struct OverhangWithSpeed + { + int percent; + ConfigOptionFloatOrPercent print_speed; + }; + + std::vector overhangs_with_speeds = {{100, ConfigOptionFloatOrPercent{default_speed, false}}}; if (config.enable_dynamic_overhang_speeds) { - overhangs_with_speeds = {{0, config.overhang_speed_0}, - {25, config.overhang_speed_1}, - {50, config.overhang_speed_2}, - {75, config.overhang_speed_3}, + overhangs_with_speeds = {{ 0, config.overhang_speed_0}, + { 25, config.overhang_speed_1}, + { 50, config.overhang_speed_2}, + { 75, config.overhang_speed_3}, {100, ConfigOptionFloatOrPercent{default_speed, false}}}; } - std::vector> overhang_with_fan_speeds = {{100, ConfigOptionInts{0}}}; - if (config.enable_dynamic_fan_speeds.get_at(extruder_id)) { - overhang_with_fan_speeds = {{0, config.overhang_fan_speed_0}, - {25, config.overhang_fan_speed_1}, - {50, config.overhang_fan_speed_2}, - {75, config.overhang_fan_speed_3}, - {100, ConfigOptionInts{0}}}; - } - - float speed_base = external_perim_reference_speed > 0 ? external_perim_reference_speed : default_speed; + const float speed_base = external_perimeter_reference_speed > 0 ? external_perimeter_reference_speed : default_speed; std::map speed_sections; - for (size_t i = 0; i < overhangs_with_speeds.size(); i++) { - float distance = attributes.width * (1.0 - (overhangs_with_speeds[i].first / 100.0)); - float speed = overhangs_with_speeds[i].second.percent ? (speed_base * overhangs_with_speeds[i].second.value / 100.0) : - overhangs_with_speeds[i].second.value; - if (speed < EPSILON) + for (OverhangWithSpeed &overhangs_with_speed : overhangs_with_speeds) { + const float distance = attributes.width * (1.f - (float(overhangs_with_speed.percent) / 100.f)); + float speed = float(overhangs_with_speed.print_speed.get_abs_value(speed_base)); + + if (speed < EPSILON) { speed = speed_base; + } + speed_sections[distance] = speed; } + return speed_sections; +} + +static std::map calc_fan_speed_sections(const ExtrusionAttributes &attributes, + const FullPrintConfig &config, + const size_t extruder_id) +{ + struct OverhangWithFanSpeed + { + int percent; + ConfigOptionInts fan_speed; + }; + + std::vector overhang_with_fan_speeds = {{100, ConfigOptionInts{0}}}; + if (config.enable_dynamic_fan_speeds.get_at(extruder_id)) { + overhang_with_fan_speeds = {{ 0, config.overhang_fan_speed_0}, + { 25, config.overhang_fan_speed_1}, + { 50, config.overhang_fan_speed_2}, + { 75, config.overhang_fan_speed_3}, + {100, ConfigOptionInts{0}}}; + } + std::map fan_speed_sections; - for (size_t i = 0; i < overhang_with_fan_speeds.size(); i++) { - float distance = attributes.width * (1.0 - (overhang_with_fan_speeds[i].first / 100.0)); - float fan_speed = overhang_with_fan_speeds[i].second.get_at(extruder_id); + for (OverhangWithFanSpeed &overhang_with_fan_speed : overhang_with_fan_speeds) { + float distance = attributes.width * (1.f - (float(overhang_with_fan_speed.percent) / 100.f)); + float fan_speed = float(overhang_with_fan_speed.fan_speed.get_at(extruder_id)); fan_speed_sections[distance] = fan_speed; } + return fan_speed_sections; +} + +OverhangSpeeds calculate_overhang_speed(const ExtrusionAttributes &attributes, + const FullPrintConfig &config, + const size_t extruder_id, + const float external_perimeter_reference_speed, + const float default_speed) +{ + assert(attributes.overhang_attributes.has_value()); + auto interpolate_speed = [](const std::map &values, float distance) { auto upper_dist = values.lower_bound(distance); if (upper_dist == values.end()) { return values.rbegin()->second; - } - if (upper_dist == values.begin()) { + } else if (upper_dist == values.begin()) { return upper_dist->second; } @@ -205,22 +232,26 @@ std::pair calculate_overhang_speed(const ExtrusionAttributes &attri return (1.0f - t) * lower_dist->second + t * upper_dist->second; }; - float extrusion_speed = std::min(interpolate_speed(speed_sections, attributes.overhang_attributes->start_distance_from_prev_layer), - interpolate_speed(speed_sections, attributes.overhang_attributes->end_distance_from_prev_layer)); - float curled_base_speed = interpolate_speed(speed_sections, - attributes.width * attributes.overhang_attributes->proximity_to_curled_lines); - float final_speed = std::min(curled_base_speed, extrusion_speed); - float fan_speed = std::min(interpolate_speed(fan_speed_sections, attributes.overhang_attributes->start_distance_from_prev_layer), - interpolate_speed(fan_speed_sections, attributes.overhang_attributes->end_distance_from_prev_layer)); + const std::map speed_sections = calc_print_speed_sections(attributes, config, external_perimeter_reference_speed, default_speed); + const std::map fan_speed_sections = calc_fan_speed_sections(attributes, config, extruder_id); + const float extrusion_speed = std::min(interpolate_speed(speed_sections, attributes.overhang_attributes->start_distance_from_prev_layer), + interpolate_speed(speed_sections, attributes.overhang_attributes->end_distance_from_prev_layer)); + const float curled_base_speed = interpolate_speed(speed_sections, attributes.width * attributes.overhang_attributes->proximity_to_curled_lines); + + const float fan_speed = std::min(interpolate_speed(fan_speed_sections, attributes.overhang_attributes->start_distance_from_prev_layer), + interpolate_speed(fan_speed_sections, attributes.overhang_attributes->end_distance_from_prev_layer)); + + OverhangSpeeds overhang_speeds = {std::min(curled_base_speed, extrusion_speed), fan_speed}; if (!config.enable_dynamic_overhang_speeds) { - final_speed = -1; - } - if (!config.enable_dynamic_fan_speeds.get_at(extruder_id)) { - fan_speed = -1; + overhang_speeds.print_speed = -1; } - return {final_speed, fan_speed}; + if (!config.enable_dynamic_fan_speeds.get_at(extruder_id)) { + overhang_speeds.fan_speed = -1; + } + + return overhang_speeds; } -}} // namespace Slic3r::ExtrusionProcessor +} // namespace Slic3r::ExtrusionProcessor diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 2dc94b2f65..0b0610bc30 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -42,7 +42,7 @@ class CurledLine; class Linef; } // namespace Slic3r -namespace Slic3r { namespace ExtrusionProcessor { +namespace Slic3r::ExtrusionProcessor { struct ExtendedPoint { @@ -51,6 +51,12 @@ struct ExtendedPoint float curvature; }; +struct OverhangSpeeds +{ + float print_speed; + float fan_speed; +}; + template std::vector estimate_points_properties(const POINTS &input_points, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, @@ -266,12 +272,12 @@ ExtrusionEntityCollection calculate_and_split_overhanging_extrusions( const AABBTreeLines::LinesDistancer &unscaled_prev_layer, const AABBTreeLines::LinesDistancer &prev_layer_curled_lines); -std::pair calculate_overhang_speed(const ExtrusionAttributes &attributes, - const FullPrintConfig &config, - size_t extruder_id, - float external_perim_reference_speed, - float default_speed); +OverhangSpeeds calculate_overhang_speed(const ExtrusionAttributes &attributes, + const FullPrintConfig &config, + size_t extruder_id, + float external_perimeter_reference_speed, + float default_speed); -}} // namespace Slic3r::ExtrusionProcessor +} // namespace Slic3r::ExtrusionProcessor #endif // slic3r_ExtrusionProcessor_hpp_ diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fc00ac88b9..c68c7128fc 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2389,7 +2389,7 @@ void TabFilament::toggle_options() bool dynamic_fan_speeds = m_config->opt_bool("enable_dynamic_fan_speeds", 0); for (int i = 0; i < 4; i++) { - toggle_option("overhang_fan_speed_"+std::to_string(i),dynamic_fan_speeds); + toggle_option("overhang_fan_speed_"+std::to_string(i),dynamic_fan_speeds); } }