Add closest unsorted
This commit is contained in:
parent
08f18d28a4
commit
aba094dcd8
@ -6,12 +6,12 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sort points and use sweep line algo to find closest point in points
|
/// Sort points and use find_closest_in_sorted
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="p">Seach for closest index to this point</param>
|
/// <param name="p">Seach for closest index to this point</param>
|
||||||
/// <param name="pts">Search inside of thoose points</param>
|
/// <param name="pts">Search inside of thoose points</param>
|
||||||
/// <returns>Index of closest point from sorted_pts</returns>
|
/// <returns>Index of closest point from sorted_pts</returns>
|
||||||
// size_t find_closest(const Point &p, const Points& pts);
|
template<class P> size_t find_closest(const P &p, const std::vector<P> &pts);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use a plane sweep algorithm to find closest point in sorted points
|
/// 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<P> &sorted_pts);
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pts">Seach for closest index to thoose points</param>
|
/// <param name="pts">Seach for closest index to thoose points</param>
|
||||||
/// <param name="sorted_pts">Sorted points by X coordinate</param>
|
/// <param name="sorted_pts">Sorted points by X coordinate</param>
|
||||||
/// <returns>Index of closest point from sorted_pts</returns>
|
/// <returns>Indices to pts(first) and sorted_pts(second)</returns>
|
||||||
// size_t find_closest_in_sorted(const Point &pts, const Points &sorted_pts);
|
template<class P>
|
||||||
|
std::pair<size_t, size_t> find_closest_in_sorted(
|
||||||
|
const std::vector<P> &pts, const std::vector<P> &sorted_pts);
|
||||||
|
|
||||||
namespace closestPoint {
|
namespace closestPoint {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -46,10 +48,37 @@ template<class P, typename V> bool upper_fnc(V value, const P &p){ return value
|
|||||||
/// <summary> Function used to find lower bound in sorted points. </summary>
|
/// <summary> Function used to find lower bound in sorted points. </summary>
|
||||||
template<class P, typename V> bool lower_fnc(const P &p, V value){ return value > p.x(); }
|
template<class P, typename V> bool lower_fnc(const P &p, V value){ return value > p.x(); }
|
||||||
/// <summary> Calc manhatn size of point. Mainly to explain meaning</summary>
|
/// <summary> Calc manhatn size of point. Mainly to explain meaning</summary>
|
||||||
template<class P> uint32_t manhattan_size(const P &p){ return std::abs(p.x()) + abs(p.y()); }
|
template<class P> 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 closestPoint
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
template<class P>
|
||||||
|
size_t Slic3r::find_closest(const P &p, const std::vector<P> &pts)
|
||||||
|
{
|
||||||
|
// check input
|
||||||
|
if (pts.empty()) return std::numeric_limits<size_t>::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<PP> 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 pp{0, &p};
|
||||||
|
size_t closest_index = find_closest_in_sorted(pp, pts_ord);
|
||||||
|
return pts_ord[closest_index].ord;
|
||||||
|
}
|
||||||
|
|
||||||
template<class P>
|
template<class P>
|
||||||
size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
||||||
{
|
{
|
||||||
@ -62,17 +91,17 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
|||||||
if (pts.size() == 1) return 0;
|
if (pts.size() == 1) return 0;
|
||||||
|
|
||||||
using V = decltype(p.x());
|
using V = decltype(p.x());
|
||||||
|
using It = std::vector<P>::const_iterator;
|
||||||
// closest point node in X
|
// closest point node in X
|
||||||
Points::const_iterator it_x = std::upper_bound(pts.begin(), pts.end(), p.x(), upper_fnc<P,V>);
|
It it_x = std::upper_bound(pts.begin(), pts.end(), p.x(), upper_fnc<P,V>);
|
||||||
bool is_it_x_end = it_x == pts.end();
|
bool is_it_x_end = it_x == pts.end();
|
||||||
// it_x can't pointing to end so change to last point
|
// it_x can't pointing to end so change to last point
|
||||||
if (is_it_x_end) --it_x;
|
if (is_it_x_end) --it_x;
|
||||||
// manhatn distance to closest point
|
// 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
|
// node for lower bound
|
||||||
Points::const_iterator it_l;
|
It it_l;
|
||||||
if (it_x == pts.begin()) {
|
if (it_x == pts.begin()) {
|
||||||
it_l = it_x;
|
it_l = it_x;
|
||||||
} else {
|
} else {
|
||||||
@ -90,7 +119,7 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// node for upper bound
|
// node for upper bound
|
||||||
Points::const_iterator it_u;
|
It it_u;
|
||||||
if (is_it_x_end) {
|
if (is_it_x_end) {
|
||||||
it_u = pts.end();
|
it_u = pts.end();
|
||||||
} else {
|
} else {
|
||||||
@ -111,7 +140,7 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
|||||||
// find closest by squer distance
|
// find closest by squer distance
|
||||||
float dist_sq = std::numeric_limits<float>::max();
|
float dist_sq = std::numeric_limits<float>::max();
|
||||||
size_t result = it_x - pts.begin();
|
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());
|
uint32_t diff_y = std::abs(it->y() - p.y());
|
||||||
if (diff_y > manhattan_dist) continue;
|
if (diff_y > manhattan_dist) continue;
|
||||||
float diff_x = it->x() - p.x();
|
float diff_x = it->x() - p.x();
|
||||||
@ -125,4 +154,11 @@ size_t Slic3r::find_closest_in_sorted(const P &p, const std::vector<P> &pts)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class P>
|
||||||
|
std::pair<size_t, size_t> find_closest_in_sorted(
|
||||||
|
const std::vector<P> &pts, const std::vector<P> &sorted_pts)
|
||||||
|
{
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // slic3r_ClosestPoint_hpp_
|
#endif // slic3r_ClosestPoint_hpp_
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
#include <libslic3r/ClosestPoint.hpp>
|
#include <libslic3r/ClosestPoint.hpp>
|
||||||
|
#include <libslic3r/Point.hpp>
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
TEST_CASE("Find the closest point from 2", "[ClosestPoint]")
|
TEST_CASE("Find the closest point from 2", "[ClosestPoint]")
|
||||||
{
|
{
|
||||||
Points pts = {{0, 1}, {0, 2}};
|
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<Point>));
|
||||||
CHECK(0 == find_closest_in_sorted(Point{0, 0}, pts));
|
CHECK(0 == find_closest_in_sorted(Point{0, 0}, pts));
|
||||||
CHECK(0 == find_closest_in_sorted(Point{1, 1}, pts));
|
CHECK(0 == find_closest_in_sorted(Point{1, 1}, pts));
|
||||||
CHECK(1 == find_closest_in_sorted(Point{1, 2}, 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
|
// 2 - 5 - 8
|
||||||
Points pts = {{-3, 3}, {-3, 0}, {-3, -3}, {0, 3}, {0, 0},
|
Points pts = {{-3, 3}, {-3, 0}, {-3, -3}, {0, 3}, {0, 0},
|
||||||
{0, -3}, {3, 3}, {3, 0}, {3, -3}};
|
{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<Point>));
|
||||||
|
|
||||||
CHECK(0 == find_closest_in_sorted(Point{-4, 4}, pts));
|
CHECK(0 == find_closest_in_sorted(Point{-4, 4}, pts));
|
||||||
CHECK(0 == find_closest_in_sorted(Point{-2, 2}, 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(7 == find_closest_in_sorted(Point{2, 1}, pts));
|
||||||
CHECK(8 == find_closest_in_sorted(Point{2,-2}, 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));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user