Skip to content

Commit

Permalink
Enhancement: Additional controls over bridges (#8263)
Browse files Browse the repository at this point in the history
* Additional control over bridges

* Label updates

* Detect and handle layers over external bridges

* Label updates

* To-Do placeholders

* Filter out small external bridges

* Apply safety offset for internal bridge polygon intersections

* code comments

* Increase bridge offsets to 3 perimeters total (1.5 perimeter in each dimension)

* Filter out bridges based on perimeter counts to focus bridge on areas where bridge infill is actually generated in the end.

* Fixing bugs

* Convert tick boxes to drop down menu

* Additional geometry checks for second internal bridge to ensure no small polygons are left over.

* Minor code refactor for clarity

* Further refinements in polygon logic

* Polygon logic refinements pt3

* Further union operations to ensure clean geometry

* Fix compile error

* Clean up constructors

* Only create bridges on stInternalSolid areas, not sparse infill.

* Refactor internal second bridge logic to stand alone parallel for loop to avoid thread deadlocks

* Revert change to only consider stInternalSolid areas for second internal bridge layer.

This resulted in partly unsupported solid infill areas above as the remainder was too narrow to generate sparse infill

* Updated beta statements and tooltip changes

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
  • Loading branch information
igiannakas and SoftFever authored Feb 12, 2025
1 parent 3bbee6c commit b4a7721
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.density = layerm->region().config().bridge_density.get_abs_value(1.0);
params.dont_adjust = true;
}
if(surface_fill.surface.is_internal_bridge()){
params.density = f->print_object_config->internal_bridge_density.get_abs_value(1.0);
params.dont_adjust = true;
}
// BBS: make fill
f->fill_surface_extrusion(&surface_fill.surface,
params,
Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ static std::vector<std::string> s_Preset_print_options {
"independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges","enable_extra_bridge_layer", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang",
"filename_format", "wall_filament", "support_bottom_z_distance",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body",
"ooze_prevention", "standby_temperature_delta", "preheat_time","preheat_steps", "interface_shells", "line_width", "initial_layer_line_width",
Expand All @@ -824,7 +824,7 @@ static std::vector<std::string> s_Preset_print_options {
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop",
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"bridge_density","internal_bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width",
Expand Down
88 changes: 71 additions & 17 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,14 @@ static t_config_enum_values s_keys_map_InternalBridgeFilter {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InternalBridgeFilter)

static t_config_enum_values s_keys_map_EnableExtraBridgeLayer {
{ "disabled", eblDisabled },
{ "external_bridge_only", eblExternalBridgeOnly },
{ "internal_bridge_only", eblInternalBridgeOnly },
{ "apply_to_all", eblApplyToAll },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(EnableExtraBridgeLayer)

// Orca
static t_config_enum_values s_keys_map_GapFillTarget {
{ "everywhere", gftEverywhere },
Expand Down Expand Up @@ -967,16 +975,32 @@ void PrintConfigDef::init_fff_params()
def->category = L("Strength");
def->tooltip = L("Internal bridging angle override. If left to zero, the bridging angle will be calculated "
"automatically. Otherwise the provided angle will be used for internal bridges. "
"Use 180°for zero angle.\n\n It is recommended to leave it at 0 unless there is a specific model need not to.");
"Use 180°for zero angle.\n\nIt is recommended to leave it at 0 unless there is a specific model need not to.");
def->sidetext = L("°");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.));

def = this->add("bridge_density", coPercent);
def->label = L("Bridge density");
def->label = L("External bridge density");
def->category = L("Strength");
def->tooltip = L("Density of external bridges. 100% means solid bridge. Default is 100%.");
def->tooltip = L("Controls the density (spacing) of external bridge lines. 100% means solid bridge. Default is 100%.\n\n"
"Lower density external bridges can help improve reliability as there is more space for air to circulate "
"around the extruded bridge, improving its cooling speed.");
def->sidetext = L("%");
def->min = 10;
def->max = 100;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionPercent(100));

def = this->add("internal_bridge_density", coPercent);
def->label = L("Internal bridge density");
def->category = L("Strength");
def->tooltip = L("Controls the density (spacing) of internal bridge lines. 100% means solid bridge. Default is 100%.\n\n "
"Lower density internal bridges can help reduce top surface pillowing and improve internal bridge reliability as there is more space for "
"air to circulate around the extruded bridge, improving its cooling speed. \n\n"
"This option works particularly well when combined with the second internal bridge over infill option, "
"further improving internal bridging structure before solid infill is extruded.");
def->sidetext = L("%");
def->min = 10;
def->max = 100;
Expand Down Expand Up @@ -1432,7 +1456,7 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionBool(false));

def = this->add("thick_bridges", coBool);
def->label = L("Thick bridges");
def->label = L("Thick external bridges");
def->category = L("Quality");
def->tooltip = L("If enabled, bridges are more reliable, can bridge longer distances, but may look worse. "
"If disabled, bridges look better but are reliable just for shorter bridged distances.");
Expand All @@ -1446,23 +1470,53 @@ void PrintConfigDef::init_fff_params()
"consider turning it off if you are using large nozzles.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));

def = this->add("enable_extra_bridge_layer", coEnum);
def->label = L("Extra bridge layers (beta)");
def->category = L("Quality");
def->tooltip = L("This option enables the generation of an extra bridge layer over internal and/or external bridges.\n\n"
"Extra bridge layers help improve bridge appearance and reliability, as the solid infill is better supported. "
"This is especially useful in fast printers, where the bridge and solid infill speeds vary greatly. "
"The extra bridge layer results in reduced pillowing on top surfaces, as well as reduced separation of the external bridge layer from its surrounding perimeters.\n\n"
"It is generally recommended to set this to at least 'External bridge only', unless specific issues with the sliced model are found.\n\n"
"Options:\n"
"1. Disabled - does not generate second bridge layers. This is the default and is set for compatibility purposes.\n"
"2. External bridge only - generates second bridge layers for external-facing bridges only. Please note that small bridges that are shorter "
"or narrower than the set number of perimeters will be skipped as they would not benefit from a second bridge layer. If generated, the second bridge layer will be extruded "
"parallel to the first bridge layer to reinforce the bridge strength.\n"
"3. Internal bridge only - generates second bridge layers for internal bridges over sparse infill only. Please note that the internal "
"bridges count towards the top shell layer count of your model. The second internal bridge layer will be extruded as close to perpendicular to the first as possible. If multiple regions "
"in the same island, with varying bridge angles are present, the last region of that island will be selected as the angle reference.\n"
"4. Apply to all - generates second bridge layers for both internal and external-facing bridges\n");

def->enum_keys_map = &ConfigOptionEnum<EnableExtraBridgeLayer>::get_enum_values();
def->enum_values.push_back("disabled");
def->enum_values.push_back("external_bridge_only");
def->enum_values.push_back("internal_bridge_only");
def->enum_values.push_back("apply_to_all");
def->enum_labels.push_back(L("Disabled"));
def->enum_labels.push_back(L("External bridge only"));
def->enum_labels.push_back(L("Internal bridge only"));
def->enum_labels.push_back(L("Apply to all"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<EnableExtraBridgeLayer>(eblDisabled));

def = this->add("dont_filter_internal_bridges", coEnum);
def->label = L("Filter out small internal bridges (beta)");
def->label = L("Filter out small internal bridges");
def->category = L("Quality");
def->tooltip = L("This option can help reducing pillowing on top surfaces in heavily slanted or curved models.\n\n"
"By default, small internal bridges are filtered out and the internal solid infill is printed directly"
" over the sparse infill. This works well in most cases, speeding up printing without too much compromise"
" on top surface quality. \n\nHowever, in heavily slanted or curved models especially where too low sparse"
" infill density is used, this may result in curling of the unsupported solid infill, causing pillowing.\n\n"
"Disabling this option will print internal bridge layer over slightly unsupported internal"
" solid infill. The options below control the amount of filtering, i.e. the amount of internal bridges "
def->tooltip = L("This option can help reduce pillowing on top surfaces in heavily slanted or curved models.\n\n"
"By default, small internal bridges are filtered out and the internal solid infill is printed directly "
"over the sparse infill. This works well in most cases, speeding up printing without too much compromise "
"on top surface quality. \n\nHowever, in heavily slanted or curved models, especially where too low a sparse "
"infill density is used, this may result in curling of the unsupported solid infill, causing pillowing.\n\n"
"Enabling limited filtering or no filtering will print internal bridge layer over slightly unsupported internal "
"solid infill. The options below control the sensitivity of the filtering, i.e. they control where internal bridges are "
"created.\n\n"
"Filter - enable this option. This is the default behavior and works well in most cases.\n\n"
"Limited filtering - creates internal bridges on heavily slanted surfaces, while avoiding creating "
"unnecessary internal bridges. This works well for most difficult models.\n\n"
"No filtering - creates internal bridges on every potential internal overhang. This option is useful "
"for heavily slanted top surface models. However, in most cases it creates too many unnecessary bridges.");
"1. Filter - enables this option. This is the default behavior and works well in most cases.\n\n"
"2. Limited filtering - creates internal bridges on heavily slanted surfaces while avoiding unnecessary bridges. "
"This works well for most difficult models.\n\n"
"3. No filtering - creates internal bridges on every potential internal overhang. This option is useful for "
"heavily slanted top surface models; however, in most cases, it creates too many unnecessary bridges.");
def->enum_keys_map = &ConfigOptionEnum<InternalBridgeFilter>::get_enum_values();
def->enum_values.push_back("disabled");
def->enum_values.push_back("limited");
Expand Down
8 changes: 8 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ enum InternalBridgeFilter {
ibfDisabled, ibfLimited, ibfNofilter
};

//Orca
enum EnableExtraBridgeLayer {
eblDisabled, eblExternalBridgeOnly, eblInternalBridgeOnly, eblApplyToAll
};

//Orca
enum GapFillTarget {
gftEverywhere, gftTopBottom, gftNowhere
Expand Down Expand Up @@ -827,6 +832,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, thick_bridges))
((ConfigOptionBool, thick_internal_bridges))
((ConfigOptionEnum<InternalBridgeFilter>, dont_filter_internal_bridges))
// Orca
((ConfigOptionEnum<EnableExtraBridgeLayer>, enable_extra_bridge_layer))
((ConfigOptionPercent, internal_bridge_density))
// Overhang angle threshold.
((ConfigOptionInt, support_threshold_angle))
((ConfigOptionFloatOrPercent, support_threshold_overlap))
Expand Down
Loading

0 comments on commit b4a7721

Please sign in to comment.