SPE-1950: Optimization of computation complexity of perimeter ordering for Arachne generator.

The previous implementation during the grouping of perimeters using depth-first searches unnecessarily searched nodes that had no impact on grouping, which significantly increased the search space.
This commit is contained in:
Lukáš Hejl 2024-07-08 14:21:15 +02:00 committed by Lukas Matena
parent 82fb648cb7
commit 86309ba939

View File

@ -134,7 +134,7 @@ static std::vector<const PerimeterExtrusion *> ordered_perimeter_extrusions_to_m
const Point &extrusion_start_position = extrusion_line.junctions.front().p; const Point &extrusion_start_position = extrusion_line.junctions.front().p;
const double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm(); const double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm();
if (distance_sqr < nearest_distance_sqr) { if (distance_sqr < nearest_distance_sqr) {
if (extrusion_line.is_closed || (!extrusion_line.is_closed && nearest_distance_sqr != std::numeric_limits<double>::max()) || (!extrusion_line.is_closed && !is_nearest_closed)) { if (extrusion_line.is_closed || (!extrusion_line.is_closed && nearest_distance_sqr == std::numeric_limits<double>::max()) || (!extrusion_line.is_closed && !is_nearest_closed)) {
nearest_extrusion_idx = extrusion_idx; nearest_extrusion_idx = extrusion_idx;
nearest_distance_sqr = distance_sqr; nearest_distance_sqr = distance_sqr;
is_nearest_closed = extrusion_line.is_closed; is_nearest_closed = extrusion_line.is_closed;
@ -190,7 +190,7 @@ static std::vector<size_t> order_of_grouped_perimeter_extrusions_to_minimize_dis
const Point &extrusion_start_position = external_perimeter_extrusion_line.junctions.front().p; const Point &extrusion_start_position = external_perimeter_extrusion_line.junctions.front().p;
const double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm(); const double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm();
if (distance_sqr < nearest_distance_sqr) { if (distance_sqr < nearest_distance_sqr) {
if (external_perimeter_extrusion_line.is_closed || (!external_perimeter_extrusion_line.is_closed && nearest_distance_sqr != std::numeric_limits<double>::max()) || (!external_perimeter_extrusion_line.is_closed && !is_nearest_closed)) { if (external_perimeter_extrusion_line.is_closed || (!external_perimeter_extrusion_line.is_closed && nearest_distance_sqr == std::numeric_limits<double>::max()) || (!external_perimeter_extrusion_line.is_closed && !is_nearest_closed)) {
nearest_grouped_extrusions_idx = grouped_extrusion_idx; nearest_grouped_extrusions_idx = grouped_extrusion_idx;
nearest_distance_sqr = distance_sqr; nearest_distance_sqr = distance_sqr;
is_nearest_closed = external_perimeter_extrusion_line.is_closed; is_nearest_closed = external_perimeter_extrusion_line.is_closed;
@ -225,33 +225,32 @@ static PerimeterExtrusions extract_ordered_perimeter_extrusions(const PerimeterE
while (!stack.empty()) { while (!stack.empty()) {
const PerimeterExtrusion *current_extrusion = stack.top(); const PerimeterExtrusion *current_extrusion = stack.top();
const size_t current_extrusion_idx = current_extrusion - sorted_perimeter_extrusions.data(); const size_t current_extrusion_idx = current_extrusion - sorted_perimeter_extrusions.data();
stack.pop(); stack.pop();
visited[current_extrusion_idx] = true;
if (visited[current_extrusion_idx]) if (current_extrusion->nearest_external_perimeter == &perimeter_extrusion) {
continue;
if (current_extrusion->nearest_external_perimeter == &perimeter_extrusion)
grouped_extrusions.back().extrusions.emplace_back(current_extrusion); grouped_extrusions.back().extrusions.emplace_back(current_extrusion);
if (current_extrusion->adjacent_perimeter_extrusions.size() == 1) {
const PerimeterExtrusion *adjacent_extrusion = current_extrusion->adjacent_perimeter_extrusions.front();
stack.push(adjacent_extrusion);
} else if (current_extrusion->adjacent_perimeter_extrusions.size() > 1) {
// When there is more than one available candidate, then order candidates to minimize distances between
// candidates and also to minimize the distance from the current_position.
std::vector<const PerimeterExtrusion *> available_candidates;
for (const PerimeterExtrusion *adjacent_extrusion : current_extrusion->adjacent_perimeter_extrusions) {
if (const size_t adjacent_extrusion_idx = adjacent_extrusion - sorted_perimeter_extrusions.data(); !visited[adjacent_extrusion_idx])
available_candidates.emplace_back(adjacent_extrusion);
}
std::vector<const PerimeterExtrusion *> adjacent_extrusions = ordered_perimeter_extrusions_to_minimize_distances(Point::Zero(), available_candidates);
std::reverse(adjacent_extrusions.begin(), adjacent_extrusions.end());
for (const PerimeterExtrusion *adjacent_extrusion : adjacent_extrusions)
stack.push(adjacent_extrusion);
} }
visited[current_extrusion_idx] = true; std::vector<const PerimeterExtrusion *> available_candidates;
for (const PerimeterExtrusion *adjacent_extrusion : current_extrusion->adjacent_perimeter_extrusions) {
const size_t adjacent_extrusion_idx = adjacent_extrusion - sorted_perimeter_extrusions.data();
if (!visited[adjacent_extrusion_idx] && !adjacent_extrusion->is_external_perimeter() && adjacent_extrusion->nearest_external_perimeter == &perimeter_extrusion) {
available_candidates.emplace_back(adjacent_extrusion);
}
}
if (available_candidates.size() == 1) {
stack.push(available_candidates.front());
} else if (available_candidates.size() > 1) {
// When there is more than one available candidate, then order candidates to minimize distances between
// candidates and also to minimize the distance from the current_position.
std::vector<const PerimeterExtrusion *> adjacent_extrusions = ordered_perimeter_extrusions_to_minimize_distances(Point::Zero(), available_candidates);
for (auto extrusion_it = adjacent_extrusions.rbegin(); extrusion_it != adjacent_extrusions.rend(); ++extrusion_it) {
stack.push(*extrusion_it);
}
}
} }
if (!external_perimeters_first) if (!external_perimeters_first)