Blender V4.3
kdtree_impl.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_kdtree_impl.h"
12#include "BLI_math_base.h"
13#include "BLI_utildefines.h"
14
15#include <string.h>
16
17#include "BLI_strict_flags.h" /* Keep last. */
18
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)
22
28
29typedef struct KDTreeNode {
31 float co[KD_DIMS];
32 int index;
33 uint d; /* range is only (0..KD_DIMS - 1) */
35
36struct KDTree {
41#ifndef NDEBUG
42 bool is_balanced; /* ensure we call balance first */
43 uint nodes_len_capacity; /* max size of the tree */
44#endif
45};
46
47#define KD_STACK_INIT 100 /* initial size for array (on the stack) */
48#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */
49#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */
50
51#define KD_NODE_UNSET ((uint)-1)
52
57#define KD_NODE_ROOT_IS_INIT ((uint)-2)
58
59/* -------------------------------------------------------------------- */
63static void copy_vn_vn(float v0[KD_DIMS], const float v1[KD_DIMS])
64{
65 for (uint j = 0; j < KD_DIMS; j++) {
66 v0[j] = v1[j];
67 }
68}
69
70static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
71{
72 float d = 0.0f;
73 for (uint j = 0; j < KD_DIMS; j++) {
74 d += square_f(v0[j] - v1[j]);
75 }
76 return d;
77}
78
79static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS],
80 const float co_search[KD_DIMS],
81 const void *UNUSED(user_data))
82{
83 return len_squared_vnvn(co_kdtree, co_search);
84}
85
91KDTree *BLI_kdtree_nd_(new)(uint nodes_len_capacity)
92{
93 KDTree *tree;
94
95 tree = MEM_mallocN(sizeof(KDTree), "KDTree");
96 tree->nodes = MEM_mallocN(sizeof(KDTreeNode) * nodes_len_capacity, "KDTreeNode");
97 tree->nodes_len = 0;
99 tree->max_node_index = -1;
100
101#ifndef NDEBUG
102 tree->is_balanced = false;
103 tree->nodes_len_capacity = nodes_len_capacity;
104#endif
105
106 return tree;
107}
108
110{
111 if (tree) {
112 MEM_freeN(tree->nodes);
114 }
115}
116
120void BLI_kdtree_nd_(insert)(KDTree *tree, int index, const float co[KD_DIMS])
121{
122 KDTreeNode *node = &tree->nodes[tree->nodes_len++];
123
124#ifndef NDEBUG
125 BLI_assert(tree->nodes_len <= tree->nodes_len_capacity);
126#endif
127
128 /* NOTE: array isn't calloc'd,
129 * need to initialize all struct members */
130
131 node->left = node->right = KD_NODE_UNSET;
132 copy_vn_vn(node->co, co);
133 node->index = index;
134 node->d = 0;
135 tree->max_node_index = MAX2(tree->max_node_index, index);
136
137#ifndef NDEBUG
138 tree->is_balanced = false;
139#endif
140}
141
142static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs)
143{
145 float co;
146 uint left, right, median, i, j;
147
148 if (nodes_len <= 0) {
149 return KD_NODE_UNSET;
150 }
151 else if (nodes_len == 1) {
152 return 0 + ofs;
153 }
154
155 /* Quick-sort style sorting around median. */
156 left = 0;
157 right = nodes_len - 1;
158 median = nodes_len / 2;
159
160 while (right > left) {
161 co = nodes[right].co[axis];
162 i = left - 1;
163 j = right;
164
165 while (1) {
166 while (nodes[++i].co[axis] < co) { /* pass */
167 }
168 while (nodes[--j].co[axis] > co && j > left) { /* pass */
169 }
170
171 if (i >= j) {
172 break;
173 }
174
175 SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[j]);
176 }
177
178 SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[right]);
179 if (i >= median) {
180 right = i - 1;
181 }
182 if (i <= median) {
183 left = i + 1;
184 }
185 }
186
187 /* Set node and sort sub-nodes. */
188 node = &nodes[median];
189 node->d = axis;
190 axis = (axis + 1) % KD_DIMS;
191 node->left = kdtree_balance(nodes, median, axis, ofs);
192 node->right = kdtree_balance(
193 nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs);
194
195 return median + ofs;
196}
197
199{
200 if (tree->root != KD_NODE_ROOT_IS_INIT) {
201 for (uint i = 0; i < tree->nodes_len; i++) {
202 tree->nodes[i].left = KD_NODE_UNSET;
203 tree->nodes[i].right = KD_NODE_UNSET;
204 }
205 }
206
207 tree->root = kdtree_balance(tree->nodes, tree->nodes_len, 0, 0);
208
209#ifndef NDEBUG
210 tree->is_balanced = true;
211#endif
212}
213
214static uint *realloc_nodes(uint *stack, uint *stack_len_capacity, const bool is_alloc)
215{
216 uint *stack_new = MEM_mallocN((*stack_len_capacity + KD_NEAR_ALLOC_INC) * sizeof(uint),
217 "KDTree.treestack");
218 memcpy(stack_new, stack, *stack_len_capacity * sizeof(uint));
219 // memset(stack_new + *stack_len_capacity, 0, sizeof(uint) * KD_NEAR_ALLOC_INC);
220 if (is_alloc) {
221 MEM_freeN(stack);
222 }
223 *stack_len_capacity += KD_NEAR_ALLOC_INC;
224 return stack_new;
225}
226
231 const float co[KD_DIMS],
232 KDTreeNearest *r_nearest)
233{
234 const KDTreeNode *nodes = tree->nodes;
235 const KDTreeNode *root, *min_node;
236 uint *stack, stack_default[KD_STACK_INIT];
237 float min_dist, cur_dist;
238 uint stack_len_capacity, cur = 0;
239
240#ifndef NDEBUG
241 BLI_assert(tree->is_balanced == true);
242#endif
243
244 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
245 return -1;
246 }
247
248 stack = stack_default;
249 stack_len_capacity = KD_STACK_INIT;
250
251 root = &nodes[tree->root];
252 min_node = root;
253 min_dist = len_squared_vnvn(root->co, co);
254
255 if (co[root->d] < root->co[root->d]) {
256 if (root->right != KD_NODE_UNSET) {
257 stack[cur++] = root->right;
258 }
259 if (root->left != KD_NODE_UNSET) {
260 stack[cur++] = root->left;
261 }
262 }
263 else {
264 if (root->left != KD_NODE_UNSET) {
265 stack[cur++] = root->left;
266 }
267 if (root->right != KD_NODE_UNSET) {
268 stack[cur++] = root->right;
269 }
270 }
271
272 while (cur--) {
273 const KDTreeNode *node = &nodes[stack[cur]];
274
275 cur_dist = node->co[node->d] - co[node->d];
276
277 if (cur_dist < 0.0f) {
278 cur_dist = -cur_dist * cur_dist;
279
280 if (-cur_dist < min_dist) {
281 cur_dist = len_squared_vnvn(node->co, co);
282 if (cur_dist < min_dist) {
283 min_dist = cur_dist;
284 min_node = node;
285 }
286 if (node->left != KD_NODE_UNSET) {
287 stack[cur++] = node->left;
288 }
289 }
290 if (node->right != KD_NODE_UNSET) {
291 stack[cur++] = node->right;
292 }
293 }
294 else {
295 cur_dist = cur_dist * cur_dist;
296
297 if (cur_dist < min_dist) {
298 cur_dist = len_squared_vnvn(node->co, co);
299 if (cur_dist < min_dist) {
300 min_dist = cur_dist;
301 min_node = node;
302 }
303 if (node->right != KD_NODE_UNSET) {
304 stack[cur++] = node->right;
305 }
306 }
307 if (node->left != KD_NODE_UNSET) {
308 stack[cur++] = node->left;
309 }
310 }
311 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
312 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
313 }
314 }
315
316 if (r_nearest) {
317 r_nearest->index = min_node->index;
318 r_nearest->dist = sqrtf(min_dist);
319 copy_vn_vn(r_nearest->co, min_node->co);
320 }
321
322 if (stack != stack_default) {
323 MEM_freeN(stack);
324 }
325
326 return min_node->index;
327}
328
337 const KDTree *tree,
338 const float co[KD_DIMS],
339 int (*filter_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq),
340 void *user_data,
341 KDTreeNearest *r_nearest)
342{
343 const KDTreeNode *nodes = tree->nodes;
344 const KDTreeNode *min_node = NULL;
345
346 uint *stack, stack_default[KD_STACK_INIT];
347 float min_dist = FLT_MAX, cur_dist;
348 uint stack_len_capacity, cur = 0;
349
350#ifndef NDEBUG
351 BLI_assert(tree->is_balanced == true);
352#endif
353
354 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
355 return -1;
356 }
357
358 stack = stack_default;
359 stack_len_capacity = ARRAY_SIZE(stack_default);
360
361#define NODE_TEST_NEAREST(node) \
362 { \
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); \
366 if (result == 1) { \
367 min_dist = dist_sq; \
368 min_node = node; \
369 } \
370 else if (result == 0) { \
371 /* pass */ \
372 } \
373 else { \
374 BLI_assert(result == -1); \
375 goto finally; \
376 } \
377 } \
378 } \
379 ((void)0)
380
381 stack[cur++] = tree->root;
382
383 while (cur--) {
384 const KDTreeNode *node = &nodes[stack[cur]];
385
386 cur_dist = node->co[node->d] - co[node->d];
387
388 if (cur_dist < 0.0f) {
389 cur_dist = -cur_dist * cur_dist;
390
391 if (-cur_dist < min_dist) {
392 NODE_TEST_NEAREST(node);
393
394 if (node->left != KD_NODE_UNSET) {
395 stack[cur++] = node->left;
396 }
397 }
398 if (node->right != KD_NODE_UNSET) {
399 stack[cur++] = node->right;
400 }
401 }
402 else {
403 cur_dist = cur_dist * cur_dist;
404
405 if (cur_dist < min_dist) {
406 NODE_TEST_NEAREST(node);
407
408 if (node->right != KD_NODE_UNSET) {
409 stack[cur++] = node->right;
410 }
411 }
412 if (node->left != KD_NODE_UNSET) {
413 stack[cur++] = node->left;
414 }
415 }
416 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
417 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
418 }
419 }
420
421#undef NODE_TEST_NEAREST
422
423finally:
424 if (stack != stack_default) {
425 MEM_freeN(stack);
426 }
427
428 if (min_node) {
429 if (r_nearest) {
430 r_nearest->index = min_node->index;
431 r_nearest->dist = sqrtf(min_dist);
432 copy_vn_vn(r_nearest->co, min_node->co);
433 }
434
435 return min_node->index;
436 }
437 else {
438 return -1;
439 }
440}
441
443 uint *nearest_len,
444 const uint nearest_len_capacity,
445 const int index,
446 const float dist,
447 const float co[KD_DIMS])
448{
449 uint i;
450
451 if (*nearest_len < nearest_len_capacity) {
452 (*nearest_len)++;
453 }
454
455 for (i = *nearest_len - 1; i > 0; i--) {
456 if (dist >= nearest[i - 1].dist) {
457 break;
458 }
459 else {
460 nearest[i] = nearest[i - 1];
461 }
462 }
463
464 nearest[i].index = index;
465 nearest[i].dist = dist;
466 copy_vn_vn(nearest[i].co, co);
467}
468
475 const KDTree *tree,
476 const float co[KD_DIMS],
477 KDTreeNearest r_nearest[],
478 const uint nearest_len_capacity,
479 float (*len_sq_fn)(const float co_search[KD_DIMS],
480 const float co_test[KD_DIMS],
481 const void *user_data),
482 const void *user_data)
483{
484 const KDTreeNode *nodes = tree->nodes;
485 const KDTreeNode *root;
486 uint *stack, stack_default[KD_STACK_INIT];
487 float cur_dist;
488 uint stack_len_capacity, cur = 0;
489 uint i, nearest_len = 0;
490
491#ifndef NDEBUG
492 BLI_assert(tree->is_balanced == true);
493#endif
494
495 if (UNLIKELY((tree->root == KD_NODE_UNSET) || nearest_len_capacity == 0)) {
496 return 0;
497 }
498
499 if (len_sq_fn == NULL) {
500 len_sq_fn = len_squared_vnvn_cb;
501 BLI_assert(user_data == NULL);
502 }
503
504 stack = stack_default;
505 stack_len_capacity = ARRAY_SIZE(stack_default);
506
507 root = &nodes[tree->root];
508
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);
512
513 if (co[root->d] < root->co[root->d]) {
514 if (root->right != KD_NODE_UNSET) {
515 stack[cur++] = root->right;
516 }
517 if (root->left != KD_NODE_UNSET) {
518 stack[cur++] = root->left;
519 }
520 }
521 else {
522 if (root->left != KD_NODE_UNSET) {
523 stack[cur++] = root->left;
524 }
525 if (root->right != KD_NODE_UNSET) {
526 stack[cur++] = root->right;
527 }
528 }
529
530 while (cur--) {
531 const KDTreeNode *node = &nodes[stack[cur]];
532
533 cur_dist = node->co[node->d] - co[node->d];
534
535 if (cur_dist < 0.0f) {
536 cur_dist = -cur_dist * cur_dist;
537
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);
540
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);
544 }
545
546 if (node->left != KD_NODE_UNSET) {
547 stack[cur++] = node->left;
548 }
549 }
550 if (node->right != KD_NODE_UNSET) {
551 stack[cur++] = node->right;
552 }
553 }
554 else {
555 cur_dist = cur_dist * cur_dist;
556
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);
562 }
563
564 if (node->right != KD_NODE_UNSET) {
565 stack[cur++] = node->right;
566 }
567 }
568 if (node->left != KD_NODE_UNSET) {
569 stack[cur++] = node->left;
570 }
571 }
572 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
573 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
574 }
575 }
576
577 for (i = 0; i < nearest_len; i++) {
578 r_nearest[i].dist = sqrtf(r_nearest[i].dist);
579 }
580
581 if (stack != stack_default) {
582 MEM_freeN(stack);
583 }
584
585 return (int)nearest_len;
586}
587
589 const float co[KD_DIMS],
590 KDTreeNearest r_nearest[],
591 uint nearest_len_capacity)
592{
594 tree, co, r_nearest, nearest_len_capacity, NULL, NULL);
595}
596
597static int nearest_cmp_dist(const void *a, const void *b)
598{
599 const KDTreeNearest *kda = a;
600 const KDTreeNearest *kdb = b;
601
602 if (kda->dist < kdb->dist) {
603 return -1;
604 }
605 else if (kda->dist > kdb->dist) {
606 return 1;
607 }
608 else {
609 return 0;
610 }
611}
612static void nearest_add_in_range(KDTreeNearest **r_nearest,
613 uint nearest_index,
614 uint *nearest_len_capacity,
615 const int index,
616 const float dist,
617 const float co[KD_DIMS])
618{
619 KDTreeNearest *to;
620
621 if (UNLIKELY(nearest_index >= *nearest_len_capacity)) {
622 *r_nearest = MEM_reallocN_id(
623 *r_nearest, (*nearest_len_capacity += KD_FOUND_ALLOC_INC) * sizeof(KDTreeNode), __func__);
624 }
625
626 to = (*r_nearest) + nearest_index;
627
628 to->index = index;
629 to->dist = sqrtf(dist);
630 copy_vn_vn(to->co, co);
631}
632
639 const KDTree *tree,
640 const float co[KD_DIMS],
641 KDTreeNearest **r_nearest,
642 const float range,
643 float (*len_sq_fn)(const float co_search[KD_DIMS],
644 const float co_test[KD_DIMS],
645 const void *user_data),
646 const void *user_data)
647{
648 const KDTreeNode *nodes = tree->nodes;
649 uint *stack, stack_default[KD_STACK_INIT];
650 KDTreeNearest *nearest = NULL;
651 const float range_sq = range * range;
652 float dist_sq;
653 uint stack_len_capacity, cur = 0;
654 uint nearest_len = 0, nearest_len_capacity = 0;
655
656#ifndef NDEBUG
657 BLI_assert(tree->is_balanced == true);
658#endif
659
660 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
661 return 0;
662 }
663
664 if (len_sq_fn == NULL) {
665 len_sq_fn = len_squared_vnvn_cb;
666 BLI_assert(user_data == NULL);
667 }
668
669 stack = stack_default;
670 stack_len_capacity = ARRAY_SIZE(stack_default);
671
672 stack[cur++] = tree->root;
673
674 while (cur--) {
675 const KDTreeNode *node = &nodes[stack[cur]];
676
677 if (co[node->d] + range < node->co[node->d]) {
678 if (node->left != KD_NODE_UNSET) {
679 stack[cur++] = node->left;
680 }
681 }
682 else if (co[node->d] - range > node->co[node->d]) {
683 if (node->right != KD_NODE_UNSET) {
684 stack[cur++] = node->right;
685 }
686 }
687 else {
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);
692 }
693
694 if (node->left != KD_NODE_UNSET) {
695 stack[cur++] = node->left;
696 }
697 if (node->right != KD_NODE_UNSET) {
698 stack[cur++] = node->right;
699 }
700 }
701
702 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
703 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
704 }
705 }
706
707 if (stack != stack_default) {
708 MEM_freeN(stack);
709 }
710
711 if (nearest_len) {
712 qsort(nearest, nearest_len, sizeof(KDTreeNearest), nearest_cmp_dist);
713 }
714
715 *r_nearest = nearest;
716
717 return (int)nearest_len;
718}
719
721 const float co[KD_DIMS],
722 KDTreeNearest **r_nearest,
723 float range)
724{
726}
727
738 const KDTree *tree,
739 const float co[KD_DIMS],
740 float range,
741 bool (*search_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq),
742 void *user_data)
743{
744 const KDTreeNode *nodes = tree->nodes;
745
746 uint *stack, stack_default[KD_STACK_INIT];
747 float range_sq = range * range, dist_sq;
748 uint stack_len_capacity, cur = 0;
749
750#ifndef NDEBUG
751 BLI_assert(tree->is_balanced == true);
752#endif
753
754 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
755 return;
756 }
757
758 stack = stack_default;
759 stack_len_capacity = ARRAY_SIZE(stack_default);
760
761 stack[cur++] = tree->root;
762
763 while (cur--) {
764 const KDTreeNode *node = &nodes[stack[cur]];
765
766 if (co[node->d] + range < node->co[node->d]) {
767 if (node->left != KD_NODE_UNSET) {
768 stack[cur++] = node->left;
769 }
770 }
771 else if (co[node->d] - range > node->co[node->d]) {
772 if (node->right != KD_NODE_UNSET) {
773 stack[cur++] = node->right;
774 }
775 }
776 else {
777 dist_sq = len_squared_vnvn(node->co, co);
778 if (dist_sq <= range_sq) {
779 if (search_cb(user_data, node->index, node->co, dist_sq) == false) {
780 goto finally;
781 }
782 }
783
784 if (node->left != KD_NODE_UNSET) {
785 stack[cur++] = node->left;
786 }
787 if (node->right != KD_NODE_UNSET) {
788 stack[cur++] = node->right;
789 }
790 }
791
792 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
793 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
794 }
795 }
796
797finally:
798 if (stack != stack_default) {
799 MEM_freeN(stack);
800 }
801}
802
807static int *kdtree_order(const KDTree *tree)
808{
809 const KDTreeNode *nodes = tree->nodes;
810 const size_t bytes_num = sizeof(int) * (size_t)(tree->max_node_index + 1);
811 int *order = MEM_mallocN(bytes_num, __func__);
812 memset(order, -1, bytes_num);
813 for (uint i = 0; i < tree->nodes_len; i++) {
814 order[nodes[i].index] = (int)i;
815 }
816 return order;
817}
818
819/* -------------------------------------------------------------------- */
824 /* Static */
826 float range;
827 float range_sq;
830
831 /* Per Search */
834};
835
836static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i)
837{
838 const KDTreeNode *node = &p->nodes[i];
839 if (p->search_co[node->d] + p->range <= node->co[node->d]) {
840 if (node->left != KD_NODE_UNSET) {
841 deduplicate_recursive(p, node->left);
842 }
843 }
844 else if (p->search_co[node->d] - p->range >= node->co[node->d]) {
845 if (node->right != KD_NODE_UNSET) {
846 deduplicate_recursive(p, node->right);
847 }
848 }
849 else {
850 if ((p->search != node->index) && (p->duplicates[node->index] == -1)) {
851 if (len_squared_vnvn(node->co, p->search_co) <= p->range_sq) {
852 p->duplicates[node->index] = (int)p->search;
853 *p->duplicates_found += 1;
854 }
855 }
856 if (node->left != KD_NODE_UNSET) {
857 deduplicate_recursive(p, node->left);
858 }
859 if (node->right != KD_NODE_UNSET) {
860 deduplicate_recursive(p, node->right);
861 }
862 }
863}
864
884 const float range,
885 bool use_index_order,
886 int *duplicates)
887{
888 int found = 0;
889 struct DeDuplicateParams p = {
890 .nodes = tree->nodes,
891 .range = range,
892 .range_sq = square_f(range),
893 .duplicates = duplicates,
894 .duplicates_found = &found,
895 };
896
897 if (use_index_order) {
898 int *order = kdtree_order(tree);
899 for (int i = 0; i < tree->max_node_index + 1; i++) {
900 const int node_index = order[i];
901 if (node_index == -1) {
902 continue;
903 }
904 const int index = i;
905 if (ELEM(duplicates[index], -1, index)) {
906 p.search = index;
907 copy_vn_vn(p.search_co, tree->nodes[node_index].co);
908 int found_prev = found;
909 deduplicate_recursive(&p, tree->root);
910 if (found != found_prev) {
911 /* Prevent chains of doubles. */
912 duplicates[index] = index;
913 }
914 }
915 }
916 MEM_freeN(order);
917 }
918 else {
919 for (uint i = 0; i < tree->nodes_len; i++) {
920 const uint node_index = i;
921 const int index = p.nodes[node_index].index;
922 if (ELEM(duplicates[index], -1, index)) {
923 p.search = index;
924 copy_vn_vn(p.search_co, tree->nodes[node_index].co);
925 int found_prev = found;
926 deduplicate_recursive(&p, tree->root);
927 if (found != found_prev) {
928 /* Prevent chains of doubles. */
929 duplicates[index] = index;
930 }
931 }
932 }
933 }
934 return found;
935}
936
939/* -------------------------------------------------------------------- */
943static int kdtree_cmp_bool(const bool a, const bool b)
944{
945 if (a == b) {
946 return 0;
947 }
948 return b ? -1 : 1;
949}
950
951static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p)
952{
953 const KDTreeNode *n0 = n0_p;
954 const KDTreeNode *n1 = n1_p;
955 for (uint j = 0; j < KD_DIMS; j++) {
956 if (n0->co[j] < n1->co[j]) {
957 return -1;
958 }
959 else if (n0->co[j] > n1->co[j]) {
960 return 1;
961 }
962 }
963
964 if (n0->d != KD_DIMS && n1->d != KD_DIMS) {
965 /* Two nodes share identical `co`
966 * Both are still valid.
967 * Cast away `const` and tag one of them as invalid. */
968 ((KDTreeNode *)n1)->d = KD_DIMS;
969 }
970
971 /* Keep sorting until each unique value has one and only one valid node. */
972 return kdtree_cmp_bool(n0->d == KD_DIMS, n1->d == KD_DIMS);
973}
974
981{
982#ifndef NDEBUG
983 tree->is_balanced = false;
984#endif
985 qsort(tree->nodes, (size_t)tree->nodes_len, sizeof(*tree->nodes), kdtree_node_cmp_deduplicate);
986 uint j = 0;
987 for (uint i = 0; i < tree->nodes_len; i++) {
988 if (tree->nodes[i].d != KD_DIMS) {
989 if (i != j) {
990 tree->nodes[j] = tree->nodes[i];
991 }
992 j++;
993 }
994 }
995 tree->nodes_len = j;
996 return (int)tree->nodes_len;
997}
998
#define BLI_assert(a)
Definition BLI_assert.h:50
#define KD_DIMS
Definition BLI_kdtree.h:13
A KD-tree for nearest neighbor search.
MINLINE float square_f(float a)
unsigned int uint
#define ARRAY_SIZE(arr)
#define SWAP(type, a, b)
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
Read Guarded memory(de)allocation.
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
#define NULL
#define sqrtf(x)
KDTree_3d * tree
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
IndexRange range
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
Definition kdtree_impl.h:48
#define KD_NODE_ROOT_IS_INIT
Definition kdtree_impl.h:57
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])
Definition kdtree_impl.h:63
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))
Definition kdtree_impl.h:79
#define KD_NODE_UNSET
Definition kdtree_impl.h:51
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
Definition kdtree_impl.h:49
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)
#define KD_STACK_INIT
Definition kdtree_impl.h:47
static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
Definition kdtree_impl.h:70
#define BLI_kdtree_nd_(id)
Definition kdtree_impl.h:21
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)
Definition mallocn.cc:40
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static int left
#define FLT_MAX
Definition stdcycles.h:14
const KDTreeNode * nodes
float search_co[KD_DIMS]
float co[KD_DIMS]
float co[KD_DIMS]
Definition kdtree_impl.h:25
float co[KD_DIMS]
Definition kdtree_impl.h:31
uint root
Definition kdtree_impl.h:39
bool is_balanced
Definition kdtree_impl.h:42
uint nodes_len_capacity
Definition kdtree_impl.h:43
uint nodes_len
Definition kdtree_impl.h:38
KDTreeNode * nodes
Definition kdtree_impl.h:37
int max_node_index
Definition kdtree_impl.h:40