forked from crvs/KDTree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
KDTree.hpp
130 lines (105 loc) · 3.31 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
#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 <memory>
#include <vector>
using point_t = std::vector< double >;
using indexArr = std::vector< size_t >;
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(const point_t &, const size_t &, const KDNodePtr &,
const KDNodePtr &);
KDNode(const pointIndex &, const KDNodePtr &, const KDNodePtr &);
~KDNode();
// getter
double coord(const size_t &);
// 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(const point_t &, const point_t &);
inline double dist2(const KDNodePtr &, const KDNodePtr &);
// euclidean distance
inline double dist(const point_t &, const point_t &);
inline double dist(const KDNodePtr &, const KDNodePtr &);
// Need for sorting
class comparer {
public:
size_t idx;
explicit comparer(size_t idx_);
inline bool compare_idx(
const std::pair< std::vector< double >, size_t > &, //
const std::pair< std::vector< double >, size_t > & //
);
};
using pointIndexArr = typename std::vector< pointIndex >;
inline void sort_on_idx(const pointIndexArr::iterator &, //
const pointIndexArr::iterator &, //
size_t idx);
using pointVec = std::vector< point_t >;
class KDTree {
KDNodePtr root;
KDNodePtr leaf;
KDNodePtr make_tree(const pointIndexArr::iterator &begin, //
const pointIndexArr::iterator &end, //
const size_t &length, //
const size_t &level //
);
public:
KDTree() = default;
explicit KDTree(pointVec point_array);
private:
KDNodePtr nearest_( //
const KDNodePtr &branch, //
const point_t &pt, //
const size_t &level, //
const KDNodePtr &best, //
const double &best_dist //
);
// default caller
KDNodePtr nearest_(const point_t &pt);
public:
point_t nearest_point(const point_t &pt);
size_t nearest_index(const point_t &pt);
pointIndex nearest_pointIndex(const point_t &pt);
private:
pointIndexArr neighborhood_( //
const KDNodePtr &branch, //
const point_t &pt, //
const double &rad, //
const size_t &level //
);
public:
pointIndexArr neighborhood( //
const point_t &pt, //
const double &rad);
pointVec neighborhood_points( //
const point_t &pt, //
const double &rad);
indexArr neighborhood_indices( //
const point_t &pt, //
const double &rad);
};