Blender V2.61 - r43446
|
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 }