Skip to content

Commit b5f3c83

Browse files
committed
Improve kd-tree implementation, and fix tester
1 parent cbeb4a9 commit b5f3c83

File tree

5 files changed

+32
-30
lines changed

5 files changed

+32
-30
lines changed

TODO.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ Things to do
22
============
33

44
* Fix convex hull edge case (some small edge case that included at least three collinear lines would return the same point on both the upper and lower hull)
5-
* Fix 2d-Tree (for some reason it's segfaulting on tests)
65
* Shortest Path Faster Algorithm
76
* Prim's algorithm
87
* More formulas for geometry, trigonometry, сombinatorics, number theory

code/data-structures/kd_tree.cpp

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,31 +65,24 @@ template <int K> struct kd_tree {
6565
void clear() { _clr(root); root = NULL; }
6666
void _clr(node *n) {
6767
if (n) _clr(n->l), _clr(n->r), delete n; }
68-
pt nearest_neighbour(const pt &p, bool allow_same=true) {
69-
assert(root);
68+
pair<pt, bool> nearest_neighbour(const pt &p,
69+
bool allow_same=true) {
7070
double mn = INFINITY, cs[K];
7171
rep(i,0,K) cs[i] = -INFINITY;
7272
pt from(cs);
7373
rep(i,0,K) cs[i] = INFINITY;
74-
pt to(cs);
75-
return _nn(p, root, bb(from, to), mn, 0, allow_same).first;
76-
}
77-
pair<pt, bool> _nn(const pt &p, node *n, bb b,
78-
double &mn, int c, bool same) {
79-
if (!n || b.dist(p) > mn) return make_pair(pt(), false);
80-
bool found = same || p.dist(n->p) > EPS,
81-
l1 = true, l2 = false;
82-
pt resp = n->p;
83-
if (found) mn = min(mn, p.dist(resp));
74+
pt to(cs), resp;
75+
_nn(p, root, bb(from, to), mn, resp, 0, allow_same);
76+
return make_pair(resp, !std::isinf(mn)); }
77+
void _nn(const pt &p, node *n, bb b,
78+
double &mn, pt &resp, int c, bool same) {
79+
if (!n || b.dist(p) > mn) return;
80+
bool l1 = true, l2 = false;
81+
if ((same || p.dist(n->p) > EPS) && p.dist(n->p) < mn)
82+
mn = p.dist(resp = n->p);
8483
node *n1 = n->l, *n2 = n->r;
8584
rep(i,0,2) {
86-
if (i == 1 || cmp(c)(n->p, p))
87-
swap(n1, n2), swap(l1, l2);
88-
pair<pt, bool> res =_nn(p, n1,
89-
b.bound(n->p.coord[c], c, l1), mn, INC(c), same);
90-
if (res.second &&
91-
(!found || p.dist(res.first) < p.dist(resp)))
92-
resp = res.first, found = true;
93-
}
94-
return make_pair(resp, found); } };
85+
if (i == 1 || cmp(c)(n->p, p)) swap(n1,n2),swap(l1,l2);
86+
_nn(p, n1, b.bound(n->p.coord[c], c, l1), mn,
87+
resp, INC(c), same); } } };
9588
// vim: cc=60 ts=2 sts=2 sw=2:

code/data-structures/kd_tree.test.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,20 @@ struct naive_kd_tree {
4141
pts.insert(p);
4242
}
4343

44-
point nearest_neighbour(const point &p, bool allow_same = true) {
44+
pair<point, bool> nearest_neighbour(const point &p, bool allow_same = true) {
4545
double mn = INFINITY;
4646
point res;
47+
bool found = false;
4748
for (typename set<point>::const_iterator it = pts.begin(); it != pts.end(); ++it) {
4849
double dist = p.dist_to(*it);
4950
if (abs(dist) < EPS && !allow_same) continue;
5051
if (dist < mn) {
5152
mn = dist;
5253
res = *it;
54+
found = true;
5355
}
5456
}
55-
56-
return res;
57+
return make_pair(res, found);
5758
}
5859
};
5960

@@ -149,19 +150,29 @@ void test() {
149150
bool allow_same = rand() % 2 == 0;
150151
// bool allow_same = true;
151152
#if TREE1
152-
kd_tree<CURK>::pt a = tree1.nearest_neighbour(kd_tree<CURK>::pt(pt), allow_same);
153+
pair<kd_tree<CURK>::pt, bool> a = tree1.nearest_neighbour(kd_tree<CURK>::pt(pt), allow_same);
154+
#endif
155+
156+
#if TREE2
157+
pair<naive_kd_tree<CURK>::point, bool> b = tree2.nearest_neighbour(naive_kd_tree<CURK>::point(pt), allow_same);
153158
#endif
154159

160+
#if TREE1 && TREE2
161+
assert(a.second == b.second);
162+
#endif
163+
#if TREE1
164+
if (!a.second) continue;
165+
#endif
155166
#if TREE2
156-
naive_kd_tree<CURK>::point b = tree2.nearest_neighbour(naive_kd_tree<CURK>::point(pt), allow_same);
167+
if (!b.second) continue;
157168
#endif
158169

159170
#if TREE1
160-
double x = a.dist(kd_tree<CURK>::pt(pt));
171+
double x = a.first.dist(kd_tree<CURK>::pt(pt));
161172
#endif
162173

163174
#if TREE2
164-
double y = b.dist_to(naive_kd_tree<CURK>::point(pt));
175+
double y = b.first.dist_to(naive_kd_tree<CURK>::point(pt));
165176
#endif
166177

167178
#if TREE1 && TREE2

comprog.pdf

-20 Bytes
Binary file not shown.

comprog.tex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ \section{Data Structures}
183183
A $k$-dimensional tree supporting fast construction, adding points, and
184184
nearest neighbor queries.
185185
\fi
186-
NOTE: Not completely stable, occasionally segfaults.
187186
\code{data-structures/kd_tree.cpp}
188187
\fi
189188

0 commit comments

Comments
 (0)