From fc7ab914a1963261413d619ea4f385126062902c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Thu, 31 Oct 2024 14:43:47 +0100 Subject: [PATCH 1/2] Create method for infill above bridges identification --- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/ExtrusionRole.hpp | 2 + src/libslic3r/Fill/Fill.cpp | 27 +++++-- src/libslic3r/GCode.cpp | 2 + src/libslic3r/InfillAboveBridges.cpp | 36 +++++++++ src/libslic3r/InfillAboveBridges.hpp | 16 ++++ src/libslic3r/PrintObject.cpp | 14 ++++ src/libslic3r/Surface.cpp | 3 + src/libslic3r/Surface.hpp | 9 ++- tests/fff_print/CMakeLists.txt | 1 + tests/fff_print/test_infill_above_bridges.cpp | 81 +++++++++++++++++++ 11 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 src/libslic3r/InfillAboveBridges.cpp create mode 100644 src/libslic3r/InfillAboveBridges.hpp create mode 100644 tests/fff_print/test_infill_above_bridges.cpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 57d42e6409..3d79437076 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -245,6 +245,8 @@ set(SLIC3R_SOURCES Geometry/VoronoiUtils.hpp Geometry/VoronoiUtils.cpp Geometry/VoronoiVisualUtils.hpp + InfillAboveBridges.hpp + InfillAboveBridges.cpp JumpPointSearch.cpp JumpPointSearch.hpp KDTreeIndirect.hpp diff --git a/src/libslic3r/ExtrusionRole.hpp b/src/libslic3r/ExtrusionRole.hpp index 844c485f10..5d6b9e0cdc 100644 --- a/src/libslic3r/ExtrusionRole.hpp +++ b/src/libslic3r/ExtrusionRole.hpp @@ -31,6 +31,7 @@ enum class ExtrusionRoleModifier : uint16_t { Solid, Ironing, Bridge, + OverBridge, // 3) Special types // Indicator that the extrusion role was mixed from multiple differing extrusion roles, // for example from Support and SupportInterface. @@ -62,6 +63,7 @@ struct ExtrusionRole : public ExtrusionRoleModifiers static constexpr const ExtrusionRoleModifiers SolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid }; // Top solid infill (visible). //FIXME why there is no bottom solid infill type? + static constexpr const ExtrusionRoleModifiers InfillOverBridge{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::OverBridge }; static constexpr const ExtrusionRoleModifiers TopSolidInfill{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::External }; // Ironing infill at the top surfaces. static constexpr const ExtrusionRoleModifiers Ironing{ ExtrusionRoleModifier::Infill | ExtrusionRoleModifier::Solid | ExtrusionRoleModifier::Ironing | ExtrusionRoleModifier::External }; diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index b49ee57a0b..7a0ffe39bc 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -183,15 +183,24 @@ std::vector group_fills(const Layer &layer) } else if (params.density <= 0) continue; - params.extrusion_role = - is_bridge ? - ExtrusionRole::BridgeInfill : - (surface.is_solid() ? - (surface.is_top() ? ExtrusionRole::TopSolidInfill : ExtrusionRole::SolidInfill) : - ExtrusionRole::InternalInfill); + if (is_bridge) { + params.extrusion_role = ExtrusionRole::BridgeInfill; + } else { + if (surface.is_solid()) { + if (surface.is_top()) { + params.extrusion_role = ExtrusionRole::TopSolidInfill; + } else if (surface.surface_type == stSolidOverBridge) { + params.extrusion_role = ExtrusionRole::InfillOverBridge; + } else { + params.extrusion_role = ExtrusionRole::SolidInfill; + } + } else { + params.extrusion_role = ExtrusionRole::InternalInfill; + } + } params.bridge_angle = float(surface.bridge_angle); params.angle = float(Geometry::deg2rad(region_config.fill_angle.value)); - + // Calculate the actual flow we'll be using for this infill. params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern); params.flow = params.bridge ? @@ -342,7 +351,9 @@ std::vector group_fills(const Layer &layer) // Use ipEnsuring pattern for all internal Solids. { for (size_t surface_fill_id = 0; surface_fill_id < surface_fills.size(); ++surface_fill_id) - if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) { + if (SurfaceFill &fill = surface_fills[surface_fill_id]; + fill.surface.surface_type == stInternalSolid + || fill.surface.surface_type == stSolidOverBridge) { fill.params.pattern = ipEnsuring; } } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b427ea82f2..7f576412db 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3387,6 +3387,8 @@ std::string GCodeGenerator::_extrude( speed = m_config.get_abs_value("infill_speed"); } else if (path_attr.role == ExtrusionRole::SolidInfill) { speed = m_config.get_abs_value("solid_infill_speed"); + } else if (path_attr.role == ExtrusionRole::InfillOverBridge) { + speed = 10; } else if (path_attr.role == ExtrusionRole::TopSolidInfill) { speed = m_config.get_abs_value("top_solid_infill_speed"); } else if (path_attr.role == ExtrusionRole::Ironing) { diff --git a/src/libslic3r/InfillAboveBridges.cpp b/src/libslic3r/InfillAboveBridges.cpp new file mode 100644 index 0000000000..dd3206215f --- /dev/null +++ b/src/libslic3r/InfillAboveBridges.cpp @@ -0,0 +1,36 @@ +#include +#include "libslic3r/InfillAboveBridges.hpp" +#include "libslic3r/ClipperUtils.hpp" + +namespace Slic3r::PrepareInfill { + void mark_as_infill_above_bridge(const ExPolygons &marker, const SurfaceRefsByRegion &layer) { + for (const SurfaceCollectionRef ®ion : layer) { + const ExPolygons intersection{intersection_ex(region.get().filter_by_type(stInternalSolid), marker, ApplySafetyOffset::No)}; + if (intersection.empty()) { + continue; + } + const ExPolygons clipped{diff_ex(region.get().filter_by_type(stInternalSolid), marker, ApplySafetyOffset::Yes)}; + region.get().remove_type(stInternalSolid); + region.get().append(clipped, stInternalSolid); + region.get().append(intersection, stSolidOverBridge); + } + } + + void separate_infill_above_bridges(const SurfaceRefs &surfaces) { + if (surfaces.empty()) { + return; + } + + const SurfaceRefsByRegion *previous_layer{&surfaces.front()}; + for (const SurfaceRefsByRegion &layer : tcb::span{surfaces}.subspan(1)) { + ExPolygons bridges; + for (const SurfaceCollectionRef ®ion : *previous_layer) { + for (const Surface *bridge : region.get().filter_by_type(stBottomBridge)) { + bridges.push_back(bridge->expolygon); + } + } + mark_as_infill_above_bridge(bridges, layer); + previous_layer = &layer; + } + } +} diff --git a/src/libslic3r/InfillAboveBridges.hpp b/src/libslic3r/InfillAboveBridges.hpp new file mode 100644 index 0000000000..2e2fc2c564 --- /dev/null +++ b/src/libslic3r/InfillAboveBridges.hpp @@ -0,0 +1,16 @@ +#ifndef slic3r_InfillAboveBridges_hpp_ +#define slic3r_InfillAboveBridges_hpp_ + +#include +#include +#include "libslic3r/SurfaceCollection.hpp" + +namespace Slic3r::PrepareInfill { + using SurfaceCollectionRef = std::reference_wrapper; + using SurfaceRefsByRegion = std::vector; + using SurfaceRefs = std::vector; + + void separate_infill_above_bridges(const SurfaceRefs &surfaces); +} + +#endif // slic3r_InfillAboveBridges_hpp_ diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index f9c5727b44..9f8d404763 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -64,6 +64,7 @@ #include "libslic3r/TriangleSelector.hpp" #include "tcbspan/span.hpp" #include "libslic3r/Point.hpp" +#include "libslic3r/InfillAboveBridges.hpp" using namespace std::literals; @@ -412,6 +413,19 @@ void PrintObject::prepare_infill() } // for each layer #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + + PrepareInfill::SurfaceRefs surfaces; + for (const Layer *layer : m_layers) { + surfaces.emplace_back(); + for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) { + LayerRegion *layerm = layer->m_regions[region_id]; + if (!layerm->fill_surfaces().empty()) { + surfaces.back().push_back(std::ref(layerm->m_fill_surfaces)); + } + } + } + PrepareInfill::separate_infill_above_bridges(surfaces); + this->set_done(posPrepareInfill); } diff --git a/src/libslic3r/Surface.cpp b/src/libslic3r/Surface.cpp index fbecc33118..65dda46ae0 100644 --- a/src/libslic3r/Surface.cpp +++ b/src/libslic3r/Surface.cpp @@ -53,6 +53,7 @@ const char* surface_type_to_color_name(const SurfaceType surface_type) case stInternalSolid: return "rgb(255,0,255)"; // magenta case stInternalBridge: return "rgb(0,255,255)"; case stInternalVoid: return "rgb(128,128,128)"; + case stSolidOverBridge: return "rgb(255,128,0)"; // orange case stPerimeter: return "rgb(128,0,0)"; // maroon default: return "rgb(64,64,64)"; }; @@ -89,6 +90,8 @@ void export_surface_type_legend_to_svg(SVG &svg, const Point &pos) svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge)); pos_x += step_x; svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stInternalVoid)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "over bridge" , surface_type_to_color_name(stSolidOverBridge)); } bool export_to_svg(const char *path, const Surfaces &surfaces, const float transparency) diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index 8e7663afa4..557ceb8340 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -44,6 +44,8 @@ enum SurfaceType { stInternalVoid, // Inner/outer perimeters. stPerimeter, + // InternalSolid that is directly above stBottomBridge. + stSolidOverBridge, // Number of SurfaceType enums. stCount, }; @@ -111,7 +113,12 @@ public: bool is_bridge() const { return this->surface_type == stBottomBridge || this->surface_type == stInternalBridge; } bool is_external() const { return this->is_top() || this->is_bottom(); } bool is_internal() const { return ! this->is_external(); } - bool is_solid() const { return this->is_external() || this->surface_type == stInternalSolid || this->surface_type == stInternalBridge; } + bool is_solid() const { + return this->is_external() + || this->surface_type == stInternalSolid + || this->surface_type == stSolidOverBridge + || this->surface_type == stInternalBridge; + } }; typedef std::vector Surfaces; diff --git a/tests/fff_print/CMakeLists.txt b/tests/fff_print/CMakeLists.txt index ce04286a64..2fc1573c2b 100644 --- a/tests/fff_print/CMakeLists.txt +++ b/tests/fff_print/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(${_TEST_NAME}_tests test_gaps.cpp test_gcode.cpp test_gcode_travels.cpp + test_infill_above_bridges.cpp test_seam_perimeters.cpp test_seam_shells.cpp test_seam_geometry.cpp diff --git a/tests/fff_print/test_infill_above_bridges.cpp b/tests/fff_print/test_infill_above_bridges.cpp new file mode 100644 index 0000000000..c55c230125 --- /dev/null +++ b/tests/fff_print/test_infill_above_bridges.cpp @@ -0,0 +1,81 @@ +#include +#include + +using namespace Slic3r; + +const ExPolygon square{ + Point::new_scale(0, 0), + Point::new_scale(10, 0), + Point::new_scale(10, 10), + Point::new_scale(0, 10) +}; + +ExPolygon translate(const ExPolygon &polygon, const Point &offset) { + ExPolygons result{polygon}; + translate(result, offset); + return result.front(); +} + +constexpr bool debug_files{false}; + +void draw_surfaces(const PrepareInfill::SurfaceRefsByRegion &surfaces, std::string_view file_name) { + using PrepareInfill::SurfaceCollectionRef; + + SurfaceCollection to_display; + for (const SurfaceCollectionRef &surface_collection : surfaces) { + to_display.append(surface_collection.get()); + } + to_display.export_to_svg(file_name.data(), false); +} + +TEST_CASE("Separate infill above bridges", "[PrepareInfill]") { + ExPolygons layer_0_region_0_bridge{ + square + }; + ExPolygons layer_0_region_0_internal{ + translate(square, Point::new_scale(10, 0)) + }; + ExPolygons layer_0_region_1_internal{ + translate(square, Point::new_scale(0, 10)) + }; + ExPolygons layer_0_region_1_bridge{ + translate(square, Point::new_scale(10, 10)) + }; + SurfaceCollection layer_0_region_0; + layer_0_region_0.append(layer_0_region_0_bridge, stBottomBridge); + layer_0_region_0.append(layer_0_region_0_internal, stInternal); + SurfaceCollection layer_0_region_1; + layer_0_region_1.append(layer_0_region_1_bridge, stBottomBridge); + layer_0_region_1.append(layer_0_region_1_internal, stInternal); + + PrepareInfill::SurfaceRefsByRegion layer_0{layer_0_region_0, layer_0_region_1}; + + ExPolygons layer_1_region_0_solid{ + translate(square, Point::new_scale(5, 5)) + }; + SurfaceCollection layer_1_region_0; + layer_1_region_0.append(layer_1_region_0_solid, stInternalSolid); + PrepareInfill::SurfaceRefsByRegion layer_1{layer_1_region_0}; + + if constexpr (debug_files) { + draw_surfaces(layer_0, "layer_0.svg"); + } + + PrepareInfill::separate_infill_above_bridges({layer_0, layer_1}); + + if constexpr (debug_files) { + draw_surfaces(layer_1, "layer_1.svg"); + } + + const Surfaces &result{layer_1.front().get().surfaces}; + REQUIRE(result.size() == 4); + const double expected_area{scale_(5.0) * scale_(5.0)}; + CHECK(result[0].expolygon.contour.area() == Approx(expected_area)); + CHECK(result[0].surface_type == stInternalSolid); + CHECK(result[1].expolygon.contour.area() == Approx(expected_area)); + CHECK(result[1].surface_type == stInternalSolid); + CHECK(result[2].expolygon.contour.area() == Approx(expected_area)); + CHECK(result[2].surface_type == stSolidOverBridge); + CHECK(result[3].expolygon.contour.area() == Approx(expected_area)); + CHECK(result[3].surface_type == stSolidOverBridge); +} From 20687bc27a5d2e4ee017baca81e81c04e06cf617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Thu, 31 Oct 2024 17:08:29 +0100 Subject: [PATCH 2/2] Use slowdown above bridges --- src/libslic3r/ExtrusionRole.cpp | 1 + src/libslic3r/GCode.cpp | 11 +++++++++-- src/libslic3r/InfillAboveBridges.cpp | 5 ++++- src/libslic3r/InfillAboveBridges.hpp | 2 +- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 10 ++++++++++ src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/PrintObject.cpp | 17 +++++++++++++++-- src/libslic3r/SupportSpotsGenerator.cpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + tests/fff_print/test_infill_above_bridges.cpp | 2 +- 12 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/ExtrusionRole.cpp b/src/libslic3r/ExtrusionRole.cpp index 09052e0e19..34fb888758 100644 --- a/src/libslic3r/ExtrusionRole.cpp +++ b/src/libslic3r/ExtrusionRole.cpp @@ -23,6 +23,7 @@ GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role) } if (role == ExtrusionRole::InternalInfill) return GCodeExtrusionRole::InternalInfill; if (role == ExtrusionRole::SolidInfill) return GCodeExtrusionRole::SolidInfill; + if (role == ExtrusionRole::InfillOverBridge) return GCodeExtrusionRole::SolidInfill; if (role == ExtrusionRole::TopSolidInfill) return GCodeExtrusionRole::TopSolidInfill; if (role == ExtrusionRole::Ironing) return GCodeExtrusionRole::Ironing; if (role == ExtrusionRole::BridgeInfill) return GCodeExtrusionRole::BridgeInfill; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7f576412db..970320568c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -704,7 +704,8 @@ namespace DoExport { if (region.config().get_abs_value("infill_speed") == 0 || region.config().get_abs_value("solid_infill_speed") == 0 || region.config().get_abs_value("top_solid_infill_speed") == 0 || - region.config().get_abs_value("bridge_speed") == 0) + region.config().get_abs_value("bridge_speed") == 0 || + region.config().get_abs_value("over_bridge_speed") == 0) { // Minimal volumetric flow should not be calculated over ironing extrusions. // Use following lambda instead of the built-it method. @@ -3388,7 +3389,13 @@ std::string GCodeGenerator::_extrude( } else if (path_attr.role == ExtrusionRole::SolidInfill) { speed = m_config.get_abs_value("solid_infill_speed"); } else if (path_attr.role == ExtrusionRole::InfillOverBridge) { - speed = 10; + const double solid_infill_speed = m_config.get_abs_value("solid_infill_speed"); + const double over_bridge_speed{m_config.get_abs_value("over_bridge_speed", solid_infill_speed)}; + if (over_bridge_speed > 0) { + speed = over_bridge_speed; + } else { + speed = solid_infill_speed; + } } else if (path_attr.role == ExtrusionRole::TopSolidInfill) { speed = m_config.get_abs_value("top_solid_infill_speed"); } else if (path_attr.role == ExtrusionRole::Ironing) { diff --git a/src/libslic3r/InfillAboveBridges.cpp b/src/libslic3r/InfillAboveBridges.cpp index dd3206215f..cb9787c66e 100644 --- a/src/libslic3r/InfillAboveBridges.cpp +++ b/src/libslic3r/InfillAboveBridges.cpp @@ -16,7 +16,7 @@ namespace Slic3r::PrepareInfill { } } - void separate_infill_above_bridges(const SurfaceRefs &surfaces) { + void separate_infill_above_bridges(const SurfaceRefs &surfaces, const double expand_offset) { if (surfaces.empty()) { return; } @@ -29,6 +29,9 @@ namespace Slic3r::PrepareInfill { bridges.push_back(bridge->expolygon); } } + if (expand_offset > 0) { + bridges = offset_ex(bridges, scale_(expand_offset)); + } mark_as_infill_above_bridge(bridges, layer); previous_layer = &layer; } diff --git a/src/libslic3r/InfillAboveBridges.hpp b/src/libslic3r/InfillAboveBridges.hpp index 2e2fc2c564..43b2037f90 100644 --- a/src/libslic3r/InfillAboveBridges.hpp +++ b/src/libslic3r/InfillAboveBridges.hpp @@ -10,7 +10,7 @@ namespace Slic3r::PrepareInfill { using SurfaceRefsByRegion = std::vector; using SurfaceRefs = std::vector; - void separate_infill_above_bridges(const SurfaceRefs &surfaces); + void separate_infill_above_bridges(const SurfaceRefs &surfaces, const double expand_offset); } #endif // slic3r_InfillAboveBridges_hpp_ diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index a54ac49bae..557b7767da 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -485,7 +485,7 @@ static std::vector s_Preset_print_options { "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "enable_dynamic_overhang_speeds", "overhang_speed_0", "overhang_speed_1", "overhang_speed_2", "overhang_speed_3", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", - "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", + "bridge_speed", "over_bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", "external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration", "travel_acceleration", "wipe_tower_acceleration", "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 5acc2cf8d3..db517d6f8e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -727,6 +727,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(60)); + def = this->add("over_bridge_speed", coFloatOrPercent); + def->label = L("Over bridges"); + def->category = L("Speed"); + def->tooltip = L("Speed for printing solid infill above bridges. Set to 0 to use solid infill speed. " + "If set as percentage, the speed is calculated over solid infill speed. "); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); + def = this->add("enable_dynamic_overhang_speeds", coBool); def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index a7dfe1a460..8da9046f6a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -693,6 +693,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, bridge_flow_ratio)) ((ConfigOptionFloat, bridge_speed)) ((ConfigOptionEnum, ensure_vertical_shell_thickness)) + ((ConfigOptionFloatOrPercent, over_bridge_speed)) ((ConfigOptionEnum, top_fill_pattern)) ((ConfigOptionEnum, bottom_fill_pattern)) ((ConfigOptionFloatOrPercent, external_perimeter_extrusion_width)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 9f8d404763..58f31e3e10 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -419,12 +419,13 @@ void PrintObject::prepare_infill() surfaces.emplace_back(); for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) { LayerRegion *layerm = layer->m_regions[region_id]; - if (!layerm->fill_surfaces().empty()) { + if (!layerm->fill_surfaces().empty() && layerm->region().config().over_bridge_speed > 0) { surfaces.back().push_back(std::ref(layerm->m_fill_surfaces)); } } } - PrepareInfill::separate_infill_above_bridges(surfaces); + constexpr double infill_over_bridges_expand{1.0}; + PrepareInfill::separate_infill_above_bridges(surfaces, infill_over_bridges_expand); this->set_done(posPrepareInfill); } @@ -847,6 +848,18 @@ bool PrintObject::invalidate_state_by_config_options( steps.emplace_back(posInfill); } else if (opt_key == "fill_pattern") { steps.emplace_back(posPrepareInfill); + } else if (opt_key == "over_bridge_speed") { + const auto *old_speed = old_config.option(opt_key); + const auto *new_speed = new_config.option(opt_key); + if ( + old_speed == nullptr + || new_speed == nullptr + || old_speed->value == 0 + || new_speed->value == 0 + ) { + steps.emplace_back(posPrepareInfill); + } + invalidated |= m_print->invalidate_step(psGCodeExport); } else if (opt_key == "fill_density") { // One likely wants to reslice only when switching between zero infill to simulate boolean difference (subtracting volumes), // normal infill and 100% (solid) infill. diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index f735d77d31..3bd9e0adb4 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -278,6 +278,7 @@ float get_flow_width(const LayerRegion *region, ExtrusionRole role) if (role == ExtrusionRole::GapFill) return region->flow(FlowRole::frInfill).width(); if (role == ExtrusionRole::Perimeter) return region->flow(FlowRole::frPerimeter).width(); if (role == ExtrusionRole::SolidInfill) return region->flow(FlowRole::frSolidInfill).width(); + if (role == ExtrusionRole::InfillOverBridge) return region->flow(FlowRole::frSolidInfill).width(); if (role == ExtrusionRole::InternalInfill) return region->flow(FlowRole::frInfill).width(); if (role == ExtrusionRole::TopSolidInfill) return region->flow(FlowRole::frTopSolidInfill).width(); // default diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index ac6b29a2d5..70c187107c 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -317,7 +317,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field(el, has_solid_infill); for (auto el : { "fill_angle", "bridge_angle", "infill_extrusion_width", - "infill_speed", "bridge_speed" }) + "infill_speed", "bridge_speed", "over_bridge_speed" }) toggle_field(el, have_infill || has_solid_infill); const bool has_ensure_vertical_shell_thickness = config->opt_enum("ensure_vertical_shell_thickness") != EnsureVerticalShellThickness::Disabled; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 2b1d1be57d..d6a890ae4d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1585,6 +1585,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_material_speed"); optgroup->append_single_option_line("support_material_interface_speed"); optgroup->append_single_option_line("bridge_speed"); + optgroup->append_single_option_line("over_bridge_speed"); optgroup->append_single_option_line("gap_fill_speed"); optgroup->append_single_option_line("ironing_speed"); diff --git a/tests/fff_print/test_infill_above_bridges.cpp b/tests/fff_print/test_infill_above_bridges.cpp index c55c230125..dc0d72338c 100644 --- a/tests/fff_print/test_infill_above_bridges.cpp +++ b/tests/fff_print/test_infill_above_bridges.cpp @@ -61,7 +61,7 @@ TEST_CASE("Separate infill above bridges", "[PrepareInfill]") { draw_surfaces(layer_0, "layer_0.svg"); } - PrepareInfill::separate_infill_above_bridges({layer_0, layer_1}); + PrepareInfill::separate_infill_above_bridges({layer_0, layer_1}, 0); if constexpr (debug_files) { draw_surfaces(layer_1, "layer_1.svg");