21#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
22#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
23#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id)
53#define KD_STACK_INIT 100
54#define KD_NEAR_ALLOC_INC 100
55#define KD_FOUND_ALLOC_INC 50
57#define KD_NODE_UNSET ((uint)-1)
63#define KD_NODE_ROOT_IS_INIT ((uint)-2)
105 tree->max_node_index = -1;
108 tree->is_balanced =
false;
109 tree->nodes_len_capacity = nodes_len_capacity;
141 tree->max_node_index = std::max(
tree->max_node_index, index);
144 tree->is_balanced =
false;
154 if (nodes_len <= 0) {
157 if (nodes_len == 1) {
163 right = nodes_len - 1;
164 median = nodes_len / 2;
166 while (right >
left) {
167 co = nodes[right].
co[axis];
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);
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;
281 cur_dist = node->
co[node->
d] - co[node->
d];
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 = int(
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;
392 cur_dist = node->
co[node->
d] - co[node->
d];
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;
448 const uint nearest_len_capacity,
455 if (*nearest_len < nearest_len_capacity) {
459 for (
i = *nearest_len - 1;
i > 0;
i--) {
460 if (dist >= nearest[
i - 1].dist) {
463 nearest[
i] = nearest[
i - 1];
467 nearest[
i].
dist = dist;
480 const uint nearest_len_capacity,
481 float (*len_sq_fn)(
const float co_search[
KD_DIMS],
483 const void *user_data),
484 const void *user_data)
490 uint stack_len_capacity, cur = 0;
491 uint i, nearest_len = 0;
501 if (len_sq_fn ==
nullptr) {
506 stack = stack_default;
507 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
509 root = &nodes[
tree->root];
511 cur_dist = len_sq_fn(co, root->
co, user_data);
513 r_nearest, &nearest_len, nearest_len_capacity, root->
index, cur_dist, root->
co);
515 if (co[root->
d] < root->
co[root->
d]) {
517 stack[cur++] = root->
right;
520 stack[cur++] = root->
left;
525 stack[cur++] = root->
left;
528 stack[cur++] = root->
right;
535 cur_dist = node->
co[node->
d] - co[node->
d];
537 if (cur_dist < 0.0f) {
538 cur_dist = -cur_dist * cur_dist;
540 if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) {
541 cur_dist = len_sq_fn(co, node->
co, user_data);
543 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
545 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->
co);
549 stack[cur++] = node->
left;
553 stack[cur++] = node->
right;
557 cur_dist = cur_dist * cur_dist;
559 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
560 cur_dist = len_sq_fn(co, node->
co, user_data);
561 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
563 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->
co);
567 stack[cur++] = node->
right;
571 stack[cur++] = node->
left;
575 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
579 for (
i = 0;
i < nearest_len;
i++) {
583 if (stack != stack_default) {
587 return (
int)nearest_len;
593 uint nearest_len_capacity)
596 tree, co, r_nearest, nearest_len_capacity,
nullptr,
nullptr);
614 uint *nearest_len_capacity,
621 if (
UNLIKELY(nearest_index >= *nearest_len_capacity)) {
626 to = (*r_nearest) + nearest_index;
643 float (*len_sq_fn)(
const float co_search[
KD_DIMS],
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 ==
nullptr) {
669 stack = stack_default;
670 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
672 stack[cur++] =
tree->root;
677 if (co[node->
d] + range < node->co[node->
d]) {
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;
726 tree, co, r_nearest, range,
nullptr,
nullptr);
742 bool (*search_cb)(
void *user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
748 float range_sq = range * range, dist_sq;
749 uint stack_len_capacity, cur = 0;
759 stack = stack_default;
760 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
762 stack[cur++] =
tree->root;
767 if (co[node->
d] + range < node->co[node->
d]) {
769 stack[cur++] = node->
left;
772 else if (co[node->
d] - range > node->
co[node->
d]) {
774 stack[cur++] = node->
right;
779 if (dist_sq <= range_sq) {
780 if (search_cb(user_data, node->
index, node->
co, dist_sq) ==
false) {
786 stack[cur++] = node->
left;
789 stack[cur++] = node->
right;
794 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
799 if (stack != stack_default) {
813 order[nodes[
i].
index] = (int)
i;
884 bool use_index_order,
896 if (use_index_order) {
898 for (
int i = 0;
i <
tree->max_node_index + 1;
i++) {
899 const int node_index = order[
i];
900 if (node_index == -1) {
904 if (
ELEM(duplicates[index], -1, index)) {
907 int found_prev = found;
909 if (found != found_prev) {
911 duplicates[index] = index;
918 const uint node_index =
i;
920 if (
ELEM(duplicates[index], -1, index)) {
923 int found_prev = found;
925 if (found != found_prev) {
927 duplicates[index] = index;
954 if (n0->
co[j] < n1->
co[j]) {
957 if (n0->
co[j] > n1->
co[j]) {
981 tree->is_balanced =
false;
994 return (
int)
tree->nodes_len;
A KD-tree for nearest neighbor search.
void BLI_kdtree_nd_ int BLI_kdtree_nd_ int BLI_kdtree_nd_ find_nearest_n(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest *r_nearest, uint nearest_len_capacity) ATTR_NONNULL(1
void BLI_kdtree_nd_ free(KDTree *tree)
int BLI_kdtree_nd_ calc_duplicates_fast(const KDTree *tree, float range, bool use_index_order, int *duplicates)
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)
void BLI_kdtree_nd_ int BLI_kdtree_nd_ find_nearest(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest *r_nearest) ATTR_NONNULL(1
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)
int BLI_kdtree_nd_ find_nearest_n_with_len_squared_cb(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest *r_nearest, 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) ATTR_NONNULL(1
int BLI_kdtree_nd_ deduplicate(KDTree *tree)
void BLI_kdtree_nd_ int BLI_kdtree_nd_ int BLI_kdtree_nd_ int BLI_kdtree_nd_ range_search(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest **r_nearest, float range) ATTR_NONNULL(1
void BLI_kdtree_nd_ balance(KDTree *tree) ATTR_NONNULL(1)
int BLI_kdtree_nd_ int BLI_kdtree_nd_ range_search_with_len_squared_cb(const KDTree *tree, const float co[KD_DIMS], KDTreeNearest **r_nearest, 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) ATTR_NONNULL(1
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
MINLINE float square_f(float a)
Read Guarded memory(de)allocation.
static int kdtree_cmp_bool(const bool a, const bool b)
#define KD_NEAR_ALLOC_INC
#define KD_NODE_ROOT_IS_INIT
static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs)
#define NODE_TEST_NEAREST(node)
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])
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])
static void deduplicate_recursive(const DeDuplicateParams *p, uint i)
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
static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], const float co_search[KD_DIMS], const void *)
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])
static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
#define BLI_kdtree_nd_(id)
static blender::Vector< int > kdtree_order(const KDTree *tree)
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)