lk_math/
aabb.rs

1use std::ops::Sub;
2
3use super::{geometric_traits::CoverObject, vector::Vector};
4
5#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
6pub struct Aabb<const C: usize, T> {
7    pub min: Vector<C, T>,
8    pub max: Vector<C, T>,
9}
10
11impl<const C: usize, T: std::cmp::Ord + Copy> CoverObject<Vector<C, T>> for Aabb<C, T> {
12    fn cover(&mut self, point: &Vector<C, T>) {
13        #[allow(clippy::needless_range_loop)]
14        for x in 0..C {
15            self.min.values[x] = std::cmp::min(self.min.values[x], point.values[x]);
16            self.max.values[x] = std::cmp::max(self.max.values[x], point.values[x]);
17        }
18    }
19}
20
21impl<const C: usize, T> Aabb<C, T>
22where
23    T: std::cmp::Ord + Copy,
24    Vector<C, T>: Sub<Output = Vector<C, T>>,
25{
26    pub fn new(min: Vector<C, T>, max: Vector<C, T>) -> Self {
27        Self { min, max }
28    }
29
30    #[allow(dead_code)]
31    pub fn covering(points: &[Vector<C, T>]) -> Option<Self> {
32        let mut iter = points.iter();
33        if let Some(a) = iter.next() {
34            let mut result = Self::new(*a, *a);
35
36            for b in iter {
37                result.cover(b);
38            }
39
40            Some(result)
41        } else {
42            None
43        }
44    }
45    pub fn dim(&self) -> Vector<C, T> {
46        self.max - self.min
47    }
48}
49
50pub type Aabb2<T> = Aabb<2, T>;
51pub type Aabb3<T> = Aabb<3, T>;
52pub type Aabb4<T> = Aabb<4, T>;
53
54#[cfg(test)]
55mod tests {
56    use crate::{aabb::Aabb2, vector::V2};
57
58    #[test]
59    fn aabb_covering() {
60        let points = vec![V2::from_xy(2, 0), V2::from_xy(0, 2)];
61        let aabb = Aabb2::covering(&points);
62        assert_eq!(
63            aabb.unwrap(),
64            Aabb2::new(V2::from_xy(0, 0), V2::from_xy(2, 2))
65        );
66    }
67}