From 2ce55950e03a8da30248d9f8eca7c1955f68f281 Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Mon, 5 Mar 2018 10:37:48 +0100 Subject: [PATCH] Initial commit --- .gitignore | 4 +++ Cargo.toml | 12 +++++++ src/example.rs | 21 ++++++++++++ src/lib.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/example.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..143b1ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +/target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0faacfa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "kdtree" +version = "0.1.0" +authors = ["Thomas Forgione "] + +[dependencies] +model-converter = { path = "../model-converter" } +num = "*" + +[[bin]] +name = "kdtree-example" +path = "src/example.rs" diff --git a/src/example.rs b/src/example.rs new file mode 100644 index 0000000..658c274 --- /dev/null +++ b/src/example.rs @@ -0,0 +1,21 @@ +extern crate model_converter; +extern crate kdtree; + +use model_converter::math::vector::Vector2; +use kdtree::KdTree2; + +fn main() { + let mut points = vec![ + Vector2::new(2.0, 3.0), + Vector2::new(5.0, 4.0), + Vector2::new(9.0, 6.0), + Vector2::new(4.0, 7.0), + Vector2::new(8.0, 1.0), + Vector2::new(7.0, 2.0), + ]; + + let kdtree = KdTree2::new(&mut points); + + println!("{}", kdtree); + +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a5c37a6 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,86 @@ +extern crate num; +extern crate model_converter; + +use std::fmt; + +use num::Zero; + +use model_converter::math::vector; + +macro_rules! define_kdtree { + + ($name: ident, $vector_type: ty, $dimension: expr) => { + + /// A 3-dimension kd tree + pub struct $name { + location: $vector_type, + left: Option>, + right: Option>, + } + + impl $name { + pub fn new(points: &mut [$vector_type]) -> $name { + $name::new_with_depth(points, 0) + } + + 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))), + } + } + } + + 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);