mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-21 05:37:52 -06:00
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 "PerimeterOrder.hpp"
|
||||||
|
#include "libslic3r/Arachne/utils/ExtrusionJunction.hpp"
|
||||||
|
#include "libslic3r/Point.hpp"
|
||||||
|
|
||||||
namespace Slic3r::Arachne::PerimeterOrder {
|
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 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;
|
||||||
|
@ -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 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;
|
||||||
|
@ -219,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)
|
||||||
|
@ -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);
|
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;
|
PerimeterExtrusions ordered_extrusions;
|
||||||
for (size_t order_idx : grouped_extrusion_order) {
|
for (size_t order_idx : grouped_extrusion_order) {
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
#ifndef slic3r_GCode_PerimeterOrder_hpp_
|
#ifndef slic3r_GCode_PerimeterOrder_hpp_
|
||||||
#define 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 {
|
namespace Slic3r::Arachne::PerimeterOrder {
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue