mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:12:04 +08:00
SPE-1950: Optimization of extrusion sorting for the ensuring infill.
This commit is contained in:
parent
b3510ac808
commit
82fb648cb7
@ -18,8 +18,39 @@
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Algorithm {
|
||||
namespace Slic3r::Algorithm {
|
||||
|
||||
bool is_first_path_touching_second_path(const AABBTreeLines::LinesDistancer<Line> &first_distancer,
|
||||
const AABBTreeLines::LinesDistancer<Line> &second_distancer,
|
||||
const BoundingBox &second_distancer_bbox,
|
||||
const double touch_distance_threshold)
|
||||
{
|
||||
for (const Line &line : first_distancer.get_lines()) {
|
||||
if (bbox_point_distance(second_distancer_bbox, line.a) < touch_distance_threshold && second_distancer.distance_from_lines<false>(line.a) < touch_distance_threshold) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const Point first_distancer_last_pt = first_distancer.get_lines().back().b;
|
||||
if (bbox_point_distance(second_distancer_bbox, first_distancer_last_pt) && second_distancer.distance_from_lines<false>(first_distancer_last_pt) < touch_distance_threshold) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool are_paths_touching(const AABBTreeLines::LinesDistancer<Line> &first_distancer, const BoundingBox &first_distancer_bbox,
|
||||
const AABBTreeLines::LinesDistancer<Line> &second_distancer, const BoundingBox &second_distancer_bbox,
|
||||
const double touch_distance_threshold)
|
||||
{
|
||||
if (is_first_path_touching_second_path(first_distancer, second_distancer, second_distancer_bbox, touch_distance_threshold)) {
|
||||
return true;
|
||||
} else if (is_first_path_touching_second_path(second_distancer, first_distancer, first_distancer_bbox, touch_distance_threshold)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Sorts the paths such that all paths between begin and last_seed are printed first, in some order. The rest of the paths is sorted
|
||||
// such that the paths that are touching some of the already printed are printed first, sorted secondary by the distance to the last point of the last
|
||||
@ -28,44 +59,34 @@ namespace Algorithm {
|
||||
// to the second, then they touch.
|
||||
// convert_to_lines is a lambda that should accept the path as argument and return it as Lines vector, in correct order.
|
||||
template<typename RandomAccessIterator, typename ToLines>
|
||||
void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point start, double touch_limit_distance, ToLines convert_to_lines)
|
||||
void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point start, const double touch_distance_threshold, ToLines convert_to_lines)
|
||||
{
|
||||
size_t paths_count = std::distance(begin, end);
|
||||
const size_t paths_count = std::distance(begin, end);
|
||||
if (paths_count <= 1)
|
||||
return;
|
||||
|
||||
auto paths_touch = [touch_limit_distance](const AABBTreeLines::LinesDistancer<Line> &left,
|
||||
const AABBTreeLines::LinesDistancer<Line> &right) {
|
||||
for (const Line &l : left.get_lines()) {
|
||||
if (right.distance_from_lines<false>(l.a) < touch_limit_distance) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (right.distance_from_lines<false>(left.get_lines().back().b) < touch_limit_distance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const Line &l : right.get_lines()) {
|
||||
if (left.distance_from_lines<false>(l.a) < touch_limit_distance) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (left.distance_from_lines<false>(right.get_lines().back().b) < touch_limit_distance) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::vector<AABBTreeLines::LinesDistancer<Line>> distancers(paths_count);
|
||||
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
|
||||
distancers[path_idx] = AABBTreeLines::LinesDistancer<Line>{convert_to_lines(*std::next(begin, path_idx))};
|
||||
}
|
||||
|
||||
BoundingBoxes bboxes;
|
||||
bboxes.reserve(paths_count);
|
||||
for (auto tp_it = begin; tp_it != end; ++tp_it) {
|
||||
bboxes.emplace_back(tp_it->bounding_box());
|
||||
}
|
||||
|
||||
std::vector<std::unordered_set<size_t>> dependencies(paths_count);
|
||||
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
|
||||
for (size_t next_path_idx = path_idx + 1; next_path_idx < paths_count; next_path_idx++) {
|
||||
if (paths_touch(distancers[path_idx], distancers[next_path_idx])) {
|
||||
dependencies[next_path_idx].insert(path_idx);
|
||||
for (size_t curr_path_idx = 0; curr_path_idx < paths_count; ++curr_path_idx) {
|
||||
for (size_t next_path_idx = curr_path_idx + 1; next_path_idx < paths_count; ++next_path_idx) {
|
||||
const BoundingBox &curr_path_bbox = bboxes[curr_path_idx];
|
||||
const BoundingBox &next_path_bbox = bboxes[next_path_idx];
|
||||
|
||||
if (bbox_bbox_distance(curr_path_bbox, next_path_bbox) >= touch_distance_threshold)
|
||||
continue;
|
||||
|
||||
if (are_paths_touching(distancers[curr_path_idx], curr_path_bbox, distancers[next_path_idx], next_path_bbox, touch_distance_threshold)) {
|
||||
dependencies[next_path_idx].insert(curr_path_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,6 +148,6 @@ void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point star
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::Algorithm
|
||||
} // namespace Slic3r::Algorithm
|
||||
|
||||
#endif /*SRC_LIBSLIC3R_PATH_SORTING_HPP_*/
|
||||
|
@ -328,6 +328,23 @@ inline double bbox_point_distance_squared(const BoundingBox &bbox, const Point &
|
||||
coord_t(0));
|
||||
}
|
||||
|
||||
// Minimum distance between two Bounding boxes.
|
||||
// Returns zero when Bounding boxes overlap.
|
||||
inline double bbox_bbox_distance(const BoundingBox &first_bbox, const BoundingBox &second_bbox) {
|
||||
if (first_bbox.overlap(second_bbox))
|
||||
return 0.;
|
||||
|
||||
double bboxes_distance_squared = 0.;
|
||||
|
||||
for (size_t axis = 0; axis < 2; ++axis) {
|
||||
const coord_t axis_distance = std::max(std::max(0, first_bbox.min[axis] - second_bbox.max[axis]),
|
||||
second_bbox.min[axis] - first_bbox.max[axis]);
|
||||
bboxes_distance_squared += Slic3r::sqr(static_cast<double>(axis_distance));
|
||||
}
|
||||
|
||||
return std::sqrt(bboxes_distance_squared);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BoundingBoxBase<Vec<2, T>> to_2d(const BoundingBox3Base<Vec<3, T>> &bb)
|
||||
{
|
||||
|
@ -201,6 +201,10 @@ bool Polyline::is_straight() const
|
||||
return true;
|
||||
}
|
||||
|
||||
BoundingBox ThickPolyline::bounding_box() const {
|
||||
return BoundingBox(this->points);
|
||||
}
|
||||
|
||||
BoundingBox get_extents(const Polyline &polyline)
|
||||
{
|
||||
return polyline.bounding_box();
|
||||
@ -335,6 +339,22 @@ Lines to_lines(const ThickPolylines &thick_polylines) {
|
||||
return lines;
|
||||
}
|
||||
|
||||
BoundingBox get_extents(const ThickPolyline &thick_polyline) {
|
||||
return thick_polyline.bounding_box();
|
||||
}
|
||||
|
||||
BoundingBox get_extents(const ThickPolylines &thick_polylines) {
|
||||
BoundingBox bbox;
|
||||
if (!thick_polylines.empty()) {
|
||||
bbox = thick_polylines.front().bounding_box();
|
||||
for (size_t i = 1; i < thick_polylines.size(); ++i) {
|
||||
bbox.merge(thick_polylines[i].points);
|
||||
}
|
||||
}
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
ThickLines ThickPolyline::thicklines() const
|
||||
{
|
||||
ThickLines lines;
|
||||
|
@ -241,6 +241,8 @@ struct ThickPolyline {
|
||||
// On open ThickPolyline make no effect.
|
||||
void start_at_index(int index);
|
||||
|
||||
BoundingBox bounding_box() const;
|
||||
|
||||
Points points;
|
||||
// vector of startpoint width and endpoint width of each line segment. The size should be always (points.size()-1) * 2
|
||||
// e.g. let four be points a,b,c,d. that are three lines ab, bc, cd. for each line, there should be start width, so the width vector is:
|
||||
@ -266,6 +268,9 @@ size_t total_lines_count(const ThickPolylines &thick_polylines);
|
||||
Lines to_lines(const ThickPolyline &thick_polyline);
|
||||
Lines to_lines(const ThickPolylines &thick_polylines);
|
||||
|
||||
BoundingBox get_extents(const ThickPolyline &thick_polyline);
|
||||
BoundingBox get_extents(const ThickPolylines &thick_polylines);
|
||||
|
||||
class Polyline3 : public MultiPoint3
|
||||
{
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user