28 #define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
29 #define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
30 #define BLI_kdtree_nd_(id) _CONCAT(KDTREE_PREFIX_ID, _##id)
51 uint nodes_len_capacity;
55 #define KD_STACK_INIT 100
56 #define KD_NEAR_ALLOC_INC 100
57 #define KD_FOUND_ALLOC_INC 50
59 #define KD_NODE_UNSET ((uint)-1)
65 #define KD_NODE_ROOT_IS_INIT ((uint)-2)
109 tree->is_balanced =
false;
110 tree->nodes_len_capacity = nodes_len_capacity;
144 tree->is_balanced =
false;
154 if (nodes_len <= 0) {
157 else if (nodes_len == 1) {
163 right = nodes_len - 1;
164 median = nodes_len / 2;
172 while (nodes[++i].co[axis] < co) {
174 while (nodes[--j].co[axis] > co && j >
left) {
194 node = &nodes[median];
199 nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs);
207 for (
uint i = 0; i <
tree->nodes_len; i++) {
216 tree->is_balanced =
true;
224 memcpy(stack_new, stack, *stack_len_capacity *
sizeof(
uint));
243 float min_dist, cur_dist;
244 uint stack_len_capacity, cur = 0;
254 stack = stack_default;
257 root = &nodes[
tree->root];
261 if (co[root->
d] < root->
co[root->
d]) {
263 stack[cur++] = root->
right;
266 stack[cur++] = root->
left;
271 stack[cur++] = root->
left;
274 stack[cur++] = root->
right;
283 if (cur_dist < 0.0f) {
284 cur_dist = -cur_dist * cur_dist;
286 if (-cur_dist < min_dist) {
288 if (cur_dist < min_dist) {
293 stack[cur++] =
node->left;
297 stack[cur++] =
node->right;
301 cur_dist = cur_dist * cur_dist;
303 if (cur_dist < min_dist) {
305 if (cur_dist < min_dist) {
310 stack[cur++] =
node->right;
314 stack[cur++] =
node->left;
318 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
323 r_nearest->index = min_node->
index;
324 r_nearest->dist =
sqrtf(min_dist);
328 if (stack != stack_default) {
332 return min_node->
index;
345 int (*filter_cb)(
void *
user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
353 float min_dist = FLT_MAX, cur_dist;
354 uint stack_len_capacity, cur = 0;
364 stack = stack_default;
365 stack_len_capacity =
ARRAY_SIZE(stack_default);
367 #define NODE_TEST_NEAREST(node) \
369 const float dist_sq = len_squared_vnvn((node)->co, co); \
370 if (dist_sq < min_dist) { \
371 const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \
373 min_dist = dist_sq; \
376 else if (result == 0) { \
380 BLI_assert(result == -1); \
387 stack[cur++] =
tree->root;
394 if (cur_dist < 0.0f) {
395 cur_dist = -cur_dist * cur_dist;
397 if (-cur_dist < min_dist) {
401 stack[cur++] =
node->left;
405 stack[cur++] =
node->right;
409 cur_dist = cur_dist * cur_dist;
411 if (cur_dist < min_dist) {
415 stack[cur++] =
node->right;
419 stack[cur++] =
node->left;
423 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
427 #undef NODE_TEST_NEAREST
430 if (stack != stack_default) {
441 return min_node->
index;
450 const uint nearest_len_capacity,
457 if (*nearest_len < nearest_len_capacity) {
461 for (i = *nearest_len - 1; i > 0; i--) {
462 if (dist >= nearest[i - 1].dist) {
466 nearest[i] = nearest[i - 1];
470 nearest[i].
index = index;
471 nearest[i].
dist = dist;
484 const uint nearest_len_capacity,
494 uint stack_len_capacity, cur = 0;
495 uint i, nearest_len = 0;
505 if (len_sq_fn ==
NULL) {
510 stack = stack_default;
511 stack_len_capacity =
ARRAY_SIZE(stack_default);
513 root = &nodes[
tree->root];
517 r_nearest, &nearest_len, nearest_len_capacity, root->
index, cur_dist, root->
co);
519 if (co[root->
d] < root->
co[root->
d]) {
521 stack[cur++] = root->
right;
524 stack[cur++] = root->
left;
529 stack[cur++] = root->
left;
532 stack[cur++] = root->
right;
541 if (cur_dist < 0.0f) {
542 cur_dist = -cur_dist * cur_dist;
544 if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) {
547 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
549 r_nearest, &nearest_len, nearest_len_capacity,
node->index, cur_dist,
node->co);
553 stack[cur++] =
node->left;
557 stack[cur++] =
node->right;
561 cur_dist = cur_dist * cur_dist;
563 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
565 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
567 r_nearest, &nearest_len, nearest_len_capacity,
node->index, cur_dist,
node->co);
571 stack[cur++] =
node->right;
575 stack[cur++] =
node->left;
579 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
583 for (i = 0; i < nearest_len; i++) {
584 r_nearest[i].
dist =
sqrtf(r_nearest[i].dist);
587 if (stack != stack_default) {
591 return (
int)nearest_len;
597 const uint nearest_len_capacity)
620 uint *nearest_len_capacity,
627 if (
UNLIKELY(nearest_index >= *nearest_len_capacity)) {
632 to = (*r_nearest) + nearest_index;
657 const float range_sq = range * range;
659 uint stack_len_capacity, cur = 0;
660 uint nearest_len = 0, nearest_len_capacity = 0;
670 if (len_sq_fn ==
NULL) {
675 stack = stack_default;
676 stack_len_capacity =
ARRAY_SIZE(stack_default);
678 stack[cur++] =
tree->root;
683 if (co[
node->d] + range < node->co[
node->d]) {
685 stack[cur++] =
node->left;
690 stack[cur++] =
node->right;
695 if (dist_sq <= range_sq) {
697 &nearest, nearest_len++, &nearest_len_capacity,
node->index, dist_sq,
node->co);
701 stack[cur++] =
node->left;
704 stack[cur++] =
node->right;
709 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
713 if (stack != stack_default) {
721 *r_nearest = nearest;
723 return (
int)nearest_len;
747 bool (*search_cb)(
void *
user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
753 float range_sq = range * range, dist_sq;
754 uint stack_len_capacity, cur = 0;
764 stack = stack_default;
765 stack_len_capacity =
ARRAY_SIZE(stack_default);
767 stack[cur++] =
tree->root;
772 if (co[
node->d] + range < node->co[
node->d]) {
774 stack[cur++] =
node->left;
779 stack[cur++] =
node->right;
784 if (dist_sq <= range_sq) {
791 stack[cur++] =
node->left;
794 stack[cur++] =
node->right;
799 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
804 if (stack != stack_default) {
817 for (
uint i = 0; i <
tree->nodes_len; i++) {
889 bool use_index_order,
898 .duplicates_found = &found,
901 if (use_index_order) {
903 for (
uint i = 0; i <
tree->nodes_len; i++) {
905 const int index = (int)i;
909 int found_prev = found;
911 if (found != found_prev) {
920 for (
uint i = 0; i <
tree->nodes_len; i++) {
921 const uint node_index = i;
926 int found_prev = found;
928 if (found != found_prev) {
949 if (n0->
co[j] < n1->
co[j]) {
952 else if (n0->
co[j] > n1->
co[j]) {
977 tree->is_balanced =
false;
981 for (
uint i = 0; i <
tree->nodes_len; i++) {
990 return (
int)
tree->nodes_len;
typedef float(TangentPoint)[2]
A kd-tree for nearest neighbor search.
MINLINE float square_f(float a)
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble right
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i)
int BLI_kdtree_nd_() calc_duplicates_fast(const KDTree *tree, const float range, bool use_index_order, int *duplicates)
int BLI_kdtree_nd_() find_nearest_n_with_len_squared_cb(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest r_nearest[], const uint nearest_len_capacity, float(*len_sq_fn)(const float co_search[KD_DIMS], const float co_test[KD_DIMS], const void *user_data), const void *user_data)
#define KD_NEAR_ALLOC_INC
#define KD_NODE_ROOT_IS_INIT
void BLI_kdtree_nd_() range_search_cb(const KDTree *tree, const float co[KD_DIMS], float range, bool(*search_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), void *user_data)
int BLI_kdtree_nd_() find_nearest(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest *r_nearest)
void BLI_kdtree_nd_() balance(KDTree *tree)
static uint * kdtree_order(const KDTree *tree)
static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs)
#define NODE_TEST_NEAREST(node)
static uint * realloc_nodes(uint *stack, uint *stack_len_capacity, const bool is_alloc)
int BLI_kdtree_nd_() deduplicate(KDTree *tree)
void BLI_kdtree_nd_() insert(KDTree *tree, int index, const float co[KD_DIMS])
static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p)
static void copy_vn_vn(float v0[KD_DIMS], const float v1[KD_DIMS])
struct KDTreeNode KDTreeNode
static void nearest_ordered_insert(KDTreeNearest *nearest, uint *nearest_len, const uint nearest_len_capacity, const int index, const float dist, const float co[KD_DIMS])
int BLI_kdtree_nd_() range_search(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest **r_nearest, const float range)
struct KDTreeNode_head KDTreeNode_head
void BLI_kdtree_nd_() free(KDTree *tree)
static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], const float co_search[KD_DIMS], const void *UNUSED(user_data))
int BLI_kdtree_nd_() find_nearest_n(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest r_nearest[], const uint nearest_len_capacity)
int BLI_kdtree_nd_() range_search_with_len_squared_cb(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest **r_nearest, const float range, float(*len_sq_fn)(const float co_search[KD_DIMS], const float co_test[KD_DIMS], const void *user_data), const void *user_data)
static int nearest_cmp_dist(const void *a, const void *b)
#define KD_FOUND_ALLOC_INC
static void nearest_add_in_range(KDTreeNearest **r_nearest, uint nearest_index, uint *nearest_len_capacity, const int index, const float dist, const float co[KD_DIMS])
int BLI_kdtree_nd_() find_nearest_cb(const KDTree *tree, const float co[KD_DIMS], int(*filter_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), void *user_data, KDTreeNearest *r_nearest)
static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
#define BLI_kdtree_nd_(id)
void(* MEM_freeN)(void *vmemh)
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)