Ponca  7d8ac87a7de01d881c9fde3c42e397b44bffb901
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#pragma once
8
9#include "../defines.h"
10#include "../../Common/Macro.h"
11
12#include <cstddef>
13
14#include <Eigen/Geometry>
15
16namespace Ponca
17{
18#ifndef PARSED_WITH_DOXYGEN
19 namespace 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 } // namespace internal
40#endif
41
42 template <typename NodeIndex, typename Scalar, int DIM>
44 {
45 private:
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
64 public:
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
78 template <typename Index, typename Size>
80 {
81 Index start{0};
82 Size size{0};
83 };
84
106 template <typename Index, typename NodeIndex, typename DataPoint, typename LeafSize = Index,
110 {
111 private:
112 using Scalar = typename DataPoint::Scalar;
114 using LeafType = _LeafNodeType;
115
116 public:
117 enum : std::size_t
118 {
123 MAX_COUNT = std::size_t(2) << InnerType::INDEX_BITS,
124 };
125
132 using AabbType = Eigen::AlignedBox<Scalar, DataPoint::Dim>;
133
134 PONCA_MULTIARCH KdTreeCustomizableNode() = default;
135
136 PONCA_MULTIARCH constexpr KdTreeCustomizableNode(KdTreeCustomizableNode&& n) : m_is_leaf(n.m_is_leaf)
137 {
138 if (m_is_leaf)
139 {
140 data.m_leaf = n.data.m_leaf;
141 }
142 else
143 {
144 data.m_inner = n.data.m_inner;
145 }
146 }
147
148 PONCA_MULTIARCH constexpr KdTreeCustomizableNode& operator=(KdTreeCustomizableNode&& n)
149 {
150 if (&n != this)
151 {
152 m_is_leaf = n.m_is_leaf;
153 if (m_is_leaf)
154 {
155 data.m_leaf = n.data.m_leaf;
156 }
157 else
158 {
159 data.m_inner = n.data.m_inner;
160 }
161 }
162
163 return *this;
164 }
165
166 PONCA_MULTIARCH constexpr KdTreeCustomizableNode(const KdTreeCustomizableNode& n) : m_is_leaf(n.m_is_leaf)
167 {
168 if (n.m_is_leaf)
169 {
170 data.m_leaf = n.data.m_leaf;
171 }
172 else
173 {
174 data.m_inner = n.data.m_inner;
175 }
176 }
177
178 PONCA_MULTIARCH constexpr KdTreeCustomizableNode& operator=(const KdTreeCustomizableNode& n)
179 {
180 if (&n != this)
181 {
182 m_is_leaf = n.m_is_leaf;
183 if (n.m_is_leaf)
184 {
185 data.m_leaf = n.data.m_leaf;
186 }
187 else
188 {
189 data.m_inner = n.data.m_inner;
190 }
191 }
192
193 return *this;
194 }
195
196 PONCA_MULTIARCH_HOST ~KdTreeCustomizableNode() {}
197
198 PONCA_MULTIARCH [[nodiscard]] bool is_leaf() const { return m_is_leaf; }
199 PONCA_MULTIARCH void set_is_leaf(bool is_leaf) { m_is_leaf = is_leaf; }
200
213 PONCA_MULTIARCH void configure_range(Index start, Index size, const AabbType& aabb)
214 {
215 if (m_is_leaf)
216 {
217 data.m_leaf.start = start;
218 data.m_leaf.size = (LeafSize)size;
219 }
220 }
221
231 PONCA_MULTIARCH void configure_inner(Scalar split_value, Index first_child_id, Index split_dim)
232 {
233 if (!m_is_leaf)
234 {
235 data.m_inner.split_value = split_value;
236 data.m_inner.first_child_id = first_child_id;
237 data.m_inner.split_dim = split_dim;
238 }
239 }
240
245 PONCA_MULTIARCH [[nodiscard]] Index leaf_start() const { return data.m_leaf.start; }
246
250 PONCA_MULTIARCH [[nodiscard]] LeafSize leaf_size() const { return data.m_leaf.size; }
251
255 PONCA_MULTIARCH [[nodiscard]] Scalar inner_split_value() const { return data.m_inner.split_value; }
256
260 PONCA_MULTIARCH [[nodiscard]] int inner_split_dim() const { return (int)data.m_inner.split_dim; }
261
269 PONCA_MULTIARCH [[nodiscard]] Index inner_first_child_id() const { return (Index)data.m_inner.first_child_id; }
270
271 protected:
272 PONCA_MULTIARCH [[nodiscard]] inline LeafType& getAsLeaf() { return data.m_leaf; }
273 PONCA_MULTIARCH [[nodiscard]] inline InnerType& getAsInner() { return data.m_inner; }
274 PONCA_MULTIARCH [[nodiscard]] inline const LeafType& getAsLeaf() const { return data.m_leaf; }
275 PONCA_MULTIARCH [[nodiscard]] inline const InnerType& getAsInner() const { return data.m_inner; }
276
277 private:
278 bool m_is_leaf{true};
279 union Data {
280 // We need an explicit constructor here, see https://stackoverflow.com/a/70428826
281 constexpr Data() : m_leaf() {}
282
283 ~Data() {}
284 LeafType m_leaf;
285 InnerType m_inner;
286 };
287 Data data;
288 };
289
290 template <typename Index, typename NodeIndex, typename DataPoint, typename LeafSize = Index>
292 : public KdTreeCustomizableNode<Index, NodeIndex, DataPoint, LeafSize,
293 KdTreeDefaultInnerNode<NodeIndex, typename DataPoint::Scalar, DataPoint::Dim>,
294 KdTreeDefaultLeafNode<Index, LeafSize>>
295 {
296 using Base =
297 KdTreeCustomizableNode<Index, NodeIndex, DataPoint, LeafSize,
300 };
301
309 template <typename _DataPoint, template <typename /*Index*/, typename /*NodeIndex*/, typename /*DataPoint*/,
310 typename /*LeafSize*/> typename _NodeType = KdTreeDefaultNode>
312 {
313 enum
314 {
319 };
320
331 using IndexType = int;
332 using LeafSizeType = unsigned short;
333
334 // Containers
335 using PointContainer = std::vector<DataPoint>;
336 using IndexContainer = std::vector<IndexType>;
337
338 // Nodes
339 using NodeIndexType = std::size_t;
341 using NodeContainer = std::vector<NodeType>;
342 };
343
351 template <typename _DataPoint, template <typename /*Index*/, typename /*NodeIndex*/, typename /*DataPoint*/,
352 typename /*LeafSize*/> typename _NodeType = Ponca::KdTreeDefaultNode>
354 {
355 enum
356 {
361 };
362
373 using IndexType = int;
374 using LeafSizeType = unsigned short;
375
376 // Containers
377 using PointContainer = DataPoint*;
378 using IndexContainer = IndexType*;
379
380 // Nodes
381 using NodeIndexType = std::size_t;
383 using NodeContainer = NodeType*;
384 };
385} // namespace Ponca
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:318
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.
@ MAX_COUNT
The maximum number of nodes that a kd-tree can have when using this node type.
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.
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.
@ 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.