From 8e38ac234f6f6bb9e80a4d005b10e503dfa61851 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Sun, 13 Apr 2025 17:39:28 +0800 Subject: [PATCH] Fix rare crash when calculating bridge expansion (#9287) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #12469 - crash caused by bridge expansion. Handle a very rare case in which the algorithm picks a wrong polygon for expansion seed. (cherry picked from commit 5f843cc93470c96483abcbd47cf8ee5fe38dffe2) * SPE-2698: Fix crash during regions expansion. (cherry picked from commit a3f75133c8baead6f8d7bb01722a6bfcdc2e9038) --------- Co-authored-by: Martin Šach Co-authored-by: Lukáš Hejl --- src/libslic3r/Algorithm/RegionExpansion.cpp | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Algorithm/RegionExpansion.cpp b/src/libslic3r/Algorithm/RegionExpansion.cpp index ee2a5aaf2a..db127ce207 100644 --- a/src/libslic3r/Algorithm/RegionExpansion.cpp +++ b/src/libslic3r/Algorithm/RegionExpansion.cpp @@ -258,14 +258,33 @@ std::vector wave_seeds( int iseed = 0; for (const ClipperLib_Z::Path &path : segments) { assert(path.size() >= 2); - const ClipperLib_Z::IntPoint &front = path.front(); - const ClipperLib_Z::IntPoint &back = path.back(); + ClipperLib_Z::IntPoint front = path.front(); + ClipperLib_Z::IntPoint back = path.back(); // Both ends of a seed segment are supposed to be inside a single boundary expolygon. // Thus as long as the seed contour is not closed, it should be open at a boundary point. assert((front == back && front.z() >= idx_boundary_end && front.z() < idx_src_end) || //(front.z() < 0 && back.z() < 0)); // Hope that at least one end of an open polyline is clipped by the boundary, thus an intersection point is created. (front.z() < 0 || back.z() < 0)); + + if (front != back && front.z() >= 0 && back.z() >= 0) { + // Very rare case when both endpoints intersect boundary ExPolygons in existing points. + // So the ZFillFunction callback hasn't been called. + continue; + } else + if (front == back && (front.z() < idx_boundary_end)) { + // This should be a very rare exception. + // See https://github.com/prusa3d/PrusaSlicer/issues/12469. + // Segement is open, yet its first point seems to be part of boundary polygon. + // Take the first point with src polygon index. + for (const ClipperLib_Z::IntPoint &point : path) { + if (point.z() >= idx_boundary_end) { + front = point; + back = point; + } + } + } + const Intersection *intersection = nullptr; auto intersection_point_valid = [idx_boundary_end, idx_src_end](const Intersection &is) { return is.first >= 1 && is.first < idx_boundary_end &&