pub fn intersections_against_line<Real, const NDIM: usize, const SIZE_AABB: usize>(
aabb: &[Real; SIZE_AABB],
line_org: &[Real; NDIM],
line_dir: &[Real; NDIM],
) -> Option<(Real, Real)>
where
Real: num_traits::Float,
{
assert_eq!(NDIM * 2, SIZE_AABB);
let mut tmin = Real::min_value();
let mut tmax = Real::max_value();
for i_dim in 0..NDIM {
if !line_dir[i_dim].abs().is_zero() {
let t1 = (aabb[i_dim] - line_org[i_dim]) / line_dir[i_dim];
let t2 = (aabb[i_dim + NDIM] - line_org[i_dim]) / line_dir[i_dim];
tmin = tmin.max(t1.min(t2));
tmax = tmax.min(t1.max(t2));
} else if line_org[i_dim] < aabb[i_dim] || line_org[i_dim] > aabb[i_dim + NDIM] {
return None;
}
}
if tmax >= tmin {
Some((tmin, tmax))
} else {
None
}
}
pub fn intersections_against_ray<Real, const NDIM: usize, const SIZE_AABB: usize>(
aabb: &[Real; SIZE_AABB],
ray_org: &[Real; NDIM],
ray_dir: &[Real; NDIM],
) -> Option<(Real, Real)>
where
Real: num_traits::Float,
{
intersections_against_line(aabb, ray_org, ray_dir).filter(|(_tmin, tmax)| *tmax >= Real::zero())
}
pub fn is_include_point<Real, const NDIM: usize, const SIZE_AABB: usize>(
aabb: &[Real; SIZE_AABB],
point: &[Real; NDIM],
) -> bool
where
Real: num_traits::Float,
{
assert_eq!(NDIM * 2, SIZE_AABB);
point
.iter()
.zip(&aabb[..NDIM])
.zip(&aabb[NDIM..])
.all(|((p, &min), &max)| *p >= min && *p <= max)
}
pub fn center<Real, const NDIM: usize, const SIZE_AABB: usize>(
aabb: &[Real; SIZE_AABB],
) -> [Real; NDIM]
where
Real: num_traits::Float,
{
let half = Real::one() / (Real::one() + Real::one());
std::array::from_fn::<_, NDIM, _>(|i| (aabb[i] + aabb[i + NDIM]) * half)
}
#[derive(Debug, Clone, Copy)]
pub struct AABB<Real, const NDIM: usize, const SIZE_AABB: usize> {
pub aabb: [Real; SIZE_AABB],
}
impl<Real, const NDIM: usize, const SIZE_AABB: usize> AABB<Real, NDIM, SIZE_AABB>
where
Real: num_traits::Float,
{
pub fn is_include_point(&self, point: &[Real; NDIM]) -> bool {
is_include_point::<Real, NDIM, SIZE_AABB>(&self.aabb, point)
}
pub fn intersections_against_ray(
&self,
ray_org: &[Real; NDIM],
ray_dir: &[Real; NDIM],
) -> Option<(Real, Real)> {
intersections_against_ray::<Real, NDIM, SIZE_AABB>(&self.aabb, ray_org, ray_dir)
}
pub fn intersections_against_line(
&self,
line_org: &[Real; NDIM],
line_dir: &[Real; NDIM],
) -> Option<(Real, Real)> {
intersections_against_line::<Real, NDIM, SIZE_AABB>(&self.aabb, line_org, line_dir)
}
pub fn center(&self) -> [Real; NDIM] {
center(&self.aabb)
}
}