java-topology/defects/prusaslicer-0004/patch/prusaslicer-0004.patch

94 lines
5.3 KiB
Diff

# UNDF: UNDF-2026-000001207
--- a/src/libslic3r/Fill/FillRectilinear.cpp
+++ b/src/libslic3r/Fill/FillRectilinear.cpp
@@ -2235,6 +2235,8 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
// Queue of regions, which have their left neighbors already printed.
std::vector<MonotonicRegion*> queue;
queue.reserve(regions.size());
+ // O(1) membership check — avoids std::find(queue) which is O(queue.size()) = O(R).
+ std::vector<bool> in_queue(regions.size(), false);
for (MonotonicRegion &region : regions)
if (region.left_neighbors.empty())
queue.emplace_back(&region);
@@ -2247,6 +2249,8 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
auto left_neighbors_unprocessed_initial = left_neighbors_unprocessed;
auto queue_initial = queue;
+ // Snapshot in_queue for ant colony resets below.
+ auto in_queue_initial = in_queue;
std::vector<MonotonicRegionLink> path, best_path;
path.reserve(regions.size());
@@ -2341,6 +2345,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
queue = queue_initial;
left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
+ in_queue = in_queue_initial;
assert(validate_unprocessed());
// Pick the last of the queue.
MonotonicRegionLink path_end { queue.back(), false };
queue.pop_back();
+ in_queue[path_end.region - regions.data()] = false;
-- left_neighbors_unprocessed[path_end.region - regions.data()];
@@ -2380,11 +2385,13 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
// Move the other right neighbors with satisified constraints to the queue.
for (MonotonicRegion *next : region.right_neighbors)
- if (-- left_neighbors_unprocessed[next - regions.data()] == 1 && next_candidate.region != next)
+ if (-- left_neighbors_unprocessed[next - regions.data()] == 1 && next_candidate.region != next) {
queue.emplace_back(next);
+ in_queue[next - regions.data()] = true;
+ }
if (from_queue) {
// Remove the selected path from the queue.
- auto it = std::find(queue.begin(), queue.end(), next_candidate.region);
+ size_t idx = next_candidate.region - regions.data();
+ auto it = std::find(queue.begin(), queue.end(), next_candidate.region); // still needed for swap-and-pop
assert(it != queue.end());
*it = queue.back();
queue.pop_back();
+ in_queue[idx] = false;
}
// Extend the path.
assert(next_candidate.region);
@@ -2417,6 +2424,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
// Iteration of the ant colony ants.
queue = queue_initial;
left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
+ in_queue = in_queue_initial;
MonotonicRegionLink path_end;
{
@@ -2432,6 +2440,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
int first_idx = std::uniform_int_distribution<>(0, int(queue.size()) - 1)(rng);
path_end = { queue[first_idx], false };
queue[first_idx] = queue.back();
+ in_queue[path_end.region - regions.data()] = false;
queue.pop_back();
-- left_neighbors_unprocessed[path_end.region - regions.data()];
}
@@ -2469,6 +2479,8 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
next_candidates.emplace_back(NextCandidate{ next, &path1, &path1, path1.visibility, false });
next_candidates.emplace_back(NextCandidate{ next, &path2, &path2, path2.visibility, true });
+ // Track newly eligible regions that will enter the queue below.
}
int num_direct_neighbors = int(next_candidates.size());
// Add the best-next from queue to candidates.
@@ -2507,17 +2519,24 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
// Move the other right neighbors with satisified constraints to the queue.
for (std::vector<NextCandidate>::iterator it_next_candidate = next_candidates.begin(); it_next_candidate != next_candidates.begin() + num_direct_neighbors; ++ it_next_candidate)
- if ((queue.empty() || it_next_candidate->region != queue.back()) && it_next_candidate->region != take_path->region)
+ if ((queue.empty() || it_next_candidate->region != queue.back()) && it_next_candidate->region != take_path->region) {
queue.emplace_back(it_next_candidate->region);
+ in_queue[it_next_candidate->region - regions.data()] = true;
+ }
if (size_t(take_path - next_candidates.begin()) >= num_direct_neighbors) {
// Remove the selected path from the queue.
- auto it = std::find(queue.begin(), queue.end(), take_path->region);
+ size_t idx2 = take_path->region - regions.data();
+ auto it = std::find(queue.begin(), queue.end(), take_path->region); // still needed for swap-and-pop
assert(it != queue.end());
*it = queue.back();
queue.pop_back();
+ in_queue[idx2] = false;
}
// Extend the path.
MonotonicRegion *next_region = take_path->region;