From e6a4ddf32d65297c540e658a69ce80cdd9c2004e Mon Sep 17 00:00:00 2001 From: Valerii Bokhan <80919135+valerii-bokhan@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:45:52 +0200 Subject: [PATCH] Feature: Ability to change flow ratios by extrusion path types (Code + Docs) (#10641) This new feature allows users to override flow ratios for the following extrusion path types: * First layer (excluding Brims and Skirts) * Outer walls * Inner walls * Overhang perimeters * Sparse infill * Internal solid infill * Gap fill * Support * Support interfaces --- .../quality_settings_wall_and_surfaces.md | 4 +- src/libslic3r/GCode.cpp | 38 ++++++-- src/libslic3r/Preset.cpp | 1 + src/libslic3r/PrintConfig.cpp | 96 +++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 12 +++ src/slic3r/GUI/ConfigManipulation.cpp | 4 + src/slic3r/GUI/Tab.cpp | 10 ++ 7 files changed, 158 insertions(+), 7 deletions(-) diff --git a/doc/print_settings/quality/quality_settings_wall_and_surfaces.md b/doc/print_settings/quality/quality_settings_wall_and_surfaces.md index 5674f41e0b..fce72eff22 100644 --- a/doc/print_settings/quality/quality_settings_wall_and_surfaces.md +++ b/doc/print_settings/quality/quality_settings_wall_and_surfaces.md @@ -60,7 +60,9 @@ Set this to any option other than Auto will force the wall direction regardless ## Surface flow ratio This factor affects the amount of material for [top or bottom solid infill](strength_settings_top_bottom_shells). You can decrease it slightly to have smooth surface finish. -The actual top surface flow used is calculated by multiplying this value with the filament flow ratio, and if set, the object's flow ratio. +The actual top or bottom surface flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio. + +Other flow ratios, such as ratios for the first layer (does not affect brims and skirts), outer and inner walls, overhang perimeters, sparse infill, internal solid infill, gap fill, support, and support interfaces, can also be adjusted after enabling the "Set other flow ratios" option. > [!TIP] > Before using a value other than 1, it is recommended to [calibrate the flow ratio](flow-rate-calib) to ensure that the flow ratio is set correctly for your printer and filament. diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 285fdcbab7..65ed652495 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5306,21 +5306,47 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // We set _mm3_per_mm to effectove flow = Geometric volume * print flow ratio * filament flow ratio * role-based-flow-ratios auto _mm3_per_mm = path.mm3_per_mm * this->config().print_flow_ratio; _mm3_per_mm *= filament_flow_ratio; - if (path.role() == erTopSolidInfill) + + if (path.role() == erTopSolidInfill) { _mm3_per_mm *= m_config.top_solid_infill_flow_ratio; - else if (path.role() == erBottomSurface) + } else if (path.role() == erBottomSurface) { _mm3_per_mm *= m_config.bottom_solid_infill_flow_ratio; - else if (path.role() == erInternalBridgeInfill) + } else if (path.role() == erInternalBridgeInfill) { _mm3_per_mm *= m_config.internal_bridge_flow; - else if(sloped) + } else if (sloped) { _mm3_per_mm *= m_config.scarf_joint_flow_ratio; + } + + if (m_config.set_other_flow_ratios) { + if (path.role() == erExternalPerimeter) { + _mm3_per_mm *= m_config.outer_wall_flow_ratio; + } else if (path.role() == erPerimeter) { + _mm3_per_mm *= m_config.inner_wall_flow_ratio; + } else if (path.role() == erOverhangPerimeter) { + _mm3_per_mm *= m_config.overhang_flow_ratio; + } else if (path.role() == erInternalInfill) { + _mm3_per_mm *= m_config.sparse_infill_flow_ratio; + } else if (path.role() == erSolidInfill) { + _mm3_per_mm *= m_config.internal_solid_infill_flow_ratio; + } else if (path.role() == erGapFill) { + _mm3_per_mm *= m_config.gap_fill_flow_ratio; + } else if (path.role() == erSupportMaterial) { // Should this condition also cover erSupportTransition? + _mm3_per_mm *= m_config.support_flow_ratio; + } else if (path.role() == erSupportMaterialInterface) { + _mm3_per_mm *= m_config.support_interface_flow_ratio; + } + + // Additionally, adjust the value if we are on the first layer (except for brims and skirts) + if (this->on_first_layer() && (path.role() != erBrim && path.role() != erSkirt)) { + _mm3_per_mm *= m_config.first_layer_flow_ratio; + } + } + // Effective extrusion length per distance unit = (filament_flow_ratio/cross_section) * mm3_per_mm / print flow ratio // m_writer.extruder()->e_per_mm3() below is (filament flow ratio / cross-sectional area) double e_per_mm = m_writer.extruder()->e_per_mm3() * _mm3_per_mm; e_per_mm /= filament_flow_ratio; - - // set speed if (speed == -1) { if (path.role() == erPerimeter) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 6718e0e809..a57cb84f9b 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -834,6 +834,7 @@ static std::vector s_Preset_print_options { "small_perimeter_speed", "small_perimeter_threshold","bridge_angle","internal_bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface", "default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk","default_junction_deviation", "top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap", + "set_other_flow_ratios", "first_layer_flow_ratio", "outer_wall_flow_ratio", "inner_wall_flow_ratio", "overhang_flow_ratio", "sparse_infill_flow_ratio", "internal_solid_infill_flow_ratio", "gap_fill_flow_ratio", "support_flow_ratio", "support_interface_flow_ratio", "role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop", "bridge_density","internal_bridge_density", "precise_outer_wall", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7b9422c909..c02a9f7744 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1085,6 +1085,102 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(1)); + def = this->add("set_other_flow_ratios", coBool); + def->label = L("Set other flow ratios"); + def->category = L("Advanced"); + def->tooltip = L("Change flow ratios for other extrusion path types."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("first_layer_flow_ratio", coFloat); + def->label = L("First layer flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material on the first layer for the extrusion path roles listed in this section.\n\n" + "For the first layer, the actual flow ratio for each path role (does not affect brims and skirts) will be multiplied by this value."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("outer_wall_flow_ratio", coFloat); + def->label = L("Outer wall flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for outer walls.\n\n" + "The actual outer wall flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("inner_wall_flow_ratio", coFloat); + def->label = L("Inner wall flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for inner walls.\n\n" + "The actual inner wall flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("overhang_flow_ratio", coFloat); + def->label = L("Overhang flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for overhangs.\n\n" + "The actual overhang flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("sparse_infill_flow_ratio", coFloat); + def->label = L("Sparse infill flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for sparse infill.\n\n" + "The actual sparse infill flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("internal_solid_infill_flow_ratio", coFloat); + def->label = L("Internal solid infill flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for internal solid infill.\n\n" + "The actual internal solid infill flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("gap_fill_flow_ratio", coFloat); + def->label = L("Gap fill flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for filling the gaps.\n\n" + "The actual gap filling flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("support_flow_ratio", coFloat); + def->label = L("Support flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for support.\n\n" + "The actual support flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); + + def = this->add("support_interface_flow_ratio", coFloat); + def->label = L("Support interface flow ratio"); + def->category = L("Advanced"); + def->tooltip = L("This factor affects the amount of material for the support interface.\n\n" + "The actual support interface flow used is calculated by multiplying this value by the filament flow ratio, and if set, the object's flow ratio."); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(1)); def = this->add("precise_outer_wall",coBool); def->label = L("Precise wall"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 1e927a1a13..45f775bc3a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1082,6 +1082,18 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, small_area_infill_flow_compensation)) ((ConfigOptionEnum, wall_direction)) + // Orca: flow ratios + ((ConfigOptionBool, set_other_flow_ratios)) + ((ConfigOptionFloat, first_layer_flow_ratio)) + ((ConfigOptionFloat, outer_wall_flow_ratio)) + ((ConfigOptionFloat, inner_wall_flow_ratio)) + ((ConfigOptionFloat, overhang_flow_ratio)) + ((ConfigOptionFloat, sparse_infill_flow_ratio)) + ((ConfigOptionFloat, internal_solid_infill_flow_ratio)) + ((ConfigOptionFloat, gap_fill_flow_ratio)) + ((ConfigOptionFloat, support_flow_ratio)) + ((ConfigOptionFloat, support_interface_flow_ratio)) + // Orca: seam slopes ((ConfigOptionEnum, seam_slope_type)) ((ConfigOptionBool, seam_slope_conditional)) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index a8e4e37ac2..f81fb1c62c 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -805,6 +805,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool have_avoid_crossing_perimeters = config->opt_bool("reduce_crossing_wall"); toggle_line("max_travel_detour_distance", have_avoid_crossing_perimeters); + bool has_set_other_flow_ratios = config->opt_bool("set_other_flow_ratios"); + for (auto el : {"first_layer_flow_ratio", "outer_wall_flow_ratio", "inner_wall_flow_ratio", "overhang_flow_ratio", "sparse_infill_flow_ratio", "internal_solid_infill_flow_ratio", "gap_fill_flow_ratio", "support_flow_ratio", "support_interface_flow_ratio"}) + toggle_line(el, has_set_other_flow_ratios); + bool has_overhang_speed = config->opt_bool("enable_overhang_speed"); for (auto el : {"overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"}) toggle_line(el, has_overhang_speed); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 69cffa7571..d8016f8e28 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2183,6 +2183,16 @@ void TabPrint::build() optgroup->append_single_option_line("print_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); optgroup->append_single_option_line("top_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); optgroup->append_single_option_line("bottom_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("set_other_flow_ratios", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("first_layer_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("outer_wall_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("inner_wall_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("overhang_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("sparse_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("internal_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("gap_fill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("support_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); + optgroup->append_single_option_line("support_interface_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); optgroup->append_single_option_line("only_one_wall_top", "quality_settings_wall_and_surfaces#only-one-wall"); optgroup->append_single_option_line("min_width_top_surface", "quality_settings_wall_and_surfaces#threshold"); optgroup->append_single_option_line("only_one_wall_first_layer", "quality_settings_wall_and_surfaces#only-one-wall");