kdtree 0.8.0

K-dimensional tree in Rust for fast geospatial indexing and nearest neighbors lookup
Documentation
use num_traits::Float;

pub fn distance_to_space<F, T>(p1: &[T], min_bounds: &[T], max_bounds: &[T], distance: &F) -> T
where
    F: Fn(&[T], &[T]) -> T,
    T: Float,
{
    let mut p2 = vec![T::nan(); p1.len()];
    for i in 0..p1.len() {
        if p1[i] > max_bounds[i] {
            p2[i] = max_bounds[i];
        } else if p1[i] < min_bounds[i] {
            p2[i] = min_bounds[i];
        } else {
            p2[i] = p1[i];
        }
    }
    distance(p1, &p2[..])
}

pub fn within_bounding_box<T>(p: &[T], min_bounds: &[T], max_bounds: &[T]) -> bool
where
    T: Float,
{
    for ((l, h), v) in min_bounds.iter().zip(max_bounds.iter()).zip(p) {
        if v < l || v > h {
            return false;
        }
    }
    true
}

#[cfg(test)]
mod tests {
    use super::distance_to_space;
    use super::within_bounding_box;
    use crate::distance::squared_euclidean;

    #[test]
    fn test_normal_distance_to_space() {
        let dis = distance_to_space(&[0.0, 0.0], &[1.0, 1.0], &[2.0, 2.0], &squared_euclidean);
        assert_eq!(dis, 2.0);
    }

    #[test]
    fn test_distance_outside_inf() {
        let dis = distance_to_space(
            &[0.0, 0.0],
            &[1.0, 1.0],
            &[f64::INFINITY, f64::INFINITY],
            &squared_euclidean,
        );
        assert_eq!(dis, 2.0);
    }

    #[test]
    fn test_distance_inside_inf() {
        let dis = distance_to_space(
            &[2.0, 2.0],
            &[f64::NEG_INFINITY, f64::NEG_INFINITY],
            &[f64::INFINITY, f64::INFINITY],
            &squared_euclidean,
        );
        assert_eq!(dis, 0.0);
    }

    #[test]
    fn test_distance_inside_normal() {
        let dis = distance_to_space(&[2.0, 2.0], &[0.0, 0.0], &[3.0, 3.0], &squared_euclidean);
        assert_eq!(dis, 0.0);
    }

    #[test]
    fn distance_to_half_space() {
        let dis = distance_to_space(
            &[-2.0, 0.0],
            &[0.0, f64::NEG_INFINITY],
            &[f64::INFINITY, f64::INFINITY],
            &squared_euclidean,
        );
        assert_eq!(dis, 4.0);
    }

    #[test]
    fn test_within_bounding_box() {
        assert!(within_bounding_box(&[1.0, 1.0], &[0.0, 0.0], &[2.0, 2.0]));
        assert!(within_bounding_box(&[1.0, 1.0], &[1.0, 1.0], &[2.0, 2.0]));
        assert!(within_bounding_box(&[1.0, 1.0], &[0.0, 0.0], &[1.0, 1.0]));
        assert!(!within_bounding_box(&[2.0, 2.0], &[0.0, 0.0], &[1.0, 1.0]));
        assert!(!within_bounding_box(&[0.0, 0.0], &[1.0, 1.0], &[2.0, 2.0]));
    }
}