Detection of curled edges to enhance slowdown for overhangs algorithm (#2056)

* Overhang perimeter handling

Updated code to handle overhang perimeters as an overhang and not as a bridge.

* Preparing to add curled extrusions identification

* Porting curling calculations from Prusa Slier 2.6.1

* Prototype 1 - slowdown extended to detect curled edges and further reduce speed

First prototype of the code submitted.

* Working prototype - 2

Code is now finally working - external perimeters are slowed down as needed when there is likelyhood of curling up.

ToDo:
1. Reslicing the model causes the algorithm not to run - need to find where this fails to trigger the call for this.
2. Slowdown of internal perimeters not working yet.

* Updated to use overhang wall speed instead of bridging speed for this algorithm

* Fixed bug in speed calculation and tweaked parameters for high speed printer

Fixed bug in speed calculation and tweaked parameters for high speed printer

* Attempting to fix "set started" not being set

* Parameter tweak after print tests

* Fixed estimation not running when model is re-sliced.

* Removing debug printf statements and fixed threading flag.

* Fixed threading

* Parameter tweaks following print tests

* Made this as an option in the GUI

* Reintroduced handling of bridges as per original design

* UI line toggling when option makes sense to be visible.

* Fixed bug in field visibility & made it default to off

* Code optimisation

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
igiannakas 2023-09-16 15:24:18 +01:00 committed by GitHub
parent bcedb431ab
commit 61437b2c76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 322 additions and 143 deletions

View file

@ -247,6 +247,8 @@ class ExtrusionQualityEstimator
{
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> prev_curled_extrusions;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> next_curled_extrusions;
const PrintObject *current_object;
public:
@ -258,16 +260,22 @@ public:
const PrintObject *object = obj;
prev_layer_boundaries[object] = next_layer_boundaries[object];
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
prev_curled_extrusions[object] = next_curled_extrusions[object];
next_curled_extrusions[object] = AABBTreeLines::LinesDistancer<CurledLine>{layer->curled_lines};
}
std::vector<ProcessedPoint> estimate_extrusion_quality(const ExtrusionPath &path,
const ConfigOptionPercents &overlaps,
const ConfigOptionFloatsOrPercents &speeds,
float ext_perimeter_speed,
float original_speed)
float original_speed,
bool slowdown_for_curled_edges)
{
size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size());
std::vector<std::pair<float, float>> 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 ? (ext_perimeter_speed * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value;
@ -297,6 +305,56 @@ public:
for (size_t i = 0; i < extended_points.size(); i++) {
const ExtendedPoint &curr = extended_points[i];
const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
float artificial_distance_to_curled_lines = 0.0;
if(slowdown_for_curled_edges) {
// The following code artifically increases the distance to provide slowdown for extrusions that are over curled lines
const double dist_limit = 10.0 * path.width;
{
Vec2d middle = 0.5 * (curr.position + next.position);
auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle), scale_(dist_limit));
if (!line_indices.empty()) {
double len = (next.position - curr.position).norm();
// For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line
// The whole segment gets slower unnecesarily. For these long lines, we do additional check whether it is worth slowing down.
// NOTE that this is still quite rough approximation, e.g. we are still checking lines only near the middle point
// TODO maybe split the lines into smaller segments before running this alg? but can be demanding, and GCode will be huge
if (len > 8) {
Vec2d dir = Vec2d(next.position - curr.position) / len;
Vec2d right = Vec2d(-dir.y(), dir.x());
Polygon box_of_influence = {
scaled(Vec2d(curr.position + right * dist_limit)),
scaled(Vec2d(next.position + right * dist_limit)),
scaled(Vec2d(next.position - right * dist_limit)),
scaled(Vec2d(curr.position - right * dist_limit)),
};
double projected_lengths_sum = 0;
for (size_t idx : line_indices) {
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence});
if (inside.empty())
continue;
double projected_length = abs(dir.dot(unscaled(Vec2d((inside.back().b - inside.back().a).cast<double>()))));
projected_lengths_sum += projected_length;
}
if (projected_lengths_sum < 0.4 * len) {
line_indices.clear();
}
}
for (size_t idx : line_indices) {
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
float distance_from_curled = unscaled(line_alg::distance_to(line, Point::new_scale(middle)));
float dist = path.width * (1.0 - (distance_from_curled / dist_limit)) *
(1.0 - (distance_from_curled / dist_limit)) *
(line.curled_height / (path.height * 10.0f)); // max_curled_height_factor from SupportSpotGenerator
artificial_distance_to_curled_lines = std::max(artificial_distance_to_curled_lines, dist);
}
}
}
}
auto calculate_speed = [&speed_sections, &original_speed](float distance) {
float final_speed;
@ -316,10 +374,15 @@ public:
}
return final_speed;
};
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
if(slowdown_for_curled_edges) {
float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
extrusion_speed = std::min(curled_speed, extrusion_speed); // adjust extrusion speed based on what is smallest - the calculated overhang speed or the artificial curled speed
}
float overlap = std::min(1 - curr.distance * width_inv, 1 - next.distance * width_inv);
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
}
return processed_points;