Ponca  7df32c91629c89b89840c4d7917cb272433f2d2b
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:
284 IndexType k) const
285 {
287 }
288
294 IndexType k) const
295 {
296 return KdTreeKNearestIndexQuery<Traits>(this, k, index);
297 }
298
308 {
309 return KdTreeKNearestPointQuery<Traits>(this, 0, VectorType::Zero());
310 }
311
324
336
342 {
343 return KdTreeNearestIndexQuery<Traits>(this, index);
344 }
345
356 {
357 return KdTreeNearestIndexQuery<Traits>(this, VectorType::Zero());
358 }
359
373
383 Scalar r) const
384 {
386 }
387
394 {
395 return KdTreeRangeIndexQuery<Traits>(this, r, index);
396 }
397
408 {
409 return KdTreeRangePointQuery<Traits>(this, 0, VectorType::Zero());
410 }
411
422 {
423 return KdTreeRangeIndexQuery<Traits>(this, 0, 0);
424 }
425
426 // Utilities ---------------------------------------------------------------
427 public:
428 PONCA_MULTIARCH_HOST [[nodiscard]] inline bool valid() const;
429 PONCA_MULTIARCH_HOST inline void print(std::ostream& os, bool verbose = false) const;
430
431 // Data --------------------------------------------------------------------
432 protected:
436 };
437
454 template <typename Traits>
455 class KdTreeBase : public StaticKdTreeBase<Traits>
456 {
457 public:
459 WRITE_TRAITS
465 template <typename PointUserContainer, typename PointConverter>
466 PONCA_MULTIARCH_HOST inline void build(PointUserContainer&& points, PointConverter c);
467
470 {
471 template <typename Input>
472 PONCA_MULTIARCH_HOST inline void operator()(Input&& i, PointContainer& o)
473 {
474 using InputContainer = std::remove_reference_t<Input>;
475 if constexpr (std::is_same_v<InputContainer, PointContainer> && std::is_copy_assignable_v<DataPoint>)
476 o = std::forward<Input>(i); // Either move or copy
477 else
478 std::transform(
479 i.cbegin(), i.cend(), std::back_inserter(o),
480 [](const typename InputContainer::value_type& p) -> DataPoint { return DataPoint(p); });
481 }
482 };
483
487 template <typename PointUserContainer>
488 PONCA_MULTIARCH_HOST inline void build(PointUserContainer&& points)
489 {
490 build(std::forward<PointUserContainer>(points), DefaultConverter());
491 }
492
493 // Internal ----------------------------------------------------------------
494 protected:
502 template <typename PointUserContainer, typename IndexUserContainer, typename PointConverter>
505
511 template <typename PointUserContainer, typename IndexUserContainer>
513 {
514 buildWithSampling(std::forward<PointUserContainer>(points), std::forward<IndexUserContainer>(sampling),
516 }
517
518 private:
519 PONCA_MULTIARCH_HOST inline void buildRec(NodeIndexType node_id, IndexType start, IndexType end, int level);
520 PONCA_MULTIARCH_HOST [[nodiscard]] inline IndexType partition(IndexType start, IndexType end, int dim,
521 Scalar value);
522 };
523
537 template <typename Traits>
538 class KdTreeDenseBase : public KdTreeBase<Traits>
539 {
540 private:
541 using Base = KdTreeBase<Traits>;
542
543 public:
546 PONCA_MULTIARCH KdTreeDenseBase() = default;
547
549 template <typename PointUserContainer>
550 PONCA_MULTIARCH_HOST inline explicit KdTreeDenseBase(PointUserContainer&& points) : Base()
551 {
552 Base::build(std::forward<PointUserContainer>(points));
553 }
554 };
555
569 template <typename Traits>
570 class KdTreeSparseBase : public KdTreeBase<Traits>
571 {
572 private:
573 using Base = KdTreeBase<Traits>;
574
575 public:
576 static constexpr bool SUPPORTS_SUBSAMPLING = true;
577
580 PONCA_MULTIARCH KdTreeSparseBase() = default;
581
583 template <typename PointUserContainer>
584 PONCA_MULTIARCH_HOST inline explicit KdTreeSparseBase(PointUserContainer&& points) : Base()
585 {
586 this->build(std::forward<PointUserContainer>(points));
587 }
588
595 template <typename PointUserContainer, typename IndexUserContainer>
597 {
598 this->buildWithSampling(std::forward<PointUserContainer>(points), std::move(sampling));
599 }
600
602 };
603
604#include "./kdTree.hpp"
605} // namespace Ponca
606
607template <typename Traits>
608PONCA_MULTIARCH_HOST std::ostream& operator<<(std::ostream& os, const Ponca::KdTreeBase<Traits>& kdtree)
609{
610 kdtree.print(os);
611 return os;
612}
613
614#undef WRITE_TRAITS
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:257
typename Traits::DataPoint DataPoint
DataPoint given by user via Traits
Definition kdTree.h:459
typename Traits::IndexType IndexType
Type used to index points into the PointContainer
Definition kdTree.h:459
typename Traits::NodeIndexType NodeIndexType
Type used to index nodes into the NodeContainer
Definition kdTree.h:459
void build(PointUserContainer &&points)
Generate a tree from a custom contained type converted using DefaultConverter.
Definition kdTree.h:488
typename Traits::PointContainer PointContainer
Container for DataPoint used inside the KdTree.
Definition kdTree.h:459
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:512
Customizable base class for dense KdTree datastructure.
Definition kdTree.h:539
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:550
Customizable base class for KdTreeSparse datastructure.
Definition kdTree.h:571
KdTreeSparseBase(PointUserContainer &&points, IndexUserContainer sampling)
Constructor generating a tree sampled from a custom contained type converted using a Traits::Containe...
Definition kdTree.h:596
KdTreeSparseBase(PointUserContainer &&points)
Constructor generating a tree from a custom contained type converted using a Traits::ContainerConvert...
Definition kdTree.h:584
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:433
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:434
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:293
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:341
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:407
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:320
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:421
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:393
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:332
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:382
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:307
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:283
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:369
NodeIndexType m_leaf_count
Number of leaves in the Kdtree (computed during construction)
Definition kdTree.h:435
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:355
This Source Code Form is subject to the terms of the Mozilla Public License, v.
Definition bitset.h:17
Convert a custom point container to the KdTree PointContainer using DataPoint default constructor.
Definition kdTree.h:470
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