diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 9a3fe368d3..105bea2dff 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -65,6 +65,8 @@ public: void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces); void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered); double infill_area_threshold() const; + // True if infill voids (computed from infill_density) are larger than bridge_infill_threshold. + bool needs_bridge_over_infill() const; // Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer. void trim_surfaces(const Polygons &trimming_polygons); // Single elephant foot compensation step, used by the elephant foor compensation at the 1st layer. diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index 2db3abf125..6816cb91eb 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -405,6 +405,17 @@ double LayerRegion::infill_area_threshold() const return ss*ss; } +bool LayerRegion::needs_bridge_over_infill() const +{ + auto region_config = region()->config(); + if (region_config.fill_density <= 0) + return true; + const double infill_extrusion_width = flow(frInfill).width; + // Compute the unsupported area assuming a grid, which is pragmatically good enough for all infill types. + const double bridging_area = pow(2.0 * 100.0 * infill_extrusion_width / region_config.fill_density - infill_extrusion_width, 2); + return bridging_area > region_config.bridge_infill_threshold; +} + void LayerRegion::trim_surfaces(const Polygons &trimming_polygons) { #ifndef NDEBUG diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index b7e966c9e7..a49f52dca5 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -410,7 +410,7 @@ const std::vector& Preset::print_options() "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", - "max_print_speed", "max_volumetric_speed", "avoid_crossing_perimeters_max_detour", + "max_print_speed", "max_volumetric_speed", "bridge_infill_threshold", "avoid_crossing_perimeters_max_detour", "fuzzy_skin_perimeter_mode", /* "fuzzy_skin_shape", */ "fuzzy_skin_thickness", "fuzzy_skin_point_dist", #ifdef HAS_PRESSURE_EQUALIZER "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b96768904d..7b885116b0 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -74,6 +74,7 @@ bool Print::invalidate_state_by_config_options(const std::vectormode = comAdvanced; def->set_default_value(new ConfigOptionFloat(1)); + def = this->add("bridge_infill_threshold", coFloat); + def->label = L("Bridge infill threshold"); + def->tooltip = L("Forces bridge settings for the layer above infill where voids are larger than the specified area. " + "The infill void area is computed from the infill density and infill extrusion width. " + "Set to zero to force bridge settings for any layer above non-solid infill."); + def->sidetext = L("mm²"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(25.)); + def = this->add("bridge_speed", coFloat); def->label = L("Bridges"); def->category = L("Speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5189baab2d..6c931ac9c1 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -602,6 +602,7 @@ public: ConfigOptionFloat bottom_solid_min_thickness; ConfigOptionFloat bridge_flow_ratio; ConfigOptionFloat bridge_speed; + ConfigOptionFloat bridge_infill_threshold; ConfigOptionBool ensure_vertical_shell_thickness; ConfigOptionEnum top_fill_pattern; ConfigOptionEnum bottom_fill_pattern; @@ -654,6 +655,7 @@ protected: OPT_PTR(bottom_solid_layers); OPT_PTR(bottom_solid_min_thickness); OPT_PTR(bridge_flow_ratio); + OPT_PTR(bridge_infill_threshold); OPT_PTR(bridge_speed); OPT_PTR(ensure_vertical_shell_thickness); OPT_PTR(top_fill_pattern); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 233f693e3c..1d431400e4 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1472,9 +1472,16 @@ void PrintObject::bridge_over_infill() // iterate through regions and collect internal surfaces Polygons lower_internal; - for (LayerRegion *lower_layerm : lower_layer->m_regions) - lower_layerm->fill_surfaces.filter_by_type(stInternal, &lower_internal); - + for (LayerRegion* lower_layerm : lower_layer->m_regions) { + auto surfaces = lower_layerm->fill_surfaces.surfaces; + for (Surfaces::iterator surface = surfaces.begin(); surface != surfaces.end(); ++surface) { + if (surface->surface_type == stInternal && layerm->needs_bridge_over_infill()) { + Polygons pp = surface->expolygon; + lower_internal.insert(lower_internal.end(), pp.begin(), pp.end()); + } + } + } + // intersect such lower internal surfaces with the candidate solid surfaces to_bridge_pp = intersection(to_bridge_pp, lower_internal); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6f371d1752..4ed25d3fc3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1473,6 +1473,7 @@ void TabPrint::build() optgroup->append_single_option_line("fill_angle", category_path + "fill-angle"); optgroup->append_single_option_line("solid_infill_below_area", category_path + "solid-infill-threshold-area"); optgroup->append_single_option_line("bridge_angle"); + optgroup->append_single_option_line("bridge_infill_threshold"); optgroup->append_single_option_line("only_retract_when_crossing_perimeters"); optgroup->append_single_option_line("infill_first");