Cleaner, min leaf size
This commit is contained in:
parent
4c773c290d
commit
64f25f51bd
|
@ -50,7 +50,7 @@ fn main() {
|
||||||
Vector2::new(7.0, 2.0),
|
Vector2::new(7.0, 2.0),
|
||||||
];
|
];
|
||||||
|
|
||||||
let kdtree = KdTree::new(&mut points, 2);
|
let kdtree = KdTree::new(&mut points, 2, 1);
|
||||||
|
|
||||||
println!("{}", kdtree);
|
println!("{}", kdtree);
|
||||||
|
|
||||||
|
|
60
src/lib.rs
60
src/lib.rs
|
@ -15,18 +15,17 @@ impl<T: num::Zero> Zero for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A k-dimension kd tree
|
/// A k-dimension kd tree
|
||||||
pub struct KdTree<T> {
|
pub enum KdTree<T> {
|
||||||
location: T,
|
Node { location: T, left: Box<KdTree<T>>, right: Box<KdTree<T>> },
|
||||||
left: Option<Box<KdTree<T>>>,
|
Leaf(Vec<T>),
|
||||||
right: Option<Box<KdTree<T>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> KdTree<T> where T: Copy + Clone + Index<usize, Output = U> + Zero, U: PartialOrd {
|
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> {
|
pub fn new(points: &mut [T], dimension: usize, leaf_size: usize) -> KdTree<T> {
|
||||||
KdTree::new_with_depth(points, dimension, 0)
|
KdTree::new_with_depth(points, dimension, leaf_size, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_with_depth(points: &mut [T], dimension: usize, depth: usize) -> KdTree<T> {
|
fn new_with_depth(points: &mut [T], dimension: usize, leaf_size: usize, depth: usize) -> KdTree<T> {
|
||||||
|
|
||||||
// Select axis to work on
|
// Select axis to work on
|
||||||
let axis = depth % dimension;
|
let axis = depth % dimension;
|
||||||
|
@ -36,41 +35,50 @@ impl<T, U> KdTree<T> where T: Copy + Clone + Index<usize, Output = U> + Zero, U:
|
||||||
|
|
||||||
// Find the median
|
// Find the median
|
||||||
let len = points.len();
|
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);
|
||||||
|
return KdTree::Leaf(contained);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else split what's remaining
|
||||||
let delimiter = points.len() / 2;
|
let delimiter = points.len() / 2;
|
||||||
let median = points[delimiter];
|
let median = points[delimiter];
|
||||||
|
|
||||||
|
// Build the left and right branches
|
||||||
let zero = Zero::zero();
|
let zero = Zero::zero();
|
||||||
let mut left = vec![zero; delimiter];
|
let mut left = vec![zero; delimiter];
|
||||||
left.copy_from_slice(&points[0..delimiter]);
|
left.copy_from_slice(&points[0..delimiter]);
|
||||||
|
|
||||||
let right = &mut points[delimiter + 1 .. len];
|
let right = &mut points[delimiter + 1 .. len];
|
||||||
|
|
||||||
if left.len() == 0 || right.len() == 0 {
|
// Recursive call
|
||||||
KdTree {
|
KdTree::Node {
|
||||||
location: median,
|
location: median,
|
||||||
left: None,
|
left: Box::new(KdTree::new_with_depth(&mut left, dimension, leaf_size, depth + 1)),
|
||||||
right: None,
|
right: Box::new(KdTree::new_with_depth(right, dimension, leaf_size, 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))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Zero + Copy + Clone + fmt::Display + Index<usize>> KdTree<T> {
|
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)?;
|
match self {
|
||||||
|
&KdTree::Node { location, ref left, ref right } => {
|
||||||
|
writeln!(formatter, "{}{}", indent, location)?;
|
||||||
|
left.print(formatter, &format!("{} ", indent))?;
|
||||||
|
right.print(formatter, &format!("{} ", indent))?;
|
||||||
|
},
|
||||||
|
|
||||||
if let Some(left) = self.left.as_ref() {
|
&KdTree::Leaf(ref elements) => {
|
||||||
left.print(formatter, &format!("{} ", indent))?;
|
write!(formatter, "{}[", indent)?;
|
||||||
}
|
for element in elements {
|
||||||
|
write!(formatter, "{}, ", element)?;
|
||||||
if let Some(right) = self.right.as_ref() {
|
}
|
||||||
right.print(formatter, &format!("{} ", indent))?;
|
writeln!(formatter, "]")?;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue