diff --git a/src/kdtree/buffors.rs b/src/kdtree/buffors.rs new file mode 100644 index 0000000..0fef572 --- /dev/null +++ b/src/kdtree/buffors.rs @@ -0,0 +1,24 @@ +use ::kdtree::KdtreePointTrait; + +pub trait KdtreeBuffor { + fn nearest_search(&self, node : &KdtreePoint) -> Option; + fn has_neighbor_in_range(&self, node : &KdtreePoint) -> bool; +} + +pub struct FakeKdtreeBuffor { +} + +impl FakeKdtreeBuffor { + pub fn new() -> FakeKdtreeBuffor { + FakeKdtreeBuffor {} + } +} + +impl KdtreeBuffor for FakeKdtreeBuffor { + fn nearest_search(&self, node : &KdtreePoint) -> Option { + None + } + fn has_neighbor_in_range(&self, node : &KdtreePoint) -> bool { + false + } +} diff --git a/src/kdtree/mod.rs b/src/kdtree/mod.rs index 612c246..74502b1 100644 --- a/src/kdtree/mod.rs +++ b/src/kdtree/mod.rs @@ -2,23 +2,32 @@ pub mod test_common; pub mod distance; +pub mod buffors; mod partition; mod bounds; use self::bounds::*; use self::distance::*; +use self::buffors::*; pub trait KdtreePointTrait: Copy { fn dims(&self) -> &[f64]; } -pub struct Kdtree { - nodes: Vec>, +pub struct Kdtree { + nodes: Vec>, + buffor : KdtreeBuffor, } -impl Kdtree { - pub fn new(mut points: &mut [T]) -> Kdtree { +impl Kdtree { + pub fn new(mut points: &mut [KdtreePoint]) -> Kdtree { + Kdtree::new_with_buffor(&mut points, FakeKdtreeBuffor{}) + } +} + +impl > Kdtree { + pub fn new_with_buffor(mut points: &mut [KdtreePoint], buffor : Buffor) -> Kdtree { if points.len() == 0 { panic!("empty vector point not allowed"); } @@ -27,6 +36,7 @@ impl Kdtree { let mut tree = Kdtree { nodes: vec![], + buffor: buffor }; tree.build_tree(&mut points, &rect); @@ -34,7 +44,7 @@ impl Kdtree { tree } - pub fn nearest_search(&self, node: &T) -> T + pub fn nearest_search(&self, node: &KdtreePoint) -> KdtreePoint { let mut nearest_neighbor = 0usize; let mut best_distance = squared_euclidean(node.dims(), &self.nodes[0].point.dims()); @@ -43,7 +53,13 @@ impl Kdtree { self.nodes[nearest_neighbor].point } - fn nearest_search_impl(&self, p: &T, searched_index: usize, best_distance_squared: &mut f64, best_leaf_found: &mut usize) { + pub fn has_neighbor_in_range(&self, node: &KdtreePoint, range: f64) -> bool { + let squared_range = range * range; + + squared_euclidean(&self.nearest_search(node).dims(), node.dims()) <= squared_range + } + + fn nearest_search_impl(&self, p: &KdtreePoint, searched_index: usize, best_distance_squared: &mut f64, best_leaf_found: &mut usize) { let node = &self.nodes[searched_index]; let dimension = node.dimension; @@ -77,14 +93,14 @@ impl Kdtree { } - fn add_node(&mut self, p: T, dimension: usize, split_on: f64) -> usize { + fn add_node(&mut self, p: KdtreePoint, dimension: usize, split_on: f64) -> usize { let node = KdtreeNode::new(p, dimension, split_on); self.nodes.push(node); self.nodes.len() - 1 } - fn build_tree(&mut self, nodes: &mut [T], bounds: &Bounds) -> usize { + fn build_tree(&mut self, nodes: &mut [KdtreePoint], bounds: &Bounds) -> usize { let (splitting_index, pivot_value) = partition::partition_sliding_midpoint(nodes, bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim()); let node_id = self.add_node(nodes[splitting_index], bounds.get_widest_dim(), bounds.get_midvalue_of_widest_dim()); @@ -194,6 +210,18 @@ mod tests { } } + #[test] + fn has_neighbor_in_range() { + let mut vec: Vec = vec![Point2WithId::new(0,2.,0.)]; + + let tree = Kdtree::new(&mut vec); + + assert_eq!(false,tree.has_neighbor_in_range(&Point2WithId::new(0,0.,0.), 0.)); + assert_eq!(false,tree.has_neighbor_in_range(&Point2WithId::new(0,0.,0.), 1.)); + assert_eq!(true,tree.has_neighbor_in_range(&Point2WithId::new(0,0.,0.), 2.)); + assert_eq!(true,tree.has_neighbor_in_range(&Point2WithId::new(0,0.,0.), 300.)); + } + fn qc_value_vec_to_2d_points_vec(xs: &Vec) -> Vec { let mut vec: Vec = vec![]; for i in 0..xs.len() {