From 8e064659ad1992d8a83227a6240b006f7165a752 Mon Sep 17 00:00:00 2001 From: HanifKoh <76276251+HanifKoh@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:33:12 +0800 Subject: [PATCH] Fix Non-Deterministic Slicing - Order Per-Layer Intersection Lines Canonically (#15563) Fix nondeterministic slicing: order per-layer intersection lines canonically Facet processing in slice_make_lines() is parallel, so the per-layer line order depended on thread scheduling. make_loops() consumes that order for island order and loop start vertices, so the same model could slice to different G-code run to run. Sort each layer's lines by a topology-based key. edge_type and flags are appended to the key purely to break ties: two lines can share every id and endpoint (a Horizontal facet can emit such a pair) and std::sort is not stable, so without them that pair's order would stay thread-dependent. --- src/libslic3r/TriangleMeshSlicer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index 417ca354d3..4ff18165cb 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -607,6 +608,17 @@ static inline std::vector slice_make_lines( } } ); + // Facet processing above is parallel, so per-layer line order depends on thread scheduling, + // and make_loops() derives island order and loop start vertices from it. Sort canonically; + // edge_type and flags only break ties, std::sort being unstable. + tbb::parallel_for(tbb::blocked_range(0, lines.size()), + [&lines](const tbb::blocked_range &range) { + for (size_t i = range.begin(); i < range.end(); ++ i) + std::sort(lines[i].begin(), lines[i].end(), [](const IntersectionLine &l, const IntersectionLine &r) { + return std::make_tuple(l.edge_a_id, l.edge_b_id, l.a_id, l.b_id, l.a.x(), l.a.y(), l.b.x(), l.b.y(), l.edge_type, l.flags) < + std::make_tuple(r.edge_a_id, r.edge_b_id, r.a_id, r.b_id, r.a.x(), r.a.y(), r.b.x(), r.b.y(), r.edge_type, r.flags); + }); + }); return lines; }