More generic

This commit is contained in:
Thomas Forgione 2018-03-05 11:17:50 +01:00
parent 2ce55950e0
commit 4c773c290d
No known key found for this signature in database
GPG Key ID: C75CD416BD1FFCE1
3 changed files with 110 additions and 76 deletions

View File

@ -4,7 +4,6 @@ version = "0.1.0"
authors = ["Thomas Forgione <thomas@tforgione.fr>"] authors = ["Thomas Forgione <thomas@tforgione.fr>"]
[dependencies] [dependencies]
model-converter = { path = "../model-converter" }
num = "*" num = "*"
[[bin]] [[bin]]

View File

@ -1,8 +1,44 @@
extern crate model_converter; extern crate num;
extern crate kdtree; extern crate kdtree;
use model_converter::math::vector::Vector2; use std::fmt;
use kdtree::KdTree2; 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<usize> 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() { fn main() {
let mut points = vec![ let mut points = vec![
@ -14,7 +50,7 @@ fn main() {
Vector2::new(7.0, 2.0), Vector2::new(7.0, 2.0),
]; ];
let kdtree = KdTree2::new(&mut points); let kdtree = KdTree::new(&mut points, 2);
println!("{}", kdtree); println!("{}", kdtree);

View File

@ -1,32 +1,35 @@
extern crate num; extern crate num;
extern crate model_converter;
use std::fmt; 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;
macro_rules! define_kdtree {
($name: ident, $vector_type: ty, $dimension: expr) => {
/// A 3-dimension kd tree
pub struct $name {
location: $vector_type,
left: Option<Box<$name>>,
right: Option<Box<$name>>,
} }
impl $name { impl<T: num::Zero> Zero for T {
pub fn new(points: &mut [$vector_type]) -> $name { fn zero() -> Self {
$name::new_with_depth(points, 0) num::Zero::zero()
}
} }
fn new_with_depth(points: &mut [$vector_type], depth: usize) -> $name { /// A k-dimension kd tree
pub struct KdTree<T> {
location: T,
left: Option<Box<KdTree<T>>>,
right: Option<Box<KdTree<T>>>,
}
impl<T, U> KdTree<T> where T: Copy + Clone + Index<usize, Output = U> + Zero, U: PartialOrd {
pub fn new(points: &mut [T], dimension: usize) -> KdTree<T> {
KdTree::new_with_depth(points, dimension, 0)
}
fn new_with_depth(points: &mut [T], dimension: usize, depth: usize) -> KdTree<T> {
// Select axis to work on // Select axis to work on
let axis = depth % $dimension; let axis = depth % dimension;
// Sort the points by axis // Sort the points by axis
points.sort_by(|p1, p2| p1[axis].partial_cmp(&p2[axis]).unwrap()); points.sort_by(|p1, p2| p1[axis].partial_cmp(&p2[axis]).unwrap());
@ -43,20 +46,22 @@ macro_rules! define_kdtree {
let right = &mut points[delimiter + 1 .. len]; let right = &mut points[delimiter + 1 .. len];
if left.len() == 0 || right.len() == 0 { if left.len() == 0 || right.len() == 0 {
$name { KdTree {
location: median, location: median,
left: None, left: None,
right: None, right: None,
} }
} else { } else {
$name { KdTree {
location: median, location: median,
left: Some(Box::new($name::new_with_depth(&mut left, depth + 1))), left: Some(Box::new(KdTree::new_with_depth(&mut left, dimension, depth + 1))),
right: Some(Box::new($name::new_with_depth(right, depth + 1))), right: Some(Box::new(KdTree::new_with_depth(right, dimension, depth + 1))),
}
} }
} }
} }
impl<T: Zero + Copy + Clone + fmt::Display + Index<usize>> KdTree<T> {
fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result { fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result {
writeln!(formatter, "{}{}", indent, self.location)?; writeln!(formatter, "{}{}", indent, self.location)?;
@ -72,15 +77,9 @@ macro_rules! define_kdtree {
} }
} }
impl fmt::Display for $name { impl<T: Zero + Copy + Clone + fmt::Display + Index<usize>> fmt::Display for KdTree<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.print(formatter, "") self.print(formatter, "")
} }
} }
}
}
define_kdtree!(KdTree2, vector::Vector2<f64>, 2);
define_kdtree!(KdTree3, vector::Vector3<f64>, 3);
define_kdtree!(KdTree4, vector::Vector4<f64>, 4);