extern crate num; use std::fmt; use std::ops::Index; use std::cmp::PartialOrd; pub trait Zero { fn zero() -> Self; } impl Zero for T { fn zero() -> Self { num::Zero::zero() } } /// A k-dimension kd tree pub struct KdTree { location: T, left: Option>>, right: Option>>, } impl KdTree where T: Copy + Clone + Index + Zero, U: PartialOrd { pub fn new(points: &mut [T], dimension: usize) -> KdTree { KdTree::new_with_depth(points, dimension, 0) } fn new_with_depth(points: &mut [T], dimension: usize, depth: usize) -> KdTree { // 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> KdTree { 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> fmt::Display for KdTree { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.print(formatter, "") } }