Skip to content

Commit 2dec76d

Browse files
authored
CURA-12352 different minimum layer time for layers that contain overhangs (#2187)
2 parents 4c2c378 + 0ca9c26 commit 2dec76d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+192
-86
lines changed

include/FanSpeedLayerTime.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
//Copyright (c) 2020 Ultimaker B.V.
2-
//CuraEngine is released under the terms of the AGPLv3 or higher.
1+
// Copyright (c) 2020 Ultimaker B.V.
2+
// CuraEngine is released under the terms of the AGPLv3 or higher.
33

44
#ifndef FAN_SPEED_LAYER_TIME_H
55
#define FAN_SPEED_LAYER_TIME_H
66

7+
#include <utils/Coord_t.h>
8+
79
#include "settings/types/Duration.h"
810
#include "settings/types/LayerIndex.h"
911
#include "settings/types/Velocity.h"
1012

11-
namespace cura
13+
namespace cura
1214
{
1315

1416
/*!
@@ -19,7 +21,7 @@ namespace cura
1921
* store these settings over and over again for each part, even though the
2022
* settings may be different for each part on a layer.
2123
*/
22-
struct FanSpeedLayerTimeSettings
24+
struct FanSpeedLayerTimeSettings
2325
{
2426
public:
2527
/*!
@@ -28,6 +30,16 @@ struct FanSpeedLayerTimeSettings
2830
*/
2931
Duration cool_min_layer_time;
3032

33+
/*!
34+
* Similar to Minimum layer time, but to be applied for layers that contain overhanging extrusion.
35+
*/
36+
Duration cool_min_layer_time_overhang;
37+
38+
/*!
39+
* The specific minimum layer time for overhanging will be applied only if there is at least one overhanging segment longer that this threshold
40+
*/
41+
coord_t cool_min_layer_time_overhang_min_segment_length;
42+
3143
/*!
3244
* "Regular/Maximum Fan Speed Threshold". If the layers take longer to print
3345
* than this, they'll use the regular fan speed. If they take shorter, we'll

include/LayerPlan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ class LayerPlan : public NoCopy
124124
std::vector<OverhangMask> overhang_masks_; //!< The regions of a layer part where the walls overhang, calculated for multiple overhang angles. The latter is the most
125125
//!< overhanging. For a visual explanation of the result, see doc/gradual_overhang_speed.svg
126126
Shape seam_overhang_mask_; //!< The regions of a layer part where the walls overhang, specifically as defined for the seam
127+
bool currently_overhanging_{ false }; //!< Indicates whether the last extrusion move was overhanging
128+
coord_t current_overhang_length_{ 0 }; //!< When doing consecutive overhanging moves, this is the current accumulated overhanging length
129+
coord_t max_overhang_length_{ 0 }; //!< From all consecutive overhanging moves in the layer, this is the longest one
130+
127131
Shape roofing_mask_; //!< The regions of a layer part where the walls are exposed to the air
128132

129133
bool min_layer_time_used = false; //!< Wether or not the minimum layer time (cool_min_layer_time) was actually used in this layerplan.

src/FffGcodeWriter.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ void FffGcodeWriter::setConfigFanSpeedLayerTime()
319319
fan_speed_layer_time_settings_per_extruder.emplace_back();
320320
FanSpeedLayerTimeSettings& fan_speed_layer_time_settings = fan_speed_layer_time_settings_per_extruder.back();
321321
fan_speed_layer_time_settings.cool_min_layer_time = train.settings_.get<Duration>("cool_min_layer_time");
322+
fan_speed_layer_time_settings.cool_min_layer_time_overhang = train.settings_.get<Duration>("cool_min_layer_time_overhang");
323+
fan_speed_layer_time_settings.cool_min_layer_time_overhang_min_segment_length = train.settings_.get<coord_t>("cool_min_layer_time_overhang_min_segment_length");
322324
fan_speed_layer_time_settings.cool_min_layer_time_fan_speed_max = train.settings_.get<Duration>("cool_min_layer_time_fan_speed_max");
323325
fan_speed_layer_time_settings.cool_fan_speed_0 = train.settings_.get<Ratio>("cool_fan_speed_0") * 100.0;
324326
fan_speed_layer_time_settings.cool_fan_speed_min = train.settings_.get<Ratio>("cool_fan_speed_min") * 100.0;
@@ -3112,16 +3114,18 @@ bool FffGcodeWriter::processInsets(
31123114
{
31133115
AngleDegrees overhang_angle;
31143116
Ratio speed_factor;
3117+
bool chunk = true;
31153118
};
31163119

31173120
// Create raw speed regions
31183121
const AngleDegrees overhang_step = (90.0 - wall_overhang_angle) / static_cast<double>(overhang_angles_count);
31193122
std::vector<SpeedRegion> speed_regions;
3120-
speed_regions.reserve(overhang_angles_count + 1);
3123+
speed_regions.reserve(overhang_angles_count + 2);
31213124

3122-
speed_regions.push_back(SpeedRegion{ wall_overhang_angle, 1.0_r }); // Initial internal region, always 100% speed factor
3125+
constexpr bool dont_chunk_first = false; // Never merge internal region in order to detect actual overhanging
3126+
speed_regions.push_back(SpeedRegion{ wall_overhang_angle, 1.0_r, dont_chunk_first }); // Initial internal region, always 100% speed factor
31233127

3124-
for (size_t angle_index = 1; angle_index < overhang_angles_count; ++angle_index)
3128+
for (size_t angle_index = 1; angle_index <= overhang_angles_count; ++angle_index)
31253129
{
31263130
const AngleDegrees actual_wall_overhang_angle = wall_overhang_angle + static_cast<double>(angle_index) * overhang_step;
31273131
const Ratio speed_factor = overhang_speed_factors[angle_index - 1];
@@ -3136,7 +3140,7 @@ bool FffGcodeWriter::processInsets(
31363140
| ranges::views::chunk_by(
31373141
[](const auto& region_a, const auto& region_b)
31383142
{
3139-
return region_a.speed_factor == region_b.speed_factor;
3143+
return region_a.chunk && region_b.chunk && region_a.speed_factor == region_b.speed_factor;
31403144
});
31413145

31423146
// If finally necessary, add actual calculated speed regions

src/LayerPlan.cpp

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -568,14 +568,32 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
568568
const double fan_speed,
569569
const bool travel_to_z)
570570
{
571-
const auto add_extrusion_move = [&](const Point3LL& target, const Ratio& overhang_speed_factor = 1.0_r)
571+
const auto add_extrusion_move = [&](const Point3LL& target, const std::optional<size_t> speed_region_index = std::nullopt)
572572
{
573+
const Ratio overhang_speed_factor = speed_region_index.has_value() ? overhang_masks_[speed_region_index.value()].speed_ratio : 1.0_r;
573574
addExtrusionMove(target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z);
574575
};
575576

577+
const auto update_is_overhanging = [this](const Point2LL& target, std::optional<Point2LL> current_position, const bool is_overhanging = false)
578+
{
579+
if (is_overhanging != currently_overhanging_)
580+
{
581+
max_overhang_length_ = std::max(current_overhang_length_, max_overhang_length_);
582+
current_overhang_length_ = 0;
583+
}
584+
585+
if (is_overhanging && current_position.has_value())
586+
{
587+
current_overhang_length_ += vSize(target - current_position.value());
588+
}
589+
590+
currently_overhanging_ = is_overhanging;
591+
};
592+
576593
if (overhang_masks_.empty() || ! last_planned_position_.has_value())
577594
{
578595
// Unable to apply gradual overhanging (probably just disabled), just add the basic extrusion move
596+
update_is_overhanging(p.toPoint2LL(), last_planned_position_);
579597
add_extrusion_move(p);
580598
return;
581599
}
@@ -619,7 +637,13 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
619637
}
620638
};
621639

622-
const std::vector<SVG::Color> colors = { SVG::Color::RED, SVG::Color::GREEN, SVG::Color::BLUE, SVG::Color::YELLOW };
640+
struct SegmentExtrusionMove
641+
{
642+
Point2LL position;
643+
size_t speed_region_index;
644+
};
645+
646+
std::vector<SegmentExtrusionMove> extrusion_moves;
623647

624648
// Now move along segment and split it where we cross speed regions
625649
while (true)
@@ -658,7 +682,7 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
658682

659683
// Move to intersection at current region speed
660684
const Point2LL split_position = start + vector * intersection_parameter;
661-
add_extrusion_move(split_position, overhang_masks_[actual_speed_region_index].speed_ratio);
685+
extrusion_moves.push_back(SegmentExtrusionMove{ split_position, actual_speed_region_index });
662686

663687
// Prepare for next move in different region
664688
actual_speed_region_index = next_speed_region_index;
@@ -667,10 +691,68 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
667691
else
668692
{
669693
// We cross no border, which means we can reach the end of the segment within the current speed region, so we are done
670-
add_extrusion_move(p, overhang_masks_[actual_speed_region_index].speed_ratio);
671-
return;
694+
extrusion_moves.push_back(SegmentExtrusionMove{ p.toPoint2LL(), actual_speed_region_index });
695+
break;
696+
}
697+
}
698+
699+
// Filter out micro-segments
700+
std::vector<SegmentExtrusionMove> extrusion_moves_filtered;
701+
extrusion_moves_filtered.reserve(extrusion_moves.size());
702+
Point2LL current_position = start;
703+
for (const SegmentExtrusionMove& extrusion_move : extrusion_moves | ranges::views::drop_last(1))
704+
{
705+
if (vSize2(extrusion_move.position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
706+
{
707+
extrusion_moves_filtered.push_back(extrusion_move);
708+
}
709+
710+
current_position = extrusion_move.position;
711+
}
712+
713+
if (extrusion_moves_filtered.empty() || vSize2(extrusion_moves.back().position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
714+
{
715+
extrusion_moves_filtered.push_back(extrusion_moves.back());
716+
}
717+
else
718+
{
719+
extrusion_moves_filtered.back().position = extrusion_moves.back().position;
720+
}
721+
722+
// Calculate max consecutive overhanging segment length
723+
current_position = start;
724+
for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered)
725+
{
726+
const bool is_overhanging = extrusion_move.speed_region_index > 0;
727+
update_is_overhanging(extrusion_move.position, current_position, is_overhanging);
728+
current_position = extrusion_move.position;
729+
}
730+
731+
// Merge consecutive sub-segments that in the end have the same speed
732+
std::vector<SegmentExtrusionMove> extrusion_moves_merged;
733+
extrusion_moves_merged.reserve(extrusion_moves_filtered.size());
734+
extrusion_moves_merged.push_back(extrusion_moves_filtered.front());
735+
736+
for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered | ranges::views::drop(1))
737+
{
738+
const Ratio previous_speed_factor = overhang_masks_[extrusion_moves_merged.back().speed_region_index].speed_ratio;
739+
const Ratio next_speed_factor = overhang_masks_[extrusion_move.speed_region_index].speed_ratio;
740+
741+
if (next_speed_factor == previous_speed_factor)
742+
{
743+
extrusion_moves_merged.back().position = extrusion_move.position;
744+
}
745+
else
746+
{
747+
extrusion_moves_merged.push_back(extrusion_move);
672748
}
673749
}
750+
751+
// Finally, add extrusion moves
752+
for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_merged)
753+
{
754+
add_extrusion_move(extrusion_move.position, extrusion_move.speed_region_index);
755+
}
674756
}
675757

676758
template<class PathType>
@@ -2561,7 +2643,11 @@ void LayerPlan::processFanSpeedAndMinimalLayerTime(Point2LL starting_position)
25612643
{
25622644
other_extr_plan_time += extruder_plan.estimates_.getTotalTime();
25632645
}
2564-
maximum_cool_min_layer_time = std::max(maximum_cool_min_layer_time, extruder_plan.fan_speed_layer_time_settings_.cool_min_layer_time);
2646+
2647+
const FanSpeedLayerTimeSettings& settings = extruder_plan.fan_speed_layer_time_settings_;
2648+
const bool apply_minimum_layer_time_overhang = max_overhang_length_ > settings.cool_min_layer_time_overhang_min_segment_length;
2649+
maximum_cool_min_layer_time
2650+
= std::max(maximum_cool_min_layer_time, apply_minimum_layer_time_overhang ? settings.cool_min_layer_time_overhang : settings.cool_min_layer_time);
25652651

25662652
// Modify fan speeds for the first layer(s)
25672653
extruder_plan.processFanSpeedForFirstLayers();

stress_benchmark/resources/001.settings

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ acceleration_support_roof=300
516516
material_print_temp_wait=True
517517
support_roof_angles=[]
518518
machine_gcode_flavor=Griffin
519-
wall_overhang_speed_factor=100
519+
wall_overhang_speed_factors=[100]
520520
jerk_support_infill=12.5
521521
wall_0_wipe_dist=0
522522
jerk_wall_0_roofing=12.5

stress_benchmark/resources/002.settings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ adaptive_layer_height_threshold=0.1
584584
support_interface_height=0.8
585585
support_brim_enable=True
586586
jerk_support_infill=8
587-
wall_overhang_speed_factor=100
587+
wall_overhang_speed_factors=[100]
588588
acceleration_travel=500
589589
support_bottom_material_flow=100
590590
raft_base_extruder_nr=0
@@ -972,7 +972,7 @@ extruder_prime_pos_abs=False
972972
support_tower_maximum_supported_diameter=3.0
973973
support_tree_angle=45
974974
jerk_support_infill=8
975-
wall_overhang_speed_factor=100
975+
wall_overhang_speed_factors=[100]
976976
infill_before_walls=False
977977
material=0
978978
brim_width=8.0

stress_benchmark/resources/003.settings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ adaptive_layer_height_threshold=0.2
585585
support_interface_height=0.96
586586
support_brim_enable=True
587587
jerk_support_infill=12.0
588-
wall_overhang_speed_factor=100
588+
wall_overhang_speed_factors=[100]
589589
acceleration_travel=500
590590
support_bottom_material_flow=95.0
591591
raft_base_extruder_nr=0
@@ -973,7 +973,7 @@ extruder_prime_pos_abs=False
973973
support_tower_maximum_supported_diameter=3.0
974974
support_tree_angle=50
975975
jerk_support_infill=12.0
976-
wall_overhang_speed_factor=100
976+
wall_overhang_speed_factors=[100]
977977
infill_before_walls=False
978978
material=0
979979
brim_width=8.0

stress_benchmark/resources/004.settings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ adaptive_layer_height_threshold=0.2
585585
support_interface_height=0.8
586586
support_brim_enable=True
587587
jerk_support_infill=8
588-
wall_overhang_speed_factor=100
588+
wall_overhang_speed_factors=[100]
589589
acceleration_travel=500
590590
support_bottom_material_flow=100
591591
raft_base_extruder_nr=0
@@ -973,7 +973,7 @@ extruder_prime_pos_abs=False
973973
support_tower_maximum_supported_diameter=3.0
974974
support_tree_angle=55
975975
jerk_support_infill=8
976-
wall_overhang_speed_factor=100
976+
wall_overhang_speed_factors=[100]
977977
infill_before_walls=False
978978
material=0
979979
brim_width=8.0

stress_benchmark/resources/005.settings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ adaptive_layer_height_threshold=0.2
586586
support_interface_height=0.8
587587
support_brim_enable=True
588588
jerk_support_infill=8
589-
wall_overhang_speed_factor=100
589+
wall_overhang_speed_factors=[100]
590590
acceleration_travel=500
591591
support_bottom_material_flow=100
592592
raft_base_extruder_nr=0
@@ -974,7 +974,7 @@ extruder_prime_pos_abs=False
974974
support_tower_maximum_supported_diameter=3.0
975975
support_tree_angle=65.0
976976
jerk_support_infill=8
977-
wall_overhang_speed_factor=100
977+
wall_overhang_speed_factors=[100]
978978
infill_before_walls=False
979979
material=0
980980
brim_width=3

stress_benchmark/resources/006.settings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ adaptive_layer_height_threshold=0.2
586586
support_interface_height=0.8
587587
support_brim_enable=True
588588
jerk_support_infill=8
589-
wall_overhang_speed_factor=100
589+
wall_overhang_speed_factors=[100]
590590
acceleration_travel=500
591591
support_bottom_material_flow=100
592592
raft_base_extruder_nr=0
@@ -974,7 +974,7 @@ extruder_prime_pos_abs=False
974974
support_tower_maximum_supported_diameter=3.0
975975
support_tree_angle=60.0
976976
jerk_support_infill=8
977-
wall_overhang_speed_factor=100
977+
wall_overhang_speed_factors=[100]
978978
infill_before_walls=False
979979
material=0
980980
brim_width=8.0

0 commit comments

Comments
 (0)