19#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
20#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
21#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id)
47#define KD_STACK_INIT 100
48#define KD_NEAR_ALLOC_INC 100
49#define KD_FOUND_ALLOC_INC 50
51#define KD_NODE_UNSET ((uint)-1)
57#define KD_NODE_ROOT_IS_INIT ((uint)-2)
81 const void *
UNUSED(user_data))
99 tree->max_node_index = -1;
102 tree->is_balanced =
false;
103 tree->nodes_len_capacity = nodes_len_capacity;
135 tree->max_node_index =
MAX2(
tree->max_node_index, index);
138 tree->is_balanced =
false;
148 if (nodes_len <= 0) {
151 else if (nodes_len == 1) {
157 right = nodes_len - 1;
158 median = nodes_len / 2;
160 while (right > left) {
161 co = nodes[right].
co[axis];
166 while (nodes[++i].co[axis] < co) {
168 while (nodes[--j].co[axis] > co && j > left) {
188 node = &nodes[median];
193 nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs);
201 for (
uint i = 0; i <
tree->nodes_len; i++) {
210 tree->is_balanced =
true;
218 memcpy(stack_new, stack, *stack_len_capacity *
sizeof(
uint));
237 float min_dist, cur_dist;
238 uint stack_len_capacity, cur = 0;
248 stack = stack_default;
251 root = &nodes[
tree->root];
255 if (co[root->
d] < root->
co[root->
d]) {
257 stack[cur++] = root->
right;
260 stack[cur++] = root->
left;
265 stack[cur++] = root->
left;
268 stack[cur++] = root->
right;
275 cur_dist = node->
co[node->d] - co[node->d];
277 if (cur_dist < 0.0f) {
278 cur_dist = -cur_dist * cur_dist;
280 if (-cur_dist < min_dist) {
282 if (cur_dist < min_dist) {
287 stack[cur++] = node->left;
291 stack[cur++] = node->right;
295 cur_dist = cur_dist * cur_dist;
297 if (cur_dist < min_dist) {
299 if (cur_dist < min_dist) {
304 stack[cur++] = node->right;
308 stack[cur++] = node->left;
312 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
317 r_nearest->index = min_node->
index;
318 r_nearest->dist =
sqrtf(min_dist);
322 if (stack != stack_default) {
326 return min_node->
index;
339 int (*filter_cb)(
void *user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
347 float min_dist =
FLT_MAX, cur_dist;
348 uint stack_len_capacity, cur = 0;
358 stack = stack_default;
359 stack_len_capacity =
ARRAY_SIZE(stack_default);
361#define NODE_TEST_NEAREST(node) \
363 const float dist_sq = len_squared_vnvn((node)->co, co); \
364 if (dist_sq < min_dist) { \
365 const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \
367 min_dist = dist_sq; \
370 else if (result == 0) { \
374 BLI_assert(result == -1); \
381 stack[cur++] =
tree->root;
386 cur_dist = node->
co[node->d] - co[node->d];
388 if (cur_dist < 0.0f) {
389 cur_dist = -cur_dist * cur_dist;
391 if (-cur_dist < min_dist) {
395 stack[cur++] = node->left;
399 stack[cur++] = node->right;
403 cur_dist = cur_dist * cur_dist;
405 if (cur_dist < min_dist) {
409 stack[cur++] = node->right;
413 stack[cur++] = node->left;
417 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
421#undef NODE_TEST_NEAREST
424 if (stack != stack_default) {
435 return min_node->
index;
444 const uint nearest_len_capacity,
451 if (*nearest_len < nearest_len_capacity) {
455 for (i = *nearest_len - 1; i > 0; i--) {
456 if (dist >= nearest[i - 1].dist) {
460 nearest[i] = nearest[i - 1];
464 nearest[i].index = index;
465 nearest[i].dist = dist;
478 const uint nearest_len_capacity,
481 const void *user_data),
482 const void *user_data)
488 uint stack_len_capacity, cur = 0;
489 uint i, nearest_len = 0;
499 if (len_sq_fn ==
NULL) {
504 stack = stack_default;
505 stack_len_capacity =
ARRAY_SIZE(stack_default);
507 root = &nodes[
tree->root];
509 cur_dist = len_sq_fn(co, root->
co, user_data);
511 r_nearest, &nearest_len, nearest_len_capacity, root->
index, cur_dist, root->
co);
513 if (co[root->
d] < root->
co[root->
d]) {
515 stack[cur++] = root->
right;
518 stack[cur++] = root->
left;
523 stack[cur++] = root->
left;
526 stack[cur++] = root->
right;
533 cur_dist = node->
co[node->d] - co[node->d];
535 if (cur_dist < 0.0f) {
536 cur_dist = -cur_dist * cur_dist;
538 if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) {
539 cur_dist = len_sq_fn(co, node->co, user_data);
541 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
543 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->co);
547 stack[cur++] = node->left;
551 stack[cur++] = node->right;
555 cur_dist = cur_dist * cur_dist;
557 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
558 cur_dist = len_sq_fn(co, node->co, user_data);
559 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
561 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->co);
565 stack[cur++] = node->right;
569 stack[cur++] = node->left;
573 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
577 for (i = 0; i < nearest_len; i++) {
578 r_nearest[i].
dist =
sqrtf(r_nearest[i].dist);
581 if (stack != stack_default) {
585 return (
int)nearest_len;
591 uint nearest_len_capacity)
614 uint *nearest_len_capacity,
621 if (
UNLIKELY(nearest_index >= *nearest_len_capacity)) {
626 to = (*r_nearest) + nearest_index;
629 to->dist =
sqrtf(dist);
645 const void *user_data),
646 const void *user_data)
651 const float range_sq = range *
range;
653 uint stack_len_capacity, cur = 0;
654 uint nearest_len = 0, nearest_len_capacity = 0;
664 if (len_sq_fn ==
NULL) {
669 stack = stack_default;
670 stack_len_capacity =
ARRAY_SIZE(stack_default);
672 stack[cur++] =
tree->root;
679 stack[cur++] = node->left;
682 else if (co[node->d] - range > node->co[node->d]) {
684 stack[cur++] = node->right;
688 dist_sq = len_sq_fn(co, node->co, user_data);
689 if (dist_sq <= range_sq) {
691 &nearest, nearest_len++, &nearest_len_capacity, node->index, dist_sq, node->co);
695 stack[cur++] = node->left;
698 stack[cur++] = node->right;
703 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
707 if (stack != stack_default) {
715 *r_nearest = nearest;
717 return (
int)nearest_len;
741 bool (*search_cb)(
void *user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
747 float range_sq = range *
range, dist_sq;
748 uint stack_len_capacity, cur = 0;
758 stack = stack_default;
759 stack_len_capacity =
ARRAY_SIZE(stack_default);
761 stack[cur++] =
tree->root;
768 stack[cur++] = node->left;
771 else if (co[node->d] - range > node->co[node->d]) {
773 stack[cur++] = node->right;
778 if (dist_sq <= range_sq) {
779 if (search_cb(user_data, node->index, node->co, dist_sq) ==
false) {
785 stack[cur++] = node->left;
788 stack[cur++] = node->right;
793 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
798 if (stack != stack_default) {
810 const size_t bytes_num =
sizeof(
int) * (
size_t)(
tree->max_node_index + 1);
812 memset(order, -1, bytes_num);
813 for (
uint i = 0; i <
tree->nodes_len; i++) {
814 order[nodes[i].index] = (
int)i;
885 bool use_index_order,
894 .duplicates_found = &found,
897 if (use_index_order) {
899 for (
int i = 0; i <
tree->max_node_index + 1; i++) {
900 const int node_index = order[i];
901 if (node_index == -1) {
908 int found_prev = found;
910 if (found != found_prev) {
919 for (
uint i = 0; i <
tree->nodes_len; i++) {
920 const uint node_index = i;
925 int found_prev = found;
927 if (found != found_prev) {
956 if (n0->
co[j] < n1->
co[j]) {
959 else if (n0->
co[j] > n1->
co[j]) {
983 tree->is_balanced =
false;
987 for (
uint i = 0; i <
tree->nodes_len; i++) {
996 return (
int)
tree->nodes_len;
A KD-tree for nearest neighbor search.
MINLINE float square_f(float a)
Read Guarded memory(de)allocation.
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS])
static int kdtree_cmp_bool(const bool a, const bool b)
static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i)
void BLI_kdtree_nd_ free(KDTree *tree)
#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)
static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs)
#define NODE_TEST_NEAREST(node)
int BLI_kdtree_nd_ find_nearest_n(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest r_nearest[], uint nearest_len_capacity)
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, float range)
struct KDTreeNode_head KDTreeNode_head
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)
void BLI_kdtree_nd_ balance(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))
static uint * realloc_nodes(uint *stack, uint *stack_len_capacity, const bool is_alloc)
static int nearest_cmp_dist(const void *a, const void *b)
#define KD_FOUND_ALLOC_INC
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)
int BLI_kdtree_nd_ deduplicate(KDTree *tree)
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_ calc_duplicates_fast(const KDTree *tree, const float range, bool use_index_order, int *duplicates)
static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
#define BLI_kdtree_nd_(id)
static int * kdtree_order(const KDTree *tree)
int BLI_kdtree_nd_ find_nearest(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest *r_nearest)
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)
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)