예제 #1
0
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 i, side;
	double dummy, dist_sq;
	struct kdnode *nearer_subtree, *farther_subtree;
	double *nearer_hyperrect_coord, *farther_hyperrect_coord;
    
	/* Decide whether to go left or right in the tree */
	dummy = pos[dir] - node->pos[dir];
	if (dummy <= 0) {
		nearer_subtree = node->left;
		farther_subtree = node->right;
		nearer_hyperrect_coord = rect->max + dir;
		farther_hyperrect_coord = rect->min + dir;
		side = 0;
	} else {
		nearer_subtree = node->right;
		farther_subtree = node->left;
		nearer_hyperrect_coord = rect->min + dir;
		farther_hyperrect_coord = rect->max + dir;
		side = 1;
	}
    
	if (nearer_subtree) {
		/* Slice the hyperrect to get the hyperrect of the nearer subtree */
		dummy = *nearer_hyperrect_coord;
		*nearer_hyperrect_coord = node->pos[dir];
		/* Recurse down into nearer subtree */
		kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
		/* Undo the slice */
		*nearer_hyperrect_coord = dummy;
	}
    
	/* Check the distance of the point at the current node, compare it
	 * with our best so far */
	dist_sq = 0;
	for(i=0; i < rect->dim; i++) {
		dist_sq += SQ(node->pos[i] - pos[i]);
	}
	if (dist_sq < *result_dist_sq) {
		*result = node;
		*result_dist_sq = dist_sq;
	}
    
	if (farther_subtree) {
		/* Get the hyperrect of the farther subtree */
		dummy = *farther_hyperrect_coord;
		*farther_hyperrect_coord = node->pos[dir];
		/* Check if we have to recurse down by calculating the closest
		 * point of the hyperrect and see if it's closer than our
		 * minimum distance in result_dist_sq. */
		if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {
			/* Recurse down into farther subtree */
			kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
		}
		/* Undo the slice on the hyperrect */
		*farther_hyperrect_coord = dummy;
	}
}
예제 #2
0
파일: kdtree.c 프로젝트: TNick/aitown
struct kdnode *kd_find_exact(struct kdtree *kd, const double *pos)
{
    struct kdhyperrect *rect;
    struct kdnode *result;
    double dist_sq;
    int i;

    if (!kd) return 0;
    if (!kd->rect) return 0;

    /* Duplicate the bounding hyperrectangle, we will work on the copy */
    if (!(rect = hyperrect_duplicate(kd->rect))) {
        return NULL;
    }

    /* Our first guesstimate is the root node */
    result = kd->root;
    dist_sq = 0;
    for (i = 0; i < kd->dim; i++)
        dist_sq += SQ(result->pos[i] - pos[i]);

    /* Search for the nearest neighbour recursively */
    kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);

    /* Free the copy of the hyperrect */
    hyperrect_free(rect);

    return dist_sq == 0.0 ? result : NULL;
}
예제 #3
0
파일: kdtree.c 프로젝트: ahmadyan/Duplex
struct kdres *kd_nearest(struct kdtree *kd, const double *pos) {
  struct kdhyperrect *rect;
  struct kdnode *result;
  struct kdres *rset;
  double dist_sq;
  int i;

  if (!kd)
    return 0;
  if (!kd->rect)
    return 0;

  /* Allocate result set */
  if (!(rset = malloc(sizeof *rset))) {
    return 0;
  }
  if (!(rset->rlist = alloc_resnode())) {
    free(rset);
    return 0;
  }
  rset->rlist->next = 0;
  rset->tree = kd;

  /* Duplicate the bounding hyperrectangle, we will work on the copy */
  if (!(rect = hyperrect_duplicate(kd->rect))) {
    kd_res_free(rset);
    return 0;
  }

  /* Our first guesstimate is the root node */
  result = kd->root;
  dist_sq = 0;
  for (i = 0; i < kd->dim; i++)
    dist_sq += SQ(result->pos[i] - pos[i]);

  /* Search for the nearest neighbour recursively */
  kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);

  /* Free the copy of the hyperrect */
  hyperrect_free(rect);

  /* Store the result */
  if (result) {
    if (rlist_insert(rset->rlist, result, -1.0) == -1) {
      kd_res_free(rset);
      return 0;
    }
    rset->size = 1;
    kd_res_rewind(rset);
    return rset;
  } else {
    kd_res_free(rset);
    return 0;
  }
}
예제 #4
0
 /// return a point in the tree that is nearest to the given point
 /// false is returned if the tree is empty. 
 std::pair<point_type,bool> nearest( const point_type& pos) {
     if (!root_) return std::make_pair(pos,false);
     num_nearest_i_calls=0;
     kd_hyperrect<point_type> rect = *rect_;
     kd_node<point_type>* result;
     /* Our first guesstimate is the root node */
     result = root_;
     /* Search for the nearest neighbour recursively */
     double result_dist = root_->pos.dist(pos);
     kd_nearest_i( root_, pos, result, result_dist , rect);
     return std::make_pair( result->pos, true);
 }
예제 #5
0
    /// find nearest point
    void kd_nearest_i(kd_node<point_type> *node, const point_type pos, 
                       kd_node<point_type>*& result, double& result_dist_sq , kd_hyperrect<point_type>& rect) {
        int dir = node->dir;
        num_nearest_i_calls++;
        //int i;
        //double dummy;
        kd_node<point_type> *nearer_subtree, *farther_subtree;
        double nearer_hyperrect_coord, farther_hyperrect_coord;

        /* Decide whether to go left or right in the tree */
        //dummy = pos[dir] - node->pos[dir];
        //if (dummy <= 0) {
            bool b;
        if (pos[dir] <= node->pos[dir]) {
            nearer_subtree = node->left;
            farther_subtree = node->right;
            nearer_hyperrect_coord  = rect.max[dir];
            farther_hyperrect_coord = rect.min[dir];
            b= true;
        } else {
            nearer_subtree = node->right;
            farther_subtree = node->left;
            nearer_hyperrect_coord  = rect.min[dir];
            farther_hyperrect_coord = rect.max[dir];
            b=false;
        }

        if (nearer_subtree) {
            //std::cout << " recurse into nearer subtree \n";
            /* Slice the hyperrect to get the hyperrect of the nearer subtree */
            double dummy = nearer_hyperrect_coord;
            //nearer_hyperrect_coord = node->pos[dir];
            if (b)
                rect.max[dir] = node->pos[dir];
            else
                rect.min[dir] = node->pos[dir];
            /* Recurse down into nearer subtree */
            kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
            /* Undo the slice */
            if (b)
                rect.max[dir] = dummy; //node->pos[dir];
            else
                rect.min[dir] = dummy; //node->pos[dir];
            //rect->min[dir] = //nearer_hyperrect_coord = dummy;
        }

        /* Check the distance of the point at the current node, compare it
         * with our best so far */
        double dist_sq = node->pos.dist( pos );
        //for(int i=0; i < dim_; i++) {
        //    dist_sq += sq(node->pos[i] - pos[i]);
        //}
        if (dist_sq < result_dist_sq) {
            result = node;
            result_dist_sq = dist_sq;
        }

        if (farther_subtree) {
            //std::cout << " recurse into farther subtree \n";
            /* Get the hyperrect of the farther subtree */
            double dummy = farther_hyperrect_coord;
            if (b)
                rect.min[dir] = node->pos[dir];
            else
                rect.max[dir] = node->pos[dir];
            //farther_hyperrect_coord = node->pos[dir]; // this changes rect_ !!
            /* Check if we have to recurse down by calculating the closest
             * point of the hyperrect and see if it's closer than our
             * minimum distance in result_dist_sq. */
            if (hyperrect_dist_sq(rect, pos) < result_dist_sq) 
            {
                /* Recurse down into farther subtree */
                kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
                      //double dist_sq = node->pos.dist( pos );
            //for(int i=0; i < dim_; i++) {
            //    dist_sq += sq(node->pos[i] - pos[i]);
            //}
            /*
            if (dist_sq < result_dist_sq) {
                result = node;
                result_dist_sq = dist_sq;
            }*/
            }
            /* Undo the slice on the hyperrect */
            if (b)
                rect.min[dir] = dummy;
            else
                rect.max[dir] = dummy;
                
            //*farther_hyperrect_coord = dummy;
        }
    }