24KDNode::KDNode() =
default;
26KDNode::KDNode(
const point_t &pt,
const size_t &idx_,
const KDNodePtr &left_,
27 const KDNodePtr &right_) {
34KDNode::KDNode(
const pointIndex &pi,
const KDNodePtr &left_,
35 const KDNodePtr &right_) {
42KDNode::~KDNode() =
default;
44double KDNode::coord(
const size_t &idx) {
return x.at(idx); }
45KDNode::operator bool() {
return (!x.empty()); }
46KDNode::operator point_t() {
return x; }
47KDNode::operator size_t() {
return index; }
48KDNode::operator pointIndex() {
return pointIndex(x, index); }
50KDNodePtr NewKDNodePtr() {
51 KDNodePtr mynode = std::make_shared< KDNode >();
55inline double dist2(
const point_t &a,
const point_t &b) {
57 for (
size_t i = 0; i < a.size(); i++) {
58 double di = a.at(i) - b.at(i);
64inline double dist2(
const KDNodePtr &a,
const KDNodePtr &b) {
65 return dist2(a->x, b->x);
68inline double dist(
const point_t &a,
const point_t &b) {
69 return std::sqrt(dist2(a, b));
72inline double dist(
const KDNodePtr &a,
const KDNodePtr &b) {
73 return std::sqrt(dist2(a, b));
76comparer::comparer(
size_t idx_) : idx{idx_} {};
78inline bool comparer::compare_idx(
const pointIndex &a,
81 return (a.first.at(idx) < b.first.at(idx));
84inline void sort_on_idx(
const pointIndexArr::iterator &begin,
85 const pointIndexArr::iterator &end,
90 using std::placeholders::_1;
91 using std::placeholders::_2;
93 std::nth_element(begin, begin + std::distance(begin, end) / 2,
94 end, std::bind(&comparer::compare_idx, comp, _1, _2));
97using pointVec = std::vector< point_t >;
99KDNodePtr KDTree::make_tree(
const pointIndexArr::iterator &begin,
100 const pointIndexArr::iterator &end,
101 const size_t &length,
105 return NewKDNodePtr();
108 size_t dim =
begin->first.size();
111 sort_on_idx(begin, end, level);
114 auto middle =
begin + (length / 2);
116 auto l_begin =
begin;
118 auto r_begin = middle + 1;
121 size_t l_len = length / 2;
122 size_t r_len = length - l_len - 1;
125 if (l_len > 0 && dim > 0) {
126 left = make_tree(l_begin, l_end, l_len, (level + 1) % dim);
131 if (r_len > 0 && dim > 0) {
132 right = make_tree(r_begin, r_end, r_len, (level + 1) % dim);
138 return std::make_shared< KDNode >(*middle, left, right);
141KDTree::KDTree(pointVec point_array) {
142 leaf = std::make_shared< KDNode >();
145 for (
size_t i = 0; i < point_array.size(); i++) {
146 arr.push_back(pointIndex(point_array.at(i), i));
149 auto begin = arr.begin();
150 auto end = arr.end();
152 size_t length = arr.size();
155 root = KDTree::make_tree(begin, end, length, level);
157 m_empty = point_array.size();
160KDNodePtr KDTree::nearest_(
161 const KDNodePtr &branch,
164 const KDNodePtr &best,
165 const double &best_dist
169 if (!
bool(*branch)) {
170 return NewKDNodePtr();
173 point_t branch_pt(*branch);
174 size_t dim = branch_pt.size();
176 d = dist2(branch_pt, pt);
177 dx = branch_pt.at(level) - pt.at(level);
180 KDNodePtr best_l = best;
181 double best_dist_l = best_dist;
188 size_t next_lv = (
level + 1) % dim;
194 section = branch->left;
195 other = branch->right;
197 section = branch->right;
198 other = branch->left;
202 KDNodePtr further = nearest_(section, pt, next_lv, best_l, best_dist_l);
203 if (!further->x.empty()) {
204 double dl = dist2(further->x, pt);
205 if (dl < best_dist_l) {
211 if (dx2 < best_dist_l) {
212 further = nearest_(other, pt, next_lv, best_l, best_dist_l);
213 if (!further->x.empty()) {
214 double dl = dist2(further->x, pt);
215 if (dl < best_dist_l) {
226KDNodePtr KDTree::nearest_(
const point_t &pt) {
229 double branch_dist = dist2(point_t(*root), pt);
230 return nearest_(root,
237point_t KDTree::nearest_point(
const point_t &pt) {
238 return point_t(*nearest_(pt));
240size_t KDTree::nearest_index(
const point_t &pt) {
241 return size_t(*nearest_(pt));
244pointIndex KDTree::nearest_pointIndex(
const point_t &pt) {
245 KDNodePtr Nearest = nearest_(pt);
246 return pointIndex(point_t(*Nearest),
size_t(*Nearest));
254pointIndexArr KDTree::neighborhood_(
255 const KDNodePtr &branch,
262 if (!
bool(*branch)) {
265 return pointIndexArr();
268 size_t dim = pt.size();
270 double r2 = rad * rad;
272 d = dist2(point_t(*branch), pt);
273 dx = point_t(*branch).at(level) - pt.at(level);
276 pointIndexArr nbh, nbh_s, nbh_o;
278 nbh.push_back(pointIndex(*branch));
285 section = branch->left;
286 other = branch->right;
288 section = branch->right;
289 other = branch->left;
292 nbh_s = neighborhood_(section, pt, rad, (level + 1) % dim);
293 nbh.insert(nbh.end(), nbh_s.begin(), nbh_s.end());
295 nbh_o = neighborhood_(other, pt, rad, (level + 1) % dim);
296 nbh.insert(nbh.end(), nbh_o.begin(), nbh_o.end());
302pointIndexArr KDTree::neighborhood(
306 return neighborhood_(root, pt, rad, level);
309pointVec KDTree::neighborhood_points(
313 pointIndexArr nbh = neighborhood_(root, pt, rad, level);
315 nbhp.resize(nbh.size());
316 std::transform(nbh.begin(), nbh.end(), nbhp.begin(),
317 [](pointIndex x) { return x.first; });
321indexArr KDTree::neighborhood_indices(
325 pointIndexArr nbh = neighborhood_(root, pt, rad, level);
327 nbhi.resize(nbh.size());
328 std::transform(nbh.begin(), nbh.end(), nbhi.begin(),
329 [](pointIndex x) { return x.second; });
QStringView level(QStringView ifopt)
const QList< QKeySequence > & begin()
const QList< QKeySequence > & end()
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)