mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-29 01:27:38 +08:00
Optimized for reduced memory allocation and clarity.
This commit is contained in:
parent
3e50699576
commit
50b603df5d
@ -556,10 +556,9 @@ static void export_infill_lines_to_svg(const ExPolygon &expoly, const Polylines
|
|||||||
static Matrix2d rotation_matrix_from_vector(const Point &vector)
|
static Matrix2d rotation_matrix_from_vector(const Point &vector)
|
||||||
{
|
{
|
||||||
Matrix2d rotation;
|
Matrix2d rotation;
|
||||||
rotation.block<1, 2>(0, 0) = vector.cast<double>() / vector.cast<double>().norm();
|
rotation.block<1, 2>(0, 0) = vector.cast<double>().normalized();
|
||||||
rotation(1, 0) = -rotation(0, 1);
|
rotation(1, 0) = -rotation(0, 1);
|
||||||
rotation(1, 1) = rotation(0, 0);
|
rotation(1, 1) = rotation(0, 0);
|
||||||
|
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,6 +637,13 @@ using rtree_point_t = bgm::point<float, 2, boost::geometry::cs::cartesian>;
|
|||||||
using rtree_segment_t = bgm::segment<rtree_point_t>;
|
using rtree_segment_t = bgm::segment<rtree_point_t>;
|
||||||
using rtree_t = bgi::rtree<std::pair<rtree_segment_t, size_t>, bgi::rstar<16, 4>>;
|
using rtree_t = bgi::rtree<std::pair<rtree_segment_t, size_t>, bgi::rstar<16, 4>>;
|
||||||
|
|
||||||
|
static inline rtree_segment_t mk_rtree_seg(const Point &a, const Point &b) {
|
||||||
|
return { rtree_point_t(float(a.x()), float(a.y())), rtree_point_t(float(b.x()), float(b.y())) };
|
||||||
|
}
|
||||||
|
static inline rtree_segment_t mk_rtree_seg(const Line &l) {
|
||||||
|
return mk_rtree_seg(l.a, l.b);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a hook based on hook_line and append it to the begin or end of the polyline in the intersection
|
// Create a hook based on hook_line and append it to the begin or end of the polyline in the intersection
|
||||||
static void add_hook(const Intersection &intersection, const Line &hook_line, const double scaled_spacing, const int hook_length, const rtree_t &rtree)
|
static void add_hook(const Intersection &intersection, const Line &hook_line, const double scaled_spacing, const int hook_length, const rtree_t &rtree)
|
||||||
{
|
{
|
||||||
@ -660,9 +666,7 @@ static void add_hook(const Intersection &intersection, const Line &hook_line, co
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::pair<rtree_segment_t, size_t>> hook_intersections;
|
std::vector<std::pair<rtree_segment_t, size_t>> hook_intersections;
|
||||||
rtree.query(bgi::intersects(rtree_segment_t(rtree_point_t(float(hook_forward.a.x()), float(hook_forward.a.y())),
|
rtree.query(bgi::intersects(mk_rtree_seg(hook_forward)) && bgi::satisfies(filter_itself),
|
||||||
rtree_point_t(float(hook_forward.b.x()), float(hook_forward.b.y())))) &&
|
|
||||||
bgi::satisfies(filter_itself),
|
|
||||||
std::back_inserter(hook_intersections));
|
std::back_inserter(hook_intersections));
|
||||||
|
|
||||||
auto max_hook_length = [&hook_intersections, &hook_length](const Line &hook) {
|
auto max_hook_length = [&hook_intersections, &hook_length](const Line &hook) {
|
||||||
@ -683,9 +687,7 @@ static void add_hook(const Intersection &intersection, const Line &hook_line, co
|
|||||||
// There is not enough space for the hook, try another direction
|
// There is not enough space for the hook, try another direction
|
||||||
coord_t hook_forward_max_length = max_hook_length(hook_forward);
|
coord_t hook_forward_max_length = max_hook_length(hook_forward);
|
||||||
hook_intersections.clear();
|
hook_intersections.clear();
|
||||||
rtree.query(bgi::intersects(rtree_segment_t(rtree_point_t(float(hook_backward.a.x()), float(hook_backward.a.y())),
|
rtree.query(bgi::intersects(mk_rtree_seg(hook_backward)) && bgi::satisfies(filter_itself),
|
||||||
rtree_point_t(float(hook_backward.b.x()), float(hook_backward.b.y())))) &&
|
|
||||||
bgi::satisfies(filter_itself),
|
|
||||||
std::back_inserter(hook_intersections));
|
std::back_inserter(hook_intersections));
|
||||||
|
|
||||||
if (hook_intersections.empty()) {
|
if (hook_intersections.empty()) {
|
||||||
@ -712,40 +714,42 @@ static void add_hook(const Intersection &intersection, const Line &hook_line, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void connect_lines_using_hooks(Polylines &&lines, Polylines &polylines_out, const ExPolygon &boundary, const double spacing, const int hook_length)
|
static Polylines connect_lines_using_hooks(Polylines &&lines, const ExPolygon &boundary, const double spacing, const int hook_length)
|
||||||
{
|
{
|
||||||
rtree_t rtree;
|
rtree_t rtree;
|
||||||
size_t poly_idx = 0;
|
size_t poly_idx = 0;
|
||||||
for (const Polyline &poly : lines) {
|
for (const Polyline &poly : lines) {
|
||||||
rtree.insert(std::make_pair(rtree_segment_t(rtree_point_t(float(poly.points.front().x()), float(poly.points.front().y())),
|
rtree.insert(std::make_pair(mk_rtree_seg(poly.points.front(), poly.points.back()), poly_idx++));
|
||||||
rtree_point_t(float(poly.points.back().x()), float(poly.points.back().y()))),
|
|
||||||
poly_idx++));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Intersection> intersections;
|
std::vector<Intersection> intersections;
|
||||||
coord_t scaled_spacing = coord_t(scale_(spacing));
|
{
|
||||||
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
const coord_t scaled_spacing = coord_t(scale_(spacing));
|
||||||
Polyline &line = lines[line_idx];
|
// Keeping the vector of closest points outside the loop, so the vector does not need to be reallocated.
|
||||||
// Lines shorter than spacing are skipped because it is needed to shrink a line by the value of spacing.
|
|
||||||
// A shorter line than spacing could produce a degenerate polyline.
|
|
||||||
if (line.length() <= (scaled_spacing + SCALED_EPSILON)) continue;
|
|
||||||
|
|
||||||
Point front_point = line.points.front();
|
|
||||||
Point back_point = line.points.back();
|
|
||||||
std::vector<std::pair<rtree_segment_t, size_t>> closest;
|
std::vector<std::pair<rtree_segment_t, size_t>> closest;
|
||||||
|
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
||||||
|
Polyline &line = lines[line_idx];
|
||||||
|
// Lines shorter than spacing are skipped because it is needed to shrink a line by the value of spacing.
|
||||||
|
// A shorter line than spacing could produce a degenerate polyline.
|
||||||
|
if (line.length() <= (scaled_spacing + SCALED_EPSILON)) continue;
|
||||||
|
|
||||||
auto filter_itself = [line_idx](const auto &item) { return item.second != line_idx; };
|
Point front_point = line.points.front();
|
||||||
|
Point back_point = line.points.back();
|
||||||
|
|
||||||
// Find the nearest line from the start point of the line.
|
auto filter_itself = [line_idx](const auto &item) { return item.second != line_idx; };
|
||||||
rtree.query(bgi::nearest(rtree_point_t(float(front_point.x()), float(front_point.y())), 1) && bgi::satisfies(filter_itself), std::back_inserter(closest));
|
|
||||||
if (((Line) lines[closest[0].second]).distance_to(front_point) <= 1000)
|
|
||||||
intersections.emplace_back(closest[0].second, (Line) lines[closest[0].second], front_point, line_idx, &line, (Line) line, true);
|
|
||||||
|
|
||||||
closest.clear();
|
// Find the nearest line from the start point of the line.
|
||||||
// Find the nearest line from the end point of the line
|
closest.clear();
|
||||||
rtree.query(bgi::nearest(rtree_point_t(float(back_point.x()), float(back_point.y())), 1) && bgi::satisfies(filter_itself), std::back_inserter(closest));
|
rtree.query(bgi::nearest(rtree_point_t(float(front_point.x()), float(front_point.y())), 1) && bgi::satisfies(filter_itself), std::back_inserter(closest));
|
||||||
if (((Line) lines[closest[0].second]).distance_to(back_point) <= 1000)
|
if (((Line) lines[closest[0].second]).distance_to(front_point) <= 1000)
|
||||||
intersections.emplace_back(closest[0].second, (Line) lines[closest[0].second], back_point, line_idx, &line, (Line) line, false);
|
intersections.emplace_back(closest[0].second, (Line) lines[closest[0].second], front_point, line_idx, &line, (Line) line, true);
|
||||||
|
|
||||||
|
// Find the nearest line from the end point of the line
|
||||||
|
closest.clear();
|
||||||
|
rtree.query(bgi::nearest(rtree_point_t(float(back_point.x()), float(back_point.y())), 1) && bgi::satisfies(filter_itself), std::back_inserter(closest));
|
||||||
|
if (((Line) lines[closest[0].second]).distance_to(back_point) <= 1000)
|
||||||
|
intersections.emplace_back(closest[0].second, (Line) lines[closest[0].second], back_point, line_idx, &line, (Line) line, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(intersections.begin(), intersections.end(),
|
std::sort(intersections.begin(), intersections.end(),
|
||||||
@ -755,15 +759,20 @@ static void connect_lines_using_hooks(Polylines &&lines, Polylines &polylines_ou
|
|||||||
std::iota(merged_with.begin(), merged_with.end(), 0);
|
std::iota(merged_with.begin(), merged_with.end(), 0);
|
||||||
|
|
||||||
// Appends the boundary polygon with all holes to rtree for detection if hooks not crossing the boundary
|
// Appends the boundary polygon with all holes to rtree for detection if hooks not crossing the boundary
|
||||||
for (const Line &line : boundary.contour.lines())
|
{
|
||||||
rtree.insert(
|
Point prev = boundary.contour.points.back();
|
||||||
std::make_pair(rtree_segment_t(rtree_point_t(float(line.a.x()), float(line.a.y())), rtree_point_t(float(line.b.x()), float(line.b.y()))),
|
for (const Point &point : boundary.contour.points) {
|
||||||
poly_idx++));
|
rtree.insert(std::make_pair(mk_rtree_seg(prev, point), poly_idx++));
|
||||||
for (const Polygon &polygon : boundary.holes)
|
prev = point;
|
||||||
for (const Line &line : polygon.lines())
|
}
|
||||||
rtree.insert(std::make_pair(rtree_segment_t(rtree_point_t(float(line.a.x()), float(line.a.y())),
|
for (const Polygon &polygon : boundary.holes) {
|
||||||
rtree_point_t(float(line.b.x()), float(line.b.y()))),
|
Point prev = polygon.points.back();
|
||||||
poly_idx++));
|
for (const Point &point : polygon.points) {
|
||||||
|
rtree.insert(std::make_pair(mk_rtree_seg(prev, point), poly_idx++));
|
||||||
|
prev = point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto update_merged_polyline = [&lines, &merged_with](Intersection &intersection) {
|
auto update_merged_polyline = [&lines, &merged_with](Intersection &intersection) {
|
||||||
// Update the polyline index to index which is merged
|
// Update the polyline index to index which is merged
|
||||||
@ -884,9 +893,11 @@ static void connect_lines_using_hooks(Polylines &&lines, Polylines &polylines_ou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Polylines polylines_out;
|
||||||
polylines_out.reserve(polylines_out.size() + std::count_if(lines.begin(), lines.end(), [](const Polyline &pl) { return !pl.empty(); }));
|
polylines_out.reserve(polylines_out.size() + std::count_if(lines.begin(), lines.end(), [](const Polyline &pl) { return !pl.empty(); }));
|
||||||
for (Polyline &pl : lines)
|
for (Polyline &pl : lines)
|
||||||
if (!pl.empty()) polylines_out.emplace_back(std::move(pl));
|
if (!pl.empty()) polylines_out.emplace_back(std::move(pl));
|
||||||
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
coord_t get_hook_length(const double spacing) { return coord_t(scale_(spacing)) * 5; }
|
coord_t get_hook_length(const double spacing) { return coord_t(scale_(spacing)) * 5; }
|
||||||
@ -937,8 +948,11 @@ void Filler::_fill_surface_single(
|
|||||||
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
|
all_polylines = intersection_pl(std::move(all_polylines), to_polygons(expolygon));
|
||||||
|
|
||||||
// After intersection_pl some polylines with only one line are split into more lines
|
// After intersection_pl some polylines with only one line are split into more lines
|
||||||
for (Polyline &polyline : all_polylines)
|
for (Polyline &polyline : all_polylines) {
|
||||||
if (polyline.points.size() > 2) polyline = Polyline(polyline.points.front(), polyline.points.back());
|
//FIXME assert that all the points are collinear and in between the start and end point.
|
||||||
|
if (polyline.points.size() > 2)
|
||||||
|
polyline.points.erase(polyline.points.begin() + 1, polyline.points.end() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
{
|
{
|
||||||
@ -948,8 +962,7 @@ void Filler::_fill_surface_single(
|
|||||||
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
||||||
|
|
||||||
coord_t hook_length = get_hook_length(this->spacing);
|
coord_t hook_length = get_hook_length(this->spacing);
|
||||||
Polylines all_polylines_with_hooks;
|
Polylines all_polylines_with_hooks = connect_lines_using_hooks(std::move(all_polylines), expolygon, this->spacing, hook_length);
|
||||||
connect_lines_using_hooks(std::move(all_polylines), all_polylines_with_hooks, expolygon, this->spacing, hook_length);
|
|
||||||
|
|
||||||
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
#ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user