Skip to content

Commit

Permalink
[FEATURE] Alternate extra perimeter
Browse files Browse the repository at this point in the history
This ports the "Alternate extra wall" feature from [Cura](https://support.makerbot.com/s/article/1837650983225) to PrusaSlicer.

This setting adds an extra wall every other layer. This way the infill gets caught between the walls, resulting in:

* Theoretically, stronger prints due to better infill anchoring.
* Allows for the infill/wall overlap to be set to low values without compromising object strength while maintaining external surface quality.
* It may contribute to improving water tightness of models as the gaps between the top and bottom layers and the walls are overlapping.
  • Loading branch information
mjonuschat committed Sep 13, 2024
1 parent 28cfe1b commit 2ccc328
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 7 deletions.
8 changes: 8 additions & 0 deletions src/libslic3r/PerimeterGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,8 @@ static std::vector<std::string> s_Preset_print_options {
"travel_jerk",
"wipe_tower_accel_to_decel",
"wipe_tower_jerk",

"alternate_extra_perimeter",
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
10 changes: 10 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<InfillPattern>, fill_pattern))
Expand Down
9 changes: 5 additions & 4 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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())) {
Expand Down Expand Up @@ -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);
}

Expand Down
5 changes: 4 additions & 1 deletion src/slic3r/GUI/ConfigManipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
double fill_density = config->option<ConfigOptionPercent>("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") &&
Expand All @@ -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"
Expand All @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion src/slic3r/GUI/GUI_Factories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/slic3r/GUI/Plater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<NotificationManager>(q))
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit 2ccc328

Please sign in to comment.