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. Cherry-picked from prusa3d/PrusaSlicer@86309ba939 Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
parent
babb84c70a
commit
47ec9b9b06
2 changed files with 37 additions and 26 deletions
|
@ -1,4 +1,10 @@
|
|||
#include <stack>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "PerimeterOrder.hpp"
|
||||
#include "libslic3r/Arachne/utils/ExtrusionJunction.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
|
||||
namespace Slic3r::Arachne::PerimeterOrder {
|
||||
|
||||
|
@ -128,7 +134,7 @@ static std::vector<const PerimeterExtrusion *> ordered_perimeter_extrusions_to_m
|
|||
const Point &extrusion_start_position = extrusion_line.junctions.front().p;
|
||||
const double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm();
|
||||
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_distance_sqr = distance_sqr;
|
||||
is_nearest_closed = extrusion_line.is_closed;
|
||||
|
@ -184,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 double distance_sqr = (current_position - extrusion_start_position).cast<double>().squaredNorm();
|
||||
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_distance_sqr = distance_sqr;
|
||||
is_nearest_closed = external_perimeter_extrusion_line.is_closed;
|
||||
|
@ -219,33 +225,32 @@ static PerimeterExtrusions extract_ordered_perimeter_extrusions(const PerimeterE
|
|||
while (!stack.empty()) {
|
||||
const PerimeterExtrusion *current_extrusion = stack.top();
|
||||
const size_t current_extrusion_idx = current_extrusion - sorted_perimeter_extrusions.data();
|
||||
|
||||
stack.pop();
|
||||
visited[current_extrusion_idx] = true;
|
||||
|
||||
if (visited[current_extrusion_idx])
|
||||
continue;
|
||||
|
||||
if (current_extrusion->nearest_external_perimeter == &perimeter_extrusion)
|
||||
if (current_extrusion->nearest_external_perimeter == &perimeter_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)
|
||||
|
@ -253,7 +258,6 @@ static PerimeterExtrusions extract_ordered_perimeter_extrusions(const PerimeterE
|
|||
}
|
||||
|
||||
const std::vector<size_t> grouped_extrusion_order = order_of_grouped_perimeter_extrusions_to_minimize_distances(Point::Zero(), grouped_extrusions);
|
||||
assert(grouped_extrusion_order.size() == grouped_ordered_extrusions.size());
|
||||
|
||||
PerimeterExtrusions ordered_extrusions;
|
||||
for (size_t order_idx : grouped_extrusion_order) {
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
#ifndef slic3r_GCode_PerimeterOrder_hpp_
|
||||
#define slic3r_GCode_PerimeterOrder_hpp_
|
||||
|
||||
#include <Arachne/utils/ExtrusionLine.hpp>
|
||||
#include <stddef.h>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
|
||||
#include "libslic3r/Arachne/utils/ExtrusionLine.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
|
||||
namespace Slic3r::Arachne::PerimeterOrder {
|
||||
|
||||
|
|
Loading…
Reference in a new issue