Top and Bottom layer directions (#13631)

* Top layer direction

* Bottom layer direction

* comSimple
This commit is contained in:
Ian Bassi
2026-07-03 17:27:05 -03:00
committed by GitHub
parent 8309a9e8ee
commit a6dd002fe7
8 changed files with 52 additions and 9 deletions

View File

@@ -936,9 +936,16 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
region_config.sparse_infill_rotate_template.value);
params.fixed_angle = !region_config.sparse_infill_rotate_template.value.empty();
} else {
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value,
region_config.solid_infill_rotate_template.value);
params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty();
const bool top_layer_direction_set = surface.is_top() && region_config.top_layer_direction.value >= 0.;
const bool bottom_layer_direction_set = surface.is_bottom() && region_config.bottom_layer_direction.value >= 0.;
if (top_layer_direction_set || bottom_layer_direction_set) {
params.angle = Geometry::deg2rad(top_layer_direction_set ? region_config.top_layer_direction.value : region_config.bottom_layer_direction.value);
params.fixed_angle = true;
} else {
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value,
region_config.solid_infill_rotate_template.value);
params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty();
}
}
params.bridge_angle = float(surface.bridge_angle);
@@ -1599,16 +1606,20 @@ void Layer::make_ironing()
ironing_params.height = default_layer_height * 0.01 * (!config.filament_ironing_flow.is_nil(extruder_idx)
? config.filament_ironing_flow.get_at(extruder_idx)
: config.ironing_flow);
ironing_params.speed = (!config.filament_ironing_speed.is_nil(extruder_idx)
? config.filament_ironing_speed.get_at(extruder_idx)
: config.ironing_speed);
double ironing_angle = (config.ironing_angle_fixed ? 0 : calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value)) + config.ironing_angle * M_PI / 180.;
ironing_params.speed = (!config.filament_ironing_speed.is_nil(extruder_idx)
? config.filament_ironing_speed.get_at(extruder_idx)
: config.ironing_speed);
const bool top_layer_direction_set = config.top_layer_direction.value >= 0.;
const double top_layer_base_angle = top_layer_direction_set ?
Geometry::deg2rad(config.top_layer_direction.value) :
calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value);
double ironing_angle = (config.ironing_angle_fixed ? 0. : top_layer_base_angle) + config.ironing_angle * M_PI / 180.;
if (config.align_infill_direction_to_model) {
auto m = this->object()->trafo().matrix();
ironing_angle += atan2((double)m(1, 0), (double)m(0, 0));
}
ironing_params.angle = ironing_angle;
ironing_params.fixed_angle = config.ironing_angle_fixed || !config.solid_infill_rotate_template.value.empty();
ironing_params.angle = ironing_angle;
ironing_params.fixed_angle = config.ironing_angle_fixed || top_layer_direction_set || !config.solid_infill_rotate_template.value.empty();
ironing_params.pattern = config.ironing_pattern;
ironing_params.layerm = layerm;
by_extruder.emplace_back(ironing_params);

View File

@@ -1047,6 +1047,8 @@ static std::vector<std::string> s_Preset_print_options{
"bottom_surface_pattern",
"infill_direction",
"solid_infill_direction",
"top_layer_direction",
"bottom_layer_direction",
"counterbore_hole_bridging",
"infill_shift_step",
"sparse_infill_rotate_template",

View File

@@ -2984,6 +2984,26 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(45));
def = this->add("top_layer_direction", coFloat);
def->label = L("Top layer direction");
def->category = L("Strength");
def->tooltip = L("Optional absolute angle for top-layer infill and ironing base direction. Set to -1 to use the current solid infill direction behavior.");
def->sidetext = u8"°"; // degrees, don't need translation
def->min = -1;
def->max = 360;
def->mode = comSimple;
def->set_default_value(new ConfigOptionFloat(-1));
def = this->add("bottom_layer_direction", coFloat);
def->label = L("Bottom layer direction");
def->category = L("Strength");
def->tooltip = L("Optional absolute angle for bottom-layer infill. Set to -1 to use the current solid infill direction behavior.");
def->sidetext = u8"°"; // degrees, don't need translation
def->min = -1;
def->max = 360;
def->mode = comSimple;
def->set_default_value(new ConfigOptionFloat(-1));
def = this->add("sparse_infill_density", coPercent);
def->label = L("Sparse infill density");
def->category = L("Strength");

View File

@@ -1107,6 +1107,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatsNullable, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionFloat, solid_infill_direction))
((ConfigOptionFloat, top_layer_direction))
((ConfigOptionFloat, bottom_layer_direction))
((ConfigOptionString, solid_infill_rotate_template))
((ConfigOptionBool, symmetric_infill_y_axis))
((ConfigOptionFloat, infill_shift_step))

View File

@@ -1303,6 +1303,8 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "skeleton_infill_line_width"
|| opt_key == "infill_direction"
|| opt_key == "solid_infill_direction"
|| opt_key == "top_layer_direction"
|| opt_key == "bottom_layer_direction"
|| opt_key == "align_infill_direction_to_model"
|| opt_key == "extra_solid_infills"
|| opt_key == "ensure_vertical_shell_thickness"

View File

@@ -710,6 +710,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
toggle_field("bottom_surface_pattern", has_bottom_shell);
toggle_field("top_surface_density", has_top_shell);
toggle_field("bottom_surface_density", has_bottom_shell);
toggle_field("top_layer_direction", has_top_shell);
toggle_field("bottom_layer_direction", has_bottom_shell);
for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap",
"bridge_angle", "internal_bridge_angle", "relative_bridge_angle",

View File

@@ -141,6 +141,8 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CATE
{"infill_wall_overlap", "", 1},
{"top_bottom_infill_wall_overlap", "", 1},
{"solid_infill_direction", "", 1},
{"top_layer_direction", "", 1},
{"bottom_layer_direction", "", 1},
{"infill_direction", "", 1},
{"bridge_angle", "", 1},
{"internal_bridge_angle", "", 1},

View File

@@ -2741,10 +2741,12 @@ void TabPrint::build()
optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density");
optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-direction");
optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers");
optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density");
optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#direction");
optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap");
optgroup = page->new_optgroup(L("Infill"), L"param_infill");