From 27ec1980bcf62b8618182e9c6d73aa20452ada0c Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Wed, 18 Dec 2024 21:32:41 +0800 Subject: [PATCH] Arachne: Fix an arithmetic overflow that causing extra points outside plate (#7330) * Arachne: Fix an arithmetic overflow that causing extra points outside the plate (SoftFever/OrcaSlicer#7321) * Better way of avoiding overflow, works in Release mode as well * Fix debug build * Fix build --- src/libslic3r/Arachne/utils/ExtrusionLine.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index ac7b88af833..35233f10751 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -153,10 +153,19 @@ void ExtrusionLine::simplify(const int64_t smallest_line_segment_squared, const // ^ current Point intersection_point; bool has_intersection = Line(previous_previous.p, previous.p).intersection_infinite(Line(current.p, next.p), &intersection_point); + const auto dist_greater = [](const Point& p1, const Point& p2, const int64_t threshold) { + const auto vec = (p1 - p2).cwiseAbs().cast(); + if(vec.x() > threshold || vec.y() > threshold) { + // If this condition is true, the distance is definitely greater than the threshold. + // We don't need to calculate the squared norm at all, which avoid potential arithmetic overflow. + return true; + } + return vec.squaredNorm() > threshold; + }; if (!has_intersection || Line::distance_to_infinite_squared(intersection_point, previous.p, current.p) > double(allowed_error_distance_squared) - || (intersection_point - previous.p).cast().squaredNorm() > smallest_line_segment_squared // The intersection point is way too far from the 'previous' - || (intersection_point - current.p).cast().squaredNorm() > smallest_line_segment_squared) // and 'current' points, so it shouldn't replace 'current' + || dist_greater(intersection_point, previous.p, smallest_line_segment_squared) // The intersection point is way too far from the 'previous' + || dist_greater(intersection_point, current.p, smallest_line_segment_squared)) // and 'current' points, so it shouldn't replace 'current' { // We can't find a better spot for it, but the size of the line is more than 5 micron. // So the only thing we can do here is leave it in...