API Documentation
Loading...
Searching...
No Matches
KDTree.hpp
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Tree
28File: KDTree
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "TreeIterator.h>
34#include "Node.h>
35#include "Tree.h>
36#include "Base\Headers\BaseValues.h>
37#include "Base\Headers\Buffer.h>
38#include "Base\Headers\Bounds.h>
39#include "Base\Headers\Median.h>
40#include "Base\Headers\ProgressInfo.h>
41#include "Base\Headers\BoolBuffer.h>
42#include "Base\Headers\Vector.h>
43#include "Base\Headers\VectorFunctions.h>
44#include "Base\Headers\intersection.h>
45#include "Base\Headers\BinaryHeap.h>
46
47
48namespace NDEVR
49{
50 template<uint01 t_dims, class t_type>
51 class KDNode : public TreeNode
52 {
53 public:
54 KDNode(const KDNode& node)
55 : TreeNode(node)
56 , m_split(0)
57 , m_split_dim(0)
58 {}
59 explicit KDNode(uint04 index_start)
60 : TreeNode(index_start)
61 , m_split(0)
62 , m_split_dim(0)
63 {}
64
65 void clear(uint04 index_start, const Bounds<t_dims, t_type>& bounds)
66 {
67 setBegin(index_start);
68 //TreeNode::template m_cache_bounds = bounds;
70 }
71
72 uint04 left() const
73 {
74 return uint04(m_child_start);
75 }
76 uint04 right() const
77 {
78 return uint04(m_child_start) + 1;
79 }
80
81 const t_type& split() const
82 {
83 return m_split;
84 }
85 const uint01& splitDim() const
86 {
87 return m_split_dim;
88 }
89 void setSplit(uint01 split_dim, t_type split)
90 {
91 m_split = split;
92 m_split_dim = split_dim;
93 }
94 protected:
95 t_type m_split;
97 };
98
99
100
101 template<uint01 t_dims, class t_type>
102 class KDTreeBase : public TreeBase<KDNode<t_dims, t_type>, t_type, 2>
103 {
104 public:
105 explicit KDTreeBase<t_dims, t_type>(uint04 bucket_size)
106 : TreeBase(bucket_size)
107 {}
109 : TreeBase(tree)
110 {}
112 : TreeBase(std::move(tree))
113 {}
114 protected:
115 KDTreeBase<t_dims, t_type>(const Buffer<KDNode<t_dims, t_type>>& nodes, const Buffer<uint04>& indices, bool is_read_only)
116 : TreeBase(nodes, indices, is_read_only)
117 {}
118 public:
119 template<class t_node_type>
120 bool validate(const Buffer<t_node_type>& elements)
121 {
122 TreeIterator iterator(root_node);
123
124 Buffer<bool> values;
125 values.setSize(elements.size());
126
127 while (iterator.valid())
128 {
129
130 uint04 node_index = iterator.get();
131 KDNode<t_dims, t_type>& node = m_nodes[node_index];
132 iterator.pop();
133
134 values.setAllToValue(false);
135 _getAllT(node_index, values);
136 if (node.size() != values.numSet())
137 return false;
138 }
139 return true;
140 }
141
142 protected:
143 template<class t_node_type, class t_buffer_type>
144 uint04 _calculateAndSplit(uint04 node_index, Bounds<t_dims, t_type> node_bounds, const t_buffer_type& elements, Buffer<uint04>& indices, uint04 start, uint04 end, bool is_precise)
145 {
146 Vector<t_dims, uint04> location;
147 Vector<t_dims, t_type> d_size;//The difference between the right and left size if a given node is chosen
148 for (uint01 dim = 0; dim < t_dims; ++dim)
149 {
150 if (is_precise)
151 location[dim] = median(elements, indices, start, end, dim);
152 else
153 location[dim] = apxMedian(elements, indices, start, end, dim);
154 Bounds<t_dims, t_type> bounds(elements[indices[location[dim]]]);
155 d_size[dim] = getMin(
156 abs(bounds.center()[dim] - node_bounds[MIN][dim])
157 , abs(node_bounds[MAX][dim] - bounds.center()[dim]));
158 }
159 const uint01 split_dim = d_size.getDimension<MAX>();//maximize our smallest split dimension
160 if (is_precise)
161 location[split_dim] = median(elements, indices, start, end, split_dim);
162
163 const uint04 new_left = sortAboutValue<t_type>(location[split_dim], elements, indices, start, end, split_dim);
164
165 splitLeafNode(node_index);
166 m_nodes[node_index].setSplit(split_dim, elements[indices[new_left]][split_dim]);
167
168 return new_left;
169 }
170
171
172 template<class t_node_type, class t_buffer_type>
173 bool _balanceLeafNode(uint04 top_index, const t_buffer_type& elements, Buffer<uint04>& indices, uint04 top_start, uint04 top_end, bool is_precise, ProgressInfo* progress = nullptr)
174 {
175 uint04 start_stack[256];
176 uint04 end_stack[256];
177 Bounds<t_dims, t_type> node_bounds[256];
178 start_stack[0] = top_start;
179 end_stack[0] = top_end;
180 node_bounds[0] = _getBounds<t_dims>(indices, elements, top_start, top_end);
181 TreeIterator iterator(top_index);
182 uint04 size = 0;
183 const uint04 update_size = getMax(uint04(1000), (top_end - top_start) / 10000);
184
185 while (iterator.valid())
186 {
187 uint01 level = iterator.depth();
188 uint04 start = start_stack[level];
189 uint04 end = end_stack[level];
190 uint04 node_index = iterator.get();
191 Bounds<t_dims, t_type> bounds = node_bounds[level];
192
193 iterator.pop();
194 m_nodes[node_index].setSize(end - start);
195
196 if ((end - start) > m_bucket_size)
197 {
198 const uint04 new_left = _calculateAndSplit(node_index, bounds, elements, indices, start, end, is_precise);
199
200 iterator.addAndGoToIndex(m_nodes[node_index].right());
201 start_stack[iterator.depth()] = new_left;
202 end_stack[iterator.depth()] = end;
203 node_bounds[iterator.depth()] = bounds;
204 node_bounds[iterator.depth()][MIN][m_nodes[node_index].splitDim()] = m_nodes[node_index].split();
205
206 iterator.addAndGoToIndex(m_nodes[node_index].left());
207 start_stack[iterator.depth()] = start;
208 end_stack[iterator.depth()] = new_left;
209 node_bounds[iterator.depth()] = bounds;
210 node_bounds[iterator.depth()][MAX][m_nodes[node_index].splitDim()] = m_nodes[node_index].split();
211 }
212 else
213 {
214 m_indices.setAll(indices.begin(start), m_nodes[node_index].begin(), (end - start));
215 size += (end - start);
216
217 if (progress != nullptr && node_index % update_size == 0)
218 {
219 if (progress->setProgress(cast<fltp04>(size) / elements.size()))
220 {
221 clear();
222 return false;
223 }
224 }
225 }
226 }
227 if (progress != nullptr)
228 {
229 if (progress->setProgress(1.0f))
230 {
231 clear();
232 return false;
233 }
234 }
235 return true;
236 }
237
238
239 template<class t_node_type, class t_buffer_type>
240 bool _getClosestElement(uint04 top_index, const Vector<t_dims, t_type>& point, const t_buffer_type& elements, t_type& min_distance, const t_type epsilon, uint04& min_index) const
241 {
242 TreeIterator iterator(top_index);
243 t_type split_values[256];
244 while (iterator.valid())
245 {
246 const uint04 index = iterator.get();
247 if (split_values[iterator.depth()] >= min_distance)
248 {
249 iterator.pop();
250 continue;
251 }
252 iterator.pop();
253
254 const KDNode<t_dims, t_type>& node = m_nodes[index];
255
256 if (node.isLeaf())
257 {
258 const uint04 end = node.end();
259 for (uint04 i = node.begin(); i < end; i++)
260 {
261 const uint04 check_index = m_indices[i];
262 t_type distance = distanceSquared(point, elements[check_index]);
263 if (distance < min_distance)
264 {
265 min_distance = distance;
266 min_index = check_index;
267 if (distance <= epsilon)
268 return true;
269 }
270 }
271 }
272 else
273 {
274 const t_type distance = point[node.splitDim()] - node.split();
275 if (distance > 0)
276 {
277 iterator.addAndGoToIndex(node.left());
278 split_values[iterator.depth()] = distance * distance;
279
280 iterator.addAndGoToIndex(node.right());
281 split_values[iterator.depth()] = 0;
282 }
283 else
284 {
285 iterator.addAndGoToIndex(node.right());
286 split_values[iterator.depth()] = distance * distance;
287
288 iterator.addAndGoToIndex(node.left());
289 split_values[iterator.depth()] = 0;
290 }
291 }
292 }
293 return false;
294 }
295
296 template<class t_node_type, class t_buffer_type>
297 void _getClosestElements(uint04 top_index, const Vector<t_dims, t_type>& point, const t_buffer_type& elements, t_type& min_distance, const t_type& epsilon, MinHeap<t_type, uint04>& heap, uint04 size) const
298 {
299 TreeIterator iterator(top_index);
300 t_type split_values[255];
301 while (iterator.valid())
302 {
303 const uint04 index = iterator.get();
304 if (split_values[iterator.depth()] >= min_distance)
305 {
306 iterator.pop();
307 continue;
308 }
309 iterator.pop();
310
312 if (node.isLeaf())
313 {
314 const uint04 end = node.end();
315 for (uint04 i = node.begin(); i < end; i++)
316 {
317 uint04 check_index = m_indices[i];
318 t_type distance = distanceSquared(point, elements[check_index]);
319 if (distance < min_distance)
320 {
321 heap.insert(distance, check_index);
322 if (heap.size() == size + 1)
323 {
324 heap.deleteMax();
325 min_distance = heap.max();
326 }
327 }
328 }
329 if (min_distance <= epsilon)
330 return;
331 }
332 else
333 {
334 const t_type distance = point[node.splitDim()] - node.split();
335 if (distance > 0)
336 {
337 iterator.addAndGoToIndex(node.left());
338 split_values[iterator.depth()] = distance * distance;
339
340
341 iterator.addAndGoToIndex(node.right());
342 split_values[iterator.depth()] = 0;
343 }
344 else
345 {
346 iterator.addAndGoToIndex(node.right());
347 split_values[iterator.depth()] = distance * distance;
348
349
350 iterator.addAndGoToIndex(node.left());
351 split_values[iterator.depth()] = 0;
352 }
353 }
354 }
355 }
356
357 template<class t_node_type, class t_buffer_type>
358 bool _getClosestElement(uint04 top_index, const LineSegment<t_dims, t_type>& top_line, const t_buffer_type& elements, t_type& min_distance, t_type epsilon, uint04& min_index) const
359 {
360 TreeIterator iterator(top_index);
361 t_type split_values[256];
362
363 Vector<3, uint01> dim_min;
364 Vector<3, uint01> dim_max;
365 for (uint01 i = 0; i < t_dims; i++)
366 {
367 dim_min[i] = top_line[0][i] < top_line[1][i] ? MIN : MAX;
368 dim_max[i] = dim_min[i] != MIN ? MIN : MAX;
369 }
370
371 split_values[0] = 0;
372 t_type sqrt_min_dist = sqrt(min_index);
373 CachedLineSegment<t_dims, t_type> cached_line(top_line);
374
375 while (iterator.valid())
376 {
377 const uint04 index = iterator.get();
378 if (abs(split_values[iterator.depth()]) >= min_distance)
379 {
380 iterator.pop();
381 continue;
382 }
383 //const LineSegment<t_dims, t_type> line = lines[iterator.depth()];
384
385 iterator.pop();
386 const KDNode<t_dims, t_type>& node = m_nodes[index];
387
388 if (node.isLeaf())
389 {
390 const uint04 end = node.end();
391 for (uint04 i = node.begin(); i < end; i++)
392 {
393 uint04 check_index = m_indices[i];
394 t_type distance = distanceSquared(cached_line, elements[check_index]);
395 if (distance < min_distance)
396 {
397 min_distance = distance;
398 min_index = check_index;
399 sqrt_min_dist = sqrt(min_index);
400 }
401 }
402 if (distance <= epsilon)
403 return true;
404 }
405 else
406 {
407 const uint01 split_dim = m_nodes[index].splitDim();
408 const uint01 min = dim_min[split_dim];
409 const uint01 max = dim_max[split_dim];
410 if (cached_line[max][split_dim] >= m_nodes[index].split())
411 {
412 if (cached_line[min][split_dim] <= m_nodes[index].split())
413 {
414 iterator.addAndGoToIndex(node.right());
415 split_values[iterator.depth()] = 0;
416
417 iterator.addAndGoToIndex(node.left());
418 split_values[iterator.depth()] = 0;
419 }
420 else
421 {
422 iterator.addAndGoToIndex(node.left());
423 split_values[iterator.depth()] = cached_line[min][split_dim] - m_nodes[index].split();
424 split_values[iterator.depth()] *= split_values[iterator.depth()];
425
426 iterator.addAndGoToIndex(node.right());
427 split_values[iterator.depth()] = 0;
428 }
429 }
430 else if (cached_line[min][split_dim] <= m_nodes[index].split())
431 {
432 iterator.addAndGoToIndex(node.right());
433 split_values[iterator.depth()] = m_nodes[index].split() - cached_line[max][split_dim];
434 split_values[iterator.depth()] *= -split_values[iterator.depth()];
435
436 iterator.addAndGoToIndex(node.left());
437 split_values[iterator.depth()] = 0;
438 }
439 }
440 }
441 return false;
442 }
443
444 template<class t_node_type, class t_buffer_type>
445 bool _getClosestElement(uint04 top_index, const Triangle<t_dims, t_type>& triangle, const t_buffer_type& elements, t_type& min_distance, t_type epsilon, uint04& min_index) const
446 {
447 TreeIterator iterator(top_index);
448
449 CachedTriangle<t_dims, t_type> cached_tri(triangle);
450
451 while (iterator.valid())
452 {
453 const uint04 index = iterator.get();
454 iterator.pop();
456 if (!node.bounds().expand(sqrt(min_distance)).doBoundsIntersect<t_dims>(cached_tri))
457 continue;
458 if (node.isLeaf())
459 {
460 const uint04 end = node.end();
461 for (uint04 i = node.begin(); i < end; i++)
462 {
463 const uint04 check_index = m_indices[i];
464 const t_type distance = distanceSquared(cached_tri, elements[check_index]);
465 if (distance < min_distance)
466 {
467 min_distance = distance;
468 min_index = check_index;
469 }
470 }
471 if (distance <= epsilon)
472 return true;
473 }
474 else
475 {
476 if (m_nodes[node.left()].bounds().contains(cached_tri.centroid()))
477 iterator.addAndGoToIndex(node.right(), node.left());
478 else
479 iterator.addAndGoToIndex(node.left(), node.right());
480 }
481 }
482 return false;
483 }
484
485 template<class t_node_type, class t_area_type, class t_buffer_type>
486 void _getEnclosedElements(uint04 top_node, t_area_type area, Buffer<bool>& indices, const t_buffer_type& elements) const
487 {
488 Bounds<t_dims, t_type> bounds[256];
489 bounds[0] = Constant<Bounds<t_dims, t_type>>::Max;
490 TreeIterator iterator(top_node);
491 while (iterator.valid())
492 {
493 uint04 index = iterator.get();
494 const KDNode<t_dims, t_type>& node = m_nodes[index];
495 const Bounds<t_dims, t_type> box = bounds[iterator.depth()];
496 iterator.pop();
497 switch (classify(area, box))
498 {
500 _getAll<false>(index, indices);
501 break;
503 break;
505 if (node.isLeaf())
506 {
507 const uint04 end = node.begin() + node.size();
508 for (uint04 i = node.begin(); i < end; i++)
509 {
510 if (classify(area, elements[m_indices[i]]) != outside)
511 {
512 indices.set(m_indices[i], true);
513 }
514 }
515 }
516 else
517 {
518 Bounds<t_dims, t_type> left = box;
519 left[MAX][node.splitDim()] = node.split();
520 Bounds<t_dims, t_type> right = box;
521
522 Bounds<t_dims, t_type> left = box;
523 right[MIN][node.splitDim()] = node.split();
524
525 iterator.addAndGoToIndex(node.left());
526 bounds[iterator.depth()] = left;
527
528 iterator.addAndGoToIndex(node.right());
529 bounds[iterator.depth()] = right;
530 }
531 break;
532 }
533 }
534 }
535
536 template<class t_area_type, class t_node_type, class t_buffer_type>
537 uint04 _getNumberOfEnclosedElements(uint04 top_node, const t_area_type& area, const t_buffer_type& elements) const
538 {
539 TreeIterator iterator(top_node);
540 uint04 size = 0;
541 while (iterator.valid())
542 {
543 uint04 index = iterator.get();
544 const KDNode<t_dims, t_type>& node = m_nodes[index];
545 iterator.pop();
546 switch (classify(area, node.bounds()))
547 {
549 size += node.size();
550 break;
552 break;
554 if (node.isLeaf())
555 {
556 const uint04 end = node.begin() + node.size();
557 for (uint04 i = node.begin(); i < end; i++)
558 {
559 if (classify(area, elements[m_indices[i]]) != outside)
560 {
561 ++size;
562 }
563 }
564 }
565 else
566 {
567 iterator.addAndGoToIndex(node.left(), node.right());
568 }
569 break;
570 }
571 }
572 return size;
573 }
574
575
576 template<class t_node_type, class t_buffer_type>
577 void _removeValue(uint04 top_node, uint04 index, const t_buffer_type& elements)
578 {
579 bool recalculate_bounds = false;
580 TreeIterator iterator(top_node);
581 while (iterator.valid())
582 {
583 const uint04 node_index = iterator.get();
584 KDNode<t_dims, t_type>& node = m_nodes[node_index];
585 if (node.isLeaf())
586 {
587 uint04 end = node.end();
589 uint04 index_location = Constant<uint04>::NaN;
590 for (uint04 i = node.begin(); i < end; i++)
591 {
592 uint04 check_index = m_indices[i];
593 if (index != check_index)
594 bounds.addToBounds(elements[check_index]);
595 else
596 index_location = i;
597 }
598 node.setSize(node.size() - 1);
599 if (node.size() != 0)
600 m_indices.swapIndices(index_location, node.end());
601 if (classify(node.bounds(), bounds) == inside)
602 recalculate_bounds = true;
603 node.setBounds(bounds);
604 iterator.pop();
605 break;
606 }
607 else
608 {
609
610 bool needs_rebalance = false;
611 if (classify(m_nodes[node.left()].bounds(), elements[index]) == inside)
612 {
613 if (needsRebalance(m_nodes[node.left()].size() - 1, m_nodes[node.right()].size()))
614 needs_rebalance = true;
615 else
616 iterator.addAndGoToIndex(node.left());
617 }
618 else
619 {
620 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() - 1))
621 needs_rebalance = true;
622 else
623 iterator.addAndGoToIndex(node.right());
624 }
625 if (needs_rebalance || node.size() - 1 == m_bucket_size)
626 {
628 _getAll(node_index, indices);
629 node.setSize(node.size() - 1);
630 indices.removeElement(index);
631 reclaimChildren(node_index);
632 _balanceLeafNode(node_index, elements, indices, 0, indices.size(), false);
633 recalculate_bounds = true;
634 break;
635 }
636 else
637 {
638 node.setSize(node.size() - 1);
639 }
640 }
641 }
642 if (recalculate_bounds)
643 {
644 while (iterator.valid())
645 {
646 if (!recalculateBounds(iterator.get(), elements))
647 return;
648 iterator.pop();
649 }
650 }
651 }
652
653
654 template<class t_node_type, class t_buffer_type>
655 void _moveValue(uint04 top_node, uint04 index, const t_node_type& new_location, const t_buffer_type& elements)
656 {
657 TreeIterator iterator(top_node);
658 bool recalculate_bounds = false;
659 while (iterator.valid())
660 {
661 const uint04 node_index = iterator.get();
662 KDNode<t_dims, t_type>& node = m_nodes[node_index];
663 if (node.isLeaf())
664 {
665 if (classify(m_nodes[node.left()].bounds(), new_location) == inside)
666 return;
667 uint04 end = node.end();
669 uint04 index_location = Constant<uint04>::NaN;
670 for (uint04 i = node.begin(); i < end; i++)
671 {
672 uint04 check_index = m_indices[i];
673 if (index != check_index)
674 bounds.addToBounds(elements[check_index]);
675 else
676 index_location = i;
677 }
678 node.setSize(node.size() - 1);
679 if (node.size() != 0)
680 m_indices.swapIndices(index_location, node.end());
681 recalculate_bounds = (classify(node.bounds(), bounds) != inside);
682 node.setBounds(bounds);
683 iterator.pop();
684 break;
685 }
686 else
687 {
688
689 bool needs_rebalance = false;
690 if (classify(m_nodes[node.left()].bounds(), elements[index]) == inside)
691 {
692 if (needsRebalance(m_nodes[node.left()].size() - 1, m_nodes[node.right()].size()))
693 needs_rebalance = true;
694 else
695 iterator.addAndGoToIndex(node.left());
696 }
697 else
698 {
699 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() - 1))
700 needs_rebalance = true;
701 else
702 iterator.addAndGoToIndex(node.right());
703 }
704 if (needs_rebalance || node.size() - 1 == m_bucket_size)
705 {
707 _getAll(node_index, indices);
708 node.setSize(node.size() - 1);
709 indices.removeElement(index);
710 reclaimChildren(node_index);
711 _balanceLeafNode(node_index, elements, indices, 0, indices.size());
712 recalculate_bounds = true;
713 break;
714 }
715 else
716 {
717 node.setSize(node.size() - 1);
718 }
719 }
720 }
721 if (recalculate_bounds)
722 {
723 while (iterator.valid())
724 {
725 if (!recalculateBounds(iterator.get(), elements))
726 return;
727 iterator.pop();
728 }
729 }
730 }
731
732 bool needsRebalance(uint04 left_size, uint04 right_size)
733 {
734 const uint04 total_size = left_size + right_size;
735 return (left_size < total_size / 4 || right_size < total_size / 4);
736 }
737
738 bool useBulkResize(uint04 change_size)
739 {
740 return (change_size > size() / 4);
741 }
742
743 template<class t_node_type, class t_buffer_type>
744 void _addValues(uint04 top_node, Buffer<uint04> indices, const t_buffer_type& elements, bool is_precise, ProgressInfo* progress = nullptr)
745 {
746 _getAll(top_node, indices);
747 reclaimChildren(top_node);
748
749 uint04 max_size = 3 * indices.size();
751 m_nodes.ensureCapacity(2 * max_size / m_bucket_size + (m_nodes.size() - getNumberOfNodes()));
752
753 //m_nodes[top_node].setBounds(_getBounds(indices, elements, 0, indices.size()));
754 bool did_balance = _balanceLeafNode(top_node, elements, indices, 0, indices.size(), is_precise, progress);
755 }
756
757
758 template<class t_node_type, class t_buffer_type>
759 void _addValue(uint04 node_index, uint04 index, const t_buffer_type& elements)
760 {
761 /*Bounds<t_dims, t_type> bounds(elements[index]);
762 for (;;)
763 {
764
765 KDNode<t_dims, t_type>& node = m_nodes[node_index];
766 node.bounds().addToBoundingBox(bounds);
767 if (node.isLeaf())
768 {
769 if (node.size() == m_bucket_size)
770 {
771 Buffer<uint04> indices(m_bucket_size + 1);
772 _getAll(node_index, indices);
773 indices.add(index);
774 _balanceLeafNode(node_index, elements, indices, 0, m_bucket_size + 1, false);
775 }
776 else
777 {
778 m_indices[node.begin() + node.size()] = index;
779 node.setSize(node.size() + 1);
780 }
781 return;
782 }
783 else
784 {
785 Bounds<t_dims, t_type> left = m_nodes[node.left()].bounds();
786 Bounds<t_dims, t_type> right = m_nodes[node.right()].bounds();
787
788 left.addToBoundingBox(bounds);
789 right.addToBoundingBox(bounds);
790 bool needs_rebalance = false;
791 if (left.volume() - m_nodes[node.left()].bounds().volume() < right.volume() - m_nodes[node.right()].bounds().volume())
792 {
793 if (needsRebalance(m_nodes[node.left()].size() + 1, m_nodes[node.right()].size()))
794 needs_rebalance = true;
795 else
796 node_index = node.left();
797 }
798 else
799 {
800 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() + 1))
801 needs_rebalance = true;
802 else
803 node_index = node.right();
804 }
805 if (needs_rebalance)
806 {
807 Buffer<uint04> indices(node.size() + 1);
808 _getAll(node_index, indices);
809 indices.add(index);
810 reclaimChildren(node_index);
811 _balanceLeafNode(node_index, elements, indices, 0, indices.size(), false);
812 return;
813 }
814 else
815 {
816 node.setSize(node.size() + 1);
817 }
818 }
819 }*/
820 }
821
822 template<class t_node_type, class t_buffer_type>
823 bool recalculateBounds(uint04 node_index, const t_buffer_type& elements)
824 {
826 KDNode<t_dims, t_type>& node = m_nodes[node_index];
827 if (node.isLeaf())
828 {
829 uint04 end = node.end();
830 for (uint04 i = node.begin(); i < end; i++)
831 {
832 bounds.addToBounds(elements[m_indices[i]]);
833 }
834 }
835 else
836 {
837 bounds = Bounds<t_dims, t_type>(m_nodes[node.left()].bounds(), m_nodes[node.right()].bounds());
838 }
839 if (classify(node.bounds(), bounds) == inside)
840 return false;
841 node.setBounds(bounds);
842 return true;
843 }
844
846 {
847 if (!m_is_read_only)
848 return;
850
851 TreeIterator iterator(root_node);
852 while (iterator.valid())
853 {
855 iterator.pop();
856 if (node.isLeaf())
857 {
858 node.setBegin(iterator.size());
859 indices.addAll(m_indices.begin(node.begin()), node.size());
860 }
861 else
862 iterator.addAndGoToIndex(node.left(), node.right());
863 }
865 }
866 };
867
868
869 template<uint01 t_dims, class t_type>
870 class KDTree : public Tree<t_dims, t_type, KDTreeBase<t_dims, t_type>>
871 {
872 public:
873 explicit KDTree<t_dims, t_type>(uint04 bucket_size)
874 : Tree(bucket_size)
875 {}
877 : Tree(tree)
878 {}
880 : Tree(std::move(tree))
881 {}
882 protected:
883 KDTree<t_dims, t_type>(const Buffer<KDNode<t_dims, t_type>>& nodes, const Buffer<uint04>& indices, bool is_read_only)
884 : TreeBase(nodes, indices, is_read_only)
885 {}
886 public:
887 inline KDTree& operator=(const KDTree& value)
888 {
889 m_indices = value.m_indices;//setting equal to ourselves
890 m_nodes = value.m_nodes;
893 return (*this);
894 }
895 inline KDTree& operator=(KDTree&& value)
896 {
897 std::swap(m_indices, value.m_indices);//setting equal to ourselves
898 std::swap(m_nodes, value.m_nodes);
899 std::swap(m_available_node_positions, value.m_available_node_positions);
900 std::swap(m_available_indexed_positions, value.m_available_indexed_positions);
901 return (*this);
902 }
903
904 virtual const char* getTreeType() const override
905 {
906 return "KD Tree";
907 }
908 };
909}
Definition BinaryHeap.hpp:39
void insert(t_comp_type comparison, t_value_type value)
Definition BinaryHeap.hpp:44
uint04 size() const
Definition BinaryHeap.hpp:71
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:57
constexpr void addToBounds(const t_vertex &vector)
Adds to the bounds such that the new bounds fully encompasses the argument.
Definition Bounds.hpp:498
constexpr t_vertex center() const
Returns the center of the bounds.
Definition Bounds.hpp:156
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:64
void setAll(const t_o_type *src, t_index_type offset, t_index_type size)
Definition Buffer.hpp:1313
constexpr t_index_type size() const
Definition Buffer.hpp:1461
void addAll(const Buffer< t_type, t_other_index_type, t_other_memory_allocator, t_other_memory_manager > &buffer)
Definition Buffer.hpp:248
void setSize(t_index_type new_size)
Definition Buffer.hpp:1413
void swapIndices(t_index_type index_1, t_index_type index_2)
Definition Buffer.hpp:1550
void ensureCapacity(t_index_type new_capacity, bool ensure_not_greater=false, bool ensure_not_less=true)
Definition Buffer.hpp:803
decltype(auto) begin()
Definition Buffer.hpp:504
bool removeElement(const t_type &element)
Definition Buffer.hpp:1076
void setAllToValue(const t_o_type &fill_element, const t_index_type offset=0, t_index_type fill_size=Constant< t_index_type >::NaN)
Definition Buffer.hpp:1378
Definition KDTree.hpp:52
t_type m_split
Definition KDTree.hpp:95
uint04 right() const
Definition KDTree.hpp:76
uint01 m_split_dim
Definition KDTree.hpp:96
const uint01 & splitDim() const
Definition KDTree.hpp:85
KDNode(uint04 index_start)
Definition KDTree.hpp:59
uint04 left() const
Definition KDTree.hpp:72
void clear(uint04 index_start, const Bounds< t_dims, t_type > &bounds)
Definition KDTree.hpp:65
void setSplit(uint01 split_dim, t_type split)
Definition KDTree.hpp:89
KDNode(const KDNode &node)
Definition KDTree.hpp:54
const t_type & split() const
Definition KDTree.hpp:81
Definition KDTree.hpp:103
bool _balanceLeafNode(uint04 top_index, const t_buffer_type &elements, Buffer< uint04 > &indices, uint04 top_start, uint04 top_end, bool is_precise, ProgressInfo *progress=nullptr)
Definition KDTree.hpp:173
void _makeWriteable()
Definition KDTree.hpp:845
bool validate(const Buffer< t_node_type > &elements)
Definition KDTree.hpp:120
uint04 _getNumberOfEnclosedElements(uint04 top_node, const t_area_type &area, const t_buffer_type &elements) const
Definition KDTree.hpp:537
void _getClosestElements(uint04 top_index, const Vector< t_dims, t_type > &point, const t_buffer_type &elements, t_type &min_distance, const t_type &epsilon, MinHeap< t_type, uint04 > &heap, uint04 size) const
Definition KDTree.hpp:297
void _addValue(uint04 node_index, uint04 index, const t_buffer_type &elements)
Definition KDTree.hpp:759
void _getEnclosedElements(uint04 top_node, t_area_type area, Buffer< bool > &indices, const t_buffer_type &elements) const
Definition KDTree.hpp:486
bool needsRebalance(uint04 left_size, uint04 right_size)
Definition KDTree.hpp:732
KDTreeBase(uint04 bucket_size)
Definition KDTree.hpp:105
bool useBulkResize(uint04 change_size)
Definition KDTree.hpp:738
bool _getClosestElement(uint04 top_index, const Triangle< t_dims, t_type > &triangle, const t_buffer_type &elements, t_type &min_distance, t_type epsilon, uint04 &min_index) const
Definition KDTree.hpp:445
void _moveValue(uint04 top_node, uint04 index, const t_node_type &new_location, const t_buffer_type &elements)
Definition KDTree.hpp:655
void _addValues(uint04 top_node, Buffer< uint04 > indices, const t_buffer_type &elements, bool is_precise, ProgressInfo *progress=nullptr)
Definition KDTree.hpp:744
bool _getClosestElement(uint04 top_index, const Vector< t_dims, t_type > &point, const t_buffer_type &elements, t_type &min_distance, const t_type epsilon, uint04 &min_index) const
Definition KDTree.hpp:240
void _removeValue(uint04 top_node, uint04 index, const t_buffer_type &elements)
Definition KDTree.hpp:577
bool recalculateBounds(uint04 node_index, const t_buffer_type &elements)
Definition KDTree.hpp:823
uint04 _calculateAndSplit(uint04 node_index, Bounds< t_dims, t_type > node_bounds, const t_buffer_type &elements, Buffer< uint04 > &indices, uint04 start, uint04 end, bool is_precise)
Definition KDTree.hpp:144
bool _getClosestElement(uint04 top_index, const LineSegment< t_dims, t_type > &top_line, const t_buffer_type &elements, t_type &min_distance, t_type epsilon, uint04 &min_index) const
Definition KDTree.hpp:358
Definition KDTree.hpp:871
virtual const char * getTreeType() const override
Definition KDTree.hpp:904
KDTree & operator=(KDTree &&value)
Definition KDTree.hpp:895
KDTree & operator=(const KDTree &value)
Definition KDTree.hpp:887
KDTree(uint04 bucket_size)
Definition KDTree.hpp:873
A line segment represented by two vertices, a start and end.
Definition Line.hpp:55
Definition ProgressInfo.hpp:43
Definition Tree.hpp:54
uint04 getNumberOfFreeIndices()
Definition Tree.hpp:343
Buffer< KDNode< t_dims, t_type >, uint04, ObjectAllocator< true > > m_nodes
Definition Tree.hpp:480
void reclaimChildren(uint04 index)
Definition Tree.hpp:397
const Buffer< uint04 > & indices() const
Definition Tree.hpp:287
Buffer< uint04 > m_available_node_positions
Definition Tree.hpp:481
void _getAllT(const uint04 &node_index, Buffer< bool > &indices) const
Definition Tree.hpp:423
void _getAll(const uint04 &node_index, Buffer< uint04 > &indices) const
Definition Tree.hpp:445
uint04 getNumberOfNodes() const
Definition Tree.hpp:104
Bounds< t_dims, t_type > _getBounds(const Buffer< uint04 > &indices, const t_buffer_type &elements, uint04 start, uint04 end)
Definition Tree.hpp:257
uint04 size() const
Definition Tree.hpp:229
Buffer< uint04 > m_indices
Definition Tree.hpp:479
static const uint04 root_node
Definition Tree.hpp:483
TreeBase(uint04 bucket_size)
Definition Tree.hpp:57
void splitLeafNode(uint04 index)
Definition Tree.hpp:353
Buffer< uint04 > m_available_indexed_positions
Definition Tree.hpp:482
Definition Tree.hpp:489
Tree(uint04 bucket_size)
Definition Tree.hpp:491
Definition TreeIterator.hpp:38
void pop()
Definition TreeIterator.hpp:53
bool valid() const
Definition TreeIterator.hpp:49
uint01 depth()
Definition TreeIterator.hpp:57
void addAndGoToIndex(uint04 index)
Definition TreeIterator.hpp:61
uint04 get() const
Definition TreeIterator.hpp:45
Definition Node.hpp:37
uint04 begin() const
Definition Node.hpp:54
bool isLeaf() const
Definition Node.hpp:87
void setSize(uint04 bucket_size)
Definition Node.hpp:82
uint04 end() const
Definition Node.hpp:59
uint04 size() const
Definition Node.hpp:78
uint04 m_element_size
Definition Node.hpp:92
void setBegin(uint04 index_start)
Definition Node.hpp:50
sint04 m_child_start
Definition Node.hpp:93
Definition Triangle.hpp:143
An element of a vector space. An element of the real coordinate space Rn Basis vector,...
Definition Vector.hpp:62
Definition ACIColor.h:37
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator.
Definition BaseFunctions.hpp:116
@ MIN
Definition BaseValues.hpp:226
@ MAX
Definition BaseValues.hpp:227
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:98
uint04 apxMedian(const t_buffer_type &elements, const Buffer< uint04 > &indices, uint04 start, uint04 end, uint01 dimension)
Definition Median.hpp:298
t_type distanceSquared(const Bounds< t_dims, t_type, t_vertex > &bounds, const Vector< t_dims, t_type > &vertex)
Definition Distance.hpp:42
@ inside
Definition BaseValues.hpp:243
@ mixed
Definition BaseValues.hpp:244
@ outside
Definition BaseValues.hpp:242
IntersectionTypes classify(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition Intersection.hpp:338
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
t_type sqrt(const t_type &value)
Definition VectorFunctions.hpp:1309
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:514
constexpr t_type distance(const t_vertex &vertex, const LineSegment< t_dims, t_type, t_vertex > &line)
Definition Distance.hpp:250
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Definition AngleFunctions.h:750
uint04 sortAboutValue(uint04 value_index, const Buffer< t_node_type > &points, Buffer< uint04 > &indices, uint04 start, uint04 end, uint01 dimension)
Definition Median.hpp:337
uint04 median(const t_container_type &elements, Buffer< uint04 > &indices, const uint04 start, const uint04 end, uint01 dimension)
Definition Median.hpp:39
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator.
Definition BaseFunctions.hpp:67
Definition BaseValues.hpp:272