From 28cd3ac212f9d2a67538dc5998ce6883d37defb6 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Tue, 18 Jul 2023 17:28:22 +0200 Subject: [PATCH] new step for overhangs --- src/libslic3r/GCode/ExtrusionProcessor.hpp | 86 ++++++++++++++++++++++ src/libslic3r/Print.hpp | 3 +- src/libslic3r/PrintObject.cpp | 35 +++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index f6f75bef30..1deb1cd067 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -211,6 +211,92 @@ std::vector estimate_points_properties(const POINTS return points; } +void calculate_and_split_overhanging_extrusions(ExtrusionPath &path, + AABBTreeLines::LinesDistancer prev_layer_polygon, + AABBTreeLines::LinesDistancer prev_layer_curled_lines) +{ + std::vector extended_points = estimate_points_properties(path.polyline.points, + prev_layer_polygon, path.width()); + + + 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]; + + // The following code artifically increases the distance to provide slowdown for extrusions that are over curled lines + float artificial_distance_to_curled_lines = 0.0; + const double dist_limit = 10.0 * path.width(); + { + Vec2d middle = 0.5 * (curr.position + next.position); + auto line_indices = prev_layer_curled_lines.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_layer_curled_lines.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())))); + 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_layer_curled_lines.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 interpolate_speed = [](const std::map &values, float distance) { + auto upper_dist = values.lower_bound(distance); + if (upper_dist == values.end()) { + return values.rbegin()->second; + } + if (upper_dist == values.begin()) { + return upper_dist->second; + } + + auto lower_dist = std::prev(upper_dist); + float t = (distance - lower_dist->first) / (upper_dist->first - lower_dist->first); + return (1.0f - t) * lower_dist->second + t * upper_dist->second; + }; + + float extrusion_speed = std::min(interpolate_speed(speed_sections, curr.distance), interpolate_speed(speed_sections, next.distance)); + float curled_base_speed = interpolate_speed(speed_sections, artificial_distance_to_curled_lines); + float final_speed = std::min(curled_base_speed, extrusion_speed); + float fan_speed = std::min(interpolate_speed(fan_speed_sections, curr.distance), + interpolate_speed(fan_speed_sections, next.distance)); + + processed_points.push_back({scaled(curr.position), final_speed, int(fan_speed)}); + } + return processed_points; +} + + struct ProcessedPoint { Point p; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 0600b02fff..f16befc964 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -67,7 +67,7 @@ enum PrintStep : unsigned int { enum PrintObjectStep : unsigned int { posSlice, posPerimeters, posPrepareInfill, - posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posEstimateCurledExtrusions, posCount, + posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posEstimateCurledExtrusions, posCalculateOverhangingPerimeters, posCount, }; // A PrintRegion object represents a group of volumes to print @@ -376,6 +376,7 @@ private: void generate_support_spots(); void generate_support_material(); void estimate_curled_extrusions(); + void calculate_overhanging_perimeters(); void slice_volumes(); // Has any support (not counting the raft). diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ebf6e8d48c..522a61375e 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -4,6 +4,7 @@ #include "Exception.hpp" #include "Flow.hpp" #include "KDTreeIndirect.hpp" +#include "Line.hpp" #include "Point.hpp" #include "Polygon.hpp" #include "Polyline.hpp" @@ -533,6 +534,40 @@ void PrintObject::estimate_curled_extrusions() } } +void PrintObject::calculate_overhanging_perimeters() +{ + if (this->set_started(posCalculateOverhangingPerimeters)) { + std::unordered_set regions_with_dynamic_overhangs; + for (const PrintRegion *pr : this->print()->m_print_regions) { + if (pr->config().enable_dynamic_overhang_speeds.getBool()) { + regions_with_dynamic_overhangs.insert(pr); + } + } + if (!regions_with_dynamic_overhangs.empty()) { + BOOST_LOG_TRIVIAL(debug) << "Calculating overhanging perimeters - start"; + m_print->set_status(89, _u8L("Calculating overhanging perimeters")); + + std::unordered_map> curled_lines; + for (const Layer *l : this->layers()) { + curled_lines[l->id()] = AABBTreeLines::LinesDistancer{l->curled_lines}; + } + + for (Layer *l : this->layers()) { + for (const LayerRegion *layer_region : l->regions()) { + if (regions_with_dynamic_overhangs.find(layer_region->m_region) == regions_with_dynamic_overhangs.end()) { + continue; + } + + } + } + + m_print->throw_if_canceled(); + BOOST_LOG_TRIVIAL(debug) << "Calculating overhanging perimeters - end"; + } + this->set_done(posCalculateOverhangingPerimeters); + } +} + std::pair PrintObject::prepare_adaptive_infill_data( const std::vector> &surfaces_w_bottom_z) const {