diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 9b0a46869d..18b15d4073 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -185,7 +185,7 @@ std::vector group_fills(const Layer &layer) params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern); params.flow = params.bridge ? //BBS: always enable thick bridge for internal bridge - layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || object_config.thick_bridges) : + layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || object_config.thick_bridges, surface.is_external() ? region_config.bridge_density.get_abs_value(1.0) : 1.0f) : layerm.flow(extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness); // Calculate flow spacing for infill pattern generation. diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp index 64c0532dda..7ead899a19 100644 --- a/src/libslic3r/Flow.hpp +++ b/src/libslic3r/Flow.hpp @@ -65,6 +65,7 @@ public: float height() const { return m_height; } // Spacing between the extrusion centerlines. float spacing() const { return m_spacing; } + void set_spacing(float spacing) { m_spacing = spacing; } coord_t scaled_spacing() const { return coord_t(scale_(m_spacing)); } // Nozzle diameter. float nozzle_diameter() const { return m_nozzle_diameter; } diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 3440e404ab..67a200f738 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -68,7 +68,7 @@ public: Flow flow(FlowRole role) const; Flow flow(FlowRole role, double layer_height) const; - Flow bridging_flow(FlowRole role, bool thick_bridge = false) const; + Flow bridging_flow(FlowRole role, bool thick_bridge = false , float bridge_density = 1.0f) const; void slices_to_fill_surfaces_clipped(); void prepare_fill_surfaces(); diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index a02d3e42c1..e33a33dd2b 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -12,6 +12,7 @@ #include #include +#include namespace Slic3r { @@ -25,22 +26,27 @@ Flow LayerRegion::flow(FlowRole role, double layer_height) const return m_region->flow(*m_layer->object(), role, layer_height, m_layer->id() == 0); } -Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge) const +Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge, float bridge_density) const { const PrintRegion ®ion = this->region(); const PrintRegionConfig ®ion_config = region.config(); const PrintObject &print_object = *this->layer()->object(); + Flow bridge_flow; + auto nozzle_diameter = float(print_object.print()->config().nozzle_diameter.get_at(region.extruder(role) - 1)); if (thick_bridge) { // The old Slic3r way (different from all other slicers): Use rounded extrusions. // Get the configured nozzle_diameter for the extruder associated to the flow role requested. // Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right. - auto nozzle_diameter = float(print_object.print()->config().nozzle_diameter.get_at(region.extruder(role) - 1)); // Applies default bridge spacing. - return Flow::bridging_flow(float(sqrt(region_config.bridge_flow)) * nozzle_diameter, nozzle_diameter); + bridge_flow = Flow::bridging_flow(float(sqrt(region_config.bridge_flow)) * nozzle_diameter, nozzle_diameter); } else { // The same way as other slicers: Use normal extrusions. Apply bridge_flow while maintaining the original spacing. - return this->flow(role).with_flow_ratio(region_config.bridge_flow); + bridge_flow = this->flow(role).with_flow_ratio(region_config.bridge_flow); } + bridge_density = boost::algorithm::clamp(bridge_density, 0.1f, 1.0f); + bridge_flow.set_spacing(bridge_flow.spacing() + bridge_flow.width() * ((1.0f / bridge_density) - 1.0f)); + return bridge_flow; + } // Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces. @@ -230,7 +236,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly // Grown by 3mm. //BBS: eliminate too narrow area to avoid generating bridge on top layer when wall loop is 1 //Polygons polys = offset(bridges[i].expolygon, bridge_margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS); - Polygons polys = offset2({ bridges[i].expolygon }, -scale_(nozzle_diameter * 0.1), bridge_margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS); + Polygons polys = offset2({ bridges[i].expolygon }, -scale_(nozzle_diameter * 0.1), bridge_margin + scale_((1.0 / this->region().config().bridge_density.get_abs_value(1.0) - 1.0)*nozzle_diameter/2.0), EXTERNAL_SURFACES_OFFSET_PARAMETERS); if (idx_island == -1) { BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!"; } else { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 48a721ed91..3a5b7d5dc3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -709,7 +709,7 @@ static std::vector s_Preset_print_options { "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", - "infill_direction", "bridge_angle", + "infill_direction", "minimum_sparse_infill_area", "reduce_infill_retraction", "ironing_type", "ironing_flow", "ironing_speed", "ironing_spacing", "max_travel_detour_distance", @@ -752,7 +752,7 @@ static std::vector s_Preset_print_options { "small_perimeter_speed", "small_perimeter_threshold","bridge_angle", "filter_out_gap_fill", "post_process", "travel_acceleration","inner_wall_acceleration", "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" + "print_flow_ratio","seam_gap","role_based_wipe_speed","wipe_speed","accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "bridge_density" }; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 26c50ffb46..f8f4c4b5b8 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -677,6 +677,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.)); + def = this->add("bridge_density", coPercent); + def->label = L("Bridge density"); + def->category = L("Strength"); + def->tooltip = L("Density of external bridges. 100% means solid bridge. Default is 100%."); + def->sidetext = L("%"); + def->min = 10; + def->max = 100; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionPercent(100)); + def = this->add("bridge_flow", coFloat); def->label = L("Bridge flow"); def->category = L("Quality"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index abc521f2c3..db18c56674 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -701,6 +701,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, bridge_angle)) ((ConfigOptionFloat, bridge_flow)) ((ConfigOptionFloat, bridge_speed)) + ((ConfigOptionPercent, bridge_density)) ((ConfigOptionBool, ensure_vertical_shell_thickness)) ((ConfigOptionEnum, top_surface_pattern)) ((ConfigOptionFloat, top_solid_infill_flow_ratio)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 7efb2c5e94..bcbb638aa6 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -828,7 +828,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "detect_thin_wall") { steps.emplace_back(posPerimeters); steps.emplace_back(posSupportMaterial); - } else if (opt_key == "bridge_flow") { + } else if (opt_key == "bridge_flow" || opt_key == "bridge_density") { if (m_config.support_top_z_distance > 0.) { // Only invalidate due to bridging if bridging is enabled. // If later "support_top_z_distance" is modified, the complete PrintObject is invalidated anyway. diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index d415e91092..9dbbcafe3e 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -90,7 +90,7 @@ static constexpr bool g_config_remove_small_overhangs = true; static constexpr float g_config_tree_support_collision_resolution = 0.2; // Write slices as SVG images into out directory during the 2D processing of the slices. -// #define SLIC3R_DEBUG_SLICE_PROCESSING +//#define SLIC3R_DEBUG_SLICE_PROCESSING namespace Slic3r { diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 96b1c7480b..5aaefa7076 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -90,7 +90,7 @@ std::map> SettingsFactory::OBJECT_C std::map> SettingsFactory::PART_CATEGORY_SETTINGS= { - { L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11} + { L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11},{"bridge_density", "", 1} }}, { L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1}, {"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1}, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 0eff871c40..bfc3d20751 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1868,9 +1868,10 @@ void TabPrint::build() optgroup->append_single_option_line("wall_infill_order"); optgroup->append_single_option_line("print_flow_ratio"); optgroup->append_single_option_line("bridge_flow"); + optgroup->append_single_option_line("bridge_density"); + optgroup->append_single_option_line("thick_bridges"); optgroup->append_single_option_line("top_solid_infill_flow_ratio"); optgroup->append_single_option_line("bottom_solid_infill_flow_ratio"); - optgroup->append_single_option_line("thick_bridges"); optgroup->append_single_option_line("only_one_wall_top"); optgroup->append_single_option_line("only_one_wall_first_layer"); optgroup->append_single_option_line("detect_overhang_wall");