From 4c773c290dc2636f3974bc1bf7141c839634e78a Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Mon, 5 Mar 2018 11:17:50 +0100 Subject: [PATCH] More generic --- Cargo.toml | 1 - src/example.rs | 44 +++++++++++++-- src/lib.rs | 141 ++++++++++++++++++++++++------------------------- 3 files changed, 110 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0faacfa..3431415 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" authors = ["Thomas Forgione "] [dependencies] -model-converter = { path = "../model-converter" } num = "*" [[bin]] diff --git a/src/example.rs b/src/example.rs index 658c274..578398b 100644 --- a/src/example.rs +++ b/src/example.rs @@ -1,8 +1,44 @@ -extern crate model_converter; +extern crate num; extern crate kdtree; -use model_converter::math::vector::Vector2; -use kdtree::KdTree2; +use std::fmt; +use std::ops::Index; + +use kdtree::Zero; +use kdtree::KdTree; + +#[derive(Copy, 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) + } +} + +impl fmt::Display for Vector2 { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "({}, {})", self[0], self[1]) + } +} + fn main() { let mut points = vec![ @@ -14,7 +50,7 @@ fn main() { Vector2::new(7.0, 2.0), ]; - let kdtree = KdTree2::new(&mut points); + let kdtree = KdTree::new(&mut points, 2); println!("{}", kdtree); diff --git a/src/lib.rs b/src/lib.rs index a5c37a6..a7e06bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,86 +1,85 @@ extern crate num; -extern crate model_converter; use std::fmt; +use std::ops::Index; +use std::cmp::PartialOrd; -use num::Zero; +pub trait Zero { + fn zero() -> Self; +} -use model_converter::math::vector; +impl Zero for T { + fn zero() -> Self { + num::Zero::zero() + } +} -macro_rules! define_kdtree { +/// A k-dimension kd tree +pub struct KdTree { + location: T, + left: Option>>, + right: Option>>, +} - ($name: ident, $vector_type: ty, $dimension: expr) => { +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) + } - /// A 3-dimension kd tree - pub struct $name { - location: $vector_type, - left: Option>, - right: Option>, - } + fn new_with_depth(points: &mut [T], dimension: usize, depth: usize) -> KdTree { - impl $name { - pub fn new(points: &mut [$vector_type]) -> $name { - $name::new_with_depth(points, 0) + // 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, } - - fn new_with_depth(points: &mut [$vector_type], depth: usize) -> $name { - - // 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 { - $name { - location: median, - left: None, - right: None, - } - } else { - $name { - location: median, - left: Some(Box::new($name::new_with_depth(&mut left, depth + 1))), - right: Some(Box::new($name::new_with_depth(right, depth + 1))), - } - } + } 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))), } - - 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 $name { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.print(formatter, "") - } - } } } -define_kdtree!(KdTree2, vector::Vector2, 2); -define_kdtree!(KdTree3, vector::Vector3, 3); -define_kdtree!(KdTree4, vector::Vector4, 4); +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, "") + } + +}