From 03f728dfbdadcc944cb638165de7b333d4256daf Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 30 Jan 2025 17:12:32 +0100 Subject: [PATCH] (Almost) add new setting; reduce fan speed for overhangs. Nearly done, but doesn't handle the engine-plugin code yet, causing it to not show up, since the default is 1.0 part of CURA-11966 --- include/GCodePathConfig.h | 3 +++ include/LayerPlan.h | 6 ++++-- include/pathPlanning/GCodePath.h | 12 ++++++++++++ include/settings/MeshPathConfigs.h | 8 +++++++- include/settings/PathConfigStorage.h | 3 +++ src/GCodePathConfig.cpp | 5 +++++ src/LayerPlan.cpp | 19 ++++++++++++------- src/pathPlanning/GCodePath.cpp | 10 ++++++++++ src/settings/MeshPathConfigs.cpp | 26 +++++++++++++++++++------- src/settings/PathConfigStorage.cpp | 13 ++++++++++++- tests/FffGcodeWriterTest.cpp | 2 +- 11 files changed, 88 insertions(+), 19 deletions(-) diff --git a/include/GCodePathConfig.h b/include/GCodePathConfig.h index 27672049df..00736678fd 100644 --- a/include/GCodePathConfig.h +++ b/include/GCodePathConfig.h @@ -28,6 +28,7 @@ struct GCodePathConfig SpeedDerivatives speed_derivatives{}; //!< The speed settings (and acceleration and jerk) of the extruded line. May be changed when smoothSpeed is called. bool is_bridge_path{ false }; //!< whether current config is used when bridging double fan_speed{ FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise + double fan_overhang_factor{ 1.0 }; //!< fan speed overhang factor, multiplicative double extrusion_mm3_per_mm{ calculateExtrusion() }; //!< current mm^3 filament moved per mm line traversed [[nodiscard]] constexpr bool operator==(const GCodePathConfig& other) const noexcept = default; @@ -61,6 +62,8 @@ struct GCodePathConfig [[nodiscard]] double getFanSpeed() const noexcept; + [[nodiscard]] double getFanOverhangFactor() const noexcept; + [[nodiscard]] Ratio getFlowRatio() const noexcept; [[nodiscard]] coord_t getLayerThickness() const noexcept; diff --git a/include/LayerPlan.h b/include/LayerPlan.h index 8ad1793b43..da5863abad 100644 --- a/include/LayerPlan.h +++ b/include/LayerPlan.h @@ -159,7 +159,8 @@ class LayerPlan : public NoCopy const Ratio flow = 1.0_r, const Ratio width_factor = 1.0_r, const bool spiralize = false, - const Ratio speed_factor = 1.0_r); + const Ratio speed_factor = 1.0_r, + const Ratio fan_speed_overhang_factor = 1.0_r); public: /*! @@ -402,7 +403,8 @@ class LayerPlan : public NoCopy const bool spiralize = false, const Ratio speed_factor = 1.0_r, const double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT, - const bool travel_to_z = true); + const bool travel_to_z = true, + const Ratio fan_speed_overhang_factor = 1.0_r); void addExtrusionMoveWithGradualOverhang( const Point3LL& p, diff --git a/include/pathPlanning/GCodePath.h b/include/pathPlanning/GCodePath.h index 2eaf050d2e..683d35597d 100644 --- a/include/pathPlanning/GCodePath.h +++ b/include/pathPlanning/GCodePath.h @@ -49,6 +49,7 @@ struct GCodePath std::vector points{}; //!< The points constituting this path. The Z coordinate is an offset relative to the actual layer height, added to the global z_offset. bool done{ false }; //!< Path is finished, no more moves should be added, and a new path should be started instead of any appending done to this one. double fan_speed{ GCodePathConfig::FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise + double fan_speed_overhang_factor{ 1.0 }; //!< fan speed overhang factor, multiplicative TimeMaterialEstimates estimates{}; //!< Naive time and material estimates bool travel_to_z{ true }; //! Indicates whether we should add a travel move to the Z height of the first point before processing the path @@ -86,6 +87,17 @@ struct GCodePath * \return the value of fan_speed if it is in the range 0-100, otherwise the value from the config */ [[nodiscard]] double getFanSpeed() const noexcept; + + /*! + * Set the fan speed overhang factor, this needs to be separate from the fan speed because of signalling values. + */ + void setFanSpeedOverhangFactor(const double overhang_factor) noexcept; + + /*! + * Get the fan speed overhang factor, this needs to be separate from the fan speed because of signalling values. + * \return the value of fan_overhang_factor + */ + [[nodiscard]] double getFanSpeedOverhangFactor() const noexcept; }; } // namespace cura diff --git a/include/settings/MeshPathConfigs.h b/include/settings/MeshPathConfigs.h index 61c993b9a8..3f24843b8d 100644 --- a/include/settings/MeshPathConfigs.h +++ b/include/settings/MeshPathConfigs.h @@ -27,7 +27,13 @@ struct MeshPathConfigs std::vector infill_config{}; GCodePathConfig ironing_config{}; - MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t layer_thickness, const LayerIndex layer_nr, const std::vector& line_width_factor_per_extruder); + MeshPathConfigs( + const SliceMeshStorage& mesh, + const coord_t layer_thickness, + const LayerIndex layer_nr, + const std::vector& line_width_factor_per_extruder, + const std::vector& fan_overhang_factor_per_extruder + ); void smoothAllSpeeds(const SpeedDerivatives& first_layer_config, const LayerIndex layer_nr, const LayerIndex max_speed_layer); }; diff --git a/include/settings/PathConfigStorage.h b/include/settings/PathConfigStorage.h index 06206f7ebb..e5ee3655f9 100644 --- a/include/settings/PathConfigStorage.h +++ b/include/settings/PathConfigStorage.h @@ -38,6 +38,9 @@ class PathConfigStorage const std::vector line_width_factor_per_extruder; static std::vector getLineWidthFactorPerExtruder(const LayerIndex& layer_nr); + const std::vector fan_overhang_factor_per_extruder; + static std::vector getFanOverhangFactorPerExtruder(); + public: GCodePathConfig raft_base_config; GCodePathConfig raft_interface_config; diff --git a/src/GCodePathConfig.cpp b/src/GCodePathConfig.cpp index 35e81edbb3..9271189cb9 100644 --- a/src/GCodePathConfig.cpp +++ b/src/GCodePathConfig.cpp @@ -58,6 +58,11 @@ namespace cura return fan_speed; } +[[nodiscard]] double GCodePathConfig::getFanOverhangFactor() const noexcept +{ + return fan_overhang_factor; +} + [[nodiscard]] Ratio GCodePathConfig::getFlowRatio() const noexcept { return flow; diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index dc73c224ea..d40ce7e5cf 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -48,11 +48,12 @@ GCodePath* LayerPlan::getLatestPathWithConfig( const Ratio flow, const Ratio width_factor, const bool spiralize, - const Ratio speed_factor) + const Ratio speed_factor, + const Ratio fan_speed_overhang_factor) { std::vector& paths = extruder_plans_.back().paths_; if (paths.size() > 0 && paths.back().config == config && ! paths.back().done && paths.back().flow == flow && paths.back().width_factor == width_factor - && paths.back().speed_factor == speed_factor && paths.back().z_offset == z_offset + && paths.back().speed_factor == speed_factor && paths.back().z_offset == z_offset && paths.back().fan_speed_overhang_factor == fan_speed_overhang_factor && paths.back().mesh == current_mesh_) // spiralize can only change when a travel path is in between { return &paths.back(); @@ -64,7 +65,8 @@ GCodePath* LayerPlan::getLatestPathWithConfig( .flow = flow, .width_factor = width_factor, .spiralize = spiralize, - .speed_factor = speed_factor }); + .speed_factor = speed_factor, + .fan_speed_overhang_factor = fan_speed_overhang_factor }); GCodePath* ret = &paths.back(); ret->skip_agressive_merge_hint = mode_skip_agressive_merge_; @@ -544,11 +546,13 @@ void LayerPlan::addExtrusionMove( const bool spiralize, const Ratio speed_factor, const double fan_speed, - const bool travel_to_z) + const bool travel_to_z, + const Ratio fan_speed_overhang_factor) { - GCodePath* path = getLatestPathWithConfig(config, space_fill_type, config.z_offset, flow, width_factor, spiralize, speed_factor); + GCodePath* path = getLatestPathWithConfig(config, space_fill_type, config.z_offset, flow, width_factor, spiralize, speed_factor, fan_speed_overhang_factor); path->points.push_back(p); path->setFanSpeed(fan_speed); + path->setFanSpeedOverhangFactor(fan_speed_overhang_factor); path->travel_to_z = travel_to_z; if (! static_cast(first_extrusion_acc_jerk_)) { @@ -571,7 +575,8 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang( const auto add_extrusion_move = [&](const Point3LL& target, const std::optional speed_region_index = std::nullopt) { const Ratio overhang_speed_factor = speed_region_index.has_value() ? overhang_masks_[speed_region_index.value()].speed_ratio : 1.0_r; - addExtrusionMove(target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z); + const double fan_speed_overhang_factor = fan_speed < 0 && currently_overhanging_ ? config.fan_overhang_factor : 1.0; + addExtrusionMove(target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z, fan_speed_overhang_factor); }; const auto update_is_overhanging = [this](const Point2LL& target, std::optional current_position, const bool is_overhanging = false) @@ -2831,7 +2836,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) if (! path.isTravelPath() || path.fan_speed >= 0) { const double path_fan_speed = path.getFanSpeed(); - gcode.writeFanCommand(path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed()); + gcode.writeFanCommand(path.getFanSpeedOverhangFactor() * (path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed())); } if (path.perform_prime) diff --git a/src/pathPlanning/GCodePath.cpp b/src/pathPlanning/GCodePath.cpp index 5e0fa03be6..0d73821213 100644 --- a/src/pathPlanning/GCodePath.cpp +++ b/src/pathPlanning/GCodePath.cpp @@ -31,4 +31,14 @@ void GCodePath::setFanSpeed(const double fanspeed) noexcept return (fan_speed >= 0 && fan_speed <= 100) ? fan_speed : config.getFanSpeed(); } +void GCodePath::setFanSpeedOverhangFactor(const double overhang_factor) noexcept +{ + fan_speed_overhang_factor = overhang_factor; +} + +[[nodiscard]] double GCodePath::getFanSpeedOverhangFactor() const noexcept +{ + return fan_speed_overhang_factor; +} + } // namespace cura diff --git a/src/settings/MeshPathConfigs.cpp b/src/settings/MeshPathConfigs.cpp index fffc0d311a..b7fcfcfe57 100644 --- a/src/settings/MeshPathConfigs.cpp +++ b/src/settings/MeshPathConfigs.cpp @@ -11,7 +11,13 @@ namespace cura { -MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t layer_thickness, const LayerIndex layer_nr, const std::vector& line_width_factor_per_extruder) +MeshPathConfigs::MeshPathConfigs( + const SliceMeshStorage& mesh, + const coord_t layer_thickness, + const LayerIndex layer_nr, + const std::vector& line_width_factor_per_extruder, + const std::vector& fan_overhang_factor_per_extruder +) : inset0_config{ .type = PrintFeatureType::OuterWall, .line_width = static_cast( mesh.settings.get("wall_line_width_0") * line_width_factor_per_extruder[mesh.settings.get("wall_0_extruder_nr").extruder_nr_]), @@ -19,7 +25,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay .flow = mesh.settings.get("wall_0_material_flow") * (layer_nr == 0 ? mesh.settings.get("wall_0_material_flow_layer_0") : Ratio{ 1.0 }), .speed_derivatives = { .speed = mesh.settings.get("speed_wall_0"), .acceleration = mesh.settings.get("acceleration_wall_0"), - .jerk = mesh.settings.get("jerk_wall_0") } } + .jerk = mesh.settings.get("jerk_wall_0") }, + .fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get("wall_0_extruder_nr").extruder_nr_] } , insetX_config{ .type = PrintFeatureType::InnerWall, .line_width = static_cast( mesh.settings.get("wall_line_width_x") * line_width_factor_per_extruder[mesh.settings.get("wall_x_extruder_nr").extruder_nr_]), @@ -27,7 +34,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay .flow = mesh.settings.get("wall_x_material_flow") * (layer_nr == 0 ? mesh.settings.get("wall_x_material_flow_layer_0") : Ratio{ 1.0 }), .speed_derivatives = { .speed = mesh.settings.get("speed_wall_x"), .acceleration = mesh.settings.get("acceleration_wall_x"), - .jerk = mesh.settings.get("jerk_wall_x") } } + .jerk = mesh.settings.get("jerk_wall_x") }, + .fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get("wall_x_extruder_nr").extruder_nr_] } , inset0_roofing_config{ .type = PrintFeatureType::OuterWall, .line_width = static_cast( mesh.settings.get("wall_line_width_0") @@ -37,7 +45,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay = mesh.settings.get("wall_0_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get("wall_0_material_flow_layer_0") : Ratio{ 1.0 }), .speed_derivatives = { .speed = mesh.settings.get("speed_wall_0_roofing"), .acceleration = mesh.settings.get("acceleration_wall_0_roofing"), - .jerk = mesh.settings.get("jerk_wall_0_roofing") } } + .jerk = mesh.settings.get("jerk_wall_0_roofing") }, + .fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get("wall_0_extruder_nr").extruder_nr_] } , insetX_roofing_config{ .type = PrintFeatureType::InnerWall, .line_width = static_cast( mesh.settings.get("wall_line_width_x") @@ -47,7 +56,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay = mesh.settings.get("wall_x_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get("wall_x_material_flow_layer_0") : Ratio{ 1.0 }), .speed_derivatives = { .speed = mesh.settings.get("speed_wall_x_roofing"), .acceleration = mesh.settings.get("acceleration_wall_x_roofing"), - .jerk = mesh.settings.get("jerk_wall_x_roofing") } } + .jerk = mesh.settings.get("jerk_wall_x_roofing") }, + .fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get("wall_x_extruder_nr").extruder_nr_] } , bridge_inset0_config{ .type = PrintFeatureType::OuterWall, .line_width = static_cast( mesh.settings.get("wall_line_width_0") @@ -77,7 +87,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay .flow = mesh.settings.get("skin_material_flow") * (layer_nr == 0 ? mesh.settings.get("skin_material_flow_layer_0") : Ratio{ 1.0 }), .speed_derivatives = { .speed = mesh.settings.get("speed_topbottom"), .acceleration = mesh.settings.get("acceleration_topbottom"), - .jerk = mesh.settings.get("jerk_topbottom") } } + .jerk = mesh.settings.get("jerk_topbottom") }, + .fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get("top_bottom_extruder_nr").extruder_nr_] } , bridge_skin_config{ .type = PrintFeatureType::Skin, .line_width = static_cast( mesh.settings.get("skin_line_width") @@ -125,7 +136,6 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay .speed_derivatives = { .speed = mesh.settings.get("speed_ironing"), .acceleration = mesh.settings.get("acceleration_ironing"), .jerk = mesh.settings.get("jerk_ironing") } } - { infill_config.reserve(MAX_INFILL_COMBINE); @@ -141,6 +151,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay .acceleration = mesh.settings.get("acceleration_infill"), .jerk = mesh.settings.get("jerk_infill") } }); } + + } } // namespace cura diff --git a/src/settings/PathConfigStorage.cpp b/src/settings/PathConfigStorage.cpp index d4944f1e8d..e6b80dc81a 100644 --- a/src/settings/PathConfigStorage.cpp +++ b/src/settings/PathConfigStorage.cpp @@ -11,6 +11,9 @@ #include "settings/Settings.h" // MAX_INFILL_COMBINE #include "sliceDataStorage.h" // SliceDataStorage +#include +#include + namespace cura { @@ -32,6 +35,13 @@ std::vector PathConfigStorage::getLineWidthFactorPerExtruder(const LayerI return ret; } +std::vector PathConfigStorage::getFanOverhangFactorPerExtruder() +{ + return Application::getInstance().current_slice_->scene.extruders | ranges::views::transform([](const ExtruderTrain& train) -> Ratio { + return train.settings_.get("cool_fan_speed_overhang_factor"); + }) | ranges::to>; +} + PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const LayerIndex& layer_nr, const coord_t layer_thickness) : support_infill_extruder_nr(Application::getInstance().current_slice_->scene.current_mesh_group->settings.get("support_infill_extruder_nr").extruder_nr_) , support_roof_extruder_nr(Application::getInstance().current_slice_->scene.current_mesh_group->settings.get("support_roof_extruder_nr").extruder_nr_) @@ -43,6 +53,7 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye , support_roof_train(Application::getInstance().current_slice_->scene.extruders[support_roof_extruder_nr]) , support_bottom_train(Application::getInstance().current_slice_->scene.extruders[support_bottom_extruder_nr]) , line_width_factor_per_extruder(PathConfigStorage::getLineWidthFactorPerExtruder(layer_nr)) + , fan_overhang_factor_per_extruder(PathConfigStorage::getFanOverhangFactorPerExtruder()) , raft_base_config(GCodePathConfig{ .type = PrintFeatureType::SupportInterface, .line_width = raft_base_train.settings_.get("raft_base_line_width"), .layer_thickness = raft_base_train.settings_.get("raft_base_thickness"), @@ -126,7 +137,7 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye mesh_configs.reserve(storage.meshes.size()); for (const std::shared_ptr& mesh_storage : storage.meshes) { - mesh_configs.emplace_back(*mesh_storage, layer_thickness, layer_nr, line_width_factor_per_extruder); + mesh_configs.emplace_back(*mesh_storage, layer_thickness, layer_nr, line_width_factor_per_extruder, fan_overhang_factor_per_extruder); } support_infill_config.reserve(MAX_INFILL_COMBINE); diff --git a/tests/FffGcodeWriterTest.cpp b/tests/FffGcodeWriterTest.cpp index 452dd4a749..24d279b1b7 100644 --- a/tests/FffGcodeWriterTest.cpp +++ b/tests/FffGcodeWriterTest.cpp @@ -116,7 +116,7 @@ TEST_F(FffGcodeWriterTest, SurfaceGetsExtraInfillLinesUnderIt) LayerPlan gcode_layer(*storage, 100, 10000, 100, 0, {fan_settings}, 20, 10, 5000 ); SliceMeshStorage mesh_storage(&mesh, 200); size_t extruder_nr = 0; - MeshPathConfigs mesh_config(mesh_storage, 10, 100, {0.5}); + MeshPathConfigs mesh_config(mesh_storage, 10, 100, { 0.5 }, { 1.0 }); SliceLayerPart part; part.infill_area_per_combine_per_density = { { outer_square } };