00001
00002
00003
00004
00005
00006
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
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
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
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
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
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
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
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
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
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
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 }