-
Notifications
You must be signed in to change notification settings - Fork 71
/
KDTree.hpp
179 lines (145 loc) · 5.71 KB
/
KDTree.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#pragma once
/// @file KDTree.hpp
/// @author J. Frederico Carvalho
///
/// This is an adaptation of the KD-tree implementation in rosetta code
/// https://rosettacode.org/wiki/K-d_tree
/// It is a reimplementation of the C code using C++.
/// It also includes a few more queries than the original
#include <algorithm>
#include <functional>
#include <list>
#include <memory>
#include <vector>
/// The point type (vector of double precision floats)
using point_t = std::vector<double>;
/// Array of indices
using indexArr = std::vector<size_t>;
/// Pair of point and Index
using pointIndex = typename std::pair<std::vector<double>, size_t>;
class KDNode {
public:
using KDNodePtr = std::shared_ptr<KDNode>;
size_t index;
point_t x;
KDNodePtr left;
KDNodePtr right;
// initializer
KDNode();
KDNode(point_t const&, size_t const&, KDNodePtr const&, KDNodePtr const&);
KDNode(pointIndex const&, KDNodePtr const&, KDNodePtr const&);
~KDNode();
// getter
double coord(size_t const&);
// conversions
explicit operator bool();
explicit operator point_t();
explicit operator size_t();
explicit operator pointIndex();
};
using KDNodePtr = std::shared_ptr<KDNode>;
KDNodePtr NewKDNodePtr();
// square euclidean distance
inline double dist2(point_t const&, point_t const&);
inline double dist2(KDNodePtr const&, KDNodePtr const&);
// Need for sorting
class comparer {
public:
size_t idx;
explicit comparer(size_t idx_);
inline bool compare_idx(std::pair<std::vector<double>, size_t> const&, //
std::pair<std::vector<double>, size_t> const& //
);
};
using pointIndexArr = typename std::vector<pointIndex>;
inline void sort_on_idx(pointIndexArr::iterator const&, //
pointIndexArr::iterator const&, //
size_t idx);
using pointVec = std::vector<point_t>;
class KDTree {
public:
KDTree() = default;
/// Build a KDtree
explicit KDTree(pointVec point_array);
/// Get the point which lies closest to the input point.
/// @param pt input point.
point_t nearest_point(point_t const& pt);
/// Get the index of the point which lies closest to the input point.
///
/// @param pt input point.
size_t nearest_index(point_t const& pt);
/// Get the point and its index which lies closest to the input point.
///
/// @param pt input point.
pointIndex nearest_pointIndex(point_t const& pt);
/// Get both the point and the index of the points closest to the input
/// point.
///
/// @param pt input point.
/// @param num_nearest Number of nearest points to return.
///
/// @returns a vector containing the points and their respective indices
/// which are at a distance smaller than rad to the input point.
pointIndexArr nearest_pointIndices(point_t const& pt,
size_t const& num_nearest);
/// Get the nearest set of points to the given input point.
///
/// @param pt input point.
/// @param num_nearest Number of nearest points to return.
///
/// @returns a vector containing the points which are at a distance smaller
/// than rad to the input point.
pointVec nearest_points(point_t const& pt, size_t const& num_nearest);
/// Get the indices of points closest to the input point.
///
/// @param pt input point.
/// @param num_nearest Number of nearest points to return.
///
/// @returns a vector containing the indices of the points which are at a
/// distance smaller than rad to the input point.
indexArr nearest_indices(point_t const& pt, size_t const& num_nearest);
/// Get both the point and the index of the points which are at a distance
/// smaller than the input radius to the input point.
///
/// @param pt input point.
/// @param rad input radius.
///
/// @returns a vector containing the points and their respective indices
/// which are at a distance smaller than rad to the input point.
pointIndexArr neighborhood(point_t const& pt, double const& rad);
/// Get the points that are at a distance to the input point which is
/// smaller than the input radius.
///
/// @param pt input point.
/// @param rad input radius.
///
/// @returns a vector containing the points which are at a distance smaller
/// than rad to the input point.
pointVec neighborhood_points(point_t const& pt, double const& rad);
/// Get the indices of points that are at a distance to the input point
/// which is smaller than the input radius.
///
/// @param pt input point.
/// @param rad input radius.
///
/// @returns a vector containing the indices of the points which are at a
/// distance smaller than rad to the input point.
indexArr neighborhood_indices(point_t const& pt, double const& rad);
private:
KDNodePtr make_tree(pointIndexArr::iterator const& begin,
pointIndexArr::iterator const& end,
size_t const& level);
void knearest_(KDNodePtr const& branch, point_t const& pt,
size_t const& level, size_t const& num_nearest,
std::list<std::pair<KDNodePtr, double>>& k_nearest_buffer);
void node_query_(KDNodePtr const& branch, point_t const& pt,
size_t const& level, size_t const& num_nearest,
std::list<std::pair<KDNodePtr, double>>& k_nearest_buffer);
// default caller
KDNodePtr nearest_(point_t const& pt);
void neighborhood_(KDNodePtr const& branch, point_t const& pt,
double const& rad2, size_t const& level,
pointIndexArr& nbh);
KDNodePtr root_;
KDNodePtr leaf_;
};