Ponca  93eea5457c48839cb5d16642765afa89fc7cfe66
Point Cloud Analysis library
Loading...
Searching...
No Matches
kdTreeTraits.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
8#pragma once
9
10#include "../defines.h"
11#include "../../Common/Macro.h"
12
13#include <cstddef>
14
15#include <Eigen/Geometry>
16
17namespace Ponca {
18#ifndef PARSED_WITH_DOXYGEN
19namespace internal
20{
21 constexpr int clz(unsigned int value)
22 {
23#if PONCA_HAS_BUILTIN_CLZ
24 return __builtin_clz(value);
25#else
26 if (value == 0)
27 {
28 return 0;
29 }
30
31 unsigned int msb_mask = 1 << (sizeof(unsigned int)*8 - 1);
32 int count = 0;
33 for (; (value & msb_mask) == 0; value <<= 1, ++count)
34 {
35 }
36 return count;
37#endif
38 }
39}
40#endif
41
42template <typename NodeIndex, typename Scalar, int DIM>
44{
45private:
46 enum
47 {
48 // The minimum bit width required to store the split dimension.
49 //
50 // Equal to the index of DIM's most significant bit (starting at 1), e.g.:
51 // With DIM = 4,
52 // -------------
53 // DIM = 0b | 1 | 0 | 0 |
54 // -------------
55 // Bit index = #3 #2 #1
56 //
57 // The MSB has an index of 3, so we store the dimension on 3 bits.
58 DIM_BITS = sizeof(unsigned int)*8 - internal::clz((unsigned int)DIM),
59 };
60
61 // The node stores bitfields as unsigned indices.
62 using UIndex = typename std::make_unsigned<NodeIndex>::type;
63
64public:
65 enum
66 {
70 INDEX_BITS = sizeof(UIndex)*8 - DIM_BITS,
71 };
72
73 Scalar split_value{0};
74 UIndex first_child_id : INDEX_BITS;
75 UIndex split_dim : DIM_BITS;
76};
77
78template <typename Index, typename Size>
80{
81 Index start{0};
82 Size size{0};
83};
84
106template <typename Index, typename NodeIndex, typename DataPoint,
107 typename LeafSize = Index,
109 typename _LeafNodeType = KdTreeDefaultLeafNode<Index, LeafSize>>
111{
112private:
113 using Scalar = typename DataPoint::Scalar;
114 using InnerType = _InnerNodeType;
115 using LeafType = _LeafNodeType;
116
117public:
118 enum : std::size_t
119 {
124 MAX_COUNT = std::size_t(2) << InnerType::INDEX_BITS,
125 };
126
133 using AabbType = Eigen::AlignedBox<Scalar, DataPoint::Dim>;
134
135 PONCA_MULTIARCH KdTreeCustomizableNode() = default;
136
137 PONCA_MULTIARCH constexpr KdTreeCustomizableNode(KdTreeCustomizableNode&& n)
138 : m_is_leaf(n.m_is_leaf)
139 {
140 if (m_is_leaf)
141 {
142 data.m_leaf = n.data.m_leaf;
143 }
144 else
145 {
146 data.m_inner = n.data.m_inner;
147 }
148 }
149
150 PONCA_MULTIARCH constexpr KdTreeCustomizableNode& operator=(KdTreeCustomizableNode&& n)
151 {
152 if (&n != this)
153 {
154 m_is_leaf = n.m_is_leaf;
155 if (m_is_leaf)
156 {
157 data.m_leaf = n.data.m_leaf;
158 }
159 else
160 {
161 data.m_inner = n.data.m_inner;
162 }
163 }
164
165 return *this;
166 }
167
168 PONCA_MULTIARCH constexpr KdTreeCustomizableNode(const KdTreeCustomizableNode& n)
169 : m_is_leaf(n.m_is_leaf)
170 {
171 if (n.m_is_leaf)
172 {
173 data.m_leaf = n.data.m_leaf;
174 }
175 else
176 {
177 data.m_inner = n.data.m_inner;
178 }
179 }
180
181 PONCA_MULTIARCH constexpr KdTreeCustomizableNode& operator=(const KdTreeCustomizableNode& n)
182 {
183 if (&n != this)
184 {
185 m_is_leaf = n.m_is_leaf;
186 if (n.m_is_leaf)
187 {
188 data.m_leaf = n.data.m_leaf;
189 }
190 else
191 {
192 data.m_inner = n.data.m_inner;
193 }
194 }
195
196 return *this;
197 }
198
199 PONCA_MULTIARCH_HOST ~KdTreeCustomizableNode() {}
200
201 PONCA_MULTIARCH [[nodiscard]] bool is_leaf() const { return m_is_leaf; }
202 PONCA_MULTIARCH void set_is_leaf(bool is_leaf) { m_is_leaf = is_leaf; }
203
216 PONCA_MULTIARCH void configure_range(Index start, Index size, const AabbType &aabb)
217 {
218 if (m_is_leaf)
219 {
220 data.m_leaf.start = start;
221 data.m_leaf.size = (LeafSize)size;
222 }
223 }
224
234 PONCA_MULTIARCH void configure_inner(Scalar split_value, Index first_child_id, Index split_dim)
235 {
236 if (!m_is_leaf)
237 {
238 data.m_inner.split_value = split_value;
239 data.m_inner.first_child_id = first_child_id;
240 data.m_inner.split_dim = split_dim;
241 }
242 }
243
248 PONCA_MULTIARCH [[nodiscard]] Index leaf_start() const { return data.m_leaf.start; }
249
253 PONCA_MULTIARCH [[nodiscard]] LeafSize leaf_size() const { return data.m_leaf.size; }
254
258 PONCA_MULTIARCH [[nodiscard]] Scalar inner_split_value() const { return data.m_inner.split_value; }
259
263 PONCA_MULTIARCH [[nodiscard]] int inner_split_dim() const { return (int)data.m_inner.split_dim; }
264
272 PONCA_MULTIARCH [[nodiscard]] Index inner_first_child_id() const { return (Index)data.m_inner.first_child_id; }
273
274protected:
275 PONCA_MULTIARCH [[nodiscard]] inline LeafType& getAsLeaf() { return data.m_leaf; }
276 PONCA_MULTIARCH [[nodiscard]] inline InnerType& getAsInner() { return data.m_inner; }
277 PONCA_MULTIARCH [[nodiscard]] inline const LeafType& getAsLeaf() const { return data.m_leaf; }
278 PONCA_MULTIARCH [[nodiscard]] inline const InnerType& getAsInner() const { return data.m_inner; }
279
280private:
281 bool m_is_leaf{true};
282 union Data
283 {
284 // We need an explicit constructor here, see https://stackoverflow.com/a/70428826
285 constexpr Data() : m_leaf() {}
286
287 ~Data() {}
288 LeafType m_leaf;
289 InnerType m_inner;
290 };
291 Data data;
292};
293
294template <typename Index, typename NodeIndex, typename DataPoint,
295 typename LeafSize = Index>
296struct KdTreeDefaultNode : public KdTreeCustomizableNode<Index, NodeIndex, DataPoint, LeafSize,
297 KdTreeDefaultInnerNode<NodeIndex, typename DataPoint::Scalar, DataPoint::Dim>,
298 KdTreeDefaultLeafNode<Index, LeafSize>> {
299 using Base = KdTreeCustomizableNode<Index, NodeIndex, DataPoint, LeafSize,
302};
303
311template <typename _DataPoint,
312 template <typename /*Index*/,
313 typename /*NodeIndex*/,
314 typename /*DataPoint*/,
315 typename /*LeafSize*/> typename _NodeType = KdTreeDefaultNode>
317{
318 enum
319 {
324 };
325
335 using DataPoint = _DataPoint;
336 using IndexType = int;
337 using LeafSizeType = unsigned short;
338
339 // Containers
340 using PointContainer = std::vector<DataPoint>;
341 using IndexContainer = std::vector<IndexType>;
342
343 // Nodes
344 using NodeIndexType = std::size_t;
345 using NodeType = _NodeType<IndexType, NodeIndexType, DataPoint, LeafSizeType>;
346 using NodeContainer = std::vector<NodeType>;
347};
348
355template <typename _DataPoint,
356 template <typename /*Index*/,
357 typename /*NodeIndex*/,
358 typename /*DataPoint*/,
359 typename /*LeafSize*/> typename _NodeType = Ponca::KdTreeDefaultNode>
361{
362 enum
363 {
368 };
369
379 using DataPoint = _DataPoint;
380 using IndexType = int;
381 using LeafSizeType = unsigned short;
382
383 // Containers
384 using PointContainer = DataPoint*;
385 using IndexContainer = IndexType*;
386
387 // Nodes
388 using NodeIndexType = std::size_t;
389 using NodeType = _NodeType<IndexType, NodeIndexType, DataPoint, LeafSizeType>;
390 using NodeContainer = NodeType*;
391};
392} // namespace Ponca
The node type used by default by the kd-tree.
Scalar inner_split_value() const
The position of the AABB split of the inner node.
Index leaf_start() const
The start index of the range of the leaf node in the sample index array.
Eigen::AlignedBox< Scalar, DataPoint::Dim > AabbType
The type used to store node bounding boxes.
void configure_range(Index start, Index size, const AabbType &aabb)
Configures the range of the node in the sample index array of the kd-tree.
@ MAX_COUNT
The maximum number of nodes that a kd-tree can have when using this node type.
void configure_inner(Scalar split_value, Index first_child_id, Index split_dim)
Configures the inner node information.
int inner_split_dim() const
Which axis the split of the AABB of the inner node was done on.
LeafSize leaf_size() const
The size of the range of the leaf node in the sample index array.
Index inner_first_child_id() const
The index of the first child of the node in the node array of the kd-tree.
This Source Code Form is subject to the terms of the Mozilla Public License, v.
@ INDEX_BITS
The bit width used to store the first child index.
The default traits type used by the kd-tree.
_DataPoint DataPoint
The type used to store point data.
@ MAX_DEPTH
A compile-time constant specifying the maximum depth of the kd-tree.
Variant to the KdTree Traits type that uses pointers as internal storage instead of an STL-like conta...
@ MAX_DEPTH
A compile-time constant specifying the maximum depth of the kd-tree.
_DataPoint DataPoint
The type used to store point data.