26KDNode::KDNode() =
default;
28KDNode::KDNode(
const point_t &pt,
const size_t &idx_,
const KDNodePtr &left_,
29 const KDNodePtr &right_) {
36KDNode::KDNode(
const pointIndex &pi,
const KDNodePtr &left_,
37 const KDNodePtr &right_) {
44KDNode::~KDNode() =
default;
46double KDNode::coord(
const size_t &idx) {
return x.at(idx); }
47KDNode::operator bool() {
return (!x.empty()); }
48KDNode::operator point_t() {
return x; }
49KDNode::operator size_t() {
return index; }
50KDNode::operator pointIndex() {
return pointIndex(x, index); }
52KDNodePtr NewKDNodePtr() {
53 KDNodePtr mynode = std::make_shared< KDNode >();
57inline double dist2(
const point_t &a,
const point_t &b) {
59 for (
size_t i = 0; i < a.size(); i++) {
60 double di = a.at(i) - b.at(i);
66inline double dist2(
const KDNodePtr &a,
const KDNodePtr &b) {
67 return dist2(a->x, b->x);
70inline double dist(
const point_t &a,
const point_t &b) {
71 return std::sqrt(dist2(a, b));
74inline double dist(
const KDNodePtr &a,
const KDNodePtr &b) {
75 return std::sqrt(dist2(a, b));
78comparer::comparer(
size_t idx_) : idx{idx_} {};
80inline bool comparer::compare_idx(
const pointIndex &a,
83 return (a.first.at(idx) < b.first.at(idx));
86inline void sort_on_idx(
const pointIndexArr::iterator &begin,
87 const pointIndexArr::iterator &end,
92 using std::placeholders::_1;
93 using std::placeholders::_2;
95 std::nth_element(begin, begin + std::distance(begin, end) / 2,
96 end, std::bind(&comparer::compare_idx, comp, _1, _2));
99using pointVec = std::vector< point_t >;
101KDNodePtr KDTree::make_tree(
const pointIndexArr::iterator &begin,
102 const pointIndexArr::iterator &end,
103 const size_t &length,
107 return NewKDNodePtr();
110 size_t dim =
begin->first.size();
113 sort_on_idx(begin, end, level);
116 auto middle =
begin + (length / 2);
118 auto l_begin =
begin;
120 auto r_begin = middle + 1;
123 size_t l_len = length / 2;
124 size_t r_len = length - l_len - 1;
127 if (l_len > 0 && dim > 0) {
128 left = make_tree(l_begin, l_end, l_len, (level + 1) % dim);
133 if (r_len > 0 && dim > 0) {
134 right = make_tree(r_begin, r_end, r_len, (level + 1) % dim);
140 return std::make_shared< KDNode >(*middle, left, right);
143KDTree::KDTree(pointVec point_array) {
145 qDebug() <<
"CREATING KDETREE INSTANCE";
147 leaf = std::make_shared< KDNode >();
150 for (
size_t i = 0; i < point_array.size(); i++) {
151 arr.push_back(pointIndex(point_array.at(i), i));
154 auto begin = arr.begin();
155 auto end = arr.end();
157 size_t length = arr.size();
160 root = KDTree::make_tree(begin, end, length, level);
162 m_empty = point_array.size();
165KDNodePtr KDTree::nearest_(
166 const KDNodePtr &branch,
169 const KDNodePtr &best,
170 const double &best_dist
174 if (!
bool(*branch)) {
175 return NewKDNodePtr();
178 point_t branch_pt(*branch);
179 size_t dim = branch_pt.size();
181 d = dist2(branch_pt, pt);
182 dx = branch_pt.at(level) - pt.at(level);
185 KDNodePtr best_l = best;
186 double best_dist_l = best_dist;
193 size_t next_lv = (
level + 1) % dim;
199 section = branch->left;
200 other = branch->right;
202 section = branch->right;
203 other = branch->left;
207 KDNodePtr further = nearest_(section, pt, next_lv, best_l, best_dist_l);
208 if (!further->x.empty()) {
209 double dl = dist2(further->x, pt);
210 if (dl < best_dist_l) {
216 if (dx2 < best_dist_l) {
217 further = nearest_(other, pt, next_lv, best_l, best_dist_l);
218 if (!further->x.empty()) {
219 double dl = dist2(further->x, pt);
220 if (dl < best_dist_l) {
231KDNodePtr KDTree::nearest_(
const point_t &pt) {
234 double branch_dist = dist2(point_t(*root), pt);
235 return nearest_(root,
242point_t KDTree::nearest_point(
const point_t &pt) {
243 return point_t(*nearest_(pt));
245size_t KDTree::nearest_index(
const point_t &pt) {
246 return size_t(*nearest_(pt));
249pointIndex KDTree::nearest_pointIndex(
const point_t &pt) {
250 KDNodePtr Nearest = nearest_(pt);
251 return pointIndex(point_t(*Nearest),
size_t(*Nearest));
259pointIndexArr KDTree::neighborhood_(
260 const KDNodePtr &branch,
267 if (!
bool(*branch)) {
270 return pointIndexArr();
273 size_t dim = pt.size();
275 double r2 = rad * rad;
277 d = dist2(point_t(*branch), pt);
278 dx = point_t(*branch).at(level) - pt.at(level);
281 pointIndexArr nbh, nbh_s, nbh_o;
283 nbh.push_back(pointIndex(*branch));
290 section = branch->left;
291 other = branch->right;
293 section = branch->right;
294 other = branch->left;
297 nbh_s = neighborhood_(section, pt, rad, (level + 1) % dim);
298 nbh.insert(nbh.end(), nbh_s.begin(), nbh_s.end());
300 nbh_o = neighborhood_(other, pt, rad, (level + 1) % dim);
301 nbh.insert(nbh.end(), nbh_o.begin(), nbh_o.end());
307pointIndexArr KDTree::neighborhood(
311 return neighborhood_(root, pt, rad, level);
314pointVec KDTree::neighborhood_points(
318 pointIndexArr nbh = neighborhood_(root, pt, rad, level);
320 nbhp.resize(nbh.size());
321 std::transform(nbh.begin(), nbh.end(), nbhp.begin(),
322 [](pointIndex x) { return x.first; });
326indexArr KDTree::neighborhood_indices(
330 pointIndexArr nbh = neighborhood_(root, pt, rad, level);
332 nbhi.resize(nbh.size());
333 std::transform(nbh.begin(), nbh.end(), nbhi.begin(),
334 [](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)