use crate::bounds::Bounds;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Predicate {
Intersects(Bounds),
Within(Bounds),
Contains(Bounds),
}
impl Predicate {
#[must_use]
pub fn matches(&self, value: &Bounds) -> bool {
match self {
Predicate::Intersects(q) => q.intersects(value),
Predicate::Within(q) => q.contains(value),
Predicate::Contains(q) => value.contains(q),
}
}
#[must_use]
pub fn could_match(&self, node: &Bounds) -> bool {
match self {
Predicate::Intersects(q) | Predicate::Within(q) => q.intersects(node),
Predicate::Contains(q) => node.intersects(q),
}
}
}
#[cfg(test)]
mod tests {
use super::Predicate;
use crate::bounds::Bounds;
#[test]
fn intersects_matches_overlap() {
let p = Predicate::Intersects(Bounds::new([0.0, 0.0], [2.0, 2.0]));
assert!(p.matches(&Bounds::new([1.0, 1.0], [3.0, 3.0])));
assert!(!p.matches(&Bounds::new([5.0, 5.0], [6.0, 6.0])));
}
#[test]
fn within_matches_contained() {
let p = Predicate::Within(Bounds::new([0.0, 0.0], [10.0, 10.0]));
assert!(p.matches(&Bounds::new([2.0, 2.0], [3.0, 3.0])));
assert!(!p.matches(&Bounds::new([2.0, 2.0], [12.0, 3.0])));
}
#[test]
fn contains_matches_covering() {
let p = Predicate::Contains(Bounds::new([4.0, 4.0], [5.0, 5.0]));
assert!(p.matches(&Bounds::new([0.0, 0.0], [10.0, 10.0])));
assert!(!p.matches(&Bounds::new([0.0, 0.0], [4.5, 4.5])));
}
#[test]
fn pruning_skips_disjoint_subtrees() {
let p = Predicate::Intersects(Bounds::new([0.0, 0.0], [1.0, 1.0]));
assert!(p.could_match(&Bounds::new([0.5, 0.5], [9.0, 9.0])));
assert!(!p.could_match(&Bounds::new([5.0, 5.0], [9.0, 9.0])));
}
}