11 #ifndef CUBBYFLOW_KDTREE_IMPL_HPP 12 #define CUBBYFLOW_KDTREE_IMPL_HPP 18 template <
typename T,
size_t K>
23 child = std::numeric_limits<size_t>::max();
27 template <
typename T,
size_t K>
37 template <
typename T,
size_t K>
43 template <
typename T,
size_t K>
46 m_points.resize(points.
Length());
47 std::copy(points.
begin(), points.
end(), m_points.begin());
56 std::vector<size_t> itemIndices(m_points.size());
57 std::iota(std::begin(itemIndices), std::end(itemIndices), 0);
59 [[maybe_unused]]
const size_t d =
60 Build(0, itemIndices.data(), m_points.size(), 0);
63 template <
typename T,
size_t K>
65 const Point& origin, T radius,
66 const std::function<
void(
size_t,
const Point&)>& callback)
const 68 const T r2 = radius * radius;
71 static const int maxTreeDepth = 8 *
sizeof(size_t);
72 const Node* todo[maxTreeDepth];
76 const Node* node = m_nodes.data();
78 while (node !=
nullptr)
80 if (node->item != std::numeric_limits<size_t>::max() &&
81 (node->point - origin).LengthSquared() <= r2)
83 callback(node->item, node->point);
103 const Node* firstChild = node + 1;
104 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
107 const size_t axis = node->flags;
108 const T plane = node->point[axis];
110 if (plane - origin[axis] > radius)
114 else if (origin[axis] - plane > radius)
121 todo[todoPos] = secondChild;
129 template <
typename T,
size_t K>
132 const T r2 = radius * radius;
135 static const int maxTreeDepth = 8 *
sizeof(size_t);
136 const Node* todo[maxTreeDepth];
140 const Node* node = m_nodes.data();
142 while (node !=
nullptr)
144 if (node->item != std::numeric_limits<size_t>::max() &&
145 (node->point - origin).LengthSquared() <= r2)
157 node = todo[todoPos];
167 const Node* firstChild = node + 1;
168 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
171 const size_t axis = node->flags;
172 const T plane = node->point[axis];
174 if (origin[axis] < plane && plane - origin[axis] > radius)
178 else if (origin[axis] > plane && origin[axis] - plane > radius)
185 todo[todoPos] = secondChild;
195 template <
typename T,
size_t K>
199 static const int maxTreeDepth = 8 *
sizeof(size_t);
200 const Node* todo[maxTreeDepth];
204 const Node* node = m_nodes.data();
206 T minDist2 = (node->point - origin).LengthSquared();
208 while (node !=
nullptr)
210 const T newDist2 = (node->point - origin).LengthSquared();
211 if (newDist2 <= minDist2)
213 nearest = node->item;
224 node = todo[todoPos];
234 const Node* firstChild = node + 1;
235 const Node* secondChild =
static_cast<Node*
>(&m_nodes[node->child]);
238 const size_t axis = node->flags;
239 const T plane = node->point[axis];
240 const T minDist = std::sqrt(minDist2);
242 if (plane - origin[axis] > minDist)
246 else if (origin[axis] - plane > minDist)
253 todo[todoPos] = secondChild;
263 template <
typename T,
size_t K>
266 m_points.resize(numPoints);
267 m_nodes.resize(numNodes);
270 template <
typename T,
size_t K>
273 return m_points.begin();
276 template <
typename T,
size_t K>
279 return m_points.end();
282 template <
typename T,
size_t K>
285 return m_points.begin();
288 template <
typename T,
size_t K>
291 return m_points.end();
294 template <
typename T,
size_t K>
297 return m_nodes.begin();
300 template <
typename T,
size_t K>
303 return m_nodes.end();
306 template <
typename T,
size_t K>
309 return m_nodes.begin();
312 template <
typename T,
size_t K>
315 return m_nodes.end();
318 template <
typename T,
size_t K>
323 m_nodes.emplace_back();
328 m_nodes[nodeIndex].InitLeaf(std::numeric_limits<size_t>::max(), {});
329 return currentDepth + 1;
333 m_nodes[nodeIndex].InitLeaf(itemIndices[0], m_points[itemIndices[0]]);
334 return currentDepth + 1;
339 for (
size_t i = 0; i < nItems; ++i)
341 nodeBound.
Merge(m_points[itemIndices[i]]);
344 const size_t axis =
static_cast<size_t>(d.
DominantAxis());
347 std::nth_element(itemIndices, itemIndices + nItems / 2,
348 itemIndices + nItems, [&](
size_t a,
size_t b) {
349 return m_points[a][axis] < m_points[b][axis];
351 const size_t midPoint = nItems / 2;
355 Build(nodeIndex + 1, itemIndices, midPoint, currentDepth + 1);
356 m_nodes[nodeIndex].InitInternal(axis, itemIndices[midPoint], m_nodes.size(),
357 m_points[itemIndices[midPoint]]);
359 Build(m_nodes[nodeIndex].
child, itemIndices + midPoint + 1,
360 nItems - midPoint - 1, currentDepth + 1);
362 return std::max(d0, d1);
VectorType upperCorner
Upper corner of the bounding box.
Definition: BoundingBox.hpp:148
void Reserve(size_t numPoints, size_t numNodes)
Reserves memory space for this tree.
Definition: KdTree-Impl.hpp:264
NodeIterator EndNode()
Returns the mutable end iterator of the node.
Definition: KdTree-Impl.hpp:301
typename ContainerType::const_iterator ConstIterator
Definition: KdTree.hpp:56
typename NodeContainerType::iterator NodeIterator
Definition: KdTree.hpp:59
N-D axis-aligned bounding box class.
Definition: BoundingBox.hpp:46
Iterator begin()
Returns the mutable begin iterator of the item.
Definition: KdTree-Impl.hpp:271
bool IsLeaf() const
Returns true if leaf.
Definition: KdTree-Impl.hpp:38
Iterator end()
Definition: ArrayBase-Impl.hpp:102
bool HasNearbyPoint(const Point &origin, T radius) const
Definition: KdTree-Impl.hpp:130
Point point
Point stored in the node.
Definition: KdTree.hpp:51
NodeIterator BeginNode()
Returns the mutable begin iterator of the node.
Definition: KdTree-Impl.hpp:295
Definition: Matrix.hpp:27
void InitInternal(size_t axis, size_t it, size_t c, const Point &pt)
Initializes internal node.
Definition: KdTree-Impl.hpp:28
size_t GetNearestPoint(const Point &origin) const
Returns index of the nearest point.
Definition: KdTree-Impl.hpp:196
Definition: pybind11Utils.hpp:20
size_t DominantAxis() const
Definition: MatrixExpression-Impl.hpp:206
Iterator begin()
Definition: ArrayBase-Impl.hpp:90
typename NodeContainerType::const_iterator ConstNodeIterator
Definition: KdTree.hpp:60
VectorType lowerCorner
Lower corner of the bounding box.
Definition: BoundingBox.hpp:145
size_t Length() const
Definition: ArrayBase-Impl.hpp:84
void Build(const ConstArrayView1< Point > &points)
Builds internal acceleration structure for given points list.
Definition: KdTree-Impl.hpp:44
size_t flags
Split axis if flags < K, leaf indicator if flags == K.
Definition: KdTree.hpp:41
void Merge(const VectorType &point)
Merges this and other point.
Definition: BoundingBox-Impl.hpp:219
Generic N-dimensional array class interface.
Definition: Array.hpp:32
size_t child
Right child index. Note that left child index is this node index + 1.
Definition: KdTree.hpp:45
Iterator end()
Returns the mutable end iterator of the item.
Definition: KdTree-Impl.hpp:277
typename ContainerType::iterator Iterator
Definition: KdTree.hpp:55
size_t item
Item index.
Definition: KdTree.hpp:48
void ForEachNearbyPoint(const Point &origin, T radius, const std::function< void(size_t, const Point &)> &callback) const
Definition: KdTree-Impl.hpp:64
void InitLeaf(size_t it, const Point &pt)
Initializes leaf node.
Definition: KdTree-Impl.hpp:19