From 73f3b155077d5e7a6fea8853c4caaf85a9dd264c Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Fri, 2 Dec 2022 12:16:14 +0100 Subject: [PATCH] added curvature, fixed bugs, improved point placement --- src/libslic3r/GCode.cpp | 1 + src/libslic3r/GCode/ExtrusionProcessor.hpp | 83 +++++++++++++++++----- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 4fb5da1ae1..ffa90c354b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2705,6 +2705,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::s std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed) { + m_extrusion_quality_estimator.reset_for_next_extrusion(); if (const ExtrusionPath* path = dynamic_cast(&entity)) return this->extrude_path(*path, description, speed); else if (const ExtrusionMultiPath* multipath = dynamic_cast(&entity)) diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 24cc71fcef..afe957b8e5 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -11,6 +11,7 @@ #include "../BoundingBox.hpp" #include "../Polygon.hpp" #include "../ClipperUtils.hpp" +#include "../Flow.hpp" #include #include @@ -96,8 +97,11 @@ class ExtrusionQualityEstimator { AABBTreeLines::LinesDistancer prev_layer_boundary; AABBTreeLines::LinesDistancer next_layer_boundary; + CurvatureEstimator cestim; public: + void reset_for_next_extrusion() { cestim.reset(); } + void prepare_for_new_layer(const std::vector &layers) { std::vector layer_lines; @@ -157,49 +161,90 @@ public: float quality; }; - float flow_width = path.width; - float min_malformation_dist = 0.2; - float peak_malformation_dist = 0.5; + float flow_width = path.width; + float min_malformation_dist = 0.1; + float peak_malformation_dist = 1.0; const Points &original_points = path.polyline.points; std::vector points; - float distance = prev_layer_boundary.signed_distance_from_lines(unscaled(original_points[0])) / flow_width + flow_width * 0.5f; + float distance = prev_layer_boundary.signed_distance_from_lines(unscaled(original_points[0])) / flow_width + 0.5 * flow_width; points.push_back({unscaled(original_points[0]), distance, 1.0f}); for (size_t i = 1; i < original_points.size(); i++) { Vec2d next_point_pos = unscaled(original_points[i]); - float distance_of_next = prev_layer_boundary.signed_distance_from_lines(next_point_pos) / flow_width + flow_width * 0.5f; - // if ((points.back().distance > min_malformation_dist) != - // (distance_of_next > min_malformation_dist)) { // not same sign, so one is grounded, one not - if (true) { + float distance_of_next = prev_layer_boundary.signed_distance_from_lines(next_point_pos) / flow_width + 0.5 * flow_width; + if (points.back().distance < min_malformation_dist != distance_of_next < min_malformation_dist) { // one in air, one not auto intersections = prev_layer_boundary.intersections_with_line({points.back().position, next_point_pos}); for (const auto &intersection : intersections) { points.push_back({intersection, 0.0f, 1.0}); } + points.push_back({next_point_pos, distance_of_next, 1.0}); } + + if (points.back().distance > min_malformation_dist && distance_of_next > min_malformation_dist) { // both in air + double line_len = (points.back().position - next_point_pos).norm(); + if (line_len > 3.0) { + double a0 = std::clamp((0.5 * flow_width + points.back().distance) / line_len, 0.0, 1.0); + double a1 = std::clamp((0.5 * flow_width + distance_of_next) / line_len, 0.0, 1.0); + double t0 = std::min(a0, a1); + double t1 = std::max(a0, a1); + + auto p0 = points.back().position + t0 * (next_point_pos - points.back().position); + auto p0_dist = prev_layer_boundary.signed_distance_from_lines(p0) / flow_width + 0.5 * flow_width; + points.push_back({p0, float(p0_dist), 1.0}); + auto p1 = points.back().position + t1 * (next_point_pos - points.back().position); + auto p1_dist = prev_layer_boundary.signed_distance_from_lines(p1) / flow_width + 0.5 * flow_width; + points.push_back({p1, float(p1_dist), 1.0}); + } + } + points.push_back({next_point_pos, distance_of_next, 1.0}); } for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) { ExtendedPoint &a = points[point_idx]; ExtendedPoint &b = points[point_idx + 1]; - if (b.distance < min_malformation_dist) { - a.quality = 1.0; + + float distance = std::min(a.distance, b.distance); + + int prev_point_idx = point_idx; + while (prev_point_idx > 0) { + prev_point_idx--; + if ((b.position - points[prev_point_idx].position).squaredNorm() > EPSILON) { break; } } - if (b.distance < peak_malformation_dist) { - a.quality = 1.0 - (distance - min_malformation_dist) / (peak_malformation_dist - min_malformation_dist); + + int next_point_index = point_idx; + while (next_point_index < int(points.size()) - 1) { + next_point_index++; + if ((b.position - points[next_point_index].position).squaredNorm() > EPSILON) { break; } + } + + if (prev_point_idx != point_idx && next_point_index != point_idx) { + float distance = (b.position - a.position).norm(); + float alfa = angle(b.position - points[prev_point_idx].position, points[next_point_index].position - b.position); + cestim.add_point(distance, alfa); + } + + if (distance < min_malformation_dist) { + a.quality = 1.0; + cestim.reset(); + } else if (distance < peak_malformation_dist) { + a.quality = 1.0 - (distance - min_malformation_dist) / (peak_malformation_dist - min_malformation_dist); + float curvature_penalty = 0.0f; + float curvature = std::abs(cestim.get_curvature()); + if (curvature > 1.0f) { + curvature_penalty = 1.0f; + } else if (curvature > 0.1f) { + curvature_penalty = fmin(1.0, distance - min_malformation_dist) * curvature; + } + + a.quality -= curvature_penalty; } else { a.quality = 0.0f; } } - // if (points.size() >= 3) { - // points[0].quality = points[1].quality; - // points[points.size()-2].quality = points[points.size()-3].quality; - // } - std::vector result; result.reserve(points.size()); - for (const ExtendedPoint &p : points) { - result.push_back({Point::new_scale(p.position), p.quality}); } + for (const ExtendedPoint &p : points) { result.push_back({Point::new_scale(p.position), std::clamp(p.quality, 0.0f, 1.0f)}); } return result; }