kdtree 0.8.1

K-dimensional tree in Rust for fast geospatial indexing and nearest neighbors lookup
Documentation
mod __util__;

use __util__::{POINT_A, POINT_B, basic_tree};
use kdtree::distance::squared_euclidean;
use std::sync::atomic::{AtomicUsize, Ordering};

fn countered_distance<'a>(counter: &'a AtomicUsize) -> impl Fn(&[f64], &[f64]) -> f64 + 'a {
    move |a, b| {
        counter.fetch_add(1, Ordering::SeqCst);
        squared_euclidean(a, b)
    }
}

fn reset(counter: &AtomicUsize) -> usize {
    counter.swap(0, Ordering::SeqCst)
}

#[test]
fn nearest_queries_limit_distance_evaluations() {
    let tree = basic_tree();
    let counter = AtomicUsize::new(0);
    let distance = countered_distance(&counter);

    tree.nearest(&POINT_A.0, 0, &distance).unwrap();
    assert_eq!(reset(&counter), 0);

    tree.nearest(&POINT_A.0, 1, &distance).unwrap();
    assert_eq!(reset(&counter), 2);

    tree.nearest(&POINT_A.0, 2, &distance).unwrap();
    assert_eq!(reset(&counter), 4);

    tree.nearest(&POINT_A.0, 3, &distance).unwrap();
    assert_eq!(reset(&counter), 6);

    tree.nearest(&POINT_A.0, 4, &distance).unwrap();
    assert_eq!(reset(&counter), 6);

    tree.nearest(&POINT_A.0, 5, &distance).unwrap();
    assert_eq!(reset(&counter), 6);

    tree.nearest(&POINT_B.0, 4, &distance).unwrap();
    assert_eq!(reset(&counter), 6);
}

#[test]
fn nearest_within_radius_limits_distance_evaluations() {
    let tree = basic_tree();
    let counter = AtomicUsize::new(0);
    let distance = countered_distance(&counter);

    tree.nearest_within_radius(&POINT_A.0, 4, None, &distance).unwrap();
    assert_eq!(reset(&counter), 6);

    tree.nearest_within_radius(&POINT_A.0, 4, Some(0.0), &distance).unwrap();
    assert_eq!(reset(&counter), 2);

    tree.nearest_within_radius(&POINT_B.0, 4, Some(1.0), &distance).unwrap();
    assert_eq!(reset(&counter), 3);
}

#[test]
fn within_queries_limit_distance_evaluations() {
    let tree = basic_tree();
    let counter = AtomicUsize::new(0);
    let distance = countered_distance(&counter);

    tree.within(&POINT_A.0, 0.0, &distance).unwrap();
    assert_eq!(reset(&counter), 2);

    tree.within(&POINT_B.0, 1.0, &distance).unwrap();
    assert_eq!(reset(&counter), 3);

    tree.within(&POINT_B.0, 2.0, &distance).unwrap();
    assert_eq!(reset(&counter), 6);
}

#[test]
fn iter_nearest_limits_distance_evaluations() {
    let counter = AtomicUsize::new(0);
    let distance = countered_distance(&counter);
    let tree = basic_tree();
    let mut iter = tree.iter_nearest(&POINT_A.0, &distance).unwrap();

    assert_eq!(reset(&counter), 0);
    iter.next().unwrap();
    assert_eq!(reset(&counter), 2);
    iter.next().unwrap();
    assert_eq!(reset(&counter), 2);
    iter.next().unwrap();
    assert_eq!(reset(&counter), 2);
    iter.next().unwrap();
    assert_eq!(reset(&counter), 0);
}