Skip to content

Commit 03f728d

Browse files
committed
(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
1 parent d1534f5 commit 03f728d

11 files changed

+88
-19
lines changed

include/GCodePathConfig.h

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct GCodePathConfig
2828
SpeedDerivatives speed_derivatives{}; //!< The speed settings (and acceleration and jerk) of the extruded line. May be changed when smoothSpeed is called.
2929
bool is_bridge_path{ false }; //!< whether current config is used when bridging
3030
double fan_speed{ FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise
31+
double fan_overhang_factor{ 1.0 }; //!< fan speed overhang factor, multiplicative
3132
double extrusion_mm3_per_mm{ calculateExtrusion() }; //!< current mm^3 filament moved per mm line traversed
3233

3334
[[nodiscard]] constexpr bool operator==(const GCodePathConfig& other) const noexcept = default;
@@ -61,6 +62,8 @@ struct GCodePathConfig
6162

6263
[[nodiscard]] double getFanSpeed() const noexcept;
6364

65+
[[nodiscard]] double getFanOverhangFactor() const noexcept;
66+
6467
[[nodiscard]] Ratio getFlowRatio() const noexcept;
6568

6669
[[nodiscard]] coord_t getLayerThickness() const noexcept;

include/LayerPlan.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ class LayerPlan : public NoCopy
159159
const Ratio flow = 1.0_r,
160160
const Ratio width_factor = 1.0_r,
161161
const bool spiralize = false,
162-
const Ratio speed_factor = 1.0_r);
162+
const Ratio speed_factor = 1.0_r,
163+
const Ratio fan_speed_overhang_factor = 1.0_r);
163164

164165
public:
165166
/*!
@@ -402,7 +403,8 @@ class LayerPlan : public NoCopy
402403
const bool spiralize = false,
403404
const Ratio speed_factor = 1.0_r,
404405
const double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT,
405-
const bool travel_to_z = true);
406+
const bool travel_to_z = true,
407+
const Ratio fan_speed_overhang_factor = 1.0_r);
406408

407409
void addExtrusionMoveWithGradualOverhang(
408410
const Point3LL& p,

include/pathPlanning/GCodePath.h

+12
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct GCodePath
4949
std::vector<Point3LL> points{}; //!< The points constituting this path. The Z coordinate is an offset relative to the actual layer height, added to the global z_offset.
5050
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.
5151
double fan_speed{ GCodePathConfig::FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise
52+
double fan_speed_overhang_factor{ 1.0 }; //!< fan speed overhang factor, multiplicative
5253
TimeMaterialEstimates estimates{}; //!< Naive time and material estimates
5354
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
5455

@@ -86,6 +87,17 @@ struct GCodePath
8687
* \return the value of fan_speed if it is in the range 0-100, otherwise the value from the config
8788
*/
8889
[[nodiscard]] double getFanSpeed() const noexcept;
90+
91+
/*!
92+
* Set the fan speed overhang factor, this needs to be separate from the fan speed because of signalling values.
93+
*/
94+
void setFanSpeedOverhangFactor(const double overhang_factor) noexcept;
95+
96+
/*!
97+
* Get the fan speed overhang factor, this needs to be separate from the fan speed because of signalling values.
98+
* \return the value of fan_overhang_factor
99+
*/
100+
[[nodiscard]] double getFanSpeedOverhangFactor() const noexcept;
89101
};
90102

91103
} // namespace cura

include/settings/MeshPathConfigs.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ struct MeshPathConfigs
2727
std::vector<GCodePathConfig> infill_config{};
2828
GCodePathConfig ironing_config{};
2929

30-
MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t layer_thickness, const LayerIndex layer_nr, const std::vector<Ratio>& line_width_factor_per_extruder);
30+
MeshPathConfigs(
31+
const SliceMeshStorage& mesh,
32+
const coord_t layer_thickness,
33+
const LayerIndex layer_nr,
34+
const std::vector<Ratio>& line_width_factor_per_extruder,
35+
const std::vector<Ratio>& fan_overhang_factor_per_extruder
36+
);
3137
void smoothAllSpeeds(const SpeedDerivatives& first_layer_config, const LayerIndex layer_nr, const LayerIndex max_speed_layer);
3238
};
3339

include/settings/PathConfigStorage.h

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class PathConfigStorage
3838
const std::vector<Ratio> line_width_factor_per_extruder;
3939
static std::vector<Ratio> getLineWidthFactorPerExtruder(const LayerIndex& layer_nr);
4040

41+
const std::vector<Ratio> fan_overhang_factor_per_extruder;
42+
static std::vector<Ratio> getFanOverhangFactorPerExtruder();
43+
4144
public:
4245
GCodePathConfig raft_base_config;
4346
GCodePathConfig raft_interface_config;

src/GCodePathConfig.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ namespace cura
5858
return fan_speed;
5959
}
6060

61+
[[nodiscard]] double GCodePathConfig::getFanOverhangFactor() const noexcept
62+
{
63+
return fan_overhang_factor;
64+
}
65+
6166
[[nodiscard]] Ratio GCodePathConfig::getFlowRatio() const noexcept
6267
{
6368
return flow;

src/LayerPlan.cpp

+12-7
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@ GCodePath* LayerPlan::getLatestPathWithConfig(
4848
const Ratio flow,
4949
const Ratio width_factor,
5050
const bool spiralize,
51-
const Ratio speed_factor)
51+
const Ratio speed_factor,
52+
const Ratio fan_speed_overhang_factor)
5253
{
5354
std::vector<GCodePath>& paths = extruder_plans_.back().paths_;
5455
if (paths.size() > 0 && paths.back().config == config && ! paths.back().done && paths.back().flow == flow && paths.back().width_factor == width_factor
55-
&& paths.back().speed_factor == speed_factor && paths.back().z_offset == z_offset
56+
&& paths.back().speed_factor == speed_factor && paths.back().z_offset == z_offset && paths.back().fan_speed_overhang_factor == fan_speed_overhang_factor
5657
&& paths.back().mesh == current_mesh_) // spiralize can only change when a travel path is in between
5758
{
5859
return &paths.back();
@@ -64,7 +65,8 @@ GCodePath* LayerPlan::getLatestPathWithConfig(
6465
.flow = flow,
6566
.width_factor = width_factor,
6667
.spiralize = spiralize,
67-
.speed_factor = speed_factor });
68+
.speed_factor = speed_factor,
69+
.fan_speed_overhang_factor = fan_speed_overhang_factor });
6870

6971
GCodePath* ret = &paths.back();
7072
ret->skip_agressive_merge_hint = mode_skip_agressive_merge_;
@@ -544,11 +546,13 @@ void LayerPlan::addExtrusionMove(
544546
const bool spiralize,
545547
const Ratio speed_factor,
546548
const double fan_speed,
547-
const bool travel_to_z)
549+
const bool travel_to_z,
550+
const Ratio fan_speed_overhang_factor)
548551
{
549-
GCodePath* path = getLatestPathWithConfig(config, space_fill_type, config.z_offset, flow, width_factor, spiralize, speed_factor);
552+
GCodePath* path = getLatestPathWithConfig(config, space_fill_type, config.z_offset, flow, width_factor, spiralize, speed_factor, fan_speed_overhang_factor);
550553
path->points.push_back(p);
551554
path->setFanSpeed(fan_speed);
555+
path->setFanSpeedOverhangFactor(fan_speed_overhang_factor);
552556
path->travel_to_z = travel_to_z;
553557
if (! static_cast<bool>(first_extrusion_acc_jerk_))
554558
{
@@ -571,7 +575,8 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
571575
const auto add_extrusion_move = [&](const Point3LL& target, const std::optional<size_t> speed_region_index = std::nullopt)
572576
{
573577
const Ratio overhang_speed_factor = speed_region_index.has_value() ? overhang_masks_[speed_region_index.value()].speed_ratio : 1.0_r;
574-
addExtrusionMove(target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z);
578+
const double fan_speed_overhang_factor = fan_speed < 0 && currently_overhanging_ ? config.fan_overhang_factor : 1.0;
579+
addExtrusionMove(target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z, fan_speed_overhang_factor);
575580
};
576581

577582
const auto update_is_overhanging = [this](const Point2LL& target, std::optional<Point2LL> current_position, const bool is_overhanging = false)
@@ -2831,7 +2836,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode)
28312836
if (! path.isTravelPath() || path.fan_speed >= 0)
28322837
{
28332838
const double path_fan_speed = path.getFanSpeed();
2834-
gcode.writeFanCommand(path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed());
2839+
gcode.writeFanCommand(path.getFanSpeedOverhangFactor() * (path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed()));
28352840
}
28362841

28372842
if (path.perform_prime)

src/pathPlanning/GCodePath.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,14 @@ void GCodePath::setFanSpeed(const double fanspeed) noexcept
3131
return (fan_speed >= 0 && fan_speed <= 100) ? fan_speed : config.getFanSpeed();
3232
}
3333

34+
void GCodePath::setFanSpeedOverhangFactor(const double overhang_factor) noexcept
35+
{
36+
fan_speed_overhang_factor = overhang_factor;
37+
}
38+
39+
[[nodiscard]] double GCodePath::getFanSpeedOverhangFactor() const noexcept
40+
{
41+
return fan_speed_overhang_factor;
42+
}
43+
3444
} // namespace cura

src/settings/MeshPathConfigs.cpp

+19-7
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,31 @@
1111
namespace cura
1212
{
1313

14-
MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t layer_thickness, const LayerIndex layer_nr, const std::vector<Ratio>& line_width_factor_per_extruder)
14+
MeshPathConfigs::MeshPathConfigs(
15+
const SliceMeshStorage& mesh,
16+
const coord_t layer_thickness,
17+
const LayerIndex layer_nr,
18+
const std::vector<Ratio>& line_width_factor_per_extruder,
19+
const std::vector<Ratio>& fan_overhang_factor_per_extruder
20+
)
1521
: inset0_config{ .type = PrintFeatureType::OuterWall,
1622
.line_width = static_cast<coord_t>(
1723
mesh.settings.get<coord_t>("wall_line_width_0") * line_width_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr_]),
1824
.layer_thickness = layer_thickness,
1925
.flow = mesh.settings.get<Ratio>("wall_0_material_flow") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_0_material_flow_layer_0") : Ratio{ 1.0 }),
2026
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_0"),
2127
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_0"),
22-
.jerk = mesh.settings.get<Velocity>("jerk_wall_0") } }
28+
.jerk = mesh.settings.get<Velocity>("jerk_wall_0") },
29+
.fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr_] }
2330
, insetX_config{ .type = PrintFeatureType::InnerWall,
2431
.line_width = static_cast<coord_t>(
2532
mesh.settings.get<coord_t>("wall_line_width_x") * line_width_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr_]),
2633
.layer_thickness = layer_thickness,
2734
.flow = mesh.settings.get<Ratio>("wall_x_material_flow") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_x_material_flow_layer_0") : Ratio{ 1.0 }),
2835
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_x"),
2936
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_x"),
30-
.jerk = mesh.settings.get<Velocity>("jerk_wall_x") } }
37+
.jerk = mesh.settings.get<Velocity>("jerk_wall_x") },
38+
.fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr_] }
3139
, inset0_roofing_config{ .type = PrintFeatureType::OuterWall,
3240
.line_width = static_cast<coord_t>(
3341
mesh.settings.get<coord_t>("wall_line_width_0")
@@ -37,7 +45,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
3745
= mesh.settings.get<Ratio>("wall_0_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_0_material_flow_layer_0") : Ratio{ 1.0 }),
3846
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_0_roofing"),
3947
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_0_roofing"),
40-
.jerk = mesh.settings.get<Velocity>("jerk_wall_0_roofing") } }
48+
.jerk = mesh.settings.get<Velocity>("jerk_wall_0_roofing") },
49+
.fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_0_extruder_nr").extruder_nr_] }
4150
, insetX_roofing_config{ .type = PrintFeatureType::InnerWall,
4251
.line_width = static_cast<coord_t>(
4352
mesh.settings.get<coord_t>("wall_line_width_x")
@@ -47,7 +56,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
4756
= mesh.settings.get<Ratio>("wall_x_material_flow_roofing") * (layer_nr == 0 ? mesh.settings.get<Ratio>("wall_x_material_flow_layer_0") : Ratio{ 1.0 }),
4857
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_wall_x_roofing"),
4958
.acceleration = mesh.settings.get<Acceleration>("acceleration_wall_x_roofing"),
50-
.jerk = mesh.settings.get<Velocity>("jerk_wall_x_roofing") } }
59+
.jerk = mesh.settings.get<Velocity>("jerk_wall_x_roofing") },
60+
.fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("wall_x_extruder_nr").extruder_nr_] }
5161
, bridge_inset0_config{ .type = PrintFeatureType::OuterWall,
5262
.line_width = static_cast<coord_t>(
5363
mesh.settings.get<coord_t>("wall_line_width_0")
@@ -77,7 +87,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
7787
.flow = mesh.settings.get<Ratio>("skin_material_flow") * (layer_nr == 0 ? mesh.settings.get<Ratio>("skin_material_flow_layer_0") : Ratio{ 1.0 }),
7888
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_topbottom"),
7989
.acceleration = mesh.settings.get<Acceleration>("acceleration_topbottom"),
80-
.jerk = mesh.settings.get<Velocity>("jerk_topbottom") } }
90+
.jerk = mesh.settings.get<Velocity>("jerk_topbottom") },
91+
.fan_overhang_factor = fan_overhang_factor_per_extruder[mesh.settings.get<ExtruderTrain&>("top_bottom_extruder_nr").extruder_nr_] }
8192
, bridge_skin_config{ .type = PrintFeatureType::Skin,
8293
.line_width = static_cast<coord_t>(
8394
mesh.settings.get<coord_t>("skin_line_width")
@@ -125,7 +136,6 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
125136
.speed_derivatives = { .speed = mesh.settings.get<Velocity>("speed_ironing"),
126137
.acceleration = mesh.settings.get<Acceleration>("acceleration_ironing"),
127138
.jerk = mesh.settings.get<Velocity>("jerk_ironing") } }
128-
129139
{
130140
infill_config.reserve(MAX_INFILL_COMBINE);
131141

@@ -141,6 +151,8 @@ MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, const coord_t lay
141151
.acceleration = mesh.settings.get<Acceleration>("acceleration_infill"),
142152
.jerk = mesh.settings.get<Velocity>("jerk_infill") } });
143153
}
154+
155+
144156
}
145157

146158
} // namespace cura

src/settings/PathConfigStorage.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "settings/Settings.h" // MAX_INFILL_COMBINE
1212
#include "sliceDataStorage.h" // SliceDataStorage
1313

14+
#include <range/v3/to_container.hpp>
15+
#include <range/v3/view/transform.hpp>
16+
1417
namespace cura
1518
{
1619

@@ -32,6 +35,13 @@ std::vector<Ratio> PathConfigStorage::getLineWidthFactorPerExtruder(const LayerI
3235
return ret;
3336
}
3437

38+
std::vector<Ratio> PathConfigStorage::getFanOverhangFactorPerExtruder()
39+
{
40+
return Application::getInstance().current_slice_->scene.extruders | ranges::views::transform([](const ExtruderTrain& train) -> Ratio {
41+
return train.settings_.get<Ratio>("cool_fan_speed_overhang_factor");
42+
}) | ranges::to<std::vector<Ratio>>;
43+
}
44+
3545
PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const LayerIndex& layer_nr, const coord_t layer_thickness)
3646
: support_infill_extruder_nr(Application::getInstance().current_slice_->scene.current_mesh_group->settings.get<ExtruderTrain&>("support_infill_extruder_nr").extruder_nr_)
3747
, support_roof_extruder_nr(Application::getInstance().current_slice_->scene.current_mesh_group->settings.get<ExtruderTrain&>("support_roof_extruder_nr").extruder_nr_)
@@ -43,6 +53,7 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye
4353
, support_roof_train(Application::getInstance().current_slice_->scene.extruders[support_roof_extruder_nr])
4454
, support_bottom_train(Application::getInstance().current_slice_->scene.extruders[support_bottom_extruder_nr])
4555
, line_width_factor_per_extruder(PathConfigStorage::getLineWidthFactorPerExtruder(layer_nr))
56+
, fan_overhang_factor_per_extruder(PathConfigStorage::getFanOverhangFactorPerExtruder())
4657
, raft_base_config(GCodePathConfig{ .type = PrintFeatureType::SupportInterface,
4758
.line_width = raft_base_train.settings_.get<coord_t>("raft_base_line_width"),
4859
.layer_thickness = raft_base_train.settings_.get<coord_t>("raft_base_thickness"),
@@ -126,7 +137,7 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye
126137
mesh_configs.reserve(storage.meshes.size());
127138
for (const std::shared_ptr<SliceMeshStorage>& mesh_storage : storage.meshes)
128139
{
129-
mesh_configs.emplace_back(*mesh_storage, layer_thickness, layer_nr, line_width_factor_per_extruder);
140+
mesh_configs.emplace_back(*mesh_storage, layer_thickness, layer_nr, line_width_factor_per_extruder, fan_overhang_factor_per_extruder);
130141
}
131142

132143
support_infill_config.reserve(MAX_INFILL_COMBINE);

tests/FffGcodeWriterTest.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ TEST_F(FffGcodeWriterTest, SurfaceGetsExtraInfillLinesUnderIt)
116116
LayerPlan gcode_layer(*storage, 100, 10000, 100, 0, {fan_settings}, 20, 10, 5000 );
117117
SliceMeshStorage mesh_storage(&mesh, 200);
118118
size_t extruder_nr = 0;
119-
MeshPathConfigs mesh_config(mesh_storage, 10, 100, {0.5});
119+
MeshPathConfigs mesh_config(mesh_storage, 10, 100, { 0.5 }, { 1.0 });
120120
SliceLayerPart part;
121121

122122
part.infill_area_per_combine_per_density = { { outer_square } };

0 commit comments

Comments
 (0)