More generic
This commit is contained in:
parent
2ce55950e0
commit
4c773c290d
|
@ -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]]
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
59
src/lib.rs
59
src/lib.rs
|
@ -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);
|
|
||||||
|
|
Loading…
Reference in New Issue