use std::fmt; use std::cmp::Ordering; /// A k-dimension kd tree pub enum KdTree { Node { location: T, left: Box>, right: Box>, }, Leaf(Vec), } impl KdTree where { pub fn new Ordering>( points: &mut [T], dimension: usize, comparator: F, leaf_size: usize, ) -> KdTree { KdTree::new_with_depth(points, dimension, &comparator, leaf_size, 0) } fn new_with_depth Ordering>( points: &mut [T], dimension: usize, comparator: &F, leaf_size: usize, depth: usize, ) -> KdTree { // Select axis to work on let axis = depth % dimension; // Sort the points by axis points.sort_by(|a, b| comparator(axis, a, b)); // Find the median let len = points.len(); // If there are not enough elements for a leaf, make a leaf if len <= leaf_size { let mut contained = vec![]; for p in points { contained.push(p.clone()); } return KdTree::Leaf(contained); } // Else split what's remaining let delimiter = points.len() / 2; let median = points[delimiter].clone(); // Build the left and right branches let mut left = vec![]; for i in &points[0..delimiter] { left.push(i.clone()); } let right = &mut points[delimiter + 1..len]; // Recursive call KdTree::Node { location: median, left: Box::new(KdTree::new_with_depth( &mut left, dimension, comparator, leaf_size, depth + 1, )), right: Box::new(KdTree::new_with_depth( right, dimension, comparator, leaf_size, depth + 1, )), } } } impl KdTree { fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result { match self { &KdTree::Node { ref location, ref left, ref right, } => { writeln!(formatter, "{}{}", indent, location)?; left.print(formatter, &format!("{} ", indent))?; right.print(formatter, &format!("{} ", indent))?; } &KdTree::Leaf(ref elements) => { write!(formatter, "{}[", indent)?; for element in elements { write!(formatter, "{}, ", element)?; } writeln!(formatter, "]")?; } } Ok(()) } } impl fmt::Display for KdTree { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.print(formatter, "") } }