From b146d944c3db6e14eb0c00bf1041b4c41dfaab46 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Thu, 18 Jun 2015 13:55:19 -0400 Subject: [PATCH 1/9] Added kd_in_bounds() --- kdtree.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kdtree.h | 8 +++++++ 2 files changed, 77 insertions(+) diff --git a/kdtree.c b/kdtree.c index 41cd9c0..4cca1a4 100644 --- a/kdtree.c +++ b/kdtree.c @@ -25,6 +25,7 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* single nearest neighbor search written by Tamas Nepusz */ +/* in_bounds written by Philip Kovac */ #ifdef HAVE_CONFIG_H #include @@ -259,6 +260,47 @@ int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data) return kd_insert(tree, buf, data); } +static int in_bounds(struct kdnode *node, const double* min_pos, const double* max_pos, struct res_node *list, int ordered, int dim) +{ + int i, is_in_bounds, ret, added_res = 0; + + if (!node) return 0; + + is_in_bounds = 1; + + for (i=0; ipos[i] < min_pos[i] || node->pos[i] > max_pos[i]) + { + is_in_bounds = 0; + break; + } + + if (is_in_bounds) + { + if (rlist_insert(list, node, -1.0) == -1) { + return -1; + } + added_res = 1; + } + + if (min_pos[node->dir] > node->pos[node->dir]) + { + ret = in_bounds(node->left, min_pos, max_pos, list, ordered, dim); + if (ret == -1) + return -1; + added_res += ret; + } + + if (max_pos[node->dir] < node->pos[node->dir]) + { + ret = in_bounds(node->right, min_pos, max_pos, list, ordered, dim); + if (ret == -1) + return -1; + added_res += ret; + } + + return added_res; +} + static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim) { double dist_sq, dx; @@ -534,6 +576,33 @@ static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) return rset; }*/ +struct kdres *kd_in_bounds(struct kdtree *kd, const double* min_pos, const double* max_pos) +{ + int ret; + struct kdres *rset; + + if (!(rset = malloc(sizeof *rset))) { + return 0; + } + + if (!(rset->rlist = alloc_resnode())) { + free(rset); + return 0; + } + + rset->rlist->next = 0; + rset->tree = kd; + + if ((ret = in_bounds(kd->root, min_pos, max_pos, rset->rlist, 0, kd->dim)) == -1) { + kd_res_free(rset); + return 0; + } + + rset->size = ret; + kd_res_rewind(rset); + return rset; +} + struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range) { int ret; diff --git a/kdtree.h b/kdtree.h index 92d43e4..f29aa1d 100644 --- a/kdtree.h +++ b/kdtree.h @@ -93,6 +93,14 @@ struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float ran struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range); struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range); +/* Find nodes within a given range. + * This function returns a pointer to a result set. + * The returned pointer can be null as an indication of an error. Otherwise + * a valid result set is always returned which may contain 0 or more elements. + * The result set must be deallocated with kd_res_free after use. + */ +struct kdres *kd_in_bounds(struct kdtree *tree, const double *min_pos, const double *max_pos); + /* frees a result set returned by kd_nearest_range() */ void kd_res_free(struct kdres *set); From 8c2d2ec2440a76a44cdd884b34f6d1dac3fb05d4 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Thu, 18 Jun 2015 18:09:33 -0400 Subject: [PATCH 2/9] Added 'inclusive' option to kd_in_bounds --- kdtree.c | 29 +++++++++++++++++++++-------- kdtree.h | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/kdtree.c b/kdtree.c index 4cca1a4..d972e18 100644 --- a/kdtree.c +++ b/kdtree.c @@ -260,7 +260,7 @@ int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data) return kd_insert(tree, buf, data); } -static int in_bounds(struct kdnode *node, const double* min_pos, const double* max_pos, struct res_node *list, int ordered, int dim) +static int in_bounds(struct kdnode *node, const double* min_pos, const double* max_pos, struct res_node *list, int ordered, int dim, int inclusive) { int i, is_in_bounds, ret, added_res = 0; @@ -268,10 +268,23 @@ static int in_bounds(struct kdnode *node, const double* min_pos, const double* m is_in_bounds = 1; - for (i=0; ipos[i] < min_pos[i] || node->pos[i] > max_pos[i]) + if (inclusive) { - is_in_bounds = 0; - break; + for (i=0; ipos[i] < min_pos[i] || node->pos[i] > max_pos[i]) + { + is_in_bounds = 0; + break; + } + } + else + { + for (i=0; ipos[i] <= min_pos[i] || node->pos[i] >= max_pos[i]) + { + is_in_bounds = 0; + break; + } } if (is_in_bounds) @@ -284,7 +297,7 @@ static int in_bounds(struct kdnode *node, const double* min_pos, const double* m if (min_pos[node->dir] > node->pos[node->dir]) { - ret = in_bounds(node->left, min_pos, max_pos, list, ordered, dim); + ret = in_bounds(node->left, min_pos, max_pos, list, ordered, dim, inclusive); if (ret == -1) return -1; added_res += ret; @@ -292,7 +305,7 @@ static int in_bounds(struct kdnode *node, const double* min_pos, const double* m if (max_pos[node->dir] < node->pos[node->dir]) { - ret = in_bounds(node->right, min_pos, max_pos, list, ordered, dim); + ret = in_bounds(node->right, min_pos, max_pos, list, ordered, dim, inclusive); if (ret == -1) return -1; added_res += ret; @@ -576,7 +589,7 @@ static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) return rset; }*/ -struct kdres *kd_in_bounds(struct kdtree *kd, const double* min_pos, const double* max_pos) +struct kdres *kd_in_bounds(struct kdtree *kd, const double* min_pos, const double* max_pos, int inclusive) { int ret; struct kdres *rset; @@ -593,7 +606,7 @@ struct kdres *kd_in_bounds(struct kdtree *kd, const double* min_pos, const doubl rset->rlist->next = 0; rset->tree = kd; - if ((ret = in_bounds(kd->root, min_pos, max_pos, rset->rlist, 0, kd->dim)) == -1) { + if ((ret = in_bounds(kd->root, min_pos, max_pos, rset->rlist, 0, kd->dim, inclusive)) == -1) { kd_res_free(rset); return 0; } diff --git a/kdtree.h b/kdtree.h index f29aa1d..9115269 100644 --- a/kdtree.h +++ b/kdtree.h @@ -99,7 +99,7 @@ struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, * a valid result set is always returned which may contain 0 or more elements. * The result set must be deallocated with kd_res_free after use. */ -struct kdres *kd_in_bounds(struct kdtree *tree, const double *min_pos, const double *max_pos); +struct kdres *kd_in_bounds(struct kdtree *tree, const double *min_pos, const double *max_pos, int inclusive); /* frees a result set returned by kd_nearest_range() */ void kd_res_free(struct kdres *set); From 08ec22438465a5ce082cdebe1975f0e5bee6542b Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Thu, 25 Jun 2015 13:38:02 -0400 Subject: [PATCH 3/9] Fixed some missing negations in in_bounds (thanks adufilie); added optimization for equal nodes. --- kdtree.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/kdtree.c b/kdtree.c index d972e18..4a8a690 100644 --- a/kdtree.c +++ b/kdtree.c @@ -64,7 +64,7 @@ struct kdnode { int dir; void *data; - struct kdnode *left, *right; /* negative/positive side */ + struct kdnode *left, *right, *next; /* negative/positive/equal side */ }; struct res_node { @@ -139,6 +139,7 @@ static void clear_rec(struct kdnode *node, void (*destr)(void*)) if(!node) return; clear_rec(node->left, destr); + clear_rec(node->next, destr); clear_rec(node->right, destr); if(destr) { @@ -167,7 +168,7 @@ void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)) static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim) { - int new_dir; + int new_dir, pos_idx; struct kdnode *node; if(!*nptr) { @@ -188,10 +189,25 @@ static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int d node = *nptr; new_dir = (node->dir + 1) % dim; + if(pos[node->dir] < node->pos[node->dir]) { - return insert_rec(&(*nptr)->left, pos, data, new_dir, dim); + return insert_rec(&(node->left), pos, data, new_dir, dim); } - return insert_rec(&(*nptr)->right, pos, data, new_dir, dim); + else if (pos[node->dir] == node->pos[node->dir]) + { + /* Test for equality of all position info */ + for (pos_idx = 0; pos_idx < dim; pos_idx++) + if (pos[pos_idx] != node->pos[pos_idx]) break; + + if (pos_idx == dim) /* all were equal, we didn't break */ + { + /* Instead of building up a huge callstack for no reason, just zip to the end */ + for (; node->next; node = node->next); + return insert_rec(&(node->next), pos, data, dir, dim); + } + } + + return insert_rec(&(node->right), pos, data, new_dir, dim); } int kd_insert(struct kdtree *tree, const double *pos, void *data) @@ -295,7 +311,7 @@ static int in_bounds(struct kdnode *node, const double* min_pos, const double* m added_res = 1; } - if (min_pos[node->dir] > node->pos[node->dir]) + if (!(min_pos[node->dir] > node->pos[node->dir])) { ret = in_bounds(node->left, min_pos, max_pos, list, ordered, dim, inclusive); if (ret == -1) @@ -303,7 +319,7 @@ static int in_bounds(struct kdnode *node, const double* min_pos, const double* m added_res += ret; } - if (max_pos[node->dir] < node->pos[node->dir]) + if (!(max_pos[node->dir] < node->pos[node->dir])) { ret = in_bounds(node->right, min_pos, max_pos, list, ordered, dim, inclusive); if (ret == -1) From 1648955da9ba56da95d143f1e9396f03452e954a Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Thu, 25 Jun 2015 14:30:36 -0400 Subject: [PATCH 4/9] Added expansion for equal-node optimization result lists. --- kdtree.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/kdtree.c b/kdtree.c index 4a8a690..773a6c9 100644 --- a/kdtree.c +++ b/kdtree.c @@ -71,6 +71,7 @@ struct res_node { struct kdnode *item; double dist_sq; struct res_node *next; + int expanded; }; struct kdtree { @@ -723,6 +724,7 @@ int kd_res_size(struct kdres *set) void kd_res_rewind(struct kdres *rset) { rset->riter = rset->rlist->next; + if (!(rset->expanded)) res_expand(rset); } int kd_res_end(struct kdres *rset) @@ -736,6 +738,39 @@ int kd_res_next(struct kdres *rset) return rset->riter != 0; } +static int res_expand_node(struct res_node** rnode) +{ + int size_inc = 0; + struct kdnode* node, oldnode; + node = rnode->item; + while (node->next) + { + rnode = (rnode->next = alloc_resnode()); + + rnode->item = node->next; + oldnode = node; + node = node->next; + size_inc++; + } + return size_inc; +} + +static int res_expand(struct kdres *rset) +{ + struct kdnode* parent_node, child_node; + struct res_node* rnode, next_node; + if (rset->expanded) return 0; /* Has already been expanded, don't do anything */ + rnode = rset->riter; + while (rnode) + { + next_node = rnode->next; + rset->size += res_expand_node(&rnode); + rnode = (rnode->next = next_node); + } + rset->expanded = 1; + return 0; +} + void *kd_res_item(struct kdres *rset, double *pos) { if(rset->riter) { From 278ad2f47e8f70a5928f7747b3e30eddc0d41088 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Tue, 30 Jun 2015 18:03:34 -0400 Subject: [PATCH 5/9] Unwound recursion in insert_rec, in_bounds, clear_rec --- kdtree.c | 282 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 169 insertions(+), 113 deletions(-) diff --git a/kdtree.c b/kdtree.c index 773a6c9..43a83b5 100644 --- a/kdtree.c +++ b/kdtree.c @@ -71,13 +71,15 @@ struct res_node { struct kdnode *item; double dist_sq; struct res_node *next; - int expanded; }; struct kdtree { int dim; struct kdnode *root; struct kdhyperrect *rect; + + struct kdnode** node_stack; + size_t depth, node_stack_head, node_stack_max; void (*destr)(void*); }; @@ -85,13 +87,14 @@ struct kdres { struct kdtree *tree; struct res_node *rlist, *riter; int size; + int expanded; }; #define SQ(x) ((x) * (x)) -static void clear_rec(struct kdnode *node, void (*destr)(void*)); -static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim); +static void clear_rec(struct kdtree *tree, void (*destr)(void*)); +static int insert_rec(struct kdnode **node, const double *pos, void *data, int dim); static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq); static void clear_results(struct kdres *set); @@ -109,7 +112,28 @@ static void free_resnode(struct res_node*); #define free_resnode(n) free(n) #endif +static inline void node_stack_prep(struct kdtree* tree) +{ + if (!tree->node_stack || tree->node_stack_max < tree->depth) + { + if (tree->node_stack) + free(tree->node_stack); + tree->node_stack = malloc(sizeof(struct kdnode*) * tree->depth); + tree->node_stack_max = tree->depth; + } +} +static inline struct kdnode* node_stack_pop(struct kdtree* tree) +{ + if (tree->node_stack_head == 0) + return NULL; + else + return tree->node_stack[tree->node_stack_head--]; +} +static inline void node_stack_push(struct kdtree* tree, struct kdnode* node) +{ + tree->node_stack[tree->node_stack_head++] = node; +} struct kdtree *kd_create(int k) { @@ -123,6 +147,7 @@ struct kdtree *kd_create(int k) tree->root = 0; tree->destr = 0; tree->rect = 0; + tree->depth = 0; return tree; } @@ -135,25 +160,37 @@ void kd_free(struct kdtree *tree) } } -static void clear_rec(struct kdnode *node, void (*destr)(void*)) +static void clear_rec(struct kdtree *tree, void (*destr)(void*)) { - if(!node) return; + struct kdnode* node; - clear_rec(node->left, destr); - clear_rec(node->next, destr); - clear_rec(node->right, destr); - - if(destr) { - destr(node->data); + node_stack_prep(tree); + + while ((node = node_stack_pop(tree))) + { + if (node->left) node_stack_push(tree, node->left); + if (node->next) node_stack_push(tree, node->next); + if (node->right) node_stack_push(tree, node->right); + + if (destr) { + destr(node->data); + }; + free(node->pos); + free(node); } - free(node->pos); - free(node); } void kd_clear(struct kdtree *tree) { - clear_rec(tree->root, tree->destr); + clear_rec(tree, tree->destr); tree->root = 0; + tree->depth = 0; + if (tree->node_stack) + { + free(tree->node_stack); + tree->node_stack = 0; + tree->node_stack_head = tree->node_stack_max = 0; + } if (tree->rect) { hyperrect_free(tree->rect); @@ -167,55 +204,74 @@ void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)) } -static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim) +static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dim) { - int new_dir, pos_idx; struct kdnode *node; + size_t depth = 0; + int pos_idx, dir, new_dir = 0; + while (*nptr) + { + depth++; + node = *nptr; + dir = node->dir; + new_dir = (dir + 1) % dim; - if(!*nptr) { - if(!(node = malloc(sizeof *node))) { - return -1; + if (pos[dir] < node->pos[dir]) + { + nptr = &(node->left); + continue; } - if(!(node->pos = malloc(dim * sizeof *node->pos))) { - free(node); - return -1; + else if (pos[dir] == node->pos[dir]) + { + for (pos_idx = 0; pos_idx < dim; pos_idx++) + if (pos[pos_idx] != node->pos[pos_idx]) break; + if (pos_idx == dim) + { + while (node->next) + node = node->next; + nptr = &(node->next); + break; + } + } + else /* pos[dir] > node->pos[dir] */ + { + nptr = &(node->right); + continue; } - memcpy(node->pos, pos, dim * sizeof *node->pos); - node->data = data; - node->dir = dir; - node->left = node->right = 0; - *nptr = node; - return 0; } - node = *nptr; - new_dir = (node->dir + 1) % dim; - - if(pos[node->dir] < node->pos[node->dir]) { - return insert_rec(&(node->left), pos, data, new_dir, dim); + if(!(node = malloc(sizeof *node))) { + return -1; } - else if (pos[node->dir] == node->pos[node->dir]) - { - /* Test for equality of all position info */ - for (pos_idx = 0; pos_idx < dim; pos_idx++) - if (pos[pos_idx] != node->pos[pos_idx]) break; - if (pos_idx == dim) /* all were equal, we didn't break */ - { - /* Instead of building up a huge callstack for no reason, just zip to the end */ - for (; node->next; node = node->next); - return insert_rec(&(node->next), pos, data, dir, dim); - } + if(!(node->pos = malloc(dim * sizeof *node->pos))) { + free(node); + return -1; } - return insert_rec(&(node->right), pos, data, new_dir, dim); + memcpy(node->pos, pos, dim * sizeof *node->pos); + + node->data = data; + node->dir = new_dir; + node->left = node->right = node->next = 0; + *nptr = node; + + return depth + 1; } int kd_insert(struct kdtree *tree, const double *pos, void *data) { - if (insert_rec(&tree->root, pos, data, 0, tree->dim)) { + int result; + + result = insert_rec(&tree->root, pos, data, tree->dim); + + if (result == -1) { return -1; } + else + { + if (result > tree->depth) tree->depth = result; + } if (tree->rect == 0) { tree->rect = hyperrect_create(tree->dim, pos, pos); @@ -277,55 +333,50 @@ int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data) return kd_insert(tree, buf, data); } -static int in_bounds(struct kdnode *node, const double* min_pos, const double* max_pos, struct res_node *list, int ordered, int dim, int inclusive) +static int in_bounds(struct kdtree* tree, const double* min_pos, const double* max_pos, struct res_node *list, int ordered, int dim, int inclusive) { - int i, is_in_bounds, ret, added_res = 0; - - if (!node) return 0; + int i, is_in_bounds, added_res = 0; + struct kdnode* node; - is_in_bounds = 1; + node_stack_prep(tree); + node_stack_push(tree, tree->root); - if (inclusive) + while ((node = node_stack_pop(tree))) { - for (i=0; ipos[i] < min_pos[i] || node->pos[i] > max_pos[i]) - { - is_in_bounds = 0; - break; - } - } - else - { - for (i=0; ipos[i] <= min_pos[i] || node->pos[i] >= max_pos[i]) - { - is_in_bounds = 0; - break; - } - } + is_in_bounds = 1; - if (is_in_bounds) - { - if (rlist_insert(list, node, -1.0) == -1) { - return -1; + if (inclusive) + { + for (i=0; ipos[i] < min_pos[i] || node->pos[i] > max_pos[i]) + { + is_in_bounds = 0; + break; + } + } + else + { + for (i=0; ipos[i] <= min_pos[i] || node->pos[i] >= max_pos[i]) + { + is_in_bounds = 0; + break; + } } - added_res = 1; - } - if (!(min_pos[node->dir] > node->pos[node->dir])) - { - ret = in_bounds(node->left, min_pos, max_pos, list, ordered, dim, inclusive); - if (ret == -1) - return -1; - added_res += ret; - } + if (is_in_bounds) + { + if (rlist_insert(list, node, -1.0) == -1) { + return -1; + } + added_res++; + } - if (!(max_pos[node->dir] < node->pos[node->dir])) - { - ret = in_bounds(node->right, min_pos, max_pos, list, ordered, dim, inclusive); - if (ret == -1) - return -1; - added_res += ret; + if (!(min_pos[node->dir] > node->pos[node->dir]) && node->left) + node_stack_push(tree, node->left); + + if (!(max_pos[node->dir] < node->pos[node->dir]) && node->right) + node_stack_push(tree, node->right); } return added_res; @@ -493,6 +544,7 @@ struct kdres *kd_nearest(struct kdtree *kd, const double *pos) return 0; } rset->rlist->next = 0; + rset->expanded = 0; rset->tree = kd; /* Duplicate the bounding hyperrectangle, we will work on the copy */ @@ -595,6 +647,7 @@ static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) return 0; } rset->rlist->next = 0; + rset->expanded = 0; rset->tree = kd; if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) { @@ -621,9 +674,10 @@ struct kdres *kd_in_bounds(struct kdtree *kd, const double* min_pos, const doubl } rset->rlist->next = 0; + rset->expanded = 0; rset->tree = kd; - if ((ret = in_bounds(kd->root, min_pos, max_pos, rset->rlist, 0, kd->dim, inclusive)) == -1) { + if ((ret = in_bounds(kd, min_pos, max_pos, rset->rlist, 0, kd->dim, inclusive)) == -1) { kd_res_free(rset); return 0; } @@ -646,6 +700,7 @@ struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double rang return 0; } rset->rlist->next = 0; + rset->expanded = 0; rset->tree = kd; if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) { @@ -721,34 +776,16 @@ int kd_res_size(struct kdres *set) return (set->size); } -void kd_res_rewind(struct kdres *rset) -{ - rset->riter = rset->rlist->next; - if (!(rset->expanded)) res_expand(rset); -} - -int kd_res_end(struct kdres *rset) -{ - return rset->riter == 0; -} - -int kd_res_next(struct kdres *rset) -{ - rset->riter = rset->riter->next; - return rset->riter != 0; -} - static int res_expand_node(struct res_node** rnode) { int size_inc = 0; - struct kdnode* node, oldnode; - node = rnode->item; + struct kdnode *node; + node = (*rnode)->item; while (node->next) { - rnode = (rnode->next = alloc_resnode()); + *rnode = ((*rnode)->next = alloc_resnode()); - rnode->item = node->next; - oldnode = node; + (*rnode)->item = node->next; node = node->next; size_inc++; } @@ -757,9 +794,9 @@ static int res_expand_node(struct res_node** rnode) static int res_expand(struct kdres *rset) { - struct kdnode* parent_node, child_node; - struct res_node* rnode, next_node; - if (rset->expanded) return 0; /* Has already been expanded, don't do anything */ + struct res_node *rnode, *next_node; + if (rset->expanded) + return 0; /* Has already been expanded, don't do anything */ rnode = rset->riter; while (rnode) { @@ -771,6 +808,24 @@ static int res_expand(struct kdres *rset) return 0; } +void kd_res_rewind(struct kdres *rset) +{ + rset->riter = rset->rlist->next; + if (!(rset->expanded)) + res_expand(rset); +} + +int kd_res_end(struct kdres *rset) +{ + return rset->riter == 0; +} + +int kd_res_next(struct kdres *rset) +{ + rset->riter = rset->riter->next; + return rset->riter != 0; +} + void *kd_res_item(struct kdres *rset, double *pos) { if(rset->riter) { @@ -971,4 +1026,5 @@ static void clear_results(struct kdres *rset) } rset->rlist->next = 0; + rset->expanded = 0; } From 6dff9b054f3f25469a45ac836d0a8066a67d3cc3 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Tue, 30 Jun 2015 18:13:24 -0400 Subject: [PATCH 6/9] Fixed uninitialized memory bugs in new stack logic. --- kdtree.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kdtree.c b/kdtree.c index 43a83b5..eb7857b 100644 --- a/kdtree.c +++ b/kdtree.c @@ -120,6 +120,7 @@ static inline void node_stack_prep(struct kdtree* tree) free(tree->node_stack); tree->node_stack = malloc(sizeof(struct kdnode*) * tree->depth); tree->node_stack_max = tree->depth; + tree->node_stack_head = 0; } } @@ -148,6 +149,9 @@ struct kdtree *kd_create(int k) tree->destr = 0; tree->rect = 0; tree->depth = 0; + tree->node_stack = 0; + tree->node_stack_max = 0; + tree->node_stack_head = 0; return tree; } @@ -185,6 +189,7 @@ void kd_clear(struct kdtree *tree) clear_rec(tree, tree->destr); tree->root = 0; tree->depth = 0; + if (tree->node_stack) { free(tree->node_stack); From 7ec2c729173f6a8a9d7834a3e01ddde410056622 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Tue, 30 Jun 2015 18:21:49 -0400 Subject: [PATCH 7/9] Fixed off-by-one in stack functions. --- kdtree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kdtree.c b/kdtree.c index eb7857b..4bffe08 100644 --- a/kdtree.c +++ b/kdtree.c @@ -79,7 +79,8 @@ struct kdtree { struct kdhyperrect *rect; struct kdnode** node_stack; - size_t depth, node_stack_head, node_stack_max; + size_t depth, node_stack_max; + int node_stack_head; void (*destr)(void*); }; @@ -129,7 +130,7 @@ static inline struct kdnode* node_stack_pop(struct kdtree* tree) if (tree->node_stack_head == 0) return NULL; else - return tree->node_stack[tree->node_stack_head--]; + return tree->node_stack[--tree->node_stack_head]; } static inline void node_stack_push(struct kdtree* tree, struct kdnode* node) { From 79e9b05e1233f110c913e1e571f0c1ecd720b770 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Tue, 30 Jun 2015 18:39:16 -0400 Subject: [PATCH 8/9] Added test for kd_in_bounds --- examples/Makefile | 3 ++- examples/test3 | Bin 0 -> 21932 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100755 examples/test3 diff --git a/examples/Makefile b/examples/Makefile index dab0f7e..ea683e4 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -5,10 +5,11 @@ CFLAGS = -std=c89 -pedantic -Wall -g -I.. LDFLAGS = $(kdlib) -lm .PHONY: all -all: test test2 +all: test test2 test3 test: test.c $(kdlib) test2: test2.c $(kdlib) +test3: test3.c $(kdlib) .PHONY: clean clean: diff --git a/examples/test3 b/examples/test3 new file mode 100755 index 0000000000000000000000000000000000000000..4850b3a1a4cd9de9e76e8bb396d6aa3468a5b3ff GIT binary patch literal 21932 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%0DoXVAPD9BBX%mB=u)f@RxEy<>yNac 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 TB!vkrc4Loj(D978tM-2Y;P>_U literal 0 HcmV?d00001 From 77125fc53f955f2cedd90794f3cb9fbd0dd32cf2 Mon Sep 17 00:00:00 2001 From: "Philip \"digitalfox\" Kovac" Date: Tue, 30 Jun 2015 18:40:16 -0400 Subject: [PATCH 9/9] Added the wrong file. --- examples/test.c | 4 +- examples/test2.c | 2 +- examples/test3 | Bin 21932 -> 0 bytes examples/test3.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 3 deletions(-) delete mode 100755 examples/test3 create mode 100644 examples/test3.c diff --git a/examples/test.c b/examples/test.c index 89e6195..76defd2 100644 --- a/examples/test.c +++ b/examples/test.c @@ -23,7 +23,7 @@ unsigned int get_msec(void) int main(int argc, char **argv) { - int i, vcount = 10; + int i, vcount = 10000; void *kd, *set; unsigned int msec, start; @@ -52,7 +52,7 @@ int main(int argc, char **argv) msec = get_msec() - start; printf("range query returned %d items in %.5f sec\n", kd_res_size(set), (float)msec / 1000.0); kd_res_free(set); - + kd_clear(kd); kd_free(kd); return 0; } diff --git a/examples/test2.c b/examples/test2.c index f06859a..ae6c3d1 100644 --- a/examples/test2.c +++ b/examples/test2.c @@ -8,7 +8,7 @@ #include #include "kdtree.h" -#define DEF_NUM_PTS 10 +#define DEF_NUM_PTS 10000 /* returns the distance squared between two dims-dimensional double arrays */ static double dist_sq( double *a1, double *a2, int dims ); diff --git a/examples/test3 b/examples/test3 deleted file mode 100755 index 4850b3a1a4cd9de9e76e8bb396d6aa3468a5b3ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21932 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%0DoXVAPD9BBX%mB=u)f@RxEy<>yNac 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 TB!vkrc4Loj(D978tM-2Y;P>_U diff --git a/examples/test3.c b/examples/test3.c new file mode 100644 index 0000000..88a09fc --- /dev/null +++ b/examples/test3.c @@ -0,0 +1,94 @@ +/*! gcc -std=c89 -pedantic -Wall -g -o test2 test2.c libkdtree.a -lm */ +/* Extended test program, contributed by David Underhill */ +#include +#include +#include +#include +#include +#include +#include "kdtree.h" + +#define DEF_NUM_PTS 10000 +#define DIM 3 + +/* returns the distance squared between two dims-dimensional double arrays */ +static double dist_sq( double *a1, double *a2, int dims ); + +/* get a random double between -10 and 10 */ +static double rd( void ); + +int main(int argc, char **argv) { + int i, num_pts = DEF_NUM_PTS; + void *ptree; + char *data, *pch; + struct kdres *presults; + double pos[3], dist, minpos[3], maxpos[3]; + double pt[3] = { 0, 0, 1 }; + double radius = 10; + + if(argc > 1 && isdigit(argv[1][0])) { + num_pts = atoi(argv[1]); + } + + if(!(data = malloc(num_pts))) { + perror("malloc failed"); + return 1; + } + + srand( time(0) ); + + /* create a k-d tree for 3-dimensional points */ + ptree = kd_create( DIM ); + + /* add some random nodes to the tree (assert nodes are successfully inserted) */ + for( i=0; i= 0 ) { + diff = (a1[dims] - a2[dims]); + dist_sq += diff*diff; + } + return dist_sq; +} + +static double rd( void ) { + return (double)rand()/RAND_MAX * 20.0 - 10.0; +}