34#include <NDEVR/TreeIterator.h>
35#include <NDEVR/Node.h>
36#include <NDEVR/Tree.h>
37#include <NDEVR/BaseValues.h>
38#include <NDEVR/Buffer.h>
39#include <NDEVR/Bounds.h>
40#include <NDEVR/Median.h>
41#include <NDEVR/InfoPipe.h>
42#include <NDEVR/Vector.h>
43#include <NDEVR/VectorFunctions.h>
44#include <NDEVR/Intersection.h>
45#include <NDEVR/BinaryHeap.h>
50 template<u
int01 t_dims,
class t_type>
51 class KDNode :
public TreeNode
54 KDNode(
const KDNode& node)
59 explicit KDNode(
uint04 index_start)
60 : TreeNode(index_start)
65 void clear(
uint04 index_start,
const Bounds<t_dims, t_type>& bounds)
67 setBegin(index_start);
74 return uint04(m_child_start);
78 return uint04(m_child_start) + 1;
81 const t_type& split()
const
85 const uint01& splitDim()
const
89 void setSplit(
uint01 split_dim, t_type split)
92 m_split_dim = split_dim;
101 template<u
int01 t_dims,
class t_type>
102 class KDTreeBase :
public TreeBase<KDNode<t_dims, t_type>, t_type, 2>
105 explicit KDTreeBase<t_dims, t_type>(
uint04 bucket_size)
106 : TreeBase(bucket_size)
108 KDTreeBase<t_dims, t_type>(
const KDTreeBase<t_dims, t_type>& tree)
111 KDTreeBase<t_dims, t_type>(KDTreeBase<t_dims, t_type>&& tree)
112 : TreeBase(std::move(tree))
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)
119 template<
class t_node_type>
120 bool validate(
const Buffer<t_node_type>& elements)
122 TreeIterator iterator(root_node);
125 values.setSize(elements.size());
127 while (iterator.valid())
130 uint04 node_index = iterator.get();
131 KDNode<t_dims, t_type>& node = m_nodes[node_index];
134 values.setAllToValue(
false);
135 _getAllT(node_index, values);
136 if (node.size() != values.numSet())
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)
146 Vector<t_dims, uint04> location;
147 Vector<t_dims, t_type> d_size;
148 for (
uint01 dim = 0; dim < t_dims; ++dim)
151 location[dim] = median(elements, indices, start, end, dim);
153 location[dim] =
ApxMedian(elements, indices, start, end, dim);
154 Bounds<t_dims, t_type> bounds(elements[indices[location[dim]]]);
156 abs(bounds.center()[dim] - node_bounds[MIN][dim])
157 ,
abs(node_bounds[MAX][dim] - bounds.center()[dim]));
159 const uint01 split_dim = d_size.getDimension<MAX>();
161 location[split_dim] = median(elements, indices, start, end, split_dim);
165 splitLeafNode(node_index);
166 m_nodes[node_index].setSplit(split_dim, elements[indices[new_left]][split_dim]);
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)
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);
185 while (iterator.valid())
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];
194 m_nodes[node_index].setSize(end - start);
196 if ((end - start) > m_bucket_size)
198 const uint04 new_left = _calculateAndSplit(node_index, bounds, elements, indices, start, end, is_precise);
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();
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();
214 m_indices.setAll(indices.begin(start), m_nodes[node_index].begin(), (end - start));
215 size += (end - start);
217 if (progress.isValid() && node_index % update_size == 0)
218 progress.setProgress(
cast<fltp04>(size) / elements.size());
221 if (progress.isValid())
222 progress.setProgress(1.0f);
227 template<
class t_node_type,
class t_buffer_type>
228 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
230 TreeIterator iterator(top_index);
231 t_type split_values[256];
232 while (iterator.valid())
234 const uint04 index = iterator.get();
235 if (split_values[iterator.depth()] >= min_distance)
242 const KDNode<t_dims, t_type>& node = m_nodes[index];
246 const uint04 end = node.end();
247 for (
uint04 i = node.begin(); i < end; i++)
249 const uint04 check_index = m_indices[i];
250 t_type distance = distanceSquared(point, elements[check_index]);
251 if (distance < min_distance)
253 min_distance = distance;
254 min_index = check_index;
255 if (distance <= epsilon)
262 const t_type distance = point[node.splitDim()] - node.split();
265 iterator.addAndGoToIndex(node.left());
266 split_values[iterator.depth()] = distance * distance;
268 iterator.addAndGoToIndex(node.right());
269 split_values[iterator.depth()] = 0;
273 iterator.addAndGoToIndex(node.right());
274 split_values[iterator.depth()] = distance * distance;
276 iterator.addAndGoToIndex(node.left());
277 split_values[iterator.depth()] = 0;
284 template<
class t_node_type,
class t_buffer_type>
285 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
287 TreeIterator iterator(top_index);
288 t_type split_values[255];
289 while (iterator.valid())
291 const uint04 index = iterator.get();
292 if (split_values[iterator.depth()] >= min_distance)
299 const KDNode<m_bucket_size, t_dims, t_type>& node = m_nodes[index];
302 const uint04 end = node.end();
303 for (
uint04 i = node.begin(); i < end; i++)
305 uint04 check_index = m_indices[i];
306 t_type distance = distanceSquared(point, elements[check_index]);
307 if (distance < min_distance)
309 heap.insert(distance, check_index);
310 if (heap.size() == size + 1)
313 min_distance = heap.max();
317 if (min_distance <= epsilon)
322 const t_type distance = point[node.splitDim()] - node.split();
325 iterator.addAndGoToIndex(node.left());
326 split_values[iterator.depth()] = distance * distance;
329 iterator.addAndGoToIndex(node.right());
330 split_values[iterator.depth()] = 0;
334 iterator.addAndGoToIndex(node.right());
335 split_values[iterator.depth()] = distance * distance;
338 iterator.addAndGoToIndex(node.left());
339 split_values[iterator.depth()] = 0;
345 template<
class t_node_type,
class t_buffer_type>
346 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
348 TreeIterator iterator(top_index);
349 t_type split_values[256];
351 Vector<3, uint01> dim_min;
352 Vector<3, uint01> dim_max;
353 for (
uint01 i = 0; i < t_dims; i++)
355 dim_min[i] = top_line[0][i] < top_line[1][i] ? MIN : MAX;
356 dim_max[i] = dim_min[i] != MIN ? MIN : MAX;
360 t_type sqrt_min_dist =
sqrt(min_index);
361 CachedLineSegment<t_dims, t_type> cached_line(top_line);
363 while (iterator.valid())
365 const uint04 index = iterator.get();
366 if (
abs(split_values[iterator.depth()]) >= min_distance)
374 const KDNode<t_dims, t_type>& node = m_nodes[index];
378 const uint04 end = node.end();
379 for (
uint04 i = node.begin(); i < end; i++)
381 uint04 check_index = m_indices[i];
382 t_type distance = distanceSquared(cached_line, elements[check_index]);
383 if (distance < min_distance)
385 min_distance = distance;
386 min_index = check_index;
387 sqrt_min_dist =
sqrt(min_index);
390 if (distance <= epsilon)
395 const uint01 split_dim = m_nodes[index].splitDim();
396 const uint01 min = dim_min[split_dim];
397 const uint01 max = dim_max[split_dim];
398 if (cached_line[max][split_dim] >= m_nodes[index].split())
400 if (cached_line[min][split_dim] <= m_nodes[index].split())
402 iterator.addAndGoToIndex(node.right());
403 split_values[iterator.depth()] = 0;
405 iterator.addAndGoToIndex(node.left());
406 split_values[iterator.depth()] = 0;
410 iterator.addAndGoToIndex(node.left());
411 split_values[iterator.depth()] = cached_line[min][split_dim] - m_nodes[index].split();
412 split_values[iterator.depth()] *= split_values[iterator.depth()];
414 iterator.addAndGoToIndex(node.right());
415 split_values[iterator.depth()] = 0;
418 else if (cached_line[min][split_dim] <= m_nodes[index].split())
420 iterator.addAndGoToIndex(node.right());
421 split_values[iterator.depth()] = m_nodes[index].split() - cached_line[max][split_dim];
422 split_values[iterator.depth()] *= -split_values[iterator.depth()];
424 iterator.addAndGoToIndex(node.left());
425 split_values[iterator.depth()] = 0;
432 template<
class t_node_type,
class t_buffer_type>
433 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
435 TreeIterator iterator(top_index);
437 CachedTriangle<t_dims, t_type> cached_tri(triangle);
439 while (iterator.valid())
441 const uint04 index = iterator.get();
443 const KDNode<m_bucket_size, t_dims, t_type>& node = m_nodes[index];
444 if (!node.bounds().expand(
sqrt(min_distance)).doBoundsIntersect<t_dims>(cached_tri))
448 const uint04 end = node.end();
449 for (
uint04 i = node.begin(); i < end; i++)
451 const uint04 check_index = m_indices[i];
452 const t_type distance = distanceSquared(cached_tri, elements[check_index]);
453 if (distance < min_distance)
455 min_distance = distance;
456 min_index = check_index;
459 if (distance <= epsilon)
464 if (m_nodes[node.left()].bounds().contains(cached_tri.centroid()))
465 iterator.addAndGoToIndex(node.right(), node.left());
467 iterator.addAndGoToIndex(node.left(), node.right());
473 template<
class t_node_type,
class t_area_type,
class t_buffer_type>
474 void _getEnclosedElements(
uint04 top_node, t_area_type area, Buffer<bool>& indices,
const t_buffer_type& elements)
const
476 Bounds<t_dims, t_type> bounds[256];
477 bounds[0] = Constant<Bounds<t_dims, t_type>>
::Max;
478 TreeIterator iterator(top_node);
479 while (iterator.valid())
481 uint04 index = iterator.get();
482 const KDNode<t_dims, t_type>& node = m_nodes[index];
483 const Bounds<t_dims, t_type> box = bounds[iterator.depth()];
485 switch (classify(area, box))
487 case IntersectionTypes::e_inside:
488 _getAll<false>(index, indices);
490 case IntersectionTypes::e_outside:
492 case IntersectionTypes::e_mixed:
495 const uint04 end = node.begin() + node.size();
496 for (
uint04 i = node.begin(); i < end; i++)
498 if (classify(area, elements[m_indices[i]]) != IntersectionTypes::e_outside)
500 indices.set(m_indices[i],
true);
506 Bounds<t_dims, t_type> left = box;
507 left[MAX][node.splitDim()] = node.split();
508 Bounds<t_dims, t_type> right = box;
510 Bounds<t_dims, t_type> left = box;
511 right[MIN][node.splitDim()] = node.split();
513 iterator.addAndGoToIndex(node.left());
514 bounds[iterator.depth()] = left;
516 iterator.addAndGoToIndex(node.right());
517 bounds[iterator.depth()] = right;
524 template<
class t_area_type,
class t_node_type,
class t_buffer_type>
525 uint04 _getNumberOfEnclosedElements(
uint04 top_node,
const t_area_type& area,
const t_buffer_type& elements)
const
527 TreeIterator iterator(top_node);
529 while (iterator.valid())
531 uint04 index = iterator.get();
532 const KDNode<t_dims, t_type>& node = m_nodes[index];
534 switch (classify(area, node.bounds()))
536 case IntersectionTypes::e_inside:
539 case IntersectionTypes::e_outside:
541 case IntersectionTypes::e_mixed:
544 const uint04 end = node.begin() + node.size();
545 for (
uint04 i = node.begin(); i < end; i++)
547 if (classify(area, elements[m_indices[i]]) != IntersectionTypes::e_outside)
555 iterator.addAndGoToIndex(node.left(), node.right());
564 template<
class t_node_type,
class t_buffer_type>
565 void _removeValue(
uint04 top_node,
uint04 index,
const t_buffer_type& elements)
567 bool recalculate_bounds =
false;
568 TreeIterator iterator(top_node);
569 while (iterator.valid())
571 const uint04 node_index = iterator.get();
572 KDNode<t_dims, t_type>& node = m_nodes[node_index];
576 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
577 uint04 index_location = Constant<uint04>::Invalid;
578 for (
uint04 i = node.begin(); i < end; i++)
580 uint04 check_index = m_indices[i];
581 if (index != check_index)
582 bounds.addToBounds(elements[check_index]);
586 node.setSize(node.size() - 1);
587 if (node.size() != 0)
588 m_indices.swapIndices(index_location, node.end());
589 if (classify(node.bounds(), bounds) == IntersectionTypes::e_inside)
590 recalculate_bounds =
true;
591 node.setBounds(bounds);
598 bool needs_rebalance =
false;
599 if (classify(m_nodes[node.left()].bounds(), elements[index]) == IntersectionTypes::e_inside)
601 if (needsRebalance(m_nodes[node.left()].size() - 1, m_nodes[node.right()].size()))
602 needs_rebalance =
true;
604 iterator.addAndGoToIndex(node.left());
608 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() - 1))
609 needs_rebalance =
true;
611 iterator.addAndGoToIndex(node.right());
613 if (needs_rebalance || node.size() - 1 == m_bucket_size)
615 Buffer<uint04> indices(node.size());
616 _getAll(node_index, indices);
617 node.setSize(node.size() - 1);
618 indices.removeElement(index);
619 reclaimChildren(node_index);
620 _balanceLeafNode(node_index, elements, indices, 0, indices.size(),
false);
621 recalculate_bounds =
true;
626 node.setSize(node.size() - 1);
630 if (recalculate_bounds)
632 while (iterator.valid())
634 if (!recalculateBounds(iterator.get(), elements))
642 template<
class t_node_type,
class t_buffer_type>
643 void _moveValue(
uint04 top_node,
uint04 index,
const t_node_type& new_location,
const t_buffer_type& elements)
645 TreeIterator iterator(top_node);
646 bool recalculate_bounds =
false;
647 while (iterator.valid())
649 const uint04 node_index = iterator.get();
650 KDNode<t_dims, t_type>& node = m_nodes[node_index];
653 if (classify(m_nodes[node.left()].bounds(), new_location) == IntersectionTypes::e_inside)
656 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
657 uint04 index_location = Constant<uint04>::Invalid;
658 for (
uint04 i = node.begin(); i < end; i++)
660 uint04 check_index = m_indices[i];
661 if (index != check_index)
662 bounds.addToBounds(elements[check_index]);
666 node.setSize(node.size() - 1);
667 if (node.size() != 0)
668 m_indices.swapIndices(index_location, node.end());
669 recalculate_bounds = (classify(node.bounds(), bounds) != IntersectionTypes::e_inside);
670 node.setBounds(bounds);
677 bool needs_rebalance =
false;
678 if (classify(m_nodes[node.left()].bounds(), elements[index]) == IntersectionTypes::e_inside)
680 if (needsRebalance(m_nodes[node.left()].size() - 1, m_nodes[node.right()].size()))
681 needs_rebalance =
true;
683 iterator.addAndGoToIndex(node.left());
687 if (needsRebalance(m_nodes[node.left()].size(), m_nodes[node.right()].size() - 1))
688 needs_rebalance =
true;
690 iterator.addAndGoToIndex(node.right());
692 if (needs_rebalance || node.size() - 1 == m_bucket_size)
694 Buffer<uint04> indices(node.size());
695 _getAll(node_index, indices);
696 node.setSize(node.size() - 1);
697 indices.removeElement(index);
698 reclaimChildren(node_index);
699 _balanceLeafNode(node_index, elements, indices, 0, indices.size());
700 recalculate_bounds =
true;
705 node.setSize(node.size() - 1);
709 if (recalculate_bounds)
711 while (iterator.valid())
713 if (!recalculateBounds(iterator.get(), elements))
720 bool needsRebalance(
uint04 left_size,
uint04 right_size)
722 const uint04 total_size = left_size + right_size;
723 return (left_size < total_size / 4 || right_size < total_size / 4);
726 bool useBulkResize(
uint04 change_size)
728 return (change_size > size() / 4);
730 template<
class t_node_type,
class t_buffer_type>
731 bool recalculateBounds(
uint04 node_index,
const t_buffer_type& elements)
733 Bounds<t_dims, t_type> bounds(Constant<Bounds<t_dims, t_type>>
::Min);
734 KDNode<t_dims, t_type>& node = m_nodes[node_index];
738 for (
uint04 i = node.begin(); i < end; i++)
740 bounds.addToBounds(elements[m_indices[i]]);
745 bounds = Bounds<t_dims, t_type>(m_nodes[node.left()].bounds(), m_nodes[node.right()].bounds());
747 if (classify(node.bounds(), bounds) == IntersectionTypes::e_inside)
749 node.setBounds(bounds);
753 template<
class t_node_type,
class t_buffer_type>
754 void _addValues(
uint04 top_node, Buffer<uint04> indices,
const t_buffer_type& elements,
bool is_precise, ProgressInfo& progress)
756 _getAll(top_node, indices);
757 reclaimChildren(top_node);
759 uint04 max_size = 3 * indices.size();
760 m_indices.ensureCapacity(max_size + (m_indices.size() - getNumberOfFreeIndices()));
761 m_nodes.ensureCapacity(2 * max_size / m_bucket_size + (m_nodes.size() - getNumberOfNodes()));
764 bool did_balance = _balanceLeafNode(top_node, elements, indices, 0, indices.size(), is_precise, progress);
768 template<
class t_node_type,
class t_buffer_type>
769 void _addValue(
uint04 node_index,
uint04 index,
const t_buffer_type& elements)
832 void _makeWriteable()
836 Buffer<uint04> indices(size());
838 TreeIterator iterator(root_node);
839 while (iterator.valid())
841 KDNode<m_bucket_size, t_dims, t_type>& node = m_nodes[iterator.get()];
845 node.setBegin(iterator.size());
846 indices.addAll(m_indices.begin(node.begin()), node.size());
849 iterator.addAndGoToIndex(node.left(), node.right());
856 template<u
int01 t_dims,
class t_type>
857 class KDTree :
public Tree<t_dims, t_type, KDTreeBase<t_dims, t_type>>
860 explicit KDTree<t_dims, t_type>(
uint04 bucket_size)
863 KDTree<t_dims, t_type>(
const KDTreeBase<t_dims, t_type>& tree)
866 KDTree<t_dims, t_type>(KDTreeBase<t_dims, t_type>&& tree)
867 : Tree(std::move(tree))
870 KDTree<t_dims, t_type>(
const Buffer<KDNode<t_dims, t_type>>& nodes,
const Buffer<uint04>& indices,
bool is_read_only)
871 : TreeBase(nodes, indices, is_read_only)
874 inline KDTree& operator=(
const KDTree& value)
876 m_indices = value.m_indices;
877 m_nodes = value.m_nodes;
878 m_available_node_positions = value.m_available_node_positions;
879 m_available_indexed_positions = value.m_available_indexed_positions;
882 inline KDTree& operator=(KDTree&& value)
884 std::swap(m_indices, value.m_indices);
885 std::swap(m_nodes, value.m_nodes);
886 std::swap(m_available_node_positions, value.m_available_node_positions);
887 std::swap(m_available_indexed_positions, value.m_available_indexed_positions);
891 virtual const char* getTreeType()
const override
The primary namespace for the NDEVR SDK.
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator The only requirement is that t_type have > ...
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
uint04 SortAboutValue(uint04 value_index, const Buffer< t_node_type > &points, Buffer< uint04 > &indices, uint04 start, uint04 end, uint01 dimension)
Sorts all incoming indices within the given range such that the resulting index matrix will have valu...
constexpr HSLColor Constant< HSLColor >::Max
The maximum HSLColor constant with all components at their maximum values.
uint04 ApxMedian(const t_buffer_type &elements, const Buffer< uint04 > &indices, uint04 start, uint04 end, uint01 dimension)
Returns the aproximate median, or value that is close to the median, significantly faster than it wou...
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
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.