update libkdtree
switch to version 0.7.4 fix for a compiler warning inkdtree++/region.hpp fixes of warnings, latest c++ standard compatibility. .
This commit is contained in:
2
src/3rdParty/libkdtree/CMakeLists.txt
vendored
2
src/3rdParty/libkdtree/CMakeLists.txt
vendored
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
project (libkdtree CXX)
|
||||
cmake_minimum_required (VERSION 2.6.0)
|
||||
|
||||
option (BUILD_PYTHON_BINDINGS "Build Python bindings (requires SWIG)")
|
||||
|
||||
|
||||
2
src/3rdParty/libkdtree/COPYING
vendored
2
src/3rdParty/libkdtree/COPYING
vendored
@@ -1,6 +1,6 @@
|
||||
"The Artistic Licence 2.0"
|
||||
Copyright (c) 2000-2006, The Perl Foundation.
|
||||
https://www.perlfoundation.org/artistic-license-20.html
|
||||
http://www.perlfoundation.org/legal/licenses/artistic-2_0.html
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
236
src/3rdParty/libkdtree/ChangeLog
vendored
236
src/3rdParty/libkdtree/ChangeLog
vendored
@@ -1,236 +0,0 @@
|
||||
libkdtree++ ChangeLog
|
||||
=====================
|
||||
|
||||
2008-11-17 Sylvain Bougerel <sylvain.bougerel@asia.thalesgroup.com>
|
||||
|
||||
- Added #include<cstdio> in order to compile 'printf' statements in the
|
||||
file 'examples/test_find_within_range.cpp'.
|
||||
- Added patch from Max Fellermann in order to compile libkdtree++ with
|
||||
clang++.
|
||||
|
||||
2009-02-10 Paul Harris <paulharris@computer.org>
|
||||
|
||||
- Bug fix: was incorrectly casting a pointer when the search key type
|
||||
was different to the stored type.
|
||||
|
||||
2008-12-30 Paul Harris <paulharris@computer.org>
|
||||
|
||||
- New function: efficient_replace_and_optimise().
|
||||
Yes, its a long name. Sylvain doesn't like it.
|
||||
The reason for the long name is that it is a dangerous function,
|
||||
and it will resort whatever vector<> of data that you pass it.
|
||||
So I wanted the user to really know what they were doing before
|
||||
they called this function.
|
||||
- Now calls sqrt() when required in order to search for items
|
||||
in 'real' distance units... And so it will accept and return distance
|
||||
in 'real' units (as opposed to squared units).
|
||||
This is not an ideal solution, we have all sorts of ideas to improve
|
||||
kdtree which will include less calls to sqrt() for more speed, and
|
||||
the ability to change the standard euclidean distance measurements
|
||||
for distance-on-a-sphere or whatever the user wants.
|
||||
- Changed from using std::sort() to std::nth_element() when optimising
|
||||
the tree. Performance boost.
|
||||
- Added lots of tests to check that the find functions are working
|
||||
correctly when fed edge-cases, including:
|
||||
- Items that are exactly 'max' distance away from the target.
|
||||
- When there are no value items to find.
|
||||
- Templated the find functions so that the target/center point can be
|
||||
anything that can be accessed via the Accessor.
|
||||
- Fixes to make it compile.
|
||||
|
||||
- And, a Python wrapper ! See README.Python
|
||||
|
||||
- CMake support now can build the python wrapper and install the headers
|
||||
and the python wrapper to a destination folder. Its simple, but neat.
|
||||
Does not install python module into the python site packages or anything
|
||||
like that.
|
||||
|
||||
2008-11-17 Sylvain Bougerel <sylvain.bougerel@asia.thalesgroup.com>
|
||||
|
||||
- The version number of the library is now part of the headers.
|
||||
- Fixed a bug with assignment operator.
|
||||
- Fixed uninitialized memory problem with valgrind, when printing the
|
||||
content of the tree. Due to the fact the _M_header was a _Link_type
|
||||
instead of a _Node_base type and _M_root was a _Base_ptr type instead of
|
||||
a _Link_type.
|
||||
- Paul Harris fixed find() by ensuring that the correct node is being
|
||||
matched during a find(). Thus, fixed a similar problem in erase. Paul
|
||||
also added a new test courtesy of Hayne.
|
||||
- Paul Harris augmented test_kdtree with various test on copy
|
||||
construction, assignment, and formatting operator.
|
||||
- Paul Harris added support for CMake, which should suit not only
|
||||
MSVC users but others too.
|
||||
- Paul Harris fixed bug with compiling with MSVC2005 with the 64bit
|
||||
warnings turned on.
|
||||
|
||||
2008-11-12 Sylvain Bougerel <sylvain.bougerel@asia.thalesgroup.com>
|
||||
|
||||
- Fix segfault on the regular iterator when _M_header->_M_right ==
|
||||
_M_root. Fix segfault on the reverse iterator when _M_header->_M_left ==
|
||||
_M_root.
|
||||
|
||||
Besides, it also change the behavior when iterating past the end() or
|
||||
rend(). Previously this would result in segfaults, now it makes the
|
||||
iterator points to an undetermined location in the tree, similarly to
|
||||
the current implementation of GNU libstdc++.
|
||||
|
||||
2008-11-10 Sylvain Bougerel <sylvain.bougerel@asia.thalesgroup.com>
|
||||
|
||||
- kdtree++/iterator.hpp (KDTree): the decrement iterator was
|
||||
ill-written. Its buggy behavior, and the use of non-standard
|
||||
reverse_iterator initialiser needed to be fixed. These error were do to
|
||||
a previous failed attempt by me at fixing the reverse_iterator.
|
||||
|
||||
This time, I believe I got it right, however it needed the kdtree
|
||||
structure to be modified. The reason is that without modification it is
|
||||
not possible to distinguish the "header" from the "root" within the
|
||||
iterator. This is required for the reverse_iterator to work properly.
|
||||
|
||||
Now the kdtree has an additional pointer that points directly to the
|
||||
root. The parent pointer of the header is permanently null. And
|
||||
therefore the header can be distinguished from the root within the
|
||||
iterator by checking the parent of the current node: if it is null, we
|
||||
are at the header.
|
||||
|
||||
|
||||
2008-11-10 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com)
|
||||
|
||||
- patch from Martin Shreiber to make libkdtree to compile with newer
|
||||
version of g++-4.2 and g++4.3.
|
||||
|
||||
- patch from Paul Harris to make libkdtree more exception transparent.
|
||||
|
||||
2007-12-08 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com)
|
||||
|
||||
- fix bug where find_nearest() could return the wrong value if a
|
||||
maximum distance greater than the root distance to the target value
|
||||
was given in argument to the function.
|
||||
|
||||
- find_nearest() still returns SQUARED value of the distance. You still
|
||||
have to use sqrt() on the second member of the iterator.
|
||||
|
||||
- find_nearest() behavior was slightly changed: if many nodes are at
|
||||
the same distance from the target value, the node with the lowest
|
||||
memory address will be returned. This is to catter for the
|
||||
reimplementation of find_exact() coming soon.
|
||||
|
||||
2007-12-02 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com)
|
||||
|
||||
- find_nearest() now returned the SQUARED value of the distance for
|
||||
euclidean space calculation (the default). You have to use sqrt() on
|
||||
the returned distance (i.e. iterator->second) if you want to read the
|
||||
absolute distance returned by find_nearest. My apologies for not
|
||||
making highlighting this beforehand.
|
||||
|
||||
- Increased the performance of find and find_nearest/find_nearest_if by
|
||||
about 50x to 100x depending on your compilation flags.
|
||||
|
||||
- KDTree are not defined as:
|
||||
KDTree<__K, _Val, _Acc, _Cmp, _Alloc>
|
||||
but as:
|
||||
KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc>
|
||||
So pay attention to the _Dist functor. The distance functor calculate
|
||||
the squared difference between 2 elements returned by the accessor. You
|
||||
might have to change your code to reflect the new definition, or it wont
|
||||
compile if you have set custom accessor and comparison functors.
|
||||
|
||||
- The following functors are now accessible in the tree:
|
||||
- the comparison functor, accessible by copy only
|
||||
- the accessor functor, accessible by copy only
|
||||
- the distance functor, accessible read-write, this means that
|
||||
you can modify the behavior of find, find_nearest,
|
||||
find_nearest_if within the same KDTree object.
|
||||
|
||||
- find_exact has not be modified and retained the code of the former,
|
||||
slower algorithm. I have to write some more code to do this. Pls wait a
|
||||
little more.
|
||||
|
||||
- The file accessor.hpp was renamed as function.hpp for it now boast
|
||||
more than just the KDTree accessor
|
||||
|
||||
2007-11-25 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com)
|
||||
|
||||
- fixed the reverse_iterator. Now it can be used.
|
||||
|
||||
2007-10-24 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com)
|
||||
|
||||
- Removal of all the warnings that are yield by the compiler when
|
||||
using the following flags:
|
||||
-Wall -pedantic -ansi
|
||||
Do not hesitate to suggest any flags for additional code checking.
|
||||
|
||||
This release also feature numerous of enhancements by Paul Harris
|
||||
(paulharris@computer.org):
|
||||
- const kdtrees can be searched
|
||||
- find_nearest_if() enforce validation of a predicate
|
||||
- visit_within_range() walk the tree and calls
|
||||
Visitor::operator() on template argument <Visitor> for
|
||||
each node within the range
|
||||
- find_exact() matches an kdtree::value_type by location and by
|
||||
calling kdtree::value_type::operator==() (in case two different
|
||||
items have the same location find_exact() will not return the
|
||||
wrong item)
|
||||
- erase_exact() is to erase() what find_exact() is to find()
|
||||
- check_tree() and num_dist_calcs for debugging purpose plus
|
||||
additional improvements on erase and region intersection
|
||||
|
||||
2004-11-26 Paul Harris (paulharris@computer.org)
|
||||
|
||||
- New feature: find_nearest()
|
||||
- Accessors can now be initialised with the tree, so ptr_fun()
|
||||
or functors can be used to access datapoints.
|
||||
- Accessors now much more generic, so you can use the same
|
||||
accessor to access multiple types.
|
||||
- Range-constructors now optimise() automatically, simplifying
|
||||
the construction of a filled tree.
|
||||
- _Range is now more easy to construct.
|
||||
|
||||
2004-11-15 Martin F. Krafft (libkdtree@pobox.madduck.net)
|
||||
|
||||
- fixed numerous little bugs that led to compilation problems
|
||||
- changed code to compile cleanly with GCC 3.4 and GCC 4.0
|
||||
|
||||
2004-11-06 Martin F. Krafft (libkdtree@pobox.madduck.net)
|
||||
|
||||
- reverted to optimise() to prevent API change, and added an optimize()
|
||||
passthrough method with an appropriate comment.
|
||||
|
||||
2004-11-05 Paul Harris (paulharris@computer.org)
|
||||
|
||||
- Renamed optimise() to optimize().
|
||||
- Added a full set of range constructors and insert(range) methods.
|
||||
it now works with inserter(tree,tree.begin())
|
||||
- Target type no longer needs a default constructor. This also fixes
|
||||
problems with empty trees (would crash if optimized).
|
||||
- Some code cleanup (removed inlines, switched from const_iterator to
|
||||
iterator, added this-> to ensure the methods are called).
|
||||
- Added a new method: count_within_range().
|
||||
- Fixed bug in rend().
|
||||
|
||||
2004-11-04 Martin F. Krafft (libkdtree@pobox.madduck.net)
|
||||
|
||||
- Integrated patch by Paul Harris to fix a logic error pertaining to
|
||||
OutputIterators in find_within_range. find_within_range() now
|
||||
returns the output iterator instead of a count. Thanks, Paul!
|
||||
- Added another fix by Paul Harris to _M_get_j_max, which would cause
|
||||
a dimensional overflow for trees with depths >= K. Thanks (again) Paul!
|
||||
- Made some improvements to the autotools files.
|
||||
|
||||
2004-05-11 Martin F. Krafft (libkdtree@pobox.madduck.net)
|
||||
|
||||
- Fixed CFlags and Libs entries in pkgconfig file.
|
||||
|
||||
2004-05-11 Martin F. Krafft (libkdtree@pobox.madduck.net)
|
||||
|
||||
- Initial release.
|
||||
|
||||
|
||||
COPYRIGHT --
|
||||
libkdtree++ is (c) 2004-2007 Martin F. Krafft <libkdtree@pobox.madduck.net> and
|
||||
Sylvain Bougerel <sylvain.bougerel.devel@gmail.com> and distributed under the
|
||||
terms of the Artistic License 2.0. See the ./COPYING file in the source tree
|
||||
root for more information.
|
||||
|
||||
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
10
src/3rdParty/libkdtree/README.md
vendored
10
src/3rdParty/libkdtree/README.md
vendored
@@ -24,12 +24,12 @@ Please leave bugreports on Github Issues page <https://github.com/nvmd/libkdtree
|
||||
Historical background
|
||||
---------------------
|
||||
|
||||
In the past, this library was available from [http://libkdtree.alioth.debian.org/](https://web.archive.org/web/20180422154001/http://libkdtree.alioth.debian.org/).
|
||||
This page seems to be gone now, available only via [WebArchive](https://web.archive.org/web/20180422154001/http://libkdtree.alioth.debian.org/).
|
||||
In the past, this library was available from <http://libkdtree.alioth.debian.org/>.
|
||||
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 are preserved below.
|
||||
Notes of the original author a preserved below.
|
||||
|
||||
Installation
|
||||
------------
|
||||
@@ -114,8 +114,8 @@ 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)
|
||||
orbitz, quix, Erwin, pwned, wcstok, dasOp, Chaku, Adrinael, The_Vulture, and
|
||||
LIM2 (if I left anyone out, let me know). Finally, I thank the Artificial
|
||||
Intelligence Laboratory of the University of Zurich, Dr. Peter Eggenberger, and
|
||||
Gabriel Gómez for giving me the opportunity to write this stuff.
|
||||
Intelligence Laboratory of the University of Zurich, Dr. Peter Eggenberger and
|
||||
Gabriel Gómez for giving me the opportunity to write this stuff.
|
||||
|
||||
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++
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
add_executable (test_hayne test_hayne.cpp)
|
||||
add_executable (test_kdtree test_kdtree.cpp)
|
||||
add_executable (test_find_within_range test_find_within_range.cpp)
|
||||
@@ -1,108 +0,0 @@
|
||||
// Thanks to James Remillard
|
||||
//
|
||||
#include <cstdio>
|
||||
#include <kdtree++/kdtree.hpp>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct kdtreeNode
|
||||
{
|
||||
typedef double value_type;
|
||||
|
||||
double xyz[3];
|
||||
size_t index;
|
||||
|
||||
value_type operator[](size_t n) const
|
||||
{
|
||||
return xyz[n];
|
||||
}
|
||||
|
||||
double distance( const kdtreeNode &node)
|
||||
{
|
||||
double x = xyz[0] - node.xyz[0];
|
||||
double y = xyz[1] - node.xyz[1];
|
||||
double z = xyz[2] - node.xyz[2];
|
||||
|
||||
// this is not correct return sqrt( x*x+y*y+z*z);
|
||||
|
||||
// this is what kdtree checks with find_within_range()
|
||||
// the "manhattan distance" from the search point.
|
||||
// effectively, distance is the maximum distance in any one dimension.
|
||||
return max(fabs(x),max(fabs(y),fabs(z)));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
vector<kdtreeNode> pts;
|
||||
|
||||
typedef KDTree::KDTree<3,kdtreeNode> treeType;
|
||||
|
||||
treeType tree;
|
||||
|
||||
// make random 3d points
|
||||
for ( size_t n = 0; n < 10000; ++n)
|
||||
{
|
||||
kdtreeNode node;
|
||||
node.xyz[0] = double(rand())/RAND_MAX;
|
||||
node.xyz[1] = double(rand())/RAND_MAX;
|
||||
node.xyz[2] = double(rand())/RAND_MAX;
|
||||
node.index = n;
|
||||
|
||||
tree.insert( node);
|
||||
pts.push_back( node);
|
||||
}
|
||||
|
||||
for (size_t r = 0; r < 1000; ++r)
|
||||
{
|
||||
kdtreeNode refNode;
|
||||
refNode.xyz[0] = double(rand())/RAND_MAX;
|
||||
refNode.xyz[1] = double(rand())/RAND_MAX;
|
||||
refNode.xyz[2] = double(rand())/RAND_MAX;
|
||||
|
||||
double limit = double(rand())/RAND_MAX;
|
||||
|
||||
// find the correct return list by checking every single point
|
||||
set<size_t> correctCloseList;
|
||||
|
||||
for ( size_t i= 0; i < pts.size(); ++i)
|
||||
{
|
||||
double dist = refNode.distance( pts[i]);
|
||||
if ( dist < limit)
|
||||
correctCloseList.insert( i );
|
||||
}
|
||||
|
||||
// now do the same with the kdtree.
|
||||
vector<kdtreeNode> howClose;
|
||||
tree.find_within_range(refNode,limit,back_insert_iterator<vector<kdtreeNode> >(howClose));
|
||||
|
||||
// make sure no extra points are returned, and the return has no missing points.
|
||||
for ( size_t i = 0; i < howClose.size(); ++i)
|
||||
{
|
||||
set<size_t>::iterator hit = correctCloseList.find( howClose[i].index);
|
||||
|
||||
if ( hit != correctCloseList.end())
|
||||
{
|
||||
correctCloseList.erase(hit);
|
||||
}
|
||||
else
|
||||
{
|
||||
// point that is too far away - fail!
|
||||
assert(false);
|
||||
printf("fail, extra points.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// fail, not all of the close enough points returned.
|
||||
assert( correctCloseList.size() == 0);
|
||||
if ( correctCloseList.size() > 0)
|
||||
{
|
||||
printf("fail, missing points.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
116
src/3rdParty/libkdtree/examples/test_hayne.cpp
vendored
116
src/3rdParty/libkdtree/examples/test_hayne.cpp
vendored
@@ -1,116 +0,0 @@
|
||||
#define KDTREE_SIZE_T unsigned int
|
||||
#include <kdtree++/kdtree.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct duplet
|
||||
{
|
||||
typedef int value_type;
|
||||
|
||||
inline value_type operator[](int const N) const { return d[N]; }
|
||||
|
||||
inline bool operator==(duplet const& other) const
|
||||
{
|
||||
return this->d[0] == other.d[0] && this->d[1] == other.d[1];
|
||||
}
|
||||
|
||||
inline bool operator!=(duplet const& other) const
|
||||
{
|
||||
return this->d[0] != other.d[0] || this->d[1] != other.d[1];
|
||||
}
|
||||
|
||||
friend ostream & operator<<(ostream & o, duplet const& d)
|
||||
{
|
||||
return o << "(" << d[0] << "," << d[1] << ")";
|
||||
}
|
||||
|
||||
value_type d[2];
|
||||
};
|
||||
|
||||
typedef KDTree::KDTree<2, duplet, std::pointer_to_binary_function<duplet,int,double> > duplet_tree_type;
|
||||
|
||||
inline double return_dup( duplet d, int k ) { return d[k]; }
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
duplet_tree_type dupl_tree_test(std::ptr_fun(return_dup));
|
||||
std::vector<duplet> vDuplets;
|
||||
|
||||
//srand(time(0));
|
||||
int randy1 = 0;
|
||||
int randy2 = 0;
|
||||
for (int i=0; i<700; i++)
|
||||
{
|
||||
//create coordinate for new duplet
|
||||
randy1+=2;
|
||||
randy1=randy1%255;
|
||||
randy2+=3;
|
||||
randy2=randy2%255;
|
||||
//randy1 = rand() % 255;
|
||||
//randy2 = rand() % 255;
|
||||
|
||||
//new duplet
|
||||
duplet super_dupre = { {randy1, randy2} };
|
||||
|
||||
//check if duplet with same coordinate already in vector/tree. If not: insert in vector and tree
|
||||
duplet_tree_type::iterator pItr = dupl_tree_test.find_nearest(super_dupre,std::numeric_limits<double>::max()).first;
|
||||
if (*pItr!=super_dupre)
|
||||
{
|
||||
dupl_tree_test.insert(super_dupre);
|
||||
vDuplets.push_back(super_dupre);
|
||||
}
|
||||
}
|
||||
|
||||
dupl_tree_test.optimise();
|
||||
|
||||
size_t elements;
|
||||
|
||||
while (vDuplets.size() > 0) //delete all duplets from tree which are in the vector
|
||||
{
|
||||
elements = vDuplets.size();
|
||||
|
||||
duplet element_to_erase = vDuplets.back();
|
||||
vDuplets.pop_back();
|
||||
|
||||
if (vDuplets.size() == 147)
|
||||
cout << "THIS IS THE BUG TRIGGER" << endl;
|
||||
|
||||
cout << vDuplets.size() << " : Deleting " << element_to_erase << endl;
|
||||
|
||||
assert( find(dupl_tree_test.begin(),dupl_tree_test.end(), element_to_erase) != dupl_tree_test.end() );
|
||||
assert(dupl_tree_test.find(element_to_erase) != dupl_tree_test.end());
|
||||
|
||||
duplet_tree_type::iterator will = dupl_tree_test.find(element_to_erase);
|
||||
duplet_tree_type::iterator should = dupl_tree_test.find_exact(element_to_erase);
|
||||
|
||||
cout << " tree will delete: " << *will << endl;
|
||||
cout << " tree should delete: " << *should << endl;
|
||||
|
||||
assert(*will == *should);
|
||||
|
||||
dupl_tree_test.erase(element_to_erase); //erase() : will probably erase wrong element sooner or later
|
||||
//dupl_tree_test.erase_exact(element_to_erase); --> this works
|
||||
|
||||
// now check that it cannot find the element UNLESS there is another one with the identical location in the list...
|
||||
if (find(vDuplets.begin(),vDuplets.end(),element_to_erase) == vDuplets.end())
|
||||
{
|
||||
duplet_tree_type::iterator not_there = dupl_tree_test.find(element_to_erase);
|
||||
if (not_there != dupl_tree_test.end())
|
||||
{
|
||||
cout << "SHOULD NOT HAVE FOUND THIS: " << *not_there << endl;
|
||||
assert(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << " find() double-check passed." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
424
src/3rdParty/libkdtree/examples/test_kdtree.cpp
vendored
424
src/3rdParty/libkdtree/examples/test_kdtree.cpp
vendored
@@ -1,424 +0,0 @@
|
||||
#define KDTREE_DEFINE_OSTREAM_OPERATORS
|
||||
|
||||
// Make SURE all our asserts() are checked
|
||||
#undef NDEBUG
|
||||
|
||||
#include <kdtree++/kdtree.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
// used to ensure all triplets that are accessed via the operator<< are initialised.
|
||||
std::set<const void*> registered;
|
||||
|
||||
struct triplet
|
||||
{
|
||||
typedef double value_type;
|
||||
|
||||
triplet(value_type a, value_type b, value_type c)
|
||||
{
|
||||
d[0] = a;
|
||||
d[1] = b;
|
||||
d[2] = c;
|
||||
bool reg_ok = (registered.find(this) == registered.end());
|
||||
assert(reg_ok);
|
||||
bool reg_inserted_ok = registered.insert(this).second;
|
||||
assert(reg_inserted_ok);
|
||||
}
|
||||
|
||||
triplet(const triplet & x)
|
||||
{
|
||||
d[0] = x.d[0];
|
||||
d[1] = x.d[1];
|
||||
d[2] = x.d[2];
|
||||
bool reg_ok = (registered.find(this) == registered.end());
|
||||
assert(reg_ok);
|
||||
bool reg_inserted_ok = registered.insert(this).second;
|
||||
assert(reg_inserted_ok);
|
||||
}
|
||||
|
||||
~triplet()
|
||||
{
|
||||
bool unreg_ok = (registered.find(this) != registered.end());
|
||||
assert(unreg_ok);
|
||||
registered.erase(this);
|
||||
}
|
||||
|
||||
double distance_to(triplet const& x) const
|
||||
{
|
||||
double dist = 0;
|
||||
for (int i = 0; i != 3; ++i)
|
||||
dist += (d[i]-x.d[i])*(d[i]-x.d[i]);
|
||||
return std::sqrt(dist);
|
||||
}
|
||||
|
||||
inline value_type operator[](size_t const N) const { return d[N]; }
|
||||
|
||||
value_type d[3];
|
||||
};
|
||||
|
||||
|
||||
|
||||
// same as triplet, except with the values reversed.
|
||||
struct alternate_triplet
|
||||
{
|
||||
typedef double value_type;
|
||||
|
||||
alternate_triplet(const triplet & x)
|
||||
{
|
||||
d[0] = x.d[2];
|
||||
d[1] = x.d[1];
|
||||
d[2] = x.d[0];
|
||||
}
|
||||
|
||||
inline value_type operator[](size_t const N) const { return d[2-N]; }
|
||||
|
||||
value_type d[3];
|
||||
};
|
||||
|
||||
inline bool operator==(triplet const& A, triplet const& B) {
|
||||
return A.d[0] == B.d[0] && A.d[1] == B.d[1] && A.d[2] == B.d[2];
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, triplet const& T)
|
||||
{
|
||||
assert(registered.find(&T) != registered.end());
|
||||
return out << '(' << T.d[0] << ',' << T.d[1] << ',' << T.d[2] << ')';
|
||||
}
|
||||
|
||||
inline double tac( triplet t, size_t k ) { return t[k]; }
|
||||
|
||||
// use tac as a class instead of a function,
|
||||
// can access more than one type with just 1 definition.
|
||||
struct alternate_tac
|
||||
{
|
||||
typedef double result_type;
|
||||
double operator()( triplet const& t, size_t k ) const { return t[k]; }
|
||||
double operator()( alternate_triplet const& t, size_t k ) const { return t[k]; }
|
||||
};
|
||||
|
||||
|
||||
typedef KDTree::KDTree<3, triplet, std::pointer_to_binary_function<triplet,size_t,double> > tree_type;
|
||||
|
||||
struct Predicate
|
||||
{
|
||||
bool operator()( triplet const& t ) const
|
||||
{
|
||||
return t[0] > 3; // anything, we are currently testing that it compiles.
|
||||
}
|
||||
};
|
||||
|
||||
// never finds anything
|
||||
struct FalsePredicate
|
||||
{
|
||||
bool operator()( triplet const& t ) const { return false; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// check that it'll find nodes exactly MAX away
|
||||
{
|
||||
tree_type exact_dist(std::ptr_fun(tac));
|
||||
triplet c0(5, 4, 0);
|
||||
exact_dist.insert(c0);
|
||||
triplet target(7,4,0);
|
||||
|
||||
std::pair<tree_type::const_iterator,double> found = exact_dist.find_nearest(target,2);
|
||||
assert(found.first != exact_dist.end());
|
||||
assert(found.second == 2);
|
||||
std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << std::endl;
|
||||
}
|
||||
|
||||
// do the same test, except use alternate_triplet as the search key
|
||||
{
|
||||
// NOTE: stores triplet, but we search with alternate_triplet
|
||||
typedef KDTree::KDTree<3, triplet, alternate_tac> alt_tree;
|
||||
|
||||
triplet actual_target(7,0,0);
|
||||
|
||||
alt_tree tree;
|
||||
tree.insert( triplet(0, 0, 7) );
|
||||
tree.insert( triplet(0, 0, 7) );
|
||||
tree.insert( triplet(0, 0, 7) );
|
||||
tree.insert( triplet(3, 0, 0) );
|
||||
tree.insert( actual_target );
|
||||
tree.optimise();
|
||||
|
||||
alternate_triplet target( actual_target );
|
||||
|
||||
std::pair<alt_tree::const_iterator,double> found = tree.find_nearest(target);
|
||||
assert(found.first != tree.end());
|
||||
std::cout << "Test with alternate search type, found: " << *found.first << ", wanted " << actual_target << std::endl;
|
||||
assert(found.second == 0);
|
||||
assert(*found.first == actual_target);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
tree_type exact_dist(std::ptr_fun(tac));
|
||||
triplet c0(5, 2, 0);
|
||||
exact_dist.insert(c0);
|
||||
triplet target(7,4,0);
|
||||
|
||||
// call find_nearest without a range value - it found a compile error earlier.
|
||||
std::pair<tree_type::const_iterator,double> found = exact_dist.find_nearest(target);
|
||||
assert(found.first != exact_dist.end());
|
||||
std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << " @ " << found.second << " should be " << std::sqrt(8) << std::endl;
|
||||
assert(found.second == std::sqrt(8));
|
||||
}
|
||||
|
||||
{
|
||||
tree_type exact_dist(std::ptr_fun(tac));
|
||||
triplet c0(5, 2, 0);
|
||||
exact_dist.insert(c0);
|
||||
triplet target(7,4,0);
|
||||
|
||||
std::pair<tree_type::const_iterator,double> found = exact_dist.find_nearest(target,std::sqrt(8));
|
||||
assert(found.first != exact_dist.end());
|
||||
std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << " @ " << found.second << " should be " << std::sqrt(8) << std::endl;
|
||||
assert(found.second == std::sqrt(8));
|
||||
}
|
||||
|
||||
tree_type src(std::ptr_fun(tac));
|
||||
|
||||
triplet c0(5, 4, 0); src.insert(c0);
|
||||
triplet c1(4, 2, 1); src.insert(c1);
|
||||
triplet c2(7, 6, 9); src.insert(c2);
|
||||
triplet c3(2, 2, 1); src.insert(c3);
|
||||
triplet c4(8, 0, 5); src.insert(c4);
|
||||
triplet c5(5, 7, 0); src.insert(c5);
|
||||
triplet c6(3, 3, 8); src.insert(c6);
|
||||
triplet c7(9, 7, 3); src.insert(c7);
|
||||
triplet c8(2, 2, 6); src.insert(c8);
|
||||
triplet c9(2, 0, 6); src.insert(c9);
|
||||
|
||||
std::cout << src << std::endl;
|
||||
|
||||
src.erase(c0);
|
||||
src.erase(c1);
|
||||
src.erase(c3);
|
||||
src.erase(c5);
|
||||
|
||||
src.optimise();
|
||||
|
||||
|
||||
// test the efficient_replace_and_optimise()
|
||||
tree_type eff_repl = src;
|
||||
{
|
||||
std::vector<triplet> vec;
|
||||
// erased above as part of test vec.push_back(triplet(5, 4, 0));
|
||||
// erased above as part of test vec.push_back(triplet(4, 2, 1));
|
||||
vec.push_back(triplet(7, 6, 9));
|
||||
// erased above as part of test vec.push_back(triplet(2, 2, 1));
|
||||
vec.push_back(triplet(8, 0, 5));
|
||||
// erased above as part of test vec.push_back(triplet(5, 7, 0));
|
||||
vec.push_back(triplet(3, 3, 8));
|
||||
vec.push_back(triplet(9, 7, 3));
|
||||
vec.push_back(triplet(2, 2, 6));
|
||||
vec.push_back(triplet(2, 0, 6));
|
||||
|
||||
eff_repl.clear();
|
||||
eff_repl.efficient_replace_and_optimise(vec);
|
||||
}
|
||||
|
||||
|
||||
std::cout << std::endl << src << std::endl;
|
||||
|
||||
tree_type copied(src);
|
||||
std::cout << copied << std::endl;
|
||||
tree_type assigned = src;
|
||||
std::cout << assigned << std::endl;
|
||||
|
||||
for (int loop = 0; loop != 4; ++loop)
|
||||
{
|
||||
tree_type * target;
|
||||
switch (loop)
|
||||
{
|
||||
case 0: std::cout << "Testing plain construction" << std::endl;
|
||||
target = &src;
|
||||
break;
|
||||
|
||||
case 1: std::cout << "Testing copy-construction" << std::endl;
|
||||
target = &copied;
|
||||
break;
|
||||
|
||||
case 2: std::cout << "Testing assign-construction" << std::endl;
|
||||
target = &assigned;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 4: std::cout << "Testing efficient-replace-and-optimise" << std::endl;
|
||||
target = &eff_repl;
|
||||
break;
|
||||
}
|
||||
tree_type & t = *target;
|
||||
|
||||
int i=0;
|
||||
for (tree_type::const_iterator iter=t.begin(); iter!=t.end(); ++iter, ++i);
|
||||
std::cout << "iterator walked through " << i << " nodes in total" << std::endl;
|
||||
if (i!=6)
|
||||
{
|
||||
std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
i=0;
|
||||
for (tree_type::const_reverse_iterator iter=t.rbegin(); iter!=t.rend(); ++iter, ++i);
|
||||
std::cout << "reverse_iterator walked through " << i << " nodes in total" << std::endl;
|
||||
if (i!=6)
|
||||
{
|
||||
std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
triplet s(5, 4, 3);
|
||||
std::vector<triplet> v;
|
||||
unsigned int const RANGE = 3;
|
||||
|
||||
size_t count = t.count_within_range(s, RANGE);
|
||||
std::cout << "counted " << count
|
||||
<< " nodes within range " << RANGE << " of " << s << ".\n";
|
||||
t.find_within_range(s, RANGE, std::back_inserter(v));
|
||||
|
||||
std::cout << "found " << v.size() << " nodes within range " << RANGE
|
||||
<< " of " << s << ":\n";
|
||||
std::vector<triplet>::const_iterator ci = v.begin();
|
||||
for (; ci != v.end(); ++ci)
|
||||
std::cout << *ci << " ";
|
||||
std::cout << "\n" << std::endl;
|
||||
|
||||
std::cout << std::endl << t << std::endl;
|
||||
|
||||
// search for all the nodes at exactly 0 dist away
|
||||
for (tree_type::const_iterator target = t.begin(); target != t.end(); ++target)
|
||||
{
|
||||
std::pair<tree_type::const_iterator,double> found = t.find_nearest(*target,0);
|
||||
assert(found.first != t.end());
|
||||
assert(*found.first == *target);
|
||||
std::cout << "Test find_nearest(), found at exact distance away from " << *target << ", found " << *found.first << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
const double small_dist = 0.0001;
|
||||
std::pair<tree_type::const_iterator,double> notfound = t.find_nearest(s,small_dist);
|
||||
std::cout << "Test find_nearest(), nearest to " << s << " within " << small_dist << " should not be found" << std::endl;
|
||||
|
||||
if (notfound.first != t.end())
|
||||
{
|
||||
std::cout << "ERROR found a node at dist " << notfound.second << " : " << *notfound.first << std::endl;
|
||||
std::cout << "Actual distance = " << s.distance_to(*notfound.first) << std::endl;
|
||||
}
|
||||
|
||||
assert(notfound.first == t.end());
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<tree_type::const_iterator,double> nif = t.find_nearest_if(s,std::numeric_limits<double>::max(),Predicate());
|
||||
std::cout << "Test find_nearest_if(), nearest to " << s << " @ " << nif.second << ": " << *nif.first << std::endl;
|
||||
|
||||
std::pair<tree_type::const_iterator,double> cantfind = t.find_nearest_if(s,std::numeric_limits<double>::max(),FalsePredicate());
|
||||
std::cout << "Test find_nearest_if(), nearest to " << s << " should never be found (predicate too strong)" << std::endl;
|
||||
assert(cantfind.first == t.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
std::pair<tree_type::const_iterator,double> found = t.find_nearest(s,std::numeric_limits<double>::max());
|
||||
std::cout << "Nearest to " << s << " @ " << found.second << " " << *found.first << std::endl;
|
||||
std::cout << "Should be " << found.first->distance_to(s) << std::endl;
|
||||
// NOTE: the assert does not check for an exact match, as it is not exact when -O2 or -O3 is
|
||||
// switched on. Some sort of optimisation makes the math inexact.
|
||||
assert( fabs(found.second - found.first->distance_to(s)) < std::numeric_limits<double>::epsilon() );
|
||||
}
|
||||
|
||||
{
|
||||
triplet s2(10, 10, 2);
|
||||
std::pair<tree_type::const_iterator,double> found = t.find_nearest(s2,std::numeric_limits<double>::max());
|
||||
std::cout << "Nearest to " << s2 << " @ " << found.second << " " << *found.first << std::endl;
|
||||
std::cout << "Should be " << found.first->distance_to(s2) << std::endl;
|
||||
// NOTE: the assert does not check for an exact match, as it is not exact when -O2 or -O3 is
|
||||
// switched on. Some sort of optimisation makes the math inexact.
|
||||
assert( fabs(found.second - found.first->distance_to(s2)) < std::numeric_limits<double>::epsilon() );
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << t << std::endl;
|
||||
|
||||
// Testing iterators
|
||||
{
|
||||
std::cout << "Testing iterators" << std::endl;
|
||||
|
||||
t.erase(c2);
|
||||
t.erase(c4);
|
||||
t.erase(c6);
|
||||
t.erase(c7);
|
||||
t.erase(c8);
|
||||
// t.erase(c9);
|
||||
|
||||
std::cout << std::endl << t << std::endl;
|
||||
|
||||
std::cout << "Forward iterator test..." << std::endl;
|
||||
std::vector<triplet> forwards;
|
||||
for (tree_type::iterator i = t.begin(); i != t.end(); ++i)
|
||||
{ std::cout << *i << " " << std::flush; forwards.push_back(*i); }
|
||||
std::cout << std::endl;
|
||||
std::cout << "Reverse iterator test..." << std::endl;
|
||||
std::vector<triplet> backwards;
|
||||
for (tree_type::reverse_iterator i = t.rbegin(); i != t.rend(); ++i)
|
||||
{ std::cout << *i << " " << std::flush; backwards.push_back(*i); }
|
||||
std::cout << std::endl;
|
||||
std::reverse(backwards.begin(),backwards.end());
|
||||
assert(backwards == forwards);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Walter reported that the find_within_range() wasn't giving results that were within
|
||||
// the specified range... this is the test.
|
||||
{
|
||||
tree_type tree(std::ptr_fun(tac));
|
||||
tree.insert( triplet(28.771200,16.921600,-2.665970) );
|
||||
tree.insert( triplet(28.553101,18.649700,-2.155560) );
|
||||
tree.insert( triplet(28.107500,20.341400,-1.188940) );
|
||||
tree.optimise();
|
||||
|
||||
std::deque< triplet > vectors;
|
||||
triplet sv(18.892500,20.341400,-1.188940);
|
||||
tree.find_within_range(sv, 10.0f, std::back_inserter(vectors));
|
||||
|
||||
std::cout << std::endl << "Test find_with_range( " << sv << ", 10.0f) found " << vectors.size() << " candidates." << std::endl;
|
||||
|
||||
// double-check the ranges
|
||||
for (std::deque<triplet>::iterator v = vectors.begin(); v != vectors.end(); ++v)
|
||||
{
|
||||
double dist = sv.distance_to(*v);
|
||||
std::cout << " " << *v << " dist=" << dist << std::endl;
|
||||
if (dist > 10.0f)
|
||||
std::cout << " This point is too far! But that is by design, its within a 'box' with a 'radius' of 10, not a sphere with a radius of 10" << std::endl;
|
||||
// Not a valid test, it can be greater than 10 if the point is in the corners of the box.
|
||||
// assert(dist <= 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* COPYRIGHT --
|
||||
*
|
||||
* This file is part of libkdtree++, a C++ template KD-Tree sorting container.
|
||||
* libkdtree++ is (c) 2004-2007 Martin F. Krafft <libkdtree@pobox.madduck.net>
|
||||
* and Sylvain Bougerel <sylvain.bougerel.devel@gmail.com> distributed under the
|
||||
* terms of the Artistic License 2.0. See the ./COPYING file in the source tree
|
||||
* root for more information.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
4
src/3rdParty/libkdtree/kdtree++/iterator.hpp
vendored
4
src/3rdParty/libkdtree/kdtree++/iterator.hpp
vendored
@@ -54,8 +54,8 @@ namespace KDTree
|
||||
|
||||
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()
|
||||
|
||||
5
src/3rdParty/libkdtree/kdtree++/kdtree.hpp
vendored
5
src/3rdParty/libkdtree/kdtree++/kdtree.hpp
vendored
@@ -53,12 +53,12 @@
|
||||
// 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 702
|
||||
#define KDTREE_VERSION 704
|
||||
//
|
||||
// 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_2"
|
||||
#define KDTREE_LIB_VERSION "0_7_4"
|
||||
|
||||
|
||||
#include <vector>
|
||||
@@ -1214,7 +1214,6 @@ protected:
|
||||
o << "dimensions: " << __K << std::endl;
|
||||
|
||||
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());
|
||||
|
||||
2
src/3rdParty/libkdtree/kdtree++/region.hpp
vendored
2
src/3rdParty/libkdtree/kdtree++/region.hpp
vendored
@@ -27,7 +27,7 @@ namespace KDTree
|
||||
typedef std::pair<_Region,_SubVal> _CenterPt;
|
||||
|
||||
_Region(_Acc const& __acc=_Acc(), const _Cmp& __cmp=_Cmp())
|
||||
: _M_cmp(__cmp), _M_acc(__acc) {}
|
||||
: _M_acc(__acc), _M_cmp(__cmp) {}
|
||||
|
||||
template <typename Val>
|
||||
_Region(Val const& __V,
|
||||
|
||||
@@ -10,7 +10,7 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
# Build the _kdtree python module
|
||||
set_source_files_properties (py-kdtree.i PROPERTIES CPLUSPLUS ON)
|
||||
swig_add_module (kdtree python py-kdtree.i)
|
||||
swig_link_libraries (kdtree ${Python3_LIBRARIES})
|
||||
swig_link_libraries (kdtree ${PYTHON_LIBRARIES})
|
||||
|
||||
# Copy the test file into the build dir
|
||||
install (FILES py-kdtree_test.py DESTINATION ${CMAKE_INSTALL_PREFIX}/python)
|
||||
|
||||
Reference in New Issue
Block a user