diff --git a/src/3rdParty/libkdtree/README b/src/3rdParty/libkdtree/README.md similarity index 60% rename from src/3rdParty/libkdtree/README rename to src/3rdParty/libkdtree/README.md index 3c015ba61f..b7364c581b 100644 --- a/src/3rdParty/libkdtree/README +++ b/src/3rdParty/libkdtree/README.md @@ -1,14 +1,5 @@ -libkdtree++ README -================== - -libkdtree++ is (c) 2004-2007 Martin F. Krafft -and distributed under the terms of the Artistic License 2.0. -See the file LICENSE in the source distribution for more information. - -Please send bugreports to . - -Introduction ------------- +libkdtree++ +=========== libkdtree++ is a C++ template container implementation of k-dimensional space sorting, using a kd-tree. It: @@ -16,34 +7,108 @@ sorting, using a kd-tree. It: - sports an unlimited number of dimensions (in theory) - can store any data structure, access and comparison between the individual dimensional components defaults to the bracket operator, in - the range [0, k-1] and the std::less functor by default, but other + the range `[0, k-1]` and the `std::less` functor by default, but other accessors and comparator can be defined. - has support for custom allocators - implements iterators - provides standard find as well as range queries - - has amortised O(lg n) time (O(n lg n) worst case) on most - operations (insert/erase/find optimised) and worst-case O(n) space. + - has amortised `O(lg n)` time (`O(n lg n)` worst case) on most + operations (insert/erase/find optimised) and worst-case `O(n)` space. - provides a means to rebalance and thus optimise the tree. - exists in its own namespace - - uses STL coding style, basing a lot of the code on stl_tree.h + - uses STL coding style, basing a lot of the code on `stl_tree.h` -Notes +Please leave bugreports on Github Issues page . + + +Historical background +--------------------- + +In the past, this library was available from . +This page seems to be gone now, available only via WebArchive. +This is a mirror and a fork of that original repository, created in +2011 and maintained ever since. + +Notes of the original author a preserved below. + +Installation +------------ + +As there is no need to compile any files, you can just: + +```sh +$ ./configure +$ sudo make install +``` + + +It now also supports cmake, which can be used to build the examples +and tests. +To build with cmake: + +```sh +$ mkdir build +$ cd build +$ cmake .. +$ make +``` + +You can use cmake to build the tests and examples on Windows with +Visual C++. Use the windows cmake to create a Visual C++ solution and +build that. + +Note that `cmake` and `./configure` is not needed at all in order to use +kdtree in your application. As libkdtree++ is a header-only library, you +just need to #include the `kdtree.hpp`. + +Read the following to make use of the library. + +Usage ----- +A simple example program is provided in the `./examples` directory +(`/usr/share/doc/libkdtree++-dev/examples` on Debian). + +For those using the ./configure system, the library supports pkg-config. +Thus, to compile with the library, + +```c++ +#include +``` + +and append the output of `pkg-config libkdtree++ --cflags` to your `$CPPFLAGS`. + +Each call to `erase()` and `insert()` unbalances the tree. It is possible that +nodes will not be found while the tree is unbalanced. You rebalance the +tree by calling `optimize()`, and you should call it before you need to search +the tree (this includes `erase(value)` calls, which search the tree). + +It is ok to call `insert(value)` many times and `optimize()` at the end, but +every `erase()` call should be followed with `optimize()`. + + +Notes (Martin F. Kraft) +----------------------- + Note that the library is not (yet) complete and it's not thoroughly tested. However, given the effort and grief I went through in writing it, I would like to make it available to folks, get people to test it, and hopefully have -some peeps submit improvements. If you have any suggestions, please write to -libkdtree-devel@lists.alioth.debian.org . +some peeps submit improvements. If you have any suggestions, please create an +issue on Github Issue page . It's not yet documented, although the usage should be fairly straight forward. I am hoping to find someone else to document it as I suck at documentation and as the author, it's exceptionally difficult to stay didactically correct. + Credits (Martin F. Kraft) ------------------------- +libkdtree++ is (c) 2004-2007 Martin F. Krafft +and distributed under the terms of the Artistic License 2.0. +See the file LICENSE in the source distribution for more information. + While the library was written all by myself, it would not have been possible without the help of a number of people. Foremost, I would like to thank the folks from the #c++ channel on Freenode, specifically (in no particular order) @@ -54,68 +119,8 @@ Gabriel G Since libkdtree++ makes an effort to stay as close as possible to the feel of a STL container, concepts and inspiration was gained from the SGI C++ -implementation of red-black trees (stl_tree.h). +implementation of red-black trees (`stl_tree.h`). I also have to thank the Debian project for providing an amazingly reliable and flexible developer station with their operating system. I am sorry for everyone who has to use something else. - -Installation ------------- - -As there is no need to compile any files, you can just: - -$ ./configure -$ sudo make install - - -It now also supports cmake, which can be used to build the examples -and tests. -To build with cmake, do an out-of-source build like so: - -# ASSUMING you have decompressed it into a directory called libkdtree, -# and you are currently in that directory... - -$ cd .. # go up, out of the kdtree source directory -$ mkdir build -$ cd build -$ cmake ../libkdtree -$ make - - -You can use cmake to build the tests and examples on Windows with -Visual C++. Use the windows cmake to create a Visual C++ solution and -build that. - -Note that cmake and ./configure is not needed at all in order to use -kdtree in your application. As kdtree is a header-only library, you -just need to #include the kdtree.hpp - - -Read the following to make use of the library. - -Usage ------ - -A simple example program is provided in the ./examples directory -(/usr/share/doc/libkdtree++-dev/examples on Debian). - -For those using the ./configure system, the library supports pkg-config. -Thus, to compile with the library, - - #include - -and append the output of `pkg-config libkdtree++ --cflags` to your $CPPFLAGS. - -Each call to erase() and insert() unbalances the tree. It is possible that -nodes will not be found while the tree is unbalanced. You rebalance the -tree by calling optimize(), and you should call it before you need to search -the tree (this includes erase(value) calls, which search the tree). - -It is ok to call insert(value) many times and optimize() at the end, but -every erase() call should be followed with optimize(). - -These notes are a bit out of date, please check the webpage and mailing list -for more info. Documentation is on the TODO list. - -Have fun. diff --git a/src/3rdParty/libkdtree/examples/test_kdtree.cpp b/src/3rdParty/libkdtree/examples/test_kdtree.cpp index d62ac970e5..4bbd9a2e4e 100644 --- a/src/3rdParty/libkdtree/examples/test_kdtree.cpp +++ b/src/3rdParty/libkdtree/examples/test_kdtree.cpp @@ -17,7 +17,7 @@ std::set registered; struct triplet { - typedef int value_type; + typedef double value_type; triplet(value_type a, value_type b, value_type c) { @@ -26,7 +26,8 @@ struct triplet d[2] = c; bool reg_ok = (registered.find(this) == registered.end()); assert(reg_ok); - registered.insert(this).second; + bool reg_inserted_ok = registered.insert(this).second; + assert(reg_inserted_ok); } triplet(const triplet & x) @@ -36,7 +37,8 @@ struct triplet d[2] = x.d[2]; bool reg_ok = (registered.find(this) == registered.end()); assert(reg_ok); - registered.insert(this).second; + bool reg_inserted_ok = registered.insert(this).second; + assert(reg_inserted_ok); } ~triplet() @@ -64,7 +66,7 @@ struct triplet // same as triplet, except with the values reversed. struct alternate_triplet { - typedef int value_type; + typedef double value_type; alternate_triplet(const triplet & x) { @@ -228,8 +230,7 @@ int main() tree_type copied(src); std::cout << copied << std::endl; - tree_type assigned; - assigned = src; + tree_type assigned = src; std::cout << assigned << std::endl; for (int loop = 0; loop != 4; ++loop) diff --git a/src/3rdParty/libkdtree/kdtree++/allocator.hpp b/src/3rdParty/libkdtree/kdtree++/allocator.hpp index 9c6e098f7c..560f4c768b 100644 --- a/src/3rdParty/libkdtree/kdtree++/allocator.hpp +++ b/src/3rdParty/libkdtree/kdtree++/allocator.hpp @@ -41,7 +41,7 @@ namespace KDTree NoLeakAlloc(_Alloc_base * b) : base(b), new_node(base->_M_allocate_node()) {} _Node_ * get() { return new_node; } - void disconnect() { new_node = nullptr; } + void disconnect() { new_node = NULL; } ~NoLeakAlloc() { if (new_node) base->_M_deallocate_node(new_node); } }; @@ -74,7 +74,11 @@ namespace KDTree void _M_destroy_node(_Node_* __p) { +#if __cplusplus >= 201703L + std::allocator_traits::destroy(_M_node_allocator,__p); +#else _M_node_allocator.destroy(__p); +#endif } }; diff --git a/src/3rdParty/libkdtree/kdtree++/iterator.hpp b/src/3rdParty/libkdtree/kdtree++/iterator.hpp index 22dc5861fe..4b24ea1a95 100644 --- a/src/3rdParty/libkdtree/kdtree++/iterator.hpp +++ b/src/3rdParty/libkdtree/kdtree++/iterator.hpp @@ -9,7 +9,7 @@ #include -#include +#include "node.hpp" namespace KDTree { @@ -52,10 +52,10 @@ namespace KDTree typedef _Node_base::_Base_const_ptr _Base_const_ptr; _Base_const_ptr _M_node; - inline _Base_iterator(_Base_const_ptr const __N = nullptr) + inline _Base_iterator(_Base_const_ptr const __N = NULL) : _M_node(__N) {} - //inline _Base_iterator(_Base_iterator const& __THAT) - // : _M_node(__THAT._M_node) {} + inline _Base_iterator(_Base_iterator const& __THAT) + : _M_node(__THAT._M_node) {} inline void _M_increment() @@ -205,37 +205,37 @@ namespace KDTree }; template - inline bool + bool operator==(_Iterator<_Val, _Ref, _Ptr> const& __X, _Iterator<_Val, _Ref, _Ptr> const& __Y) { return __X._M_node == __Y._M_node; } template - inline bool + bool operator==(_Iterator<_Val, const _Val&, const _Val*> const& __X, _Iterator<_Val, _Val&, _Val*> const& __Y) { return __X._M_node == __Y._M_node; } template - inline bool + bool operator==(_Iterator<_Val, _Val&, _Val*> const& __X, _Iterator<_Val, const _Val&, const _Val*> const& __Y) { return __X._M_node == __Y._M_node; } template - inline bool + bool operator!=(_Iterator<_Val, _Ref, _Ptr> const& __X, _Iterator<_Val, _Ref, _Ptr> const& __Y) { return __X._M_node != __Y._M_node; } template - inline bool + bool operator!=(_Iterator<_Val, const _Val&, const _Val*> const& __X, _Iterator<_Val, _Val&, _Val*> const& __Y) { return __X._M_node != __Y._M_node; } template - inline bool + bool operator!=(_Iterator<_Val, _Val&, _Val*> const& __X, _Iterator<_Val, const _Val&, const _Val*> const& __Y) { return __X._M_node != __Y._M_node; } diff --git a/src/3rdParty/libkdtree/kdtree++/kdtree.hpp b/src/3rdParty/libkdtree/kdtree++/kdtree.hpp index d86d763694..27a41a28bf 100644 --- a/src/3rdParty/libkdtree/kdtree++/kdtree.hpp +++ b/src/3rdParty/libkdtree/kdtree++/kdtree.hpp @@ -48,17 +48,17 @@ // -// This number is guaranteed to change with every release. +// This number is guarenteed to change with every release. // // KDTREE_VERSION % 100 is the patch level // KDTREE_VERSION / 100 % 1000 is the minor version // KDTREE_VERSION / 100000 is the major version -#define KDTREE_VERSION 700 +#define KDTREE_VERSION 702 // // KDTREE_LIB_VERSION must be defined to be the same as KDTREE_VERSION // but as a *string* in the form "x_y[_z]" where x is the major version // number, y is the minor version number, and z is the patch level if not 0. -#define KDTREE_LIB_VERSION "0_7_0" +#define KDTREE_LIB_VERSION "0_7_2" #include @@ -67,6 +67,7 @@ # include #endif #include +#include #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS # include @@ -90,1142 +91,1148 @@ namespace KDTree unsigned long long num_dist_calcs = 0; #endif - template , - typename _Dist = squared_difference, - typename _Cmp = std::less, - typename _Alloc = std::allocator<_Node<_Val> > > - class KDTree : protected _Alloc_base<_Val, _Alloc> - { - protected: - typedef _Alloc_base<_Val, _Alloc> _Base; - typedef typename _Base::allocator_type allocator_type; +template , + typename _Dist = squared_difference, + typename _Cmp = std::less, + typename _Alloc = std::allocator<_Node<_Val> > > +class KDTree : protected _Alloc_base<_Val, _Alloc> +{ +protected: + typedef _Alloc_base<_Val, _Alloc> _Base; + typedef typename _Base::allocator_type allocator_type; - typedef _Node_base* _Base_ptr; - typedef _Node_base const* _Base_const_ptr; - typedef _Node<_Val>* _Link_type; - typedef _Node<_Val> const* _Link_const_type; + typedef _Node_base* _Base_ptr; + typedef _Node_base const* _Base_const_ptr; + typedef _Node<_Val>* _Link_type; + typedef _Node<_Val> const* _Link_const_type; - typedef _Node_compare<_Val, _Acc, _Cmp> _Node_compare_; + typedef _Node_compare<_Val, _Acc, _Cmp> _Node_compare_; - public: - typedef _Region<__K, _Val, typename _Acc::result_type, _Acc, _Cmp> - _Region_; - typedef _Val value_type; - typedef value_type* pointer; - typedef value_type const* const_pointer; - typedef value_type& reference; - typedef value_type const& const_reference; - typedef typename _Acc::result_type subvalue_type; - typedef typename _Dist::distance_type distance_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; +public: + typedef _Region<__K, _Val, typename _Acc::result_type, _Acc, _Cmp> + _Region_; + typedef _Val value_type; + typedef value_type* pointer; + typedef value_type const* const_pointer; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef typename _Acc::result_type subvalue_type; + typedef typename _Dist::distance_type distance_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; - KDTree(_Acc const& __acc = _Acc(), _Dist const& __dist = _Dist(), - _Cmp const& __cmp = _Cmp(), const allocator_type& __a = allocator_type()) - : _Base(__a), _M_header(), - _M_count(0), _M_acc(__acc), _M_cmp(__cmp), _M_dist(__dist) + KDTree(_Acc const& __acc = _Acc(), _Dist const& __dist = _Dist(), + _Cmp const& __cmp = _Cmp(), const allocator_type& __a = allocator_type()) + : _Base(__a), _M_header(), + _M_count(0), _M_acc(__acc), _M_cmp(__cmp), _M_dist(__dist) + { + _M_empty_initialise(); + } + + KDTree(const KDTree& __x) + : _Base(__x.get_allocator()), _M_header(), _M_count(0), + _M_acc(__x._M_acc), _M_cmp(__x._M_cmp), _M_dist(__x._M_dist) + { + _M_empty_initialise(); + // this is slow: + // this->insert(begin(), __x.begin(), __x.end()); + // this->optimise(); + + // this is much faster, as it skips a lot of useless work + // do the optimisation before inserting + // Needs to be stored in a vector first as _M_optimise() + // sorts the data in the passed iterators directly. + std::vector temp; + temp.reserve(__x.size()); + std::copy(__x.begin(),__x.end(),std::back_inserter(temp)); + _M_optimise(temp.begin(), temp.end(), 0); + } + + template + KDTree(_InputIterator __first, _InputIterator __last, + _Acc const& acc = _Acc(), _Dist const& __dist = _Dist(), + _Cmp const& __cmp = _Cmp(), const allocator_type& __a = allocator_type()) + : _Base(__a), _M_header(), _M_count(0), + _M_acc(acc), _M_cmp(__cmp), _M_dist(__dist) + { + _M_empty_initialise(); + // this is slow: + // this->insert(begin(), __first, __last); + // this->optimise(); + + // this is much faster, as it skips a lot of useless work + // do the optimisation before inserting + // Needs to be stored in a vector first as _M_optimise() + // sorts the data in the passed iterators directly. + std::vector temp; + temp.reserve(std::distance(__first,__last)); + std::copy(__first,__last,std::back_inserter(temp)); + _M_optimise(temp.begin(), temp.end(), 0); + + // NOTE: this will BREAK users that are passing in + // read-once data via the iterator... + // We increment __first all the way to __last once within + // the distance() call, and again within the copy() call. + // + // This should end up using some funky C++ concepts or + // type traits to check that the iterators can be used in this way... + } + + + // this will CLEAR the tree and fill it with the contents + // of 'writable_vector'. it will use the passed vector directly, + // and will basically resort the vector many times over while + // optimising the tree. + // + // Paul: I use this when I have already built up a vector of data + // that I want to add, and I don't mind if its contents get shuffled + // by the kdtree optimise routine. + void efficient_replace_and_optimise( std::vector & writable_vector ) + { + this->clear(); + _M_optimise(writable_vector.begin(), writable_vector.end(), 0); + } + + + + KDTree& + operator=(const KDTree& __x) + { + if (this != &__x) + { + _M_acc = __x._M_acc; + _M_dist = __x._M_dist; + _M_cmp = __x._M_cmp; + // this is slow: + // this->insert(begin(), __x.begin(), __x.end()); + // this->optimise(); + + // this is much faster, as it skips a lot of useless work + // do the optimisation before inserting + // Needs to be stored in a vector first as _M_optimise() + // sorts the data in the passed iterators directly. + std::vector temp; + temp.reserve(__x.size()); + std::copy(__x.begin(),__x.end(),std::back_inserter(temp)); + efficient_replace_and_optimise(temp); + } + return *this; + } + + ~KDTree() + { + this->clear(); + } + + allocator_type + get_allocator() const + { + return _Base::get_allocator(); + } + + size_type + size() const + { + return _M_count; + } + + size_type + max_size() const + { + return size_type(-1); + } + + bool + empty() const + { + return this->size() == 0; + } + + void + clear() + { + _M_erase_subtree(_M_get_root()); + _M_set_leftmost(&_M_header); + _M_set_rightmost(&_M_header); + _M_set_root(NULL); + _M_count = 0; + } + + /*! \brief Comparator for the values in the KDTree. + +The comparator shall not be modified, it could invalidate the tree. +\return a copy of the comparator used by the KDTree. + */ + _Cmp + value_comp() const + { return _M_cmp; } + + /*! \brief Accessor to the value's elements. + +This accessor shall not be modified, it could invalidate the tree. +\return a copy of the accessor used by the KDTree. + */ + _Acc + value_acc() const + { return _M_acc; } + + /*! \brief Distance calculator between 2 value's element. + +This functor can be modified. It's modification will only affect the +behavior of the find and find_nearest functions. +\return a reference to the distance calculator used by the KDTree. + */ + const _Dist& + value_distance() const + { return _M_dist; } + + _Dist& + value_distance() + { return _M_dist; } + + // typedef _Iterator<_Val, reference, pointer> iterator; + typedef _Iterator<_Val, const_reference, const_pointer> const_iterator; + // No mutable iterator at this stage + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + // Note: the static_cast in end() is invalid (_M_header is not convertable to a _Link_type), but + // thats ok as it just means undefined behaviour if the user dereferences the end() iterator. + + const_iterator begin() const { return const_iterator(_M_get_leftmost()); } + const_iterator end() const { return const_iterator(static_cast<_Link_const_type>(&_M_header)); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + iterator + insert(iterator /* ignored */, const_reference __V) + { + return this->insert(__V); + } + + iterator + insert(const_reference __V) + { + if (!_M_get_root()) { - _M_empty_initialise(); + _Link_type __n = _M_new_node(__V, &_M_header); + ++_M_count; + _M_set_root(__n); + _M_set_leftmost(__n); + _M_set_rightmost(__n); + return iterator(__n); } + return _M_insert(_M_get_root(), __V, 0); + } - KDTree(const KDTree& __x) - : _Base(__x.get_allocator()), _M_header(), _M_count(0), - _M_acc(__x._M_acc), _M_cmp(__x._M_cmp), _M_dist(__x._M_dist) - { - _M_empty_initialise(); - // this is slow: - // this->insert(begin(), __x.begin(), __x.end()); - // this->optimise(); + template + void insert(_InputIterator __first, _InputIterator __last) { + for (; __first != __last; ++__first) + this->insert(*__first); + } - // this is much faster, as it skips a lot of useless work - // do the optimisation before inserting - // Needs to be stored in a vector first as _M_optimise() - // sorts the data in the passed iterators directly. - std::vector temp; - temp.reserve(__x.size()); - std::copy(__x.begin(),__x.end(),std::back_inserter(temp)); - _M_optimise(temp.begin(), temp.end(), 0); - } + void + insert(iterator __pos, size_type __n, const value_type& __x) + { + for (; __n > 0; --__n) + this->insert(__pos, __x); + } - template - KDTree(_InputIterator __first, _InputIterator __last, - _Acc const& acc = _Acc(), _Dist const& __dist = _Dist(), - _Cmp const& __cmp = _Cmp(), const allocator_type& __a = allocator_type()) - : _Base(__a), _M_header(), _M_count(0), - _M_acc(acc), _M_cmp(__cmp), _M_dist(__dist) - { - _M_empty_initialise(); - // this is slow: - // this->insert(begin(), __first, __last); - // this->optimise(); + template + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) { + for (; __first != __last; ++__first) + this->insert(__pos, *__first); + } - // this is much faster, as it skips a lot of useless work - // do the optimisation before inserting - // Needs to be stored in a vector first as _M_optimise() - // sorts the data in the passed iterators directly. - std::vector temp; - temp.reserve(std::distance(__first,__last)); - std::copy(__first,__last,std::back_inserter(temp)); - _M_optimise(temp.begin(), temp.end(), 0); + // Note: this uses the find() to location the item you want to erase. + // find() compares by equivalence of location ONLY. See the comments + // above find_exact() for why you may not want this. + // + // If you want to erase ANY item that has the same location as __V, + // then use this function. + // + // If you want to erase a PARTICULAR item, and not any other item + // that might happen to have the same location, then you should use + // erase_exact(). + void + erase(const_reference __V) { + const_iterator b = this->find(__V); + this->erase(b); + } - // NOTE: this will BREAK users that are passing in - // read-once data via the iterator... - // We increment __first all the way to __last once within - // the distance() call, and again within the copy() call. - // - // This should end up using some funky C++ concepts or - // type traits to check that the iterators can be used in this way... - } + void + erase_exact(const_reference __V) { + this->erase(this->find_exact(__V)); + } - - // this will CLEAR the tree and fill it with the contents - // of 'writable_vector'. it will use the passed vector directly, - // and will basically resort the vector many times over while - // optimising the tree. - // - // Paul: I use this when I have already built up a vector of data - // that I want to add, and I don't mind if its contents get shuffled - // by the kdtree optimise routine. - void efficient_replace_and_optimise( std::vector & writable_vector ) - { - this->clear(); - _M_optimise(writable_vector.begin(), writable_vector.end(), 0); - } - - - - KDTree& - operator=(const KDTree& __x) - { - if (this != &__x) - { - _M_acc = __x._M_acc; - _M_dist = __x._M_dist; - _M_cmp = __x._M_cmp; - // this is slow: - // this->insert(begin(), __x.begin(), __x.end()); - // this->optimise(); - - // this is much faster, as it skips a lot of useless work - // do the optimisation before inserting - // Needs to be stored in a vector first as _M_optimise() - // sorts the data in the passed iterators directly. - std::vector temp; - temp.reserve(__x.size()); - std::copy(__x.begin(),__x.end(),std::back_inserter(temp)); - efficient_replace_and_optimise(temp); - } - return *this; - } - - ~KDTree() - { - this->clear(); - } - - allocator_type - get_allocator() const - { - return _Base::get_allocator(); - } - - size_type - size() const - { - return _M_count; - } - - size_type - max_size() const - { - return size_type(-1); - } - - bool - empty() const - { - return this->size() == 0; - } - - void - clear() - { - _M_erase_subtree(_M_get_root()); - _M_set_leftmost(&_M_header); - _M_set_rightmost(&_M_header); - _M_set_root(nullptr); - _M_count = 0; - } - - /*! \brief Comparator for the values in the KDTree. - - The comparator shall not be modified, it could invalidate the tree. - \return a copy of the comparator used by the KDTree. - */ - _Cmp - value_comp() const - { return _M_cmp; } - - /*! \brief Accessor to the value's elements. - - This accessor shall not be modified, it could invalidate the tree. - \return a copy of the accessor used by the KDTree. - */ - _Acc - value_acc() const - { return _M_acc; } - - /*! \brief Distance calculator between 2 value's element. - - This functor can be modified. It's modification will only affect the - behavior of the find and find_nearest functions. - \return a reference to the distance calculator used by the KDTree. - */ - const _Dist& - value_distance() const - { return _M_dist; } - - _Dist& - value_distance() - { return _M_dist; } - - // typedef _Iterator<_Val, reference, pointer> iterator; - typedef _Iterator<_Val, const_reference, const_pointer> const_iterator; - // No mutable iterator at this stage - typedef const_iterator iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - - // Note: the static_cast in end() is invalid (_M_header is not convertible to a _Link_type), but - // that's ok as it just means undefined behaviour if the user dereferences the end() iterator. - - const_iterator begin() const { return const_iterator(_M_get_leftmost()); } - const_iterator end() const { return const_iterator(static_cast<_Link_const_type>(&_M_header)); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - - iterator - insert(iterator /* ignored */, const_reference __V) - { - return this->insert(__V); - } - - iterator - insert(const_reference __V) - { - if (!_M_get_root()) - { - _Link_type __n = _M_new_node(__V, &_M_header); - ++_M_count; - _M_set_root(__n); - _M_set_leftmost(__n); - _M_set_rightmost(__n); - return iterator(__n); - } - return _M_insert(_M_get_root(), __V, 0); - } - - template - void insert(_InputIterator __first, _InputIterator __last) { - for (; __first != __last; ++__first) - this->insert(*__first); - } - - void - insert(iterator __pos, size_type __n, const value_type& __x) - { - for (; __n > 0; --__n) - this->insert(__pos, __x); - } - - template - void - insert(iterator __pos, _InputIterator __first, _InputIterator __last) { - for (; __first != __last; ++__first) - this->insert(__pos, *__first); - } - - // Note: this uses the find() to location the item you want to erase. - // find() compares by equivalence of location ONLY. See the comments - // above find_exact() for why you may not want this. - // - // If you want to erase ANY item that has the same location as __V, - // then use this function. - // - // If you want to erase a PARTICULAR item, and not any other item - // that might happen to have the same location, then you should use - // erase_exact(). - void - erase(const_reference __V) { - const_iterator b = this->find(__V); - this->erase(b); - } - - void - erase_exact(const_reference __V) { - this->erase(this->find_exact(__V)); - } - - // note: kept as const because its easier to const-cast it away - void - erase(const_iterator const& __IT) - { - assert(__IT != this->end()); - _Link_const_type target = __IT.get_raw_node(); - _Link_const_type n = target; - size_type level = 0; - while ((n = _S_parent(n)) != &_M_header) - ++level; - _M_erase( const_cast<_Link_type>(target), level ); - _M_delete_node( const_cast<_Link_type>(target) ); - --_M_count; - } + // note: kept as const because its easier to const-cast it away + void + erase(const_iterator const& __IT) + { + assert(__IT != this->end()); + _Link_const_type target = __IT.get_raw_node(); + _Link_const_type n = target; + size_type level = 0; + while ((n = _S_parent(n)) != &_M_header) + ++level; + _M_erase( const_cast<_Link_type>(target), level ); + _M_delete_node( const_cast<_Link_type>(target) ); + --_M_count; + } /* this does not work since erasure changes sort order - void - erase(const_iterator __A, const_iterator const& __B) + void + erase(const_iterator __A, const_iterator const& __B) + { + if (0 && __A == this->begin() && __B == this->end()) { - if (0 && __A == this->begin() && __B == this->end()) - { - this->clear(); - } - else - { - while (__A != __B) - this->erase(__A++); - } + this->clear(); } + else + { + while (__A != __B) + this->erase(__A++); + } + } */ - // compares via equivalence - // so if you are looking for any item with the same location, - // according to the standard accessor comparisons, - // then this is the function for you. - template - const_iterator - find(SearchVal const& __V) const + // compares via equivalence + // so if you are looking for any item with the same location, + // according to the standard accessor comparisions, + // then this is the function for you. + template + const_iterator + find(SearchVal const& __V) const + { + if (!_M_get_root()) return this->end(); + return _M_find(_M_get_root(), __V, 0); + } + + // compares via equality + // if you are looking for a particular item in the tree, + // and (for example) it has an ID that is checked via an == comparison + // eg + // struct Item + // { + // size_type unique_id; + // bool operator==(Item const& a, Item const& b) { return a.unique_id == b.unique_id; } + // Location location; + // }; + // Two items may be equivalent in location. find() would return + // either one of them. But no two items have the same ID, so + // find_exact() would always return the item with the same location AND id. + // + template + const_iterator + find_exact(SearchVal const& __V) const + { + if (!_M_get_root()) return this->end(); + return _M_find_exact(_M_get_root(), __V, 0); + } + + // NOTE: see notes on find_within_range(). + size_type + count_within_range(const_reference __V, subvalue_type const __R) const + { + if (!_M_get_root()) return 0; + _Region_ __region(__V, __R, _M_acc, _M_cmp); + return this->count_within_range(__region); + } + + size_type + count_within_range(_Region_ const& __REGION) const + { + if (!_M_get_root()) return 0; + + _Region_ __bounds(__REGION); + return _M_count_within_range(_M_get_root(), + __REGION, __bounds, 0); + } + + // NOTE: see notes on find_within_range(). + template + Visitor + visit_within_range(SearchVal const& V, subvalue_type const R, Visitor visitor) const + { + if (!_M_get_root()) return visitor; + _Region_ region(V, R, _M_acc, _M_cmp); + return this->visit_within_range(region, visitor); + } + + template + Visitor + visit_within_range(_Region_ const& REGION, Visitor visitor) const + { + if (_M_get_root()) { - if (!_M_get_root()) return this->end(); - return _M_find(_M_get_root(), __V, 0); + _Region_ bounds(REGION); + return _M_visit_within_range(visitor, _M_get_root(), REGION, bounds, 0); } + return visitor; + } - // compares via equality - // if you are looking for a particular item in the tree, - // and (for example) it has an ID that is checked via an == comparison - // eg - // struct Item - // { - // size_type unique_id; - // bool operator==(Item const& a, Item const& b) { return a.unique_id == b.unique_id; } - // Location location; - // }; - // Two items may be equivalent in location. find() would return - // either one of them. But no two items have the same ID, so - // find_exact() would always return the item with the same location AND id. - // - template - const_iterator - find_exact(SearchVal const& __V) const + // NOTE: this will visit points based on 'Manhattan distance' aka city-block distance + // aka taxicab metric. Meaning it will find all points within: + // max(x_dist,max(y_dist,z_dist)); + // AND NOT than what you would expect: sqrt(x_dist*x_dist + y_dist*y_dist + z_dist*z_dist) + // + // This is because it converts the distance into a bounding-box 'region' and compares + // against that. + // + // If you want the sqrt() behaviour, ask on the mailing list for different options. + // + template + _OutputIterator + find_within_range(SearchVal const& val, subvalue_type const range, + _OutputIterator out) const + { + if (!_M_get_root()) return out; + _Region_ region(val, range, _M_acc, _M_cmp); + return this->find_within_range(region, out); + } + + template + _OutputIterator + find_within_range(_Region_ const& region, + _OutputIterator out) const + { + if (_M_get_root()) { - if (!_M_get_root()) return this->end(); - return _M_find_exact(_M_get_root(), __V, 0); + _Region_ bounds(region); + out = _M_find_within_range(out, _M_get_root(), + region, bounds, 0); } + return out; + } - size_type - count_within_range(const_reference __V, subvalue_type const __R) const - { - if (!_M_get_root()) return 0; - _Region_ __region(__V, __R, _M_acc, _M_cmp); - return this->count_within_range(__region); - } + template + std::pair + find_nearest (SearchVal const& __val) const + { + if (_M_get_root()) + { + std::pair*, + std::pair > + best = _S_node_nearest (__K, 0, __val, + _M_get_root(), &_M_header, _M_get_root(), + std::sqrt(_S_accumulate_node_distance + (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)), + _M_cmp, _M_acc, _M_dist, + always_true()); + return std::pair + (best.first, best.second.second); + } + return std::pair(end(), 0); + } - size_type - count_within_range(_Region_ const& __REGION) const - { - if (!_M_get_root()) return 0; - - _Region_ __bounds(__REGION); - return _M_count_within_range(_M_get_root(), - __REGION, __bounds, 0); - } - - template - Visitor - visit_within_range(SearchVal const& V, subvalue_type const R, Visitor visitor) const - { - if (!_M_get_root()) return visitor; - _Region_ region(V, R, _M_acc, _M_cmp); - return this->visit_within_range(region, visitor); - } - - template - Visitor - visit_within_range(_Region_ const& REGION, Visitor visitor) const - { - if (_M_get_root()) - { - _Region_ bounds(REGION); - return _M_visit_within_range(visitor, _M_get_root(), REGION, bounds, 0); - } - return visitor; - } - - const_iterator - find_within_range_iterative(const_reference /*__a*/, const_reference /*__b*/) - { - return const_iterator(begin()); - } - - template - _OutputIterator - find_within_range(SearchVal const& val, subvalue_type const range, - _OutputIterator out) const - { - if (!_M_get_root()) return out; - _Region_ region(val, range, _M_acc, _M_cmp); - return this->find_within_range(region, out); - } - - template - _OutputIterator - find_within_range(_Region_ const& region, - _OutputIterator out) const - { - if (_M_get_root()) - { - _Region_ bounds(region); - out = _M_find_within_range(out, _M_get_root(), - region, bounds, 0); - } - return out; - } - - template - std::pair - find_nearest (SearchVal const& __val) const - { - if (_M_get_root()) - { - std::pair*, - std::pair > - best = _S_node_nearest (__K, 0, __val, - _M_get_root(), &_M_header, _M_get_root(), - sqrt(_S_accumulate_node_distance - (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)), - _M_cmp, _M_acc, _M_dist, - always_true()); - return std::pair - (best.first, best.second.second); - } - return std::pair(end(), 0); - } - - template - std::pair - find_nearest (SearchVal const& __val, distance_type __max) const - { - if (_M_get_root()) - { + template + std::pair + find_nearest (SearchVal const& __val, distance_type __max) const + { + if (_M_get_root()) + { bool root_is_candidate = false; - const _Node<_Val>* node = _M_get_root(); - { // scope to ensure we don't use 'root_dist' anywhere else - distance_type root_dist = sqrt(_S_accumulate_node_distance - (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)); - if (root_dist <= __max) - { - root_is_candidate = true; - __max = root_dist; - } - } - std::pair*, - std::pair > - best = _S_node_nearest (__K, 0, __val, _M_get_root(), &_M_header, - node, __max, _M_cmp, _M_acc, _M_dist, - always_true()); - // make sure we didn't just get stuck with the root node... - if (root_is_candidate || best.first != _M_get_root()) - return std::pair - (best.first, best.second.second); - } - return std::pair(end(), __max); - } + const _Node<_Val>* node = _M_get_root(); + { // scope to ensure we don't use 'root_dist' anywhere else + distance_type root_dist = std::sqrt(_S_accumulate_node_distance + (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)); + if (root_dist <= __max) + { + root_is_candidate = true; + __max = root_dist; + } + } + std::pair*, + std::pair > + best = _S_node_nearest (__K, 0, __val, _M_get_root(), &_M_header, + node, __max, _M_cmp, _M_acc, _M_dist, + always_true()); + // make sure we didn't just get stuck with the root node... + if (root_is_candidate || best.first != _M_get_root()) + return std::pair + (best.first, best.second.second); + } + return std::pair(end(), __max); + } - template - std::pair - find_nearest_if (SearchVal const& __val, distance_type __max, - _Predicate __p) const - { - if (_M_get_root()) - { + template + std::pair + find_nearest_if (SearchVal const& __val, distance_type __max, + _Predicate __p) const + { + if (_M_get_root()) + { bool root_is_candidate = false; - const _Node<_Val>* node = _M_get_root(); - if (__p(_M_get_root()->_M_value)) - { - { // scope to ensure we don't use root_dist anywhere else - distance_type root_dist = sqrt(_S_accumulate_node_distance - (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)); - if (root_dist <= __max) - { - root_is_candidate = true; - root_dist = __max; - } - } - } - std::pair*, - std::pair > - best = _S_node_nearest (__K, 0, __val, _M_get_root(), &_M_header, - node, __max, _M_cmp, _M_acc, _M_dist, __p); - // make sure we didn't just get stuck with the root node... - if (root_is_candidate || best.first != _M_get_root()) - return std::pair - (best.first, best.second.second); - } - return std::pair(end(), __max); - } + const _Node<_Val>* node = _M_get_root(); + if (__p(_M_get_root()->_M_value)) + { + { // scope to ensure we don't use root_dist anywhere else + distance_type root_dist = std::sqrt(_S_accumulate_node_distance + (__K, _M_dist, _M_acc, _M_get_root()->_M_value, __val)); + if (root_dist <= __max) + { + root_is_candidate = true; + root_dist = __max; + } + } + } + std::pair*, + std::pair > + best = _S_node_nearest (__K, 0, __val, _M_get_root(), &_M_header, + node, __max, _M_cmp, _M_acc, _M_dist, __p); + // make sure we didn't just get stuck with the root node... + if (root_is_candidate || best.first != _M_get_root()) + return std::pair + (best.first, best.second.second); + } + return std::pair(end(), __max); + } - void - optimise() + void + optimise() + { + std::vector __v(this->begin(),this->end()); + this->clear(); + _M_optimise(__v.begin(), __v.end(), 0); + } + + void + optimize() + { // cater for people who cannot spell :) + this->optimise(); + } + + void check_tree() + { + _M_check_node(_M_get_root(),0); + } + +protected: + + void _M_check_children( _Link_const_type child, _Link_const_type parent, size_type const level, bool to_the_left ) + { + assert(parent); + if (child) + { + _Node_compare_ compare(level % __K, _M_acc, _M_cmp); + // REMEMBER! its a <= relationship for BOTH branches + // for left-case (true), child<=node --> !(node !(child_M_value,child->_M_value)); // check the left + assert(to_the_left || !compare(child->_M_value,parent->_M_value)); // check the right + // and recurse down the tree, checking everything + _M_check_children(_S_left(child),parent,level,to_the_left); + _M_check_children(_S_right(child),parent,level,to_the_left); + } + } + + void _M_check_node( _Link_const_type node, size_type const level ) + { + if (node) + { + // (comparing on this level) + // everything to the left of this node must be smaller than this + _M_check_children( _S_left(node), node, level, true ); + // everything to the right of this node must be larger than this + _M_check_children( _S_right(node), node, level, false ); + + _M_check_node( _S_left(node), level+1 ); + _M_check_node( _S_right(node), level+1 ); + } + } + + void _M_empty_initialise() + { + _M_set_leftmost(&_M_header); + _M_set_rightmost(&_M_header); + _M_header._M_parent = NULL; + _M_set_root(NULL); + } + + iterator + _M_insert_left(_Link_type __N, const_reference __V) + { + _S_set_left(__N, _M_new_node(__V)); ++_M_count; + _S_set_parent( _S_left(__N), __N ); + if (__N == _M_get_leftmost()) + _M_set_leftmost( _S_left(__N) ); + return iterator(_S_left(__N)); + } + + iterator + _M_insert_right(_Link_type __N, const_reference __V) + { + _S_set_right(__N, _M_new_node(__V)); ++_M_count; + _S_set_parent( _S_right(__N), __N ); + if (__N == _M_get_rightmost()) + _M_set_rightmost( _S_right(__N) ); + return iterator(_S_right(__N)); + } + + iterator + _M_insert(_Link_type __N, const_reference __V, + size_type const __L) + { + if (_Node_compare_(__L % __K, _M_acc, _M_cmp)(__V, __N->_M_value)) { - std::vector __v(this->begin(),this->end()); - this->clear(); - _M_optimise(__v.begin(), __v.end(), 0); + if (!_S_left(__N)) + return _M_insert_left(__N, __V); + return _M_insert(_S_left(__N), __V, __L+1); } - - void - optimize() - { // cater for people who cannot spell :) - this->optimise(); - } - - void check_tree() + else { - _M_check_node(_M_get_root(),0); + if (!_S_right(__N) || __N == _M_get_rightmost()) + return _M_insert_right(__N, __V); + return _M_insert(_S_right(__N), __V, __L+1); + } + } + + _Link_type + _M_erase(_Link_type dead_dad, size_type const level) + { + // find a new step_dad, he will become a drop-in replacement. + _Link_type step_dad = _M_get_erase_replacement(dead_dad, level); + + // tell dead_dad's parent that his new child is step_dad + if (dead_dad == _M_get_root()) + _M_set_root(step_dad); + else if (_S_left(_S_parent(dead_dad)) == dead_dad) + _S_set_left(_S_parent(dead_dad), step_dad); + else + _S_set_right(_S_parent(dead_dad), step_dad); + + // deal with the left and right edges of the tree... + // if the dead_dad was at the edge, then substitude... + // but if there IS no new dead, then left_most is the dead_dad's parent + if (dead_dad == _M_get_leftmost()) + _M_set_leftmost( (step_dad ? step_dad : _S_parent(dead_dad)) ); + if (dead_dad == _M_get_rightmost()) + _M_set_rightmost( (step_dad ? step_dad : _S_parent(dead_dad)) ); + + if (step_dad) + { + // step_dad gets dead_dad's parent + _S_set_parent(step_dad, _S_parent(dead_dad)); + + // first tell the children that step_dad is their new dad + if (_S_left(dead_dad)) + _S_set_parent(_S_left(dead_dad), step_dad); + if (_S_right(dead_dad)) + _S_set_parent(_S_right(dead_dad), step_dad); + + // step_dad gets dead_dad's children + _S_set_left(step_dad, _S_left(dead_dad)); + _S_set_right(step_dad, _S_right(dead_dad)); } - protected: + return step_dad; + } - void _M_check_children( _Link_const_type child, _Link_const_type parent, size_type const level, bool to_the_left ) - { - assert(parent); - if (child) - { - _Node_compare_ compare(level % __K, _M_acc, _M_cmp); - // REMEMBER! its a <= relationship for BOTH branches - // for left-case (true), child<=node --> !(node !(child_M_value,child->_M_value)); // check the left - assert(to_the_left || !compare(child->_M_value,parent->_M_value)); // check the right - // and recurse down the tree, checking everything - _M_check_children(_S_left(child),parent,level,to_the_left); - _M_check_children(_S_right(child),parent,level,to_the_left); - } - } - void _M_check_node( _Link_const_type node, size_type const level ) - { - if (node) - { - // (comparing on this level) - // everything to the left of this node must be smaller than this - _M_check_children( _S_left(node), node, level, true ); - // everything to the right of this node must be larger than this - _M_check_children( _S_right(node), node, level, false ); - _M_check_node( _S_left(node), level+1 ); - _M_check_node( _S_right(node), level+1 ); - } - } + _Link_type + _M_get_erase_replacement(_Link_type node, size_type const level) + { + // if 'node' is null, then we can't do any better + if (_S_is_leaf(node)) + return NULL; - void _M_empty_initialise() - { - _M_set_leftmost(&_M_header); - _M_set_rightmost(&_M_header); - _M_header._M_parent = nullptr; - _M_set_root(nullptr); - } - - iterator - _M_insert_left(_Link_type __N, const_reference __V) - { - _S_set_left(__N, _M_new_node(__V)); ++_M_count; - _S_set_parent( _S_left(__N), __N ); - if (__N == _M_get_leftmost()) - _M_set_leftmost( _S_left(__N) ); - return iterator(_S_left(__N)); - } - - iterator - _M_insert_right(_Link_type __N, const_reference __V) - { - _S_set_right(__N, _M_new_node(__V)); ++_M_count; - _S_set_parent( _S_right(__N), __N ); - if (__N == _M_get_rightmost()) - _M_set_rightmost( _S_right(__N) ); - return iterator(_S_right(__N)); - } - - iterator - _M_insert(_Link_type __N, const_reference __V, - size_type const __L) - { - if (_Node_compare_(__L % __K, _M_acc, _M_cmp)(__V, __N->_M_value)) - { - if (!_S_left(__N)) - return _M_insert_left(__N, __V); - return _M_insert(_S_left(__N), __V, __L+1); - } + std::pair<_Link_type,size_type> candidate; + // if there is nothing to the left, find a candidate on the right tree + if (!_S_left(node)) + candidate = _M_get_j_min( std::pair<_Link_type,size_type>(_S_right(node),level), level+1); + // ditto for the right + else if ((!_S_right(node))) + candidate = _M_get_j_max( std::pair<_Link_type,size_type>(_S_left(node),level), level+1); + // we have both children ... + else + { + // we need to do a little more work in order to find a good candidate + // this is actually a technique used to choose a node from either the + // left or right branch RANDOMLY, so that the tree has a greater change of + // staying balanced. + // If this were a true binary tree, we would always hunt down the right branch. + // See top for notes. + _Node_compare_ compare(level % __K, _M_acc, _M_cmp); + // compare the children based on this level's criteria... + // (this gives virtually random results) + if (compare(_S_right(node)->_M_value, _S_left(node)->_M_value)) + // the right is smaller, get our replacement from the SMALLEST on the right + candidate = _M_get_j_min(std::pair<_Link_type,size_type>(_S_right(node),level), level+1); else - { - if (!_S_right(__N) || __N == _M_get_rightmost()) - return _M_insert_right(__N, __V); - return _M_insert(_S_right(__N), __V, __L+1); - } + candidate = _M_get_j_max( std::pair<_Link_type,size_type>(_S_left(node),level), level+1); + } + + // we have a candidate replacement by now. + // remove it from the tree, but don't delete it. + // it must be disconnected before it can be reconnected. + _Link_type parent = _S_parent(candidate.first); + if (_S_left(parent) == candidate.first) + _S_set_left(parent, _M_erase(candidate.first, candidate.second)); + else + _S_set_right(parent, _M_erase(candidate.first, candidate.second)); + + return candidate.first; + } + + + + std::pair<_Link_type,size_type> + _M_get_j_min( std::pair<_Link_type,size_type> const node, size_type const level) + { + typedef std::pair<_Link_type,size_type> Result; + if (_S_is_leaf(node.first)) + return Result(node.first,level); + + _Node_compare_ compare(node.second % __K, _M_acc, _M_cmp); + Result candidate = node; + if (_S_left(node.first)) + { + Result left = _M_get_j_min(Result(_S_left(node.first), node.second), level+1); + if (compare(left.first->_M_value, candidate.first->_M_value)) + candidate = left; + } + if (_S_right(node.first)) + { + Result right = _M_get_j_min( Result(_S_right(node.first),node.second), level+1); + if (compare(right.first->_M_value, candidate.first->_M_value)) + candidate = right; + } + if (candidate.first == node.first) + return Result(candidate.first,level); + + return candidate; + } + + + + std::pair<_Link_type,size_type> + _M_get_j_max( std::pair<_Link_type,size_type> const node, size_type const level) + { + typedef std::pair<_Link_type,size_type> Result; + + if (_S_is_leaf(node.first)) + return Result(node.first,level); + + _Node_compare_ compare(node.second % __K, _M_acc, _M_cmp); + Result candidate = node; + if (_S_left(node.first)) + { + Result left = _M_get_j_max( Result(_S_left(node.first),node.second), level+1); + if (compare(candidate.first->_M_value, left.first->_M_value)) + candidate = left; + } + if (_S_right(node.first)) + { + Result right = _M_get_j_max(Result(_S_right(node.first),node.second), level+1); + if (compare(candidate.first->_M_value, right.first->_M_value)) + candidate = right; } - _Link_type - _M_erase(_Link_type dead_dad, size_type const level) + if (candidate.first == node.first) + return Result(candidate.first,level); + + return candidate; + } + + + void + _M_erase_subtree(_Link_type __n) + { + while (__n) { - // find a new step_dad, he will become a drop-in replacement. - _Link_type step_dad = _M_get_erase_replacement(dead_dad, level); - - // tell dead_dad's parent that his new child is step_dad - if (dead_dad == _M_get_root()) - _M_set_root(step_dad); - else if (_S_left(_S_parent(dead_dad)) == dead_dad) - _S_set_left(_S_parent(dead_dad), step_dad); - else - _S_set_right(_S_parent(dead_dad), step_dad); - - // deal with the left and right edges of the tree... - // if the dead_dad was at the edge, then substitute... - // but if there IS no new dead, then left_most is the dead_dad's parent - if (dead_dad == _M_get_leftmost()) - _M_set_leftmost( (step_dad ? step_dad : _S_parent(dead_dad)) ); - if (dead_dad == _M_get_rightmost()) - _M_set_rightmost( (step_dad ? step_dad : _S_parent(dead_dad)) ); - - if (step_dad) - { - // step_dad gets dead_dad's parent - _S_set_parent(step_dad, _S_parent(dead_dad)); - - // first tell the children that step_dad is their new dad - if (_S_left(dead_dad)) - _S_set_parent(_S_left(dead_dad), step_dad); - if (_S_right(dead_dad)) - _S_set_parent(_S_right(dead_dad), step_dad); - - // step_dad gets dead_dad's children - _S_set_left(step_dad, _S_left(dead_dad)); - _S_set_right(step_dad, _S_right(dead_dad)); - } - - return step_dad; + _M_erase_subtree(_S_right(__n)); + _Link_type __t = _S_left(__n); + _M_delete_node(__n); + __n = __t; } + } + const_iterator + _M_find(_Link_const_type node, const_reference value, size_type const level) const + { + // be aware! This is very different to normal binary searches, because of the <= + // relationship used. See top for notes. + // Basically we have to check ALL branches, as we may have an identical node + // in different branches. + const_iterator found = this->end(); - - _Link_type - _M_get_erase_replacement(_Link_type node, size_type const level) + _Node_compare_ compare(level % __K, _M_acc, _M_cmp); + if (!compare(node->_M_value,value)) // note, this is a <= test { - // if 'node' is null, then we can't do any better - if (_S_is_leaf(node)) - return NULL; - - std::pair<_Link_type,size_type> candidate; - // if there is nothing to the left, find a candidate on the right tree - if (!_S_left(node)) - candidate = _M_get_j_min( std::pair<_Link_type,size_type>(_S_right(node),level), level+1); - // ditto for the right - else if ((!_S_right(node))) - candidate = _M_get_j_max( std::pair<_Link_type,size_type>(_S_left(node),level), level+1); - // we have both children ... - else - { - // we need to do a little more work in order to find a good candidate - // this is actually a technique used to choose a node from either the - // left or right branch RANDOMLY, so that the tree has a greater change of - // staying balanced. - // If this were a true binary tree, we would always hunt down the right branch. - // See top for notes. - _Node_compare_ compare(level % __K, _M_acc, _M_cmp); - // compare the children based on this level's criteria... - // (this gives virtually random results) - if (compare(_S_right(node)->_M_value, _S_left(node)->_M_value)) - // the right is smaller, get our replacement from the SMALLEST on the right - candidate = _M_get_j_min(std::pair<_Link_type,size_type>(_S_right(node),level), level+1); - else - candidate = _M_get_j_max( std::pair<_Link_type,size_type>(_S_left(node),level), level+1); - } - - // we have a candidate replacement by now. - // remove it from the tree, but don't delete it. - // it must be disconnected before it can be reconnected. - _Link_type parent = _S_parent(candidate.first); - if (_S_left(parent) == candidate.first) - _S_set_left(parent, _M_erase(candidate.first, candidate.second)); - else - _S_set_right(parent, _M_erase(candidate.first, candidate.second)); - - return candidate.first; + // this line is the only difference between _M_find_exact() and _M_find() + if (_M_matches_node(node, value, level)) + return const_iterator(node); // return right away + if (_S_left(node)) + found = _M_find(_S_left(node), value, level+1); } + if ( _S_right(node) && found == this->end() && !compare(value,node->_M_value)) // note, this is a <= test + found = _M_find(_S_right(node), value, level+1); + return found; + } + const_iterator + _M_find_exact(_Link_const_type node, const_reference value, size_type const level) const + { + // be aware! This is very different to normal binary searches, because of the <= + // relationship used. See top for notes. + // Basically we have to check ALL branches, as we may have an identical node + // in different branches. + const_iterator found = this->end(); + _Node_compare_ compare(level % __K, _M_acc, _M_cmp); + if (!compare(node->_M_value,value)) // note, this is a <= test + { + // this line is the only difference between _M_find_exact() and _M_find() + if (value == *const_iterator(node)) + return const_iterator(node); // return right away + if (_S_left(node)) + found = _M_find_exact(_S_left(node), value, level+1); + } - std::pair<_Link_type,size_type> - _M_get_j_min( std::pair<_Link_type,size_type> const node, size_type const level) - { - typedef std::pair<_Link_type,size_type> Result; - if (_S_is_leaf(node.first)) - return Result(node.first,level); + // note: no else! items that are identical can be down both branches + if ( _S_right(node) && found == this->end() && !compare(value,node->_M_value)) // note, this is a <= test + found = _M_find_exact(_S_right(node), value, level+1); + return found; + } - _Node_compare_ compare(node.second % __K, _M_acc, _M_cmp); - Result candidate = node; - if (_S_left(node.first)) - { - Result left = _M_get_j_min(Result(_S_left(node.first), node.second), level+1); - if (compare(left.first->_M_value, candidate.first->_M_value)) - candidate = left; - } - if (_S_right(node.first)) - { - Result right = _M_get_j_min( Result(_S_right(node.first),node.second), level+1); - if (compare(right.first->_M_value, candidate.first->_M_value)) - candidate = right; - } - if (candidate.first == node.first) - return Result(candidate.first,level); + bool + _M_matches_node_in_d(_Link_const_type __N, const_reference __V, + size_type const __L) const + { + _Node_compare_ compare(__L % __K, _M_acc, _M_cmp); + return !(compare(__N->_M_value, __V) || compare(__V, __N->_M_value)); + } - return candidate; - } + bool + _M_matches_node_in_other_ds(_Link_const_type __N, const_reference __V, + size_type const __L = 0) const + { + size_type __i = __L; + while ((__i = (__i + 1) % __K) != __L % __K) + if (!_M_matches_node_in_d(__N, __V, __i)) return false; + return true; + } + bool + _M_matches_node(_Link_const_type __N, const_reference __V, + size_type __L = 0) const + { + return _M_matches_node_in_d(__N, __V, __L) + && _M_matches_node_in_other_ds(__N, __V, __L); + } - - std::pair<_Link_type,size_type> - _M_get_j_max( std::pair<_Link_type,size_type> const node, size_type const level) - { - typedef std::pair<_Link_type,size_type> Result; - - if (_S_is_leaf(node.first)) - return Result(node.first,level); - - _Node_compare_ compare(node.second % __K, _M_acc, _M_cmp); - Result candidate = node; - if (_S_left(node.first)) - { - Result left = _M_get_j_max( Result(_S_left(node.first),node.second), level+1); - if (compare(candidate.first->_M_value, left.first->_M_value)) - candidate = left; - } - if (_S_right(node.first)) - { - Result right = _M_get_j_max(Result(_S_right(node.first),node.second), level+1); - if (compare(candidate.first->_M_value, right.first->_M_value)) - candidate = right; - } - - if (candidate.first == node.first) - return Result(candidate.first,level); - - return candidate; - } - - - void - _M_erase_subtree(_Link_type __n) - { - while (__n) - { - _M_erase_subtree(_S_right(__n)); - _Link_type __t = _S_left(__n); - _M_delete_node(__n); - __n = __t; - } - } - - const_iterator - _M_find(_Link_const_type node, const_reference value, size_type const level) const - { - // be aware! This is very different to normal binary searches, because of the <= - // relationship used. See top for notes. - // Basically we have to check ALL branches, as we may have an identical node - // in different branches. - const_iterator found = this->end(); - - _Node_compare_ compare(level % __K, _M_acc, _M_cmp); - if (!compare(node->_M_value,value)) // note, this is a <= test - { - // this line is the only difference between _M_find_exact() and _M_find() - if (_M_matches_node(node, value, level)) - return const_iterator(node); // return right away - if (_S_left(node)) - found = _M_find(_S_left(node), value, level+1); - } - if ( _S_right(node) && found == this->end() && !compare(value,node->_M_value)) // note, this is a <= test - found = _M_find(_S_right(node), value, level+1); - return found; - } - - const_iterator - _M_find_exact(_Link_const_type node, const_reference value, size_type const level) const - { - // be aware! This is very different to normal binary searches, because of the <= - // relationship used. See top for notes. - // Basically we have to check ALL branches, as we may have an identical node - // in different branches. - const_iterator found = this->end(); - - _Node_compare_ compare(level % __K, _M_acc, _M_cmp); - if (!compare(node->_M_value,value)) // note, this is a <= test + size_type + _M_count_within_range(_Link_const_type __N, _Region_ const& __REGION, + _Region_ const& __BOUNDS, + size_type const __L) const + { + size_type count = 0; + if (__REGION.encloses(_S_value(__N))) { - // this line is the only difference between _M_find_exact() and _M_find() - if (value == *const_iterator(node)) - return const_iterator(node); // return right away - if (_S_left(node)) - found = _M_find_exact(_S_left(node), value, level+1); + ++count; + } + if (_S_left(__N)) + { + _Region_ __bounds(__BOUNDS); + __bounds.set_high_bound(_S_value(__N), __L); + if (__REGION.intersects_with(__bounds)) + count += _M_count_within_range(_S_left(__N), + __REGION, __bounds, __L+1); + } + if (_S_right(__N)) + { + _Region_ __bounds(__BOUNDS); + __bounds.set_low_bound(_S_value(__N), __L); + if (__REGION.intersects_with(__bounds)) + count += _M_count_within_range(_S_right(__N), + __REGION, __bounds, __L+1); } - // note: no else! items that are identical can be down both branches - if ( _S_right(node) && found == this->end() && !compare(value,node->_M_value)) // note, this is a <= test - found = _M_find_exact(_S_right(node), value, level+1); - return found; - } + return count; + } - bool - _M_matches_node_in_d(_Link_const_type __N, const_reference __V, - size_type const __L) const - { - _Node_compare_ compare(__L % __K, _M_acc, _M_cmp); - return !(compare(__N->_M_value, __V) || compare(__V, __N->_M_value)); - } - bool - _M_matches_node_in_other_ds(_Link_const_type __N, const_reference __V, - size_type const __L = 0) const - { - size_type __i = __L; - while ((__i = (__i + 1) % __K) != __L % __K) - if (!_M_matches_node_in_d(__N, __V, __i)) return false; - return true; - } - - bool - _M_matches_node(_Link_const_type __N, const_reference __V, - size_type __L = 0) const - { - return _M_matches_node_in_d(__N, __V, __L) - && _M_matches_node_in_other_ds(__N, __V, __L); - } - - size_type - _M_count_within_range(_Link_const_type __N, _Region_ const& __REGION, - _Region_ const& __BOUNDS, - size_type const __L) const + template + Visitor + _M_visit_within_range(Visitor visitor, + _Link_const_type N, _Region_ const& REGION, + _Region_ const& BOUNDS, + size_type const L) const + { + if (REGION.encloses(_S_value(N))) { - size_type count = 0; - if (__REGION.encloses(_S_value(__N))) - { - ++count; - } - if (_S_left(__N)) - { - _Region_ __bounds(__BOUNDS); - __bounds.set_high_bound(_S_value(__N), __L); - if (__REGION.intersects_with(__bounds)) - count += _M_count_within_range(_S_left(__N), - __REGION, __bounds, __L+1); - } - if (_S_right(__N)) - { - _Region_ __bounds(__BOUNDS); - __bounds.set_low_bound(_S_value(__N), __L); - if (__REGION.intersects_with(__bounds)) - count += _M_count_within_range(_S_right(__N), - __REGION, __bounds, __L+1); - } - - return count; + visitor(_S_value(N)); + } + if (_S_left(N)) + { + _Region_ bounds(BOUNDS); + bounds.set_high_bound(_S_value(N), L); + if (REGION.intersects_with(bounds)) + visitor = _M_visit_within_range(visitor, _S_left(N), + REGION, bounds, L+1); + } + if (_S_right(N)) + { + _Region_ bounds(BOUNDS); + bounds.set_low_bound(_S_value(N), L); + if (REGION.intersects_with(bounds)) + visitor = _M_visit_within_range(visitor, _S_right(N), + REGION, bounds, L+1); } + return visitor; + } - template - Visitor - _M_visit_within_range(Visitor visitor, - _Link_const_type N, _Region_ const& REGION, - _Region_ const& BOUNDS, - size_type const L) const + + + template + _OutputIterator + _M_find_within_range(_OutputIterator out, + _Link_const_type __N, _Region_ const& __REGION, + _Region_ const& __BOUNDS, + size_type const __L) const + { + if (__REGION.encloses(_S_value(__N))) { - if (REGION.encloses(_S_value(N))) - { - visitor(_S_value(N)); - } - if (_S_left(N)) - { - _Region_ bounds(BOUNDS); - bounds.set_high_bound(_S_value(N), L); - if (REGION.intersects_with(bounds)) - visitor = _M_visit_within_range(visitor, _S_left(N), - REGION, bounds, L+1); - } - if (_S_right(N)) - { - _Region_ bounds(BOUNDS); - bounds.set_low_bound(_S_value(N), L); - if (REGION.intersects_with(bounds)) - visitor = _M_visit_within_range(visitor, _S_right(N), - REGION, bounds, L+1); - } - - return visitor; + *out++ = _S_value(__N); + } + if (_S_left(__N)) + { + _Region_ __bounds(__BOUNDS); + __bounds.set_high_bound(_S_value(__N), __L); + if (__REGION.intersects_with(__bounds)) + out = _M_find_within_range(out, _S_left(__N), + __REGION, __bounds, __L+1); + } + if (_S_right(__N)) + { + _Region_ __bounds(__BOUNDS); + __bounds.set_low_bound(_S_value(__N), __L); + if (__REGION.intersects_with(__bounds)) + out = _M_find_within_range(out, _S_right(__N), + __REGION, __bounds, __L+1); } + return out; + } - template - _OutputIterator - _M_find_within_range(_OutputIterator out, - _Link_const_type __N, _Region_ const& __REGION, - _Region_ const& __BOUNDS, - size_type const __L) const - { - if (__REGION.encloses(_S_value(__N))) - { - *out++ = _S_value(__N); - } - if (_S_left(__N)) - { - _Region_ __bounds(__BOUNDS); - __bounds.set_high_bound(_S_value(__N), __L); - if (__REGION.intersects_with(__bounds)) - out = _M_find_within_range(out, _S_left(__N), - __REGION, __bounds, __L+1); - } - if (_S_right(__N)) - { - _Region_ __bounds(__BOUNDS); - __bounds.set_low_bound(_S_value(__N), __L); - if (__REGION.intersects_with(__bounds)) - out = _M_find_within_range(out, _S_right(__N), - __REGION, __bounds, __L+1); - } + template + void + _M_optimise(_Iter const& __A, _Iter const& __B, + size_type const __L) + { + if (__A == __B) return; + _Node_compare_ compare(__L % __K, _M_acc, _M_cmp); + _Iter __m = __A + (__B - __A) / 2; + std::nth_element(__A, __m, __B, compare); + this->insert(*__m); + if (__m != __A) _M_optimise(__A, __m, __L+1); + if (++__m != __B) _M_optimise(__m, __B, __L+1); + } - return out; - } + _Link_const_type + _M_get_root() const + { + return const_cast<_Link_const_type>(_M_root); + } + + _Link_type + _M_get_root() + { + return _M_root; + } + + void _M_set_root(_Link_type n) + { + _M_root = n; + } + + _Link_const_type + _M_get_leftmost() const + { + return static_cast<_Link_type>(_M_header._M_left); + } + + void + _M_set_leftmost( _Node_base * a ) + { + _M_header._M_left = a; + } + + _Link_const_type + _M_get_rightmost() const + { + return static_cast<_Link_type>( _M_header._M_right ); + } + + void + _M_set_rightmost( _Node_base * a ) + { + _M_header._M_right = a; + } + + static _Link_type + _S_parent(_Base_ptr N) + { + return static_cast<_Link_type>( N->_M_parent ); + } + + static _Link_const_type + _S_parent(_Base_const_ptr N) + { + return static_cast<_Link_const_type>( N->_M_parent ); + } + + static void + _S_set_parent(_Base_ptr N, _Base_ptr p) + { + N->_M_parent = p; + } + + static void + _S_set_left(_Base_ptr N, _Base_ptr l) + { + N->_M_left = l; + } + + static _Link_type + _S_left(_Base_ptr N) + { + return static_cast<_Link_type>( N->_M_left ); + } + + static _Link_const_type + _S_left(_Base_const_ptr N) + { + return static_cast<_Link_const_type>( N->_M_left ); + } + + static void + _S_set_right(_Base_ptr N, _Base_ptr r) + { + N->_M_right = r; + } + + static _Link_type + _S_right(_Base_ptr N) + { + return static_cast<_Link_type>( N->_M_right ); + } + + static _Link_const_type + _S_right(_Base_const_ptr N) + { + return static_cast<_Link_const_type>( N->_M_right ); + } + + static bool + _S_is_leaf(_Base_const_ptr N) + { + return !_S_left(N) && !_S_right(N); + } + + static const_reference + _S_value(_Link_const_type N) + { + return N->_M_value; + } + + static const_reference + _S_value(_Base_const_ptr N) + { + return static_cast<_Link_const_type>(N)->_M_value; + } + + static _Link_const_type + _S_minimum(_Link_const_type __X) + { + return static_cast<_Link_const_type> ( _Node_base::_S_minimum(__X) ); + } + + static _Link_const_type + _S_maximum(_Link_const_type __X) + { + return static_cast<_Link_const_type>( _Node_base::_S_maximum(__X) ); + } - template - void - _M_optimise(_Iter const& __A, _Iter const& __B, - size_type const __L) - { - if (__A == __B) return; - _Node_compare_ compare(__L % __K, _M_acc, _M_cmp); - _Iter __m = __A + (__B - __A) / 2; - std::nth_element(__A, __m, __B, compare); - this->insert(*__m); - if (__m != __A) _M_optimise(__A, __m, __L+1); - if (++__m != __B) _M_optimise(__m, __B, __L+1); - } + _Link_type + _M_new_node(const_reference __V, // = value_type(), + _Base_ptr const __PARENT = NULL, + _Base_ptr const __LEFT = NULL, + _Base_ptr const __RIGHT = NULL) + { + typename _Base::NoLeakAlloc noleak(this); + _Link_type new_node = noleak.get(); + _Base::_M_construct_node(new_node, __V, __PARENT, __LEFT, __RIGHT); + noleak.disconnect(); + return new_node; + } - _Link_const_type - _M_get_root() const - { - return const_cast<_Link_const_type>(_M_root); - } + /* WHAT was this for? + _Link_type + _M_clone_node(_Link_const_type __X) + { + _Link_type __ret = _M_allocate_node(__X->_M_value); + // TODO + return __ret; + } + */ - _Link_type - _M_get_root() - { - return _M_root; - } + void + _M_delete_node(_Link_type __p) + { + _Base::_M_destroy_node(__p); + _Base::_M_deallocate_node(__p); + } - void _M_set_root(_Link_type n) - { - _M_root = n; - } - - _Link_const_type - _M_get_leftmost() const - { - return static_cast<_Link_type>(_M_header._M_left); - } - - void - _M_set_leftmost( _Node_base * a ) - { - _M_header._M_left = a; - } - - _Link_const_type - _M_get_rightmost() const - { - return static_cast<_Link_type>( _M_header._M_right ); - } - - void - _M_set_rightmost( _Node_base * a ) - { - _M_header._M_right = a; - } - - static _Link_type - _S_parent(_Base_ptr N) - { - return static_cast<_Link_type>( N->_M_parent ); - } - - static _Link_const_type - _S_parent(_Base_const_ptr N) - { - return static_cast<_Link_const_type>( N->_M_parent ); - } - - static void - _S_set_parent(_Base_ptr N, _Base_ptr p) - { - N->_M_parent = p; - } - - static void - _S_set_left(_Base_ptr N, _Base_ptr l) - { - N->_M_left = l; - } - - static _Link_type - _S_left(_Base_ptr N) - { - return static_cast<_Link_type>( N->_M_left ); - } - - static _Link_const_type - _S_left(_Base_const_ptr N) - { - return static_cast<_Link_const_type>( N->_M_left ); - } - - static void - _S_set_right(_Base_ptr N, _Base_ptr r) - { - N->_M_right = r; - } - - static _Link_type - _S_right(_Base_ptr N) - { - return static_cast<_Link_type>( N->_M_right ); - } - - static _Link_const_type - _S_right(_Base_const_ptr N) - { - return static_cast<_Link_const_type>( N->_M_right ); - } - - static bool - _S_is_leaf(_Base_const_ptr N) - { - return !_S_left(N) && !_S_right(N); - } - - static const_reference - _S_value(_Link_const_type N) - { - return N->_M_value; - } - - static const_reference - _S_value(_Base_const_ptr N) - { - return static_cast<_Link_const_type>(N)->_M_value; - } - - static _Link_const_type - _S_minimum(_Link_const_type __X) - { - return static_cast<_Link_const_type> ( _Node_base::_S_minimum(__X) ); - } - - static _Link_const_type - _S_maximum(_Link_const_type __X) - { - return static_cast<_Link_const_type>( _Node_base::_S_maximum(__X) ); - } - - - _Link_type - _M_new_node(const_reference __V, // = value_type(), - _Base_ptr const __PARENT = nullptr, - _Base_ptr const __LEFT = nullptr, - _Base_ptr const __RIGHT = nullptr) - { - typename _Base::NoLeakAlloc noleak(this); - _Link_type new_node = noleak.get(); - _Base::_M_construct_node(new_node, __V, __PARENT, __LEFT, __RIGHT); - noleak.disconnect(); - return new_node; - } - - /* WHAT was this for? - _Link_type - _M_clone_node(_Link_const_type __X) - { - _Link_type __ret = _M_allocate_node(__X->_M_value); - // TODO - return __ret; - } - */ - - void - _M_delete_node(_Link_type __p) - { - _Base::_M_destroy_node(__p); - _Base::_M_deallocate_node(__p); - } - - _Link_type _M_root; - _Node_base _M_header; - size_type _M_count; - _Acc _M_acc; - _Cmp _M_cmp; - _Dist _M_dist; + _Link_type _M_root; + _Node_base _M_header; + size_type _M_count; + _Acc _M_acc; + _Cmp _M_cmp; + _Dist _M_dist; #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS - friend std::ostream& - operator<<(std::ostream& o, - KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> const& tree) - { - o << "meta node: " << tree._M_header << std::endl; - o << "root node: " << tree._M_root << std::endl; + friend std::ostream& + operator<<(std::ostream& o, + KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> const& tree) + { + o << "meta node: " << tree._M_header << std::endl; + o << "root node: " << tree._M_root << std::endl; - if (tree.empty()) - return o << "[empty " << __K << "d-tree " << &tree << "]"; + if (tree.empty()) + return o << "[empty " << __K << "d-tree " << &tree << "]"; - o << "nodes total: " << tree.size() << std::endl; - o << "dimensions: " << __K << std::endl; + o << "nodes total: " << tree.size() << std::endl; + o << "dimensions: " << __K << std::endl; - typedef KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> _Tree; - typedef typename _Tree::_Link_type _Link_type; + typedef KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> _Tree; + typedef typename _Tree::_Link_type _Link_type; - std::stack<_Link_const_type> s; - s.push(tree._M_get_root()); + std::stack<_Link_const_type> s; + s.push(tree._M_get_root()); - while (!s.empty()) - { - _Link_const_type n = s.top(); - s.pop(); - o << *n << std::endl; - if (_Tree::_S_left(n)) s.push(_Tree::_S_left(n)); - if (_Tree::_S_right(n)) s.push(_Tree::_S_right(n)); - } + while (!s.empty()) + { + _Link_const_type n = s.top(); + s.pop(); + o << *n << std::endl; + if (_Tree::_S_left(n)) s.push(_Tree::_S_left(n)); + if (_Tree::_S_right(n)) s.push(_Tree::_S_right(n)); + } - return o; - } + return o; + } #endif - }; +}; // class KDTree } // namespace KDTree diff --git a/src/3rdParty/libkdtree/kdtree++/node.hpp b/src/3rdParty/libkdtree/kdtree++/node.hpp index 54b18db40d..76eaa27f37 100644 --- a/src/3rdParty/libkdtree/kdtree++/node.hpp +++ b/src/3rdParty/libkdtree/kdtree++/node.hpp @@ -25,9 +25,9 @@ namespace KDTree _Base_ptr _M_left; _Base_ptr _M_right; - _Node_base(_Base_ptr const __PARENT = nullptr, - _Base_ptr const __LEFT = nullptr, - _Base_ptr const __RIGHT = nullptr) + _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 @@ -43,24 +43,8 @@ namespace KDTree while (__x->_M_right) __x = __x->_M_right; return __x; } - }; - - template - 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 = nullptr, - _Base_ptr const __LEFT = nullptr, - _Base_ptr const __RIGHT = nullptr) - : _Node_base(__PARENT, __LEFT, __RIGHT), _M_value(__VALUE) {} #ifdef KDTREE_DEFINE_OSTREAM_OPERATORS - template friend std::basic_ostream& @@ -73,7 +57,24 @@ namespace KDTree out << "; right: " << node._M_right; return out; } +#endif + }; + template + 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 friend std::basic_ostream& @@ -87,7 +88,6 @@ namespace KDTree out << "; right: " << node._M_right; return out; } - #endif }; @@ -168,17 +168,16 @@ namespace KDTree \note it's the caller responsibility to check if node is NULL. */ - template + template inline - _Node_base* + const NodeType* _S_node_descend (const size_t __dim, const _Cmp& __cmp, const _Acc& __acc, - const _Val& __val, const _Node_base* __node) + const _Val& __val, const NodeType* __node) { - if (_S_node_compare(__dim, __cmp, __acc, __val, static_cast* >(__node)->_M_value)) - return __node->_M_left; - else - return __node->_M_right; + if (_S_node_compare(__dim, __cmp, __acc, __val, __node->_M_value)) + return static_cast(__node->_M_left); + return static_cast(__node->_M_right); } /*! Find the nearest node to __val from __node @@ -190,37 +189,38 @@ namespace KDTree given arguments. */ template inline - std::pair*, + std::pair > _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 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) { - const _Node_base* pcur = __node; - const _Node_base* cur = _S_node_descend(__dim % __k, __cmp, __acc, __val, __node); + typedef const NodeType* NodePtr; + NodePtr pcur = __node; + NodePtr cur = _S_node_descend(__dim % __k, __cmp, __acc, __val, __node); size_t cur_dim = __dim+1; // find the smallest __max distance in direct descent while (cur) { - if (__p(static_cast* >(cur)->_M_value)) + 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, static_cast* >(cur)->_M_value); - d = sqrt(d); + d += _S_node_distance(i, __dist, __acc, __val, cur->_M_value); + d = std::sqrt(d); if (d <= __max) // ("bad candidate notes") // Changed: removed this test: || ( d == __max && cur < __best )) // Can't do this optimisation without checking that the current 'best' is not the root AND is not a valid candidate... // 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) { - __best = static_cast* >(cur); + __best = cur; __max = d; __dim = cur_dim; } @@ -232,20 +232,20 @@ namespace KDTree // Swap cur to prev, only prev is a valid node. cur = pcur; --cur_dim; - pcur = nullptr; + pcur = NULL; // Probe all node's children not visited yet (siblings of the visited nodes). - const _Node_base* probe = cur; - const _Node_base* pprobe = probe; - const _Node_base* near_node; - const _Node_base* far_node; + 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, static_cast* >(probe)->_M_value)) - near_node = probe->_M_right; + if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, probe->_M_value)) + near_node = static_cast(probe->_M_right); else - near_node = probe->_M_left; + near_node = static_cast(probe->_M_left); if (near_node // only visit node's children if node's plane intersect hypersphere - && (sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast* >(probe)->_M_value)) <= __max)) + && (std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max)) { probe = near_node; ++probe_dim; @@ -254,27 +254,27 @@ namespace KDTree { while (probe != cur) { - if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, static_cast* >(probe)->_M_value)) + if (_S_node_compare(probe_dim % __k, __cmp, __acc, __val, probe->_M_value)) { - near_node = probe->_M_left; - far_node = probe->_M_right; + near_node = static_cast(probe->_M_left); + far_node = static_cast(probe->_M_right); } else { - near_node = probe->_M_right; - far_node = probe->_M_left; + near_node = static_cast(probe->_M_right); + far_node = static_cast(probe->_M_left); } if (pprobe == probe->_M_parent) // going downward ... { - if (__p(static_cast* >(probe)->_M_value)) + 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, static_cast* >(probe)->_M_value); - d = sqrt(d); + d += _S_node_distance(i, __dist, __acc, __val, probe->_M_value); + d = std::sqrt(d); if (d <= __max) // CHANGED, see the above notes ("bad candidate notes") { - __best = static_cast* >(probe); + __best = probe; __max = d; __dim = probe_dim; } @@ -287,14 +287,14 @@ namespace KDTree } else if (far_node && // only visit node's children if node's plane intersect hypersphere - sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast* >(probe)->_M_value)) <= __max) + std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max) { probe = far_node; ++probe_dim; } else { - probe = probe->_M_parent; + probe = static_cast(probe->_M_parent); --probe_dim; } } @@ -302,7 +302,7 @@ namespace KDTree { if (pprobe == near_node && far_node // only visit node's children if node's plane intersect hypersphere - && sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, static_cast* >(probe)->_M_value)) <= __max) + && std::sqrt(_S_node_distance(probe_dim % __k, __dist, __acc, __val, probe->_M_value)) <= __max) { pprobe = probe; probe = far_node; @@ -311,13 +311,13 @@ namespace KDTree else { pprobe = probe; - probe = probe->_M_parent; + probe = static_cast(probe->_M_parent); --probe_dim; } } } pcur = cur; - cur = cur->_M_parent; + cur = static_cast(cur->_M_parent); --cur_dim; pprobe = cur; probe = cur; @@ -325,19 +325,19 @@ namespace KDTree if (cur != __end) { if (pcur == cur->_M_left) - near_node = cur->_M_right; + near_node = static_cast(cur->_M_right); else - near_node = cur->_M_left; + near_node = static_cast(cur->_M_left); if (near_node // only visit node's children if node's plane intersect hypersphere - && (sqrt(_S_node_distance(cur_dim % __k, __dist, __acc, __val, static_cast* >(cur)->_M_value)) <= __max)) + && (std::sqrt(_S_node_distance(cur_dim % __k, __dist, __acc, __val, cur->_M_value)) <= __max)) { probe = near_node; ++probe_dim; } } } - return std::pair*, + return std::pair > (__best, std::pair (__dim, __max)); diff --git a/src/3rdParty/libkdtree/kdtree++/region.hpp b/src/3rdParty/libkdtree/kdtree++/region.hpp index 98acab1d99..6e5a750502 100644 --- a/src/3rdParty/libkdtree/kdtree++/region.hpp +++ b/src/3rdParty/libkdtree/kdtree++/region.hpp @@ -9,7 +9,7 @@ #include -#include +#include "node.hpp" namespace KDTree { @@ -27,7 +27,7 @@ namespace KDTree typedef std::pair<_Region,_SubVal> _CenterPt; _Region(_Acc const& __acc=_Acc(), const _Cmp& __cmp=_Cmp()) - : _M_cmp(__acc), _M_acc(__cmp) {} + : _M_cmp(__cmp), _M_acc(__acc) {} template _Region(Val const& __V, diff --git a/src/3rdParty/libkdtree/python-bindings/gen-swig-hpp.py b/src/3rdParty/libkdtree/python-bindings/gen-swig-hpp.py old mode 100644 new mode 100755 diff --git a/src/3rdParty/libkdtree/python-bindings/py-kdtree_test.py b/src/3rdParty/libkdtree/python-bindings/py-kdtree_test.py index d236f13706..4227b71969 100644 --- a/src/3rdParty/libkdtree/python-bindings/py-kdtree_test.py +++ b/src/3rdParty/libkdtree/python-bindings/py-kdtree_test.py @@ -6,11 +6,6 @@ import unittest from kdtree import KDTree_2Int, KDTree_4Int, KDTree_3Float, KDTree_4Float, KDTree_6Float -try: - long -except NameError: - long = int - class KDTree_2IntTestCase(unittest.TestCase): def test_empty(self):