Blender V2.61 - r43446

BLI_kdtree.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: none of this file.
00022  *
00023  * Contributor(s): Janne Karhu
00024  *                 Brecht Van Lommel
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "BLI_math.h"
00038 #include "BLI_kdtree.h"
00039 
00040 #ifndef SWAP
00041 #define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
00042 #endif
00043 
00044 typedef struct KDTreeNode {
00045     struct KDTreeNode *left, *right;
00046     float co[3], nor[3];
00047     int index;
00048     short d;
00049 } KDTreeNode;
00050 
00051 struct KDTree {
00052     KDTreeNode *nodes;
00053     int totnode;
00054     KDTreeNode *root;
00055 };
00056 
00057 KDTree *BLI_kdtree_new(int maxsize)
00058 {
00059     KDTree *tree;
00060 
00061     tree= MEM_callocN(sizeof(KDTree), "KDTree");
00062     tree->nodes= MEM_callocN(sizeof(KDTreeNode)*maxsize, "KDTreeNode");
00063     tree->totnode= 0;
00064 
00065     return tree;
00066 }
00067 
00068 void BLI_kdtree_free(KDTree *tree)
00069 {
00070     if(tree) {
00071         MEM_freeN(tree->nodes);
00072         MEM_freeN(tree);
00073     }
00074 }
00075 
00076 void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor)
00077 {
00078     KDTreeNode *node= &tree->nodes[tree->totnode++];
00079 
00080     node->index= index;
00081     copy_v3_v3(node->co, co);
00082     if(nor) copy_v3_v3(node->nor, nor);
00083 }
00084 
00085 static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis)
00086 {
00087     KDTreeNode *node;
00088     float co;
00089     int left, right, median, i, j;
00090 
00091     if(totnode <= 0)
00092         return NULL;
00093     else if(totnode == 1)
00094         return nodes;
00095     
00096     /* quicksort style sorting around median */
00097     left= 0;
00098     right= totnode-1;
00099     median= totnode/2;
00100 
00101     while(right > left) {
00102         co= nodes[right].co[axis];
00103         i= left-1;
00104         j= right;
00105 
00106         while(1) {
00107             while(nodes[++i].co[axis] < co);
00108             while(nodes[--j].co[axis] > co && j>left);
00109 
00110             if(i >= j) break;
00111             SWAP(KDTreeNode, nodes[i], nodes[j]);
00112         }
00113 
00114         SWAP(KDTreeNode, nodes[i], nodes[right]);
00115         if(i >= median)
00116             right= i-1;
00117         if(i <= median)
00118             left= i+1;
00119     }
00120 
00121     /* set node and sort subnodes */
00122     node= &nodes[median];
00123     node->d= axis;
00124     node->left= kdtree_balance(nodes, median, (axis+1)%3);
00125     node->right= kdtree_balance(nodes+median+1, (totnode-(median+1)), (axis+1)%3);
00126 
00127     return node;
00128 }
00129 
00130 void BLI_kdtree_balance(KDTree *tree)
00131 {
00132     tree->root= kdtree_balance(tree->nodes, tree->totnode, 0);
00133 }
00134 
00135 static float squared_distance(float *v2, float *v1, float *n1, float *n2)
00136 {
00137     float d[3], dist;
00138     (void)n1; /* unused */
00139 
00140     d[0]= v2[0]-v1[0];
00141     d[1]= v2[1]-v1[1];
00142     d[2]= v2[2]-v1[2];
00143 
00144     dist= d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
00145 
00146     //if(n1 && n2 && n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2] < 0.0f)
00147     if(n2 && d[0]*n2[0] + d[1]*n2[1] + d[2]*n2[2] < 0.0f)
00148         dist *= 10.0f;
00149 
00150     return dist;
00151 }
00152 
00153 int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest)
00154 {
00155     KDTreeNode *root, *node, *min_node;
00156     KDTreeNode **stack, *defaultstack[100];
00157     float min_dist, cur_dist;
00158     int totstack, cur=0;
00159 
00160     if(!tree->root)
00161         return -1;
00162 
00163     stack= defaultstack;
00164     totstack= 100;
00165 
00166     root= tree->root;
00167     min_node= root;
00168     min_dist= squared_distance(root->co,co,root->nor,nor);
00169 
00170     if(co[root->d] < root->co[root->d]) {
00171         if(root->right)
00172             stack[cur++]=root->right;
00173         if(root->left)
00174             stack[cur++]=root->left;
00175     }
00176     else {
00177         if(root->left)
00178             stack[cur++]=root->left;
00179         if(root->right)
00180             stack[cur++]=root->right;
00181     }
00182     
00183     while(cur--){
00184         node=stack[cur];
00185 
00186         cur_dist = node->co[node->d] - co[node->d];
00187 
00188         if(cur_dist<0.0f){
00189             cur_dist= -cur_dist*cur_dist;
00190 
00191             if(-cur_dist<min_dist){
00192                 cur_dist=squared_distance(node->co,co,node->nor,nor);
00193                 if(cur_dist<min_dist){
00194                     min_dist=cur_dist;
00195                     min_node=node;
00196                 }
00197                 if(node->left)
00198                     stack[cur++]=node->left;
00199             }
00200             if(node->right)
00201                 stack[cur++]=node->right;
00202         }
00203         else{
00204             cur_dist= cur_dist*cur_dist;
00205 
00206             if(cur_dist<min_dist){
00207                 cur_dist=squared_distance(node->co,co,node->nor,nor);
00208                 if(cur_dist<min_dist){
00209                     min_dist=cur_dist;
00210                     min_node=node;
00211                 }
00212                 if(node->right)
00213                     stack[cur++]=node->right;
00214             }
00215             if(node->left)
00216                 stack[cur++]=node->left;
00217         }
00218         if(cur+3 > totstack){
00219             KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
00220             memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
00221             if(stack != defaultstack)
00222                 MEM_freeN(stack);
00223             stack=temp;
00224             totstack+=100;
00225         }
00226     }
00227 
00228     if(nearest) {
00229         nearest->index= min_node->index;
00230         nearest->dist= sqrt(min_dist);
00231         copy_v3_v3(nearest->co, min_node->co);
00232     }
00233 
00234     if(stack != defaultstack)
00235         MEM_freeN(stack);
00236 
00237     return min_node->index;
00238 }
00239 
00240 static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co)
00241 {
00242     int i;
00243 
00244     if(*found<n) (*found)++;
00245 
00246     for(i=*found-1; i>0; i--) {
00247         if(dist >= ptn[i-1].dist)
00248             break;
00249         else
00250             ptn[i]= ptn[i-1];
00251     }
00252 
00253     ptn[i].index= index;
00254     ptn[i].dist= dist;
00255     copy_v3_v3(ptn[i].co, co);
00256 }
00257 
00258 /* finds the nearest n entries in tree to specified coordinates */
00259 int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest)
00260 {
00261     KDTreeNode *root, *node= NULL;
00262     KDTreeNode **stack, *defaultstack[100];
00263     float cur_dist;
00264     int i, totstack, cur=0, found=0;
00265 
00266     if(!tree->root)
00267         return 0;
00268 
00269     stack= defaultstack;
00270     totstack= 100;
00271 
00272     root= tree->root;
00273 
00274     cur_dist= squared_distance(root->co,co,root->nor,nor);
00275     add_nearest(nearest,&found,n,root->index,cur_dist,root->co);
00276     
00277     if(co[root->d] < root->co[root->d]) {
00278         if(root->right)
00279             stack[cur++]=root->right;
00280         if(root->left)
00281             stack[cur++]=root->left;
00282     }
00283     else {
00284         if(root->left)
00285             stack[cur++]=root->left;
00286         if(root->right)
00287             stack[cur++]=root->right;
00288     }
00289 
00290     while(cur--){
00291         node=stack[cur];
00292 
00293         cur_dist = node->co[node->d] - co[node->d];
00294 
00295         if(cur_dist<0.0f){
00296             cur_dist= -cur_dist*cur_dist;
00297 
00298             if(found<n || -cur_dist<nearest[found-1].dist){
00299                 cur_dist=squared_distance(node->co,co,node->nor,nor);
00300 
00301                 if(found<n || cur_dist<nearest[found-1].dist)
00302                     add_nearest(nearest,&found,n,node->index,cur_dist,node->co);
00303 
00304                 if(node->left)
00305                     stack[cur++]=node->left;
00306             }
00307             if(node->right)
00308                 stack[cur++]=node->right;
00309         }
00310         else{
00311             cur_dist= cur_dist*cur_dist;
00312 
00313             if(found<n || cur_dist<nearest[found-1].dist){
00314                 cur_dist=squared_distance(node->co,co,node->nor,nor);
00315                 if(found<n || cur_dist<nearest[found-1].dist)
00316                     add_nearest(nearest,&found,n,node->index,cur_dist,node->co);
00317 
00318                 if(node->right)
00319                     stack[cur++]=node->right;
00320             }
00321             if(node->left)
00322                 stack[cur++]=node->left;
00323         }
00324         if(cur+3 > totstack){
00325             KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
00326             memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
00327             if(stack != defaultstack)
00328                 MEM_freeN(stack);
00329             stack=temp;
00330             totstack+=100;
00331         }
00332     }
00333 
00334     for(i=0; i<found; i++)
00335         nearest[i].dist= sqrt(nearest[i].dist);
00336 
00337     if(stack != defaultstack)
00338         MEM_freeN(stack);
00339 
00340     return found;
00341 }
00342 
00343 static int range_compare(const void * a, const void * b)
00344 {
00345     const KDTreeNearest *kda = a;
00346     const KDTreeNearest *kdb = b;
00347 
00348     if(kda->dist < kdb->dist)
00349         return -1;
00350     else if(kda->dist > kdb->dist)
00351         return 1;
00352     else
00353         return 0;
00354 }
00355 static void add_in_range(KDTreeNearest **ptn, int found, int *totfoundstack, int index, float dist, float *co)
00356 {
00357     KDTreeNearest *to;
00358 
00359     if(found+1 > *totfoundstack) {
00360         KDTreeNearest *temp=MEM_callocN((*totfoundstack+50)*sizeof(KDTreeNode), "psys_treefoundstack");
00361         memcpy(temp, *ptn, *totfoundstack * sizeof(KDTreeNearest));
00362         if(*ptn)
00363             MEM_freeN(*ptn);
00364         *ptn = temp;
00365         *totfoundstack+=50;
00366     }
00367 
00368     to = (*ptn) + found;
00369 
00370     to->index = index;
00371     to->dist = sqrt(dist);
00372     copy_v3_v3(to->co, co);
00373 }
00374 int BLI_kdtree_range_search(KDTree *tree, float range, float *co, float *nor, KDTreeNearest **nearest)
00375 {
00376     KDTreeNode *root, *node= NULL;
00377     KDTreeNode **stack, *defaultstack[100];
00378     KDTreeNearest *foundstack=NULL;
00379     float range2 = range*range, dist2;
00380     int totstack, cur=0, found=0, totfoundstack=0;
00381 
00382     if(!tree || !tree->root)
00383         return 0;
00384 
00385     stack= defaultstack;
00386     totstack= 100;
00387 
00388     root= tree->root;
00389 
00390     if(co[root->d] + range < root->co[root->d]) {
00391         if(root->left)
00392             stack[cur++]=root->left;
00393     }
00394     else if(co[root->d] - range > root->co[root->d]) {
00395         if(root->right)
00396             stack[cur++]=root->right;
00397     }
00398     else {
00399         dist2 = squared_distance(root->co, co, root->nor, nor);
00400         if(dist2  <= range2)
00401             add_in_range(&foundstack, found++, &totfoundstack, root->index, dist2, root->co);
00402 
00403         if(root->left)
00404             stack[cur++]=root->left;
00405         if(root->right)
00406             stack[cur++]=root->right;
00407     }
00408 
00409     while(cur--) {
00410         node=stack[cur];
00411 
00412         if(co[node->d] + range < node->co[node->d]) {
00413             if(node->left)
00414                 stack[cur++]=node->left;
00415         }
00416         else if(co[node->d] - range > node->co[node->d]) {
00417             if(node->right)
00418                 stack[cur++]=node->right;
00419         }
00420         else {
00421             dist2 = squared_distance(node->co, co, node->nor, nor);
00422             if(dist2 <= range2)
00423                 add_in_range(&foundstack, found++, &totfoundstack, node->index, dist2, node->co);
00424 
00425             if(node->left)
00426                 stack[cur++]=node->left;
00427             if(node->right)
00428                 stack[cur++]=node->right;
00429         }
00430 
00431         if(cur+3 > totstack){
00432             KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
00433             memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
00434             if(stack != defaultstack)
00435                 MEM_freeN(stack);
00436             stack=temp;
00437             totstack+=100;
00438         }
00439     }
00440 
00441     if(stack != defaultstack)
00442         MEM_freeN(stack);
00443 
00444     if(found)
00445         qsort(foundstack, found, sizeof(KDTreeNearest), range_compare);
00446 
00447     *nearest = foundstack;
00448 
00449     return found;
00450 }