2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: none of this file.
23 * Contributor(s): Janne Karhu
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/blenlib/intern/BLI_kdtree.c
35 #include "MEM_guardedalloc.h"
38 #include "BLI_kdtree.h"
41 # define SWAP(type, a, b) { type sw_ap; sw_ap = (a); (a) = (b); (b) = sw_ap; }
44 typedef struct KDTreeNode {
45 struct KDTreeNode *left, *right;
57 KDTree *BLI_kdtree_new(int maxsize)
61 tree = MEM_callocN(sizeof(KDTree), "KDTree");
62 tree->nodes = MEM_callocN(sizeof(KDTreeNode) * maxsize, "KDTreeNode");
68 void BLI_kdtree_free(KDTree *tree)
71 MEM_freeN(tree->nodes);
76 void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor)
78 KDTreeNode *node = &tree->nodes[tree->totnode++];
81 copy_v3_v3(node->co, co);
82 if (nor) copy_v3_v3(node->nor, nor);
85 static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis)
89 int left, right, median, i, j;
93 else if (totnode == 1)
96 /* quicksort style sorting around median */
101 while (right > left) {
102 co = nodes[right].co[axis];
107 while (nodes[++i].co[axis] < co) ;
108 while (nodes[--j].co[axis] > co && j > left) ;
111 SWAP(KDTreeNode, nodes[i], nodes[j]);
114 SWAP(KDTreeNode, nodes[i], nodes[right]);
121 /* set node and sort subnodes */
122 node = &nodes[median];
124 node->left = kdtree_balance(nodes, median, (axis + 1) % 3);
125 node->right = kdtree_balance(nodes + median + 1, (totnode - (median + 1)), (axis + 1) % 3);
130 void BLI_kdtree_balance(KDTree *tree)
132 tree->root = kdtree_balance(tree->nodes, tree->totnode, 0);
135 static float squared_distance(const float v2[3], const float v1[3], float *UNUSED(n1), float *n2)
139 d[0] = v2[0] - v1[0];
140 d[1] = v2[1] - v1[1];
141 d[2] = v2[2] - v1[2];
143 dist = dot_v3v3(d, d);
145 //if (n1 && n2 && (dot_v3v3(n1, n2) < 0.0f))
147 /* can someone explain why this is done?*/
148 if (n2 && (dot_v3v3(d, n2) < 0.0f)) {
155 int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest)
157 KDTreeNode *root, *node, *min_node;
158 KDTreeNode **stack, *defaultstack[100];
159 float min_dist, cur_dist;
160 int totstack, cur = 0;
165 stack = defaultstack;
170 min_dist = squared_distance(root->co, co, root->nor, nor);
172 if (co[root->d] < root->co[root->d]) {
174 stack[cur++] = root->right;
176 stack[cur++] = root->left;
180 stack[cur++] = root->left;
182 stack[cur++] = root->right;
188 cur_dist = node->co[node->d] - co[node->d];
190 if (cur_dist < 0.0f) {
191 cur_dist = -cur_dist * cur_dist;
193 if (-cur_dist < min_dist) {
194 cur_dist = squared_distance(node->co, co, node->nor, nor);
195 if (cur_dist < min_dist) {
200 stack[cur++] = node->left;
203 stack[cur++] = node->right;
206 cur_dist = cur_dist * cur_dist;
208 if (cur_dist < min_dist) {
209 cur_dist = squared_distance(node->co, co, node->nor, nor);
210 if (cur_dist < min_dist) {
215 stack[cur++] = node->right;
218 stack[cur++] = node->left;
220 if (cur + 3 > totstack) {
221 KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
222 memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
223 if (stack != defaultstack)
231 nearest->index = min_node->index;
232 nearest->dist = sqrt(min_dist);
233 copy_v3_v3(nearest->co, min_node->co);
236 if (stack != defaultstack)
239 return min_node->index;
242 static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co)
246 if (*found < n) (*found)++;
248 for (i = *found - 1; i > 0; i--) {
249 if (dist >= ptn[i - 1].dist)
255 ptn[i].index = index;
257 copy_v3_v3(ptn[i].co, co);
260 /* finds the nearest n entries in tree to specified coordinates */
261 int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest)
263 KDTreeNode *root, *node = NULL;
264 KDTreeNode **stack, *defaultstack[100];
266 int i, totstack, cur = 0, found = 0;
271 stack = defaultstack;
276 cur_dist = squared_distance(root->co, co, root->nor, nor);
277 add_nearest(nearest, &found, n, root->index, cur_dist, root->co);
279 if (co[root->d] < root->co[root->d]) {
281 stack[cur++] = root->right;
283 stack[cur++] = root->left;
287 stack[cur++] = root->left;
289 stack[cur++] = root->right;
295 cur_dist = node->co[node->d] - co[node->d];
297 if (cur_dist < 0.0f) {
298 cur_dist = -cur_dist * cur_dist;
300 if (found < n || -cur_dist < nearest[found - 1].dist) {
301 cur_dist = squared_distance(node->co, co, node->nor, nor);
303 if (found < n || cur_dist < nearest[found - 1].dist)
304 add_nearest(nearest, &found, n, node->index, cur_dist, node->co);
307 stack[cur++] = node->left;
310 stack[cur++] = node->right;
313 cur_dist = cur_dist * cur_dist;
315 if (found < n || cur_dist < nearest[found - 1].dist) {
316 cur_dist = squared_distance(node->co, co, node->nor, nor);
317 if (found < n || cur_dist < nearest[found - 1].dist)
318 add_nearest(nearest, &found, n, node->index, cur_dist, node->co);
321 stack[cur++] = node->right;
324 stack[cur++] = node->left;
326 if (cur + 3 > totstack) {
327 KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
328 memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
329 if (stack != defaultstack)
336 for (i = 0; i < found; i++)
337 nearest[i].dist = sqrt(nearest[i].dist);
339 if (stack != defaultstack)
345 static int range_compare(const void *a, const void *b)
347 const KDTreeNearest *kda = a;
348 const KDTreeNearest *kdb = b;
350 if (kda->dist < kdb->dist)
352 else if (kda->dist > kdb->dist)
357 static void add_in_range(KDTreeNearest **ptn, int found, int *totfoundstack, int index, float dist, float *co)
361 if (found + 1 > *totfoundstack) {
362 KDTreeNearest *temp = MEM_callocN((*totfoundstack + 50) * sizeof(KDTreeNode), "psys_treefoundstack");
363 memcpy(temp, *ptn, *totfoundstack * sizeof(KDTreeNearest));
367 *totfoundstack += 50;
373 to->dist = sqrt(dist);
374 copy_v3_v3(to->co, co);
376 int BLI_kdtree_range_search(KDTree *tree, float range, float *co, float *nor, KDTreeNearest **nearest)
378 KDTreeNode *root, *node = NULL;
379 KDTreeNode **stack, *defaultstack[100];
380 KDTreeNearest *foundstack = NULL;
381 float range2 = range * range, dist2;
382 int totstack, cur = 0, found = 0, totfoundstack = 0;
384 if (!tree || !tree->root)
387 stack = defaultstack;
392 if (co[root->d] + range < root->co[root->d]) {
394 stack[cur++] = root->left;
396 else if (co[root->d] - range > root->co[root->d]) {
398 stack[cur++] = root->right;
401 dist2 = squared_distance(root->co, co, root->nor, nor);
403 add_in_range(&foundstack, found++, &totfoundstack, root->index, dist2, root->co);
406 stack[cur++] = root->left;
408 stack[cur++] = root->right;
414 if (co[node->d] + range < node->co[node->d]) {
416 stack[cur++] = node->left;
418 else if (co[node->d] - range > node->co[node->d]) {
420 stack[cur++] = node->right;
423 dist2 = squared_distance(node->co, co, node->nor, nor);
425 add_in_range(&foundstack, found++, &totfoundstack, node->index, dist2, node->co);
428 stack[cur++] = node->left;
430 stack[cur++] = node->right;
433 if (cur + 3 > totstack) {
434 KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
435 memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
436 if (stack != defaultstack)
443 if (stack != defaultstack)
447 qsort(foundstack, found, sizeof(KDTreeNearest), range_compare);
449 *nearest = foundstack;