From 72a25e7ad0949653a5feb3499af9584f4b5f2b81 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Tue, 20 Dec 2022 17:04:31 +0100 Subject: [PATCH] use new extrusion quality estimator function in support spot generator; fix issue with local support points and incorrect distance sign; --- src/libslic3r/AABBTreeLines.hpp | 68 +++++---- src/libslic3r/GCode/ExtrusionProcessor.hpp | 61 +++++--- src/libslic3r/GCode/SeamPlacer.cpp | 4 +- src/libslic3r/PerimeterGenerator.cpp | 4 +- src/libslic3r/SupportSpotsGenerator.cpp | 158 +++++++++++---------- src/libslic3r/SupportSpotsGenerator.hpp | 2 +- 6 files changed, 171 insertions(+), 126 deletions(-) diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 55ce9a0c80..7938337d83 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -117,18 +117,18 @@ inline std::tuple coordinate_aligned_ray_hit_count(size_t } template -inline std::vector get_intersections_with_line(size_t node_idx, - const TreeType &tree, - const std::vector &lines, - const LineType &line, - const typename TreeType::BoundingBox &line_bb) +inline std::vector> get_intersections_with_line(size_t node_idx, + const TreeType &tree, + const std::vector &lines, + const LineType &line, + const typename TreeType::BoundingBox &line_bb) { const auto &node = tree.node(node_idx); assert(node.is_valid()); if (node.is_leaf()) { VectorType intersection_pt; if (line_alg::intersection(line, lines[node.idx], &intersection_pt)) { - return {intersection_pt}; + return {std::pair(intersection_pt, node_idx)}; } else { return {}; } @@ -140,17 +140,17 @@ inline std::vector get_intersections_with_line(size_t assert(node_left.is_valid()); assert(node_right.is_valid()); - std::vector result; + std::vector> result; if (node_left.bbox.intersects(line_bb)) { - std::vector intersections = get_intersections_with_line(left_node_idx, tree, lines, - line, line_bb); + std::vector> intersections = + get_intersections_with_line(left_node_idx, tree, lines, line, line_bb); result.insert(result.end(), intersections.begin(), intersections.end()); } if (node_right.bbox.intersects(line_bb)) { - std::vector intersections = get_intersections_with_line(right_node_idx, tree, lines, - line, line_bb); + std::vector> intersections = + get_intersections_with_line(right_node_idx, tree, lines, line, line_bb); result.insert(result.end(), intersections.begin(), intersections.end()); } @@ -263,9 +263,13 @@ inline int point_outside_closed_contours(const std::vector &lines, con } template -inline std::vector get_intersections_with_line(const std::vector &lines, const TreeType &tree, const LineType &line) +inline std::vector> get_intersections_with_line(const std::vector &lines, + const TreeType &tree, + const LineType &line) { - if (tree.empty()) { return {}; } + if (tree.empty()) { + return {}; + } auto line_bb = typename TreeType::BoundingBox(line.a, line.a); line_bb.extend(line.b); @@ -274,15 +278,16 @@ inline std::vector get_intersections_with_line(const std::vector::value, typename LineType::Scalar, double>::type; - std::vector> points_with_sq_distance{}; - for (const VectorType &p : intersections) { - points_with_sq_distance.emplace_back((p - line.a).template cast().squaredNorm(), p); + std::vector>> points_with_sq_distance{}; + for (const auto &p : intersections) { + points_with_sq_distance.emplace_back((p.first - line.a).template cast().squaredNorm(), p); } std::sort(points_with_sq_distance.begin(), points_with_sq_distance.end(), - [](const std::pair &left, std::pair &right) { - return left.first < right.first; - }); - for (size_t i = 0; i < points_with_sq_distance.size(); i++) { intersections[i] = points_with_sq_distance[i].second; } + [](const std::pair> &left, + std::pair> &right) { return left.first < right.first; }); + for (size_t i = 0; i < points_with_sq_distance.size(); i++) { + intersections[i] = points_with_sq_distance[i].second; + } } return intersections; @@ -290,10 +295,11 @@ inline std::vector get_intersections_with_line(const std::vector class LinesDistancer { -private: - std::vector lines; +public: using Scalar = typename LineType::Scalar; using Floating = typename std::conditional::value, Scalar, double>::type; +private: + std::vector lines; AABBTreeIndirect::Tree<2, Scalar> tree; public: @@ -313,23 +319,29 @@ public: int outside(const Vec<2, Scalar> &point) const { return point_outside_closed_contours(lines, tree, point); } // negative sign means inside - std::tuple> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const + template + std::tuple> distance_from_lines_extra(const Vec<2, Scalar> &point) const { size_t nearest_line_index_out = size_t(-1); Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero(); Vec<2, Floating> p = point.template cast(); auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out); - if (distance < 0) { return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; } + if (distance < 0) { + return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; + } distance = sqrt(distance); - distance *= outside(point); + + if (SIGNED_DISTANCE) { + distance *= outside(point); + } return {distance, nearest_line_index_out, nearest_point_out}; } - Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const + template Floating distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const { - auto [dist, idx, np] = signed_distance_from_lines_extra(point); + auto [dist, idx, np] = distance_from_lines_extra(point); return dist; } @@ -338,7 +350,7 @@ public: return all_lines_in_radius(this->lines, this->tree, point, radius * radius); } - template std::vector> intersections_with_line(const LineType &line) const + template std::vector, size_t>> intersections_with_line(const LineType &line) const { return get_intersections_with_line>(lines, tree, line); } diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index a0495dd588..eeffe75542 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -39,9 +39,9 @@ public: void add_point(float distance, float angle) { total_distance += distance; - total_curvature += std::abs(angle); + total_curvature += angle; distances.push_back(distance); - angles.push_back(std::abs(angle)); + angles.push_back(angle); while (distances.size() > 1 && total_distance > window_size) { total_distance -= distances.front(); @@ -53,8 +53,6 @@ public: float get_curvature() const { - if (total_distance < EPSILON) { return 0.0; } - return total_curvature / window_size; } @@ -70,7 +68,7 @@ public: class CurvatureEstimator { static const size_t sliders_count = 2; - SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{1.5}, {3.0}}; + SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{4.0}, {12.0}}; public: void add_point(float distance, float angle) @@ -102,45 +100,69 @@ struct ExtendedPoint float curvature; }; -template -std::vector estimate_points_properties(const std::vector

&extrusion_points, +template +std::vector estimate_points_properties(const std::vector

&input_points, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, - float flow_width) + float flow_width, + float max_line_length = -1.0f) { - if (extrusion_points.empty()) return {}; - float boundary_offset = PREV_LAYER_BOUNDARY_ONLY ? 0.5 * flow_width : 0.0f; + using AABBScalar = typename AABBTreeLines::LinesDistancer::Scalar; + if (input_points.empty()) + return {}; + float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f; CurvatureEstimator cestim; float min_malformation_dist = 0.55 * flow_width; + auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; + + std::vector

extrusion_points; + { + if (max_line_length <= 0) { + extrusion_points = input_points; + } else { + extrusion_points.reserve(input_points.size() * 2); + for (size_t i = 0; i + 1 < input_points.size(); i++) { + const P &curr = input_points[i]; + const P &next = input_points[i + 1]; + extrusion_points.push_back(curr); + auto len = maybe_unscale(next - curr).squaredNorm(); + double t = sqrt((max_line_length * max_line_length) / len); + size_t new_point_count = 1.0 / (t + EPSILON); + for (size_t j = 1; j < new_point_count + 1; j++) { + extrusion_points.push_back(curr * (1.0 - j * t) + next * (j * t)); + } + } + extrusion_points.push_back(input_points.back()); + } + } std::vector points; points.reserve(extrusion_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1)); - auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; { ExtendedPoint start_point{maybe_unscale(extrusion_points.front())}; - auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(start_point.position); + auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra(start_point.position.cast()); start_point.distance = distance + boundary_offset; start_point.nearest_prev_layer_line = nearest_line; points.push_back(start_point); } for (size_t i = 1; i < extrusion_points.size(); i++) { ExtendedPoint next_point{maybe_unscale(extrusion_points[i])}; - auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(next_point.position); + auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra(next_point.position.cast()); next_point.distance = distance + boundary_offset; next_point.nearest_prev_layer_line = nearest_line; if (ADD_INTERSECTIONS && ((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) { const ExtendedPoint &prev_point = points.back(); - auto intersections = unscaled_prev_layer.template intersections_with_line(L{prev_point.position, next_point.position}); + auto intersections = unscaled_prev_layer.template intersections_with_line(L{prev_point.position.cast(), next_point.position.cast()}); for (const auto &intersection : intersections) { - points.emplace_back(intersection, boundary_offset); + points.emplace_back(intersection.first.template cast(), boundary_offset, intersection.second); } } points.push_back(next_point); } - if (PREV_LAYER_BOUNDARY_ONLY && ADD_INTERSECTIONS) { + if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) { std::vector new_points; new_points.reserve(points.size() * 2); new_points.push_back(points.front()); @@ -159,12 +181,12 @@ std::vector estimate_points_properties(const std::vector

if (t0 < 1.0) { auto p0 = curr.position + t0 * (next.position - curr.position); - auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p0); + auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra(p0.cast()); new_points.push_back(ExtendedPoint{p0, float(p0_dist + boundary_offset), p0_near_l}); } if (t1 > 0.0) { auto p1 = curr.position + t1 * (next.position - curr.position); - auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p1); + auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra(p1.cast()); new_points.push_back(ExtendedPoint{p1, float(p1_dist + boundary_offset), p1_near_l}); } } @@ -194,7 +216,6 @@ std::vector estimate_points_properties(const std::vector

float distance = (prev.position - a.position).norm(); float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position); cestim.add_point(distance, alfa); - if (CONCAVITY_RESETS_CURVATURE && alfa < 0.0) { cestim.reset(); } } if (a.distance < min_malformation_dist) { cestim.reset(); } @@ -244,7 +265,7 @@ public: [](const std::pair &a, const std::pair &b) { return a.first < b.first; }); std::vector extended_points = - estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); + estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); std::vector processed_points; processed_points.reserve(extended_points.size()); diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index c92ff82121..6858557216 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1071,7 +1071,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) for (SeamCandidate &perimeter_point : layers[layer_idx].points) { Vec2f point = Vec2f { perimeter_point.position.head<2>() }; if (prev_layer_distancer.get() != nullptr) { - perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast()) + perimeter_point.overhang = prev_layer_distancer->distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width - tan(SeamPlacer::overhang_angle_threshold) * po->layers()[layer_idx]->height; @@ -1080,7 +1080,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam) - perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast()) + perimeter_point.embedded_distance = current_layer_distancer->distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width; } } diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index c700c45f83..f77c4c43a4 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -664,11 +664,11 @@ bool paths_touch(const ExtrusionPath &path_one, const ExtrusionPath &path_two, d AABBTreeLines::LinesDistancer lines_two{path_two.as_polyline().lines()}; for (size_t pt_idx = 0; pt_idx < path_one.polyline.size(); pt_idx++) { - if (std::abs(lines_two.signed_distance_from_lines(path_one.polyline.points[pt_idx])) < limit_distance) { return true; } + if (lines_two.distance_from_lines(path_one.polyline.points[pt_idx]) < limit_distance) { return true; } } for (size_t pt_idx = 0; pt_idx < path_two.polyline.size(); pt_idx++) { - if (std::abs(lines_one.signed_distance_from_lines(path_two.polyline.points[pt_idx])) < limit_distance) { return true; } + if (lines_one.distance_from_lines(path_two.polyline.points[pt_idx]) < limit_distance) { return true; } } return false; } diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 3d061269ae..98dfca0cdf 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -3,6 +3,7 @@ #include "ExPolygon.hpp" #include "ExtrusionEntity.hpp" #include "ExtrusionEntityCollection.hpp" +#include "GCode/ExtrusionProcessor.hpp" #include "Line.hpp" #include "Point.hpp" #include "Polygon.hpp" @@ -13,13 +14,16 @@ #include "tbb/blocked_range.h" #include "tbb/blocked_range2d.h" #include "tbb/parallel_reduce.h" +#include #include #include +#include #include #include #include #include #include +#include #include #include "AABBTreeLines.hpp" @@ -41,12 +45,14 @@ namespace Slic3r { class ExtrusionLine { public: - ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), len(0.0f), origin_entity(nullptr) {} - ExtrusionLine(const Vec2f &a, const Vec2f &b, const ExtrusionEntity *origin_entity) - : a(a), b(b), len((a - b).norm()), origin_entity(origin_entity) + ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), origin_entity(nullptr) {} + ExtrusionLine(const Vec2f &a, const Vec2f &b, float len, const ExtrusionEntity *origin_entity) + : a(a), b(b), len(len), origin_entity(origin_entity) {} - float length() { return (a - b).norm(); } + ExtrusionLine(const Vec2f &a, const Vec2f &b) + : a(a), b(b), len((a-b).norm()), origin_entity(nullptr) + {} bool is_external_perimeter() const { @@ -60,7 +66,8 @@ public: const ExtrusionEntity *origin_entity; bool support_point_generated = false; - float malformation = 0.0f; + float form_quality = 1.0f; + float curled_up_height = 0.0f; static const constexpr int Dim = 2; using Scalar = Vec2f::Scalar; @@ -205,7 +212,6 @@ std::vector to_short_lines(const ExtrusionEntity *e, float length Polyline pl = e->as_polyline(); std::vector lines; lines.reserve(pl.points.size() * 1.5f); - lines.emplace_back(unscaled(pl.points[0]).cast(), unscaled(pl.points[0]).cast(), e); for (int point_idx = 0; point_idx < int(pl.points.size()) - 1; ++point_idx) { Vec2f start = unscaled(pl.points[point_idx]).cast(); Vec2f next = unscaled(pl.points[point_idx + 1]).cast(); @@ -217,87 +223,84 @@ std::vector to_short_lines(const ExtrusionEntity *e, float length for (int i = 0; i < lines_count; ++i) { Vec2f a(start + v * (i * step_size)); Vec2f b(start + v * ((i + 1) * step_size)); - lines.emplace_back(a, b, e); + lines.emplace_back(a, b, (a-b).norm(), e); } } return lines; } -std::vector check_extrusion_entity_stability(const ExtrusionEntity *entity, - const LayerRegion *layer_region, - const LD &prev_layer_lines, - const Params ¶ms) +std::vector check_extrusion_entity_stability(const ExtrusionEntity *entity, + const LayerRegion *layer_region, + const LD &prev_layer_lines, + const AABBTreeLines::LinesDistancer &prev_layer_boundary, + const Params ¶ms) { if (entity->is_collection()) { std::vector checked_lines_out; checked_lines_out.reserve(prev_layer_lines.get_lines().size() / 3); for (const auto *e : static_cast(entity)->entities) { - auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, params); + auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, prev_layer_boundary, params); checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end()); } return checked_lines_out; } else { // single extrusion path, with possible varying parameters if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { return {}; } - std::vector lines = to_short_lines(entity, params.bridge_distance); - - ExtrusionPropertiesAccumulator bridging_acc{}; - ExtrusionPropertiesAccumulator malformation_acc{}; - bridging_acc.add_distance(params.bridge_distance + 1.0f); const float flow_width = get_flow_width(layer_region, entity->role()); - float min_malformation_dist = flow_width - params.malformation_overlap_factor.first * flow_width; - float max_malformation_dist = flow_width - params.malformation_overlap_factor.second * flow_width; - for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) { - ExtrusionLine ¤t_line = lines[line_idx]; - if (line_idx + 1 == lines.size() && current_line.b != lines.begin()->a) { - bridging_acc.add_distance(params.bridge_distance + 1.0f); - } - float curr_angle = 0; - if (line_idx + 1 < lines.size()) { - const Vec2f v1 = current_line.b - current_line.a; - const Vec2f v2 = lines[line_idx + 1].b - lines[line_idx + 1].a; - curr_angle = angle(v1, v2); - } - bridging_acc.add_angle(curr_angle); - // malformation in concave angles does not happen - malformation_acc.add_angle(std::max(0.0f, curr_angle)); - if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); } + std::vector annotated_points = estimate_points_properties(entity->as_polyline().points, + prev_layer_lines, flow_width, + params.bridge_distance); - auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b); - if (dist_from_prev_layer < flow_width) { - bridging_acc.reset(); - } else { - bridging_acc.add_distance(current_line.len); + std::vector lines_out; + lines_out.reserve(annotated_points.size()); + float bridged_distance = annotated_points.front().position != annotated_points.back().position ? (params.bridge_distance + 1.0f) : + 0.0f; + for (size_t i = 0; i < annotated_points.size(); ++i) { + ExtendedPoint &curr_point = annotated_points[i]; + float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; + ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), + curr_point.position.cast(), line_len, entity}; + + ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ? + prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) : + ExtrusionLine{}; + + float sign = prev_layer_boundary.distance_from_lines(curr_point.position) - 0.5f * flow_width < 0.0f ? -1.0f : 1.0f; + curr_point.distance *= sign; + + if (curr_point.distance > 0.9f * flow_width) { + line_out.form_quality = 0.7f; + bridged_distance += line_len; // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports. - bool in_layer_dist_condition = bridging_acc.distance > - params.bridge_distance / (1.0f + (bridging_acc.max_curvature * - params.bridge_distance_decrease_by_curvature_factor / PI)); - bool between_layers_condition = dist_from_prev_layer > max_malformation_dist; - if (in_layer_dist_condition && between_layers_condition) { - current_line.support_point_generated = true; - bridging_acc.reset(); + bool in_layer_dist_condition = bridged_distance > + params.bridge_distance / (1.0f + std::abs(curr_point.curvature) * + params.bridge_distance_decrease_by_curvature_factor); + if (in_layer_dist_condition) { + line_out.support_point_generated = true; + bridged_distance = 0.0f; } + } else if (curr_point.distance > flow_width * (0.8 + std::clamp(curr_point.curvature, -0.2f, 0.2f))) { + bridged_distance += line_len; + line_out.form_quality = nearest_prev_layer_line.form_quality - + std::abs(curr_point.curvature); + if (line_out.form_quality < 0) { + line_out.support_point_generated = true; + line_out.form_quality = 0.7f; + } + } else { + bridged_distance = 0.0f; } - // malformation propagation from below - if (fabs(dist_from_prev_layer) < 2.0f * flow_width) { - const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx); - current_line.malformation += 0.85 * nearest_line.malformation; - } - // current line maformation - if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) { - float factor = std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) / - (max_malformation_dist - min_malformation_dist); - malformation_acc.add_distance(current_line.len); - current_line.malformation += layer_region->layer()->height * factor * (2.0f + 3.0f * (malformation_acc.max_curvature / PI)); - current_line.malformation = std::min(current_line.malformation, - float(layer_region->layer()->height * params.max_malformation_factor)); - } else { - malformation_acc.reset(); + line_out.curled_up_height = 0.8 * nearest_prev_layer_line.curled_up_height; + if (curr_point.distance > 0.6 * flow_width && curr_point.distance < 0.9 * flow_width && curr_point.curvature > 0.0) { + line_out.curled_up_height = layer_region->layer()->height * (0.6f + std::min(1.0f, curr_point.curvature)); } + + lines_out.push_back(line_out); } - return lines; + + return lines_out; } } @@ -474,7 +477,7 @@ public: float movement_force = params.max_acceleration * mass; float extruder_conflict_force = params.standard_extruder_conflict_force + - std::min(extruded_line.malformation, 1.0f) * params.malformations_additive_conflict_extruder_force; + std::min(extruded_line.curled_up_height, 1.0f) * params.malformations_additive_conflict_extruder_force; // section for bed calculations { @@ -756,6 +759,15 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) const LayerSlice &slice = layer->lslices_ex.at(slice_idx); ObjectPart &part = active_object_parts.access(prev_slice_idx_to_object_part_mapping[slice_idx]); SliceConnection &weakest_conn = prev_slice_idx_to_weakest_connection[slice_idx]; + + std::vector boundary_lines; + for (const auto &link : slice.overlaps_below) { + auto ls = to_unscaled_linesf({layer->lower_layer->lslices[link.slice_idx]}); + boundary_lines.insert(boundary_lines.end(), ls.begin(), ls.end()); + } + AABBTreeLines::LinesDistancer boundary{std::move(boundary_lines)}; + + std::vector current_slice_ext_perims_lines{}; current_slice_ext_perims_lines.reserve(prev_layer_ext_perim_lines.get_lines().size() / layer->lslices_ex.size()); #ifdef DETAILED_DEBUG_LOGS @@ -791,7 +803,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx]; if (entity->role() == erBridgeInfill) { for (const ExtrusionLine &bridge : - check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines, params)) { + check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,boundary, params)) { if (bridge.support_point_generated) { reckon_new_support_point(create_support_point_position(bridge.b), -EPSILON, Vec2f::Zero()); } @@ -804,7 +816,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) for (const auto &perimeter_idx : island.perimeters) { const ExtrusionEntity *entity = perimeter_region->perimeters().entities[perimeter_idx]; std::vector perims = check_extrusion_entity_stability(entity, perimeter_region, - prev_layer_ext_perim_lines, params); + prev_layer_ext_perim_lines,boundary, params); for (const ExtrusionLine &perim : perims) { if (perim.support_point_generated) { reckon_new_support_point(create_support_point_position(perim.b), -EPSILON, Vec2f::Zero()); @@ -818,13 +830,13 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) float unchecked_dist = params.min_distance_between_support_points + 1.0f; for (const ExtrusionLine &line : current_slice_ext_perims_lines) { - if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.malformation < 0.3f) || line.len == 0) { + if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.curled_up_height < 0.3f) || line.len == 0) { unchecked_dist += line.len; } else { unchecked_dist = line.len; Vec2f pivot_site_search_point = Vec2f(line.b + (line.b - line.a).normalized() * 300.0f); auto [dist, nidx, - nearest_point] = current_slice_lines_distancer.signed_distance_from_lines_extra(pivot_site_search_point); + nearest_point] = current_slice_lines_distancer.distance_from_lines_extra(pivot_site_search_point); Vec3f support_point = create_support_point_position(nearest_point); auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, bottom_z, params); if (force > 0) { reckon_new_support_point(support_point, force, (line.b - line.a).normalized()); } @@ -909,25 +921,25 @@ struct LayerCurlingEstimator malformation_acc.add_angle(std::max(0.0f, curr_angle)); if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); } - auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b); + auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.distance_from_lines_extra(current_line.b); if (fabs(dist_from_prev_layer) < 2.0f * flow_width) { const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx); - current_line.malformation += 0.9 * nearest_line.malformation; + current_line.curled_up_height += 0.9 * nearest_line.curled_up_height; } if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) { float factor = 0.5f + 0.5f * std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) / (max_malformation_dist - min_malformation_dist); malformation_acc.add_distance(current_line.len); - current_line.malformation += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI)); - current_line.malformation = std::min(current_line.malformation, float(l->height * params.max_malformation_factor)); + current_line.curled_up_height += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI)); + current_line.curled_up_height = std::min(current_line.curled_up_height, float(l->height * params.max_malformation_factor)); } else { malformation_acc.reset(); } } for (const ExtrusionLine &line : extrusion_lines) { - if (line.malformation > 0.3f) { l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); } + if (line.curled_up_height > 0.3f) { l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); } } prev_layer_lines = LD(extrusion_lines); } @@ -955,7 +967,7 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float supports_fl for (int point_idx = 0; point_idx < int(pl.points.size() - 1); ++point_idx) { Vec2f start = unscaled(pl.points[point_idx]).cast(); Vec2f next = unscaled(pl.points[point_idx + 1]).cast(); - ExtrusionLine line{start, next, extrusion}; + ExtrusionLine line{start, next, (start - next).norm(), extrusion}; extrusion_lines.push_back(line); } } diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index fa6761d345..6f5c2a7468 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -27,7 +27,7 @@ struct Params { // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2] const float bridge_distance = 12.0f; //mm - const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) ) + const float bridge_distance_decrease_by_curvature_factor = 10.0f; // allowed bridge distance = bridge_distance / (1 + this factor * curvature ) const std::pair malformation_overlap_factor = std::pair { 0.50, -0.1 }; const float max_malformation_factor = 10.0f;