@@ -353,6 +353,217 @@ TEST_F(KDTreeSingle, TestCopy2)
353
353
EXPECT_EQ (precision, precision5);
354
354
}
355
355
356
+ TEST_F (KDTreeSingle, TestNoNeighbours)
357
+ {
358
+ flann::Index<L2_Simple<float > > index (data, flann::KDTreeSingleIndexParams (12 , false ));
359
+ start_timer (" Building kd-tree index..." );
360
+ index.buildIndex ();
361
+ printf (" done (%g seconds)\n " , stop_timer ());
362
+
363
+ start_timer (" Searching KNN..." );
364
+ index.knnSearch (query, indices, dists, knn, flann::SearchParams (-1 ) );
365
+ printf (" done (%g seconds)\n " , stop_timer ());
366
+
367
+
368
+ float min_dist = dists[0 ][0 ];
369
+ for (size_t i=0 ;i<query.rows ;++i) {
370
+ min_dist = std::min (min_dist, dists[i][0 ]);
371
+ }
372
+
373
+ printf (" Minimum distance: %g\n " , min_dist);
374
+
375
+ start_timer (" Searching radius smaller than minimum distance..." );
376
+ int count = index.radiusSearch (query, indices, dists, min_dist/2 , flann::SearchParams (-1 ) );
377
+ printf (" done (%g seconds)\n " , stop_timer ());
378
+
379
+ EXPECT_EQ (0 ,count);
380
+ for (size_t i=0 ;i<dists.rows ;++i) {
381
+ EXPECT_EQ (dists[i][0 ],std::numeric_limits<float >::infinity ());
382
+ }
383
+
384
+ std::vector<std::vector<size_t > > indices2;
385
+ std::vector<std::vector<float > > dists2;
386
+ start_timer (" Searching radius smaller than minimum distance..." );
387
+ int count2 = index.radiusSearch (query, indices2, dists2, min_dist/2 , flann::SearchParams (-1 ) );
388
+ printf (" done (%g seconds)\n " , stop_timer ());
389
+
390
+ EXPECT_EQ (0 ,count2);
391
+ for (size_t i=0 ;i<indices2.size ();++i) {
392
+ EXPECT_EQ (indices2[i].size (),0 );
393
+ }
394
+ }
395
+
396
+
397
+ // Test cases for 3D point clouds, borrowed from PCL test_kdtree
398
+ struct MyPoint
399
+ {
400
+ MyPoint (float x, float y, float z) {this ->x =x; this ->y =y; this ->z =z;}
401
+
402
+ float x,y,z;
403
+ };
404
+
405
+
406
+ class KDTreeSinglePointCloud : public FLANNTestFixture
407
+ {
408
+ public:
409
+ void SetUp ()
410
+ {
411
+ float resolution = 0 .1f ;
412
+ for (float z = -0 .5f ; z <= 0 .5f ; z += resolution)
413
+ for (float y = -0 .5f ; y <= 0 .5f ; y += resolution)
414
+ for (float x = -0 .5f ; x <= 0 .5f ; x += resolution)
415
+ cloud_.push_back (MyPoint (x, y, z));
416
+
417
+ cloud_mat_ = flann::Matrix<float >(&cloud_[0 ].x , cloud_.size (), 3 );
418
+
419
+
420
+ srand (static_cast <unsigned int > (time (NULL )));
421
+ // Randomly create a new point cloud
422
+ for (size_t i = 0 ; i < 640 *480 ; ++i)
423
+ cloud_big_.push_back (MyPoint (static_cast <float > (1024 * rand () / (RAND_MAX + 1.0 )),
424
+ static_cast <float > (1024 * rand () / (RAND_MAX + 1.0 )),
425
+ static_cast <float > (1024 * rand () / (RAND_MAX + 1.0 ))));
426
+
427
+
428
+ cloud_big_mat_ = flann::Matrix<float >(&cloud_big_[0 ].x , cloud_big_.size (), 3 );
429
+ }
430
+
431
+ std::vector<MyPoint> cloud_;
432
+ flann::Matrix<float > cloud_mat_;
433
+
434
+ std::vector<MyPoint> cloud_big_;
435
+ flann::Matrix<float > cloud_big_mat_;
436
+ };
437
+
438
+ TEST_F (KDTreeSinglePointCloud, TestRadiusSearch)
439
+ {
440
+ std::vector<std::vector<int > > k_indices;
441
+ std::vector<std::vector<float > > k_distances;
442
+
443
+ {
444
+ flann::Index<L2_Simple<float > > index (cloud_mat_, flann::KDTreeSingleIndexParams (12 , false ));
445
+ index.buildIndex ();
446
+
447
+ L2_Simple<float > euclideanDistance;
448
+ MyPoint test_point (0 .0f , 0 .0f , 0 .0f );
449
+ flann::Matrix<float > test_mat (&test_point.x , 1 , 3 );
450
+ double max_dist = 0.15 *0.15 ;
451
+ std::set<int > brute_force_result;
452
+ for (unsigned int i=0 ; i<cloud_mat_.rows ; ++i)
453
+ if (euclideanDistance (cloud_mat_[i], test_mat[0 ], 3 ) < max_dist)
454
+ brute_force_result.insert (i);
455
+ index.radiusSearch (test_mat, k_indices, k_distances, max_dist, flann::SearchParams (-1 ));
456
+
457
+ for (size_t i = 0 ; i < k_indices[0 ].size (); ++i)
458
+ {
459
+ std::set<int >::iterator brute_force_result_it = brute_force_result.find (k_indices[0 ][i]);
460
+ bool ok = brute_force_result_it != brute_force_result.end ();
461
+ // if (!ok) cerr << k_indices[i] << " is not correct...\n";
462
+ // else cerr << k_indices[i] << " is correct...\n";
463
+ EXPECT_EQ (ok, true );
464
+ if (ok)
465
+ brute_force_result.erase (brute_force_result_it);
466
+ }
467
+ // for (set<int>::const_iterator it=brute_force_result.begin(); it!=brute_force_result.end(); ++it)
468
+ // cerr << "FLANN missed "<<*it<<"\n";
469
+
470
+ bool error = brute_force_result.size () > 0 ;
471
+ // if (error) cerr << "Missed too many neighbors!\n";
472
+ EXPECT_EQ (error, false );
473
+ }
474
+
475
+ {
476
+ flann::Index<L2_Simple<float > > index (flann::KDTreeSingleIndexParams (15 ));
477
+ index.buildIndex (cloud_big_mat_);
478
+
479
+ start_timer (" radiusSearch..." );
480
+ flann::SearchParams params (-1 );
481
+ index.radiusSearch (cloud_big_mat_, k_indices, k_distances, 0.1 *0.1 , params);
482
+ printf (" done (%g seconds)\n " , stop_timer ());
483
+ }
484
+
485
+ {
486
+ flann::Index<L2_Simple<float > > index (flann::KDTreeSingleIndexParams (15 ));
487
+ index.buildIndex (cloud_big_mat_);
488
+
489
+ start_timer (" radiusSearch (max neighbors in radius)..." );
490
+ flann::SearchParams params (-1 );
491
+ params.max_neighbors = 10 ;
492
+ index.radiusSearch (cloud_big_mat_, k_indices, k_distances, 0.1 *0.1 , params);
493
+ printf (" done (%g seconds)\n " , stop_timer ());
494
+ }
495
+
496
+ {
497
+ flann::Index<L2_Simple<float > > index (flann::KDTreeSingleIndexParams (15 ));
498
+ index.buildIndex (cloud_big_mat_);
499
+
500
+ start_timer (" radiusSearch (unsorted results)..." );
501
+ flann::SearchParams params (-1 );
502
+ params.sorted = false ;
503
+ index.radiusSearch (cloud_big_mat_, k_indices, k_distances, 0.1 *0.1 , params);
504
+ printf (" done (%g seconds)\n " , stop_timer ());
505
+ }
506
+ }
507
+
508
+
509
+ TEST_F (KDTreeSinglePointCloud, TestKNearestSearch)
510
+ {
511
+ unsigned int no_of_neighbors = 20 ;
512
+
513
+ {
514
+ flann::Index<L2_Simple<float > > index (cloud_mat_, flann::KDTreeSingleIndexParams (12 , false ));
515
+ index.buildIndex ();
516
+
517
+ L2_Simple<float > euclideanDistance;
518
+ MyPoint test_point (0 .01f , 0 .01f , 0 .01f );
519
+ flann::Matrix<float > test_mat (&test_point.x , 1 , 3 );
520
+
521
+ std:: multimap<float , int > sorted_brute_force_result;
522
+ for (size_t i = 0 ; i < cloud_.size (); ++i)
523
+ {
524
+ float distance = euclideanDistance (cloud_mat_[i], test_mat[0 ],3 );
525
+ sorted_brute_force_result.insert (std::make_pair (distance, static_cast <int > (i)));
526
+ }
527
+ float max_dist = 0 .0f ;
528
+ unsigned int counter = 0 ;
529
+ for (std::multimap<float , int >::iterator it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end () && counter < no_of_neighbors; ++it)
530
+ {
531
+ max_dist = std::max (max_dist, it->first );
532
+ ++counter;
533
+ }
534
+
535
+ std::vector< std::vector<int > > k_indices (1 );
536
+ k_indices[0 ].resize (no_of_neighbors);
537
+ std::vector<std::vector<float > > k_distances (1 );
538
+ k_distances[0 ].resize (no_of_neighbors);
539
+ index.knnSearch (test_mat, k_indices, k_distances, no_of_neighbors, flann::SearchParams (-1 ));
540
+ // if (k_indices.size() != no_of_neighbors) cerr << "Found "<<k_indices.size()<<" instead of "<<no_of_neighbors<<" neighbors.\n";
541
+ EXPECT_EQ (k_indices[0 ].size (), no_of_neighbors);
542
+
543
+ // Check if all found neighbors have distance smaller than max_dist
544
+ for (size_t i = 0 ; i < k_indices[0 ].size (); ++i)
545
+ {
546
+ float * point = cloud_mat_[k_indices[0 ][i]];
547
+ bool ok = euclideanDistance (test_mat[0 ], point, 3 ) <= max_dist;
548
+ EXPECT_EQ (ok, true );
549
+ }
550
+ }
551
+
552
+ {
553
+ flann::Index<L2_Simple<float > > index (flann::KDTreeSingleIndexParams (15 ));
554
+ index.buildIndex (cloud_big_mat_);
555
+
556
+ start_timer (" K nearest neighbour search..." );
557
+ flann::SearchParams params (-1 );
558
+ params.sorted = false ;
559
+ std::vector<std::vector<int > > k_indices;
560
+ std::vector<std::vector<float > > k_distances;
561
+ index.knnSearch (cloud_big_mat_, k_indices, k_distances, no_of_neighbors, params);
562
+ printf (" done (%g seconds)\n " , stop_timer ());
563
+ }
564
+
565
+ }
566
+
356
567
int main (int argc, char ** argv)
357
568
{
358
569
testing::InitGoogleTest (&argc, argv);
0 commit comments