Ponca  3415d6bf4b5de0468067f7a5953b71ec2d1f6564
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 <iostream>
12#include <memory>
13#include <numeric>
14#include <optional>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19#include <Eigen/Geometry> // aabb
20
21#include "../../Common/Assert.h"
22
23#include "Query/kdTreeNearestQueries.h"
24#include "Query/kdTreeKNearestQueries.h"
25#include "Query/kdTreeRangeQueries.h"
26
27namespace Ponca {
28template <typename Traits> class KdTreeBase;
29template <typename Traits> class KdTreeDenseBase;
30template <typename Traits> class KdTreeSparseBase;
31
44#ifdef PARSED_WITH_DOXYGEN
46template <typename DataPoint>
47struct KdTree : public Ponca::KdTreeBase<KdTreeDefaultTraits<DataPoint>>{};
49#else
50template <typename DataPoint>
51using KdTree = KdTreeBase<KdTreeDefaultTraits<DataPoint>>; // prefer alias to avoid redefining methods
52#endif
53
54
63#ifdef PARSED_WITH_DOXYGEN
65template <typename DataPoint>
66struct KdTreeDense : public Ponca::KdTreeDenseBase<KdTreeDefaultTraits<DataPoint>>{};
68#else
69template <typename DataPoint>
70using KdTreeDense = KdTreeDenseBase<KdTreeDefaultTraits<DataPoint>>; // prefer alias to avoid redefining methods
71#endif
72
81#ifdef PARSED_WITH_DOXYGEN
83template <typename DataPoint>
84struct KdTreeSparse : Ponca::KdTreeSparseBase<KdTreeDefaultTraits<DataPoint>>{};
86#else
87template <typename DataPoint>
89#endif
90
102template <typename Traits>
104{
105public:
106 using DataPoint = typename Traits::DataPoint;
107 using IndexType = typename Traits::IndexType;
108 using LeafSizeType = typename Traits::LeafSizeType;
109 using PointContainer = typename Traits::PointContainer;
110 using IndexContainer = typename Traits::IndexContainer;
111 using NodeIndexType = typename Traits::NodeIndexType;
112 using NodeType = typename Traits::NodeType;
113 using NodeContainer = typename Traits::NodeContainer;
114
115 using Scalar = typename DataPoint::Scalar;
116 using VectorType = typename DataPoint::VectorType;
117 using AabbType = typename NodeType::AabbType;
118
120 static constexpr std::size_t MAX_NODE_COUNT = NodeType::MAX_COUNT;
122 static constexpr std::size_t MAX_POINT_COUNT = std::size_t(2) << sizeof(IndexType)*8;
123
125 static constexpr int MAX_DEPTH = Traits::MAX_DEPTH;
126
127 static constexpr bool SUPPORTS_SUBSAMPLING = false;
128
129 static_assert(std::is_same<typename PointContainer::value_type, DataPoint>::value,
130 "PointContainer must contain DataPoints");
131
132 // Queries use a value of -1 for invalid indices
133 static_assert(std::is_signed<IndexType>::value, "Index type must be signed");
134
135 static_assert(std::is_same<typename IndexContainer::value_type, IndexType>::value, "Index type mismatch");
136 static_assert(std::is_same<typename NodeContainer::value_type, NodeType>::value, "Node type mismatch");
137
138 static_assert(MAX_DEPTH > 0, "Max depth must be strictly positive");
139
140 // Construction ------------------------------------------------------------
141public:
147 template<typename PointUserContainer, typename Converter>
148 inline void build(PointUserContainer&& points, Converter c);
149
152 {
153 template <typename Input>
154 inline void operator()(Input&& i, PointContainer& o)
155 {
156 using InputContainer = typename std::remove_reference<Input>::type;
157 if constexpr (std::is_same<InputContainer, PointContainer>::value)
158 o = std::forward<Input>(i); // Either move or copy
159 else
160 std::transform(i.cbegin(), i.cend(), std::back_inserter(o),
161 [](const typename InputContainer::value_type &p) -> DataPoint { return DataPoint(p); });
162 }
163 };
164
168 template<typename PointUserContainer>
169 inline void build(PointUserContainer&& points)
170 {
171 build(std::forward<PointUserContainer>(points), DefaultConverter());
172 }
173
175 inline void clear();
176
177 // Accessors ---------------------------------------------------------------
178public:
179 inline NodeIndexType node_count() const
180 {
181 return m_nodes.size();
182 }
183
184 inline IndexType sample_count() const
185 {
186 return (IndexType)m_indices.size();
187 }
188
189 inline IndexType pointCount() const
190 {
191 return (IndexType)m_points.size();
192 }
193
194 inline NodeIndexType leaf_count() const
195 {
196 return m_leaf_count;
197 }
198
199 inline PointContainer& points()
200 {
201 return m_points;
202 };
203
204 inline const PointContainer& points() const
205 {
206 return m_points;
207 };
208
209 inline const NodeContainer& nodes() const
210 {
211 return m_nodes;
212 }
213
214 inline const IndexContainer& samples() const
215 {
216 return m_indices;
217 }
218
219 // Parameters --------------------------------------------------------------
220public:
223 {
224 return m_min_cell_size;
225 }
226
228 inline void setMinCellSize(LeafSizeType min_cell_size)
229 {
230 PONCA_DEBUG_ASSERT(min_cell_size > 0);
231 m_min_cell_size = min_cell_size;
232 }
233
234 // Index mapping -----------------------------------------------------------
235public:
237 inline IndexType pointFromSample(IndexType sample_index) const
238 {
239 return m_indices[sample_index];
240 }
241
246 {
247 return m_points[pointFromSample(sample_index)];
248 }
249
253 inline const DataPoint& pointDataFromSample(IndexType sample_index) const
254 {
255 return m_points[pointFromSample(sample_index)];
256 }
257
258 // Query -------------------------------------------------------------------
259public :
272
282
292 {
293 return KdTreeKNearestPointQuery<Traits>(this, 0, VectorType::Zero());
294 }
295
308
317 {
318 return KdTreeNearestPointQuery<Traits>(this, point);
319 }
320
321
330
341 {
342 return KdTreeNearestIndexQuery<Traits>(this, VectorType::Zero());
343 }
344
358
368 {
369 return KdTreeRangePointQuery<Traits>(this, r, point);
370 }
371
378 {
379 return KdTreeRangeIndexQuery<Traits>(this, r, index);
380 }
381
392 {
393 return KdTreeRangePointQuery<Traits>(this, 0, VectorType::Zero());
394 }
395
409
410 // Utilities ---------------------------------------------------------------
411public:
412 [[nodiscard]] inline bool valid() const;
413 inline void print(std::ostream& os, bool verbose = false) const;
414
415 // Data --------------------------------------------------------------------
416protected:
417 PointContainer m_points;
418 NodeContainer m_nodes;
419 IndexContainer m_indices;
420
423
424 // Internal ----------------------------------------------------------------
425protected:
426 inline KdTreeBase() = default;
427
435 template<typename PointUserContainer, typename IndexUserContainer, typename Converter>
436 inline void buildWithSampling(PointUserContainer&& points,
437 IndexUserContainer sampling,
438 Converter c);
439
445 template<typename PointUserContainer, typename IndexUserContainer>
446 inline void buildWithSampling(PointUserContainer&& points,
447 IndexUserContainer sampling)
448 {
449 buildWithSampling(std::forward<PointUserContainer>(points), std::move(sampling), DefaultConverter());
450 }
451
452private:
453 inline void buildRec(NodeIndexType node_id, IndexType start, IndexType end, int level);
454 inline IndexType partition(IndexType start, IndexType end, int dim, Scalar value);
455};
456
471template <typename Traits>
472class KdTreeDenseBase : public KdTreeBase<Traits>
473{
474private:
475 using Base = KdTreeBase<Traits>;
476
477public:
480 KdTreeDenseBase() = default;
481
483 template<typename PointUserContainer>
484 inline explicit KdTreeDenseBase(PointUserContainer&& points)
485 : Base()
486 {
487 this->build(std::forward<PointUserContainer>(points));
488 }
489};
490
505template <typename Traits>
506class KdTreeSparseBase : public KdTreeBase<Traits>
507{
508private:
509 using Base = KdTreeBase<Traits>;
510
511public:
512 static constexpr bool SUPPORTS_SUBSAMPLING = false;
513
516 KdTreeSparseBase() = default;
517
519 template<typename PointUserContainer>
520 inline explicit KdTreeSparseBase(PointUserContainer&& points)
521 : Base()
522 {
523 this->build(std::forward<PointUserContainer>(points));
524 }
525
531 template<typename PointUserContainer, typename IndexUserContainer>
532 inline KdTreeSparseBase(PointUserContainer&& points, IndexUserContainer sampling)
533 : Base()
534 {
535 this->buildWithSampling(std::forward<PointUserContainer>(points), std::move(sampling));
536 }
537
539};
540
541#include "./kdTree.hpp"
542} // namespace Ponca
543
544template <typename Traits>
545std::ostream& operator<<(std::ostream& os, const Ponca::KdTreeBase<Traits>& kdtree)
546{
547 kdtree.print(os);
548 return os;
549}
[KdTreeSparse type definition]
Definition kdTree.h:104
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:326
void setMinCellSize(LeafSizeType min_cell_size)
Write leaf min size.
Definition kdTree.h:228
typename Traits::DataPoint DataPoint
DataPoint given by user via Traits.
Definition kdTree.h:106
typename DataPoint::Scalar Scalar
Scalar given by user via DataPoint.
Definition kdTree.h:115
typename Traits::NodeType NodeType
Type of nodes used inside the KdTree.
Definition kdTree.h:112
LeafSizeType minCellSize() const
Read leaf min size.
Definition kdTree.h:222
typename Traits::IndexType IndexType
Type used to index points into the PointContainer.
Definition kdTree.h:107
KdTreeRangePointQuery< Traits > rangeNeighborsQuery() const
Convenience function that provides an empty range neighbor Query object.
Definition kdTree.h:391
KdTreeRangeIndexQuery< Traits > rangeNeighborsIndexQuery() const
KdTreeBase::rangeNeighborsQuery.
Definition kdTree.h:405
KdTreeKNearestIndexQuery< Traits > kNearestNeighborsIndexQuery() const
Convenience function that provides an empty k-nearest neighbors Query object.
Definition kdTree.h:304
void build(PointUserContainer &&points, Converter c)
Generate a tree from a custom contained type converted using the specified converter.
typename Traits::IndexContainer IndexContainer
Container for indices used inside the KdTree.
Definition kdTree.h:110
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:268
KdTreeKNearestPointQuery< Traits > kNearestNeighborsQuery() const
Convenience function that provides an empty k-nearest neighbors Query object.
Definition kdTree.h:291
static constexpr std::size_t MAX_POINT_COUNT
The maximum number of points that can be stored in the kd-tree.
Definition kdTree.h:122
typename Traits::NodeContainer NodeContainer
Container for nodes used inside the KdTree.
Definition kdTree.h:113
KdTreeNearestIndexQuery< Traits > nearestNeighborQuery() const
Convenience function that provides an empty nearest neighbor Query object.
Definition kdTree.h:340
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:367
static constexpr std::size_t MAX_NODE_COUNT
The maximum number of nodes that the kd-tree can have.
Definition kdTree.h:120
typename Traits::NodeIndexType NodeIndexType
Type used to index nodes into the NodeContainer.
Definition kdTree.h:111
void build(PointUserContainer &&points)
Generate a tree from a custom contained type converted using DefaultConverter.
Definition kdTree.h:169
typename Traits::PointContainer PointContainer
Container for DataPoint used inside the KdTree.
Definition kdTree.h:109
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:377
NodeIndexType m_leaf_count
Number of leaves in the Kdtree (computed during construction)
Definition kdTree.h:422
void clear()
Clear tree data.
Definition kdTree.hpp:19
void buildWithSampling(PointUserContainer &&points, IndexUserContainer sampling)
Generate a tree sampled from a custom contained type converted using a KdTreeBase::DefaultConverter.
Definition kdTree.h:446
static constexpr int MAX_DEPTH
The maximum depth of the kd-tree.
Definition kdTree.h:125
const DataPoint & pointDataFromSample(IndexType sample_index) const
Return the DataPoint associated with the specified sample index.
Definition kdTree.h:253
LeafSizeType m_min_cell_size
Minimal number of points per leaf.
Definition kdTree.h:421
KdTreeNearestIndexQuery< Traits > nearestNeighborIndexQuery() const
Convenience function that provides an empty nearest neighbor Query object.
Definition kdTree.h:354
IndexType pointFromSample(IndexType sample_index) const
Return the point index associated with the specified sample index.
Definition kdTree.h:237
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:278
typename NodeType::AabbType AabbType
Bounding box type given by user via NodeType.
Definition kdTree.h:117
typename Traits::LeafSizeType LeafSizeType
Type used to store the size of leaf nodes.
Definition kdTree.h:108
DataPoint & pointDataFromSample(IndexType sample_index)
Return the DataPoint associated with the specified sample index.
Definition kdTree.h:245
typename DataPoint::VectorType VectorType
VectorType given by user via DataPoint.
Definition kdTree.h:116
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:316
void buildWithSampling(PointUserContainer &&points, IndexUserContainer sampling, Converter c)
Generate a tree sampled from a custom contained type converted using a Converter
Customizable base class for dense KdTree datastructure.
Definition kdTree.h:473
KdTreeDenseBase()=default
Default constructor creating an empty tree.
KdTreeDenseBase(PointUserContainer &&points)
Constructor generating a tree from a custom contained type converted using a KdTreeBase::DefaultConve...
Definition kdTree.h:484
Extension of the Query class that allows to read the result of a k-nearest neighbors search on the Kd...
Extension of the Query class that allows to read the result of a nearest neighbor search on the KdTre...
Extension of the Query class that allows to read the result of a range neighbors search on the KdTree...
Customizable base class for KdTreeSparse datastructure.
Definition kdTree.h:507
KdTreeSparseBase(PointUserContainer &&points, IndexUserContainer sampling)
Constructor generating a tree sampled from a custom contained type converted using a KdTreeBase::Defa...
Definition kdTree.h:532
KdTreeSparseBase(PointUserContainer &&points)
Constructor generating a tree from a custom contained type converted using a KdTreeBase::DefaultConve...
Definition kdTree.h:520
KdTreeSparseBase()=default
Default constructor creating an empty tree.
void buildWithSampling(PointUserContainer &&points, IndexUserContainer sampling, Converter c)
Generate a tree sampled from a custom contained type converted using a Converter
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:152
[KdTree type definition]
Definition kdTree.h:66
[KdTreeDense type definition]
Definition kdTree.h:84
Abstract KdTree type with KdTreeDefaultTraits.
Definition kdTree.h:47