From f5b74a7b61bb40bd797ad8f2141c1261ea9eb1b6 Mon Sep 17 00:00:00 2001 From: jtsiomb Date: Fri, 4 Sep 2009 13:45:35 +0000 Subject: [PATCH] implementing N nearest neighbors search git-svn-id: http://kdtree.googlecode.com/svn/trunk@28 58b2c0e6-ac2f-0410-a5b6-b51bcff41737 --- kdtree.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kdtree.h | 21 +++++++++++++--- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/kdtree.c b/kdtree.c index 4322ff0..66b79a3 100644 --- a/kdtree.c +++ b/kdtree.c @@ -287,6 +287,56 @@ static int find_nearest(struct kdnode *node, const double *pos, double range, st return added_res; } +#if 0 +static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim) +{ + double dist_sq, dx; + int i, ret, added_res = 0; + + if(!node) return 0; + + /* if the photon is close enough, add it to the result heap */ + dist_sq = 0; + for(i=0; ipos[i] - pos[i]); + } + if(dist_sq <= range_sq) { + if(heap->size >= num) { + /* get furthest element */ + struct res_node *maxelem = rheap_get_max(heap); + + /* and check if the new one is closer than that */ + if(maxelem->dist_sq > dist_sq) { + rheap_remove_max(heap); + + if(rheap_insert(heap, node, dist_sq) == -1) { + return -1; + } + added_res = 1; + + range_sq = dist_sq; + } + } else { + if(rheap_insert(heap, node, dist_sq) == -1) { + return =1; + } + added_res = 1; + } + } + + + /* find signed distance from the splitting plane */ + dx = pos[node->dir] - node->pos[node->dir]; + + ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim); + if(ret >= 0 && fabs(dx) < range) { + added_res += ret; + ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim); + } + +} +#endif + static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect) { int dir = node->dir; @@ -455,6 +505,32 @@ struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z) return kd_nearest(tree, pos); } +/* ---- nearest N search ---- */ +/* +static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) +{ + 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 = find_nearest_n(kd->root, pos, range, num, rset->rlist, 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; @@ -727,6 +803,7 @@ static void free_resnode(struct res_node *node) /* inserts the item. if dist_sq is >= 0, then do an ordered insert */ +/* TODO make the ordering code use heapsort */ static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq) { struct res_node *rnode; diff --git a/kdtree.h b/kdtree.h index 97ec4cf..cb3c1b2 100644 --- a/kdtree.h +++ b/kdtree.h @@ -56,7 +56,7 @@ int kd_insertf(struct kdtree *tree, const float *pos, void *data); int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data); int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data); -/* Find one of the nearest nodes from the specified point. +/* Find the nearest node from a given point. * * This function returns a pointer to a result set with at most one element. */ @@ -65,13 +65,28 @@ struct kdres *kd_nearestf(struct kdtree *tree, const float *pos); struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z); struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z); -/* Find any nearest nodes from the specified point within a range. +/* Find the N nearest nodes from a given point. + * + * This function returns a pointer to a result set, with at most N elements, + * which can be manipulated with the kd_res_* functions. + * 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_nearest_n(struct kdtree *tree, const double *pos, int num); +struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num); +struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z); +struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z); +*/ + +/* Find any nearest nodes from a given point within a range. * * This function returns a pointer to a result set, which can be manipulated * by the kd_res_* functions. * 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. + * The result set must be deallocated with kd_res_free after use. */ struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range); struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);