34#include <NDEVR/TreeIterator.h>
35#include <NDEVR/Node.h>
36#include <NDEVR/Tree.h>
37#include <NDEVR/TreeSorter.h>
38#include <NDEVR/BaseValues.h>
39#include <NDEVR/Buffer.h>
40#include <NDEVR/Bounds.h>
41#include <NDEVR/Median.h>
42#include <NDEVR/OpenMP.h>
43#include <NDEVR/InfoPipe.h>
44#include <NDEVR/Vector.h>
45#include <NDEVR/VectorFunctions.h>
46#include <NDEVR/Intersection.h>
47#include <NDEVR/Distance.h>
48#include <NDEVR/BinaryHeap.h>
49#include <NDEVR/BinaryFile.h>
50#include <NDEVR/BinaryFileTableInfo.h>
54 template<u
int01 t_dims,
class t_type>
55 class RNode :
public TreeNode
60 , m_cache_bounds(Constant<Bounds<t_dims, t_type>>::
Invalid)
62 explicit RNode(
uint04 index_start)
63 : TreeNode(index_start)
64 , m_cache_bounds(Constant<Bounds<t_dims, t_type>>::
Min)
66 void clear(
uint04 index_start)
68 setBegin(index_start);
69 m_cache_bounds = Constant<Bounds<t_dims, t_type>>
::Invalid;
72 void clear(
uint04 index_start,
const Bounds<t_dims, t_type>& bounds)
74 setBegin(index_start);
75 m_cache_bounds = bounds;
81 return uint04(m_child_start);
85 return uint04(m_child_start) + 1;
88 const Bounds<t_dims, t_type>& bounds()
const
90 return m_cache_bounds;
92 Bounds<t_dims, t_type>& bounds()
94 return m_cache_bounds;
96 void setBounds(
const Bounds<t_dims, t_type>& bounds)
98 m_cache_bounds = bounds;
102 Bounds<t_dims, t_type> m_cache_bounds;
107 template<u
int01 t_dims,
class t_type>
108 class RTreeBase :
public TreeBase<RNode<t_dims, t_type>, t_type, 2>
111 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_nodes;
112 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::root_node;
113 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_indices;
114 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_bucket_size;
115 explicit RTreeBase<t_dims, t_type>(
uint04 bucket_size)
116 : TreeBase<RNode<t_dims, t_type>, t_type, 2>(bucket_size)
118 RTreeBase<t_dims, t_type>(
const RTreeBase<t_dims, t_type>& tree)
119 : TreeBase<RNode<t_dims, t_type>, t_type, 2>(tree)
121 RTreeBase<t_dims, t_type>(RTreeBase<t_dims, t_type>&& tree)
122 : TreeBase<RNode<t_dims, t_type>, t_type, 2>(std::move(tree))
125 RTreeBase<t_dims, t_type>(
const Buffer<RNode<t_dims, t_type>>& nodes,
const Buffer<uint04>& indices,
bool is_read_only)
126 : TreeBase<RNode<t_dims, t_type>, t_type, 2>(nodes, indices, is_read_only)
129 template<
class t_buffer_type>
130 bool validate(
const t_buffer_type& elements)
132 TreeIterator iterator(root_node);
134 Buffer<uint04> values;
135 values.setSize(elements.size());
136 if (elements.size() == 0)
139 while (iterator.valid())
141 if (i++ > m_nodes.size())
143 lib_assert(
false,
"invalid tree");
146 const uint04 node_index = iterator.get();
147 RNode<t_dims, t_type>& node = m_nodes[node_index];
151 if(m_indices.size() == 0)
152 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<true>(node_index, values);
154 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(node_index, values);
155 if (node.size() != values.size())
157 lib_assert(
false,
"invalid tree");
162 if (node.size() != 0 && !node.bounds().validate())
164 lib_assert(
false,
"invalid tree");
170 const uint04 end = node.begin() + node.size();
171 if (m_indices.size() > 0)
173 for (
uint04 idx = node.begin(); idx < end; idx++)
175 const auto& element = elements[m_indices[idx]];
176 if (
IsValid(element) && classify(node.bounds(), element.template as<t_dims, t_type>()) != IntersectionTypes::e_inside)
178 lib_assert(
false,
"invalid tree");
185 for (
uint04 idx = node.begin(); idx < end; idx++)
187 const auto& element = elements[idx];
188 if (
IsValid(element) && classify(node.bounds(), element.template as<t_dims, t_type>()) != IntersectionTypes::e_inside)
190 lib_assert(
false,
"invalid tree");
198 if (node.size() != m_nodes[node.left()].size() + m_nodes[node.right()].size())
200 lib_assert(
false,
"invalid tree");
203 if(
IsValid(node.bounds()) &&
IsValid(m_nodes[node.left()].bounds()))
204 if (classify(node.bounds(), m_nodes[node.left()].bounds()) != IntersectionTypes::e_inside)
206 lib_assert(
false,
"invalid tree");
209 if (
IsValid(node.bounds()) &&
IsValid(m_nodes[node.right()].bounds()))
210 if (classify(node.bounds(), m_nodes[node.right()].bounds()) != IntersectionTypes::e_inside)
212 lib_assert(
false,
"invalid tree");
216 iterator.addAndGoToIndex(node.left(), node.right());
221 void traverse(
const std::function<
void(
uint04 node_index,
const PrimitiveBuffer<RNode<t_dims, t_type>>& node,
const Buffer<uint04>& indices)>& callback)
const
223 TreeIterator iterator(root_node);
224 while (iterator.valid())
226 const uint04 node_index = iterator.get();
227 const RNode<t_dims, t_type>& node = m_nodes[node_index];
229 callback(node_index, m_nodes, m_indices);
232 iterator.addAndGoToIndex(node.left(), node.right());
238 template<
class t_buffer_type>
239 uint04 _calculateAndSplit(
uint04 node_index, TreeBoundarySorter<t_dims, t_type>& sorter,
const t_buffer_type& elements,
uint04 start,
uint04 end,
bool is_precise)
242 Vector<t_dims, t_type> d_size;
243 for (
uint01 dim = 0; dim < t_dims; ++dim)
245 if (m_nodes[node_index].bounds().span(dim) != 0)
247 Vector<2, Bounds<t_dims, t_type>> potential_bounds = sorter.getMedianBounds(dim, start, end, elements);
248 d_size[dim] = potential_bounds[0].surfaceArea() + potential_bounds[1].surfaceArea();
252 const uint01 split_dim = d_size.template dimensionalIndex<MIN>();
254 sorter.getMedian(split_dim, start, end);
255 const uint04 median_location = ((end - start) / 2) + start;
257 TreeBase<RNode<t_dims, t_type>, t_type, 2>::splitLeafNode(node_index);
258 auto left = sorter.getBounds(start, median_location, elements);
259 auto right = sorter.getBounds(median_location, end, elements);
262 if (classify(m_nodes[node_index].bounds(), left) != IntersectionTypes::e_inside)
263 lib_assert(
false,
"bad bounds creation");
265 if (classify(m_nodes[node_index].bounds(), right) != IntersectionTypes::e_inside)
266 lib_assert(
false,
"bad bounds creation");
268 m_nodes[m_nodes[node_index].left()].setBounds(left);
269 m_nodes[m_nodes[node_index].right()].setBounds(right);
271 return median_location;
273 template<
bool t_has_nans,
bool t_uses_boundary,
class t_buffer_type>
274 bool _balanceLeafNode(
uint04 top_index,
const t_buffer_type& elements, Buffer<uint04>& indices,
uint04 top_start,
uint04 top_end,
bool is_precise)
276 TreeBoundarySorter<t_dims, t_type> sorter;
277 if constexpr (t_uses_boundary)
279 sorter.template createBoundarySortList<t_has_nans>(indices, elements);
283 sorter.template createCenterSortList<t_has_nans>(indices, elements);
285 m_nodes[top_index].setBounds(sorter.getBounds(0, (top_end - top_start), elements));
288 start_stack[0] = top_start;
289 end_stack[0] = top_end;
290 TreeIterator iterator(top_index);
291 while (iterator.valid())
293 uint01 level = iterator.depth();
294 uint04 start = start_stack[level];
295 uint04 end = end_stack[level];
296 uint04 node_index = iterator.get();
298 m_nodes[node_index].setSize(end - start);
300 if ((end - start) > m_bucket_size)
302 const uint04 new_left = _calculateAndSplit(node_index, sorter, elements, start, end, is_precise);
304 iterator.addAndGoToIndex(m_nodes[node_index].right());
305 start_stack[iterator.depth()] = new_left;
306 end_stack[iterator.depth()] = end;
308 iterator.addAndGoToIndex(m_nodes[node_index].left());
309 start_stack[iterator.depth()] = start;
310 end_stack[iterator.depth()] = new_left;
314 sorter.getList(0, start, end, m_indices, m_nodes[node_index].begin());
319 template<
class t_location_type>
320 bool predictBranch(
uint04& index,
const RNode<t_dims, t_type>& node,
const t_location_type& selector, MinHeap<t_type, uint04>& node_heap, t_type min_distance_squared)
const
322 t_type left_distance = distanceSquared(selector, m_nodes[node.left()].bounds());
323 if(left_distance <= t_type(0))
324 left_distance = -(
cast<t_type>(1) / distanceSquared(selector, m_nodes[node.left()].bounds().center()));
325 t_type right_distance = distanceSquared(selector, m_nodes[node.right()].bounds());
326 if (right_distance <= t_type(0))
327 right_distance = -(
cast<t_type>(1) / distanceSquared(selector, m_nodes[node.right()].bounds().center()));
328 if (left_distance < right_distance)
330 if (left_distance >= min_distance_squared)
332 if (node_heap.size() == 0 || node_heap.extremeComp() >= min_distance_squared)
334 index = node_heap.popExtreme();
336 else if(node_heap.size() > 0 && node_heap.extremeComp() < left_distance)
338 index = node_heap.popExtreme();
339 node_heap.insert(left_distance, node.left());
340 if (right_distance < min_distance_squared)
341 node_heap.insert(right_distance, node.right());
346 if (right_distance < min_distance_squared)
347 node_heap.insert(right_distance, node.right());
352 if (right_distance >= min_distance_squared)
354 if (node_heap.size() == 0 || node_heap.extremeComp() >= min_distance_squared)
356 index = node_heap.popExtreme();
358 else if (node_heap.size() > 0 && node_heap.extremeComp() < right_distance)
360 index = node_heap.popExtreme();
361 node_heap.insert(right_distance, node.right());
362 if (left_distance < min_distance_squared)
363 node_heap.insert(left_distance, node.right());
367 index = node.right();
368 if (left_distance < min_distance_squared)
369 node_heap.insert(left_distance, node.left());
374 template<
bool t_presorted,
class t_location_type,
class t_buffer_type>
375 void _getClosestElement(
uint04 top_index,
const t_location_type& selector,
const t_buffer_type& elements, t_type& min_distance_squared,
const t_type& epsilon,
uint04& min_index)
const
377 t_type root_distance = distanceSquared(selector, m_nodes[top_index].bounds());
378 lib_assert(min_distance_squared >= 0.0f,
"Cannot search for 0.0 distance. Use epsilon");
379 if (root_distance >= min_distance_squared)
385 const RNode<t_dims, t_type>& node = m_nodes[index];
388 const uint04 end = node.end();
389 const uint04 start_index = node.begin();
390 for(
uint04 i = start_index; i < end; ++i)
393 if constexpr(t_presorted)
396 check_index = m_indices[i];
397 t_type distance = distanceSquared(selector, elements[check_index].
template as<t_dims, t_type>());
398 if (distance < min_distance_squared)
400 min_distance_squared = distance;
401 min_index = check_index;
402 if (min_distance_squared <= epsilon)
406 if (node_heap.size() == 0 || node_heap.extremeComp() >= min_distance_squared)
408 index = node_heap.popExtreme();
412 if (!predictBranch(index, node, selector, node_heap, min_distance_squared))
418 template<
bool t_presorted,
class t_buffer_type,
class t_reference_type>
419 void _getClosestElements(
uint04 top_index,
const t_reference_type& selector,
const t_buffer_type& elements, t_type& min_distance_squared,
const t_type& epsilon, MaxHeap<t_type, uint04>& value_heap,
uint04 size)
const
422 t_type root_distance = distanceSquared(selector, m_nodes[top_index].bounds());
423 if (root_distance >= min_distance_squared)
428 const RNode<t_dims, t_type>& node = m_nodes[index];
431 const uint04 end = node.end();
432 for (
uint04 i = node.begin(); i < end; ++i)
435 if constexpr (t_presorted)
438 check_index = m_indices[i];
439 t_type distance = distanceSquared(selector, elements[check_index]);
440 if (distance < min_distance_squared)
442 value_heap.insert(distance, check_index);
443 if (value_heap.size() > size)
445 value_heap.deleteExtreme();
446 min_distance_squared = value_heap.extremeComp();
447 if (min_distance_squared <= epsilon)
452 if (node_heap.size() == 0 || node_heap.extremeComp() >= min_distance_squared)
454 index = node_heap.popExtreme();
458 if (!predictBranch(index, node, selector, node_heap, min_distance_squared))
463 template<
bool t_presorted,
class t_area_type,
class t_buffer_type>
464 void _getEnclosedElements(
uint04 top_node, t_area_type area, Buffer<bool>& indices,
const t_buffer_type& elements)
const
466 TreeIterator iterator(top_node);
467 while (iterator.valid())
469 uint04 index = iterator.get();
470 const RNode<t_dims, t_type>& node = m_nodes[index];
472 switch (classify(area, node.bounds()))
474 case IntersectionTypes::e_inside:
475 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAllT<t_presorted, true>(index, indices);
477 case IntersectionTypes::e_outside:
479 case IntersectionTypes::e_mixed:
482 const uint04 end = node.begin() + node.size();
483 for (
uint04 i = node.begin(); i < end; i++)
490 if (classify(area, elements[idx]) != IntersectionTypes::e_outside)
498 iterator.addAndGoToIndex(node.left(), node.right());
505 template<
bool t_is_presorted,
class t_area_type,
class t_buffer_type>
506 void _getEnclosedElements(
uint04 top_node, t_area_type area, Buffer<uint04>& indices,
const t_buffer_type& elements)
const
508 TreeIterator iterator(top_node);
509 while (iterator.valid())
511 uint04 index = iterator.get();
512 const RNode<t_dims, t_type>& node = m_nodes[index];
514 switch (classify(area, node.bounds()))
516 case IntersectionTypes::e_inside:
517 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<t_is_presorted>(index, indices);
519 case IntersectionTypes::e_mixed:
522 const uint04 end = node.begin() + node.size();
523 for (
uint04 i = node.begin(); i < end; ++i)
526 if constexpr (t_is_presorted)
529 local_index = m_indices[i];
530 if (classify(area, elements[local_index]) != IntersectionTypes::e_outside)
532 indices.add(local_index);
538 iterator.addAndGoToIndex(node.left(), node.right());
541 case IntersectionTypes::e_outside:
546 template<
bool t_presorted,
class t_area_type,
class t_buffer_type>
547 void _getNearElements(
uint04 top_node, t_area_type area, Buffer<bool>& indices,
const t_buffer_type& elements, t_type max_distance_sqrd)
const
549 TreeIterator iterator(top_node);
550 while (iterator.valid())
552 uint04 index = iterator.get();
553 const RNode<t_dims, t_type>& node = m_nodes[index];
555 t_type distance = distanceSquared(area, node.bounds());
556 if (distance <= max_distance_sqrd)
560 const uint04 end = node.begin() + node.size();
561 for (
uint04 i = node.begin(); i < end; i++)
568 if (distanceSquared(area, elements[idx]) <= max_distance_sqrd)
576 iterator.addAndGoToIndex(node.left(), node.right());
582 template<
bool t_presorted,
class t_area_type,
class t_buffer_type>
583 void _getNearElements(
uint04 top_node, t_area_type area, Buffer<uint04>& indices,
const t_buffer_type& elements, t_type max_distance_sqrd)
const
585 TreeIterator iterator(top_node);
586 while (iterator.valid())
588 uint04 index = iterator.get();
589 const RNode<t_dims, t_type>& node = m_nodes[index];
591 t_type distance = distanceSquared(area, node.bounds());
592 if (distance <= max_distance_sqrd)
596 const uint04 end = node.begin() + node.size();
597 for (
uint04 i = node.begin(); i < end; i++)
604 if (distanceSquared(area, elements[idx]) <= max_distance_sqrd)
612 iterator.addAndGoToIndex(node.left(), node.right());
617 template<
class t_area_type,
class t_buffer_type>
618 uint04 _getNumberOfEnclosedElements(
uint04 top_node,
const t_area_type& area,
const t_buffer_type& elements)
const
620 TreeIterator iterator(top_node);
622 while (iterator.valid())
624 uint04 index = iterator.get();
625 const RNode<t_dims, t_type>& node = m_nodes[index];
627 switch (TreeBase<RNode<t_dims, t_type>, t_type, 2>::classify(area, node.bounds()))
629 case IntersectionTypes::e_inside:
632 case IntersectionTypes::e_outside:
634 case IntersectionTypes::e_mixed:
637 const uint04 end = node.begin() + node.size();
638 for (
int i = node.begin(); i < end; i++)
640 if (TreeBase<RNode<t_dims, t_type>, t_type, 2>::classify(area, elements[m_indices[i]]) != IntersectionTypes::e_outside)
648 iterator.addAndGoToIndex(node.left(), node.right());
656 template<
class t_area_type,
class t_buffer_type>
657 void _getNearElements(
uint04 top_node, t_type max_distance,
const t_area_type& area, Buffer<bool>& indices,
const t_buffer_type& elements)
const
659 TreeIterator iterator(top_node);
660 while (iterator.valid())
662 const uint04 index = iterator.get();
663 const RNode<t_dims, t_type>& node = m_nodes[index];
665 Bounds<t_dims, t_type> bounds = node.bounds();
666 bounds.expand(max_distance);
667 switch (classify(bounds, area))
670 #pragma clang diagnostic push
671 #pragma clang diagnostic ignored "-Wunused-value"
673 case IntersectionTypes::e_inside:
674 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(index, indices);
677 #pragma clang diagnostic pop
679 case IntersectionTypes::e_outside:
681 case IntersectionTypes::e_mixed:
684 const uint04 end = node.begin() + node.size();
685 for (
uint04 i = node.begin(); i < end; i++)
687 if (distanceSqaured(area, elements[m_indices[i]]) < max_distance)
689 indices[m_indices[i]] =
true;
695 iterator.addAndGoToIndex(node.left(), node.right());
701 template<
bool t_presorted,
bool t_allow_enable,
bool t_allow_disable,
class t_area_type,
class t_buffer_type>
702 void _getChangedElements(
uint04 top_node,
const t_area_type& new_area,
const t_area_type& old_area, Buffer<bool>& indices,
const t_buffer_type& elements)
const
704 TreeIterator iterator(top_node);
705 while (iterator.valid())
707 bool is_mixed =
false;
708 uint04 index = iterator.get();
709 const RNode<t_dims, t_type>& node = m_nodes[index];
711 switch (classify(new_area, node.bounds()))
713 case IntersectionTypes::e_inside:
714 switch (classify(old_area, node.bounds()))
716 case IntersectionTypes::e_inside:
718 case IntersectionTypes::e_outside:
720 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAllT<t_presorted, true>(index, indices);
722 case IntersectionTypes::e_mixed:
727 case IntersectionTypes::e_outside:
728 switch (classify(old_area, node.bounds()))
730 case IntersectionTypes::e_inside:
732 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAllT<t_presorted, false>(index, indices);
734 case IntersectionTypes::e_outside:
736 case IntersectionTypes::e_mixed:
741 case IntersectionTypes::e_mixed:
749 const uint04 end = node.begin() + node.size();
750 for (
uint04 i = node.begin(); i < end; i++)
753 if constexpr (t_presorted)
757 if constexpr (t_allow_enable && t_allow_disable)
759 indices[idx] = (classify(new_area, elements[idx]) != IntersectionTypes::e_outside);
761 else if (t_allow_disable)
765 if(classify(new_area, elements[idx]) == IntersectionTypes::e_outside)
766 indices[idx] =
false;
768 else if (t_allow_enable)
772 if(classify(new_area, elements[idx]) != IntersectionTypes::e_outside)
779 iterator.addAndGoToIndex(node.left(), node.right());
785 template<
class t_buffer_type>
786 void _removeValue(
uint04 top_node,
uint04 index,
const t_buffer_type& elements)
788 bool recalculate_bounds =
false;
789 TreeIterator iterator(top_node);
790 while (iterator.valid())
792 const uint04 node_index = iterator.get();
793 RNode<t_dims, t_type>& node = m_nodes[node_index];
797 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
798 uint04 index_location = Constant<uint04>::Invalid;
799 for (
uint04 i = node.begin(); i < end; i++)
801 uint04 check_index = m_indices[i];
802 if (index != check_index)
803 bounds.addToBounds(elements[check_index].
template as<t_dims, t_type>());
807 node.setSize(node.size() - 1);
808 if (node.size() != 0)
809 m_indices.swapIndices(index_location, node.end());
810 if (classify(node.bounds(), bounds) == IntersectionTypes::e_inside)
811 recalculate_bounds =
true;
812 node.setBounds(bounds);
819 bool needs_rebalance =
false;
820 if (classify(m_nodes[node.left()].bounds(), elements[index]) == IntersectionTypes::e_inside)
822 if (needsRebalance(m_nodes[node.left()].size() - 1, m_nodes[node.right()].size()))
823 needs_rebalance =
true;
825 iterator.addAndGoToIndex(node.left());
829 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() - 1))
830 needs_rebalance =
true;
832 iterator.addAndGoToIndex(node.right());
834 if (needs_rebalance || node.size() - 1 == m_bucket_size)
836 Buffer<uint04> indices(node.size());
837 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(node_index, indices);
838 node.setSize(node.size() - 1);
839 indices.removeElement(index);
840 TreeBase<RNode<t_dims, t_type>, t_type, 2>::reclaimChildren(node_index);
842 recalculate_bounds =
true;
847 node.setSize(node.size() - 1);
851 if (recalculate_bounds)
853 while (iterator.valid())
855 if (!recalculateBounds(iterator.get(), elements))
863 template<
class t_node_type,
class t_buffer_type>
864 void _moveValue(
uint04 top_node,
uint04 index,
const t_node_type& old_location,
const t_buffer_type& elements,
bool rebalance)
866 TreeIterator iterator(top_node);
867 bool recalculate_bounds =
false;
868 while (iterator.valid())
870 const uint04 node_index = iterator.get();
871 RNode<t_dims, t_type>& node = m_nodes[node_index];
875 if (classify(m_nodes[node.left()].bounds(), elements[index]) == IntersectionTypes::e_inside)
879 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
880 uint04 index_location = Constant<uint04>::Invalid;
881 for (
uint04 i = node.begin(); i < end; i++)
883 uint04 check_index = m_indices[i];
884 if (index != check_index)
885 bounds.addToBounds(elements[check_index]);
890 switch (classify(node.bounds(), bounds))
892 case IntersectionTypes::e_inside:
893 recalculate_bounds =
true;
894 node.setBounds(bounds);
896 case IntersectionTypes::e_mixed:
897 case IntersectionTypes::e_outside:
898 lib_assert(node.bounds() == bounds,
"Unexpected Node Resize behavior: Removing object should not increase bounds");
899 recalculate_bounds =
false;
904 node.setSize(node.size() - 1);
905 if (node.size() != 0)
906 m_indices.swapIndices(index_location, node.end());
913 if (classify(m_nodes[node.left()].bounds(), old_location) == IntersectionTypes::e_inside)
915 iterator.addAndGoToIndex(node.left());
919 lib_assert(classify(m_nodes[node.right()].bounds(), old_location) == IntersectionTypes::e_inside,
"Original Element not in either bounds");
920 iterator.addAndGoToIndex(node.right());
924 bool added_in =
false;
925 while (iterator.valid() && (!added_in || recalculate_bounds))
927 const uint04 node_index = iterator.get();
928 if (recalculate_bounds)
930 recalculate_bounds = recalculateBounds(node_index, elements);
934 RNode<t_dims, t_type>& node = m_nodes[node_index];
935 if (classify(node.bounds(), elements[index]) == IntersectionTypes::e_inside)
937 TreeBase<RNode<t_dims, t_type>, t_type, 2>::_addValue(node_index, index, elements, rebalance);
945 TreeBase<RNode<t_dims, t_type>, t_type, 2>::_addValue(top_node, index, elements, rebalance);
949 bool needsRebalance(
uint04 left_size,
uint04 right_size)
951 const uint04 total_size = left_size + right_size;
952 return (left_size < total_size / 3 || right_size < total_size / 3);
955 bool useBulkResize(
uint04 change_size)
957 return (change_size > TreeBase<RNode<t_dims, t_type>, t_type, 2>::size() / 4);
959 template<
class t_buffer_type>
960 bool recalculateBounds(
uint04 node_index,
const t_buffer_type& elements)
962 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
963 RNode<t_dims, t_type>& node = m_nodes[node_index];
967 for (
uint04 i = node.begin(); i < end; i++)
969 bounds.addToBounds(elements[m_indices[i]]);
974 bounds = Bounds<t_dims, t_type>(m_nodes[node.left()].bounds(), m_nodes[node.right()].bounds());
976 if (classify(node.bounds(), bounds) == IntersectionTypes::e_inside)
978 node.setBounds(bounds);
982 template<
bool t_has_nans,
bool t_uses_boundary,
class t_buffer_type>
983 void _addValues(
uint04 top_node, Buffer<uint04> indices,
const t_buffer_type& elements,
bool is_precise)
985 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(top_node, indices);
986 TreeBase<RNode<t_dims, t_type>, t_type, 2>::clear();
987 TreeBase<RNode<t_dims, t_type>, t_type, 2>::reclaimChildren(top_node);
990 uint04 max_index_size = m_bucket_size;
991 uint04 load_size = indices.size();
993 while (load_size >= m_bucket_size)
996 max_index_size = 2 * max_index_size;
997 max_node_size =
cast<uint04>(pow(2, level++)) + max_node_size;
999 m_indices.ensureCapacity(max_index_size);
1000 m_nodes.ensureCapacity(max_node_size);
1002 _balanceLeafNode<t_has_nans, t_uses_boundary>(top_node, elements, indices, 0, indices.size(), is_precise);
1006 template<
bool t_has_nans,
bool t_uses_boundary,
class t_buffer_type>
1007 void _addValue(
uint04 node_index,
uint04 index,
const t_buffer_type& elements,
bool balance)
1009 Bounds<t_dims, t_type> bounds = m_nodes[node_index].bounds();
1010 const auto value = elements[index].template as<t_dims, t_type>();
1011 bounds.addToBounds(value);
1014 RNode<t_dims, t_type>& node = m_nodes[node_index];
1015 node.setBounds(bounds);
1018 if (node.size() == m_bucket_size)
1020 Buffer<uint04> indices(m_bucket_size + 1);
1021 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(node_index, indices);
1022 TreeBase<RNode<t_dims, t_type>, t_type, 2>::reclaimChildren(node_index);
1024 _balanceLeafNode<t_has_nans, t_uses_boundary>(node_index, elements, indices, 0, m_bucket_size + 1,
false);
1028 m_indices[node.begin() + node.size()] = index;
1029 node.setSize(node.size() + 1);
1035 Bounds<t_dims, t_type> left = m_nodes[node.left()].bounds();
1036 Bounds<t_dims, t_type> right = m_nodes[node.right()].bounds();
1038 left.addToBounds(value);
1039 right.addToBounds(value);
1040 bool needs_rebalance =
false;
1041 t_type surface_diff =
1042 (left.surfaceArea() - m_nodes[node.left()].bounds().surfaceArea())
1043 - (right.surfaceArea() - m_nodes[node.right()].bounds().surfaceArea());
1044 if(surface_diff == 0)
1046 if (m_nodes[node.left()].size() < m_nodes[node.right()].size())
1048 node_index = node.left();
1053 node_index = node.right();
1057 else if (surface_diff < 0)
1059 if (balance && needsRebalance(
1060 m_nodes[node.left()].size() + 1
1061 , m_nodes[node.right()].size()))
1062 needs_rebalance =
true;
1064 node_index = node.left();
1069 if (balance && needsRebalance(
1070 m_nodes[node.left()].size()
1071 , m_nodes[node.right()].size() + 1))
1072 needs_rebalance =
true;
1074 node_index = node.right();
1077 if (needs_rebalance)
1079 Buffer<uint04> indices(node.size() + 1);
1080 TreeBase<RNode<t_dims, t_type>, t_type, 2>::template _getAll<false>(node_index, indices);
1082 TreeBase<RNode<t_dims, t_type>, t_type, 2>::reclaimChildren(node_index);
1083 _balanceLeafNode<t_has_nans, t_uses_boundary>(node_index, elements, indices, 0, indices.size(),
false);
1088 node.setSize(node.size() + 1);
1096 void _makeWriteable()
1098 Buffer<uint04> indices(TreeBase<RNode<t_dims, t_type>, t_type, 2>::size());
1100 TreeIterator iterator(root_node);
1101 while (iterator.valid())
1103 RNode<t_dims, t_type>& node = m_nodes[iterator.get()];
1107 node.setBegin(iterator.get());
1108 indices.addAll(m_indices.begin(node.begin()), node.size());
1111 iterator.addAndGoToIndex(node.left(), node.right());
1113 m_indices = indices;
1118 template<u
int01 t_dims,
class t_type>
1119 class RTree :
public Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>
1122 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_nodes;
1123 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::root_node;
1124 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_indices;
1125 using TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_bucket_size;
1126 RTree<t_dims, t_type>()
1127 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(16)
1129 explicit RTree<t_dims, t_type>(
uint04 bucket_size)
1130 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(bucket_size)
1132 RTree<t_dims, t_type>(
const RTreeBase<t_dims, t_type>& tree)
1133 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(tree)
1135 RTree<t_dims, t_type>(RTreeBase<t_dims, t_type>&& tree)
1136 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(std::move(tree))
1138 RTree<t_dims, t_type>(
const RTree<t_dims, t_type>& value)
1139 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(16)
1141 m_bucket_size = value.m_bucket_size;
1142 m_indices = value.m_indices;
1143 m_nodes = value.m_nodes;
1144 TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions = value.m_available_node_positions;
1145 TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions = value.m_available_indexed_positions;
1147 RTree<t_dims, t_type>(RTree<t_dims, t_type>&& value) noexcept
1148 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(64)
1150 m_bucket_size = value.m_bucket_size;
1151 std::swap(m_indices, value.m_indices);
1152 std::swap(m_nodes, value.m_nodes);
1153 std::swap(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions, value.m_available_node_positions);
1154 std::swap(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions, value.m_available_indexed_positions);
1156 Bounds<t_dims, t_type> bounds()
const
1158 const RNode<t_dims, t_type>& node = m_nodes[root_node];
1159 return node.bounds();
1162 RTree<t_dims, t_type>(
const Buffer<RNode<t_dims, t_type>>& nodes,
const Buffer<uint04>& indices,
bool is_read_only)
1163 : Tree<t_dims, t_type, RTreeBase<t_dims, t_type>>(nodes, indices, is_read_only)
1166 inline RTree& operator=(
const RTree& value)
1168 m_bucket_size = value.m_bucket_size;
1169 m_indices = value.m_indices;
1170 m_nodes = value.m_nodes;
1171 TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions = value.m_available_node_positions;
1172 TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions = value.m_available_indexed_positions;
1175 inline RTree& operator=(RTree&& value)
1177 m_bucket_size = value.m_bucket_size;
1178 std::swap(m_indices, value.m_indices);
1179 std::swap(m_nodes, value.m_nodes);
1180 std::swap(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions, value.m_available_node_positions);
1181 std::swap(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions, value.m_available_indexed_positions);
1184 void mapToFile(BinaryFileTableInfo&
file, Buffer<BinaryCompressionObject>& objects,
uint04 compression_index = 0)
1186 file.file.write(m_bucket_size);
1187 file.file.writeCompression(objects[compression_index + 0]);
1188 file.file.writeCompression(objects[compression_index + 1]);
1189 file.file.writeCompression(objects[compression_index + 2]);
1190 file.file.writeCompression(objects[compression_index + 3]);
1192 void compress(Buffer<BinaryCompressionObject>& objects, Buffer<Buffer<uint01>>&
compressed_data,
uint04 compression_index,
uint04 internal_index)
1194 switch (internal_index)
1209 , TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions);
1214 , TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions);
1221 table_info.file.write(m_bucket_size);
1222 table_info.file.write(m_indices, mode);
1223 table_info.file.write(m_nodes, mode);
1224 table_info.file.write(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions, mode);
1225 table_info.file.write(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions, mode);
1227 void mapFromFile(BinaryFileTableInfo& table_info)
1229 m_bucket_size = table_info.file.read<
uint04>();
1230 if (table_info.version_number < 1762047417)
1231 table_info.file.skip<
bool>();
1232 table_info.file.read(m_indices);
1233 table_info.file.read(m_nodes);
1234 table_info.file.read(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_node_positions);
1235 table_info.file.read(TreeBase<RNode<t_dims, t_type>, t_type, 2>::m_available_indexed_positions);
1237 virtual const char* getTreeType()
const override
static std::enable_if<!ObjectInfo< t_type >::Buffer >::type Compress(BinaryCompressionObject &object, Buffer< uint01 > &compression_data, const Buffer< t_type, t_memory_manager > &data)
Compresses a buffer of non-buffer (flat) elements into the given compression object.
The primary namespace for the NDEVR SDK.
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
constexpr HSLColor Constant< HSLColor >::Invalid
The invalid HSLColor constant with all components set to invalid.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
CompressionMode
Forward declaration of the Module struct for module metadata.
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
@ file
The source file path associated with this object.
@ compressed_data
Compressed binary data storage.
t_type sqrt(const t_type &value)
constexpr HSLColor Constant< HSLColor >::Min
The minimum HSLColor constant with saturation, brightness, and alpha at zero.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.