From 1968c8b1172db58aca4b889369729735a0ac78e8 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Mon, 17 Mar 2025 18:26:57 +0800 Subject: [PATCH] FIX: adjust the sort for segment intersections and revert the modify of I64dbbcf9e35477b597c4755863f307cf444f50d9 jira: STUDIO-10841 Change-Id: Id6a56372cade4e62f3714aae6892468575298904 --- src/libslic3r/Fill/FillRectilinear.cpp | 63 +++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 20e08bc1b..ffd9a1ce9 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -365,6 +365,66 @@ struct SegmentedIntersectionLine std::vector intersections; }; +static void adjust_sort_for_segment_intersections(std::vector &intersections) +{ + using IntersectionType = SegmentIntersection::SegmentIntersectionType; + std::stack stack; + bool has_out_low = false; + auto is_valid_type = [&stack, &has_out_low](IntersectionType type) { + if (stack.empty()) { + return type == IntersectionType::OUTER_LOW; + } else { + auto top_type = stack.top(); + switch (type) { + case SegmentIntersection::OUTER_LOW: return false; + case SegmentIntersection::OUTER_HIGH: return top_type == IntersectionType::OUTER_LOW; + case SegmentIntersection::INNER_LOW: return top_type != IntersectionType::OUTER_HIGH; + case SegmentIntersection::INNER_HIGH: return top_type == IntersectionType::INNER_LOW; + default: break; + } + return true; + } + }; + + std::vector visited(intersections.size(), false); + std::vector index_group; + for (size_t i = 0; i < intersections.size();) { + if (is_valid_type(intersections[i].type)) { + index_group.clear(); + // std::fill() + if (intersections[i].type == SegmentIntersection::OUTER_LOW || intersections[i].type == SegmentIntersection::INNER_LOW) { + stack.push(intersections[i].type); + } else if (intersections[i].type == SegmentIntersection::OUTER_HIGH || intersections[i].type == SegmentIntersection::INNER_HIGH) { + stack.pop(); + } + ++i; + } else { + visited[i] = true; + for (size_t j = i + 1; j < intersections.size(); ++j) { + if (!visited[j] && abs(intersections[j].pos() - intersections[i].pos()) < scale_(EPSILON)) { index_group.push_back(j); } + } + + if (!index_group.empty()) { + int swap_index = -1; + for (auto index : index_group) { + if (!visited[index]) { + swap_index = index; + visited[index] = true; + break; + } + } + + if (swap_index != -1) { + std::swap(intersections[i], intersections[swap_index]); + continue; + } + } + + ++i; + } + } +} + static SegmentIntersection phony_outer_intersection(SegmentIntersection::SegmentIntersectionType type, coord_t pos) { assert(type == SegmentIntersection::OUTER_LOW || type == SegmentIntersection::OUTER_HIGH); @@ -859,11 +919,12 @@ static std::vector slice_region_by_vertical_lines(con // Sort the intersection points using exact rational arithmetic. //BBS: if the LOW and HIGH has seam y pos, LOW should be first std::sort(sil.intersections.begin(), sil.intersections.end(), [](const SegmentIntersection &l, const SegmentIntersection &r) { - if (abs(l.pos() - r.pos()) < scale_(EPSILON) && l.iContour == r.iContour) + if (l.pos() == r.pos() && l.iContour == r.iContour) return l.type < r.type; return l.pos() < r.pos(); }); + adjust_sort_for_segment_intersections(sil.intersections); // Assign the intersection types, remove duplicate or overlapping intersection points. // When a loop vertex touches a vertical line, intersection point is generated for both segments. // If such two segments are oriented equally, then one of them is removed.