use parry2d_f64::bounding_volume::BoundingVolume as _;
use parry3d_f64::bounding_volume::BoundingVolume as _;
use super::{Point, Vector};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct Aabb<const D: usize> {
pub min: Point<D>,
pub max: Point<D>,
}
impl<const D: usize> Aabb<D> {
pub fn contains(&self, point: impl Into<Point<D>>) -> bool {
let point = point.into();
let min = self
.min
.coords
.components
.into_iter()
.zip(point.coords.components);
for (min, p) in min {
if min > p {
return false;
}
}
let max = self
.max
.coords
.components
.into_iter()
.zip(point.coords.components);
for (max, p) in max {
if max < p {
return false;
}
}
true
}
}
impl Aabb<2> {
pub fn from_points(
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
let points: Vec<_> = points
.into_iter()
.map(|point| point.into().to_na())
.collect();
parry2d_f64::bounding_volume::Aabb::from_points(&points).into()
}
pub fn from_parry(aabb: parry2d_f64::bounding_volume::Aabb) -> Self {
Self {
min: aabb.mins.into(),
max: aabb.maxs.into(),
}
}
pub fn to_parry(self) -> parry2d_f64::bounding_volume::Aabb {
parry2d_f64::bounding_volume::Aabb {
mins: self.min.to_na(),
maxs: self.max.to_na(),
}
}
pub fn merged(&self, other: &Self) -> Self {
self.to_parry().merged(&other.to_parry()).into()
}
}
impl Aabb<3> {
pub fn from_points(
points: impl IntoIterator<Item = impl Into<Point<3>>>,
) -> Self {
let points: Vec<_> = points
.into_iter()
.map(|point| point.into().to_na())
.collect();
parry3d_f64::bounding_volume::Aabb::from_points(&points).into()
}
pub fn from_parry(aabb: parry3d_f64::bounding_volume::Aabb) -> Self {
Self {
min: aabb.mins.into(),
max: aabb.maxs.into(),
}
}
pub fn to_parry(self) -> parry3d_f64::bounding_volume::Aabb {
parry3d_f64::bounding_volume::Aabb {
mins: self.min.to_na(),
maxs: self.max.to_na(),
}
}
pub fn vertices(&self) -> [Point<3>; 8] {
self.to_parry().vertices().map(Into::into)
}
pub fn center(&self) -> Point<3> {
self.to_parry().center().into()
}
pub fn size(&self) -> Vector<3> {
self.to_parry().extents().into()
}
pub fn include_point(self, point: &Point<3>) -> Self {
let mut aabb = self.to_parry();
aabb.take_point(point.to_na());
Self::from_parry(aabb)
}
pub fn merged(&self, other: &Self) -> Self {
self.to_parry().merged(&other.to_parry()).into()
}
}
impl From<parry2d_f64::bounding_volume::Aabb> for Aabb<2> {
fn from(aabb: parry2d_f64::bounding_volume::Aabb) -> Self {
Self::from_parry(aabb)
}
}
impl From<parry3d_f64::bounding_volume::Aabb> for Aabb<3> {
fn from(aabb: parry3d_f64::bounding_volume::Aabb) -> Self {
Self::from_parry(aabb)
}
}
#[cfg(test)]
mod tests {
use super::Aabb;
#[test]
fn contains() {
let aabb = Aabb::<2>::from_points([[1., 1.], [3., 3.]]);
assert!(aabb.contains([2., 2.]));
assert!(!aabb.contains([0., 0.]));
assert!(!aabb.contains([4., 0.]));
assert!(!aabb.contains([4., 4.]));
assert!(!aabb.contains([0., 4.]));
assert!(!aabb.contains([2., 0.]));
assert!(!aabb.contains([2., 4.]));
assert!(!aabb.contains([0., 2.]));
assert!(!aabb.contains([4., 2.]));
}
}