use na::{self, Real};
use bounding_volume::{BoundingVolume, HasBoundingVolume};
use math::{Point, Vector, Isometry};
pub fn aabb<N, G: ?Sized>(g: &G, m: &Isometry<N>) -> AABB<N>
where
N: Real,
G: HasBoundingVolume<N, AABB<N>>,
{
g.bounding_volume(m)
}
#[derive(Debug, PartialEq, Clone)]
pub struct AABB<N: Real> {
mins: Point<N>,
maxs: Point<N>,
}
impl<N: Real> AABB<N> {
pub fn new(mins: Point<N>, maxs: Point<N>) -> AABB<N> {
AABB {
mins: mins,
maxs: maxs,
}
}
#[inline]
pub fn mins(&self) -> &Point<N> {
&self.mins
}
#[inline]
pub fn maxs(&self) -> &Point<N> {
&self.maxs
}
#[inline]
pub fn center(&self) -> Point<N> {
na::center(&self.mins, &self.maxs)
}
#[inline]
pub fn half_extents(&self) -> Vector<N> {
let half: N = na::convert(0.5);
(self.maxs - self.mins) * half
}
}
impl<N: Real> BoundingVolume<N> for AABB<N> {
#[inline]
fn center(&self) -> Point<N> {
self.center()
}
#[inline]
fn intersects(&self, other: &AABB<N>) -> bool {
na::partial_le(&self.mins, &other.maxs) && na::partial_ge(&self.maxs, &other.mins)
}
#[inline]
fn contains(&self, other: &AABB<N>) -> bool {
na::partial_le(&self.mins, &other.mins) && na::partial_ge(&self.maxs, &other.maxs)
}
#[inline]
fn merge(&mut self, other: &AABB<N>) {
self.mins = na::inf(&self.mins, &other.mins);
self.maxs = na::sup(&self.maxs, &other.maxs);
}
#[inline]
fn merged(&self, other: &AABB<N>) -> AABB<N> {
AABB {
mins: na::inf(&self.mins, &other.mins),
maxs: na::sup(&self.maxs, &other.maxs),
}
}
#[inline]
fn loosen(&mut self, amount: N) {
assert!(
amount >= na::zero(),
"The loosening margin must be positive."
);
self.mins = self.mins + Vector::repeat(-amount);
self.maxs = self.maxs + Vector::repeat(amount);
}
#[inline]
fn loosened(&self, amount: N) -> AABB<N> {
assert!(
amount >= na::zero(),
"The loosening margin must be positive."
);
AABB {
mins: self.mins + Vector::repeat(-amount),
maxs: self.maxs + Vector::repeat(amount),
}
}
#[inline]
fn tighten(&mut self, amount: N) {
assert!(
amount >= na::zero(),
"The tightening margin must be positive."
);
self.mins = self.mins + Vector::repeat(amount);
self.maxs = self.maxs + Vector::repeat(-amount);
assert!(
na::partial_le(&self.mins, &self.maxs),
"The tightening margin is to large."
);
}
#[inline]
fn tightened(&self, amount: N) -> AABB<N> {
assert!(
amount >= na::zero(),
"The tightening margin must be positive."
);
AABB::new(
self.mins + Vector::repeat(amount),
self.maxs + Vector::repeat(-amount),
)
}
}