From e4255b3c01fd6fe3b987ce38235739700be8e411 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Fri, 23 Feb 2024 20:45:56 +0800 Subject: [PATCH] Allow specify wall directions (#4156) * Add wall direction option * Force wall direction if specified * Format * Rename default to auto --- src/libslic3r/Layer.cpp | 1 + src/libslic3r/PerimeterGenerator.cpp | 27 ++++++++++++++++++++++++--- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 22 ++++++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 11 +++++++++++ src/libslic3r/PrintObject.cpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 7 ++++++- src/slic3r/GUI/Tab.cpp | 1 + 8 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index a0de4c52e5..d4a1ee6fb5 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -176,6 +176,7 @@ void Layer::make_perimeters() && 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.wall_direction == other_config.wall_direction && 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 884c0652ca..c6b689971d 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -40,7 +40,6 @@ public: // Polygon of this contour. Polygon polygon; // Is it a contour or a hole? - // Contours are CCW oriented, holes are CW oriented. bool is_contour; // BBS: is perimeter using smaller width bool is_smaller_width_perimeter; @@ -1733,8 +1732,19 @@ void PerimeterGenerator::process_classic() // at this point, all loops should be in contours[0] bool steep_overhang_contour = false; bool steep_overhang_hole = false; + const WallDirection wall_direction = config->wall_direction; + if (wall_direction != WallDirection::Auto) { + // Skip steep overhang detection if wall direction is specified + steep_overhang_contour = true; + steep_overhang_hole = true; + } ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls, steep_overhang_contour, steep_overhang_hole); - reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, this->config->overhang_reverse_internal_only); + // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want + if (wall_direction != WallDirection::CounterClockwise) { + reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, + // Reverse internal only if the wall direction is auto + this->config->overhang_reverse_internal_only && wall_direction == WallDirection::Auto); + } // if brim will be printed, reverse the order of perimeters so that // we continue inwards after having finished the brim @@ -2524,8 +2534,19 @@ void PerimeterGenerator::process_arachne() bool steep_overhang_contour = false; bool steep_overhang_hole = false; + const WallDirection wall_direction = config->wall_direction; + if (wall_direction != WallDirection::Auto) { + // Skip steep overhang detection if wall direction is specified + steep_overhang_contour = true; + steep_overhang_hole = true; + } 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, this->config->overhang_reverse_internal_only); + // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want + if (wall_direction != WallDirection::CounterClockwise) { + reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, + // Reverse internal only if the wall direction is auto + this->config->overhang_reverse_internal_only && wall_direction == WallDirection::Auto); + } this->loops->append(extrusion_coll); } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index fff5fc3a8a..39411ee506 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -770,7 +770,7 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle) static std::vector s_Preset_print_options { "layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "slicing_mode", "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", - "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness","reduce_wall_solid_infill", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", + "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness","reduce_wall_solid_infill", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction", "seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", "infill_direction", "counterbole_hole_bridging", "minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index eac42ad70c..2585987198 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -189,6 +189,14 @@ static t_config_enum_values s_keys_map_WallSequence { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallSequence) +//Orca +static t_config_enum_values s_keys_map_WallDirection{ + { "auto", int(WallDirection::Auto) }, + { "ccw", int(WallDirection::CounterClockwise) }, + { "cw", int(WallDirection::Clockwise)}, +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallDirection) + //BBS static t_config_enum_values s_keys_map_PrintSequence { { "by layer", int(PrintSequence::ByLayer) }, @@ -1486,6 +1494,20 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool{false}); + def = this->add("wall_direction", coEnum); + def->label = L("Wall loop direction"); + def->category = L("Quality"); + def->tooltip = L("The direction which the wall loops are extruded when looking down from the top.\n\nBy default all walls are extruded in counter-clockwise, unless Reverse on odd is enabled. Set this to any option other than Auto will force the wall direction regardless of the Reverse on odd.\n\nThis option will be disabled if sprial vase mode is enabled."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("auto"); + def->enum_values.push_back("ccw"); + def->enum_values.push_back("cw"); + def->enum_labels.push_back(L("Auto")); + def->enum_labels.push_back(L("Counter clockwise")); + def->enum_labels.push_back(L("Clockwise")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(WallDirection::Auto)); + def = this->add("extruder", coInt); def->gui_type = ConfigOptionDef::GUIType::i_enum_open; def->label = L("Extruder"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index db53a9b781..c3a48cd9c7 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -98,6 +98,16 @@ enum class WallSequence { InnerOuterInner, Count, }; + +// Orca +enum class WallDirection +{ + Auto, + CounterClockwise, + Clockwise, + Count, +}; + //BBS enum class PrintSequence { ByLayer, @@ -932,6 +942,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionEnum, wall_sequence)) ((ConfigOptionBool, is_infill_first)) ((ConfigOptionBool, small_area_infill_flow_compensation)) + ((ConfigOptionEnum, wall_direction)) ) PRINT_CONFIG_CLASS_DEFINE( diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 8eada8cc42..d7835b0dbb 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1114,6 +1114,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "overhang_reverse" || opt_key == "overhang_reverse_internal_only" || opt_key == "overhang_reverse_threshold" + || opt_key == "wall_direction" //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 69d5279334..2469ebd9ab 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -279,6 +279,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con config->opt_int("enforce_support_layers") == 0 && ! config->opt_bool("detect_thin_wall") && ! config->opt_bool("overhang_reverse") && + config->opt_enum("wall_direction") == WallDirection::Auto && config->opt_enum("timelapse_type") == TimelapseType::tlTraditional)) { wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional.")); @@ -306,6 +307,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0)); new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); new_conf.set_key_value("overhang_reverse", new ConfigOptionBool(false)); + new_conf.set_key_value("wall_direction", new ConfigOptionEnum(WallDirection::Auto)); new_conf.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); sparse_infill_density = 0; timelapse_type = TimelapseType::tlTraditional; @@ -554,6 +556,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill); toggle_field("bottom_shell_thickness", ! has_spiral_vase && has_bottom_solid_infill); + + toggle_field("wall_direction", !has_spiral_vase); // Gap fill is newly allowed in between perimeter lines even for empty infill (see GH #1476). toggle_field("gap_infill_speed", have_perimeters); @@ -732,7 +736,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co 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; + bool force_wall_direction = config->opt_enum("wall_direction") != WallDirection::Auto; + bool allow_overhang_reverse = has_detect_overhang_wall && !has_spiral_vase && !force_wall_direction; toggle_field("overhang_reverse", allow_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); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e6f8a70c24..ae09a6302f 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2017,6 +2017,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Walls and surfaces"), L"param_advanced"); optgroup->append_single_option_line("wall_sequence"); optgroup->append_single_option_line("is_infill_first"); + optgroup->append_single_option_line("wall_direction"); optgroup->append_single_option_line("print_flow_ratio"); optgroup->append_single_option_line("top_solid_infill_flow_ratio"); optgroup->append_single_option_line("bottom_solid_infill_flow_ratio");