use crate::vector3d::*;
use crate::HashSetFnv;
#[derive(Eq, PartialEq, Default, Hash, Copy, Clone, Debug)]
pub struct Box3D {
pub position: Vector3D::<u64>,
pub size: Vector3D::<u64>,
pub id: usize,
pub origin: u16,
}
impl Box3D {
pub fn from_position_size(position: Vector3D::<u64>, size: Vector3D::<u64>, id: usize, origin: u16) -> Box3D
{
Box3D { position, size, id, origin }
}
pub fn from_xyz_whl(x: u64, y: u64, z: u64, w: u64, h: u64, l: u64, id: usize, origin: u16) -> Box3D
{
let position = Vector3D::<u64>::new(x,y,z);
let size = Vector3D::<u64>::new(w,h,l);
Box3D { position, size, id, origin }
}
pub fn volume(&self) -> u64
{
self.size.x * self.size.y * self.size.z
}
pub fn fits_in(&self, other: &Box3D) -> bool
{
self.size.x <= other.size.x && self.size.y <= other.size.y && self.size.z <= other.size.z
}
pub fn is_in(&self, other: &Box3D) -> bool
{ self.position.x >= other.position.x && self.position.y >= other.position.y && self.position.z >= other.position.z &&
self.x2() <= other.x2() && self.y2() <= other.y2() && self.z2() <= other.z2() }
pub fn x2(&self) -> u64
{
self.position.x + self.size.x
}
pub fn y2(&self) -> u64
{
self.position.y + self.size.y
}
pub fn z2(&self) -> u64
{
self.position.z + self.size.z
}
pub fn intersects(&self, other: &Box3D) -> bool
{
range_overlap(self.position.x, self.x2(), other.position.x, other.x2()) &&
range_overlap(self.position.y, self.y2(), other.position.y, other.y2()) &&
range_overlap(self.position.z, self.z2(), other.position.z, other.z2())
}
pub fn is_covered_among(&self, boxes: &HashSetFnv<Box3D>) -> bool
{
boxes.iter().any(|other| self.is_in(other))
}
pub fn get_rotations(&self) -> Vec<Box3D>
{
vec![
Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.x, self.size.y, self.size.z), self.id, self.origin), Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.y, self.size.x, self.size.z), self.id, self.origin), Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.z, self.size.y, self.size.x), self.id, self.origin), Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.x, self.size.z, self.size.y), self.id, self.origin), Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.z, self.size.x, self.size.y), self.id, self.origin), Box3D::from_position_size(self.position, Vector3D::<u64>::new(self.size.y, self.size.z, self.size.x), self.id, self.origin) ]
}
}
fn range_overlap<T: std::cmp::PartialOrd>(amin: T, amax: T, bmin: T, bmax: T) -> bool
{
amax > bmin && bmax > amin
}