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:
parent
e884a22052
commit
f5b74a7b61
2 changed files with 95 additions and 3 deletions
77
kdtree.c
77
kdtree.c
|
@ -287,6 +287,56 @@ static int find_nearest(struct kdnode *node, const double *pos, double range, st
|
||||||
return added_res;
|
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)
|
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;
|
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);
|
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)
|
struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range)
|
||||||
{
|
{
|
||||||
int ret;
|
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 */
|
/* 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)
|
static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq)
|
||||||
{
|
{
|
||||||
struct res_node *rnode;
|
struct res_node *rnode;
|
||||||
|
|
21
kdtree.h
21
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_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);
|
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.
|
* 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_nearest3(struct kdtree *tree, double x, double y, double z);
|
||||||
struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float 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
|
* This function returns a pointer to a result set, which can be manipulated
|
||||||
* by the kd_res_* functions.
|
* by the kd_res_* functions.
|
||||||
* The returned pointer can be null as an indication of an error. Otherwise
|
* 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.
|
* 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_range(struct kdtree *tree, const double *pos, double range);
|
||||||
struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);
|
struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);
|
||||||
|
|
Loading…
Reference in a new issue