Kd-tree
1. Use the background
There is a problem in the project: How to calculate the nearest distance from a point to a polyline-the vertex of a polyline may have thousands of vertices, and the points that need to be retrieved may have tens of thousands of data, which is really a question to consider ~ 2. Brute Force solution
There is a more intuitive way: Calculate the distance from the point to the polyline, and then violence to find the shortest part ~ Get solution. However, the O (n) Complexity method obviously encounters large data volumes that can seriously slow down the performance of the server. 3.K Proximity algorithm-data structure
The
KNN gives a very ingenious revelation for approximate solutions, which can be obtained by 2d-tree (k=2).
to take a slightly more complicated example, let's find the point (2,4.5), test arrival at (7,2), test arrival (4,7) at (5,4), and then Search_path node in < (7,2), (5,4), (4,7); Remove from Search_path (4,7) as the current best node nearest, dist for 3.202,
then back to (5,4), with (2,4.5) as the center, with dist=3.202 as a radius to draw a circle with the super plane y=4 intersect, as shown below, So you need to jump to (5,4) the left dial hand space to search. So to add (2,3) to the Search_path, now the Search_path node is < (7,2), (2, 3) >; in addition, (5,4) and (2,4.5) the distance is 3.04 < dist = 3.202, so (5,4) Assigned to nearest, and dist=3.04.
Back to (2,3), (2,3) is a leaf node, the direct flat judgment (2,3) is closer to (2,4.5), calculate the distance is 1.5, so nearest update to (2,3), dist update to (1.5)
Back to (7,2), similarly, to ( 2,4.5) for the center, draw a circle with dist=1.5 radius does not intersect with the x=7, so you do not have to jump to the right subspace of the node (7,2) to search.
At this point, Search_path is empty, ending the entire search, returning nearest (2,3) as the nearest neighbor of (2,4.5), and the closest distance is 1.5.
4. Code implementation KDTree.h
#define Lson (RT << 1)//Left node #define Rson (rt << 1 | 1)//Right node #include <vector> #include <algorithm>
;
#include <cmath> const int N = 50005; const int k = 2;
2d-tree struct Node {float feature[2];//feature[0] = x, feature[1] = y static int idx;
Node (float x0, float y0) {feature[0] = x0;
FEATURE[1] = y0;
} BOOL operator < (const Node &u) const {return FEATURE[IDX] < U.FEATURE[IDX];
}//tood =hao Node () {feature[0] = 0;
Feature[0] = 0;
}
};
Class Kdtree {public:kdtree ();
~kdtree ();
void Clean ();
int read_in (float* ary_x, float* ary_y, int len);
void build (int l, int r, int rt, int dept);
int Find_nearest_point (float x, float y, node& result, float& Dist);
float Distance (const node& x, const node& y);
Private void query (const node& p, node& res, float& Dist, int rt, int dept);
Std::vector<node> _data;//uses vector to simulate the array std::vector<int> _flag;//to determine if there is an int _idx;
Std::vector<node> _find_nth;
};
Kd-tree.cpp
#include "KDTree.h" int node::idx = 0;
Kdtree::kdtree () {_data.reserve (N * 4); _flag.reserve (N * 4);//todo init} kdtree::~kdtree () {} int kdtree::read_in (float* ary_x, float* ary_y, int
Len) {_find_nth.reserve (N * 4);
for (int i = 0; i < len; ++i) {Node tmp (Ary_x[i], ary_y[i]);
_find_nth.push_back (Node (Ary_x[i], ary_y[i]));
} for (int i = 0; i < N * 4; ++i) {Node tmp;
_data.push_back (TMP);
_flag.push_back (0);
} build (0, len-1, 1, 0);
return 0;
} void Kdtree::clean () {_find_nth.clear ();
_data.clear ();
_flag.clear ();
}//Establish kd-tree void kdtree::build (int l, int r, int rt, int dept) {if (L > R) return; _FLAG[RT] = 1; A node indicating that the label is RT exists _flag[lson] = _flag[rson] =-1;
The child of the current node is temporarily marked without the presence of int mid = (L + R + 1) >> 1; NOde::idx = dept% K;
Divide std::nth_element (_find_nth.begin () + L, _find_nth.begin () + Mid, _find_nth.begin () + R + 1) according to the attributes that are numbered idx.
_DATA[RT] = _find_nth[mid]; Build (L, Mid-1, Lson, dept + 1);
Recursive left subtree Build (mid + 1, R, Rson, dept + 1);
} int Kdtree::find_nearest_point (float x, float y, node &res, float& Dist) {node p (x, y);
Query (P, RES, dist, 1, 0);
return 0;
}//Find Kd-tree distance p nearest point void Kdtree::query (const node& p, node& res, float& Dist, int rt, int dept) {
if (_flag[rt] = =-1) {return;
}//nodes that do not exist do not traverse float tmp_dist = distance (_data[rt], p); BOOL FG = FALSE; Used to mark whether you need to traverse right subtree int Dim = dept% K;
As with achievements, ensure that the same node's Dim value does not change int x = Lson;
int y = Rson; if (P.feature[dim] >= _data[rt].feature[dim]) {std::swap (x, y); The dim characteristic value of the data p is greater than or equal to the current data, then it needs to go to the right subtree} if (~_flag[x]) {QUery (P, res, dist, x, dept + 1);
Node x exists, then enter subtree to continue traversal} if (Tmp_dist < dist) {//If a smaller distance is found, replace the current result dist res = _data[rt];
dist = tmp_dist;
} tmp_dist = (P.feature[dim]-_data[rt].feature[dim]) * (P.feature[dim]-_data[rt].feature[dim]);
if (Tmp_dist < dist) {//need to continue backtracking FG = true;
} if (~_flag[y] && FG) {query (P, res, dist, y, dept + 1);
}}//Calculate the distance between two points of the square float kdtree::d istance (const node& x, const node& y) {float res = 0;
for (int i = 0; i < K; i++) {res + = (X.feature[i]-y.feature[i]) * (X.feature[i]-y.feature[i]);
} return res;
}
Self-Test no discovery bug~
Reference article:
(http://blog.csdn.net/acdreamers/article/details/44664645/"Kd-tree Implementation")
(HTTP/ blog.csdn.net/silangquan/article/details/41483689/"Detailed kd-tree")
Thanks to the Giants for their sharing