| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef INCLUDE_KDTREE_NODE_HPP |
| | #define INCLUDE_KDTREE_NODE_HPP |
| |
|
| | #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS |
| | # include <ostream> |
| | #endif |
| |
|
| | #include <cstddef> |
| | #include <cmath> |
| |
|
| | namespace KDTree |
| | { |
| | struct _Node_base |
| | { |
| | typedef _Node_base* _Base_ptr; |
| | typedef _Node_base const* _Base_const_ptr; |
| |
|
| | _Base_ptr _M_parent; |
| | _Base_ptr _M_left; |
| | _Base_ptr _M_right; |
| |
|
| | _Node_base(_Base_ptr const __PARENT = NULL, |
| | _Base_ptr const __LEFT = NULL, |
| | _Base_ptr const __RIGHT = NULL) |
| | : _M_parent(__PARENT), _M_left(__LEFT), _M_right(__RIGHT) {} |
| |
|
| | static _Base_ptr |
| | _S_minimum(_Base_ptr __x) |
| | { |
| | while (__x->_M_left) __x = __x->_M_left; |
| | return __x; |
| | } |
| |
|
| | static _Base_ptr |
| | _S_maximum(_Base_ptr __x) |
| | { |
| | while (__x->_M_right) __x = __x->_M_right; |
| | return __x; |
| | } |
| |
|
| | #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS |
| | template <typename Char, typename Traits> |
| | friend |
| | std::basic_ostream<Char, Traits>& |
| | operator<<(typename std::basic_ostream<Char, Traits>& out, |
| | _Node_base const& node) |
| | { |
| | out << &node; |
| | out << " parent: " << node._M_parent; |
| | out << "; left: " << node._M_left; |
| | out << "; right: " << node._M_right; |
| | return out; |
| | } |
| | #endif |
| | }; |
| |
|
| | template <typename _Val> |
| | struct _Node : public _Node_base |
| | { |
| | using _Node_base::_Base_ptr; |
| | typedef _Node* _Link_type; |
| |
|
| | _Val _M_value; |
| |
|
| | _Node(_Val const& __VALUE = _Val(), |
| | _Base_ptr const __PARENT = NULL, |
| | _Base_ptr const __LEFT = NULL, |
| | _Base_ptr const __RIGHT = NULL) |
| | : _Node_base(__PARENT, __LEFT, __RIGHT), _M_value(__VALUE) {} |
| |
|
| | #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS |
| | template <typename Char, typename Traits> |
| | friend |
| | std::basic_ostream<Char, Traits>& |
| | operator<<(typename std::basic_ostream<Char, Traits>& out, |
| | _Node<_Val> const& node) |
| | { |
| | out << &node; |
| | out << ' ' << node._M_value; |
| | out << "; parent: " << node._M_parent; |
| | out << "; left: " << node._M_left; |
| | out << "; right: " << node._M_right; |
| | return out; |
| | } |
| | #endif |
| | }; |
| |
|
| | template <typename _Val, typename _Acc, typename _Cmp> |
| | class _Node_compare |
| | { |
| | public: |
| | _Node_compare(size_t const __DIM, _Acc const& acc, _Cmp const& cmp) |
| | : _M_DIM(__DIM), _M_acc(acc), _M_cmp(cmp) {} |
| |
|
| | bool |
| | operator()(_Val const& __A, _Val const& __B) const |
| | { |
| | return _M_cmp(_M_acc(__A, _M_DIM), _M_acc(__B, _M_DIM)); |
| | } |
| |
|
| | private: |
| | size_t _M_DIM; |
| | _Acc _M_acc; |
| | _Cmp _M_cmp; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | template <typename _ValA, typename _ValB, typename _Cmp, |
| | typename _Acc> |
| | inline |
| | bool |
| | _S_node_compare (const size_t __dim, |
| | const _Cmp& __cmp, const _Acc& __acc, |
| | const _ValA& __a, const _ValB& __b) |
| | { |
| | return __cmp(__acc(__a, __dim), __acc(__b, __dim)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | template <typename _ValA, typename _ValB, typename _Dist, |
| | typename _Acc> |
| | inline |
| | typename _Dist::distance_type |
| | _S_node_distance (const size_t __dim, |
| | const _Dist& __dist, const _Acc& __acc, |
| | const _ValA& __a, const _ValB& __b) |
| | { |
| | return __dist(__acc(__a, __dim), __acc(__b, __dim)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | template <typename _ValA, typename _ValB, typename _Dist, |
| | typename _Acc> |
| | inline |
| | typename _Dist::distance_type |
| | _S_accumulate_node_distance (const size_t __dim, |
| | const _Dist& __dist, const _Acc& __acc, |
| | const _ValA& __a, const _ValB& __b) |
| | { |
| | typename _Dist::distance_type d = 0; |
| | for (size_t i=0; i<__dim; ++i) |
| | d += __dist(__acc(__a, i), __acc(__b, i)); |
| | return d; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | template <typename _Val, typename _Cmp, typename _Acc, typename NodeType> |
| | inline |
| | const NodeType* |
| | _S_node_descend (const size_t __dim, |
| | const _Cmp& __cmp, const _Acc& __acc, |
| | const _Val& __val, const NodeType* __node) |
| | { |
| | if (_S_node_compare(__dim, __cmp, __acc, __val, __node->_M_value)) |
| | return static_cast<const NodeType *>(__node->_M_left); |
| | return static_cast<const NodeType *>(__node->_M_right); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | template <class SearchVal, |
| | typename NodeType, typename _Cmp, |
| | typename _Acc, typename _Dist, |
| | typename _Predicate> |
| | inline |
| | std::pair<const NodeType*, |
| | std::pair<size_t, typename _Dist::distance_type> > |
| | _S_node_nearest (const size_t __k, size_t __dim, SearchVal const& __val, |
| | const NodeType* __node, const _Node_base* __end, |
| | const NodeType* __best, typename _Dist::distance_type __max, |
| | const _Cmp& __cmp, const _Acc& __acc, const _Dist& __dist, |
| | _Predicate __p) |
| | { |
| | typedef const NodeType* NodePtr; |
| | NodePtr pcur = __node; |
| | NodePtr cur = _S_node_descend(__dim % __k, __cmp, __acc, __val, __node); |
| | size_t cur_dim = __dim+1; |
| | |
| | while (cur) |
| | { |
| | if (__p(cur->_M_value)) |
| | { |
| | typename _Dist::distance_type d = 0; |
| | for (size_t i=0; i != __k; ++i) |
| | d += _S_node_distance(i, __dist, __acc, __val, cur->_M_value); |
| | d = std::sqrt(d); |
| | if (d <= __max) |
| | |
| | |
| | |
| | |
| | { |
| | __best = cur; |
| | __max = d; |
| | __dim = cur_dim; |
| | } |
| | } |
| | pcur = cur; |
| | cur = _S_node_descend(cur_dim % __k, __cmp, __acc, __val, cur); |
| | ++cur_dim; |
| | } |
| | |
| | cur = pcur; |
| | --cur_dim; |
| | pcur = NULL; |
| | |
| | NodePtr probe = cur; |
| | NodePtr pprobe = probe; |
| | NodePtr near_node; |
| | NodePtr far_node; |
| | size_t probe_dim = cur_dim; |
| | if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, probe->_M_value)) |
| | near_node = static_cast<NodePtr>(probe->_M_right); |
| | else |
| | near_node = static_cast<NodePtr>(probe->_M_left); |
| | if (near_node |
| | |
| | && (std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max)) |
| | { |
| | probe = near_node; |
| | ++probe_dim; |
| | } |
| | while (cur != __end) |
| | { |
| | while (probe != cur) |
| | { |
| | if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, probe->_M_value)) |
| | { |
| | near_node = static_cast<NodePtr>(probe->_M_left); |
| | far_node = static_cast<NodePtr>(probe->_M_right); |
| | } |
| | else |
| | { |
| | near_node = static_cast<NodePtr>(probe->_M_right); |
| | far_node = static_cast<NodePtr>(probe->_M_left); |
| | } |
| | if (pprobe == probe->_M_parent) |
| | { |
| | if (__p(probe->_M_value)) |
| | { |
| | typename _Dist::distance_type d = 0; |
| | for (size_t i=0; i < __k; ++i) |
| | d += _S_node_distance(i, __dist, __acc, __val, probe->_M_value); |
| | d = std::sqrt(d); |
| | if (d <= __max) |
| | { |
| | __best = probe; |
| | __max = d; |
| | __dim = probe_dim; |
| | } |
| | } |
| | pprobe = probe; |
| | if (near_node) |
| | { |
| | probe = near_node; |
| | ++probe_dim; |
| | } |
| | else if (far_node && |
| | |
| | std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max) |
| | { |
| | probe = far_node; |
| | ++probe_dim; |
| | } |
| | else |
| | { |
| | probe = static_cast<NodePtr>(probe->_M_parent); |
| | --probe_dim; |
| | } |
| | } |
| | else |
| | { |
| | if (pprobe == near_node && far_node |
| | |
| | && std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max) |
| | { |
| | pprobe = probe; |
| | probe = far_node; |
| | ++probe_dim; |
| | } |
| | else |
| | { |
| | pprobe = probe; |
| | probe = static_cast<NodePtr>(probe->_M_parent); |
| | --probe_dim; |
| | } |
| | } |
| | } |
| | pcur = cur; |
| | cur = static_cast<NodePtr>(cur->_M_parent); |
| | --cur_dim; |
| | pprobe = cur; |
| | probe = cur; |
| | probe_dim = cur_dim; |
| | if (cur != __end) |
| | { |
| | if (pcur == cur->_M_left) |
| | near_node = static_cast<NodePtr>(cur->_M_right); |
| | else |
| | near_node = static_cast<NodePtr>(cur->_M_left); |
| | if (near_node |
| | |
| | && (std::sqrt(_S_node_distance(cur_dim % __k, __dist, __acc, __val, cur->_M_value)) <= __max)) |
| | { |
| | probe = near_node; |
| | ++probe_dim; |
| | } |
| | } |
| | } |
| | return std::pair<NodePtr, |
| | std::pair<size_t, typename _Dist::distance_type> > |
| | (__best, std::pair<size_t, typename _Dist::distance_type> |
| | (__dim, __max)); |
| | } |
| |
|
| |
|
| | } |
| |
|
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|