kdtree_common.cc
Go to the documentation of this file.
00001 // Guy Shechter
00002 // June 2004
00003 
00004 // Variables used for time debugging.
00005 //TV tv1,tv2;
00006 //TZ tz;
00007 
00008 #include "icp/kdtree_common.h"
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <cmath>
00012 
00013 namespace icp {
00014 
00015 int swap_tmp_int;
00016 #define INT_SWAP(X,Y)  { swap_tmp_int=X; X=Y; Y=swap_tmp_int; }
00017 
00018 //
00019 // Call this function to build the k-d Tree.
00020 //
00021 Tree *build_kdtree(double *reference, int N, int D, int *index, 
00022                    int L,int offset) {
00023 
00024   Tree *treeptr;
00025   if ( (treeptr = (Tree *) malloc(sizeof(Tree))) == NULL )
00026     fprintf(stderr,"Error allocating memory for kD-Tree\n");
00027   
00028   treeptr->rootptr = build_kdtree_core(reference, N, D, index, L, offset);
00029   treeptr->dims = D;
00030 
00031   return treeptr;
00032 }
00033 
00034 //
00035 // This is the core function for building the k-D tree for raw input data.
00036 //
00037 Node *build_kdtree_core(double *reference, int N, int D, int *index, 
00038                         int L,int offset) {
00039   int i,median;
00040   Node *nodeptr;
00041   
00042 #ifdef DEBUG_BUILD_TREE
00043   fprintf(stderr,"Entering build_kdtree \n");
00044 #endif
00045   
00046   if ( (nodeptr = (Node *) malloc(sizeof(Node))) == NULL )
00047     fprintf(stderr,"Error allocating memory for kD-Tree\n");
00048 
00049   if ( (nodeptr->pt = (double*) malloc(sizeof(double)*D)) == NULL )
00050     fprintf(stderr,"Error allocating memory for kD-Tree\n");
00051   
00052   if (L==1) {
00053     for (i=0; i < D; i++)
00054       nodeptr->pt[i] = EVAL_INDEX(index[0],i,N);
00055     nodeptr->index = (unsigned int) index[0];
00056     
00057 #ifdef DEBUG_BUILD_TREE
00058     fprintf(stderr,"Created leaf     node, (dim=%d) (value: ", offset);
00059     for (i=0; i < D; i++)
00060       fprintf(stderr," %f",nodeptr->pt[i]);
00061     fprintf(stderr," )\n");
00062 #endif
00063     
00064     nodeptr->orientation = offset;
00065     nodeptr->left=NULL;
00066     nodeptr->right=NULL;
00067     return nodeptr;
00068   }
00069   
00070   quicksort(index,0,L-1,reference,offset,N);
00071   median = (int)((L)/2.0);
00072   
00073   for (i=0; i < D; i++)
00074     nodeptr->pt[i] = EVAL_INDEX(index[median],i,N);
00075   nodeptr->index = (unsigned int) index[median];
00076   nodeptr->orientation = offset;
00077   nodeptr->left=NULL;
00078   nodeptr->right=NULL;
00079   
00080 #ifdef DEBUG_BUILD_TREE
00081   fprintf(stderr,"Created internal node, (dim=%d) (value: ", offset);
00082   for (i=0; i < D; i++)
00083     fprintf(stderr," %f",nodeptr->pt[i]);
00084   fprintf(stderr," )\n");
00085 #endif
00086   
00087   nodeptr->left = build_kdtree_core(reference,N,D,index,median,(offset+1)%D);
00088   
00089   if (L-median-1)
00090     nodeptr->right = build_kdtree_core(reference,N,D,index+median+1,
00091                                        L-median-1,(offset+1)%D);
00092   
00093   return nodeptr;
00094 }
00095 
00096 
00097 // 
00098 //   The following two functions are for the quicksort algorithm 
00099 //
00100 int partition(int *a, int p, int r, double *reference, int offset, int D){
00101   int i,j;
00102   double x;
00103   
00104   x= EVAL_INDEX(a[p],offset,D); i=p-1; j=r+1;
00105   while (1) {
00106     for (j--; EVAL_INDEX(a[j],offset,D) > x; j--);
00107     for (i++; EVAL_INDEX(a[i],offset,D) <x; i++);
00108     if (i<j){
00109       INT_SWAP(a[j],a[i]);
00110     }
00111     else return j;
00112   }
00113 }
00114 
00115 void quicksort(int *ra, int p, int r, double *reference, int offset,int D){
00116   int q;
00117   
00118   if (p < r) {
00119     q = partition(ra,p,r,reference,offset,D);
00120     quicksort(ra,p,q,reference,offset,D);
00121     quicksort(ra,q+1,r,reference,offset,D);
00122   }
00123 }
00124 
00125 
00126 
00127 //
00128 // Deallocate memory used by the k-D tree
00129 //
00130 void free_tree(Node *pVertex) {
00131   
00132   if (pVertex == NULL)
00133     return;
00134   if (pVertex->left)  free_tree(pVertex->left);
00135   if (pVertex->right) free_tree(pVertex->right);
00136   
00137   free(pVertex->pt);
00138   free(pVertex);
00139   return;
00140 }
00141 
00142 
00143 //
00144 // Compute the norm distance between two points of dimension Dim
00145 //
00146 double calcdistance(double *pt1, double *pt2, int Dim){
00147   int j;
00148   double d=0;
00149   for (j=0; j < Dim; j++) 
00150     d+= (pt1[j]-pt2[j])*(pt1[j]-pt2[j]);
00151   return (sqrt(d));
00152 }
00153 
00154 
00155 Node *pointLocation(Node *v, double *pt,int D){
00156   
00157   //if (!v) v=root;
00158 
00159   if ( ( v->left == NULL) && (v->right == NULL) ) 
00160     return v;
00161 
00162   if (    pt[v->orientation] < v->pt[ v->orientation] )
00163     return ( (v->left) ? pointLocation(v->left,pt,D) : v);
00164   else if (    pt[v->orientation] > v->pt[v->orientation]  ) 
00165     return ( (v->right) ? pointLocation(v->right,pt,D): v);
00166   else {
00167     //What we have is pt[v->orientation] == v->pt[v->orientation] 
00168     Node *vl = ( (v->left)? pointLocation(v->left,pt,D) : v);
00169     Node *vr = ( (v->right)? pointLocation(v->right,pt,D) : v);
00170     if ( calcdistance(vl->pt,pt,D) < calcdistance(vr->pt,pt,D) )
00171       return vl;
00172     else
00173       return vr;
00174   }
00175 }
00176 
00177 
00178 Node * rangeQuery(Node *v, double distance, double *pt, int D){
00179 
00180   Node *current=NULL, *tmp;
00181   int j;
00182 
00183   
00184   if ( ( (v->pt[v->orientation] - distance) <=  pt[v->orientation]) &&
00185        ( (v->pt[v->orientation] + distance) >=  pt[v->orientation]) ){
00186     if (calcdistance(pt,v->pt,D) <= distance){
00187       current=(Node*) malloc(sizeof(Node));
00188       current->pt=(double*) malloc(sizeof(double)*D);
00189       current->right=NULL;
00190       for (j=0; j < D; j++) current->pt[j]=v->pt[j];
00191       current->index=v->index;
00192     }
00193   }
00194 
00195   
00196   if (  (!(v->left)) && (!(v->right)) ) 
00197     return current;
00198   
00199   tmp=current;
00200   while (tmp && tmp->right) 
00201     tmp=tmp->right;
00202   
00203   if (v->left){
00204     if ( v->pt[v->orientation] >= (pt[v->orientation] - distance ) ){
00205       if (tmp)
00206         tmp->right=rangeQuery(v->left, distance, pt,D);
00207       else
00208         current=rangeQuery(v->left, distance, pt, D);
00209     }
00210   }
00211   
00212   tmp=current;
00213   while (tmp &&tmp->right) 
00214     tmp=tmp->right;
00215   
00216   if (v->right){
00217     if (   v->pt[v->orientation]  <= (pt[v->orientation] + distance ) ){
00218       if (tmp)
00219         tmp->right=rangeQuery(v->right, distance, pt, D);
00220       else
00221         current=   rangeQuery(v->right, distance, pt, D);
00222     }
00223   }    
00224 
00225   return current;
00226 }
00227 
00228 //
00229 // The top-level function for running a query on the k-D tree.
00230 //
00231 void run_queries( Node *pVertex, double *model, int M, int D, 
00232                   double *closest_pt, double *distance, short ReturnType) {
00233   
00234   int i,j;
00235   double min_distance, *pt;
00236   Node *LL, *cur, *leaf, *tmp;
00237   
00238   pt= (double*)malloc(sizeof(double)*D);
00239   
00240   for (i=0; i < M; i++) {
00241     
00242 #ifdef DEBUG_RUN_QUERIES
00243     fprintf(stderr,"Running Query (%d/%d) (value: ",
00244               i+1, M);
00245     for (j=0; j < D ; j++)
00246       fprintf(stderr," %f", model[ M*j+i]);
00247     fprintf(stderr," )\n");
00248 #endif
00249     
00250     for (j=0; j < D; j++) 
00251       pt[j]=model[M*j+i];
00252     
00253     leaf=pointLocation(pVertex,pt,D);
00254     min_distance=calcdistance(leaf->pt, pt,D )+0.001;
00255 
00256     LL=rangeQuery(pVertex,min_distance,pt,D);
00257 
00258     if (!LL) {
00259       if (ReturnType == RETURN_INDEX) 
00260         closest_pt[i] = -1;
00261       else{
00262         for (j=0; j< D; j++)
00263           closest_pt[j*M+i]=-1;
00264       }
00265       fprintf(stderr,"Null LL\n");
00266     } 
00267     else {
00268       distance[i]=calcdistance(LL->pt, pt,D);
00269       if (ReturnType == RETURN_INDEX) 
00270         closest_pt[i] = LL->index;
00271       else {
00272         for (j=0; j < D; j++) 
00273           closest_pt[j*M+i] = LL->pt[j];
00274       }
00275       cur=LL;
00276       while (cur){
00277         if ( calcdistance(cur->pt, pt,D) <= distance[i] ) {
00278           if (ReturnType == RETURN_INDEX) 
00279             closest_pt[i] = cur->index;
00280           else {
00281             for (j=0; j < D; j++) 
00282               closest_pt[j*M+i] = cur->pt[j];
00283           }
00284           distance[i]=calcdistance(cur->pt, pt,D);
00285         }
00286         tmp=cur;
00287         cur=cur->right;
00288         free(tmp->pt);
00289         free(tmp);
00290       }
00291     }
00292 
00293 #ifdef DEBUG_RUN_QUERIES
00294     fprintf(stderr,"Distance to closest point is %f\n",distance[i]);
00295 #endif
00296 
00297   }
00298   free(pt);
00299 }
00300 
00301 
00302 
00303 // 
00304 // Outputs the k-D tree while performing a depth first traversal.
00305 //
00306 void display_tree(Node *nodeptr,int D) {
00307   int i;
00308   
00309   fprintf(stderr,"Node: (dim = %d) (idx= %u) (value = ", nodeptr->orientation,
00310             nodeptr->index);
00311   for (i=0; i <D; i++)
00312     fprintf(stderr,"%f\t",nodeptr->pt[i]);
00313   fprintf(stderr,")\n");
00314 
00315   if (nodeptr->left == NULL) 
00316     fprintf(stderr,"Left is (null)\n");
00317   else{
00318     fprintf(stderr,"Going left\n");
00319     display_tree(nodeptr->left,D);
00320   }
00321   
00322   if (nodeptr->right == NULL) 
00323     fprintf(stderr,"Right is (null)\n");
00324   else{
00325     fprintf(stderr,"Going right\n");
00326     display_tree(nodeptr->right,D);
00327   }
00328 }
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 //
00339 // The top-level function for running a range search on the k-D tree.
00340 //
00341 void run_range_search( Node *pVertex, double *model, int M, int D, 
00342                        double distlim, double **pts_in_range, 
00343                        unsigned int *L, unsigned int **indices){
00344   
00345   int i,j, count;
00346   double *pt;
00347   Node *LL, *cur, *tmp;
00348 
00349   pt= (double*)malloc(sizeof(double)*D);
00350 
00351   for (i=0; i < M; i++) {
00352 
00353 #ifdef DEBUG_RUN_RANGE_SEARCH
00354     fprintf(stderr,"Running Search (%d/%d) (value: ",
00355               i+1, M);
00356     for (j=0; j < D ; j++)
00357       fprintf(stderr," %f", model[ M*j+i]);
00358     fprintf(stderr," )\n");
00359 #endif
00360 
00361     for (j=0; j < D ; j++)
00362       pt[j]=model[M*j+i];
00363     LL=rangeQuery(pVertex,distlim,pt,D);
00364 
00365     if (!LL) {
00366       *L=0;
00367       (*pts_in_range)=NULL;
00368 #ifdef DEBUG_RUN_RANGE_SEARCH
00369       fprintf(stderr,"Null LL\n");
00370 #endif
00371     } 
00372     else {
00373       cur=LL;
00374       count=0;
00375       while (cur){
00376         cur=cur->right; count++;
00377       }
00378 #ifdef DEBUG_RUN_RANGE_SEARCH
00379       fprintf(stderr,"Found %d points\n",count);
00380 #endif
00381       *L=count;
00382       (*indices) = (unsigned int *) malloc (sizeof(unsigned int)*count);
00383       (*pts_in_range) = (double *) malloc (sizeof(double) *count*D);
00384 
00385 
00386       cur=LL;
00387       count=0;
00388       while(cur){
00389         (*indices)[count] = cur->index;
00390         for (j=0; j < D; j++) {
00391           (*pts_in_range)[j*(*L)+count] = cur->pt[j];
00392         }
00393         tmp=cur;
00394         cur=cur->right;
00395         free(tmp->pt);
00396         free(tmp);
00397         count++;
00398       }
00399     }
00400   }
00401   free(pt);
00402 }
00403 
00404 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


icp
Author(s): Maintained by Juergen Sturm
autogenerated on Wed Dec 26 2012 15:34:47