8 #ifndef META_OCEAN_BASE_KD_TREE_H
9 #define META_OCEAN_BASE_KD_TREE_H
72 inline const T*
value();
90 explicit inline operator bool()
const;
98 std::unique_ptr<Node>
left_ =
nullptr;
134 bool insert(
const T** values,
const size_t number);
165 inline size_t size()
const;
176 void insertLeft(
Node& parent,
const T** values,
const size_t number,
const unsigned int depth);
185 void insertRight(
Node& parent,
const T** values,
const size_t number,
const unsigned int depth);
216 static T
median(
const T** values,
const size_t number,
const unsigned int index);
227 static void distribute(
const T** values,
const size_t number,
const unsigned int index,
const T*& medianValue,
Pointers& leftValues,
Pointers& rightValues);
249 template <
typename T>
256 template <
typename T>
262 template <
typename T>
268 template <
typename T>
274 template <
typename T>
277 ocean_assert(!left_);
278 left_ = std::move(left);
281 template <
typename T>
284 ocean_assert(!right_);
285 right_ = std::move(right);
288 template <
typename T>
291 return value_ !=
nullptr;
294 template <
typename T>
301 template <
typename T>
314 ocean_assert(values);
316 const T* median =
nullptr;
319 distribute(values, number, 0u, median, left, right);
321 root_ = std::make_unique<Node>(median);
325 insertLeft(*root_, left.data(), left.size(), 1u);
330 insertRight(*root_, right.data(), right.size(), 1u);
338 template <
typename T>
343 distance = std::numeric_limits<T>::max();
350 const T* nearest =
nullptr;
352 nearestNeighbor(*root_, value, nearest, distance, 0u);
356 template <
typename T>
360 ocean_assert(values);
362 if (!root_ || maxValues == 0)
367 size_t found = radiusSearch(*root_, value, radius, values, maxValues, 0u);
369 ocean_assert(found <= maxValues);
374 template <
typename T>
380 template <
typename T>
386 template <
typename T>
390 ocean_assert(parent);
391 ocean_assert(values && number > 0);
393 for (
size_t n = 0; n < number; ++n)
395 ocean_assert(values[n][(depth - 1) % dimension_] <= parent.
value()[(depth - 1) % dimension_]);
399 ocean_assert(!parent.
left());
401 const unsigned int index = depth % dimension_;
403 const T* median =
nullptr;
406 distribute(values, number, index, median, left, right);
408 parent.
setLeft(std::make_unique<Node>(median));
412 insertLeft(*parent.
left(), left.data(), left.size(), depth + 1);
417 insertRight(*parent.
left(), right.data(), right.size(), depth + 1);
421 template <
typename T>
425 ocean_assert(parent);
426 ocean_assert(values && number > 0);
428 for (
size_t n = 0; n < number; ++n)
430 ocean_assert(parent.
value()[(depth - 1) % dimension_] < values[n][(depth - 1) % dimension_]);
434 ocean_assert(!parent.
right());
436 const unsigned int index = depth % dimension_;
438 const T* median =
nullptr;
441 distribute(values, number, index, median, left, right);
443 parent.
setRight(std::make_unique<Node>(median));
447 insertLeft(*parent.
right(), left.data(), left.size(), depth + 1);
452 insertRight(*parent.
right(), right.data(), right.size(), depth + 1);
456 template <
typename T>
459 ocean_assert(node && value);
460 ocean_assert(index < dimension_);
463 if (localDistance < distance)
465 distance = localDistance;
466 nearest = node.
value();
469 const unsigned int nextIndex = (index + 1u) % dimension_;
472 if (value[index] <= node.
value()[index])
476 nearestNeighbor(*node.
left(), value, nearest, distance, nextIndex);
480 if (node.
right() &&
sqr(value[index] - node.
value()[index]) < distance)
482 nearestNeighbor(*node.
right(), value, nearest, distance, nextIndex);
487 ocean_assert(value[index] > node.
value()[index]);
491 nearestNeighbor(*node.
right(), value, nearest, distance, nextIndex);
495 if (node.
left() &&
sqr(value[index] - node.
value()[index]) < distance)
497 nearestNeighbor(*node.
left(), value, nearest, distance, nextIndex);
502 template <
typename T>
505 ocean_assert(node && value && values);
506 ocean_assert(index < dimension_);
513 T
const ** current = values;
514 T
const **
const end = values + maxValues;
517 if (localDistance <= radius)
519 *current++ = node.
value();
527 const unsigned int nextIndex = (index + 1u) % dimension_;
530 if (value[index] <= node.
value()[index])
534 current += radiusSearch(*node.
left(), value, radius, current, end - current, nextIndex);
542 if (node.
right() &&
sqr(value[index] - node.
value()[index]) <= radius)
544 current += radiusSearch(*node.
right(), value, radius, current, end - current, nextIndex);
549 ocean_assert(value[index] > node.
value()[index]);
553 current += radiusSearch(*node.
right(), value, radius, current, end - current, nextIndex);
561 if (node.
left() &&
sqr(value[index] - node.
value()[index]) <= radius)
563 current += radiusSearch(*node.
left(), value, radius, current, end - current, nextIndex);
567 ocean_assert(current <= end);
569 return current - values;
572 template <
typename T>
575 ocean_assert(values && number > 0);
578 for (
size_t n = 0; n < number; ++n)
580 elements[n] = values[n][index];
583 return Median::median<T>((T*)elements.data(), elements.size());
586 template <
typename T>
589 ocean_assert(values && number > 0);
591 const T middle = median(values, number, index);
593 leftValues.reserve(number / 2);
594 rightValues.reserve(number / 2);
596 ocean_assert(leftValues.empty() && rightValues.empty());
598 bool medianFound =
false;
600 for (
size_t n = 0; n < number; ++n)
602 if (values[n][index] < middle || (values[n][index] == middle && medianFound))
604 leftValues.push_back(values[n]);
606 else if (middle < values[n][index])
608 rightValues.push_back(values[n]);
612 ocean_assert(values[n][index] == middle);
613 ocean_assert(!medianFound);
615 medianValue = values[n];
620 ocean_assert(medianFound);
623 template <
typename T>
626 ocean_assert(first && second);
630 for (
size_t n = 0; n < dimension_; ++n)
632 ssd +=
sqr(first[n] - second[n]);
This class defines a node of the k-d tree.
Definition: KdTree.h:37
const T * value_
Node value.
Definition: KdTree.h:95
Node * left()
Returns the left child of this node.
Definition: KdTree.h:257
std::unique_ptr< Node > left_
Left node.
Definition: KdTree.h:98
Node * right()
Returns the right child of this node.
Definition: KdTree.h:263
~Node()=default
Destructs a node.
void setRight(std::unique_ptr< Node > &&right)
Sets the right child of this node.
Definition: KdTree.h:282
void setLeft(std::unique_ptr< Node > &&left)
Sets the left child of this node.
Definition: KdTree.h:275
Node()=default
Creates an empty node.
std::unique_ptr< Node > right_
Right node.
Definition: KdTree.h:101
const T * value()
Returns value of this node.
Definition: KdTree.h:269
This class implements a k-d tree.
Definition: KdTree.h:30
std::vector< const T * > Pointers
Definition of a vector holding single pointers.
Definition: KdTree.h:112
const T * nearestNeighbor(const T *value, typename SquareValueTyper< T >::Type &distance) const
Applies a nearest neighbor search for a given value.
Definition: KdTree.h:339
const unsigned int dimension_
Number of dimensions.
Definition: KdTree.h:246
std::vector< T > Elements
Definition of a vector holding single elements.
Definition: KdTree.h:107
std::unique_ptr< Node > root_
Root node of this tree.
Definition: KdTree.h:240
static T median(const T **values, const size_t number, const unsigned int index)
Returns the median for a given set of values.
Definition: KdTree.h:573
~KdTree()=default
Destructs a k-d tree.
static void distribute(const T **values, const size_t number, const unsigned int index, const T *&medianValue, Pointers &leftValues, Pointers &rightValues)
Distributes a given set of values into two subset according to the median.
Definition: KdTree.h:587
KdTree(const unsigned int dimension)
Creates a new k-d tree.
Definition: KdTree.h:295
size_t size() const
Returns the number of tree nodes.
Definition: KdTree.h:381
void insertLeft(Node &parent, const T **values, const size_t number, const unsigned int depth)
Inserts a set of values to a given parent as left children.
Definition: KdTree.h:387
bool insert(const T **values, const size_t number)
Inserts a set of values to this empty tree.
Definition: KdTree.h:302
size_t radiusSearch(const T *value, const typename SquareValueTyper< T >::Type radius, const T **values, const size_t maxValues) const
Applies a radius search for neighbors of a given value.
Definition: KdTree.h:357
size_t size_
Number of nodes.
Definition: KdTree.h:243
SquareValueTyper< T >::Type determineSquareDistance(const T *first, const T *second) const
Determines the square distance between two values.
Definition: KdTree.h:624
unsigned int dimension() const
Returns the dimension of the tree's values.
Definition: KdTree.h:375
void insertRight(Node &parent, const T **values, const size_t number, const unsigned int depth)
Inserts a set of values to a given parent as right children.
Definition: KdTree.h:422
T Type
Definition of the data type for the square value.
Definition: DataType.h:132
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition: base/Utilities.h:1029
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15