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}