Merge branch 'lh_extrusion_order' (#11658)

This commit is contained in:
Lukas Matena 2025-02-17 11:15:26 +01:00
commit bc36722d4b
4 changed files with 96 additions and 30 deletions

View File

@ -162,9 +162,14 @@ struct GroupedPerimeterExtrusions
};
// Returns vector of indexes that represent the order of grouped extrusions in grouped_extrusions.
static std::vector<size_t> order_of_grouped_perimeter_extrusions_to_minimize_distances(Point current_position, std::vector<GroupedPerimeterExtrusions> grouped_extrusions) {
static std::vector<size_t> order_of_grouped_perimeter_extrusions_to_minimize_distances(const std::vector<GroupedPerimeterExtrusions> &grouped_extrusions, Point current_position) {
std::vector<size_t> grouped_extrusions_sorted_indices(grouped_extrusions.size());
std::iota(grouped_extrusions_sorted_indices.begin(), grouped_extrusions_sorted_indices.end(), 0);
// Ensure that holes will be placed before contour and open extrusions before the closed one.
std::sort(grouped_extrusions.begin(), grouped_extrusions.end(), [](const GroupedPerimeterExtrusions &l, const GroupedPerimeterExtrusions &r) -> bool {
std::sort(grouped_extrusions_sorted_indices.begin(), grouped_extrusions_sorted_indices.end(), [&grouped_extrusions = std::as_const(grouped_extrusions)](const size_t l_idx, const size_t r_idx) -> bool {
const GroupedPerimeterExtrusions &l = grouped_extrusions[l_idx];
const GroupedPerimeterExtrusions &r = grouped_extrusions[r_idx];
return (l.external_perimeter_extrusion->is_contour() < r.external_perimeter_extrusion->is_contour()) ||
(l.external_perimeter_extrusion->is_contour() == r.external_perimeter_extrusion->is_contour() && l.external_perimeter_extrusion->is_closed() < r.external_perimeter_extrusion->is_closed());
});
@ -181,8 +186,9 @@ static std::vector<size_t> order_of_grouped_perimeter_extrusions_to_minimize_dis
bool is_nearest_closed = false;
// First we order all holes and then we start ordering contours.
const size_t grouped_extrusion_end = grouped_extrusions_order.size() < holes_cnt ? holes_cnt: grouped_extrusions.size();
for (size_t grouped_extrusion_idx = 0; grouped_extrusion_idx < grouped_extrusion_end; ++grouped_extrusion_idx) {
const size_t grouped_extrusions_sorted_indices_end = (grouped_extrusions_order.size() < holes_cnt) ? holes_cnt : grouped_extrusions_sorted_indices.size();
for (size_t grouped_extrusions_sorted_idx = 0; grouped_extrusions_sorted_idx < grouped_extrusions_sorted_indices_end; ++grouped_extrusions_sorted_idx) {
const size_t grouped_extrusion_idx = grouped_extrusions_sorted_indices[grouped_extrusions_sorted_idx];
if (already_selected[grouped_extrusion_idx])
continue;
@ -200,6 +206,7 @@ static std::vector<size_t> order_of_grouped_perimeter_extrusions_to_minimize_dis
grouped_extrusions_order.emplace_back(nearest_grouped_extrusions_idx);
already_selected[nearest_grouped_extrusions_idx] = true;
const GroupedPerimeterExtrusions &nearest_grouped_extrusions = grouped_extrusions[nearest_grouped_extrusions_idx];
const ExtrusionLine &last_extrusion_line = nearest_grouped_extrusions.extrusions.back()->extrusion;
current_position = get_end_position(last_extrusion_line);
@ -257,7 +264,7 @@ static PerimeterExtrusions extract_ordered_perimeter_extrusions(const PerimeterE
std::reverse(grouped_extrusions.back().extrusions.begin(), grouped_extrusions.back().extrusions.end());
}
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(grouped_extrusions, Point::Zero());
PerimeterExtrusions ordered_extrusions;
for (size_t order_idx : grouped_extrusion_order) {

View File

@ -208,6 +208,20 @@ std::vector<InfillRange> extract_infill_ranges(
return result;
}
// Returns LayerIslands ordered by the shortest distance.
std::vector<std::reference_wrapper<const LayerIsland>> get_ordered_islands(
const LayerSlice &lslice,
const std::optional<Point> &previous_position
) {
std::vector<std::reference_wrapper<const LayerIsland>> islands_to_order;
for (const LayerIsland &island : lslice.islands) {
islands_to_order.emplace_back(island);
}
chain_and_reorder_layer_islands(islands_to_order, previous_position.has_value() ? std::addressof(*previous_position) : nullptr);
return islands_to_order;
}
std::vector<IslandExtrusions> extract_island_extrusions(
const LayerSlice &lslice,
const Print &print,
@ -218,18 +232,20 @@ std::vector<IslandExtrusions> extract_island_extrusions(
const unsigned extruder_id,
std::optional<Point> &previous_position
) {
const auto should_pick_infill = [&should_pick_extrusion](const ExtrusionEntityCollection &eec, const PrintRegion &region) {
return should_pick_extrusion(eec, region) && eec.role() != ExtrusionRole::Ironing;
};
std::vector<std::reference_wrapper<const LayerIsland>> ordered_islands = get_ordered_islands(lslice, previous_position);
std::vector<IslandExtrusions> result;
for (const LayerIsland &island : lslice.islands) {
for (const LayerIsland &island : ordered_islands) {
const LayerRegion &layerm = *layer.get_region(island.perimeters.region());
// PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be
// unique to a PrintObject, they would not identify the content of PrintRegion
// accross the whole print uniquely. Translate to a Print specific PrintRegion.
const PrintRegion &region = print.get_print_region(layerm.region().print_region_id());
const auto should_pick_infill = [&should_pick_extrusion](const ExtrusionEntityCollection &eec, const PrintRegion &region) {
return should_pick_extrusion(eec, region) && eec.role() != ExtrusionRole::Ironing;
};
result.push_back(IslandExtrusions{&region});
IslandExtrusions &island_extrusions{result.back()};
island_extrusions.infill_first = print.config().infill_first;
@ -243,9 +259,9 @@ std::vector<IslandExtrusions> extract_island_extrusions(
} else {
island_extrusions.perimeters = extract_perimeter_extrusions(print, layer, island, should_pick_extrusion, extruder_id, offset, previous_position, smooth_path);
island_extrusions.infill_ranges = {extract_infill_ranges(
island_extrusions.infill_ranges = extract_infill_ranges(
print, layer, island, offset, previous_position, should_pick_infill, smooth_path, extruder_id
)};
);
}
}
return result;
@ -261,13 +277,14 @@ std::vector<InfillRange> extract_ironing_extrusions(
const unsigned extruder_id,
std::optional<Point> &previous_position
) {
std::vector<InfillRange> result;
for (const LayerIsland &island : lslice.islands) {
const auto should_pick_ironing = [&should_pick_extrusion](const auto &eec, const auto &region) {
return should_pick_extrusion(eec, region) && eec.role() == ExtrusionRole::Ironing;
};
std::vector<std::reference_wrapper<const LayerIsland>> ordered_islands = get_ordered_islands(lslice, previous_position);
std::vector<InfillRange> result;
for (const LayerIsland &island : ordered_islands) {
const std::vector<InfillRange> ironing_ranges{extract_infill_ranges(
print, layer, island, offset, previous_position, should_pick_ironing, smooth_path, extruder_id
)};

View File

@ -1110,23 +1110,30 @@ void chain_and_reorder_extrusion_paths(std::vector<ExtrusionPath> &extrusion_pat
reorder_extrusion_paths(extrusion_paths, chain_extrusion_paths(extrusion_paths, start_near));
}
std::vector<size_t> chain_points(const Points &points, Point *start_near)
std::vector<size_t> chain_points(const Points &points, const Point *start_near)
{
auto segment_end_point = [&points](size_t idx, bool /* first_point */) -> const Point& { return points[idx]; };
auto segment_end_point = [&points](size_t idx, bool /* first_point */) -> const Point & {
return points[idx];
};
std::vector<std::pair<size_t, bool>> ordered = chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, points.size(), start_near);
std::vector<size_t> out;
out.reserve(ordered.size());
for (auto &segment_and_reversal : ordered)
for (auto &segment_and_reversal : ordered) {
out.emplace_back(segment_and_reversal.first);
}
return out;
}
std::vector<size_t> chain_expolygons(const ExPolygons &expolygons, Point *start_near)
std::vector<size_t> chain_expolygons(const ExPolygons &expolygons)
{
Points ordering_points;
ordering_points.reserve(expolygons.size());
for (const ExPolygon &ex : expolygons)
for (const ExPolygon &ex : expolygons) {
ordering_points.push_back(ex.contour.first_point());
}
return chain_points(ordering_points);
}
@ -2102,4 +2109,33 @@ Polylines chain_lines(const std::vector<Line> &lines, const double point_distanc
return out;
}
std::vector<size_t> chain_layer_islands(const std::vector<std::reference_wrapper<const LayerIsland>> &islands, const Point *start_near)
{
Points ordering_points;
ordering_points.reserve(islands.size());
for (const LayerIsland &island : islands) {
ordering_points.push_back(island.boundary.contour.first_point());
}
return chain_points(ordering_points, start_near);
}
void reorder_layer_islands(std::vector<std::reference_wrapper<const LayerIsland>> &islands, const std::vector<size_t> &chain)
{
assert(islands.size() == chain.size());
std::vector<std::reference_wrapper<const LayerIsland>> islands_out;
islands_out.reserve(islands.size());
for (size_t island_idx : chain) {
islands_out.emplace_back(islands[island_idx]);
}
islands.swap(islands_out);
}
void chain_and_reorder_layer_islands(std::vector<std::reference_wrapper<const LayerIsland>> &islands, const Point *start_near)
{
reorder_layer_islands(islands, chain_layer_islands(islands, start_near));
}
} // namespace Slic3r

View File

@ -27,13 +27,14 @@ class Line;
}
class ExPolygon;
struct LayerIsland;
using ExPolygons = std::vector<ExPolygon>;
// Used by chain_expolygons()
std::vector<size_t> chain_points(const Points &points, Point *start_near = nullptr);
std::vector<size_t> chain_points(const Points &points, const Point *start_near = nullptr);
// Used to give layer islands a print order.
std::vector<size_t> chain_expolygons(const ExPolygons &expolygons, Point *start_near = nullptr);
std::vector<size_t> chain_expolygons(const ExPolygons &expolygons);
// Chain extrusion entities by a shortest distance. Returns the ordered extrusions together with a "reverse" flag.
// Set input "reversed" to true if the vector of "entities" is to be considered to be reversed once already.
@ -68,6 +69,11 @@ std::vector<const PrintInstance*> chain_print_object_instances(const Print &pr
// Chain lines into polylines.
Polylines chain_lines(const std::vector<Line> &lines, const double point_distance_epsilon);
// Chain and reorder layer islands by the shortest distance.
std::vector<size_t> chain_layer_islands(const std::vector<std::reference_wrapper<const LayerIsland>> &islands, const Point *start_near = nullptr);
void reorder_layer_islands(std::vector<std::reference_wrapper<const LayerIsland>> &islands, const std::vector<size_t> &chain);
void chain_and_reorder_layer_islands(std::vector<std::reference_wrapper<const LayerIsland>> &islands, const Point *start_near = nullptr);
} // namespace Slic3r
#endif /* slic3r_ShortestPath_hpp_ */