mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 10:15:54 +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.
|
// 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.
|
// 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()) ||
|
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());
|
(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;
|
bool is_nearest_closed = false;
|
||||||
|
|
||||||
// First we order all holes and then we start ordering contours.
|
// 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();
|
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_extrusion_idx = 0; grouped_extrusion_idx < grouped_extrusion_end; ++grouped_extrusion_idx) {
|
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])
|
if (already_selected[grouped_extrusion_idx])
|
||||||
continue;
|
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);
|
grouped_extrusions_order.emplace_back(nearest_grouped_extrusions_idx);
|
||||||
already_selected[nearest_grouped_extrusions_idx] = true;
|
already_selected[nearest_grouped_extrusions_idx] = true;
|
||||||
|
|
||||||
const GroupedPerimeterExtrusions &nearest_grouped_extrusions = grouped_extrusions[nearest_grouped_extrusions_idx];
|
const GroupedPerimeterExtrusions &nearest_grouped_extrusions = grouped_extrusions[nearest_grouped_extrusions_idx];
|
||||||
const ExtrusionLine &last_extrusion_line = nearest_grouped_extrusions.extrusions.back()->extrusion;
|
const ExtrusionLine &last_extrusion_line = nearest_grouped_extrusions.extrusions.back()->extrusion;
|
||||||
current_position = get_end_position(last_extrusion_line);
|
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());
|
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;
|
PerimeterExtrusions ordered_extrusions;
|
||||||
for (size_t order_idx : grouped_extrusion_order) {
|
for (size_t order_idx : grouped_extrusion_order) {
|
||||||
|
@ -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