113 lines
2.9 KiB
Rust
113 lines
2.9 KiB
Rust
use std::fmt;
|
|
use std::cmp::Ordering;
|
|
|
|
/// A k-dimension kd tree
|
|
pub enum KdTree<T> {
|
|
Node {
|
|
location: T,
|
|
left: Box<KdTree<T>>,
|
|
right: Box<KdTree<T>>,
|
|
},
|
|
Leaf(Vec<T>),
|
|
}
|
|
|
|
impl<T: Clone> KdTree<T> where {
|
|
pub fn new<F: Fn(usize, &T, &T) -> Ordering>(
|
|
points: &mut [T],
|
|
dimension: usize,
|
|
comparator: F,
|
|
leaf_size: usize,
|
|
) -> KdTree<T> {
|
|
KdTree::new_with_depth(points, dimension, &comparator, leaf_size, 0)
|
|
}
|
|
|
|
fn new_with_depth<F: Fn(usize, &T, &T) -> Ordering>(
|
|
points: &mut [T],
|
|
dimension: usize,
|
|
comparator: &F,
|
|
leaf_size: usize,
|
|
depth: usize,
|
|
) -> KdTree<T> {
|
|
// Select axis to work on
|
|
let axis = depth % dimension;
|
|
|
|
// Sort the points by axis
|
|
points.sort_by(|a, b| comparator(axis, a, b));
|
|
|
|
// Find the median
|
|
let len = points.len();
|
|
|
|
// If there are not enough elements for a leaf, make a leaf
|
|
if len <= leaf_size {
|
|
let mut contained = vec![];
|
|
for p in points {
|
|
contained.push(p.clone());
|
|
}
|
|
return KdTree::Leaf(contained);
|
|
}
|
|
|
|
// Else split what's remaining
|
|
let delimiter = points.len() / 2;
|
|
let median = points[delimiter].clone();
|
|
|
|
// Build the left and right branches
|
|
let mut left = vec![];
|
|
for i in &points[0..delimiter] {
|
|
left.push(i.clone());
|
|
}
|
|
|
|
let right = &mut points[delimiter + 1..len];
|
|
|
|
// Recursive call
|
|
KdTree::Node {
|
|
location: median,
|
|
left: Box::new(KdTree::new_with_depth(
|
|
&mut left,
|
|
dimension,
|
|
comparator,
|
|
leaf_size,
|
|
depth + 1,
|
|
)),
|
|
right: Box::new(KdTree::new_with_depth(
|
|
right,
|
|
dimension,
|
|
comparator,
|
|
leaf_size,
|
|
depth + 1,
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: fmt::Display> KdTree<T> {
|
|
fn print(&self, formatter: &mut fmt::Formatter, indent: &str) -> fmt::Result {
|
|
match self {
|
|
&KdTree::Node {
|
|
ref location,
|
|
ref left,
|
|
ref right,
|
|
} => {
|
|
writeln!(formatter, "{}{}", indent, location)?;
|
|
left.print(formatter, &format!("{} ", indent))?;
|
|
right.print(formatter, &format!("{} ", indent))?;
|
|
}
|
|
|
|
&KdTree::Leaf(ref elements) => {
|
|
write!(formatter, "{}[", indent)?;
|
|
for element in elements {
|
|
write!(formatter, "{}, ", element)?;
|
|
}
|
|
writeln!(formatter, "]")?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<T: fmt::Display> fmt::Display for KdTree<T> {
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
self.print(formatter, "")
|
|
}
|
|
}
|