diff --git a/src/libslic3r/Arachne/PerimeterOrder.cpp b/src/libslic3r/Arachne/PerimeterOrder.cpp index 01d50feb1..c6c2755a4 100644 --- a/src/libslic3r/Arachne/PerimeterOrder.cpp +++ b/src/libslic3r/Arachne/PerimeterOrder.cpp @@ -1,4 +1,10 @@ +#include +#include +#include + #include "PerimeterOrder.hpp" +#include "libslic3r/Arachne/utils/ExtrusionJunction.hpp" +#include "libslic3r/Point.hpp" namespace Slic3r::Arachne::PerimeterOrder { @@ -128,7 +134,7 @@ static std::vector 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().squaredNorm(); if (distance_sqr < nearest_distance_sqr) { - if (extrusion_line.is_closed || (!extrusion_line.is_closed && nearest_distance_sqr != std::numeric_limits::max()) || (!extrusion_line.is_closed && !is_nearest_closed)) { + if (extrusion_line.is_closed || (!extrusion_line.is_closed && nearest_distance_sqr == std::numeric_limits::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 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().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::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::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 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 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 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 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 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) { diff --git a/src/libslic3r/Arachne/PerimeterOrder.hpp b/src/libslic3r/Arachne/PerimeterOrder.hpp index edb13094f..f8469d917 100644 --- a/src/libslic3r/Arachne/PerimeterOrder.hpp +++ b/src/libslic3r/Arachne/PerimeterOrder.hpp @@ -1,7 +1,14 @@ #ifndef slic3r_GCode_PerimeterOrder_hpp_ #define slic3r_GCode_PerimeterOrder_hpp_ -#include +#include +#include +#include +#include + +#include "libslic3r/Arachne/utils/ExtrusionLine.hpp" +#include "libslic3r/BoundingBox.hpp" +#include "libslic3r/Polygon.hpp" namespace Slic3r::Arachne::PerimeterOrder {