22#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
23#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
24#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id)
54#define KD_STACK_INIT 100
55#define KD_NEAR_ALLOC_INC 100
56#define KD_FOUND_ALLOC_INC 50
58#define KD_NODE_UNSET ((uint) - 1)
64#define KD_NODE_ROOT_IS_INIT ((uint) - 2)
106 tree->max_node_index = -1;
109 tree->is_balanced =
false;
110 tree->nodes_len_capacity = nodes_len_capacity;
142 tree->max_node_index = std::max(
tree->max_node_index, index);
145 tree->is_balanced =
false;
155 if (nodes_len <= 0) {
158 if (nodes_len == 1) {
164 right = nodes_len - 1;
165 median = nodes_len / 2;
167 while (right >
left) {
168 co = nodes[right].
co[axis];
173 while (nodes[++
i].co[axis] < co) {
175 while (nodes[--j].co[axis] > co && j >
left) {
195 node = &nodes[median];
200 nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs);
217 tree->is_balanced =
true;
225 memcpy(stack_new, stack, *stack_len_capacity *
sizeof(
uint));
244 float min_dist, cur_dist;
245 uint stack_len_capacity, cur = 0;
255 stack = stack_default;
258 root = &nodes[
tree->root];
262 if (co[root->
d] < root->
co[root->
d]) {
264 stack[cur++] = root->
right;
267 stack[cur++] = root->
left;
272 stack[cur++] = root->
left;
275 stack[cur++] = root->
right;
282 cur_dist = node->
co[node->
d] - co[node->
d];
284 if (cur_dist < 0.0f) {
285 cur_dist = -cur_dist * cur_dist;
287 if (-cur_dist < min_dist) {
289 if (cur_dist < min_dist) {
294 stack[cur++] = node->
left;
298 stack[cur++] = node->
right;
302 cur_dist = cur_dist * cur_dist;
304 if (cur_dist < min_dist) {
306 if (cur_dist < min_dist) {
311 stack[cur++] = node->
right;
315 stack[cur++] = node->
left;
319 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
324 r_nearest->index = min_node->
index;
325 r_nearest->dist =
sqrtf(min_dist);
329 if (stack != stack_default) {
333 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 = int(
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;
442 const uint nearest_len_capacity,
449 if (*nearest_len < nearest_len_capacity) {
453 for (
i = *nearest_len - 1;
i > 0;
i--) {
454 if (dist >= nearest[
i - 1].dist) {
457 nearest[
i] = nearest[
i - 1];
461 nearest[
i].
dist = dist;
469 const uint nearest_len_capacity,
472 const void *user_data),
473 const void *user_data)
479 uint stack_len_capacity, cur = 0;
480 uint i, nearest_len = 0;
490 if (len_sq_fn ==
nullptr) {
495 stack = stack_default;
496 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
498 root = &nodes[
tree->root];
500 cur_dist = len_sq_fn(co, root->
co, user_data);
502 r_nearest, &nearest_len, nearest_len_capacity, root->
index, cur_dist, root->
co);
504 if (co[root->
d] < root->
co[root->
d]) {
506 stack[cur++] = root->
right;
509 stack[cur++] = root->
left;
514 stack[cur++] = root->
left;
517 stack[cur++] = root->
right;
524 cur_dist = node->
co[node->
d] - co[node->
d];
526 if (cur_dist < 0.0f) {
527 cur_dist = -cur_dist * cur_dist;
529 if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) {
530 cur_dist = len_sq_fn(co, node->
co, user_data);
532 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
534 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->
co);
538 stack[cur++] = node->
left;
542 stack[cur++] = node->
right;
546 cur_dist = cur_dist * cur_dist;
548 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
549 cur_dist = len_sq_fn(co, node->
co, user_data);
550 if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) {
552 r_nearest, &nearest_len, nearest_len_capacity, node->
index, cur_dist, node->
co);
556 stack[cur++] = node->
right;
560 stack[cur++] = node->
left;
564 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
568 for (
i = 0;
i < nearest_len;
i++) {
572 if (stack != stack_default) {
576 return (
int)nearest_len;
582 uint nearest_len_capacity)
585 tree, co, r_nearest, nearest_len_capacity,
nullptr,
nullptr);
603 uint *nearest_len_capacity,
610 if (
UNLIKELY(nearest_index >= *nearest_len_capacity)) {
615 to = (*r_nearest) + nearest_index;
629 const void *user_data),
630 const void *user_data)
635 const float range_sq = range * range;
637 uint stack_len_capacity, cur = 0;
638 uint nearest_len = 0, nearest_len_capacity = 0;
648 if (len_sq_fn ==
nullptr) {
653 stack = stack_default;
654 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
656 stack[cur++] =
tree->root;
661 if (co[node->
d] + range < node->co[node->
d]) {
663 stack[cur++] = node->
left;
666 else if (co[node->
d] - range > node->
co[node->
d]) {
668 stack[cur++] = node->
right;
672 dist_sq = len_sq_fn(co, node->
co, user_data);
673 if (dist_sq <= range_sq) {
675 &nearest, nearest_len++, &nearest_len_capacity, node->
index, dist_sq, node->
co);
679 stack[cur++] = node->
left;
682 stack[cur++] = node->
right;
687 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
691 if (stack != stack_default) {
699 *r_nearest = nearest;
701 return (
int)nearest_len;
710 tree, co, r_nearest, range,
nullptr,
nullptr);
717 bool (*search_cb)(
void *user_data,
int index,
const float co[
KD_DIMS],
float dist_sq),
723 float range_sq = range * range, dist_sq;
724 uint stack_len_capacity, cur = 0;
734 stack = stack_default;
735 stack_len_capacity = int(
ARRAY_SIZE(stack_default));
737 stack[cur++] =
tree->root;
742 if (co[node->
d] + range < node->co[node->
d]) {
744 stack[cur++] = node->
left;
747 else if (co[node->
d] - range > node->
co[node->
d]) {
749 stack[cur++] = node->
right;
754 if (dist_sq <= range_sq) {
755 if (search_cb(user_data, node->
index, node->
co, dist_sq) ==
false) {
761 stack[cur++] = node->
left;
764 stack[cur++] = node->
right;
769 stack =
realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
774 if (stack != stack_default) {
788 order[nodes[
i].
index] = (int)
i;
841 const bool use_index_order,
853 if (use_index_order) {
855 for (
int i = 0;
i <
tree->max_node_index + 1;
i++) {
856 const int node_index = order[
i];
857 if (node_index == -1) {
861 if (
ELEM(duplicates[index], -1, index)) {
864 int found_prev = found;
866 if (found != found_prev) {
868 duplicates[index] = index;
875 const uint node_index =
i;
877 if (
ELEM(duplicates[index], -1, index)) {
880 int found_prev = found;
882 if (found != found_prev) {
884 duplicates[index] = index;
901 const bool has_self_index,
902 int (*duplicates_cb)(
void *user_data,
913 const uint nodes_len =
tree->nodes_len;
915 for (
uint i = 0;
i < nodes_len;
i++) {
916 index_to_node_index[
tree->nodes[
i].index] = int(
i);
922 if (has_self_index) {
924 for (
uint i = 0;
i < nodes_len;
i++) {
925 const int node_index =
tree->nodes[
i].index;
926 if (node_index != duplicates[node_index]) {
929 const float *search_co =
tree->nodes[index_to_node_index[node_index]].co;
930 auto accumulate_neighbors_fn =
931 [&duplicates, &node_index, &duplicates_dist_sq, &found](
932 int neighbor_index,
const float * ,
const float dist_sq) ->
bool {
933 const int target_index = duplicates[neighbor_index];
934 if (target_index == -1) {
935 duplicates[neighbor_index] = node_index;
936 duplicates_dist_sq[neighbor_index] = dist_sq;
940 else if (target_index != neighbor_index) {
941 float &dist_sq_best = duplicates_dist_sq[neighbor_index];
943 if ((dist_sq < dist_sq_best) ||
945 ((dist_sq == dist_sq_best) && (node_index < target_index)))
947 dist_sq_best = dist_sq;
948 duplicates[neighbor_index] = node_index;
962 for (
uint i = 0;
i < nodes_len;
i++) {
963 const int node_index =
tree->nodes[
i].index;
964 if (duplicates[node_index] != -1) {
969 const float *search_co =
tree->nodes[index_to_node_index[node_index]].co;
970 auto accumulate_neighbors_fn = [&duplicates, &cluster](
int neighbor_index,
972 const float ) ->
bool {
973 if (duplicates[neighbor_index] == -1) {
974 cluster.
append(neighbor_index);
983 found += int(cluster.
size());
984 cluster.
append(node_index);
986 const int cluster_index = duplicates_cb(user_data, cluster.
data(),
int(cluster.
size()));
988 const int target_index = cluster[cluster_index];
989 for (
const int cluster_node_index : cluster) {
990 duplicates[cluster_node_index] = target_index;
1017 if (n0->
co[j] < n1->
co[j]) {
1020 if (n0->
co[j] > n1->
co[j]) {
1039 tree->is_balanced =
false;
1051 tree->nodes_len = j;
1052 return (
int)
tree->nodes_len;
A KD-tree for nearest neighbor search.
void BLI_kdtree_nd_ range_search_cb_cpp(const KDTree *tree, const float co[KD_DIMS], const float distance, const Fn &fn)
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_ calc_duplicates_cb(const KDTree *tree, const float range, int *duplicates, bool has_self_index, int(*deduplicate_cb)(void *user_data, const int *cluster, int cluster_num), void *user_data)
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.
void append(const T &value)
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)