1-
21/// A k-d tree implementation supporting the following operations:
3- ///
2+ ///
43/// Main functions:
5- ///
6- /// new() -> Create an empty k-d tree
4+ ///
5+ /// new() -> Create an empty k-d tree
76/// build() -> Generate a balance k-d tree from a vector of points
87/// insert() -> Add a point to a k-d tree
98/// delete() -> Remove a point from a k-d tree
109/// contains() -> Search for a point in a k-d tree
1110/// n_nearest_neighbors -> Search the nearest neighbors of a given point from a k-d tree with their respective distances
1211/// len() -> Determine the number of points stored in a kd-tree
1312/// is_empty() -> Determine whether or not there are points in a k-d tree
14- ///
13+ ///
1514/// Helper functions:
16- ///
15+ ///
1716/// distance() -> Calculate the Euclidean distance between two points
1817/// min_node() -> Determine the minimum node from a given k-d tree with respect to a given axis
1918/// min_node_on_axis() -> Determine the minimum node among three nodes on a given axis
20- ///
19+ ///
2120/// Check each function's definition for more details
22- ///
21+ ///
2322/// TODO: Implement a `range_search` function to return a set of points found within a given boundary
24-
2523use num_traits:: { abs, real:: Real , Signed } ;
2624use std:: iter:: Sum ;
2725
@@ -122,7 +120,6 @@ impl<T: PartialOrd + Copy, const K: usize> KDTree<T, K> {
122120 tree
123121 }
124122 }
125-
126123}
127124
128125// Helper functions ............................................................................
@@ -358,21 +355,28 @@ fn n_nearest_neighbors<T, const K: usize>(
358355#[ cfg( test) ]
359356mod test {
360357 /// Tests for the following operations:
361- ///
358+ ///
362359 /// insert(), contains(), delete(), n_nearest_neighbors(), len(), is_empty()
363360 /// This test uses a 2-Dimensional point
364- ///
365- /// TODO: Create a global constant(K for example) to hold the dimension to be tested and adjust each test case to make use of K for points allocation.
366-
361+ ///
362+ /// TODO: Create a global constant(K for example) to hold the dimension to be tested and adjust each test case to make use of K for points allocation.
367363 use super :: KDTree ;
368364
369365 #[ test]
370366 fn insert ( ) {
371- let points = ( 0 ..100 ) . map ( |_| {
372- [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ]
373- } ) . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
367+ let points = ( 0 ..100 )
368+ . map ( |_| {
369+ [
370+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
371+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
372+ ]
373+ } )
374+ . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
374375 let mut kd_tree = KDTree :: build ( points) ;
375- let point = [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ] ;
376+ let point = [
377+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
378+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
379+ ] ;
376380
377381 assert ! ( kd_tree. insert( point) ) ;
378382 // Cannot insert twice
@@ -381,22 +385,35 @@ mod test {
381385
382386 #[ test]
383387 fn contains ( ) {
384- let points = ( 0 ..100 ) . map ( |_| {
385- [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ]
386- } ) . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
388+ let points = ( 0 ..100 )
389+ . map ( |_| {
390+ [
391+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
392+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
393+ ]
394+ } )
395+ . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
387396 let mut kd_tree = KDTree :: build ( points) ;
388- let point = [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ] ;
397+ let point = [
398+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
399+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
400+ ] ;
389401 kd_tree. insert ( point) ;
390402
391403 assert ! ( kd_tree. contains( & point) ) ;
392404 }
393405
394406 #[ test]
395407 fn delete ( ) {
396- let points = ( 0 ..100 ) . map ( |_| {
397- [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ]
398- } ) . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
399- let point = points[ ( rand:: random :: < f64 > ( ) * 100.0 ) . round ( ) as usize ] . clone ( ) ;
408+ let points = ( 0 ..100 )
409+ . map ( |_| {
410+ [
411+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
412+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
413+ ]
414+ } )
415+ . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
416+ let point = points[ ( rand:: random :: < f64 > ( ) * 100.0 ) . round ( ) as usize ] ;
400417 let mut kd_tree = KDTree :: build ( points) ;
401418
402419 assert ! ( kd_tree. delete( & point) ) ;
@@ -409,27 +426,37 @@ mod test {
409426 #[ test]
410427 fn nearest_neighbors ( ) {
411428 // Test with large data set
412- let points_1 = ( 0 ..1000 ) . map ( |_| {
413- [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ]
414- } ) . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
429+ let points_1 = ( 0 ..1000 )
430+ . map ( |_| {
431+ [
432+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
433+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
434+ ]
435+ } )
436+ . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
415437 let kd_tree_1 = KDTree :: build ( points_1) ;
416438 let target = [ 50.0 , 50.0 ] ;
417439 let neighbors_1 = kd_tree_1. nearest_neighbors ( & target, 10 ) ;
418-
440+
419441 // Confirm we have exactly 10 nearest neighbors
420442 assert_eq ! ( neighbors_1. len( ) , 10 ) ;
421443
422- // `14.14` is the approximate distance between [40.0, 40.0] and [50.0, 50.0] &
423- // [50.0, 50.0] and [60.0, 60.0]
424- // so our closest neighbors are expected to be found between the bounding box [40.0, 40.0] - [60.0, 60.0]
444+ // `14.14` is the approximate distance between [40.0, 40.0] and [50.0, 50.0] &
445+ // [50.0, 50.0] and [60.0, 60.0]
446+ // so our closest neighbors are expected to be found between the bounding box [40.0, 40.0] - [60.0, 60.0]
425447 // with a distance from [50.0, 50.0] less than or equal 14.14
426448 for neighbor in neighbors_1 {
427449 assert ! ( neighbor. 0 <= 14.14 ) ;
428450 }
429451
430452 // Test with small data set
431- let points_2 = vec ! [ [ 2.0 , 3.0 ] , [ 5.0 , 4.0 ] , [ 9.0 , 6.0 ] , [ 4.0 , 7.0 ] , [ 8.0 , 1.0 ] ,
432- [ 7.0 , 2.0 ] ,
453+ let points_2 = vec ! [
454+ [ 2.0 , 3.0 ] ,
455+ [ 5.0 , 4.0 ] ,
456+ [ 9.0 , 6.0 ] ,
457+ [ 4.0 , 7.0 ] ,
458+ [ 8.0 , 1.0 ] ,
459+ [ 7.0 , 2.0 ] ,
433460 ] ;
434461 let kd_tree_2 = KDTree :: build ( points_2) ;
435462 let neighbors_2 = kd_tree_2. nearest_neighbors ( & [ 6.0 , 3.0 ] , 3 ) ;
@@ -457,11 +484,16 @@ mod test {
457484
458485 #[ test]
459486 fn len ( ) {
460- let points = ( 0 ..1000 ) . map ( |_| {
461- [ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 , ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ]
462- } ) . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
487+ let points = ( 0 ..1000 )
488+ . map ( |_| {
489+ [
490+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
491+ ( rand:: random :: < f64 > ( ) * 1000.0 ) . round ( ) / 10.0 ,
492+ ]
493+ } )
494+ . collect :: < Vec < [ f64 ; 2 ] > > ( ) ;
463495 let kd_tree = KDTree :: build ( points) ;
464-
496+
465497 assert_eq ! ( kd_tree. len( ) , 1000 ) ;
466498 }
467499}
0 commit comments