Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
node.hpp
Go to the documentation of this file.
1
6
7#ifndef INCLUDE_KDTREE_NODE_HPP
8#define INCLUDE_KDTREE_NODE_HPP
9
10#ifdef KDTREE_DEFINE_OSTREAM_OPERATORS
11# include <ostream>
12#endif
13
14#include <cstddef>
15#include <cmath>
16
17namespace KDTree
18{
19 struct _Node_base
20 {
21 typedef _Node_base* _Base_ptr;
22 typedef _Node_base const* _Base_const_ptr;
23
24 _Base_ptr _M_parent;
25 _Base_ptr _M_left;
26 _Base_ptr _M_right;
27
28 _Node_base(_Base_ptr const __PARENT = NULL,
29 _Base_ptr const __LEFT = NULL,
30 _Base_ptr const __RIGHT = NULL)
31 : _M_parent(__PARENT), _M_left(__LEFT), _M_right(__RIGHT) {}
32
33 static _Base_ptr
34 _S_minimum(_Base_ptr __x)
35 {
36 while (__x->_M_left) __x = __x->_M_left;
37 return __x;
38 }
39
40 static _Base_ptr
41 _S_maximum(_Base_ptr __x)
42 {
43 while (__x->_M_right) __x = __x->_M_right;
44 return __x;
45 }
46 };
47
48 template <typename _Val>
49 struct _Node : public _Node_base
50 {
51 using _Node_base::_Base_ptr;
52 typedef _Node* _Link_type;
53
54 _Val _M_value;
55
56 _Node(_Val const& __VALUE = _Val(),
57 _Base_ptr const __PARENT = NULL,
58 _Base_ptr const __LEFT = NULL,
59 _Base_ptr const __RIGHT = NULL)
60 : _Node_base(__PARENT, __LEFT, __RIGHT), _M_value(__VALUE) {}
61
62#ifdef KDTREE_DEFINE_OSTREAM_OPERATORS
63
64 template <typename Char, typename Traits>
65 friend
66 std::basic_ostream<Char, Traits>&
67 operator<<(typename std::basic_ostream<Char, Traits>& out,
68 _Node_base const& node)
69 {
70 out << &node;
71 out << " parent: " << node._M_parent;
72 out << "; left: " << node._M_left;
73 out << "; right: " << node._M_right;
74 return out;
75 }
76
77 template <typename Char, typename Traits>
78 friend
79 std::basic_ostream<Char, Traits>&
80 operator<<(typename std::basic_ostream<Char, Traits>& out,
81 _Node<_Val> const& node)
82 {
83 out << &node;
84 out << ' ' << node._M_value;
85 out << "; parent: " << node._M_parent;
86 out << "; left: " << node._M_left;
87 out << "; right: " << node._M_right;
88 return out;
89 }
90
91#endif
92 };
93
94 template <typename _Val, typename _Acc, typename _Cmp>
95 class _Node_compare
96 {
97 public:
98 _Node_compare(size_t const __DIM, _Acc const& acc, _Cmp const& cmp)
99 : _M_DIM(__DIM), _M_acc(acc), _M_cmp(cmp) {}
100
101 bool
102 operator()(_Val const& __A, _Val const& __B) const
103 {
104 return _M_cmp(_M_acc(__A, _M_DIM), _M_acc(__B, _M_DIM));
105 }
106
107 private:
108 size_t _M_DIM; // don't make this const so that an assignment operator can be auto-generated
109 _Acc _M_acc;
110 _Cmp _M_cmp;
111 };
112
119 template <typename _ValA, typename _ValB, typename _Cmp,
120 typename _Acc>
121 inline
122 bool
123 _S_node_compare (const size_t __dim,
124 const _Cmp& __cmp, const _Acc& __acc,
125 const _ValA& __a, const _ValB& __b)
126 {
127 return __cmp(__acc(__a, __dim), __acc(__b, __dim));
128 }
129
135 template <typename _ValA, typename _ValB, typename _Dist,
136 typename _Acc>
137 inline
138 typename _Dist::distance_type
139 _S_node_distance (const size_t __dim,
140 const _Dist& __dist, const _Acc& __acc,
141 const _ValA& __a, const _ValB& __b)
142 {
143 return __dist(__acc(__a, __dim), __acc(__b, __dim));
144 }
145
152 template <typename _ValA, typename _ValB, typename _Dist,
153 typename _Acc>
154 inline
155 typename _Dist::distance_type
156 _S_accumulate_node_distance (const size_t __dim,
157 const _Dist& __dist, const _Acc& __acc,
158 const _ValA& __a, const _ValB& __b)
159 {
160 typename _Dist::distance_type d = 0;
161 for (size_t i=0; i<__dim; ++i)
162 d += __dist(__acc(__a, i), __acc(__b, i));
163 return d;
164 }
165
171 template <typename _Val, typename _Cmp, typename _Acc>
172 inline
173 _Node_base*
174 _S_node_descend (const size_t __dim,
175 const _Cmp& __cmp, const _Acc& __acc,
176 const _Val& __val, const _Node_base* __node)
177 {
178 if (_S_node_compare(__dim, __cmp, __acc, __val, static_cast<const _Node<_Val>* >(__node)->_M_value))
179 return __node->_M_left;
180 else
181 return __node->_M_right;
182 }
183
192 template <class SearchVal,
193 typename _Val, typename _Cmp,
194 typename _Acc, typename _Dist,
195 typename _Predicate>
196 inline
197 std::pair<const _Node<_Val>*,
198 std::pair<size_t, typename _Dist::distance_type> >
199 _S_node_nearest (const size_t __k, size_t __dim, SearchVal const& __val,
200 const _Node<_Val>* __node, const _Node_base* __end,
201 const _Node<_Val>* __best, typename _Dist::distance_type __max,
202 const _Cmp& __cmp, const _Acc& __acc, const _Dist& __dist,
203 _Predicate __p)
204 {
205 const _Node_base* pcur = __node;
206 const _Node_base* cur = _S_node_descend(__dim % __k, __cmp, __acc, __val, __node);
207 size_t cur_dim = __dim+1;
208 // find the smallest __max distance in direct descent
209 while (cur)
210 {
211 if (__p(static_cast<const _Node<_Val>* >(cur)->_M_value))
212 {
213 typename _Dist::distance_type d = 0;
214 for (size_t i=0; i != __k; ++i)
215 d += _S_node_distance(i, __dist, __acc, __val, static_cast<const _Node<_Val>* >(cur)->_M_value);
216 d = sqrt(d);
217 if (d <= __max)
218 // ("bad candidate notes")
219 // Changed: removed this test: || ( d == __max && cur < __best ))
220 // Can't do this optimisation without checking that the current 'best' is not the root AND is not a valid candidate...
221 // This is because find_nearest() etc will call this function with the best set to _M_root EVEN IF _M_root is not a valid answer (eg too far away or doesn't pass the predicate test)
222 {
223 __best = static_cast<const _Node<_Val>* >(cur);
224 __max = d;
225 __dim = cur_dim;
226 }
227 }
228 pcur = cur;
229 cur = _S_node_descend(cur_dim % __k, __cmp, __acc, __val, cur);
230 ++cur_dim;
231 }
232 // Swap cur to prev, only prev is a valid node.
233 cur = pcur;
234 --cur_dim;
235 pcur = NULL;
236 // Probe all node's children not visited yet (siblings of the visited nodes).
237 const _Node_base* probe = cur;
238 const _Node_base* pprobe = probe;
239 const _Node_base* near_node;
240 const _Node_base* far_node;
241 size_t probe_dim = cur_dim;
242 if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value))
243 near_node = probe->_M_right;
244 else
245 near_node = probe->_M_left;
246 if (near_node
247 // only visit node's children if node's plane intersect hypersphere
248 && (sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value)) <= __max))
249 {
250 probe = near_node;
251 ++probe_dim;
252 }
253 while (cur != __end)
254 {
255 while (probe != cur)
256 {
257 if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value))
258 {
259 near_node = probe->_M_left;
260 far_node = probe->_M_right;
261 }
262 else
263 {
264 near_node = probe->_M_right;
265 far_node = probe->_M_left;
266 }
267 if (pprobe == probe->_M_parent) // going downward ...
268 {
269 if (__p(static_cast<const _Node<_Val>* >(probe)->_M_value))
270 {
271 typename _Dist::distance_type d = 0;
272 for (size_t i=0; i < __k; ++i)
273 d += _S_node_distance(i, __dist, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value);
274 d = sqrt(d);
275 if (d <= __max) // CHANGED, see the above notes ("bad candidate notes")
276 {
277 __best = static_cast<const _Node<_Val>* >(probe);
278 __max = d;
279 __dim = probe_dim;
280 }
281 }
282 pprobe = probe;
283 if (near_node)
284 {
285 probe = near_node;
286 ++probe_dim;
287 }
288 else if (far_node &&
289 // only visit node's children if node's plane intersect hypersphere
290 sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value)) <= __max)
291 {
292 probe = far_node;
293 ++probe_dim;
294 }
295 else
296 {
297 probe = probe->_M_parent;
298 --probe_dim;
299 }
300 }
301 else // ... and going upward.
302 {
303 if (pprobe == near_node && far_node
304 // only visit node's children if node's plane intersect hypersphere
305 && sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast<const _Node<_Val>* >(probe)->_M_value)) <= __max)
306 {
307 pprobe = probe;
308 probe = far_node;
309 ++probe_dim;
310 }
311 else
312 {
313 pprobe = probe;
314 probe = probe->_M_parent;
315 --probe_dim;
316 }
317 }
318 }
319 pcur = cur;
320 cur = cur->_M_parent;
321 --cur_dim;
322 pprobe = cur;
323 probe = cur;
324 probe_dim = cur_dim;
325 if (cur != __end)
326 {
327 if (pcur == cur->_M_left)
328 near_node = cur->_M_right;
329 else
330 near_node = cur->_M_left;
331 if (near_node
332 // only visit node's children if node's plane intersect hypersphere
333 && (sqrt(_S_node_distance(cur_dim % __k, __dist, __acc, __val, static_cast<const _Node<_Val>* >(cur)->_M_value)) <= __max))
334 {
335 probe = near_node;
336 ++probe_dim;
337 }
338 }
339 }
340 return std::pair<const _Node<_Val>*,
341 std::pair<size_t, typename _Dist::distance_type> >
342 (__best, std::pair<size_t, typename _Dist::distance_type>
343 (__dim, __max));
344 }
345
346
347} // namespace KDTree
348
349#endif // include guard
350
351/* COPYRIGHT --
352 *
353 * This file is part of libkdtree++, a C++ template KD-Tree sorting container.
354 * libkdtree++ is (c) 2004-2007 Martin F. Krafft <libkdtree@pobox.madduck.net>
355 * and Sylvain Bougerel <sylvain.bougerel.devel@gmail.com> distributed under the
356 * terms of the Artistic License 2.0. See the ./COPYING file in the source tree
357 * root for more information.
358 *
359 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
360 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
361 * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
362 */
std::pair< const _Node< _Val > *, std::pair< size_t, typename _Dist::distance_type > > _S_node_nearest(const size_t __k, size_t __dim, SearchVal const &__val, const _Node< _Val > *__node, const _Node_base *__end, const _Node< _Val > *__best, typename _Dist::distance_type __max, const _Cmp &__cmp, const _Acc &__acc, const _Dist &__dist, _Predicate __p)
Definition node.hpp:199
bool _S_node_compare(const size_t __dim, const _Cmp &__cmp, const _Acc &__acc, const _ValA &__a, const _ValB &__b)
Definition node.hpp:123
_Node_base * _S_node_descend(const size_t __dim, const _Cmp &__cmp, const _Acc &__acc, const _Val &__val, const _Node_base *__node)
Definition node.hpp:174
_Dist::distance_type _S_accumulate_node_distance(const size_t __dim, const _Dist &__dist, const _Acc &__acc, const _ValA &__a, const _ValB &__b)
Definition node.hpp:156
_Dist::distance_type _S_node_distance(const size_t __dim, const _Dist &__dist, const _Acc &__acc, const _ValA &__a, const _ValB &__b)
Definition node.hpp:139
Definition node.hpp:20
Definition node.hpp:50