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
This commit is contained in:
Valerii Bokhan 2025-10-20 15:45:52 +02:00 committed by GitHub
parent 0bdb114881
commit e6a4ddf32d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 158 additions and 7 deletions

View file

@ -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.

View file

@ -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) {

View file

@ -834,6 +834,7 @@ static std::vector<std::string> 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",

View file

@ -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");

View file

@ -1082,6 +1082,18 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, small_area_infill_flow_compensation))
((ConfigOptionEnum<WallDirection>, 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<SeamScarfType>, seam_slope_type))
((ConfigOptionBool, seam_slope_conditional))

View file

@ -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);

View file

@ -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");