Add option to "Reverse only internal perimeters" under the reverse on odd feature to reduce part warping (#2722)

This commit is contained in:
Ioannis Giannakas 2023-11-19 11:02:47 +00:00 committed by GitHub
parent e9f519d092
commit cd475f0f94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 71 deletions

View file

@ -1404,7 +1404,7 @@ void PerimeterGenerator::apply_extra_perimeters(ExPolygons &infill_area)
} }
// Reorient loop direction // Reorient loop direction
static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_overhang_contour, bool steep_overhang_hole) static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_overhang_contour, bool steep_overhang_hole, bool reverse_internal_only)
{ {
if (steep_overhang_hole || steep_overhang_contour) { if (steep_overhang_hole || steep_overhang_contour) {
for (auto entity : entities) { for (auto entity : entities) {
@ -1412,7 +1412,18 @@ static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_
ExtrusionLoop *eloop = static_cast<ExtrusionLoop *>(entity); ExtrusionLoop *eloop = static_cast<ExtrusionLoop *>(entity);
// Only reverse when needed // Only reverse when needed
bool need_reverse = ((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour; bool need_reverse = ((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour;
if (need_reverse) {
bool isExternal = false;
if(reverse_internal_only){
for(auto path : eloop->paths){
if(path.role() == erExternalPerimeter){
isExternal = true;
break;
}
}
}
if (need_reverse && !isExternal) {
eloop->make_clockwise(); eloop->make_clockwise();
} }
} }
@ -1710,7 +1721,7 @@ void PerimeterGenerator::process_classic()
bool steep_overhang_contour = false; bool steep_overhang_contour = false;
bool steep_overhang_hole = false; bool steep_overhang_hole = false;
ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls, steep_overhang_contour, steep_overhang_hole); ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls, steep_overhang_contour, steep_overhang_hole);
reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole); reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, this->config->overhang_reverse_internal_only);
// if brim will be printed, reverse the order of perimeters so that // if brim will be printed, reverse the order of perimeters so that
// we continue inwards after having finished the brim // we continue inwards after having finished the brim
@ -2232,7 +2243,7 @@ void PerimeterGenerator::process_arachne()
bool steep_overhang_contour = false; bool steep_overhang_contour = false;
bool steep_overhang_hole = false; bool steep_overhang_hole = false;
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions, steep_overhang_contour, steep_overhang_hole); !extrusion_coll.empty()) { if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions, steep_overhang_contour, steep_overhang_hole); !extrusion_coll.empty()) {
reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole); reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, this->config->overhang_reverse_internal_only);
this->loops->append(extrusion_coll); this->loops->append(extrusion_coll);
} }

View file

@ -726,7 +726,7 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle)
static std::vector<std::string> s_Preset_print_options { static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode", "layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold", "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
"seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", "seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction", "infill_direction",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern", "minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",

View file

@ -840,7 +840,15 @@ void PrintConfigDef::init_fff_params()
def->label = L("Reverse on odd"); def->label = L("Reverse on odd");
def->full_label = L("Overhang reversal"); def->full_label = L("Overhang reversal");
def->category = L("Quality"); def->category = L("Quality");
def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating pattern can drastically improve steep overhang."); def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating pattern can drastically improve steep overhangs.\n\nThis setting can also help reduce part warping due to the reduction of stresses in the part walls.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("overhang_reverse_internal_only", coBool);
def->label = L("Reverse only internal perimeters");
def->full_label = L("Reverse only internal perimeters");
def->category = L("Quality");
def->tooltip = L("Apply the reverse perimeters logic only on internal perimeters. \n\nThis setting greatly reduces part stresses as they are now distributed in alternating directions. This should reduce part warping while also maintaining external wall quality. This feature can be very useful for warp prone material, like ABS/ASA, and also for elastic filaments, like TPU and Silk PLA. It can also help reduce warping on floating regions over supports.\n\nFor this setting to be the most effective, it is recomended to set the Reverse Threshold to 0 so that all internal walls print in alternating directions on odd layers irrespective of their overhang degree.");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));

View file

@ -877,6 +877,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatOrPercent, hole_to_polyhole_threshold)) ((ConfigOptionFloatOrPercent, hole_to_polyhole_threshold))
((ConfigOptionBool, hole_to_polyhole_twisted)) ((ConfigOptionBool, hole_to_polyhole_twisted))
((ConfigOptionBool, overhang_reverse)) ((ConfigOptionBool, overhang_reverse))
((ConfigOptionBool, overhang_reverse_internal_only))
((ConfigOptionFloatOrPercent, overhang_reverse_threshold)) ((ConfigOptionFloatOrPercent, overhang_reverse_threshold))
) )

View file

@ -1097,6 +1097,7 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "fuzzy_skin_point_distance" || opt_key == "fuzzy_skin_point_distance"
|| opt_key == "detect_overhang_wall" || opt_key == "detect_overhang_wall"
|| opt_key == "overhang_reverse" || opt_key == "overhang_reverse"
|| opt_key == "overhang_reverse_internal_only"
|| opt_key == "overhang_reverse_threshold" || opt_key == "overhang_reverse_threshold"
//BBS //BBS
|| opt_key == "enable_overhang_speed" || opt_key == "enable_overhang_speed"

View file

@ -520,21 +520,21 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line("max_volumetric_extrusion_rate_slope_segment_length", have_volumetric_extrusion_rate_slope); toggle_line("max_volumetric_extrusion_rate_slope_segment_length", have_volumetric_extrusion_rate_slope);
if(have_volumetric_extrusion_rate_slope) config->set_key_value("enable_arc_fitting", new ConfigOptionBool(false)); if(have_volumetric_extrusion_rate_slope) config->set_key_value("enable_arc_fitting", new ConfigOptionBool(false));
if(have_volumetric_extrusion_rate_slope_segment_length==0) { if(have_volumetric_extrusion_rate_slope_segment_length==0) {
DynamicPrintConfig new_conf = *config; DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("max_volumetric_extrusion_rate_slope_segment_length", new ConfigOptionInt(1)); new_conf.set_key_value("max_volumetric_extrusion_rate_slope_segment_length", new ConfigOptionInt(1));
apply(config, &new_conf); apply(config, &new_conf);
} }
bool have_perimeters = config->opt_int("wall_loops") > 0; bool have_perimeters = config->opt_int("wall_loops") > 0;
for (auto el : { "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall", for (auto el : { "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width", "seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width",
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" }) "inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" })
toggle_field(el, have_perimeters); toggle_field(el, have_perimeters);
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0; bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
// sparse_infill_filament uses the same logic as in Print::extruders() // sparse_infill_filament uses the same logic as in Print::extruders()
for (auto el : { "sparse_infill_pattern", "infill_combination", for (auto el : { "sparse_infill_pattern", "infill_combination",
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"}) "minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"})
toggle_line(el, have_infill); toggle_line(el, have_infill);
// Only allow configuration of open anchors if the anchoring is enabled. // Only allow configuration of open anchors if the anchoring is enabled.
@ -550,7 +550,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_field(el, has_solid_infill); toggle_field(el, has_solid_infill);
for (auto el : { "infill_direction", "sparse_infill_line_width", for (auto el : { "infill_direction", "sparse_infill_line_width",
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle" }) "sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle" })
toggle_field(el, have_infill || has_solid_infill); toggle_field(el, have_infill || has_solid_infill);
toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill); toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill);
@ -565,7 +565,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_default_acceleration = config->opt_float("default_acceleration") > 0; bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
for (auto el : {"outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration", for (auto el : {"outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration",
"top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"}) "top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"})
toggle_field(el, have_default_acceleration); toggle_field(el, have_default_acceleration);
bool have_default_jerk = config->opt_float("default_jerk") > 0; bool have_default_jerk = config->opt_float("default_jerk") > 0;
@ -605,20 +605,20 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_support_soluble = have_support_material && config->opt_float("support_top_z_distance") == 0; bool have_support_soluble = have_support_material && config->opt_float("support_top_z_distance") == 0;
auto support_style = config->opt_enum<SupportMaterialStyle>("support_style"); auto support_style = config->opt_enum<SupportMaterialStyle>("support_style");
for (auto el : { "support_style", "support_base_pattern", for (auto el : { "support_style", "support_base_pattern",
"support_base_pattern_spacing", "support_expansion", "support_angle", "support_base_pattern_spacing", "support_expansion", "support_angle",
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance", "bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
//BBS: add more support params to dependent of enable_support //BBS: add more support params to dependent of enable_support
"support_type", "support_on_build_plate_only", "support_critical_regions_only", "support_type", "support_on_build_plate_only", "support_critical_regions_only",
"support_object_xy_distance"/*, "independent_support_layer_height"*/}) "support_object_xy_distance"/*, "independent_support_layer_height"*/})
toggle_field(el, have_support_material); toggle_field(el, have_support_material);
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type)); toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug); //toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type); bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
bool support_is_normal_tree = support_is_tree && support_style != smsOrganic && bool support_is_normal_tree = support_is_tree && support_style != smsOrganic &&
// Orca: use organic as default // Orca: use organic as default
support_style != smsDefault; support_style != smsDefault;
bool support_is_organic = support_is_tree && !support_is_normal_tree; bool support_is_organic = support_is_tree && !support_is_normal_tree;
// settings shared by normal and organic trees // settings shared by normal and organic trees
for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter" }) for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter" })
@ -639,11 +639,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_normal_tree); toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_normal_tree);
for (auto el : { "support_interface_spacing", "support_interface_filament", for (auto el : { "support_interface_spacing", "support_interface_filament",
"support_interface_loop_pattern", "support_bottom_interface_spacing" }) "support_interface_loop_pattern", "support_bottom_interface_spacing" })
toggle_field(el, have_support_material && have_support_interface); toggle_field(el, have_support_material && have_support_interface);
bool have_skirt_height = have_skirt && bool have_skirt_height = have_skirt &&
(config->opt_int("skirt_height") > 1 || config->opt_enum<DraftShield>("draft_shield") != dsEnabled); (config->opt_int("skirt_height") > 1 || config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
toggle_line("support_speed", have_support_material || have_skirt_height); toggle_line("support_speed", have_support_material || have_skirt_height);
toggle_line("support_interface_speed", have_support_material && have_support_interface); toggle_line("support_interface_speed", have_support_material && have_support_interface);
@ -693,7 +693,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool has_overhang_speed = config->opt_bool("enable_overhang_speed"); bool has_overhang_speed = config->opt_bool("enable_overhang_speed");
for (auto el : for (auto el :
{"overhang_speed_classic", "overhang_1_4_speed", {"overhang_speed_classic", "overhang_1_4_speed",
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"}) "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
toggle_line(el, has_overhang_speed); toggle_line(el, has_overhang_speed);
bool has_overhang_speed_classic = config->opt_bool("overhang_speed_classic"); bool has_overhang_speed_classic = config->opt_bool("overhang_speed_classic");
@ -707,7 +707,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_arachne = config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne; bool have_arachne = config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne;
for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"min_feature_size", "min_bead_width", "wall_distribution_count", "initial_layer_min_bead_width"}) "min_feature_size", "min_bead_width", "wall_distribution_count", "initial_layer_min_bead_width"})
toggle_line(el, have_arachne); toggle_line(el, have_arachne);
toggle_field("detect_thin_wall", !have_arachne); toggle_field("detect_thin_wall", !have_arachne);
@ -736,6 +736,13 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool allow_overhang_reverse = has_detect_overhang_wall && !has_spiral_vase; bool allow_overhang_reverse = has_detect_overhang_wall && !has_spiral_vase;
toggle_field("overhang_reverse", allow_overhang_reverse); toggle_field("overhang_reverse", allow_overhang_reverse);
toggle_line("overhang_reverse_threshold", allow_overhang_reverse && has_overhang_reverse); toggle_line("overhang_reverse_threshold", allow_overhang_reverse && has_overhang_reverse);
toggle_line("overhang_reverse_internal_only", allow_overhang_reverse && has_overhang_reverse);
bool has_overhang_reverse_internal_only = config->opt_bool("overhang_reverse_internal_only");
if (has_overhang_reverse_internal_only){
DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("overhang_reverse_threshold", new ConfigOptionFloatOrPercent(0,true));
apply(config, &new_conf);
}
toggle_line("timelapse_type", is_BBL_Printer); toggle_line("timelapse_type", is_BBL_Printer);
} }

View file

@ -1911,6 +1911,7 @@ void TabPrint::build()
optgroup->append_single_option_line("max_travel_detour_distance"); optgroup->append_single_option_line("max_travel_detour_distance");
optgroup->append_single_option_line("extra_perimeters_on_overhangs"); optgroup->append_single_option_line("extra_perimeters_on_overhangs");
optgroup->append_single_option_line("overhang_reverse"); optgroup->append_single_option_line("overhang_reverse");
optgroup->append_single_option_line("overhang_reverse_internal_only");
optgroup->append_single_option_line("overhang_reverse_threshold"); optgroup->append_single_option_line("overhang_reverse_threshold");
page = add_options_page(L("Strength"), "empty"); page = add_options_page(L("Strength"), "empty");