SPE-2387: Order islands to minimize travels between them.

This commit is contained in:
Lukáš Hejl 2024-07-12 13:35:47 +02:00 committed by Lukas Matena
parent d7e32216e8
commit 1f958d17f1
3 changed files with 84 additions and 25 deletions

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
) {
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 : 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;
};
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]; };
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)
out.emplace_back(segment_and_reversal.first);
return out;
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) {
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_ */