mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 09:46:05 +08:00
Merge branch 'lh_extrusion_order' (#11658)
This commit is contained in:
commit
bc36722d4b
@ -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) {
|
||||
|
@ -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 ®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;
|
||||
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 ®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});
|
||||
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 ®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;
|
||||
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
|
||||
)};
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user