From a695b66d01f001287b1dc61e99002687d1818261 Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Fri, 28 Apr 2023 16:45:17 +0200 Subject: [PATCH] Stable and working version, fixed several issues in ordering and connecting --- src/libslic3r/Algorithm/PathSorting.hpp | 51 +++------ src/libslic3r/Fill/FillEnsuring.cpp | 140 ++++++++++++++++++------ 2 files changed, 121 insertions(+), 70 deletions(-) diff --git a/src/libslic3r/Algorithm/PathSorting.hpp b/src/libslic3r/Algorithm/PathSorting.hpp index 5a032a39ba..ab44627281 100644 --- a/src/libslic3r/Algorithm/PathSorting.hpp +++ b/src/libslic3r/Algorithm/PathSorting.hpp @@ -30,26 +30,26 @@ void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point star if (paths_count <= 1) return; - auto paths_min_distance = [](const AABBTreeLines::LinesDistancer &left, const AABBTreeLines::LinesDistancer &right) { - double min_distance = std::numeric_limits::max(); + auto paths_touch = [touch_limit_distance](const AABBTreeLines::LinesDistancer &left, + const AABBTreeLines::LinesDistancer &right) { for (const Line &l : left.get_lines()) { - if (double dist = right.distance_from_lines(l.a); dist < min_distance) { - min_distance = dist; + if (right.distance_from_lines(l.a) < touch_limit_distance) { + return true; } } - if (double dist = right.distance_from_lines(left.get_lines().back().b); dist < min_distance) { - min_distance = dist; + if (right.distance_from_lines(left.get_lines().back().b) < touch_limit_distance) { + return true; } for (const Line &l : right.get_lines()) { - if (double dist = left.distance_from_lines(l.a); dist < min_distance) { - min_distance = dist; + if (left.distance_from_lines(l.a) < touch_limit_distance) { + return true; } } - if (double dist = left.distance_from_lines(right.get_lines().back().b); dist < min_distance) { - min_distance = dist; + if (left.distance_from_lines(right.get_lines().back().b) < touch_limit_distance) { + return true; } - return min_distance; + return false; }; std::vector> distancers(paths_count); @@ -60,20 +60,12 @@ void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point star std::vector> 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++) { - double dist = paths_min_distance(distancers[path_idx], distancers[next_path_idx]); - if (dist < touch_limit_distance) { + if (paths_touch(distancers[path_idx], distancers[next_path_idx])) { dependencies[next_path_idx].insert(path_idx); } } } - for (size_t path_idx = 0; path_idx < paths_count; path_idx++) { - std::cout << "Dependencies of " << path_idx << " are "; - for (size_t dep : dependencies[path_idx]) - std::cout << dep << ", "; - std::cout << std::endl; - } - Point current_point = start; std::vector> correct_order_and_direction(paths_count); @@ -91,14 +83,11 @@ void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point star double ldist = distancers[path_idx].distance_from_lines(current_point); if (ldist < lines_dist) { const auto &lines = distancers[path_idx].get_lines(); - double dist_a = line_alg::distance_to(lines.front(), current_point); - double dist_b = line_alg::distance_to(lines.back(), current_point); - if (std::abs(dist_a - dist_b) < touch_limit_distance) { - dist_a = (lines.front().a - current_point).squaredNorm(); - dist_b = (lines.back().b - current_point).squaredNorm(); - } - next_idx = path_idx; - reverse = dist_b < dist_a; + double dist_a = (lines.front().a - current_point).cast().squaredNorm(); + double dist_b = (lines.back().b - current_point).cast().squaredNorm(); + next_idx = path_idx; + reverse = dist_b < dist_a; + lines_dist = ldist; } } @@ -113,12 +102,6 @@ void sort_paths(RandomAccessIterator begin, RandomAccessIterator end, Point star } } - std::cout << "Final order is "; - for (size_t path_idx = 0; path_idx < paths_count; path_idx++) { - std::cout << correct_order_and_direction[path_idx].first << ", "; - } - std::cout << std::endl; - for (size_t path_idx = 0; path_idx < paths_count; path_idx++) { if (correct_order_and_direction[path_idx].second) { std::next(begin, path_idx)->reverse(); diff --git a/src/libslic3r/Fill/FillEnsuring.cpp b/src/libslic3r/Fill/FillEnsuring.cpp index 5f07527d00..518c81627d 100644 --- a/src/libslic3r/Fill/FillEnsuring.cpp +++ b/src/libslic3r/Fill/FillEnsuring.cpp @@ -47,7 +47,7 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const }; const coord_t scaled_spacing = scaled(this->spacing); - double distance_limit_reconnection = 2 * double(scaled_spacing); + double distance_limit_reconnection = double(scaled_spacing); double squared_distance_limit_reconnection = distance_limit_reconnection * distance_limit_reconnection; Polygons filled_area = to_polygons(surface->expolygon); std::pair rotate_vector = this->_infill_direction(surface); @@ -250,16 +250,15 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const if (this->overlap != 0) { gaps_for_additional_filling = offset_ex(gaps_for_additional_filling, scaled(this->overlap)); } - // gaps_for_additional_filling = opening_ex(gaps_for_additional_filling, 0.3 * scaled_spacing); - BoundingBox bbox = get_extents(filled_area); - bbox.offset(scale_(1.)); - ::Slic3r::SVG svg(debug_out_path(("surface" + std::to_string(surface->area())).c_str()).c_str(), bbox); - svg.draw(to_lines(filled_area), "red", scale_(0.4)); - svg.draw(to_lines(reconstructed_area), "blue", scale_(0.3)); - svg.draw(to_lines(gaps_for_additional_filling), "green", scale_(0.2)); - svg.draw(vertical_lines, "black", scale_(0.1)); - svg.Close(); + // BoundingBox bbox = get_extents(filled_area); + // bbox.offset(scale_(1.)); + // ::Slic3r::SVG svg(debug_out_path(("surface" + std::to_string(surface->area())).c_str()).c_str(), bbox); + // svg.draw(to_lines(filled_area), "red", scale_(0.4)); + // svg.draw(to_lines(reconstructed_area), "blue", scale_(0.3)); + // svg.draw(to_lines(gaps_for_additional_filling), "green", scale_(0.2)); + // svg.draw(vertical_lines, "black", scale_(0.1)); + // svg.Close(); ThickPolylines thick_polylines; { @@ -316,11 +315,11 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const // Keep valid paths only. size_t j = firts_poly_idx; for (size_t i = firts_poly_idx; i < thick_polylines.size(); ++i) { - assert(thick_polylines_out[i].size() > 1); - assert(thick_polylines_out[i].length() > 0.); - //assert(thick_polylines_out[i].points.size() == thick_polylines_out[i].width.size()); + assert(thick_polylines[i].size() > 1); + assert(thick_polylines[i].length() > 0.); + //assert(thick_polylines[i].points.size() == thick_polylines[i].width.size()); thick_polylines[i].clip_end(this->loop_clipping); - assert(thick_polylines_out[i].size() > 1); + assert(thick_polylines[i].size() > 1); if (thick_polylines[i].is_valid()) { if (j < i) thick_polylines[j] = std::move(thick_polylines[i]); @@ -332,6 +331,75 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const } } + // connect tiny gap fills to close colinear line + struct EndPoint + { + Vec2d position; + size_t polyline_idx; + size_t other_end_point_idx; + bool is_first; + bool used = false; + }; + std::vector connection_endpoints; + connection_endpoints.reserve(thick_polylines.size() * 2); + for (size_t pl_idx = 0; pl_idx < thick_polylines.size(); pl_idx++) { + size_t current_idx = connection_endpoints.size(); + connection_endpoints.push_back({thick_polylines[pl_idx].first_point().cast(), pl_idx, current_idx + 1, true}); + connection_endpoints.push_back({thick_polylines[pl_idx].last_point().cast(), pl_idx, current_idx, false}); + } + + auto coord_fn = [&connection_endpoints](size_t idx, size_t dim) { return connection_endpoints[idx].position[dim]; }; + KDTreeIndirect<2, double, decltype(coord_fn)> endpoints_tree{coord_fn, connection_endpoints.size()}; + for (size_t ep_idx = 0; ep_idx < connection_endpoints.size(); ep_idx++) { + EndPoint &ep1 = connection_endpoints[ep_idx]; + if (!ep1.used) { + std::vector close_endpoints = find_nearby_points(endpoints_tree, ep1.position, scaled_spacing); + for (size_t close_endpoint_idx : close_endpoints) { + EndPoint &ep2 = connection_endpoints[close_endpoint_idx]; + if (ep2.used || ep2.polyline_idx == ep1.polyline_idx) { + continue; + } + + ThickPolyline &tp1 = thick_polylines[ep1.polyline_idx]; + ThickPolyline &tp2 = thick_polylines[ep2.polyline_idx]; + + Vec2d v1 = ep1.is_first ? (tp1.points[0] - tp1.points[1]).cast() : + (tp1.points.back() - tp1.points[tp1.points.size() - 1]).cast(); + Vec2d v2 = ep2.is_first ? (tp2.points[1] - tp2.points[0]).cast() : + (tp2.points[tp2.points.size() - 1] - tp2.points.back()).cast(); + + if (std::abs(Slic3r::angle(v1, v2)) > PI / 6.0) { + continue; + } + + // connect ep and ep2; + if (ep1.is_first) { + tp1.reverse(); + ep1.is_first = false; + connection_endpoints[ep1.other_end_point_idx].is_first = true; + } + + if (!ep2.is_first) { + tp2.reverse(); + ep2.is_first = true; + connection_endpoints[ep2.other_end_point_idx].is_first = false; + } + + tp1.points.insert(tp1.points.end(), tp2.points.begin(), tp2.points.end()); + tp1.width.push_back(tp1.width.back()); + tp1.width.push_back(tp2.width.front()); + tp1.width.insert(tp1.width.end(), tp2.width.begin(), tp2.width.end()); + ep2.used = true; + ep1.used = true; + connection_endpoints[ep2.other_end_point_idx].polyline_idx = ep1.polyline_idx; + connection_endpoints[ep2.other_end_point_idx].other_end_point_idx = ep_idx; + connection_endpoints[ep1.other_end_point_idx].other_end_point_idx = close_endpoint_idx; + tp2.clear(); + break; + } + } + } + thick_polylines.erase(std::remove_if(thick_polylines.begin(), thick_polylines.end(), [scaled_spacing](const ThickPolyline &tp) { return tp.length() < scaled_spacing && @@ -360,27 +428,27 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const return ls; }); - ThickPolylines connected_thick_polylines; - if (!thick_polylines.empty()) { - connected_thick_polylines.push_back(thick_polylines.front()); - for (ThickPolyline &tp : thick_polylines) { - ThickPolyline &tail = connected_thick_polylines.back(); - Point last = tail.last_point(); - if ((last - tp.last_point()).cast().squaredNorm() < (last - tp.first_point()).cast().squaredNorm()) { - tp.reverse(); - } - if ((last - tp.first_point()).cast().squaredNorm() < squared_distance_limit_reconnection) { - tail.points.insert(tail.points.end(), tp.points.begin(), tp.points.end()); - tail.width.push_back(tail.width.back()); - tail.width.push_back(tp.width.front()); - tail.width.insert(tail.width.end(), tp.width.begin(), tp.width.end()); - } else { - connected_thick_polylines.push_back(tp); - } - } - } - rotate_thick_polylines(connected_thick_polylines, cos(-aligning_angle), sin(-aligning_angle)); - return connected_thick_polylines; + // ThickPolylines connected_thick_polylines; + // if (!thick_polylines.empty()) { + // connected_thick_polylines.push_back(thick_polylines.front()); + // for (ThickPolyline &tp : thick_polylines) { + // ThickPolyline &tail = connected_thick_polylines.back(); + // Point last = tail.last_point(); + // if ((last - tp.last_point()).cast().squaredNorm() < (last - tp.first_point()).cast().squaredNorm()) { + // tp.reverse(); + // } + // if ((last - tp.first_point()).cast().squaredNorm() < squared_distance_limit_reconnection) { + // tail.points.insert(tail.points.end(), tp.points.begin(), tp.points.end()); + // tail.width.push_back(0); + // tail.width.push_back(0); + // tail.width.insert(tail.width.end(), tp.width.begin(), tp.width.end()); + // } else { + // connected_thick_polylines.push_back(tp); + // } + // } + // } + rotate_thick_polylines(thick_polylines, cos(-aligning_angle), sin(-aligning_angle)); + return thick_polylines; } } // namespace Slic3r @@ -461,4 +529,4 @@ ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const // } // } // } - // } \ No newline at end of file + // }