implementing N nearest neighbors search

git-svn-id: http://kdtree.googlecode.com/svn/trunk@28 58b2c0e6-ac2f-0410-a5b6-b51bcff41737
This commit is contained in:
jtsiomb 2009-09-04 13:45:35 +00:00
parent e884a22052
commit f5b74a7b61
2 changed files with 95 additions and 3 deletions

View file

@ -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; i<dim; i++) {
dist_sq += SQ(node->pos[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;

View file

@ -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);