94 lines
5.3 KiB
Diff
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 ®ion : regions)
|
|
if (region.left_neighbors.empty())
|
|
queue.emplace_back(®ion);
|
|
@@ -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;
|