mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 06:19:00 +08:00
SPE-2387: Order islands to minimize travels between them.
This commit is contained in:
parent
d7e32216e8
commit
1f958d17f1
@ -208,6 +208,20 @@ std::vector<InfillRange> extract_infill_ranges(
|
|||||||
return result;
|
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(
|
std::vector<IslandExtrusions> extract_island_extrusions(
|
||||||
const LayerSlice &lslice,
|
const LayerSlice &lslice,
|
||||||
const Print &print,
|
const Print &print,
|
||||||
@ -218,18 +232,20 @@ std::vector<IslandExtrusions> extract_island_extrusions(
|
|||||||
const unsigned extruder_id,
|
const unsigned extruder_id,
|
||||||
std::optional<Point> &previous_position
|
std::optional<Point> &previous_position
|
||||||
) {
|
) {
|
||||||
|
const auto should_pick_infill = [&should_pick_extrusion](const ExtrusionEntityCollection &eec, const PrintRegion ®ion) {
|
||||||
|
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;
|
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());
|
const LayerRegion &layerm = *layer.get_region(island.perimeters.region());
|
||||||
// PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be
|
// PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be
|
||||||
// unique to a PrintObject, they would not identify the content of PrintRegion
|
// unique to a PrintObject, they would not identify the content of PrintRegion
|
||||||
// accross the whole print uniquely. Translate to a Print specific PrintRegion.
|
// accross the whole print uniquely. Translate to a Print specific PrintRegion.
|
||||||
const PrintRegion ®ion = print.get_print_region(layerm.region().print_region_id());
|
const PrintRegion ®ion = print.get_print_region(layerm.region().print_region_id());
|
||||||
|
|
||||||
const auto should_pick_infill = [&should_pick_extrusion](const ExtrusionEntityCollection &eec, const PrintRegion ®ion) {
|
|
||||||
return should_pick_extrusion(eec, region) && eec.role() != ExtrusionRole::Ironing;
|
|
||||||
};
|
|
||||||
|
|
||||||
result.push_back(IslandExtrusions{®ion});
|
result.push_back(IslandExtrusions{®ion});
|
||||||
IslandExtrusions &island_extrusions{result.back()};
|
IslandExtrusions &island_extrusions{result.back()};
|
||||||
island_extrusions.infill_first = print.config().infill_first;
|
island_extrusions.infill_first = print.config().infill_first;
|
||||||
@ -243,9 +259,9 @@ std::vector<IslandExtrusions> extract_island_extrusions(
|
|||||||
} else {
|
} else {
|
||||||
island_extrusions.perimeters = extract_perimeter_extrusions(print, layer, island, should_pick_extrusion, extruder_id, offset, previous_position, smooth_path);
|
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
|
print, layer, island, offset, previous_position, should_pick_infill, smooth_path, extruder_id
|
||||||
)};
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -261,13 +277,14 @@ std::vector<InfillRange> extract_ironing_extrusions(
|
|||||||
const unsigned extruder_id,
|
const unsigned extruder_id,
|
||||||
std::optional<Point> &previous_position
|
std::optional<Point> &previous_position
|
||||||
) {
|
) {
|
||||||
|
const auto should_pick_ironing = [&should_pick_extrusion](const auto &eec, const auto ®ion) {
|
||||||
|
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;
|
std::vector<InfillRange> result;
|
||||||
|
for (const LayerIsland &island : ordered_islands) {
|
||||||
for (const LayerIsland &island : lslice.islands) {
|
|
||||||
const auto should_pick_ironing = [&should_pick_extrusion](const auto &eec, const auto ®ion) {
|
|
||||||
return should_pick_extrusion(eec, region) && eec.role() == ExtrusionRole::Ironing;
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<InfillRange> ironing_ranges{extract_infill_ranges(
|
const std::vector<InfillRange> ironing_ranges{extract_infill_ranges(
|
||||||
print, layer, island, offset, previous_position, should_pick_ironing, smooth_path, extruder_id
|
print, layer, island, offset, previous_position, should_pick_ironing, smooth_path, extruder_id
|
||||||
)};
|
)};
|
||||||
|
@ -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));
|
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 & {
|
||||||
std::vector<std::pair<size_t, bool>> ordered = chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, points.size(), start_near);
|
return points[idx];
|
||||||
std::vector<size_t> out;
|
};
|
||||||
out.reserve(ordered.size());
|
|
||||||
for (auto &segment_and_reversal : ordered)
|
std::vector<std::pair<size_t, bool>> ordered = chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, points.size(), start_near);
|
||||||
out.emplace_back(segment_and_reversal.first);
|
std::vector<size_t> out;
|
||||||
return 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;
|
Points ordering_points;
|
||||||
ordering_points.reserve(expolygons.size());
|
ordering_points.reserve(expolygons.size());
|
||||||
for (const ExPolygon &ex : expolygons)
|
for (const ExPolygon &ex : expolygons) {
|
||||||
ordering_points.push_back(ex.contour.first_point());
|
ordering_points.push_back(ex.contour.first_point());
|
||||||
|
}
|
||||||
|
|
||||||
return chain_points(ordering_points);
|
return chain_points(ordering_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2102,4 +2109,33 @@ Polylines chain_lines(const std::vector<Line> &lines, const double point_distanc
|
|||||||
return out;
|
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
|
} // namespace Slic3r
|
||||||
|
@ -27,13 +27,14 @@ class Line;
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ExPolygon;
|
class ExPolygon;
|
||||||
|
struct LayerIsland;
|
||||||
|
|
||||||
using ExPolygons = std::vector<ExPolygon>;
|
using ExPolygons = std::vector<ExPolygon>;
|
||||||
|
|
||||||
// Used by chain_expolygons()
|
// 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.
|
// 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.
|
// 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.
|
// 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.
|
// Chain lines into polylines.
|
||||||
Polylines chain_lines(const std::vector<Line> &lines, const double point_distance_epsilon);
|
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
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif /* slic3r_ShortestPath_hpp_ */
|
#endif /* slic3r_ShortestPath_hpp_ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user