[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15987] branches/soc-2008-unclezeiv/source /blender/blenlib: Added yet another method to BLI_kdtree: BLI_kdtree_find_callback.
Davide Vercelli
davide.vercelli at gmail.com
Wed Aug 6 17:24:44 CEST 2008
Revision: 15987
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15987
Author: unclezeiv
Date: 2008-08-06 17:24:43 +0200 (Wed, 06 Aug 2008)
Log Message:
-----------
Added yet another method to BLI_kdtree: BLI_kdtree_find_callback. It serves a very specific purpose but I tried hard to give it a general form.
Basically you can use it to find the nearest node where "nearest" is a metric computed by a callback that has also the possibility to reduce the search radius (if it decides that, outside that radius, no node can give a measure smaller than the current one); this way, larger parts of the tree can be pruned, resulting in a faster search.
Works for me but deeper testing, particularly regarding corner/degenerate cases, is welcome.
Modified Paths:
--------------
branches/soc-2008-unclezeiv/source/blender/blenlib/BLI_kdtree.h
branches/soc-2008-unclezeiv/source/blender/blenlib/intern/BLI_kdtree.c
Modified: branches/soc-2008-unclezeiv/source/blender/blenlib/BLI_kdtree.h
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/blenlib/BLI_kdtree.h 2008-08-06 13:46:44 UTC (rev 15986)
+++ branches/soc-2008-unclezeiv/source/blender/blenlib/BLI_kdtree.h 2008-08-06 15:24:43 UTC (rev 15987)
@@ -58,6 +58,14 @@
int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest);
int BLI_kdtree_find_in_sphere(KDTree *tree, float dist, float *co, float *nor, KDTreeNearest *nearest);
+/* Find element with smallest value and return index, or -1 if no node is found.
+ * The "value" of an element is computed by a callback along with a new radius that can be used
+ * to prune parts of the tree and speed up the search.
+ * If you are looking for the nearest node to a point that is already part of the tree, you can
+ * provide a vetoed_idx in order to avoid getting the node itself as "nearest point". */
+typedef void (*KDTreeValDistFunc)(void *data, int index, float *val, float *dist);
+int BLI_kdtree_find_callback(KDTree *tree, float *co, float *nor, int vetoed_idx, KDTreeValDistFunc func, void *data, KDTreeNearest *nearest);
+
/* Builds a correspondence table to convert from user provided indices to internal ones
* Factor multiplies the amount of space allocated for the table; should normally be "1"
* Optional; only useful if specifically required by a method */
Modified: branches/soc-2008-unclezeiv/source/blender/blenlib/intern/BLI_kdtree.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/blenlib/intern/BLI_kdtree.c 2008-08-06 13:46:44 UTC (rev 15986)
+++ branches/soc-2008-unclezeiv/source/blender/blenlib/intern/BLI_kdtree.c 2008-08-06 15:24:43 UTC (rev 15987)
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
+#include "blendef.h"
#include "BLI_arithb.h"
#include "BLI_kdtree.h"
#include "BKE_utildefines.h"
@@ -235,6 +236,114 @@
return min_node->index;
}
+int BLI_kdtree_find_callback(KDTree *tree, float *co, float *nor, int veto, KDTreeValDistFunc func, void *data, KDTreeNearest *nearest)
+{
+ KDTreeNode *root, *node, *min_node;
+ KDTreeNode **stack, *defaultstack[100];
+ float min_val, cur_dist, max_dist;
+ float val, dist;
+ int totstack, cur=0;
+
+ if(!tree->root)
+ return -1;
+
+ stack= defaultstack;
+ totstack= 100;
+
+ root= tree->root;
+
+ min_node= NULL;
+ min_val= MAXFLOAT;
+ max_dist= MAXFLOAT;
+
+ if (root->index != veto && !root->invalid) {
+ min_node= root;
+ func(data, root->index, &val, &dist);
+ min_val= val;
+ max_dist= dist;
+ }
+
+ if(co[root->d] < root->co[root->d]) {
+ if(root->right)
+ stack[cur++]=root->right;
+ if(root->left)
+ stack[cur++]=root->left;
+ }
+ else {
+ if(root->left)
+ stack[cur++]=root->left;
+ if(root->right)
+ stack[cur++]=root->right;
+ }
+
+ while(cur--){
+ node=stack[cur];
+
+ cur_dist = node->co[node->d] - co[node->d];
+
+ if(cur_dist<0.0){
+ cur_dist= cur_dist*cur_dist;
+
+ if(cur_dist<max_dist){
+ if (node->index!= veto && !node->invalid) {
+ func(data, node->index, &val, &dist);
+ if (val<min_val) {
+ min_val= val;
+ min_node= node;
+ }
+ if (dist<max_dist)
+ max_dist= dist;
+ }
+ if(node->left)
+ stack[cur++]=node->left;
+ }
+ if(node->right)
+ stack[cur++]=node->right;
+ }
+ else{
+ cur_dist= cur_dist*cur_dist;
+
+ if(cur_dist<max_dist){
+ if (node->index!= veto && !node->invalid) {
+ func(data, node->index, &val, &dist);
+ if (val<min_val && node->index!= veto) {
+ min_val= val;
+ min_node= node;
+ }
+ if (dist<max_dist)
+ max_dist= dist;
+ }
+ if(node->right)
+ stack[cur++]=node->right;
+ }
+ if(node->left)
+ stack[cur++]=node->left;
+ }
+ if(cur+3 > totstack){
+ KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
+ memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
+ if(stack != defaultstack)
+ MEM_freeN(stack);
+ stack=temp;
+ totstack+=100;
+ }
+ }
+
+ if (min_node==NULL)
+ return -1;
+
+ if(nearest) {
+ nearest->index= min_node->index;
+ nearest->dist= sqrt(min_val);
+ VecCopyf(nearest->co, min_node->co);
+ }
+
+ if(stack != defaultstack)
+ MEM_freeN(stack);
+
+ return min_node->index;
+}
+
static void add_nearest(KDTreeNearest *ptn, KDTreeNode *node, int *found, int n, float dist)
{
int i;
More information about the Bf-blender-cvs
mailing list