Skip to content

Commit

Permalink
add within_bounding_box (#60)
Browse files Browse the repository at this point in the history
* add within_bounding_box

* warnings
  • Loading branch information
mrhooray authored Nov 30, 2024
1 parent 16485ab commit cf79df6
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/kdtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,37 @@ impl<A: Float + Zero + One, T: std::cmp::PartialEq, U: AsRef<[A]> + std::cmp::Pa
Ok(evaluated.len())
}

pub fn within_bounding_box(&self, min_bounds: &[A], max_bounds: &[A]) -> Result<Vec<&T>, ErrorKind> {
self.check_point(min_bounds)?;
self.check_point(max_bounds)?;
if self.size == 0 {
return Ok(vec![]);
}
let mut pending = vec![];
let mut evaluated = vec![];
pending.push(self);
while let Some(curr) = pending.pop() {
if curr.is_leaf() {
let points = curr.points.as_ref().unwrap().iter();
let bucket = curr.bucket.as_ref().unwrap().iter();
for (p, b) in points.zip(bucket) {
if util::within_bounding_box(p.as_ref(), min_bounds, max_bounds) {
evaluated.push(b);
}
}
} else {
if curr.belongs_in_left(min_bounds) {
pending.push(curr.left.as_ref().unwrap());
}
if !curr.belongs_in_left(max_bounds) {
pending.push(curr.right.as_ref().unwrap());
}
}
}

Ok(evaluated)
}

#[inline(always)]
fn evaluated_heap<F>(&self, point: &[A], radius: A, distance: &F) -> BinaryHeap<HeapElement<A, &T>>
where
Expand Down Expand Up @@ -590,4 +621,33 @@ mod tests {
tree.add([max], ()).unwrap();
}
}

#[test]
fn test_within_bounding_box() {
let mut tree = KdTree::with_capacity(2, 2);
for i in 0..10 {
for j in 0..10 {
let id = i.to_string() + &j.to_string();
tree.add([i as f64, j as f64], id).unwrap();
}
}

let within: Vec<String> = tree
.within_bounding_box(&[4.0, 4.0], &[6.0, 6.0])
.unwrap()
.iter()
.cloned()
.cloned()
.collect();
assert_eq!(within.len(), 9);
assert!(within.contains(&String::from("44")));
assert!(within.contains(&String::from("45")));
assert!(within.contains(&String::from("46")));
assert!(within.contains(&String::from("54")));
assert!(within.contains(&String::from("55")));
assert!(within.contains(&String::from("56")));
assert!(within.contains(&String::from("64")));
assert!(within.contains(&String::from("65")));
assert!(within.contains(&String::from("66")));
}
}
22 changes: 22 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,22 @@ where
distance(p1, &p2[..])
}

pub fn within_bounding_box<T>(p: &[T], min_bounds: &[T], max_bounds: &[T]) -> bool
where
T: Float,
{
for ((l, h), v) in min_bounds.iter().zip(max_bounds.iter()).zip(p) {
if v < l || v > h {
return false;
}
}
true
}

#[cfg(test)]
mod tests {
use super::distance_to_space;
use super::within_bounding_box;
use crate::distance::squared_euclidean;

#[test]
Expand Down Expand Up @@ -67,4 +80,13 @@ mod tests {
);
assert_eq!(dis, 4.0);
}

#[test]
fn test_within_bounding_box() {
assert!(within_bounding_box(&[1.0, 1.0], &[0.0, 0.0], &[2.0, 2.0]));
assert!(within_bounding_box(&[1.0, 1.0], &[1.0, 1.0], &[2.0, 2.0]));
assert!(within_bounding_box(&[1.0, 1.0], &[0.0, 0.0], &[1.0, 1.0]));
assert!(!within_bounding_box(&[2.0, 2.0], &[0.0, 0.0], &[1.0, 1.0]));
assert!(!within_bounding_box(&[0.0, 0.0], &[1.0, 1.0], &[2.0, 2.0]));
}
}

0 comments on commit cf79df6

Please sign in to comment.