mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:02:02 +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 <type_traits>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r::Algorithm {
|
||||||
namespace 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
|
//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
|
// 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.
|
// 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.
|
// 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>
|
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)
|
if (paths_count <= 1)
|
||||||
return;
|
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);
|
std::vector<AABBTreeLines::LinesDistancer<Line>> distancers(paths_count);
|
||||||
for (size_t path_idx = 0; path_idx < paths_count; path_idx++) {
|
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))};
|
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);
|
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 curr_path_idx = 0; curr_path_idx < paths_count; ++curr_path_idx) {
|
||||||
for (size_t next_path_idx = path_idx + 1; next_path_idx < paths_count; next_path_idx++) {
|
for (size_t next_path_idx = curr_path_idx + 1; next_path_idx < paths_count; ++next_path_idx) {
|
||||||
if (paths_touch(distancers[path_idx], distancers[next_path_idx])) {
|
const BoundingBox &curr_path_bbox = bboxes[curr_path_idx];
|
||||||
dependencies[next_path_idx].insert(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_*/
|
#endif /*SRC_LIBSLIC3R_PATH_SORTING_HPP_*/
|
||||||
|
@ -328,6 +328,23 @@ inline double bbox_point_distance_squared(const BoundingBox &bbox, const Point &
|
|||||||
coord_t(0));
|
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>
|
template<class T>
|
||||||
BoundingBoxBase<Vec<2, T>> to_2d(const BoundingBox3Base<Vec<3, T>> &bb)
|
BoundingBoxBase<Vec<2, T>> to_2d(const BoundingBox3Base<Vec<3, T>> &bb)
|
||||||
{
|
{
|
||||||
|
@ -201,6 +201,10 @@ bool Polyline::is_straight() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox ThickPolyline::bounding_box() const {
|
||||||
|
return BoundingBox(this->points);
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox get_extents(const Polyline &polyline)
|
BoundingBox get_extents(const Polyline &polyline)
|
||||||
{
|
{
|
||||||
return polyline.bounding_box();
|
return polyline.bounding_box();
|
||||||
@ -335,6 +339,22 @@ Lines to_lines(const ThickPolylines &thick_polylines) {
|
|||||||
return lines;
|
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 ThickPolyline::thicklines() const
|
||||||
{
|
{
|
||||||
ThickLines lines;
|
ThickLines lines;
|
||||||
|
@ -241,6 +241,8 @@ struct ThickPolyline {
|
|||||||
// On open ThickPolyline make no effect.
|
// On open ThickPolyline make no effect.
|
||||||
void start_at_index(int index);
|
void start_at_index(int index);
|
||||||
|
|
||||||
|
BoundingBox bounding_box() const;
|
||||||
|
|
||||||
Points points;
|
Points points;
|
||||||
// vector of startpoint width and endpoint width of each line segment. The size should be always (points.size()-1) * 2
|
// 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:
|
// 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 ThickPolyline &thick_polyline);
|
||||||
Lines to_lines(const ThickPolylines &thick_polylines);
|
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
|
class Polyline3 : public MultiPoint3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user