diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 6a0cf9cfbf1..c120103ae7c 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -174,6 +174,8 @@ void Layer::make_perimeters() && config.gap_infill_speed.value == other_config.gap_infill_speed.value && config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value && config.detect_overhang_wall == other_config.detect_overhang_wall + && config.overhang_reverse == other_config.overhang_reverse + && config.overhang_reverse_threshold == other_config.overhang_reverse_threshold && config.opt_serialize("inner_wall_line_width") == other_config.opt_serialize("inner_wall_line_width") && config.opt_serialize("outer_wall_line_width") == other_config.opt_serialize("outer_wall_line_width") && config.detect_thin_wall == other_config.detect_thin_wall diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 890d6378985..8fa985a9632 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -21,10 +21,6 @@ static const double narrow_loop_length_threshold = 10; //we think it's small detail area and will generate smaller line width for it static constexpr double SMALLER_EXT_INSET_OVERLAP_TOLERANCE = 0.22; -// Overhang width greater than this will be consider as steep overhang -// This is a percentage of the extrusion width -static constexpr double overhang_steep_width = 0.5; // TODO: make this configurable - namespace Slic3r { // Hierarchy of perimeters. @@ -221,16 +217,18 @@ static void lowpass_filter_by_paths_overhang_degree(ExtrusionPaths& paths) { } template -static bool detect_steep_overhang(bool is_contour, - const BoundingBox &extrusion_bboxs, - double extrusion_width, - const _T extrusion, - const ExPolygons *lower_slices, - bool &steep_overhang_contour, - bool &steep_overhang_hole) +static bool detect_steep_overhang(const PrintRegionConfig *config, + bool is_contour, + const BoundingBox &extrusion_bboxs, + double extrusion_width, + const _T extrusion, + const ExPolygons *lower_slices, + bool &steep_overhang_contour, + bool &steep_overhang_hole) { + double threshold = config->overhang_reverse_threshold.get_abs_value(extrusion_width); // Special case: reverse on every odd layer - if (overhang_steep_width < EPSILON) { + if (threshold < EPSILON) { if (is_contour) { steep_overhang_contour = true; } else { @@ -242,8 +240,8 @@ static bool detect_steep_overhang(bool is_contour, Polygons lower_slcier_chopped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*lower_slices, extrusion_bboxs, true); - // All we need to check is whether we have lines outside `overhang_steep_width` - double off = (overhang_steep_width - 0.5) * extrusion_width; + // All we need to check is whether we have lines outside `threshold` + double off = threshold - 0.5 * extrusion_width; auto limiton_polygons = offset(lower_slcier_chopped, float(scale_(off))); @@ -270,7 +268,8 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime Polygon fuzzified; // Detect steep overhangs - bool overhangs_reverse = perimeter_generator.layer_id % 2 == 1 // Only calculate overhang degree on odd layers + bool overhangs_reverse = perimeter_generator.config->overhang_reverse + && perimeter_generator.layer_id % 2 == 1 // Only calculate overhang degree on odd layers && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None; // and not fuzzy skin for (const PerimeterGeneratorLoop &loop : loops) { @@ -331,7 +330,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime // Skip the check if we already found steep overhangs bool found_steep_overhang = (loop.is_contour && steep_overhang_contour) || (!loop.is_contour && steep_overhang_hole); if (overhangs_reverse && !found_steep_overhang) { - detect_steep_overhang(loop.is_contour, bbox, extrusion_width, Polygons{polygon}, perimeter_generator.lower_slices, + detect_steep_overhang(perimeter_generator.config, loop.is_contour, bbox, extrusion_width, Polygons{polygon}, perimeter_generator.lower_slices, steep_overhang_contour, steep_overhang_hole); } @@ -627,7 +626,8 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p bool &steep_overhang_contour, bool &steep_overhang_hole) { // Detect steep overhangs - bool overhangs_reverse = perimeter_generator.layer_id % 2 == 1 // Only calculate overhang degree on odd layers + bool overhangs_reverse = perimeter_generator.config->overhang_reverse + && perimeter_generator.layer_id % 2 == 1 // Only calculate overhang degree on odd layers && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None; // and not fuzzy skin ExtrusionEntityCollection extrusion_coll; @@ -696,7 +696,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p BoundingBox extrusion_bboxs = get_extents(be_clipped); - if (detect_steep_overhang(pg_extrusion.is_contour, extrusion_bboxs, it.first, be_clipped, perimeter_generator.lower_slices, + if (detect_steep_overhang(perimeter_generator.config, pg_extrusion.is_contour, extrusion_bboxs, it.first, be_clipped, perimeter_generator.lower_slices, steep_overhang_contour, steep_overhang_hole)) { break; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index aee4117fd1e..3290c98b988 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -718,7 +718,7 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle) static std::vector s_Preset_print_options { "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", - "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", + "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold", "seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", "infill_direction", "minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 88472ad0e43..433379fef75 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -807,6 +807,27 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); + def = this->add("overhang_reverse", coBool); + def->label = L("Reverse on odd"); + def->full_label = L("Overhang reversal"); + 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->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("overhang_reverse_threshold", coFloatOrPercent); + def->label = L("Reverse threshold"); + def->full_label = L("Overhang reversal threshold"); + def->category = L("Quality"); + def->tooltip = L("Number of mm the overhang need to be for the reversal to be considered useful. Can be a % of the perimeter width." + "\nValue 0 enables reversal on every odd layers regardless."); + def->sidetext = L("mm or %"); + def->ratio_over = "line_width"; + def->min = 0; + def->max_literal = 20; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(50, true)); + def = this->add("overhang_speed_classic", coBool); def->label = L("Classic mode"); def->category = L("Speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 367e594e032..fb235135669 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -828,6 +828,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, hole_to_polyhole)) ((ConfigOptionFloatOrPercent, hole_to_polyhole_threshold)) ((ConfigOptionBool, hole_to_polyhole_twisted)) + ((ConfigOptionBool, overhang_reverse)) + ((ConfigOptionFloatOrPercent, overhang_reverse_threshold)) ) PRINT_CONFIG_CLASS_DEFINE( diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 1089e27074e..0fc93facb53 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1084,6 +1084,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "fuzzy_skin_thickness" || opt_key == "fuzzy_skin_point_distance" || opt_key == "detect_overhang_wall" + || opt_key == "overhang_reverse" + || opt_key == "overhang_reverse_threshold" //BBS || opt_key == "enable_overhang_speed" || opt_key == "detect_thin_wall" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 8b67342c33a..cbe2da0053f 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -724,6 +724,12 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co for (auto el : { "hole_to_polyhole_threshold", "hole_to_polyhole_twisted" }) toggle_line(el, config->opt_bool("hole_to_polyhole")); + + bool has_detect_overhang_wall = config->opt_bool("detect_overhang_wall"); + bool has_overhang_reverse = config->opt_bool("overhang_reverse"); + bool allow_overhang_reverse = has_detect_overhang_wall && !has_spiral_vase; + toggle_field("overhang_reverse", allow_overhang_reverse); + toggle_line("overhang_reverse_threshold", allow_overhang_reverse && has_overhang_reverse); } void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index dbadbe40a7c..3b2cc375eb3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1910,6 +1910,8 @@ void TabPrint::build() optgroup->append_single_option_line("reduce_crossing_wall"); optgroup->append_single_option_line("max_travel_detour_distance"); optgroup->append_single_option_line("extra_perimeters_on_overhangs"); + optgroup->append_single_option_line("overhang_reverse"); + optgroup->append_single_option_line("overhang_reverse_threshold"); page = add_options_page(L("Strength"), "empty"); optgroup = page->new_optgroup(L("Walls"), L"param_wall");