Skip to content

Commit 20090e8

Browse files
committed
Generate multiple overhang areas for different speeds
CURA-11966
1 parent e994b6d commit 20090e8

File tree

4 files changed

+71
-29
lines changed

4 files changed

+71
-29
lines changed

include/LayerPlan.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ class LayerPlan : public NoCopy
6060
#endif
6161

6262
public:
63+
struct OverhangMask
64+
{
65+
Shape mask;
66+
Ratio speed_ratio;
67+
};
68+
6369
const PathConfigStorage configs_storage_; //!< The line configs for this layer for each feature type
6470
const coord_t z_;
6571
coord_t final_travel_z_;
@@ -115,7 +121,8 @@ class LayerPlan : public NoCopy
115121
Comb* comb_;
116122
coord_t comb_move_inside_distance_; //!< Whenever using the minimum boundary for combing it tries to move the coordinates inside by this distance after calculating the combing.
117123
Shape bridge_wall_mask_; //!< The regions of a layer part that are not supported, used for bridging
118-
Shape overhang_mask_; //!< The regions of a layer part where the walls overhang
124+
std::vector<OverhangMask>
125+
overhang_masks_; //!< The regions of a layer part where the walls overhang, calculated for multiple overhang angles. The latter is the most overhanging.
119126
Shape seam_overhang_mask_; //!< The regions of a layer part where the walls overhang, specifically as defined for the seam
120127
Shape roofing_mask_; //!< The regions of a layer part where the walls are exposed to the air
121128

@@ -295,11 +302,11 @@ class LayerPlan : public NoCopy
295302
void setBridgeWallMask(const Shape& polys);
296303

297304
/*!
298-
* Set overhang_mask.
305+
* Set overhang_masks.
299306
*
300-
* \param polys The overhung areas of the part currently being processed that will require modified print settings
307+
* \param masks The overhung areas of the part currently being processed that will require modified print settings
301308
*/
302-
void setOverhangMask(const Shape& polys);
309+
void setOverhangMasks(const std::vector<OverhangMask>& masks);
303310

304311
/*!
305312
* Set seam_overhang_mask.

src/FffGcodeWriter.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,18 +3082,33 @@ bool FffGcodeWriter::processInsets(
30823082

30833083
const auto get_overhang_region = [&](const AngleDegrees overhang_angle) -> Shape
30843084
{
3085-
if (overhang_angle >= 90)
3086-
{
3087-
return Shape(); // keep empty to disable overhang detection
3088-
}
30893085
// the overhang mask is set to the area of the current part's outline minus the region that is considered to be supported
30903086
// the supported region is made up of those areas that really are supported by either model or support on the layer below
30913087
// expanded to take into account the overhang angle, the greater the overhang angle, the larger the supported area is
30923088
// considered to be
30933089
const coord_t overhang_width = layer_height * std::tan(overhang_angle / (180 / std::numbers::pi));
30943090
return part.outline.offset(-half_outer_wall_width).difference(outlines_below.offset(10 + overhang_width - half_outer_wall_width)).offset(10);
30953091
};
3096-
gcode_layer.setOverhangMask(get_overhang_region(mesh.settings.get<AngleDegrees>("wall_overhang_angle")));
3092+
3093+
// Build overhang masks for all the overhang speeds
3094+
std::vector<LayerPlan::OverhangMask> overhang_masks;
3095+
const auto overhang_speed_factors = mesh.settings.get<std::vector<Ratio>>("wall_overhang_speed_factors");
3096+
const size_t overhang_angles_count = overhang_speed_factors.size();
3097+
if (overhang_angles_count > 0)
3098+
{
3099+
const auto wall_overhang_angle = mesh.settings.get<AngleDegrees>("wall_overhang_angle");
3100+
if (wall_overhang_angle < 90.0)
3101+
{
3102+
const AngleDegrees overhang_step = (90.0 - wall_overhang_angle) / static_cast<double>(overhang_angles_count);
3103+
for (size_t angle_index = 0; angle_index < overhang_angles_count; ++angle_index)
3104+
{
3105+
const AngleDegrees actual_wall_overhang_angle = wall_overhang_angle + static_cast<double>(angle_index) * overhang_step;
3106+
overhang_masks.emplace_back(get_overhang_region(actual_wall_overhang_angle), overhang_speed_factors[angle_index]);
3107+
}
3108+
}
3109+
}
3110+
gcode_layer.setOverhangMasks(overhang_masks);
3111+
30973112
gcode_layer.setSeamOverhangMask(get_overhang_region(mesh.settings.get<AngleDegrees>("seam_overhang_angle")));
30983113

30993114
const auto roofing_mask_fn = [&]() -> Shape
@@ -3125,7 +3140,7 @@ bool FffGcodeWriter::processInsets(
31253140
// clear to disable use of bridging settings
31263141
gcode_layer.setBridgeWallMask(Shape());
31273142
// clear to disable overhang detection
3128-
gcode_layer.setOverhangMask(Shape());
3143+
gcode_layer.setOverhangMasks({});
31293144
// clear to disable overhang detection
31303145
gcode_layer.setSeamOverhangMask(Shape());
31313146
// clear to disable use of roofing settings

src/LayerPlan.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ GCodePath* LayerPlan::getLatestPathWithConfig(
5757
{
5858
return &paths.back();
5959
}
60-
paths.emplace_back(GCodePath{ .z_offset = z_offset,
61-
.config = config,
62-
.mesh = current_mesh_,
63-
.space_fill_type = space_fill_type,
64-
.flow = flow,
65-
.width_factor = width_factor,
66-
.spiralize = spiralize,
67-
.speed_factor = speed_factor });
60+
paths.emplace_back(
61+
GCodePath{ .z_offset = z_offset,
62+
.config = config,
63+
.mesh = current_mesh_,
64+
.space_fill_type = space_fill_type,
65+
.flow = flow,
66+
.width_factor = width_factor,
67+
.spiralize = spiralize,
68+
.speed_factor = speed_factor });
6869

6970
GCodePath* ret = &paths.back();
7071
ret->skip_agressive_merge_hint = mode_skip_agressive_merge_;
@@ -724,14 +725,15 @@ void LayerPlan::addWallLine(
724725
double distance_to_bridge_start,
725726
const bool travel_to_z)
726727
{
727-
const coord_t min_line_len = 5; // we ignore lines less than 5um long
728-
const double acceleration_segment_len = MM2INT(1); // accelerate using segments of this length
729-
const double acceleration_factor = 0.75; // must be < 1, the larger the value, the slower the acceleration
730-
const bool spiralize = false;
728+
constexpr coord_t min_line_len = 5; // we ignore lines less than 5um long
729+
constexpr double acceleration_segment_len = MM2INT(1); // accelerate using segments of this length
730+
constexpr double acceleration_factor = 0.75; // must be < 1, the larger the value, the slower the acceleration
731+
constexpr bool spiralize = false;
731732

732733
const coord_t min_bridge_line_len = settings.get<coord_t>("bridge_wall_min_length");
733734
const Ratio bridge_wall_coast = settings.get<Ratio>("bridge_wall_coast");
734735
const Ratio overhang_speed_factor = settings.get<Ratio>("wall_overhang_speed_factor");
736+
const auto overhang_speed_factors = settings.get<std::vector<int>>("wall_overhang_speed_factors");
735737

736738
Point3LL cur_point = p0;
737739

@@ -1322,7 +1324,7 @@ std::vector<LayerPlan::PathCoasting>
13221324

13231325
for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse
13241326
| ranges::views::chunk_by(
1325-
[](const auto&path_a, const auto&path_b)
1327+
[](const auto& path_a, const auto& path_b)
13261328
{
13271329
return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath();
13281330
}))
@@ -1948,9 +1950,11 @@ void LayerPlan::addLinesInGivenOrder(
19481950

19491951
bool LayerPlan::segmentIsOnOverhang(const Point3LL& p0, const Point3LL& p1) const
19501952
{
1951-
const OpenPolyline segment{ p0.toPoint2LL(), p1.toPoint2LL() };
1952-
const OpenLinesSet intersected_lines = overhang_mask_.intersection(OpenLinesSet{ segment });
1953-
return ! intersected_lines.empty() && (static_cast<double>(intersected_lines.length()) / segment.length()) > 0.5;
1953+
// const OpenPolyline segment{ p0.toPoint2LL(), p1.toPoint2LL() };
1954+
// const OpenLinesSet intersected_lines = overhang_mask_.intersection(OpenLinesSet{ segment });
1955+
// return ! intersected_lines.empty() && (static_cast<double>(intersected_lines.length()) / segment.length()) > 0.5;
1956+
1957+
return false;
19541958
}
19551959

19561960
void LayerPlan::sendLineTo(const GCodePath& path, const Point3LL& position, const double extrude_speed)
@@ -3154,9 +3158,9 @@ void LayerPlan::setBridgeWallMask(const Shape& polys)
31543158
bridge_wall_mask_ = polys;
31553159
}
31563160

3157-
void LayerPlan::setOverhangMask(const Shape& polys)
3161+
void LayerPlan::setOverhangMasks(const std::vector<OverhangMask>& masks)
31583162
{
3159-
overhang_mask_ = polys;
3163+
overhang_masks_ = masks;
31603164
}
31613165

31623166
void LayerPlan::setSeamOverhangMask(const Shape& polys)

src/settings/Settings.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Acceleration Settings::get<Acceleration>(const std::string& key) const
183183
template<>
184184
Ratio Settings::get<Ratio>(const std::string& key) const
185185
{
186-
return get<double>(key) / 100.0; // The settings are all in percentages, but we need to interpret them as radians.
186+
return get<double>(key) / 100.0; // The settings are all in percentages, but we need to interpret them as ratios.
187187
}
188188

189189
template<>
@@ -787,6 +787,22 @@ std::vector<double> Settings::get<std::vector<double>>(const std::string& key) c
787787
return result;
788788
}
789789

790+
template<>
791+
std::vector<Ratio> Settings::get<std::vector<Ratio>>(const std::string& key) const
792+
{
793+
auto values_double = get<std::vector<double>>(key);
794+
795+
// The settings are all in percentages, but we need to interpret them as ratios.
796+
std::vector<Ratio> result;
797+
result.reserve(values_double.size());
798+
for (const auto& value_double : values_double)
799+
{
800+
result.emplace_back(value_double / 100.0);
801+
}
802+
803+
return result;
804+
}
805+
790806
template<>
791807
std::vector<int> Settings::get<std::vector<int>>(const std::string& key) const
792808
{

0 commit comments

Comments
 (0)