diff --git a/Cargo.toml b/Cargo.toml index 3431415..c740b9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" authors = ["Thomas Forgione "] [dependencies] -num = "*" [[bin]] name = "kdtree-example" diff --git a/src/example.rs b/src/example.rs index 5f22feb..1c89d1f 100644 --- a/src/example.rs +++ b/src/example.rs @@ -1,45 +1,26 @@ -extern crate num; extern crate kdtree; use std::fmt; -use std::ops::Index; -use kdtree::Zero; use kdtree::KdTree; -#[derive(Copy, Clone)] +#[derive(Clone)] struct Vector2 { data: [f64; 2], } impl Vector2 { pub fn new(x: f64, y: f64) -> Vector2 { - Vector2 { - data: [x, y], - } - } -} - -impl Index for Vector2 { - type Output = f64; - fn index(&self, index: usize) -> &f64 { - &self.data[index] - } -} - -impl Zero for Vector2 { - fn zero() -> Vector2 { - Vector2::new(0.0, 0.0) + Vector2 { data: [x, y] } } } impl fmt::Display for Vector2 { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "({}, {})", self[0], self[1]) + write!(formatter, "({}, {})", self.data[0], self.data[1]) } } - fn main() { let mut points = vec![ Vector2::new(2.0, 3.0), @@ -50,8 +31,12 @@ fn main() { Vector2::new(7.0, 2.0), ]; - let kdtree = KdTree::new(&mut points, 2, 1); + let kdtree = KdTree::new( + &mut points, + 2, + |coord, ref a, ref b| a.data[coord].partial_cmp(&b.data[coord]).unwrap(), + 1, + ); println!("{}", kdtree); - } diff --git a/src/lib.rs b/src/lib.rs index bacd90d..395fdb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,76 +1,96 @@ -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() - } -} +use std::cmp::Ordering; /// A k-dimension kd tree pub enum KdTree { - Node { location: T, left: Box>, right: Box> }, + Node { + location: T, + left: Box>, + right: Box>, + }, Leaf(Vec), } -impl KdTree where T: Copy + Clone + Index + Zero, U: PartialOrd { - pub fn new(points: &mut [T], dimension: usize, leaf_size: usize) -> KdTree { - KdTree::new_with_depth(points, dimension, leaf_size, 0) +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(points: &mut [T], dimension: usize, leaf_size: usize, depth: usize) -> KdTree { - + 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(|p1, p2| p1[axis].partial_cmp(&p2[axis]).unwrap()); + 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![Zero::zero(); len]; - contained.copy_from_slice(points); + 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]; + let median = points[delimiter].clone(); // Build the left and right branches - let zero = Zero::zero(); - let mut left = vec![zero; delimiter]; - left.copy_from_slice(&points[0..delimiter]); + let mut left = vec![]; + for i in &points[0..delimiter] { + left.push(i.clone()); + } - let right = &mut points[delimiter + 1 .. len]; + let right = &mut points[delimiter + 1..len]; // Recursive call KdTree::Node { location: median, - left: Box::new(KdTree::new_with_depth(&mut left, dimension, leaf_size, depth + 1)), - right: Box::new(KdTree::new_with_depth(right, dimension, leaf_size, depth + 1)), + 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 { +impl KdTree { fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result { match self { - &KdTree::Node { location, ref left, ref right } => { + &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)?; @@ -78,16 +98,15 @@ impl> KdTree { write!(formatter, "{}, ", element)?; } writeln!(formatter, "]")?; - }, + } } Ok(()) } } -impl> fmt::Display for KdTree { +impl fmt::Display for KdTree { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.print(formatter, "") } - }