Ponca  7d8ac87a7de01d881c9fde3c42e397b44bffb901
Point Cloud Analysis library
Loading...
Searching...
No Matches
kdTree.h
1/*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5*/
6
7#pragma once
8
9#include "./kdTreeTraits.h"
10
11#include <algorithm>
12#include <iostream>
13#include <memory>
14#include <numeric>
15#include <optional>
16#include <type_traits>
17#include <utility>
18#include <vector>
19
20#include <Eigen/Geometry> // aabb
21
22#include "../../Common/Assert.h"
23
24#include "Query/kdTreeNearestQueries.h"
25#include "Query/kdTreeKNearestQueries.h"
26#include "Query/kdTreeRangeQueries.h"
27
28namespace Ponca
29{
30 template <typename Traits>
31 class KdTreeBase;
32 template <typename Traits>
33 class KdTreeDenseBase;
34 template <typename Traits>
35 class KdTreeSparseBase;
36
49#ifdef PARSED_WITH_DOXYGEN
50 // [KdTree type definition]
51 template <typename DataPoint>
52 struct KdTree : public Ponca::KdTreeBase<KdTreeDefaultTraits<DataPoint>>
53 {
54 };
55// [KdTree type definition]
56#else
57 template <typename DataPoint>
58 using KdTree = KdTreeBase<KdTreeDefaultTraits<DataPoint>>; // prefer alias to avoid redefining methods
59#endif
60
70#ifdef PARSED_WITH_DOXYGEN
71 // [StaticKdTree type definition]
72 template <typename DataPoint>
73 struct StaticKdTree : public Ponca::StaticKdTreeBase<KdTreeDefaultTraits<DataPoint>>
74 {
75 };
76// [StaticKdTree type definition]
77#else
78 template <typename DataPoint>
79 using StaticKdTree = StaticKdTreeBase<KdTreeDefaultTraits<DataPoint>>; // prefer alias to avoid redefining methods
80#endif
81
90#ifdef PARSED_WITH_DOXYGEN
91 // [KdTreeDense type definition]
92 template <typename DataPoint>
93 struct KdTreeDense : public Ponca::KdTreeDenseBase<KdTreeDefaultTraits<DataPoint>>
94 {
95 };
96// [KdTreeDense type definition]
97#else
98 template <typename DataPoint>
99 using KdTreeDense = KdTreeDenseBase<KdTreeDefaultTraits<DataPoint>>; // prefer alias to avoid redefining methods
100#endif
101
110#ifdef PARSED_WITH_DOXYGEN
111 // [KdTreeSparse type definition]
112 template <typename DataPoint>
113 struct KdTreeSparse : Ponca::KdTreeSparseBase<KdTreeDefaultTraits<DataPoint>>
114 {
115 };
116// [KdTreeSparse type definition]
117#else
118 template <typename DataPoint>
120#endif
121
136 template <typename Traits>
138 {
139 public:
140#define WRITE_TRAITS \
141 using DataPoint = typename Traits::DataPoint; \
142 using IndexType = typename Traits::IndexType; \
143 using LeafSizeType = typename Traits::LeafSizeType; \
144 using PointContainer = typename Traits::PointContainer; \
145 using IndexContainer = typename Traits::IndexContainer; \
146 using NodeIndexType = typename Traits::NodeIndexType; \
147 using NodeType = typename Traits::NodeType; \
148 using NodeContainer = typename Traits::NodeContainer; \
149 using Scalar = typename DataPoint::Scalar; \
150 using VectorType = typename DataPoint::VectorType; \
151 using AabbType = typename NodeType::AabbType;
152 WRITE_TRAITS
153
155 struct Buffers
156 {
160
161 size_t points_size{0};
162 size_t nodes_size{0};
163 size_t indices_size{0};
164
165 PONCA_MULTIARCH inline Buffers() = default;
166
167 PONCA_MULTIARCH inline Buffers(PointContainer _points, NodeContainer _nodes, IndexContainer _indices,
168 const size_t _points_size, const size_t _nodes_size,
169 const size_t _indices_size)
170 : points(_points), nodes(_nodes), indices(_indices), points_size(_points_size), nodes_size(_nodes_size),
171 indices_size(_indices_size)
172 {
173 }
174 };
175
177 static constexpr std::size_t MAX_NODE_COUNT = NodeType::MAX_COUNT;
179 static constexpr std::size_t MAX_POINT_COUNT = std::size_t(2) << sizeof(IndexType) * 8;
180
182 static constexpr int MAX_DEPTH = Traits::MAX_DEPTH;
183
184 static constexpr bool SUPPORTS_SUBSAMPLING = false;
185
186 // Queries use a value of -1 for invalid indices
187 static_assert(std::is_signed_v<IndexType>, "Index type must be signed");
188 static_assert(MAX_DEPTH > 0, "Max depth must be strictly positive");
189
190 // Construction ------------------------------------------------------------
191 protected:
192 PONCA_MULTIARCH inline StaticKdTreeBase() = default;
193
194 public:
204 PONCA_MULTIARCH inline StaticKdTreeBase(Buffers& buf) : m_bufs(buf) {}
205
206 // Accessors ---------------------------------------------------------------
207 public:
209 PONCA_MULTIARCH [[nodiscard]] inline NodeIndexType nodeCount() const
210 {
211 return (NodeIndexType)m_bufs.nodes_size;
212 }
213
215 PONCA_MULTIARCH [[nodiscard]] inline IndexType sampleCount() const { return (IndexType)m_bufs.indices_size; }
216
218 PONCA_MULTIARCH [[nodiscard]] inline IndexType pointCount() const { return (IndexType)m_bufs.points_size; }
219
221 PONCA_MULTIARCH [[nodiscard]] inline NodeIndexType leafCount() const { return m_leaf_count; }
222
224 PONCA_MULTIARCH [[nodiscard]] inline PointContainer& points() { return m_bufs.points; };
225
227 PONCA_MULTIARCH [[nodiscard]] inline const PointContainer& points() const { return m_bufs.points; };
228
230 PONCA_MULTIARCH [[nodiscard]] inline const NodeContainer& nodes() const { return m_bufs.nodes; }
231
233 PONCA_MULTIARCH [[nodiscard]] inline const IndexContainer& samples() const { return m_bufs.indices; }
234
236 PONCA_MULTIARCH [[nodiscard]] inline const Buffers& buffers() const { return m_bufs; }
237
238 // Parameters --------------------------------------------------------------
239 public:
241 PONCA_MULTIARCH [[nodiscard]] inline LeafSizeType minCellSize() const { return m_min_cell_size; }
242
244 PONCA_MULTIARCH inline void setMinCellSize(LeafSizeType min_cell_size)
245 {
246 PONCA_DEBUG_ASSERT(min_cell_size > 0);
248 }
249
250 // Index mapping -----------------------------------------------------------
251 public:
253 PONCA_MULTIARCH [[nodiscard]] inline IndexType pointFromSample(IndexType sample_index) const
254 {
256 }
257
265
269 PONCA_MULTIARCH [[nodiscard]] inline const DataPoint& pointDataFromSample(IndexType sample_index) const
270 {
272 }
273
274 // Query -------------------------------------------------------------------
275 public:
285 IndexType k) const
286 {
288 }
289
296 IndexType k) const
297 {
298 return KdTreeKNearestIndexQuery<Traits>(this, k, index);
299 }
300
310 {
311 return KdTreeKNearestPointQuery<Traits>(this, 0, VectorType::Zero());
312 }
313
326
338
344 {
345 return KdTreeNearestIndexQuery<Traits>(this, index);
346 }
347
358 {
359 return KdTreeNearestIndexQuery<Traits>(this, VectorType::Zero());
360 }
361
375
385 Scalar r) const
386 {
388 }
389
396 {
397 return KdTreeRangeIndexQuery<Traits>(this, r, index);
398 }
399
410 {
411 return KdTreeRangePointQuery<Traits>(this, 0, VectorType::Zero());
412 }
413
424 {
425 return KdTreeRangeIndexQuery<Traits>(this, 0, 0);
426 }
427
428 // Utilities ---------------------------------------------------------------
429 public:
430 PONCA_MULTIARCH_HOST [[nodiscard]] inline bool valid() const;
431 PONCA_MULTIARCH_HOST inline void print(std::ostream& os, bool verbose = false) const;
432
433 // Data --------------------------------------------------------------------
434 protected:
438 };
439
456 template <typename Traits>
457 class KdTreeBase : public StaticKdTreeBase<Traits>
458 {
459 public:
461 WRITE_TRAITS
467 template <typename PointUserContainer, typename PointConverter>
468 PONCA_MULTIARCH_HOST inline void build(PointUserContainer&& points, PointConverter c);
469
472 {
473 template <typename Input>
474 PONCA_MULTIARCH_HOST inline void operator()(Input&& i, PointContainer& o)
475 {
476 using InputContainer = std::remove_reference_t<Input>;
477 if constexpr (std::is_same_v<InputContainer, PointContainer> && std::is_copy_assignable_v<DataPoint>)
478 o = std::forward<Input>(i); // Either move or copy
479 else
480 std::transform(
481 i.cbegin(), i.cend(), std::back_inserter(o),
482 [](const typename InputContainer::value_type& p) -> DataPoint { return DataPoint(p); });
483 }
484 };
485
489 template <typename PointUserContainer>
490 PONCA_MULTIARCH_HOST inline void build(PointUserContainer&& points)
491 {
492 build(std::forward<PointUserContainer>(points), DefaultConverter());
493 }
494
495 // Internal ----------------------------------------------------------------
496 protected:
504 template <typename PointUserContainer, typename IndexUserContainer, typename PointConverter>
507
513 template <typename PointUserContainer, typename IndexUserContainer>
515 {
516 buildWithSampling(std::forward<PointUserContainer>(points), std::forward<IndexUserContainer>(sampling),
518 }
519
520 private:
521 PONCA_MULTIARCH_HOST inline void buildRec(NodeIndexType node_id, IndexType start, IndexType end, int level);
522 PONCA_MULTIARCH_HOST [[nodiscard]] inline IndexType partition(IndexType start, IndexType end, int dim,
523 Scalar value);
524 };
525
539 template <typename Traits>
540 class KdTreeDenseBase : public KdTreeBase<Traits>
541 {
542 private:
543 using Base = KdTreeBase<Traits>;
544
545 public:
548 PONCA_MULTIARCH KdTreeDenseBase() = default;
549
551 template <typename PointUserContainer>
552 PONCA_MULTIARCH_HOST inline explicit KdTreeDenseBase(PointUserContainer&& points) : Base()
553 {
554 Base::build(std::forward<PointUserContainer>(points));
555 }
556 };
557
571 template <typename Traits>
572 class KdTreeSparseBase : public KdTreeBase<Traits>
573 {
574 private:
575 using Base = KdTreeBase<Traits>;
576
577 public:
578 static constexpr bool SUPPORTS_SUBSAMPLING = true;
579
582 PONCA_MULTIARCH KdTreeSparseBase() = default;
583
585 template <typename PointUserContainer>
586 PONCA_MULTIARCH_HOST inline explicit KdTreeSparseBase(PointUserContainer&& points) : Base()
587 {
588 this->build(std::forward<PointUserContainer>(points));
589 }
590
597 template <typename PointUserContainer, typename IndexUserContainer>
599 {
600 this->buildWithSampling(std::forward<PointUserContainer>(points), std::move(sampling));
601 }
602
604 };
605
606#include "./kdTree.hpp"
607} // namespace Ponca
608
609template <typename Traits>
610PONCA_MULTIARCH_HOST std::ostream& operator<<(std::ostream& os, const Ponca::KdTreeBase<Traits>& kdtree)
611{
612 kdtree.print(os);
613 return os;
614}
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:318
typename Traits::DataPoint DataPoint
DataPoint given by user via Traits
Definition kdTree.h:461
typename Traits::IndexType IndexType
Type used to index points into the PointContainer
Definition kdTree.h:461
typename Traits::NodeIndexType NodeIndexType
Type used to index nodes into the NodeContainer
Definition kdTree.h:461
void build(PointUserContainer &&points)
Generate a tree from a custom contained type converted using DefaultConverter.
Definition kdTree.h:490
typename Traits::PointContainer PointContainer
Container for DataPoint used inside the KdTree.
Definition kdTree.h:461
void buildWithSampling(PointUserContainer &&points, IndexUserContainer &&sampling, PointConverter c)
Generate a tree sampled from a custom contained type converted using a Converter
void build(PointUserContainer &&points, PointConverter c)
Generate a tree from a custom contained type converted using the specified converter.
void buildWithSampling(PointUserContainer &&points, IndexUserContainer &&sampling)
Generate a tree sampled from a custom contained type converted using a KdTreeBase::DefaultConverter.
Definition kdTree.h:514
Customizable base class for dense KdTree datastructure.
Definition kdTree.h:541
KdTreeDenseBase()=default
Default constructor creating an empty tree.
KdTreeDenseBase(PointUserContainer &&points)
Constructor generating a tree from a custom contained type converted using a Traits::ContainerConvert...
Definition kdTree.h:552
Customizable base class for KdTreeSparse datastructure.
Definition kdTree.h:573
KdTreeSparseBase(PointUserContainer &&points, IndexUserContainer sampling)
Constructor generating a tree sampled from a custom contained type converted using a Traits::Containe...
Definition kdTree.h:598
KdTreeSparseBase(PointUserContainer &&points)
Constructor generating a tree from a custom contained type converted using a Traits::ContainerConvert...
Definition kdTree.h:586
void buildWithSampling(PointUserContainer &&points, IndexUserContainer &&sampling, PointConverter c)
Generate a tree sampled from a custom contained type converted using a Converter
KdTreeSparseBase()=default
Default constructor creating an empty tree.
Customizable static base class for KdTree datastructure implementations.
Definition kdTree.h:138
IndexType pointFromSample(IndexType sample_index) const
Return the point index associated with the specified sample index.
Definition kdTree.h:253
Buffers m_bufs
Buffers used to store the KdTree.
Definition kdTree.h:435
typename Traits::NodeIndexType NodeIndexType
Type used to index nodes into the NodeContainer
Definition kdTree.h:152
typename DataPoint::VectorType VectorType
VectorType given by user via DataPoint
Definition kdTree.h:152
const IndexContainer & samples() const
Get the internal indice container.
Definition kdTree.h:233
const NodeContainer & nodes() const
Get the internal node container.
Definition kdTree.h:230
LeafSizeType m_min_cell_size
Minimal number of points per leaf.
Definition kdTree.h:436
KdTreeKNearestIndexQuery< Traits > kNearestNeighbors(IndexType index, IndexType k) const
Computes a Query object to iterate over the k-nearest neighbors of a point. The returned object can b...
Definition kdTree.h:295
StaticKdTreeBase(Buffers &buf)
Constructor that allows the use of prebuilt KdTree containers.
Definition kdTree.h:204
KdTreeNearestIndexQuery< Traits > nearestNeighbor(IndexType index) const
Computes a Query object that contains the nearest point. The returned object can be reset and reused ...
Definition kdTree.h:343
typename Traits::IndexContainer IndexContainer
Container for indices used inside the KdTree.
Definition kdTree.h:152
KdTreeRangePointQuery< Traits > rangeNeighborsQuery() const
Convenience function that provides an empty range neighbor Query object.
Definition kdTree.h:409
static constexpr std::size_t MAX_POINT_COUNT
The maximum number of points that can be stored in the kd-tree.
Definition kdTree.h:179
KdTreeKNearestIndexQuery< Traits > kNearestNeighborsIndexQuery() const
Convenience function that provides an empty k-nearest neighbors Query object.
Definition kdTree.h:322
static constexpr std::size_t MAX_NODE_COUNT
The maximum number of nodes that the kd-tree can have.
Definition kdTree.h:177
KdTreeRangeIndexQuery< Traits > rangeNeighborsIndexQuery() const
KdTreeBase::rangeNeighborsQuery.
Definition kdTree.h:423
typename Traits::IndexType IndexType
Type used to index points into the PointContainer
Definition kdTree.h:152
KdTreeRangeIndexQuery< Traits > rangeNeighbors(IndexType index, Scalar r) const
Computes a Query object to iterate over the neighbors that are inside a given radius....
Definition kdTree.h:395
KdTreeNearestPointQuery< Traits > nearestNeighbor(const VectorType &point) const
Computes a Query object that contains the nearest point. The returned object can be reset and reused ...
Definition kdTree.h:334
const Buffers & buffers() const
Get access to the internal buffer, for instance to prepare GPU binding.
Definition kdTree.h:236
KdTreeRangePointQuery< Traits > rangeNeighbors(const VectorType &point, Scalar r) const
Computes a Query object to iterate over the neighbors that are inside a given radius....
Definition kdTree.h:384
DataPoint & pointDataFromSample(IndexType sample_index)
Return the DataPoint associated with the specified sample index.
Definition kdTree.h:261
PointContainer & points()
Get the internal point container.
Definition kdTree.h:224
typename Traits::LeafSizeType LeafSizeType
Type used to store the size of leaf nodes
Definition kdTree.h:152
IndexType pointCount() const
Get the number of points.
Definition kdTree.h:218
typename Traits::NodeContainer NodeContainer
Container for nodes used inside the KdTree
Definition kdTree.h:152
NodeIndexType leafCount() const
Get the number of leafs in the KdTree.
Definition kdTree.h:221
void setMinCellSize(LeafSizeType min_cell_size)
Write leaf min size.
Definition kdTree.h:244
KdTreeKNearestPointQuery< Traits > kNearestNeighborsQuery() const
Convenience function that provides an empty k-nearest neighbors Query object.
Definition kdTree.h:309
typename DataPoint::Scalar Scalar
Scalar given by user via DataPoint
Definition kdTree.h:152
NodeIndexType nodeCount() const
Get the number of nodes in the KdTree.
Definition kdTree.h:209
KdTreeKNearestPointQuery< Traits > kNearestNeighbors(const VectorType &point, IndexType k) const
Computes a Query object to iterate over the k-nearest neighbors of a point. The returned object can b...
Definition kdTree.h:284
typename Traits::DataPoint DataPoint
DataPoint given by user via Traits
Definition kdTree.h:152
const DataPoint & pointDataFromSample(IndexType sample_index) const
Return the DataPoint associated with the specified sample index.
Definition kdTree.h:269
static constexpr int MAX_DEPTH
The maximum depth of the kd-tree.
Definition kdTree.h:182
const PointContainer & points() const
Get the internal point container.
Definition kdTree.h:227
IndexType sampleCount() const
Get the number of indices.
Definition kdTree.h:215
typename Traits::PointContainer PointContainer
Container for DataPoint used inside the KdTree.
Definition kdTree.h:152
KdTreeNearestIndexQuery< Traits > nearestNeighborIndexQuery() const
Convenience function that provides an empty nearest neighbor Query object.
Definition kdTree.h:371
NodeIndexType m_leaf_count
Number of leaves in the Kdtree (computed during construction)
Definition kdTree.h:437
LeafSizeType minCellSize() const
Read leaf min size.
Definition kdTree.h:241
KdTreeNearestIndexQuery< Traits > nearestNeighborQuery() const
Convenience function that provides an empty nearest neighbor Query object.
Definition kdTree.h:357
This Source Code Form is subject to the terms of the Mozilla Public License, v.
Convert a custom point container to the KdTree PointContainer using DataPoint default constructor.
Definition kdTree.h:472
Public interface for dense KdTree datastructure.
Definition kdTree.h:94
Public interface for sparse KdTree datastructure.
Definition kdTree.h:114
Abstract KdTree type with KdTreeDefaultTraits.
Definition kdTree.h:53
Internal structure storing all the buffers used by the KdTree.
Definition kdTree.h:156
IndexContainer indices
Buffer storing the indices associating the input points to the nodes.
Definition kdTree.h:159
NodeContainer nodes
Buffer storing the nodes of the KdTree.
Definition kdTree.h:158
PointContainer points
Buffer storing the input points (read only)
Definition kdTree.h:157
A KdTree type with KdTreeDefaultTraits that doesn't define the build function.
Definition kdTree.h:74