#include #include #include #include #include #include #include #include #include using namespace std; using namespace nanoflann; template struct Point { Point(T x, T y, T z) : x(x), y(y), z(z) {} T x,y,z; }; template ostream& operator <<(ostream& os, const Point& p) { os << p.x << " " << p.y << " " << p.z ; return os; } // This is an exampleof a custom data set class template struct PointCloud { std::vector > pts; // Must return the number of data points inline size_t kdtree_get_point_count() const { return pts.size(); } // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class: inline T kdtree_distance(const T *p1, const size_t idx_p2,size_t /* size */) const { const T d0=p1[0]-pts[idx_p2].x; const T d1=p1[1]-pts[idx_p2].y; const T d2=p1[2]-pts[idx_p2].z; return d0*d0+d1*d1+d2*d2; } // Returns the dim'th component of the idx'th point in the class: // Since this is inlined and the "dim" argument is typically an immediate value, the // "if/else's" are actually solved at compile time. inline T kdtree_get_pt(const size_t idx, int dim) const { if (dim==0) return pts[idx].x; else if (dim==1) return pts[idx].y; else return pts[idx].z; } // Optional bounding-box computation: return false to default to a standard bbox computation loop. // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again. // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds) template bool kdtree_get_bbox(BBOX & /* bb */) const { return false; } }; template void generateRandomPointCloud(PointCloud &point, istream& is, int n) { T x, y, z; for(int i=0; i < n; i++){ CGAL::read(is,x); CGAL::read(is,y); CGAL::read(is,z); point.pts.push_back(Point(x,y,z)); } std::cout << "Read "<< point.pts.size() << " points\n"; } template void kdtree_demo(int argc, char** argv) { PointCloud cloud; int n; // Generate points: std::ifstream input(argv[1], std::ios::in | std::ios::binary); CGAL::IO::set_binary_mode(input); // input >> n >> n; // dimension and # of points CGAL::read(input,n); CGAL::read(input,n); generateRandomPointCloud(cloud, input, n); std::vector > queries; std::ifstream queries_stream(argv[2], std::ios::in | std::ios::binary); CGAL::IO::set_binary_mode(queries_stream); CGAL::read(queries_stream,n); CGAL::read(queries_stream,n); // queries_stream >> n >> n; double x,y,z; for(int i=0; i < n; i++){ CGAL::read(queries_stream,x); CGAL::read(queries_stream,y); CGAL::read(queries_stream,z); queries.push_back(Point(x,y,z)); } int runs = (argc>3) ? boost::lexical_cast(argv[3]) : 1; std::cerr << "runs = " << runs <4) ? boost::lexical_cast(argv[4]) : 10; std::cerr << "bucketsize = " << bucketsize < > , PointCloud, 3 /* dim */ > my_kd_tree_t; my_kd_tree_t index(3 /*dim*/, cloud, KDTreeSingleIndexAdaptorParams(bucketsize /* max leaf */) ); index.buildIndex(); timer.stop(); std::cout << "construction time: " << timer.time() << " sec" << std::endl; std::cerr << "Tree statistics:" << std::endl; std::cerr << "Number of items stored: " << index.items << std::endl; std::cerr << "Number of nodes: " << index.internals << std::endl; std::cerr << " Tree depth: " << index.depth() << std::endl; // do a knn search const size_t num_results = 10; size_t ret_index[num_results]; num_t out_dist_sqr[num_results]; int size = queries.size(); std::cout << "start search" << std::endl; bool dump = true; double sum = 0; for(int i=0;i resultSet(num_results); for(int i = 0 ; i < size; i++){ query_pt[0] = queries[i].x; query_pt[1] = queries[i].y; query_pt[2] = queries[i].z; resultSet.init(ret_index, out_dist_sqr ); timer.reset(); timer.start(); index.findNeighbors(resultSet, &query_pt[0], nanoflann::SearchParams(10,0)); timer.stop(); for (size_t k=0; k1){ std::cerr << "average: " << sum/runs << " sec\n"; } std::cerr << "done\n"; } int main(int argc, char** argv) { kdtree_demo(argc, argv); return 0; }