use crate::Point3;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Aabb {
pub min: [f64; 3],
pub max: [f64; 3],
}
impl Aabb {
pub fn of_points<'a>(points: impl IntoIterator<Item = &'a [f64; 3]>) -> Option<Aabb> {
let mut it = points.into_iter();
let first = *it.next()?;
let mut b = Aabb {
min: first,
max: first,
};
for p in it {
b = b.union(Aabb { min: *p, max: *p });
}
Some(b)
}
pub fn union(self, other: Aabb) -> Aabb {
let mut b = self;
for ((lo, hi), (olo, ohi)) in b
.min
.iter_mut()
.zip(b.max.iter_mut())
.zip(other.min.iter().zip(other.max.iter()))
{
*lo = lo.min(*olo);
*hi = hi.max(*ohi);
}
b
}
pub fn extent(&self) -> [f64; 3] {
[
self.max[0] - self.min[0],
self.max[1] - self.min[1],
self.max[2] - self.min[2],
]
}
pub fn center(&self) -> [f64; 3] {
[
0.5 * (self.min[0] + self.max[0]),
0.5 * (self.min[1] + self.max[1]),
0.5 * (self.min[2] + self.max[2]),
]
}
pub fn diagonal(&self) -> f64 {
let e = self.extent();
(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]).sqrt()
}
pub fn of_point(p: Point3) -> Aabb {
Aabb {
min: [p.x, p.y, p.z],
max: [p.x, p.y, p.z],
}
}
pub fn intersects(&self, other: &Aabb) -> bool {
(0..3).all(|i| self.min[i] <= other.max[i] && other.min[i] <= self.max[i])
}
pub fn inflated(&self, by: f64) -> Aabb {
let mut out = *self;
for i in 0..3 {
let centre = 0.5 * (self.min[i] + self.max[i]);
out.min[i] = (self.min[i] - by).min(centre);
out.max[i] = (self.max[i] + by).max(centre);
}
out
}
}