Blender V4.5
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
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_kdtree_impl.h"
12#include "BLI_math_base.h"
13#include "BLI_utildefines.h"
14#include "BLI_vector.hh"
15
16#include <algorithm>
17#include <cstring>
18
19#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
20
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)
24
25/* All these struct names are #defines with unique names, to avoid violating the one definition
26 * rule. Otherwise `MEM_malloc_array<KDTreeNode>` can get defined once for multiple dimensions,
27 * with different node sizes. */
28
31 float co[KD_DIMS];
32 int index;
33};
34
35struct KDTreeNode {
37 float co[KD_DIMS];
38 int index;
39 uint d; /* range is only (0..KD_DIMS - 1) */
40};
41
42struct KDTree {
47#ifndef NDEBUG
48 bool is_balanced; /* ensure we call balance first */
49 uint nodes_len_capacity; /* max size of the tree */
50#endif
51};
52
53#define KD_STACK_INIT 100 /* initial size for array (on the stack) */
54#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */
55#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */
56
57#define KD_NODE_UNSET ((uint)-1)
58
63#define KD_NODE_ROOT_IS_INIT ((uint)-2)
64
65/* -------------------------------------------------------------------- */
68
69static void copy_vn_vn(float v0[KD_DIMS], const float v1[KD_DIMS])
70{
71 for (uint j = 0; j < KD_DIMS; j++) {
72 v0[j] = v1[j];
73 }
74}
75
76static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
77{
78 float d = 0.0f;
79 for (uint j = 0; j < KD_DIMS; j++) {
80 d += square_f(v0[j] - v1[j]);
81 }
82 return d;
83}
84
85static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS],
86 const float co_search[KD_DIMS],
87 const void * /*user_data*/)
88{
89 return len_squared_vnvn(co_kdtree, co_search);
90}
91
93
97KDTree *BLI_kdtree_nd_(new)(uint nodes_len_capacity)
98{
99 KDTree *tree;
100
101 tree = MEM_callocN<KDTree>("KDTree");
102 tree->nodes = MEM_malloc_arrayN<KDTreeNode>(nodes_len_capacity, "KDTreeNode");
103 tree->nodes_len = 0;
105 tree->max_node_index = -1;
106
107#ifndef NDEBUG
108 tree->is_balanced = false;
109 tree->nodes_len_capacity = nodes_len_capacity;
110#endif
111
112 return tree;
113}
114
116{
117 if (tree) {
118 MEM_freeN(tree->nodes);
120 }
121}
122
126void BLI_kdtree_nd_(insert)(KDTree *tree, int index, const float co[KD_DIMS])
127{
128 KDTreeNode *node = &tree->nodes[tree->nodes_len++];
129
130#ifndef NDEBUG
131 BLI_assert(tree->nodes_len <= tree->nodes_len_capacity);
132#endif
133
134 /* NOTE: array isn't calloc'd,
135 * need to initialize all struct members */
136
137 node->left = node->right = KD_NODE_UNSET;
138 copy_vn_vn(node->co, co);
139 node->index = index;
140 node->d = 0;
141 tree->max_node_index = std::max(tree->max_node_index, index);
142
143#ifndef NDEBUG
144 tree->is_balanced = false;
145#endif
146}
147
148static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs)
149{
150 KDTreeNode *node;
151 float co;
152 uint left, right, median, i, j;
153
154 if (nodes_len <= 0) {
155 return KD_NODE_UNSET;
156 }
157 if (nodes_len == 1) {
158 return 0 + ofs;
159 }
160
161 /* Quick-sort style sorting around median. */
162 left = 0;
163 right = nodes_len - 1;
164 median = nodes_len / 2;
165
166 while (right > left) {
167 co = nodes[right].co[axis];
168 i = left - 1;
169 j = right;
170
171 while (true) {
172 while (nodes[++i].co[axis] < co) { /* pass */
173 }
174 while (nodes[--j].co[axis] > co && j > left) { /* pass */
175 }
176
177 if (i >= j) {
178 break;
179 }
180
181 SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[j]);
182 }
183
184 SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[right]);
185 if (i >= median) {
186 right = i - 1;
187 }
188 if (i <= median) {
189 left = i + 1;
190 }
191 }
192
193 /* Set node and sort sub-nodes. */
194 node = &nodes[median];
195 node->d = axis;
196 axis = (axis + 1) % KD_DIMS;
197 node->left = kdtree_balance(nodes, median, axis, ofs);
198 node->right = kdtree_balance(
199 nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs);
200
201 return median + ofs;
202}
203
205{
206 if (tree->root != KD_NODE_ROOT_IS_INIT) {
207 for (uint i = 0; i < tree->nodes_len; i++) {
208 tree->nodes[i].left = KD_NODE_UNSET;
209 tree->nodes[i].right = KD_NODE_UNSET;
210 }
211 }
212
213 tree->root = kdtree_balance(tree->nodes, tree->nodes_len, 0, 0);
214
215#ifndef NDEBUG
216 tree->is_balanced = true;
217#endif
218}
219
220static uint *realloc_nodes(uint *stack, uint *stack_len_capacity, const bool is_alloc)
221{
222 uint *stack_new = MEM_malloc_arrayN<uint>(*stack_len_capacity + KD_NEAR_ALLOC_INC,
223 "KDTree.treestack");
224 memcpy(stack_new, stack, *stack_len_capacity * sizeof(uint));
225 // memset(stack_new + *stack_len_capacity, 0, sizeof(uint) * KD_NEAR_ALLOC_INC);
226 if (is_alloc) {
227 MEM_freeN(stack);
228 }
229 *stack_len_capacity += KD_NEAR_ALLOC_INC;
230 return stack_new;
231}
232
237 const float co[KD_DIMS],
238 KDTreeNearest *r_nearest)
239{
240 const KDTreeNode *nodes = tree->nodes;
241 const KDTreeNode *root, *min_node;
242 uint *stack, stack_default[KD_STACK_INIT];
243 float min_dist, cur_dist;
244 uint stack_len_capacity, cur = 0;
245
246#ifndef NDEBUG
247 BLI_assert(tree->is_balanced == true);
248#endif
249
250 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
251 return -1;
252 }
253
254 stack = stack_default;
255 stack_len_capacity = KD_STACK_INIT;
256
257 root = &nodes[tree->root];
258 min_node = root;
259 min_dist = len_squared_vnvn(root->co, co);
260
261 if (co[root->d] < root->co[root->d]) {
262 if (root->right != KD_NODE_UNSET) {
263 stack[cur++] = root->right;
264 }
265 if (root->left != KD_NODE_UNSET) {
266 stack[cur++] = root->left;
267 }
268 }
269 else {
270 if (root->left != KD_NODE_UNSET) {
271 stack[cur++] = root->left;
272 }
273 if (root->right != KD_NODE_UNSET) {
274 stack[cur++] = root->right;
275 }
276 }
277
278 while (cur--) {
279 const KDTreeNode *node = &nodes[stack[cur]];
280
281 cur_dist = node->co[node->d] - co[node->d];
282
283 if (cur_dist < 0.0f) {
284 cur_dist = -cur_dist * cur_dist;
285
286 if (-cur_dist < min_dist) {
287 cur_dist = len_squared_vnvn(node->co, co);
288 if (cur_dist < min_dist) {
289 min_dist = cur_dist;
290 min_node = node;
291 }
292 if (node->left != KD_NODE_UNSET) {
293 stack[cur++] = node->left;
294 }
295 }
296 if (node->right != KD_NODE_UNSET) {
297 stack[cur++] = node->right;
298 }
299 }
300 else {
301 cur_dist = cur_dist * cur_dist;
302
303 if (cur_dist < min_dist) {
304 cur_dist = len_squared_vnvn(node->co, co);
305 if (cur_dist < min_dist) {
306 min_dist = cur_dist;
307 min_node = node;
308 }
309 if (node->right != KD_NODE_UNSET) {
310 stack[cur++] = node->right;
311 }
312 }
313 if (node->left != KD_NODE_UNSET) {
314 stack[cur++] = node->left;
315 }
316 }
317 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
318 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
319 }
320 }
321
322 if (r_nearest) {
323 r_nearest->index = min_node->index;
324 r_nearest->dist = sqrtf(min_dist);
325 copy_vn_vn(r_nearest->co, min_node->co);
326 }
327
328 if (stack != stack_default) {
329 MEM_freeN(stack);
330 }
331
332 return min_node->index;
333}
334
343 const KDTree *tree,
344 const float co[KD_DIMS],
345 int (*filter_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq),
346 void *user_data,
347 KDTreeNearest *r_nearest)
348{
349 const KDTreeNode *nodes = tree->nodes;
350 const KDTreeNode *min_node = nullptr;
351
352 uint *stack, stack_default[KD_STACK_INIT];
353 float min_dist = FLT_MAX, cur_dist;
354 uint stack_len_capacity, cur = 0;
355
356#ifndef NDEBUG
357 BLI_assert(tree->is_balanced == true);
358#endif
359
360 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
361 return -1;
362 }
363
364 stack = stack_default;
365 stack_len_capacity = int(ARRAY_SIZE(stack_default));
366
367#define NODE_TEST_NEAREST(node) \
368 { \
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); \
372 if (result == 1) { \
373 min_dist = dist_sq; \
374 min_node = node; \
375 } \
376 else if (result == 0) { \
377 /* pass */ \
378 } \
379 else { \
380 BLI_assert(result == -1); \
381 goto finally; \
382 } \
383 } \
384 } \
385 ((void)0)
386
387 stack[cur++] = tree->root;
388
389 while (cur--) {
390 const KDTreeNode *node = &nodes[stack[cur]];
391
392 cur_dist = node->co[node->d] - co[node->d];
393
394 if (cur_dist < 0.0f) {
395 cur_dist = -cur_dist * cur_dist;
396
397 if (-cur_dist < min_dist) {
398 NODE_TEST_NEAREST(node);
399
400 if (node->left != KD_NODE_UNSET) {
401 stack[cur++] = node->left;
402 }
403 }
404 if (node->right != KD_NODE_UNSET) {
405 stack[cur++] = node->right;
406 }
407 }
408 else {
409 cur_dist = cur_dist * cur_dist;
410
411 if (cur_dist < min_dist) {
412 NODE_TEST_NEAREST(node);
413
414 if (node->right != KD_NODE_UNSET) {
415 stack[cur++] = node->right;
416 }
417 }
418 if (node->left != KD_NODE_UNSET) {
419 stack[cur++] = node->left;
420 }
421 }
422 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
423 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
424 }
425 }
426
427#undef NODE_TEST_NEAREST
428
429finally:
430 if (stack != stack_default) {
431 MEM_freeN(stack);
432 }
433
434 if (min_node) {
435 if (r_nearest) {
436 r_nearest->index = min_node->index;
437 r_nearest->dist = sqrtf(min_dist);
438 copy_vn_vn(r_nearest->co, min_node->co);
439 }
440
441 return min_node->index;
442 }
443 return -1;
444}
445
447 uint *nearest_len,
448 const uint nearest_len_capacity,
449 const int index,
450 const float dist,
451 const float co[KD_DIMS])
452{
453 uint i;
454
455 if (*nearest_len < nearest_len_capacity) {
456 (*nearest_len)++;
457 }
458
459 for (i = *nearest_len - 1; i > 0; i--) {
460 if (dist >= nearest[i - 1].dist) {
461 break;
462 }
463 nearest[i] = nearest[i - 1];
464 }
465
466 nearest[i].index = index;
467 nearest[i].dist = dist;
468 copy_vn_vn(nearest[i].co, co);
469}
470
477 const KDTree *tree,
478 const float co[KD_DIMS],
479 KDTreeNearest r_nearest[],
480 const uint nearest_len_capacity,
481 float (*len_sq_fn)(const float co_search[KD_DIMS],
482 const float co_test[KD_DIMS],
483 const void *user_data),
484 const void *user_data)
485{
486 const KDTreeNode *nodes = tree->nodes;
487 const KDTreeNode *root;
488 uint *stack, stack_default[KD_STACK_INIT];
489 float cur_dist;
490 uint stack_len_capacity, cur = 0;
491 uint i, nearest_len = 0;
492
493#ifndef NDEBUG
494 BLI_assert(tree->is_balanced == true);
495#endif
496
497 if (UNLIKELY((tree->root == KD_NODE_UNSET) || nearest_len_capacity == 0)) {
498 return 0;
499 }
500
501 if (len_sq_fn == nullptr) {
502 len_sq_fn = len_squared_vnvn_cb;
503 BLI_assert(user_data == nullptr);
504 }
505
506 stack = stack_default;
507 stack_len_capacity = int(ARRAY_SIZE(stack_default));
508
509 root = &nodes[tree->root];
510
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);
514
515 if (co[root->d] < root->co[root->d]) {
516 if (root->right != KD_NODE_UNSET) {
517 stack[cur++] = root->right;
518 }
519 if (root->left != KD_NODE_UNSET) {
520 stack[cur++] = root->left;
521 }
522 }
523 else {
524 if (root->left != KD_NODE_UNSET) {
525 stack[cur++] = root->left;
526 }
527 if (root->right != KD_NODE_UNSET) {
528 stack[cur++] = root->right;
529 }
530 }
531
532 while (cur--) {
533 const KDTreeNode *node = &nodes[stack[cur]];
534
535 cur_dist = node->co[node->d] - co[node->d];
536
537 if (cur_dist < 0.0f) {
538 cur_dist = -cur_dist * cur_dist;
539
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);
542
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);
546 }
547
548 if (node->left != KD_NODE_UNSET) {
549 stack[cur++] = node->left;
550 }
551 }
552 if (node->right != KD_NODE_UNSET) {
553 stack[cur++] = node->right;
554 }
555 }
556 else {
557 cur_dist = cur_dist * cur_dist;
558
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);
564 }
565
566 if (node->right != KD_NODE_UNSET) {
567 stack[cur++] = node->right;
568 }
569 }
570 if (node->left != KD_NODE_UNSET) {
571 stack[cur++] = node->left;
572 }
573 }
574 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
575 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
576 }
577 }
578
579 for (i = 0; i < nearest_len; i++) {
580 r_nearest[i].dist = sqrtf(r_nearest[i].dist);
581 }
582
583 if (stack != stack_default) {
584 MEM_freeN(stack);
585 }
586
587 return (int)nearest_len;
588}
589
591 const float co[KD_DIMS],
592 KDTreeNearest r_nearest[],
593 uint nearest_len_capacity)
594{
596 tree, co, r_nearest, nearest_len_capacity, nullptr, nullptr);
597}
598
599static int nearest_cmp_dist(const void *a, const void *b)
600{
601 const KDTreeNearest *kda = static_cast<const KDTreeNearest *>(a);
602 const KDTreeNearest *kdb = static_cast<const KDTreeNearest *>(b);
603
604 if (kda->dist < kdb->dist) {
605 return -1;
606 }
607 if (kda->dist > kdb->dist) {
608 return 1;
609 }
610 return 0;
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 = static_cast<KDTreeNearest *>(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 = nullptr;
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 == nullptr) {
665 len_sq_fn = len_squared_vnvn_cb;
666 BLI_assert(user_data == nullptr);
667 }
668
669 stack = stack_default;
670 stack_len_capacity = int(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 tree, co, r_nearest, range, nullptr, nullptr);
727}
728
739 const KDTree *tree,
740 const float co[KD_DIMS],
741 float range,
742 bool (*search_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq),
743 void *user_data)
744{
745 const KDTreeNode *nodes = tree->nodes;
746
747 uint *stack, stack_default[KD_STACK_INIT];
748 float range_sq = range * range, dist_sq;
749 uint stack_len_capacity, cur = 0;
750
751#ifndef NDEBUG
752 BLI_assert(tree->is_balanced == true);
753#endif
754
755 if (UNLIKELY(tree->root == KD_NODE_UNSET)) {
756 return;
757 }
758
759 stack = stack_default;
760 stack_len_capacity = int(ARRAY_SIZE(stack_default));
761
762 stack[cur++] = tree->root;
763
764 while (cur--) {
765 const KDTreeNode *node = &nodes[stack[cur]];
766
767 if (co[node->d] + range < node->co[node->d]) {
768 if (node->left != KD_NODE_UNSET) {
769 stack[cur++] = node->left;
770 }
771 }
772 else if (co[node->d] - range > node->co[node->d]) {
773 if (node->right != KD_NODE_UNSET) {
774 stack[cur++] = node->right;
775 }
776 }
777 else {
778 dist_sq = len_squared_vnvn(node->co, co);
779 if (dist_sq <= range_sq) {
780 if (search_cb(user_data, node->index, node->co, dist_sq) == false) {
781 goto finally;
782 }
783 }
784
785 if (node->left != KD_NODE_UNSET) {
786 stack[cur++] = node->left;
787 }
788 if (node->right != KD_NODE_UNSET) {
789 stack[cur++] = node->right;
790 }
791 }
792
793 if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) {
794 stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack);
795 }
796 }
797
798finally:
799 if (stack != stack_default) {
800 MEM_freeN(stack);
801 }
802}
803
809{
810 const KDTreeNode *nodes = tree->nodes;
811 blender::Vector<int> order(tree->max_node_index + 1, -1);
812 for (uint i = 0; i < tree->nodes_len; i++) {
813 order[nodes[i].index] = (int)i;
814 }
815 return order;
816}
817
818/* -------------------------------------------------------------------- */
821
823 /* Static */
825 float range;
826 float range_sq;
829
830 /* Per Search */
833};
834
836{
837 const KDTreeNode *node = &p->nodes[i];
838 if (p->search_co[node->d] + p->range <= node->co[node->d]) {
839 if (node->left != KD_NODE_UNSET) {
840 deduplicate_recursive(p, node->left);
841 }
842 }
843 else if (p->search_co[node->d] - p->range >= node->co[node->d]) {
844 if (node->right != KD_NODE_UNSET) {
846 }
847 }
848 else {
849 if ((p->search != node->index) && (p->duplicates[node->index] == -1)) {
850 if (len_squared_vnvn(node->co, p->search_co) <= p->range_sq) {
851 p->duplicates[node->index] = (int)p->search;
852 *p->duplicates_found += 1;
853 }
854 }
855 if (node->left != KD_NODE_UNSET) {
856 deduplicate_recursive(p, node->left);
857 }
858 if (node->right != KD_NODE_UNSET) {
860 }
861 }
862}
863
883 const float range,
884 bool use_index_order,
885 int *duplicates)
886{
887 int found = 0;
888
889 DeDuplicateParams p = {};
890 p.nodes = tree->nodes;
891 p.range = range;
892 p.range_sq = square_f(range);
893 p.duplicates = duplicates;
894 p.duplicates_found = &found;
895
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) {
901 continue;
902 }
903 const int index = i;
904 if (ELEM(duplicates[index], -1, index)) {
905 p.search = index;
906 copy_vn_vn(p.search_co, tree->nodes[node_index].co);
907 int found_prev = found;
908 deduplicate_recursive(&p, tree->root);
909 if (found != found_prev) {
910 /* Prevent chains of doubles. */
911 duplicates[index] = index;
912 }
913 }
914 }
915 }
916 else {
917 for (uint i = 0; i < tree->nodes_len; i++) {
918 const uint node_index = i;
919 const int index = p.nodes[node_index].index;
920 if (ELEM(duplicates[index], -1, index)) {
921 p.search = index;
922 copy_vn_vn(p.search_co, tree->nodes[node_index].co);
923 int found_prev = found;
924 deduplicate_recursive(&p, tree->root);
925 if (found != found_prev) {
926 /* Prevent chains of doubles. */
927 duplicates[index] = index;
928 }
929 }
930 }
931 }
932 return found;
933}
934
936
937/* -------------------------------------------------------------------- */
940
941static int kdtree_cmp_bool(const bool a, const bool b)
942{
943 if (a == b) {
944 return 0;
945 }
946 return b ? -1 : 1;
947}
948
949static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p)
950{
951 const KDTreeNode *n0 = static_cast<const KDTreeNode *>(n0_p);
952 const KDTreeNode *n1 = static_cast<const KDTreeNode *>(n1_p);
953 for (uint j = 0; j < KD_DIMS; j++) {
954 if (n0->co[j] < n1->co[j]) {
955 return -1;
956 }
957 if (n0->co[j] > n1->co[j]) {
958 return 1;
959 }
960 }
961
962 if (n0->d != KD_DIMS && n1->d != KD_DIMS) {
963 /* Two nodes share identical `co`
964 * Both are still valid.
965 * Cast away `const` and tag one of them as invalid. */
966 ((KDTreeNode *)n1)->d = KD_DIMS;
967 }
968
969 /* Keep sorting until each unique value has one and only one valid node. */
970 return kdtree_cmp_bool(n0->d == KD_DIMS, n1->d == KD_DIMS);
971}
972
979{
980#ifndef NDEBUG
981 tree->is_balanced = false;
982#endif
983 qsort(tree->nodes, (size_t)tree->nodes_len, sizeof(*tree->nodes), kdtree_node_cmp_deduplicate);
984 uint j = 0;
985 for (uint i = 0; i < tree->nodes_len; i++) {
986 if (tree->nodes[i].d != KD_DIMS) {
987 if (i != j) {
988 tree->nodes[j] = tree->nodes[i];
989 }
990 j++;
991 }
992 }
993 tree->nodes_len = j;
994 return (int)tree->nodes_len;
995}
996
#define BLI_assert(a)
Definition BLI_assert.h:46
#define KDTreeNearest
Definition BLI_kdtree.h:16
#define KDTree
Definition BLI_kdtree.h:15
#define KD_DIMS
Definition BLI_kdtree.h:13
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)
unsigned int uint
#define ARRAY_SIZE(arr)
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define ELEM(...)
Read Guarded memory(de)allocation.
#define sqrtf(x)
KDTree_3d * tree
#define KDTreeNode
Definition kdtree_1d.cc:12
#define KDTreeNode_head
Definition kdtree_1d.cc:13
static int kdtree_cmp_bool(const bool a, const bool b)
#define KD_NEAR_ALLOC_INC
Definition kdtree_impl.h:54
#define KD_NODE_ROOT_IS_INIT
Definition kdtree_impl.h:63
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])
Definition kdtree_impl.h:69
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)
#define KD_NODE_UNSET
Definition kdtree_impl.h:57
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:55
static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], const float co_search[KD_DIMS], const void *)
Definition kdtree_impl.h:85
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])
#define KD_STACK_INIT
Definition kdtree_impl.h:53
static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS])
Definition kdtree_impl.h:76
#define BLI_kdtree_nd_(id)
Definition kdtree_impl.h:23
static blender::Vector< int > kdtree_order(const KDTree *tree)
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
Definition mallocn.cc:40
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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:31
float co[KD_DIMS]
Definition kdtree_impl.h:37
uint root
Definition kdtree_impl.h:45
bool is_balanced
Definition kdtree_impl.h:48
uint nodes_len_capacity
Definition kdtree_impl.h:49
uint nodes_len
Definition kdtree_impl.h:44
KDTreeNode * nodes
Definition kdtree_impl.h:43
int max_node_index
Definition kdtree_impl.h:46
i
Definition text_draw.cc:230