86 lines
2.3 KiB
Rust
86 lines
2.3 KiB
Rust
extern crate num;
|
|
|
|
use std::fmt;
|
|
use std::ops::Index;
|
|
use std::cmp::PartialOrd;
|
|
|
|
pub trait Zero {
|
|
fn zero() -> Self;
|
|
}
|
|
|
|
impl<T: num::Zero> Zero for T {
|
|
fn zero() -> Self {
|
|
num::Zero::zero()
|
|
}
|
|
}
|
|
|
|
/// A k-dimension kd tree
|
|
pub struct KdTree<T> {
|
|
location: T,
|
|
left: Option<Box<KdTree<T>>>,
|
|
right: Option<Box<KdTree<T>>>,
|
|
}
|
|
|
|
impl<T, U> KdTree<T> where T: Copy + Clone + Index<usize, Output = U> + Zero, U: PartialOrd {
|
|
pub fn new(points: &mut [T], dimension: usize) -> KdTree<T> {
|
|
KdTree::new_with_depth(points, dimension, 0)
|
|
}
|
|
|
|
fn new_with_depth(points: &mut [T], dimension: usize, depth: usize) -> KdTree<T> {
|
|
|
|
// Select axis to work on
|
|
let axis = depth % dimension;
|
|
|
|
// Sort the points by axis
|
|
points.sort_by(|p1, p2| p1[axis].partial_cmp(&p2[axis]).unwrap());
|
|
|
|
// Find the median
|
|
let len = points.len();
|
|
let delimiter = points.len() / 2;
|
|
let median = points[delimiter];
|
|
|
|
let zero = Zero::zero();
|
|
let mut left = vec![zero; delimiter];
|
|
left.copy_from_slice(&points[0..delimiter]);
|
|
|
|
let right = &mut points[delimiter + 1 .. len];
|
|
|
|
if left.len() == 0 || right.len() == 0 {
|
|
KdTree {
|
|
location: median,
|
|
left: None,
|
|
right: None,
|
|
}
|
|
} else {
|
|
KdTree {
|
|
location: median,
|
|
left: Some(Box::new(KdTree::new_with_depth(&mut left, dimension, depth + 1))),
|
|
right: Some(Box::new(KdTree::new_with_depth(right, dimension, depth + 1))),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Zero + Copy + Clone + fmt::Display + Index<usize>> KdTree<T> {
|
|
fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result {
|
|
writeln!(formatter, "{}{}", indent, self.location)?;
|
|
|
|
if let Some(left) = self.left.as_ref() {
|
|
left.print(formatter, &format!("{} ", indent))?;
|
|
}
|
|
|
|
if let Some(right) = self.right.as_ref() {
|
|
right.print(formatter, &format!("{} ", indent))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<T: Zero + Copy + Clone + fmt::Display + Index<usize>> fmt::Display for KdTree<T> {
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
self.print(formatter, "")
|
|
}
|
|
|
|
}
|