From aba094dcd8e24b76a7bae64e9017d9e58da5b1d6 Mon Sep 17 00:00:00 2001 From: Filip Sykala - NTB T15p Date: Mon, 18 Jul 2022 15:30:29 +0200 Subject: [PATCH] Add closest unsorted --- src/libslic3r/ClosestPoint.hpp | 58 +++++++++++++++++++++----- tests/libslic3r/test_closest_point.cpp | 43 ++++++++++++++++++- 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/ClosestPoint.hpp b/src/libslic3r/ClosestPoint.hpp index 5c3f02116..f12554809 100644 --- a/src/libslic3r/ClosestPoint.hpp +++ b/src/libslic3r/ClosestPoint.hpp @@ -6,12 +6,12 @@ namespace Slic3r { /// -/// Sort points and use sweep line algo to find closest point in points +/// Sort points and use find_closest_in_sorted /// /// Seach for closest index to this point /// Search inside of thoose points /// Index of closest point from sorted_pts -// size_t find_closest(const Point &p, const Points& pts); +template size_t find_closest(const P &p, const std::vector

&pts); ///

/// Use a plane sweep algorithm to find closest point in sorted points @@ -29,8 +29,10 @@ size_t find_closest_in_sorted(const P &p, const std::vector

&sorted_pts); ///

/// Seach for closest index to thoose points /// Sorted points by X coordinate -/// Index of closest point from sorted_pts -// size_t find_closest_in_sorted(const Point &pts, const Points &sorted_pts); +/// Indices to pts(first) and sorted_pts(second) +template +std::pair find_closest_in_sorted( + const std::vector

&pts, const std::vector

&sorted_pts); namespace closestPoint { ///

@@ -46,10 +48,37 @@ template bool upper_fnc(V value, const P &p){ return value /// Function used to find lower bound in sorted points. template bool lower_fnc(const P &p, V value){ return value > p.x(); } /// Calc manhatn size of point. Mainly to explain meaning -template uint32_t manhattan_size(const P &p){ return std::abs(p.x()) + abs(p.y()); } +template uint32_t manhattan_size(const P &p1, const P &p2) +{ return std::abs(p1.x()-p2.x()) + abs(p1.y()-p2.y()); } } // namespace closestPoint } // namespace Slic3r +template +size_t Slic3r::find_closest(const P &p, const std::vector

&pts) +{ + // check input + if (pts.empty()) return std::numeric_limits::max(); + if (pts.size() == 1) return 0; + + using V = decltype(p.x()); + // extend P with order + struct PP + { + size_t ord; + const P* p; + V x() const { return p->x(); } + V y() const { return p->y(); } + }; + std::vector pts_ord; + pts_ord.reserve(pts.size()); + size_t ord = 0; + for (const P &pp : pts) pts_ord.push_back({ord++, &pp}); + std::stable_sort(pts_ord.begin(), pts_ord.end(), closestPoint::sort_fnc); + PP pp{0, &p}; + size_t closest_index = find_closest_in_sorted(pp, pts_ord); + return pts_ord[closest_index].ord; +} + template size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector

&pts) { @@ -62,17 +91,17 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector

&pts) if (pts.size() == 1) return 0; using V = decltype(p.x()); - + using It = std::vector

::const_iterator; // closest point node in X - Points::const_iterator it_x = std::upper_bound(pts.begin(), pts.end(), p.x(), upper_fnc); + It it_x = std::upper_bound(pts.begin(), pts.end(), p.x(), upper_fnc); bool is_it_x_end = it_x == pts.end(); // it_x can't pointing to end so change to last point if (is_it_x_end) --it_x; // manhatn distance to closest point - uint32_t manhattan_dist = manhattan_size(*it_x - p); + uint32_t manhattan_dist = manhattan_size(*it_x, p); // node for lower bound - Points::const_iterator it_l; + It it_l; if (it_x == pts.begin()) { it_l = it_x; } else { @@ -90,7 +119,7 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector

&pts) } // node for upper bound - Points::const_iterator it_u; + It it_u; if (is_it_x_end) { it_u = pts.end(); } else { @@ -111,7 +140,7 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector

&pts) // find closest by squer distance float dist_sq = std::numeric_limits::max(); size_t result = it_x - pts.begin(); - for (Points::const_iterator it = it_l; it < it_u; ++it) { + for (It it = it_l; it < it_u; ++it) { uint32_t diff_y = std::abs(it->y() - p.y()); if (diff_y > manhattan_dist) continue; float diff_x = it->x() - p.x(); @@ -125,4 +154,11 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector

&pts) return result; } +template +std::pair find_closest_in_sorted( + const std::vector

&pts, const std::vector

&sorted_pts) +{ + return {0, 0}; +} + #endif // slic3r_ClosestPoint_hpp_ diff --git a/tests/libslic3r/test_closest_point.cpp b/tests/libslic3r/test_closest_point.cpp index 2204f21ac..75f7d53e3 100644 --- a/tests/libslic3r/test_closest_point.cpp +++ b/tests/libslic3r/test_closest_point.cpp @@ -1,12 +1,14 @@ #include #include +#include using namespace Slic3r; TEST_CASE("Find the closest point from 2", "[ClosestPoint]") { Points pts = {{0, 1}, {0, 2}}; - CHECK(std::is_sorted(pts.begin(), pts.end(), closestPoint::sort_fnc)); + CHECK(std::is_sorted(pts.begin(), pts.end(), + closestPoint::sort_fnc)); CHECK(0 == find_closest_in_sorted(Point{0, 0}, pts)); CHECK(0 == find_closest_in_sorted(Point{1, 1}, pts)); CHECK(1 == find_closest_in_sorted(Point{1, 2}, pts)); @@ -21,7 +23,8 @@ TEST_CASE("Find the closest point from 9", "[ClosestPoint]") // 2 - 5 - 8 Points pts = {{-3, 3}, {-3, 0}, {-3, -3}, {0, 3}, {0, 0}, {0, -3}, {3, 3}, {3, 0}, {3, -3}}; - CHECK(std::is_sorted(pts.begin(), pts.end(), closestPoint::sort_fnc)); + CHECK(std::is_sorted(pts.begin(), pts.end(), + closestPoint::sort_fnc)); CHECK(0 == find_closest_in_sorted(Point{-4, 4}, pts)); CHECK(0 == find_closest_in_sorted(Point{-2, 2}, pts)); @@ -40,3 +43,39 @@ TEST_CASE("Find the closest point from 9", "[ClosestPoint]") CHECK(7 == find_closest_in_sorted(Point{2, 1}, pts)); CHECK(8 == find_closest_in_sorted(Point{2,-2}, pts)); } + +TEST_CASE("Find the closest point from 9 unsorted", "[ClosestPoint]") +{ + // 4 - 3 - 0 + // | | | + // 1 - 6 - 5 + // | | | + // 2 - 7 - 8 + Points pts = { + /*0*/ {3, 3}, + /*1*/ {-3, 0}, + /*2*/ {-3, -3}, + /*3*/ {0, 3}, + /*4*/ {-3, 3}, + /*5*/ {3, 0}, + /*6*/ {0, 0}, + /*7*/ {0, -3}, + /*8*/ {3, -3} + }; + CHECK(4 == find_closest(Point{-4, 4}, pts)); + CHECK(4 == find_closest(Point{-2, 2}, pts)); + // check center + CHECK(6 == find_closest(Point{-1, 1}, pts)); + CHECK(6 == find_closest(Point{ 0, 1}, pts)); + CHECK(6 == find_closest(Point{ 1, 1}, pts)); + CHECK(6 == find_closest(Point{-1, 0}, pts)); + CHECK(6 == find_closest(Point{ 0, 0}, pts)); + CHECK(6 == find_closest(Point{ 1, 0}, pts)); + CHECK(6 == find_closest(Point{-1,-1}, pts)); + CHECK(6 == find_closest(Point{ 0,-1}, pts)); + CHECK(6 == find_closest(Point{ 1,-1}, pts)); + CHECK(6 == find_closest(Point{ 0, 0}, pts)); + + CHECK(5 == find_closest(Point{2, 1}, pts)); + CHECK(8 == find_closest(Point{2,-2}, pts)); +} \ No newline at end of file