rb_kd_tree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kd_tree.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ryan Closner
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # KDTree
2
+
3
+ KDTree is a Ruby wrapper for John Tsiombikas' KDTree library written in C. It supports K dimensional tree nearest neighbor searches.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kd_tree'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kd_tree
18
+
19
+ ## Usage
20
+
21
+ Iniitalize a new KDTree with a multi-dimensional array of nodes, and an integer specifying how many dimensions each node has:
22
+
23
+ ```ruby
24
+ tree = KDTree.new([ [1, 2, 3], [ 4, 5, 6] ], 3)
25
+ #=> #<KDTree:0x007ffca8568748>
26
+ ```
27
+
28
+ Insert additional nodes:
29
+
30
+ ```ruby
31
+ tree.insert([7, 8, 9])
32
+ #=> [ 7, 8, 9 ]
33
+ ```
34
+
35
+ Perform a nearest neighbor search:
36
+
37
+ ```ruby
38
+ tree.nearest_neighbor([ 1, 2, 3 ])
39
+ #=> { "query"=>[1, 2, 3], "position"=>[1.0, 2.0, 3.0], "distance"=>0.0 }
40
+
41
+ tree.nearest_neighbor([ 4, 5, 6])
42
+ #=> { "query"=>[4, 5, 6], "position"=>[4.0, 5.0, 6.0], "distance"=>0.0 }
43
+
44
+ tree.nearest_neigbor([ 100, 101, 102 ])
45
+ #=> { "query"=>[100, 101, 102], "position"=>[4.0, 5.0, 6.0], "distance"=>27648.0 }
46
+ ```
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+
4
+ Rake::ExtensionTask.new("kd_tree")
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('kd_tree/kd_tree')
@@ -0,0 +1,114 @@
1
+ #include <ruby.h>
2
+ #include "vendor/kdtree.c"
3
+
4
+ VALUE cKDTreeNode;
5
+
6
+ struct kdtree * get_tree_from_klass(VALUE klass)
7
+ {
8
+ struct kdtree * pointer;
9
+ Data_Get_Struct(klass, struct kdtree, pointer);
10
+ return pointer;
11
+ }
12
+
13
+ static VALUE kd_tree_alloc(VALUE klass)
14
+ {
15
+ struct kdtree *tree;
16
+
17
+ if (!(tree = malloc(sizeof *tree))) {
18
+ return 0;
19
+ }
20
+
21
+ tree->root = 0;
22
+ tree->destr = 0;
23
+ tree->rect = 0;
24
+
25
+ VALUE object = Data_Make_Struct(klass, struct kdtree, 0, kd_free, tree);
26
+
27
+ return object;
28
+ }
29
+
30
+ static VALUE kd_tree_insert(VALUE klass, VALUE position)
31
+ {
32
+ struct kdtree *tree = get_tree_from_klass(klass);
33
+ position = rb_check_array_type(position);
34
+
35
+ if (NIL_P(position) || RARRAY_LEN(position) != tree->dim) {
36
+ rb_raise(rb_eRuntimeError, "nodes contain invalid array dimensions");
37
+ }
38
+
39
+ int i;
40
+ double pos[tree->dim];
41
+
42
+ for (i = 0; i < tree->dim; i++) {
43
+ pos[i] = NUM2DBL(rb_ary_entry(position, i));
44
+ }
45
+
46
+ kd_insert(tree, pos, 0);
47
+
48
+ return position;
49
+ }
50
+
51
+ static VALUE kd_tree_init(VALUE klass, VALUE nodes, VALUE dims)
52
+ {
53
+ Check_Type(nodes, T_ARRAY);
54
+ Check_Type(dims, T_FIXNUM);
55
+
56
+ struct kdtree *tree = get_tree_from_klass(klass);
57
+
58
+ tree->dim = NUM2INT(dims);
59
+
60
+ int i;
61
+ for (i = 0; i < RARRAY_LEN(nodes); i++) {
62
+ kd_tree_insert(klass, rb_ary_entry(nodes, i));
63
+ }
64
+
65
+ return klass;
66
+ }
67
+
68
+ static VALUE kd_tree_nearest(VALUE klass, VALUE position)
69
+ {
70
+ Check_Type(position, T_ARRAY);
71
+
72
+ struct kdtree *tree = get_tree_from_klass(klass);
73
+ struct kdhyperrect *rect;
74
+ struct kdnode *result_node = tree->root;
75
+ double pos[tree->dim];
76
+ double dist_sq;
77
+ int i;
78
+
79
+ if (!tree) return 0;
80
+ if (!tree->rect) return 0;
81
+ if (!(rect = hyperrect_duplicate(tree->rect))) return 0;
82
+
83
+ for (i = 0; i < tree->dim; i++) {
84
+ pos[i] = NUM2DBL(rb_ary_entry(position, i));
85
+ dist_sq += SQ(result_node->pos[i] - pos[i]);
86
+ }
87
+
88
+ kd_nearest_i(tree->root, pos, &result_node, &dist_sq, rect);
89
+ hyperrect_free(rect);
90
+
91
+ VALUE result = rb_hash_new();
92
+
93
+ if (result_node) {
94
+ VALUE result_node_pos = rb_ary_new();
95
+
96
+ for (i = 0; i < tree->dim; i++) {
97
+ rb_ary_push(result_node_pos, DBL2NUM(result_node->pos[i]));
98
+ }
99
+
100
+ rb_hash_aset(result, rb_str_new2("query"), position);
101
+ rb_hash_aset(result, rb_str_new2("position"), result_node_pos);
102
+ rb_hash_aset(result, rb_str_new2("distance"), DBL2NUM(dist_sq));
103
+ }
104
+
105
+ return result;
106
+ }
107
+
108
+ void Init_kd_tree(void) {
109
+ VALUE cKDTree = rb_define_class("KDTree", rb_cObject);
110
+ rb_define_alloc_func(cKDTree, kd_tree_alloc);
111
+ rb_define_method(cKDTree, "initialize", kd_tree_init, 2);
112
+ rb_define_method(cKDTree, "insert", kd_tree_insert, 1);
113
+ rb_define_method(cKDTree, "nearest_neighbor", kd_tree_nearest, 1);
114
+ }
@@ -0,0 +1,836 @@
1
+ /*
2
+ This file is part of ``kdtree'', a library for working with kd-trees.
3
+ Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org>
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+ 3. The name of the author may not be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
+ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
+ OF SUCH DAMAGE.
26
+ */
27
+ /* single nearest neighbor search written by Tamas Nepusz <tamas@cs.rhul.ac.uk> */
28
+ #include <stdio.h>
29
+ #include <stdlib.h>
30
+ #include <string.h>
31
+ #include <math.h>
32
+ #include "kdtree.h"
33
+
34
+ #if defined(WIN32) || defined(__WIN32__)
35
+ #include <malloc.h>
36
+ #endif
37
+
38
+ #ifdef USE_LIST_NODE_ALLOCATOR
39
+
40
+ #ifndef NO_PTHREADS
41
+ #include <pthread.h>
42
+ #else
43
+
44
+ #ifndef I_WANT_THREAD_BUGS
45
+ #error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads."
46
+ #endif /* I want thread bugs */
47
+
48
+ #endif /* pthread support */
49
+ #endif /* use list node allocator */
50
+
51
+ struct kdhyperrect {
52
+ int dim;
53
+ double *min, *max; /* minimum/maximum coords */
54
+ };
55
+
56
+ struct kdnode {
57
+ double *pos;
58
+ int dir;
59
+ void *data;
60
+
61
+ struct kdnode *left, *right; /* negative/positive side */
62
+ };
63
+
64
+ struct res_node {
65
+ struct kdnode *item;
66
+ double dist_sq;
67
+ struct res_node *next;
68
+ };
69
+
70
+ struct kdtree {
71
+ int dim;
72
+ struct kdnode *root;
73
+ struct kdhyperrect *rect;
74
+ void (*destr)(void*);
75
+ };
76
+
77
+ struct kdres {
78
+ struct kdtree *tree;
79
+ struct res_node *rlist, *riter;
80
+ int size;
81
+ };
82
+
83
+ #define SQ(x) ((x) * (x))
84
+
85
+
86
+ static void clear_rec(struct kdnode *node, void (*destr)(void*));
87
+ static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim);
88
+ static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq);
89
+ static void clear_results(struct kdres *set);
90
+
91
+ static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max);
92
+ static void hyperrect_free(struct kdhyperrect *rect);
93
+ static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect);
94
+ static void hyperrect_extend(struct kdhyperrect *rect, const double *pos);
95
+ static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos);
96
+
97
+ #ifdef USE_LIST_NODE_ALLOCATOR
98
+ static struct res_node *alloc_resnode(void);
99
+ static void free_resnode(struct res_node*);
100
+ #else
101
+ #define alloc_resnode() malloc(sizeof(struct res_node))
102
+ #define free_resnode(n) free(n)
103
+ #endif
104
+
105
+
106
+
107
+ struct kdtree *kd_create(int k)
108
+ {
109
+ struct kdtree *tree;
110
+
111
+ if(!(tree = malloc(sizeof *tree))) {
112
+ return 0;
113
+ }
114
+
115
+ tree->dim = k;
116
+ tree->root = 0;
117
+ tree->destr = 0;
118
+ tree->rect = 0;
119
+
120
+ return tree;
121
+ }
122
+
123
+ void kd_free(struct kdtree *tree)
124
+ {
125
+ if(tree) {
126
+ kd_clear(tree);
127
+ free(tree);
128
+ }
129
+ }
130
+
131
+ static void clear_rec(struct kdnode *node, void (*destr)(void*))
132
+ {
133
+ if(!node) return;
134
+
135
+ clear_rec(node->left, destr);
136
+ clear_rec(node->right, destr);
137
+
138
+ if(destr) {
139
+ destr(node->data);
140
+ }
141
+ free(node->pos);
142
+ free(node);
143
+ }
144
+
145
+ void kd_clear(struct kdtree *tree)
146
+ {
147
+ clear_rec(tree->root, tree->destr);
148
+ tree->root = 0;
149
+
150
+ if (tree->rect) {
151
+ hyperrect_free(tree->rect);
152
+ tree->rect = 0;
153
+ }
154
+ }
155
+
156
+ void kd_data_destructor(struct kdtree *tree, void (*destr)(void*))
157
+ {
158
+ tree->destr = destr;
159
+ }
160
+
161
+
162
+ static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim)
163
+ {
164
+ int new_dir;
165
+ struct kdnode *node;
166
+
167
+ if(!*nptr) {
168
+ if(!(node = malloc(sizeof *node))) {
169
+ return -1;
170
+ }
171
+ if(!(node->pos = malloc(dim * sizeof *node->pos))) {
172
+ free(node);
173
+ return -1;
174
+ }
175
+ memcpy(node->pos, pos, dim * sizeof *node->pos);
176
+ node->data = data;
177
+ node->dir = dir;
178
+ node->left = node->right = 0;
179
+ *nptr = node;
180
+ return 0;
181
+ }
182
+
183
+ node = *nptr;
184
+ new_dir = (node->dir + 1) % dim;
185
+ if(pos[node->dir] < node->pos[node->dir]) {
186
+ return insert_rec(&(*nptr)->left, pos, data, new_dir, dim);
187
+ }
188
+ return insert_rec(&(*nptr)->right, pos, data, new_dir, dim);
189
+ }
190
+
191
+ int kd_insert(struct kdtree *tree, const double *pos, void *data)
192
+ {
193
+ if (insert_rec(&tree->root, pos, data, 0, tree->dim)) {
194
+ return -1;
195
+ }
196
+
197
+ if (tree->rect == 0) {
198
+ tree->rect = hyperrect_create(tree->dim, pos, pos);
199
+ } else {
200
+ hyperrect_extend(tree->rect, pos);
201
+ }
202
+
203
+ return 0;
204
+ }
205
+
206
+ int kd_insertf(struct kdtree *tree, const float *pos, void *data)
207
+ {
208
+ static double sbuf[16];
209
+ double *bptr, *buf = 0;
210
+ int res, dim = tree->dim;
211
+
212
+ if(dim > 16) {
213
+ #ifndef NO_ALLOCA
214
+ if(dim <= 256)
215
+ bptr = buf = alloca(dim * sizeof *bptr);
216
+ else
217
+ #endif
218
+ if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
219
+ return -1;
220
+ }
221
+ } else {
222
+ bptr = buf = sbuf;
223
+ }
224
+
225
+ while(dim-- > 0) {
226
+ *bptr++ = *pos++;
227
+ }
228
+
229
+ res = kd_insert(tree, buf, data);
230
+ #ifndef NO_ALLOCA
231
+ if(tree->dim > 256)
232
+ #else
233
+ if(tree->dim > 16)
234
+ #endif
235
+ free(buf);
236
+ return res;
237
+ }
238
+
239
+ int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data)
240
+ {
241
+ double buf[3];
242
+ buf[0] = x;
243
+ buf[1] = y;
244
+ buf[2] = z;
245
+ return kd_insert(tree, buf, data);
246
+ }
247
+
248
+ int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data)
249
+ {
250
+ double buf[3];
251
+ buf[0] = x;
252
+ buf[1] = y;
253
+ buf[2] = z;
254
+ return kd_insert(tree, buf, data);
255
+ }
256
+
257
+ static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim)
258
+ {
259
+ double dist_sq, dx;
260
+ int i, ret, added_res = 0;
261
+
262
+ if(!node) return 0;
263
+
264
+ dist_sq = 0;
265
+ for(i=0; i<dim; i++) {
266
+ dist_sq += SQ(node->pos[i] - pos[i]);
267
+ }
268
+ if(dist_sq <= SQ(range)) {
269
+ if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) {
270
+ return -1;
271
+ }
272
+ added_res = 1;
273
+ }
274
+
275
+ dx = pos[node->dir] - node->pos[node->dir];
276
+
277
+ ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim);
278
+ if(ret >= 0 && fabs(dx) < range) {
279
+ added_res += ret;
280
+ ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim);
281
+ }
282
+ if(ret == -1) {
283
+ return -1;
284
+ }
285
+ added_res += ret;
286
+
287
+ return added_res;
288
+ }
289
+
290
+ #if 0
291
+ static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim)
292
+ {
293
+ double dist_sq, dx;
294
+ int i, ret, added_res = 0;
295
+
296
+ if(!node) return 0;
297
+
298
+ /* if the photon is close enough, add it to the result heap */
299
+ dist_sq = 0;
300
+ for(i=0; i<dim; i++) {
301
+ dist_sq += SQ(node->pos[i] - pos[i]);
302
+ }
303
+ if(dist_sq <= range_sq) {
304
+ if(heap->size >= num) {
305
+ /* get furthest element */
306
+ struct res_node *maxelem = rheap_get_max(heap);
307
+
308
+ /* and check if the new one is closer than that */
309
+ if(maxelem->dist_sq > dist_sq) {
310
+ rheap_remove_max(heap);
311
+
312
+ if(rheap_insert(heap, node, dist_sq) == -1) {
313
+ return -1;
314
+ }
315
+ added_res = 1;
316
+
317
+ range_sq = dist_sq;
318
+ }
319
+ } else {
320
+ if(rheap_insert(heap, node, dist_sq) == -1) {
321
+ return =1;
322
+ }
323
+ added_res = 1;
324
+ }
325
+ }
326
+
327
+
328
+ /* find signed distance from the splitting plane */
329
+ dx = pos[node->dir] - node->pos[node->dir];
330
+
331
+ ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim);
332
+ if(ret >= 0 && fabs(dx) < range) {
333
+ added_res += ret;
334
+ ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim);
335
+ }
336
+
337
+ }
338
+ #endif
339
+
340
+ static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect)
341
+ {
342
+ int dir = node->dir;
343
+ int i;
344
+ double dummy, dist_sq;
345
+ struct kdnode *nearer_subtree, *farther_subtree;
346
+ double *nearer_hyperrect_coord, *farther_hyperrect_coord;
347
+
348
+ /* Decide whether to go left or right in the tree */
349
+ dummy = pos[dir] - node->pos[dir];
350
+ if (dummy <= 0) {
351
+ nearer_subtree = node->left;
352
+ farther_subtree = node->right;
353
+ nearer_hyperrect_coord = rect->max + dir;
354
+ farther_hyperrect_coord = rect->min + dir;
355
+ } else {
356
+ nearer_subtree = node->right;
357
+ farther_subtree = node->left;
358
+ nearer_hyperrect_coord = rect->min + dir;
359
+ farther_hyperrect_coord = rect->max + dir;
360
+ }
361
+
362
+ if (nearer_subtree) {
363
+ /* Slice the hyperrect to get the hyperrect of the nearer subtree */
364
+ dummy = *nearer_hyperrect_coord;
365
+ *nearer_hyperrect_coord = node->pos[dir];
366
+ /* Recurse down into nearer subtree */
367
+ kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
368
+ /* Undo the slice */
369
+ *nearer_hyperrect_coord = dummy;
370
+ }
371
+
372
+ /* Check the distance of the point at the current node, compare it
373
+ * with our best so far */
374
+ dist_sq = 0;
375
+ for(i=0; i < rect->dim; i++) {
376
+ dist_sq += SQ(node->pos[i] - pos[i]);
377
+ }
378
+ if (dist_sq < *result_dist_sq) {
379
+ *result = node;
380
+ *result_dist_sq = dist_sq;
381
+ }
382
+
383
+ if (farther_subtree) {
384
+ /* Get the hyperrect of the farther subtree */
385
+ dummy = *farther_hyperrect_coord;
386
+ *farther_hyperrect_coord = node->pos[dir];
387
+ /* Check if we have to recurse down by calculating the closest
388
+ * point of the hyperrect and see if it's closer than our
389
+ * minimum distance in result_dist_sq. */
390
+ if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {
391
+ /* Recurse down into farther subtree */
392
+ kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
393
+ }
394
+ /* Undo the slice on the hyperrect */
395
+ *farther_hyperrect_coord = dummy;
396
+ }
397
+ }
398
+
399
+ struct kdres *kd_nearest(struct kdtree *kd, const double *pos)
400
+ {
401
+ struct kdhyperrect *rect;
402
+ struct kdnode *result;
403
+ struct kdres *rset;
404
+ double dist_sq;
405
+ int i;
406
+
407
+ if (!kd) return 0;
408
+ if (!kd->rect) return 0;
409
+
410
+ /* Allocate result set */
411
+ if(!(rset = malloc(sizeof *rset))) {
412
+ return 0;
413
+ }
414
+ if(!(rset->rlist = alloc_resnode())) {
415
+ free(rset);
416
+ return 0;
417
+ }
418
+ rset->rlist->next = 0;
419
+ rset->tree = kd;
420
+
421
+ /* Duplicate the bounding hyperrectangle, we will work on the copy */
422
+ if (!(rect = hyperrect_duplicate(kd->rect))) {
423
+ kd_res_free(rset);
424
+ return 0;
425
+ }
426
+
427
+ /* Our first guesstimate is the root node */
428
+ result = kd->root;
429
+ dist_sq = 0;
430
+ for (i = 0; i < kd->dim; i++)
431
+ dist_sq += SQ(result->pos[i] - pos[i]);
432
+
433
+ /* Search for the nearest neighbour recursively */
434
+ kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);
435
+
436
+ /* Free the copy of the hyperrect */
437
+ hyperrect_free(rect);
438
+
439
+ /* Store the result */
440
+ if (result) {
441
+ if (rlist_insert(rset->rlist, result, -1.0) == -1) {
442
+ kd_res_free(rset);
443
+ return 0;
444
+ }
445
+ rset->size = 1;
446
+ kd_res_rewind(rset);
447
+ return rset;
448
+ } else {
449
+ kd_res_free(rset);
450
+ return 0;
451
+ }
452
+ }
453
+
454
+ struct kdres *kd_nearestf(struct kdtree *tree, const float *pos)
455
+ {
456
+ static double sbuf[16];
457
+ double *bptr, *buf = 0;
458
+ int dim = tree->dim;
459
+ struct kdres *res;
460
+
461
+ if(dim > 16) {
462
+ #ifndef NO_ALLOCA
463
+ if(dim <= 256)
464
+ bptr = buf = alloca(dim * sizeof *bptr);
465
+ else
466
+ #endif
467
+ if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
468
+ return 0;
469
+ }
470
+ } else {
471
+ bptr = buf = sbuf;
472
+ }
473
+
474
+ while(dim-- > 0) {
475
+ *bptr++ = *pos++;
476
+ }
477
+
478
+ res = kd_nearest(tree, buf);
479
+ #ifndef NO_ALLOCA
480
+ if(tree->dim > 256)
481
+ #else
482
+ if(tree->dim > 16)
483
+ #endif
484
+ free(buf);
485
+ return res;
486
+ }
487
+
488
+ struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z)
489
+ {
490
+ double pos[3];
491
+ pos[0] = x;
492
+ pos[1] = y;
493
+ pos[2] = z;
494
+ return kd_nearest(tree, pos);
495
+ }
496
+
497
+ struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z)
498
+ {
499
+ double pos[3];
500
+ pos[0] = x;
501
+ pos[1] = y;
502
+ pos[2] = z;
503
+ return kd_nearest(tree, pos);
504
+ }
505
+
506
+ /* ---- nearest N search ---- */
507
+ /*
508
+ static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num)
509
+ {
510
+ int ret;
511
+ struct kdres *rset;
512
+
513
+ if(!(rset = malloc(sizeof *rset))) {
514
+ return 0;
515
+ }
516
+ if(!(rset->rlist = alloc_resnode())) {
517
+ free(rset);
518
+ return 0;
519
+ }
520
+ rset->rlist->next = 0;
521
+ rset->tree = kd;
522
+
523
+ if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) {
524
+ kd_res_free(rset);
525
+ return 0;
526
+ }
527
+ rset->size = ret;
528
+ kd_res_rewind(rset);
529
+ return rset;
530
+ }*/
531
+
532
+ struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range)
533
+ {
534
+ int ret;
535
+ struct kdres *rset;
536
+
537
+ if(!(rset = malloc(sizeof *rset))) {
538
+ return 0;
539
+ }
540
+ if(!(rset->rlist = alloc_resnode())) {
541
+ free(rset);
542
+ return 0;
543
+ }
544
+ rset->rlist->next = 0;
545
+ rset->tree = kd;
546
+
547
+ if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {
548
+ kd_res_free(rset);
549
+ return 0;
550
+ }
551
+ rset->size = ret;
552
+ kd_res_rewind(rset);
553
+ return rset;
554
+ }
555
+
556
+ struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range)
557
+ {
558
+ static double sbuf[16];
559
+ double *bptr, *buf = 0;
560
+ int dim = kd->dim;
561
+ struct kdres *res;
562
+
563
+ if(dim > 16) {
564
+ #ifndef NO_ALLOCA
565
+ if(dim <= 256)
566
+ bptr = buf = alloca(dim * sizeof *bptr);
567
+ else
568
+ #endif
569
+ if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
570
+ return 0;
571
+ }
572
+ } else {
573
+ bptr = buf = sbuf;
574
+ }
575
+
576
+ while(dim-- > 0) {
577
+ *bptr++ = *pos++;
578
+ }
579
+
580
+ res = kd_nearest_range(kd, buf, range);
581
+ #ifndef NO_ALLOCA
582
+ if(kd->dim > 256)
583
+ #else
584
+ if(kd->dim > 16)
585
+ #endif
586
+ free(buf);
587
+ return res;
588
+ }
589
+
590
+ struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range)
591
+ {
592
+ double buf[3];
593
+ buf[0] = x;
594
+ buf[1] = y;
595
+ buf[2] = z;
596
+ return kd_nearest_range(tree, buf, range);
597
+ }
598
+
599
+ struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range)
600
+ {
601
+ double buf[3];
602
+ buf[0] = x;
603
+ buf[1] = y;
604
+ buf[2] = z;
605
+ return kd_nearest_range(tree, buf, range);
606
+ }
607
+
608
+ void kd_res_free(struct kdres *rset)
609
+ {
610
+ clear_results(rset);
611
+ free_resnode(rset->rlist);
612
+ free(rset);
613
+ }
614
+
615
+ int kd_res_size(struct kdres *set)
616
+ {
617
+ return (set->size);
618
+ }
619
+
620
+ void kd_res_rewind(struct kdres *rset)
621
+ {
622
+ rset->riter = rset->rlist->next;
623
+ }
624
+
625
+ int kd_res_end(struct kdres *rset)
626
+ {
627
+ return rset->riter == 0;
628
+ }
629
+
630
+ int kd_res_next(struct kdres *rset)
631
+ {
632
+ rset->riter = rset->riter->next;
633
+ return rset->riter != 0;
634
+ }
635
+
636
+ void *kd_res_item(struct kdres *rset, double *pos)
637
+ {
638
+ if(rset->riter) {
639
+ if(pos) {
640
+ memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos);
641
+ }
642
+ return rset->riter->item->data;
643
+ }
644
+ return 0;
645
+ }
646
+
647
+ void *kd_res_itemf(struct kdres *rset, float *pos)
648
+ {
649
+ if(rset->riter) {
650
+ if(pos) {
651
+ int i;
652
+ for(i=0; i<rset->tree->dim; i++) {
653
+ pos[i] = rset->riter->item->pos[i];
654
+ }
655
+ }
656
+ return rset->riter->item->data;
657
+ }
658
+ return 0;
659
+ }
660
+
661
+ void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z)
662
+ {
663
+ if(rset->riter) {
664
+ if(*x) *x = rset->riter->item->pos[0];
665
+ if(*y) *y = rset->riter->item->pos[1];
666
+ if(*z) *z = rset->riter->item->pos[2];
667
+ }
668
+ return 0;
669
+ }
670
+
671
+ void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z)
672
+ {
673
+ if(rset->riter) {
674
+ if(*x) *x = rset->riter->item->pos[0];
675
+ if(*y) *y = rset->riter->item->pos[1];
676
+ if(*z) *z = rset->riter->item->pos[2];
677
+ }
678
+ return 0;
679
+ }
680
+
681
+ void *kd_res_item_data(struct kdres *set)
682
+ {
683
+ return kd_res_item(set, 0);
684
+ }
685
+
686
+ /* ---- hyperrectangle helpers ---- */
687
+ static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max)
688
+ {
689
+ size_t size = dim * sizeof(double);
690
+ struct kdhyperrect* rect = 0;
691
+
692
+ if (!(rect = malloc(sizeof(struct kdhyperrect)))) {
693
+ return 0;
694
+ }
695
+
696
+ rect->dim = dim;
697
+ if (!(rect->min = malloc(size))) {
698
+ free(rect);
699
+ return 0;
700
+ }
701
+ if (!(rect->max = malloc(size))) {
702
+ free(rect->min);
703
+ free(rect);
704
+ return 0;
705
+ }
706
+ memcpy(rect->min, min, size);
707
+ memcpy(rect->max, max, size);
708
+
709
+ return rect;
710
+ }
711
+
712
+ static void hyperrect_free(struct kdhyperrect *rect)
713
+ {
714
+ free(rect->min);
715
+ free(rect->max);
716
+ free(rect);
717
+ }
718
+
719
+ static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect)
720
+ {
721
+ return hyperrect_create(rect->dim, rect->min, rect->max);
722
+ }
723
+
724
+ static void hyperrect_extend(struct kdhyperrect *rect, const double *pos)
725
+ {
726
+ int i;
727
+
728
+ for (i=0; i < rect->dim; i++) {
729
+ if (pos[i] < rect->min[i]) {
730
+ rect->min[i] = pos[i];
731
+ }
732
+ if (pos[i] > rect->max[i]) {
733
+ rect->max[i] = pos[i];
734
+ }
735
+ }
736
+ }
737
+
738
+ static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos)
739
+ {
740
+ int i;
741
+ double result = 0;
742
+
743
+ for (i=0; i < rect->dim; i++) {
744
+ if (pos[i] < rect->min[i]) {
745
+ result += SQ(rect->min[i] - pos[i]);
746
+ } else if (pos[i] > rect->max[i]) {
747
+ result += SQ(rect->max[i] - pos[i]);
748
+ }
749
+ }
750
+
751
+ return result;
752
+ }
753
+
754
+ /* ---- static helpers ---- */
755
+
756
+ #ifdef USE_LIST_NODE_ALLOCATOR
757
+ /* special list node allocators. */
758
+ static struct res_node *free_nodes;
759
+
760
+ #ifndef NO_PTHREADS
761
+ static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER;
762
+ #endif
763
+
764
+ static struct res_node *alloc_resnode(void)
765
+ {
766
+ struct res_node *node;
767
+
768
+ #ifndef NO_PTHREADS
769
+ pthread_mutex_lock(&alloc_mutex);
770
+ #endif
771
+
772
+ if(!free_nodes) {
773
+ node = malloc(sizeof *node);
774
+ } else {
775
+ node = free_nodes;
776
+ free_nodes = free_nodes->next;
777
+ node->next = 0;
778
+ }
779
+
780
+ #ifndef NO_PTHREADS
781
+ pthread_mutex_unlock(&alloc_mutex);
782
+ #endif
783
+
784
+ return node;
785
+ }
786
+
787
+ static void free_resnode(struct res_node *node)
788
+ {
789
+ #ifndef NO_PTHREADS
790
+ pthread_mutex_lock(&alloc_mutex);
791
+ #endif
792
+
793
+ node->next = free_nodes;
794
+ free_nodes = node;
795
+
796
+ #ifndef NO_PTHREADS
797
+ pthread_mutex_unlock(&alloc_mutex);
798
+ #endif
799
+ }
800
+ #endif /* list node allocator or not */
801
+
802
+
803
+ /* inserts the item. if dist_sq is >= 0, then do an ordered insert */
804
+ /* TODO make the ordering code use heapsort */
805
+ static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq)
806
+ {
807
+ struct res_node *rnode;
808
+
809
+ if(!(rnode = alloc_resnode())) {
810
+ return -1;
811
+ }
812
+ rnode->item = item;
813
+ rnode->dist_sq = dist_sq;
814
+
815
+ if(dist_sq >= 0.0) {
816
+ while(list->next && list->next->dist_sq < dist_sq) {
817
+ list = list->next;
818
+ }
819
+ }
820
+ rnode->next = list->next;
821
+ list->next = rnode;
822
+ return 0;
823
+ }
824
+
825
+ static void clear_results(struct kdres *rset)
826
+ {
827
+ struct res_node *tmp, *node = rset->rlist->next;
828
+
829
+ while(node) {
830
+ tmp = node;
831
+ node = node->next;
832
+ free_resnode(tmp);
833
+ }
834
+
835
+ rset->rlist->next = 0;
836
+ }