diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index f5cb1d127f..0522066cda 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1099,6 +1099,10 @@ void PerimeterGenerator::process_arachne( if (loop_number > 0 && ((params.config.top_one_perimeter_type == TopOnePerimeterType::TopmostOnly && upper_slices == nullptr) || (params.config.only_one_perimeter_first_layer && params.layer_id == 0))) loop_number = 0; + // Extra perimeter on odd layers + if (params.config.alternate_extra_perimeter && params.layer_id % 2 == 0) + loop_number++; + // Calculate how many inner loops remain when TopSurfaces is selected. const int inner_loop_number = (params.config.top_one_perimeter_type == TopOnePerimeterType::TopSurfaces && upper_slices != nullptr) ? loop_number - 1 : -1; @@ -1341,6 +1345,10 @@ void PerimeterGenerator::process_classic( // detect how many perimeters must be generated for this island int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops + // Alternate extra perimeter on odd layers + if (params.config.alternate_extra_perimeter && params.layer_id % 2 == 0) + loop_number++; + // Set the topmost layer to be one perimeter. if (loop_number > 0 && ((params.config.top_one_perimeter_type != TopOnePerimeterType::None && upper_slices == nullptr) || (params.config.only_one_perimeter_first_layer && params.layer_id == 0))) loop_number = 0; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 50ebeb765f..9d768cedc3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -539,6 +539,8 @@ static std::vector s_Preset_print_options { "travel_jerk", "wipe_tower_accel_to_decel", "wipe_tower_jerk", + + "alternate_extra_perimeter", }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 597ac267bf..2b59f82a64 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1084,6 +1084,16 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); + def = this->add("alternate_extra_perimeter", coBool); + def->label = L("Extra perimeter on odd layers"); + def->category = L("Layers and Perimeters"); + def->tooltip = L("This setting adds an extra perimeter to every odd layer. This way the " + "infill gets wedged vertically between the perimeters, resulting in stronger " + "prints. Using lightning infill together with this option is not recommended " + "as there is limited infill to anchor the extra perimeters to."); + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("extruder", coInt); def->label = L("Extruder"); def->category = L("Extruders"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 8a9c881b01..530447d511 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -691,6 +691,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters_on_overhangs)) + ((ConfigOptionBool, alternate_extra_perimeter)) ((ConfigOptionFloat, fill_angle)) ((ConfigOptionPercent, fill_density)) ((ConfigOptionEnum, fill_pattern)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 310e096f58..a04f1c1d5b 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -715,8 +715,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "infill_overlap" || opt_key == "external_perimeters_first" || opt_key == "arc_fitting" - || opt_key == "top_one_perimeter_type" - || opt_key == "only_one_perimeter_first_layer") { + || opt_key == "alternate_extra_perimeter") { steps.emplace_back(posPerimeters); } else if ( opt_key == "small_area_infill_flow_compensation" @@ -1504,7 +1503,8 @@ void PrintObject::discover_vertical_shells() ++ i) { at_least_one_top_projected = true; const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i]; - combine_holes(cache.holes); + if (!region_config.alternate_extra_perimeter.value || (region_config.alternate_extra_perimeter.value && int(idx_layer) % 2 == 0)) + combine_holes(cache.holes); combine_shells(cache.top_surfaces); } if (!at_least_one_top_projected && i < int(cache_top_botom_regions.size())) { @@ -1533,7 +1533,8 @@ void PrintObject::discover_vertical_shells() -- i) { at_least_one_bottom_projected = true; const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i]; - combine_holes(cache.holes); + if (!region_config.alternate_extra_perimeter.value || (region_config.alternate_extra_perimeter.value && int(idx_layer) % 2 == 0)) + combine_holes(cache.holes); combine_shells(cache.bottom_surfaces); } diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 198ff5cf1d..79a64a9ae3 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -77,7 +77,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con double fill_density = config->option("fill_density")->value; if (config->opt_bool("spiral_vase") && - ! (config->opt_int("perimeters") == 1 && + ! (config->opt_int("perimeters") == 1 && + ! config->opt_bool("alternate_extra_perimeter") && config->opt_int("top_solid_layers") == 0 && fill_density == 0 && ! config->opt_bool("support_material") && @@ -86,6 +87,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con { wxString msg_text = _(L("The Spiral Vase mode requires:\n" "- one perimeter\n" + "- no extra perimeter on odd layers\n" "- no top solid layers\n" "- 0% fill density\n" "- no support material\n" @@ -99,6 +101,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con bool support = true; if (!is_global_config || answer == wxID_YES) { new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); + new_conf.set_key_value("alternate_extra_perimeter", new ConfigOptionBool(false)); new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0)); new_conf.set_key_value("fill_density", new ConfigOptionPercent(0)); new_conf.set_key_value("support_material", new ConfigOptionBool(false)); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 34cfead654..851df41966 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -83,7 +83,7 @@ static bool is_improper_category(const std::string& category, const int extruder // pt_FFF static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF = { - { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } }, + { L("Layers and Perimeters"), { "layer_height" , "perimeters", "alternate_extra_perimeter", "top_solid_layers", "bottom_solid_layers" } }, { L("Infill") , { "fill_density", "fill_pattern" } }, { L("Support material") , { "support_material", "support_material_auto", "support_material_threshold", "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8761a503e9..b435c8cb20 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -622,7 +622,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) "support_material", "support_material_extruder", "support_material_interface_extruder", "support_material_contact_distance", "support_material_bottom_contact_distance", "raft_layers", // SuperSlicer - "init_z_rotate", + "init_z_rotate", "alternate_extra_perimeter", })) , sidebar(new Sidebar(q)) , notification_manager(std::make_unique(q)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 8f2befb58b..6e8e336a43 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1448,6 +1448,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Quality (slower slicing)")); optgroup->append_single_option_line("extra_perimeters", category_path + "extra-perimeters-if-needed"); optgroup->append_single_option_line("extra_perimeters_on_overhangs", category_path + "extra-perimeters-on-overhangs"); + optgroup->append_single_option_line("alternate_extra_perimeter", category_path + "alternate-extra-perimeter"); optgroup->append_single_option_line("avoid_crossing_curled_overhangs", category_path + "avoid-crossing-curled-overhangs"); optgroup->append_single_option_line("avoid_crossing_perimeters", category_path + "avoid-crossing-perimeters"); optgroup->append_single_option_line("avoid_crossing_perimeters_max_detour", category_path + "avoid_crossing_perimeters_max_detour");