knnshow.cpp
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2010--2011, Stephane Magnenat, ASL, ETHZ, Switzerland
4 You can contact the author at <stephane at magnenat dot net>
5 
6 All rights reserved.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10  * Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15  * Neither the name of the <organization> nor the
16  names of its contributors may be used to endorse or promote products
17  derived from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 */
31 
32 #include "nabo/nabo.h"
33 #include <iostream>
34 #include <fstream>
35 #include <stdexcept>
36 
37 using namespace std;
38 using namespace Nabo;
39 
40 template<typename T>
41 typename NearestNeighbourSearch<T>::Matrix load(const char *fileName)
42 {
43  typedef typename NearestNeighbourSearch<T>::Matrix Matrix;
44 
45  ifstream ifs(fileName);
46  if (!ifs.good())
47  throw runtime_error(string("Cannot open file ") + fileName);
48 
49  vector<T> data;
50  int dim(0);
51  bool firstLine(true);
52 
53  while (!ifs.eof())
54  {
55  char line[1024];
56  ifs.getline(line, sizeof(line));
57  line[sizeof(line)-1] = 0;
58 
59  char *token = strtok(line, " \t,;");
60  while (token)
61  {
62  if (firstLine)
63  ++dim;
64  data.push_back(atof(token));
65  //cout << atof(token) << " ";
66  token = strtok(NULL, " \t,;"); // FIXME: non reentrant, use strtok_r
67  }
68  firstLine = false;
69  }
70 
71  return Matrix::Map(&data[0], dim, data.size() / dim);
72 }
73 
74 template<typename T>
75 void dumpCoordinateForSVG(const typename NearestNeighbourSearch<T>::Vector coord, const float zoom = 1, const float ptSize = 1, const char* style = "stroke=\"black\" fill=\"red\"")
76 {
77  if (coord.size() == 2)
78  cout
79  << "<circle cx=\"" << zoom*coord(0)
80  << "\" cy=\"" << zoom*coord(1)
81  << "\" r=\"" << ptSize
82  << "\" stroke-width=\"" << 0.2 * ptSize
83  << "\" " << style << "/>" << endl;
84  else
85  assert(false);
86 }
87 
88 int main(int argc, char* argv[])
89 {
95  typedef Nabo::KDTree<float> KDTF;
96 
97  if (argc != 2)
98  {
99  cerr << "Usage " << argv[0] << " DATA" << endl;
100  return 1;
101  }
102 
103  Matrix d(load<float>(argv[1]));
104  BFSF bfs(d);
105  KDTF kdt(d);
106  const Index K(10);
107 
108  // uncomment to compare KDTree with brute force search
109  if (K >= d.size())
110  return 2;
111  const int itCount(100);
112  for (int i = 0; i < itCount; ++i)
113  {
114  //Vector q(bfs.minBound.size());
115  //for (int i = 0; i < q.size(); ++i)
116  // q(i) = bfs.minBound(i) + float(rand()) * (bfs.maxBound(i) - bfs.minBound(i)) / float(RAND_MAX);
117  Vector q(d.col(rand() % d.cols()));
118  q.cwise() += 0.01;
119  //cerr << "bfs:\n";
120  Indexes indexes_bf(bfs.knn(q, K, false));
121  //cerr << "kdt:\n";
122  Indexes indexes_kdtree(kdt.knn(q, K, false));
123  //cout << indexes_bf.size() << " " << indexes_kdtree.size() << " " << K << endl;
124  if (ndexes_bf.size() != indexes_kdtree.size())
125  return 2;
126  assert(indexes_bf.size() == indexes_kdtree.size());
127  assert(indexes_bf.size() == K);
128  //cerr << "\nquery:\n" << q << "\n\n";
129  for (size_t j = 0; j < K; ++j)
130  {
131  Vector pbf(d.col(indexes_bf[j]));
132  Vector pkdtree(d.col(indexes_kdtree[j]));
133  //cerr << "index " << j << ": " << indexes_bf[j] << ", " << indexes_kdtree[j] << "\n";
134  //cerr << "point " << j << ": " << "\nbf:\n" << pbf << "\nkdtree:\n" << pkdtree << "\n\n";
135  assert(indexes_bf[j] == indexes_kdtree[j]);
136  assert(dist2(pbf, pkdtree) < numeric_limits<float>::epsilon());
137  }
138  }
139  cerr << "stats kdtree: "
140  << kdt.getStatistics().totalVisitCount << " on "
141  << itCount * d.cols() << " ("
142  << double(100 * kdt.getStatistics().totalVisitCount) / double(itCount * d.cols()) << " %"
143  << ")" << endl;
144 
145  /*
146  // uncomment to randomly get a point and find its minimum
147  cout << "<?xml version=\"1.0\" standalone=\"no\"?>" << endl;
148  cout << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" << endl;
149  cout << "<svg width=\"100%\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">" << endl;
150  srand(time(0));
151  for (int i = 0; i < d.cols(); ++i)
152  dumpCoordinateForSVG<float>(d.col(i), 100, 1);
153  Vector q(bfs.minBound.size());
154  for (int i = 0; i < q.size(); ++i)
155  q(i) = bfs.minBound(i) + float(rand()) * (bfs.maxBound(i) - bfs.minBound(i)) / float(RAND_MAX);
156  Indexes indexes_bf(bfs.knn(q, K, false));
157  for (size_t i = 0; i < K; ++i)
158  dumpCoordinateForSVG<float>(d.col(indexes_bf[i]), 100, 1, "stroke=\"black\" fill=\"green\"");
159  dumpCoordinateForSVG<float>(q, 100, 1, "stroke=\"black\" fill=\"blue\"");
160  cout << "</svg>" << endl;
161  */
162 
163  //cout << "Average KDTree visit count: " << double(totKDTreeVisitCount) * 100. / double(itCount * d.cols()) << " %" << endl;
164 
165 
166  return 0;
167 }
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > Matrix
a column-major Eigen matrix in which each column is a point; this matrix has dim rows ...
Definition: nabo.h:263
NearestNeighbourSearch< T >::Matrix load(const char *fileName)
Definition: knnshow.cpp:41
int main(int argc, char *argv[])
Definition: knnshow.cpp:88
Nearest neighbour search interface, templatized on scalar type.
Definition: nabo.h:258
Definition: any.hpp:450
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vector
an Eigen vector of type T, to hold the coordinates of a point
Definition: nabo.h:261
int Index
an index to a Vector or a Matrix, for refering to data points
Definition: nabo.h:267
Brute-force nearest neighbour.
Definition: nabo_private.h:72
void dumpCoordinateForSVG(const typename NearestNeighbourSearch< T >::Vector coord, const float zoom=1, const float ptSize=1, const char *style="stroke=\lack\fill=\ed\)
Definition: knnshow.cpp:75
Namespace for Nabo.
public interface
virtual unsigned long knn(const Matrix &query, IndexMatrix &indices, Matrix &dists2, const Index k, const T epsilon, const unsigned optionFlags, const T maxRadius) const
T dist2(const A &v0, const B &v1)
Euclidean distance.
Definition: nabo_private.h:65
NNSNabo::Index Index
Definition: python/nabo.cpp:11
Nabo::BruteForceSearch< float > BFSF
Definition: knnbench.cpp:60
q
Definition: test.py:8


libnabo
Author(s): Stéphane Magnenat
autogenerated on Mon Feb 28 2022 22:41:38