From 00cc73f65f50a959d36fe3d4267d6086afd47532 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 2 Mar 2023 15:17:05 +0100 Subject: [PATCH 01/10] Raft improvements: 1) Object 1st layer fill direction is locked if printing on raft. 2) Object fill direction is referenced to object layer ignoring the raft layers, thus the fill direction depends no more on number of raft layers. 2) Raft contact perpendicular to object 1st layer fill direction. 3) Raft interface / contact layers are produced with alternating directions. --- src/libslic3r/Fill/Fill.cpp | 12 ++++- src/libslic3r/PrintObject.cpp | 10 ++++ src/libslic3r/SupportMaterial.cpp | 87 +++++++++++++++++-------------- src/libslic3r/SupportMaterial.hpp | 8 +++ 4 files changed, 75 insertions(+), 42 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 082cf93cc..e0e2e0ca8 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -441,11 +441,15 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + size_t first_object_layer_id = this->object()->get_layer(0)->id(); for (SurfaceFill &surface_fill : surface_fills) { // Create the filler object. std::unique_ptr f = std::unique_ptr(Fill::new_from_type(surface_fill.params.pattern)); f->set_bounding_box(bbox); - f->layer_id = this->id(); + // Layer ID is used for orienting the infill in alternating directions. + // Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent + // from raft. + f->layer_id = this->id() - first_object_layer_id; f->z = this->print_z; f->angle = surface_fill.params.angle; f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree; @@ -698,7 +702,11 @@ void Layer::make_ironing() FillRectilinear fill; FillParams fill_params; fill.set_bounding_box(this->object()->bounding_box()); - fill.layer_id = this->id(); + // Layer ID is used for orienting the infill in alternating directions. + // Layer::id() returns layer ID including raft layers, subtract them to make the infill direction independent + // from raft. + //FIXME ironing does not take fill angle into account. Shall it? Does it matter? + fill.layer_id = this->id() - this->object()->get_layer(0)->id(); fill.z = this->print_z; fill.overlap = 0; fill_params.density = 1.; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index efdcb4fc6..65deb8261 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -20,6 +20,7 @@ #include "Fill/FillAdaptive.hpp" #include "Fill/FillLightning.hpp" #include "Format/STL.hpp" +#include "SupportMaterial.hpp" #include "SupportSpotsGenerator.hpp" #include "TriangleSelectorWrapper.hpp" #include "format.hpp" @@ -1129,6 +1130,15 @@ void PrintObject::process_external_surfaces() m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - end"; } + + if (this->has_raft() && ! m_layers.empty()) { + // Adjust bridge direction of 1st object layer over raft to be perpendicular to the raft contact layer direction. + Layer &layer = *m_layers.front(); + assert(layer.id() > 0); + for (LayerRegion *layerm : layer.regions()) + for (Surface &fill : layerm->m_fill_surfaces) + fill.bridge_angle = -1; + } } // void PrintObject::process_external_surfaces() void PrintObject::discover_vertical_shells() diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 6be62c4b3..965a9398f 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -376,8 +376,6 @@ SupportParameters::SupportParameters(const PrintObject &object) } - this->base_angle = Geometry::deg2rad(float(object_config.support_material_angle.value)); - this->interface_angle = Geometry::deg2rad(float(object_config.support_material_angle.value + 90.)); double interface_spacing = object_config.support_material_interface_spacing.value + this->support_material_interface_flow.spacing(); this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / interface_spacing); double raft_interface_spacing = object_config.support_material_interface_spacing.value + this->raft_interface_flow.spacing(); @@ -401,6 +399,39 @@ SupportParameters::SupportParameters(const PrintObject &object) object_config.support_material_interface_pattern == smipConcentric ? ipConcentric : (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase); + + this->base_angle = Geometry::deg2rad(float(object_config.support_material_angle.value)); + this->interface_angle = Geometry::deg2rad(float(object_config.support_material_angle.value + 90.)); + this->raft_angle_1st_layer = 0.f; + this->raft_angle_base = 0.f; + this->raft_angle_interface = 0.f; + if (slicing_params.base_raft_layers > 1) { + assert(slicing_params.raft_layers() >= 4); + // There are all raft layer types (1st layer, base, interface & contact layers) available. + this->raft_angle_1st_layer = this->interface_angle; + this->raft_angle_base = this->base_angle; + this->raft_angle_interface = this->interface_angle; + if ((slicing_params.interface_raft_layers & 1) == 0) + // Allign the 1st raft interface layer so that the object 1st layer is hatched perpendicularly to the raft contact interface. + this->raft_angle_interface += float(0.5 * M_PI); + } else if (slicing_params.base_raft_layers == 1 || slicing_params.interface_raft_layers > 1) { + assert(slicing_params.raft_layers() == 2 || slicing_params.raft_layers() == 3); + // 1st layer, interface & contact layers available. + this->raft_angle_1st_layer = this->base_angle; + this->raft_angle_interface = this->interface_angle + 0.5 * M_PI; + } else if (slicing_params.interface_raft_layers == 1) { + // Only the contact raft layer is non-empty, which will be printed as the 1st layer. + assert(slicing_params.base_raft_layers == 0); + assert(slicing_params.interface_raft_layers == 1); + assert(slicing_params.raft_layers() == 1); + this->raft_angle_1st_layer = float(0.5 * M_PI); + this->raft_angle_interface = this->raft_angle_1st_layer; + } else { + // No raft. + assert(slicing_params.base_raft_layers == 0); + assert(slicing_params.interface_raft_layers == 0); + assert(slicing_params.raft_layers() == 0); + } } PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) : @@ -4207,38 +4238,12 @@ void generate_support_toolpaths( // const coordf_t link_max_length_factor = 3.; const coordf_t link_max_length_factor = 0.; - float raft_angle_1st_layer = 0.f; - float raft_angle_base = 0.f; - float raft_angle_interface = 0.f; - if (slicing_params.base_raft_layers > 1) { - // There are all raft layer types (1st layer, base, interface & contact layers) available. - raft_angle_1st_layer = support_params.interface_angle; - raft_angle_base = support_params.base_angle; - raft_angle_interface = support_params.interface_angle; - } else if (slicing_params.base_raft_layers == 1 || slicing_params.interface_raft_layers > 1) { - // 1st layer, interface & contact layers available. - raft_angle_1st_layer = support_params.base_angle; - if (config.support_material || config.support_material_enforce_layers > 0) - // Print 1st layer at 45 degrees from both the interface and base angles as both can land on the 1st layer. - raft_angle_1st_layer += 0.7854f; - raft_angle_interface = support_params.interface_angle; - } else if (slicing_params.interface_raft_layers == 1) { - // Only the contact raft layer is non-empty, which will be printed as the 1st layer. - assert(slicing_params.base_raft_layers == 0); - assert(slicing_params.interface_raft_layers == 1); - assert(slicing_params.raft_layers() == 1 && raft_layers.size() == 0); - } else { - // No raft. - assert(slicing_params.base_raft_layers == 0); - assert(slicing_params.interface_raft_layers == 0); - assert(slicing_params.raft_layers() == 0 && raft_layers.size() == 0); - } - // Insert the raft base layers. auto n_raft_layers = std::min(support_layers.size(), std::max(0, int(slicing_params.raft_layers()) - 1)); + tbb::parallel_for(tbb::blocked_range(0, n_raft_layers), [&support_layers, &raft_layers, &intermediate_layers, &config, &support_params, &slicing_params, - &bbox_object, raft_angle_1st_layer, raft_angle_base, raft_angle_interface, link_max_length_factor] + &bbox_object, link_max_length_factor] (const tbb::blocked_range& range) { for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) { @@ -4270,7 +4275,7 @@ void generate_support_toolpaths( assert(!raft_layer.bridging); if (! to_infill_polygons.empty()) { Fill *filler = filler_support.get(); - filler->angle = raft_angle_base; + filler->angle = support_params.raft_angle_base; filler->spacing = support_params.support_material_flow.spacing(); filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_params.support_density)); fill_expolygons_with_sheath_generate_paths( @@ -4293,11 +4298,11 @@ void generate_support_toolpaths( float density = 0.f; if (support_layer_id == 0) { // Base flange. - filler->angle = raft_angle_1st_layer; + filler->angle = support_params.raft_angle_1st_layer; filler->spacing = support_params.first_layer_flow.spacing(); density = float(config.raft_first_layer_density.value * 0.01); } else if (support_layer_id >= slicing_params.base_raft_layers) { - filler->angle = raft_angle_interface; + filler->angle = support_params.raft_interface_angle(support_layer.interface_id()); // We don't use $base_flow->spacing because we need a constant spacing // value that guarantees that all layers are correctly aligned. filler->spacing = support_params.support_material_flow.spacing(); @@ -4345,7 +4350,7 @@ void generate_support_toolpaths( std::vector layer_caches(support_layers.size()); tbb::parallel_for(tbb::blocked_range(n_raft_layers, support_layers.size()), - [&config, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, + [&config, &slicing_params, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, &bbox_object, &angles, n_raft_layers, link_max_length_factor] (const tbb::blocked_range& range) { // Indices of the 1st layer in their respective container at the support layer height. @@ -4381,9 +4386,8 @@ void generate_support_toolpaths( { SupportLayer &support_layer = *support_layers[support_layer_id]; LayerCache &layer_cache = layer_caches[support_layer_id]; - float interface_angle_delta = config.support_material_style.value != smsGrid ? - (support_layer.interface_id() & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.) : - 0; + const float support_interface_angle = config.support_material_style.value == smsGrid ? + support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id()); // Find polygons with the same print_z. SupportGeneratorLayerExtruded &bottom_contact_layer = layer_cache.bottom_contact_layer; @@ -4412,7 +4416,8 @@ void generate_support_toolpaths( if (idx_layer_intermediate < intermediate_layers.size() && intermediate_layers[idx_layer_intermediate]->print_z < support_layer.print_z + EPSILON) base_layer.layer = intermediate_layers[idx_layer_intermediate]; - bool raft_layer = support_layer_id == n_raft_layers; + // This layer is a raft contact layer. Any contact polygons at this layer are raft contacts. + bool raft_layer = slicing_params.interface_raft_layers && top_contact_layer.layer && is_approx(top_contact_layer.layer->print_z, slicing_params.raft_contact_top_z); if (config.support_material_interface_layers == 0) { // If no top interface layers were requested, we treat the contact layer exactly as a generic base layer. // Don't merge the raft contact layer though. @@ -4470,7 +4475,9 @@ void generate_support_toolpaths( // If zero interface layers are configured, use the same angle as for the base layers. angles[support_layer_id % angles.size()] : // Use interface angle for the interface layers. - support_params.interface_angle + interface_angle_delta; + raft_contact ? + support_params.raft_interface_angle(support_layer.interface_id()) : + support_interface_angle; double density = raft_contact ? support_params.raft_interface_density : interface_as_base ? support_params.support_density : support_params.interface_density; filler->spacing = raft_contact ? support_params.raft_interface_flow.spacing() : interface_as_base ? support_params.support_material_flow.spacing() : support_params.support_material_interface_flow.spacing(); @@ -4499,7 +4506,7 @@ void generate_support_toolpaths( // the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b) assert(! base_interface_layer.layer->bridging); Flow interface_flow = support_params.support_material_flow.with_height(float(base_interface_layer.layer->height)); - filler->angle = support_params.interface_angle + interface_angle_delta; + filler->angle = support_interface_angle; filler->spacing = support_params.support_material_interface_flow.spacing(); filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_params.interface_density)); fill_expolygons_generate_paths( diff --git a/src/libslic3r/SupportMaterial.hpp b/src/libslic3r/SupportMaterial.hpp index eda70517f..2bd321144 100644 --- a/src/libslic3r/SupportMaterial.hpp +++ b/src/libslic3r/SupportMaterial.hpp @@ -161,6 +161,14 @@ struct SupportParameters { InfillPattern contact_fill_pattern; // Shall the sparse (base) layers be printed with a single perimeter line (sheath) for robustness? bool with_sheath; + + float raft_angle_1st_layer; + float raft_angle_base; + float raft_angle_interface; + + // Produce a raft interface angle for a given SupportLayer::interface_id() + float raft_interface_angle(size_t interface_id) const + { return this->raft_angle_interface + ((interface_id & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)); } }; // Remove bridges from support contact areas. From a496444b7e188dcdd4b91a2c54f28c9ec30a150e Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 22 Feb 2023 14:57:22 +0100 Subject: [PATCH 02/10] make fixed overlap levels for dynamic overhang speed --- src/libslic3r/GCode.cpp | 10 +++- src/libslic3r/GCode/ExtrusionProcessor.hpp | 31 +++++----- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 69 +++++++++++++++------- src/libslic3r/PrintConfig.hpp | 7 ++- src/libslic3r/PrintObject.cpp | 7 ++- src/slic3r/GUI/ConfigManipulation.cpp | 7 +-- src/slic3r/GUI/Search.cpp | 4 -- src/slic3r/GUI/Tab.cpp | 16 ++--- 9 files changed, 89 insertions(+), 64 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7088a158d..34a252abd 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1,3 +1,4 @@ +#include "Config.hpp" #include "libslic3r.h" #include "GCode/ExtrusionProcessor.hpp" #include "I18N.hpp" @@ -2870,12 +2871,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de bool variable_speed = false; std::vector new_points{}; if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && path.role().is_perimeter()) { + std::vector> overhangs_with_speeds{ + {0, m_config.overhang_speed_0}, {20, m_config.overhang_speed_1}, {40, m_config.overhang_speed_2}, + {60, m_config.overhang_speed_3}, {80, m_config.overhang_speed_4}, + }; double external_perim_reference_speed = std::min(m_config.get_abs_value("external_perimeter_speed"), std::min(EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm, m_config.max_volumetric_speed.value / path.mm3_per_mm)); - new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_overlap_levels, - m_config.dynamic_overhang_speeds, - external_perim_reference_speed, speed); + new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhangs_with_speeds, external_perim_reference_speed, + speed); variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; }); } diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 7ce7a77f6..066f1acd1 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -257,26 +257,25 @@ public: next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf(layer->lslices)}; } - std::vector estimate_extrusion_quality(const ExtrusionPath &path, - const ConfigOptionPercents &overlaps, - const ConfigOptionFloatsOrPercents &speeds, - float ext_perimeter_speed, - float original_speed) + std::vector estimate_extrusion_quality(const ExtrusionPath &path, + const std::vector> overhangs_w_speeds, + float ext_perimeter_speed, + float original_speed) { - size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size()); - float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; + float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; std::vector> speed_sections; - for (size_t i = 0; i < speed_sections_count; i++) { - float distance = path.width * (1.0 - (overlaps.get_at(i) / 100.0)); - float speed = speeds.get_at(i).percent ? (speed_base * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value; + for (size_t i = 0; i < overhangs_w_speeds.size(); i++) { + float distance = path.width * (1.0 - (overhangs_w_speeds[i].first / 100.0)); + float speed = overhangs_w_speeds[i].second.percent ? (speed_base * overhangs_w_speeds[i].second.value / 100.0) : + overhangs_w_speeds[i].second.value; speed_sections.push_back({distance, speed}); } - std::sort(speed_sections.begin(), speed_sections.end(), - [](const std::pair &a, const std::pair &b) { - if (a.first == b.first) { - return a.second > b.second; - } - return a.first < b.first; }); + std::sort(speed_sections.begin(), speed_sections.end(), [](const std::pair &a, const std::pair &b) { + if (a.first == b.first) { + return a.second > b.second; + } + return a.first < b.first; + }); std::pair last_section{INFINITY, 0}; for (auto §ion : speed_sections) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 55a643ea1..60c415cf6 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -440,7 +440,7 @@ static std::vector s_Preset_print_options { "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_dist", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", - "enable_dynamic_overhang_speeds", "dynamic_overhang_speeds", "overhang_overlap_levels", + "enable_dynamic_overhang_speeds", "overhang_speed_0", "overhang_speed_1", "overhang_speed_2", "overhang_speed_3", "overhang_speed_4", "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", "external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 76fddebc4..01dbfee16 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -534,36 +534,63 @@ void PrintConfigDef::init_fff_params() def = this->add("enable_dynamic_overhang_speeds", coBool); def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); - def->tooltip = L("This setting enables dynamic speed control on overhangs."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); - - def = this->add("overhang_overlap_levels", coPercents); - def->full_label = L("Overhang overlap levels"); - def->category = L("Speed"); - def->tooltip = L("Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " + def->tooltip = L("This setting enables dynamic speed control on overhangs." + "Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion). " "Each overhang level then corresponds with the overhang speed below. Speeds for overhang levels in between are " "calculated via linear interpolation." "If you set multiple different speeds for the same overhang level, only the largest speed is used. " - ); - def->sidetext = L("%"); - def->min = 0; - def->max = 100; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionPercents({60, 40, 20, 0})); - - def = this->add("dynamic_overhang_speeds", coFloatsOrPercents); - def->full_label = L("Dynamic speed on overhangs"); - def->category = L("Speed"); - def->tooltip = L("This setting controls the speed on the overhang with the overlap value set above. " + "This setting controls the speed on the overhang with the overlap value set above. " "The speed of the extrusion is calculated as a linear interpolation of the speeds for higher and lower overlap. " "If set as percentage, the speed is calculated over the external perimeter speed." - ); + ); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("overhang_speed_0", coFloatOrPercent); + def->full_label = L("speed for 0\% overlap (bridge)"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloatsOrPercents({{25, false}, {20, false}, {15, false}, {15, false}})); + def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); + + def = this->add("overhang_speed_1", coFloatOrPercent); + def->full_label = L("speed for 20\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); + + def = this->add("overhang_speed_2", coFloatOrPercent); + def->full_label = L("speed for 40\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + + def = this->add("overhang_speed_3", coFloatOrPercent); + def->full_label = L("speed for 60\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + + def = this->add("overhang_speed_4", coFloatOrPercent); + def->full_label = L("speed for 80\% overlap"); + def->category = L("Speed"); + def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); def = this->add("brim_width", coFloat); def->label = L("Brim width"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b89957149..d7889fa01 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -573,8 +573,11 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, external_perimeter_extrusion_width)) ((ConfigOptionFloatOrPercent, external_perimeter_speed)) ((ConfigOptionBool, enable_dynamic_overhang_speeds)) - ((ConfigOptionPercents, overhang_overlap_levels)) - ((ConfigOptionFloatsOrPercents, dynamic_overhang_speeds)) + ((ConfigOptionFloatOrPercent, overhang_speed_0)) + ((ConfigOptionFloatOrPercent, overhang_speed_1)) + ((ConfigOptionFloatOrPercent, overhang_speed_2)) + ((ConfigOptionFloatOrPercent, overhang_speed_3)) + ((ConfigOptionFloatOrPercent, overhang_speed_4)) ((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters_on_overhangs)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index efdcb4fc6..ad48efb6d 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -765,8 +765,11 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_interface_speed" || opt_key == "bridge_speed" || opt_key == "enable_dynamic_overhang_speeds" - || opt_key == "overhang_overlap_levels" - || opt_key == "dynamic_overhang_speeds" + || opt_key == "overhang_speed_0" + || opt_key == "overhang_speed_1" + || opt_key == "overhang_speed_2" + || opt_key == "overhang_speed_3" + || opt_key == "overhang_speed_4" || opt_key == "external_perimeter_speed" || opt_key == "infill_speed" || opt_key == "perimeter_speed" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 120aeecf3..e6316e913 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -221,12 +221,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_perimeters = config->opt_int("perimeters") > 0; for (auto el : { "extra_perimeters","extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", "seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width", - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds", "overhang_overlap_levels", "dynamic_overhang_speeds" }) + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds"}) toggle_field(el, have_perimeters); - for (size_t i = 0; i < 4; i++) { - toggle_field("overhang_overlap_levels#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); - toggle_field("dynamic_overhang_speeds#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); + for (size_t i = 0; i < 5; i++) { + toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); } bool have_infill = config->option("fill_density")->value > 0; diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index d63a46d16..02e322bca 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -98,10 +98,6 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty suffix_local = " " + _(suffix); suffix = " " + suffix; } - else if (gc.group == "Dynamic overhang speed" && id >= 0) { - suffix = " " + std::to_string(id+1); - suffix_local = suffix; - } if (!label.IsEmpty()) options.emplace_back(Option{ boost::nowide::widen(key), type, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 17ddd63ab..2d556471c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1549,18 +1549,12 @@ void TabPrint::build() optgroup->append_single_option_line("ironing_speed"); optgroup = page->new_optgroup(L("Dynamic overhang speed")); - auto append_option_line = [](ConfigOptionsGroupShp optgroup, std::string opt_key) { - auto option = optgroup->get_option(opt_key, 0); - auto line = Line{option.opt.full_label, ""}; - line.append_option(option); - line.append_option(optgroup->get_option(opt_key, 1)); - line.append_option(optgroup->get_option(opt_key, 2)); - line.append_option(optgroup->get_option(opt_key, 3)); - optgroup->append_line(line); - }; optgroup->append_single_option_line("enable_dynamic_overhang_speeds"); - append_option_line(optgroup,"overhang_overlap_levels"); - append_option_line(optgroup,"dynamic_overhang_speeds"); + optgroup->append_single_option_line("overhang_speed_0"); + optgroup->append_single_option_line("overhang_speed_1"); + optgroup->append_single_option_line("overhang_speed_2"); + optgroup->append_single_option_line("overhang_speed_3"); + optgroup->append_single_option_line("overhang_speed_4"); optgroup = page->new_optgroup(L("Speed for non-print moves")); optgroup->append_single_option_line("travel_speed"); From 59faa8691508cfc0df13746ecf5b075d3856c918 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 22 Feb 2023 15:11:15 +0100 Subject: [PATCH 03/10] fix prointConfig for dynamic speeds - for single line options, label must be used (instead of fulllabel) --- src/libslic3r/PrintConfig.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 01dbfee16..b2a23e8a2 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -535,20 +535,16 @@ void PrintConfigDef::init_fff_params() def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); def->tooltip = L("This setting enables dynamic speed control on overhangs." - "Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " - "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion). " - "Each overhang level then corresponds with the overhang speed below. Speeds for overhang levels in between are " - "calculated via linear interpolation." - "If you set multiple different speeds for the same overhang level, only the largest speed is used. " - "This setting controls the speed on the overhang with the overlap value set above. " - "The speed of the extrusion is calculated as a linear interpolation of the speeds for higher and lower overlap. " - "If set as percentage, the speed is calculated over the external perimeter speed." + "Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer - " + "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion, bridge). " + "You can set speed for each overhang size listed below. Speeds for overhang levels in between are " + "calculated via linear interpolation. If set as percentage, the speed is calculated over the external perimeter speed." ); def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); def = this->add("overhang_speed_0", coFloatOrPercent); - def->full_label = L("speed for 0\% overlap (bridge)"); + def->label = L("speed for 0\% overlap (bridge)"); def->category = L("Speed"); def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); @@ -557,7 +553,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); def = this->add("overhang_speed_1", coFloatOrPercent); - def->full_label = L("speed for 20\% overlap"); + def->label = L("speed for 20\% overlap"); def->category = L("Speed"); def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); @@ -566,7 +562,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); def = this->add("overhang_speed_2", coFloatOrPercent); - def->full_label = L("speed for 40\% overlap"); + def->label = L("speed for 40\% overlap"); def->category = L("Speed"); def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); @@ -575,7 +571,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); def = this->add("overhang_speed_3", coFloatOrPercent); - def->full_label = L("speed for 60\% overlap"); + def->label = L("speed for 60\% overlap"); def->category = L("Speed"); def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); @@ -584,7 +580,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); def = this->add("overhang_speed_4", coFloatOrPercent); - def->full_label = L("speed for 80\% overlap"); + def->label = L("speed for 80\% overlap"); def->category = L("Speed"); def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); def->sidetext = L("mm/s or %"); From 278f633a3d9ee263f5473317f03f9bb0fe95e1e9 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 22 Feb 2023 15:30:52 +0100 Subject: [PATCH 04/10] improve description --- src/libslic3r/PrintConfig.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b2a23e8a2..6af343b38 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -534,19 +534,19 @@ void PrintConfigDef::init_fff_params() def = this->add("enable_dynamic_overhang_speeds", coBool); def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); - def->tooltip = L("This setting enables dynamic speed control on overhangs." - "Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer - " - "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion, bridge). " - "You can set speed for each overhang size listed below. Speeds for overhang levels in between are " - "calculated via linear interpolation. If set as percentage, the speed is calculated over the external perimeter speed." - ); + def->tooltip = L("This setting enables dynamic speed control on overhangs."); def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); + auto overhang_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: " + "100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). " + "Speeds for overhang sizes in between are calculated via linear interpolation. " + "If set as percentage, the speed is calculated over the external perimeter speed."); + def = this->add("overhang_speed_0", coFloatOrPercent); def->label = L("speed for 0\% overlap (bridge)"); def->category = L("Speed"); - def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; @@ -555,7 +555,7 @@ void PrintConfigDef::init_fff_params() def = this->add("overhang_speed_1", coFloatOrPercent); def->label = L("speed for 20\% overlap"); def->category = L("Speed"); - def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; @@ -564,7 +564,7 @@ void PrintConfigDef::init_fff_params() def = this->add("overhang_speed_2", coFloatOrPercent); def->label = L("speed for 40\% overlap"); def->category = L("Speed"); - def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; @@ -573,7 +573,7 @@ void PrintConfigDef::init_fff_params() def = this->add("overhang_speed_3", coFloatOrPercent); def->label = L("speed for 60\% overlap"); def->category = L("Speed"); - def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; @@ -582,7 +582,7 @@ void PrintConfigDef::init_fff_params() def = this->add("overhang_speed_4", coFloatOrPercent); def->label = L("speed for 80\% overlap"); def->category = L("Speed"); - def->tooltip = L("Controls the speed for the corresponding extrusion overlap value."); + def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; From 10d04529d69de5a143060852ebe8dcde45784360 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 22 Feb 2023 18:59:54 +0100 Subject: [PATCH 05/10] Implemented dynamic fan control. Cooling buffer does not yet relfect that --- src/libslic3r/GCode.cpp | 52 +++++++++++---- src/libslic3r/GCode/ExtrusionProcessor.hpp | 71 ++++++++++----------- src/libslic3r/Preset.cpp | 5 +- src/libslic3r/Print.cpp | 5 ++ src/libslic3r/PrintConfig.cpp | 74 ++++++++++++++++------ src/libslic3r/PrintConfig.hpp | 6 +- src/libslic3r/PrintObject.cpp | 1 - src/slic3r/GUI/Tab.cpp | 13 +++- 8 files changed, 151 insertions(+), 76 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 34a252abd..b322be3b0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2868,19 +2868,37 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de ); } - bool variable_speed = false; + bool variable_speed_or_fan_speed = false; std::vector new_points{}; - if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && path.role().is_perimeter()) { - std::vector> overhangs_with_speeds{ - {0, m_config.overhang_speed_0}, {20, m_config.overhang_speed_1}, {40, m_config.overhang_speed_2}, - {60, m_config.overhang_speed_3}, {80, m_config.overhang_speed_4}, - }; + if ((this->m_config.enable_dynamic_overhang_speeds || this->config().enable_dynamic_fan_speeds.get_at(m_writer.extruder()->id())) && + !this->on_first_layer() && path.role().is_perimeter()) { + std::vector> overhangs_with_speeds = {{100, ConfigOptionFloatOrPercent{speed, false}}}; + if (this->m_config.enable_dynamic_overhang_speeds) { + std::vector> overhangs_with_speeds = {{0, m_config.overhang_speed_0}, + {25, m_config.overhang_speed_1}, + {50, m_config.overhang_speed_2}, + {75, m_config.overhang_speed_3}, + {100, + ConfigOptionFloatOrPercent{speed, false}}}; + } + + std::vector> overhang_w_fan_speeds = {{100, ConfigOptionInts{0}}}; + if (this->m_config.enable_dynamic_fan_speeds.get_at(m_writer.extruder()->id())) { + std::vector> overhang_w_fan_speeds = {{0, m_config.overhang_fan_speed_0}, + {25, m_config.overhang_fan_speed_1}, + {50, m_config.overhang_fan_speed_2}, + {75, m_config.overhang_fan_speed_3}, + {100, ConfigOptionInts{0}}}; + } + double external_perim_reference_speed = std::min(m_config.get_abs_value("external_perimeter_speed"), std::min(EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm, m_config.max_volumetric_speed.value / path.mm3_per_mm)); - new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhangs_with_speeds, external_perim_reference_speed, + new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhangs_with_speeds, overhang_w_fan_speeds, + m_writer.extruder()->id(), external_perim_reference_speed, speed); - variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; }); + variable_speed_or_fan_speed = std::any_of(new_points.begin(), new_points.end(), + [speed](const ProcessedPoint &p) { return p.speed != speed || p.fan_speed != 0; }); } double F = speed * 60; // convert mm/sec to mm/min @@ -2944,7 +2962,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de cooling_marker_setspeed_comments += ";_EXTERNAL_PERIMETER"; } - if (!variable_speed) { + if (!variable_speed_or_fan_speed) { // F is mm per minute. gcode += m_writer.set_speed(F, "", cooling_marker_setspeed_comments); double path_length = 0.; @@ -2969,20 +2987,26 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de marked_comment = description; marked_comment += description_bridge; } - double last_set_speed = new_points[0].speed * 60.0; + double last_set_speed = new_points[0].speed * 60.0; + double last_set_fan_speed = new_points[0].fan_speed; gcode += m_writer.set_speed(last_set_speed, "", cooling_marker_setspeed_comments); + gcode += m_writer.set_fan(last_set_fan_speed); Vec2d prev = this->point_to_gcode_quantized(new_points[0].p); for (size_t i = 1; i < new_points.size(); i++) { - const ProcessedPoint& processed_point = new_points[i]; - Vec2d p = this->point_to_gcode_quantized(processed_point.p); - const double line_length = (p - prev).norm(); + const ProcessedPoint &processed_point = new_points[i]; + Vec2d p = this->point_to_gcode_quantized(processed_point.p); + const double line_length = (p - prev).norm(); gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, marked_comment); - prev = p; + prev = p; double new_speed = processed_point.speed * 60.0; if (last_set_speed != new_speed) { gcode += m_writer.set_speed(new_speed, "", cooling_marker_setspeed_comments); last_set_speed = new_speed; } + if (last_set_fan_speed != processed_point.fan_speed) { + gcode += m_writer.set_fan(processed_point.fan_speed); + last_set_fan_speed = processed_point.fan_speed; + } } } diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 066f1acd1..3273e31ff 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -238,6 +238,7 @@ struct ProcessedPoint { Point p; float speed = 1.0f; + int fan_speed = 0; }; class ExtrusionQualityEstimator @@ -259,31 +260,25 @@ public: std::vector estimate_extrusion_quality(const ExtrusionPath &path, const std::vector> overhangs_w_speeds, - float ext_perimeter_speed, - float original_speed) + const std::vector> overhangs_w_fan_speeds, + size_t extruder_id, + float ext_perimeter_speed, + float original_speed) { - float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; - std::vector> speed_sections; + float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; + std::map speed_sections; for (size_t i = 0; i < overhangs_w_speeds.size(); i++) { - float distance = path.width * (1.0 - (overhangs_w_speeds[i].first / 100.0)); - float speed = overhangs_w_speeds[i].second.percent ? (speed_base * overhangs_w_speeds[i].second.value / 100.0) : - overhangs_w_speeds[i].second.value; - speed_sections.push_back({distance, speed}); + float distance = path.width * (1.0 - (overhangs_w_speeds[i].first / 100.0)); + float speed = overhangs_w_speeds[i].second.percent ? (speed_base * overhangs_w_speeds[i].second.value / 100.0) : + overhangs_w_speeds[i].second.value; + speed_sections[distance] = speed; } - std::sort(speed_sections.begin(), speed_sections.end(), [](const std::pair &a, const std::pair &b) { - if (a.first == b.first) { - return a.second > b.second; - } - return a.first < b.first; - }); - std::pair last_section{INFINITY, 0}; - for (auto §ion : speed_sections) { - if (section.first == last_section.first) { - section.second = last_section.second; - } else { - last_section = section; - } + std::map fan_speed_sections; + for (size_t i = 0; i < overhangs_w_fan_speeds.size(); i++) { + float distance = path.width * (1.0 - (overhangs_w_fan_speeds[i].first / 100.0)); + float fan_speed = overhangs_w_fan_speeds[i].second.get_at(extruder_id); + fan_speed_sections[distance] = fan_speed; } std::vector extended_points = @@ -295,28 +290,26 @@ public: const ExtendedPoint &curr = extended_points[i]; const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i]; - auto calculate_speed = [&speed_sections, &original_speed](float distance) { - float final_speed; - if (distance <= speed_sections.front().first) { - final_speed = original_speed; - } else if (distance >= speed_sections.back().first) { - final_speed = speed_sections.back().second; - } else { - size_t section_idx = 0; - while (distance > speed_sections[section_idx + 1].first) { - section_idx++; - } - float t = (distance - speed_sections[section_idx].first) / - (speed_sections[section_idx + 1].first - speed_sections[section_idx].first); - t = std::clamp(t, 0.0f, 1.0f); - final_speed = (1.0f - t) * speed_sections[section_idx].second + t * speed_sections[section_idx + 1].second; + auto interpolate_speed = [](const std::map &values, float distance) { + auto upper_dist = values.lower_bound(distance); + if (upper_dist == values.end()) { + return values.rend()->second; } - return final_speed; + if (upper_dist == values.begin()) { + return upper_dist->second; + } + + auto lower_dist = --upper_dist; + float t = (distance - lower_dist->first) / (upper_dist->first - lower_dist->first); + return (1.0f - t) * lower_dist->second + t * upper_dist->second; }; - float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance)); + float extrusion_speed = std::min(interpolate_speed(speed_sections, curr.distance), + interpolate_speed(speed_sections, next.distance)); + float fan_speed = std::min(interpolate_speed(fan_speed_sections, curr.distance), + interpolate_speed(fan_speed_sections, next.distance)); - processed_points.push_back({scaled(curr.position), extrusion_speed}); + processed_points.push_back({scaled(curr.position), extrusion_speed, int(fan_speed)}); } return processed_points; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 60c415cf6..e2fb57b17 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -440,7 +440,7 @@ static std::vector s_Preset_print_options { "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_dist", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", "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", "overhang_speed_4", + "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", "external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration", @@ -473,7 +473,8 @@ static std::vector s_Preset_filament_options { "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower", "temperature", "idle_temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", - "start_filament_gcode", "end_filament_gcode", + "start_filament_gcode", "end_filament_gcode", "enable_dynamic_fan_speeds", + "overhang_fan_speed_0", "overhang_fan_speed_1", "overhang_fan_speed_2", "overhang_fan_speed_3", // Retract overrides "filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel", "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 3c810b178..8d3ad0066 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -66,6 +66,11 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "between_objects_gcode", "bridge_acceleration", "bridge_fan_speed", + "enable_dynamic_fan_speeds", + "overhang_fan_speed_0", + "overhang_fan_speed_1", + "overhang_fan_speed_2", + "overhang_fan_speed_3", "colorprint_heights", "cooling", "default_acceleration", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 6af343b38..87499261e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -535,7 +535,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Enable dynamic overhang speeds"); def->category = L("Speed"); def->tooltip = L("This setting enables dynamic speed control on overhangs."); - def->mode = comAdvanced; + def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); auto overhang_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: " @@ -549,44 +549,82 @@ void PrintConfigDef::init_fff_params() def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; - def->mode = comAdvanced; + def->mode = comExpert; def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); def = this->add("overhang_speed_1", coFloatOrPercent); - def->label = L("speed for 20\% overlap"); + def->label = L("speed for 25\% overlap"); def->category = L("Speed"); def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); def = this->add("overhang_speed_2", coFloatOrPercent); - def->label = L("speed for 40\% overlap"); + def->label = L("speed for 50\% overlap"); def->category = L("Speed"); def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); def = this->add("overhang_speed_3", coFloatOrPercent); - def->label = L("speed for 60\% overlap"); + def->label = L("speed for 75\% overlap"); def->category = L("Speed"); def->tooltip = overhang_speed_setting_description; def->sidetext = L("mm/s or %"); def->min = 0; - def->mode = comAdvanced; + def->mode = comExpert; def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); - def = this->add("overhang_speed_4", coFloatOrPercent); - def->label = L("speed for 80\% overlap"); - def->category = L("Speed"); - def->tooltip = overhang_speed_setting_description; - def->sidetext = L("mm/s or %"); - def->min = 0; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloatOrPercent(25, false)); + def = this->add("enable_dynamic_fan_speeds", coBools); + def->label = L("Enable dynamic fan speeds"); + def->tooltip = L("This setting enables dynamic fan speed control on overhangs."); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBools{false}); + + auto fan_speed_setting_description = L( + "Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: " + "100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). " + "Fan speeds for overhang sizes in between are calculated via linear interpolation. "); + + def = this->add("overhang_fan_speed_0", coInts); + def->label = L("speed for 0\% overlap (bridge)"); + def->tooltip = fan_speed_setting_description; + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts{100}); + + def = this->add("overhang_fan_speed_1", coInts); + def->label = L("speed for 25\% overlap"); + def->tooltip = fan_speed_setting_description; + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts{75}); + + def = this->add("overhang_fan_speed_2", coInts); + def->label = L("speed for 50\% overlap"); + def->tooltip = fan_speed_setting_description; + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts{50}); + + def = this->add("overhang_fan_speed_3", coInts); + def->label = L("speed for 75\% overlap"); + def->tooltip = fan_speed_setting_description; + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts{25}); def = this->add("brim_width", coFloat); def->label = L("Brim width"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index d7889fa01..dde60bee4 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -577,7 +577,6 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, overhang_speed_1)) ((ConfigOptionFloatOrPercent, overhang_speed_2)) ((ConfigOptionFloatOrPercent, overhang_speed_3)) - ((ConfigOptionFloatOrPercent, overhang_speed_4)) ((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters_on_overhangs)) @@ -750,6 +749,11 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionInts, bed_temperature)) ((ConfigOptionFloat, bridge_acceleration)) ((ConfigOptionInts, bridge_fan_speed)) + ((ConfigOptionBools, enable_dynamic_fan_speeds)) + ((ConfigOptionInts, overhang_fan_speed_0)) + ((ConfigOptionInts, overhang_fan_speed_1)) + ((ConfigOptionInts, overhang_fan_speed_2)) + ((ConfigOptionInts, overhang_fan_speed_3)) ((ConfigOptionBool, complete_objects)) ((ConfigOptionFloats, colorprint_heights)) ((ConfigOptionBools, cooling)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ad48efb6d..c12eeea82 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -769,7 +769,6 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "overhang_speed_1" || opt_key == "overhang_speed_2" || opt_key == "overhang_speed_3" - || opt_key == "overhang_speed_4" || opt_key == "external_perimeter_speed" || opt_key == "infill_speed" || opt_key == "perimeter_speed" diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 2d556471c..ae9bb175f 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1554,7 +1554,6 @@ void TabPrint::build() optgroup->append_single_option_line("overhang_speed_1"); optgroup->append_single_option_line("overhang_speed_2"); optgroup->append_single_option_line("overhang_speed_3"); - optgroup->append_single_option_line("overhang_speed_4"); optgroup = page->new_optgroup(L("Speed for non-print moves")); optgroup->append_single_option_line("travel_speed"); @@ -1988,6 +1987,13 @@ void TabFilament::build() optgroup->append_single_option_line("disable_fan_first_layers", category_path + "fan-settings"); optgroup->append_single_option_line("full_fan_speed_layer", category_path + "fan-settings"); + optgroup = page->new_optgroup(L("Dynamic fan speeds"), 25); + optgroup->append_single_option_line("enable_dynamic_fan_speeds", category_path + "dynamic-fan-speeds"); + optgroup->append_single_option_line("overhang_fan_speed_0", category_path + "dynamic-fan-speeds"); + optgroup->append_single_option_line("overhang_fan_speed_1", category_path + "dynamic-fan-speeds"); + optgroup->append_single_option_line("overhang_fan_speed_2", category_path + "dynamic-fan-speeds"); + optgroup->append_single_option_line("overhang_fan_speed_3", category_path + "dynamic-fan-speeds"); + optgroup = page->new_optgroup(L("Cooling thresholds"), 25); optgroup->append_single_option_line("fan_below_layer_time", category_path + "cooling-thresholds"); optgroup->append_single_option_line("slowdown_below_layer_time", category_path + "cooling-thresholds"); @@ -2140,6 +2146,11 @@ void TabFilament::toggle_options() for (auto el : { "min_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer" }) toggle_option(el, fan_always_on); + + bool dynamic_fan_speeds = m_config->opt_bool("enable_dynamic_fan_speeds", 0); + for (int i = 0; i < 4; i++) { + toggle_option("overhang_fan_speed_"+std::to_string(i),dynamic_fan_speeds); + } } if (m_active_page->title() == "Filament Overrides") From 7edd813fc881210fec496677e2a1032366853df0 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Thu, 23 Feb 2023 13:52:49 +0100 Subject: [PATCH 06/10] fix bugs in ExtrusionEstimator --- src/libslic3r/GCode.cpp | 21 ++++++++++----------- src/libslic3r/GCode/ExtrusionProcessor.hpp | 5 +++-- src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Search.cpp | 4 ++++ 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b322be3b0..54254213c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2874,21 +2874,20 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de !this->on_first_layer() && path.role().is_perimeter()) { std::vector> overhangs_with_speeds = {{100, ConfigOptionFloatOrPercent{speed, false}}}; if (this->m_config.enable_dynamic_overhang_speeds) { - std::vector> overhangs_with_speeds = {{0, m_config.overhang_speed_0}, - {25, m_config.overhang_speed_1}, - {50, m_config.overhang_speed_2}, - {75, m_config.overhang_speed_3}, - {100, - ConfigOptionFloatOrPercent{speed, false}}}; + overhangs_with_speeds = {{0, m_config.overhang_speed_0}, + {25, m_config.overhang_speed_1}, + {50, m_config.overhang_speed_2}, + {75, m_config.overhang_speed_3}, + {100, ConfigOptionFloatOrPercent{speed, false}}}; } std::vector> overhang_w_fan_speeds = {{100, ConfigOptionInts{0}}}; if (this->m_config.enable_dynamic_fan_speeds.get_at(m_writer.extruder()->id())) { - std::vector> overhang_w_fan_speeds = {{0, m_config.overhang_fan_speed_0}, - {25, m_config.overhang_fan_speed_1}, - {50, m_config.overhang_fan_speed_2}, - {75, m_config.overhang_fan_speed_3}, - {100, ConfigOptionInts{0}}}; + overhang_w_fan_speeds = {{0, m_config.overhang_fan_speed_0}, + {25, m_config.overhang_fan_speed_1}, + {50, m_config.overhang_fan_speed_2}, + {75, m_config.overhang_fan_speed_3}, + {100, ConfigOptionInts{0}}}; } double external_perim_reference_speed = std::min(m_config.get_abs_value("external_perimeter_speed"), diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 3273e31ff..1b1748827 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -293,13 +294,13 @@ public: auto interpolate_speed = [](const std::map &values, float distance) { auto upper_dist = values.lower_bound(distance); if (upper_dist == values.end()) { - return values.rend()->second; + return values.rbegin()->second; } if (upper_dist == values.begin()) { return upper_dist->second; } - auto lower_dist = --upper_dist; + auto lower_dist = std::prev(upper_dist); float t = (distance - lower_dist->first) / (upper_dist->first - lower_dist->first); return (1.0f - t) * lower_dist->second + t * upper_dist->second; }; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index e6316e913..9a0cf3881 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -224,7 +224,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds"}) toggle_field(el, have_perimeters); - for (size_t i = 0; i < 5; i++) { + for (size_t i = 0; i < 4; i++) { toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); } diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 02e322bca..d63a46d16 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -98,6 +98,10 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty suffix_local = " " + _(suffix); suffix = " " + suffix; } + else if (gc.group == "Dynamic overhang speed" && id >= 0) { + suffix = " " + std::to_string(id+1); + suffix_local = suffix; + } if (!label.IsEmpty()) options.emplace_back(Option{ boost::nowide::widen(key), type, From edec566d2c44fccaeb0833a5b97ee69ff2b5e177 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Thu, 23 Feb 2023 18:38:42 +0100 Subject: [PATCH 07/10] fix and integrate with CoolingBuffer --- src/libslic3r/GCode.cpp | 6 +++-- src/libslic3r/GCode/CoolingBuffer.cpp | 36 ++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 54254213c..b1d163560 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -2989,7 +2990,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de double last_set_speed = new_points[0].speed * 60.0; double last_set_fan_speed = new_points[0].fan_speed; gcode += m_writer.set_speed(last_set_speed, "", cooling_marker_setspeed_comments); - gcode += m_writer.set_fan(last_set_fan_speed); + gcode += ";_SET_FAN_SPEED" + std::to_string(int(last_set_fan_speed)) + "\n"; Vec2d prev = this->point_to_gcode_quantized(new_points[0].p); for (size_t i = 1; i < new_points.size(); i++) { const ProcessedPoint &processed_point = new_points[i]; @@ -3003,10 +3004,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de last_set_speed = new_speed; } if (last_set_fan_speed != processed_point.fan_speed) { - gcode += m_writer.set_fan(processed_point.fan_speed); last_set_fan_speed = processed_point.fan_speed; + gcode += ";_SET_FAN_SPEED" + std::to_string(int(last_set_fan_speed)) + "\n"; } } + gcode += ";_RESET_FAN_SPEED\n"; } if (m_enable_cooling_markers) diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index fb2d12a68..693316abb 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -1,5 +1,6 @@ #include "../GCode.hpp" #include "CoolingBuffer.hpp" +#include #include #include #include @@ -59,6 +60,9 @@ struct CoolingLine // Would be TYPE_ADJUSTABLE, but the block of G-code lines has zero extrusion length, thus the block // cannot have its speed adjusted. This should not happen (sic!). TYPE_ADJUSTABLE_EMPTY = 1 << 12, + // Custom fan speed (introduced for overhang fan speed) + TYPE_SET_FAN_SPEED = 1 << 13, + TYPE_RESET_FAN_SPEED = 1 << 14, }; CoolingLine(unsigned int type, size_t line_start, size_t line_end) : @@ -88,6 +92,8 @@ struct CoolingLine float time; // Maximum duration of this segment. float time_max; + // Requested fan speed + int fan_speed; // If marked with the "slowdown" flag, the line has been slowed down. bool slowdown; }; @@ -497,7 +503,18 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: } else line.time = 0; line.time_max = line.time; + } else if (boost::contains(sline, ";_SET_FAN_SPEED")) { + auto speed_start = sline.find_last_of('D'); + int speed = 0; + for (char num : sline.substr(speed_start + 1)) { + speed = speed * 10 + (num - '0'); + } + line.type = CoolingLine::TYPE_SET_FAN_SPEED; + line.fan_speed = speed; + } else if (boost::contains(sline, ";_RESET_FAN_SPEED")) { + line.type = CoolingLine::TYPE_RESET_FAN_SPEED; } + if (line.type != 0) adjustment->lines.emplace_back(std::move(line)); } @@ -730,10 +747,11 @@ std::string CoolingBuffer::apply_layer_cooldown( new_gcode.reserve(gcode.size() * 2); bool bridge_fan_control = false; int bridge_fan_speed = 0; - auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed ]() { + auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, &bridge_fan_control, &bridge_fan_speed]() { #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0; + std::pair custom_fan_speed_limits{fan_speed_new, EXTRUDER_CONFIG(cooling) ? EXTRUDER_CONFIG(max_fan_speed) : 100 }; int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers); // Is the fan speed ramp enabled? int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer); @@ -750,11 +768,13 @@ std::string CoolingBuffer::apply_layer_cooldown( if (layer_time < slowdown_below_layer_time) { // Layer time very short. Enable the fan to a full throttle. fan_speed_new = max_fan_speed; + custom_fan_speed_limits.first = fan_speed_new; } else if (layer_time < fan_below_layer_time) { // Layer time quite short. Enable the fan proportionally according to the current layer time. assert(layer_time >= slowdown_below_layer_time); double t = (layer_time - slowdown_below_layer_time) / (fan_below_layer_time - slowdown_below_layer_time); fan_speed_new = int(floor(t * min_fan_speed + (1. - t) * max_fan_speed) + 0.5); + custom_fan_speed_limits.first = fan_speed_new; } } bridge_fan_speed = EXTRUDER_CONFIG(bridge_fan_speed); @@ -763,6 +783,7 @@ std::string CoolingBuffer::apply_layer_cooldown( float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers); fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255); bridge_fan_speed = std::clamp(int(float(bridge_fan_speed) * factor + 0.5f), 0, 255); + custom_fan_speed_limits.second = fan_speed_new; } #undef EXTRUDER_CONFIG bridge_fan_control = bridge_fan_speed > fan_speed_new; @@ -775,11 +796,12 @@ std::string CoolingBuffer::apply_layer_cooldown( m_fan_speed = fan_speed_new; new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed); } + return custom_fan_speed_limits; }; const char *pos = gcode.c_str(); int current_feedrate = 0; - change_extruder_set_fan(); + std::pair fan_speed_limits = change_extruder_set_fan(); for (const CoolingLine *line : lines) { const char *line_start = gcode.c_str() + line->line_start; const char *line_end = gcode.c_str() + line->line_end; @@ -790,9 +812,17 @@ std::string CoolingBuffer::apply_layer_cooldown( auto res = std::from_chars(line_start + m_toolchange_prefix.size(), line_end, new_extruder); if (res.ec != std::errc::invalid_argument && new_extruder != m_current_extruder) { m_current_extruder = new_extruder; - change_extruder_set_fan(); + fan_speed_limits = change_extruder_set_fan(); } new_gcode.append(line_start, line_end - line_start); + } else if (line->type & CoolingLine::TYPE_SET_FAN_SPEED) { + int new_speed = std::clamp(line->fan_speed, fan_speed_limits.first, fan_speed_limits.second); + if (m_fan_speed != new_speed) { + new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, new_speed); + m_fan_speed = new_speed; + } + } else if (line->type & CoolingLine::TYPE_RESET_FAN_SPEED){ + fan_speed_limits = change_extruder_set_fan(); } else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_START) { if (bridge_fan_control) new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, bridge_fan_speed); From c0165ec2095e5761d0adfee5380ca29b0625ff4d Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Mon, 27 Feb 2023 16:23:06 +0100 Subject: [PATCH 08/10] Fix dynamic fan speed colliding with detect bridging perimeters Allow max fan speed override cooling max fan speed --- src/libslic3r/GCode.cpp | 3 ++- src/libslic3r/GCode/CoolingBuffer.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b1d163560..28c331313 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2954,7 +2954,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de std::string cooling_marker_setspeed_comments; if (m_enable_cooling_markers) { - if (path.role().is_bridge()) + if (path.role().is_bridge() && + (!path.role().is_perimeter() || !this->config().enable_dynamic_fan_speeds.get_at(m_writer.extruder()->id()))) gcode += ";_BRIDGE_FAN_START\n"; else cooling_marker_setspeed_comments = ";_EXTRUDE_SET_SPEED"; diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 693316abb..5e521f3c1 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -751,7 +751,7 @@ std::string CoolingBuffer::apply_layer_cooldown( #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0; - std::pair custom_fan_speed_limits{fan_speed_new, EXTRUDER_CONFIG(cooling) ? EXTRUDER_CONFIG(max_fan_speed) : 100 }; + std::pair custom_fan_speed_limits{fan_speed_new, 100 }; int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers); // Is the fan speed ramp enabled? int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer); From 11624e78888842a89a1344a92f6e94ea0c269aaf Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Thu, 2 Mar 2023 15:33:28 +0100 Subject: [PATCH 09/10] Make dynamic fan speeds by default zero. This makes it clear that it is up to the user to tune this setting. Also, if enabled and left with defaults, this will just spin the fan at min fan speed value, so only loss is slower fan on briding perimeters. --- src/libslic3r/PrintConfig.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 87499261e..3425cfd7a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -597,7 +597,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->set_default_value(new ConfigOptionInts{100}); + def->set_default_value(new ConfigOptionInts{0}); def = this->add("overhang_fan_speed_1", coInts); def->label = L("speed for 25\% overlap"); @@ -606,7 +606,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->set_default_value(new ConfigOptionInts{75}); + def->set_default_value(new ConfigOptionInts{0}); def = this->add("overhang_fan_speed_2", coInts); def->label = L("speed for 50\% overlap"); @@ -615,7 +615,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->set_default_value(new ConfigOptionInts{50}); + def->set_default_value(new ConfigOptionInts{0}); def = this->add("overhang_fan_speed_3", coInts); def->label = L("speed for 75\% overlap"); @@ -624,7 +624,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->set_default_value(new ConfigOptionInts{25}); + def->set_default_value(new ConfigOptionInts{0}); def = this->add("brim_width", coFloat); def->label = L("Brim width"); From c7dbb0e18ca062bbd86e1bd7c2d2315db6c4227c Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 2 Mar 2023 15:38:25 +0100 Subject: [PATCH 10/10] Organic supports had the Z gap rounded up to an integer number of layers, while newly the Z gap is rounded at a center. Fixes SPE-1550 --- src/libslic3r/TreeModelVolumes.cpp | 5 ++--- src/libslic3r/TreeSupport.cpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/TreeModelVolumes.cpp b/src/libslic3r/TreeModelVolumes.cpp index 53ac6534d..33758f3f0 100644 --- a/src/libslic3r/TreeModelVolumes.cpp +++ b/src/libslic3r/TreeModelVolumes.cpp @@ -491,9 +491,8 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex if (const std::vector &outlines = m_layer_outlines[outline_idx].second; ! outlines.empty()) { const TreeSupportMeshGroupSettings &settings = m_layer_outlines[outline_idx].first; const coord_t layer_height = settings.layer_height; - const coord_t z_distance_bottom = settings.support_bottom_distance; - const int z_distance_bottom_layers = round_up_divide(z_distance_bottom, layer_height); - const int z_distance_top_layers = round_up_divide(settings.support_top_distance, layer_height); + const int z_distance_bottom_layers = int(round(double(settings.support_bottom_distance) / double(layer_height))); + const int z_distance_top_layers = int(round(double(settings.support_top_distance) / double(layer_height))); const LayerIndex max_required_layer = std::min(outlines.size(), max_layer_idx + std::max(coord_t(1), z_distance_top_layers)); const LayerIndex min_layer_bottom = std::max(0, min_layer_last - int(z_distance_bottom_layers)); const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist : diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index 532cf7553..752a45577 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -80,8 +80,8 @@ TreeSupportSettings::TreeSupportSettings(const TreeSupportMeshGroupSettings& mes xy_min_distance(std::min(mesh_group_settings.support_xy_distance, mesh_group_settings.support_xy_distance_overhang)), bp_radius(mesh_group_settings.support_tree_bp_diameter / 2), diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller. - z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)), - z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)), + z_distance_bottom_layers(size_t(round(double(mesh_group_settings.support_bottom_distance) / double(layer_height)))), + z_distance_top_layers(size_t(round(double(mesh_group_settings.support_top_distance) / double(layer_height)))), performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)), // support_infill_angles(mesh_group_settings.support_infill_angles), support_roof_angles(mesh_group_settings.support_roof_angles),