use super::{Float, Line1, Vec3};
use crate::core::Axis;
#[derive(Clone, Copy)]
pub struct Cuboid {
pub min: Vec3,
pub max: Vec3,
}
impl Cuboid {
pub fn new(min: Vec3, max: Vec3) -> Self {
Self { min, max }
}
pub fn new_valid(min: Vec3, max: Vec3) -> Self {
Self { min, max }.validate()
}
pub fn valid(&self) -> bool {
self.min.x < self.max.x && self.min.y < self.max.y && self.min.z < self.max.z
}
pub fn validate(self) -> Self {
let (x1, x2) = if self.min.x < self.max.x {
(self.min.x, self.max.x)
} else {
(self.max.x, self.min.x)
};
let (y1, y2) = if self.min.y < self.max.y {
(self.min.y, self.max.y)
} else {
(self.max.y, self.min.y)
};
let (z1, z2) = if self.min.z < self.max.z {
(self.min.z, self.max.z)
} else {
(self.max.z, self.min.z)
};
return Self {
min: Vec3::new(x1, y1, z1),
max: Vec3::new(x2, y2, z2),
};
}
pub fn width(&self) -> Float {
self.max.x - self.min.x
}
pub fn height(&self) -> Float {
self.max.y - self.min.y
}
pub fn length(&self) -> Float {
self.max.z - self.min.z
}
pub fn center(&self) -> Vec3 {
(self.min + self.max) / 2.0
}
pub fn corners(&self) -> [Vec3; 8] {
let x1 = self.min.x;
let x2 = self.max.x;
let y1 = self.min.y;
let y2 = self.max.y;
let z1 = self.min.z;
let z2 = self.max.z;
[
Vec3::new(x1, y1, z1),
Vec3::new(x2, y1, z1),
Vec3::new(x1, y2, z1),
Vec3::new(x2, y2, z1),
Vec3::new(x1, y1, z2),
Vec3::new(x2, y1, z2),
Vec3::new(x1, y2, z2),
Vec3::new(x2, y2, z2),
]
}
pub fn contains_point(&self, p: Vec3) -> bool {
p.x >= self.min.x
&& p.x <= self.max.x
&& p.y >= self.min.y
&& p.y <= self.max.y
&& p.z >= self.min.z
&& p.z <= self.max.z
}
pub fn contains_cuboid(&self, other: &Self) -> bool {
other.min.x >= self.min.x
&& other.min.x <= self.max.x
&& other.max.x >= self.min.x
&& other.max.x <= self.max.x
&& other.min.y >= self.min.y
&& other.min.y <= self.max.y
&& other.max.y >= self.min.y
&& other.max.y <= self.max.y
&& other.min.z >= self.min.z
&& other.min.z <= self.max.z
&& other.max.z >= self.min.z
&& other.max.z <= self.max.z
}
pub fn split(self, _position: Float, _axis: Axis) -> (Self, Self) {
todo!()
}
pub fn split_x(self, _position: Float) -> (Self, Self) {
todo!()
}
pub fn split_y(self, _position: Float) -> (Self, Self) {
todo!()
}
pub fn intersects(&self, other: &Self) -> bool {
self.x_intersects(other) && self.y_intersects(other)
}
pub fn x_intersects(&self, other: &Self) -> bool {
!(self.min.x > other.max.x || other.min.x > self.max.x)
}
pub fn y_intersects(&self, other: &Self) -> bool {
!(self.min.y > other.max.y || other.min.y > self.max.y)
}
pub fn z_intersects(&self, other: &Self) -> bool {
!(self.min.z > other.max.z || other.min.z > self.max.z)
}
pub fn intersection(&self, other: &Self) -> Option<Self> {
if !self.intersects(other) {
return None;
}
let min_x = if self.min.x > other.min.x {
self.min.x
} else {
other.min.x
};
let min_y = if self.min.y > other.min.y {
self.min.y
} else {
other.min.y
};
let min_z = if self.min.z > other.min.z {
self.min.z
} else {
other.min.z
};
let max_x = if self.max.x < other.max.x {
self.max.x
} else {
other.max.x
};
let max_y = if self.max.y < other.max.y {
self.max.y
} else {
other.max.y
};
let max_z = if self.max.z < other.max.z {
self.max.z
} else {
other.max.z
};
Some(Cuboid::new(
Vec3::new(min_x, min_y, min_z),
Vec3::new(max_x, max_y, max_z),
))
}
pub fn intersection_x(&self, other: &Self) -> Option<Line1> {
if !self.x_intersects(other) {
return None;
}
let min = if self.min.x > other.min.x {
self.min.x
} else {
other.min.x
};
let max = if self.max.x < other.max.x {
self.max.x
} else {
other.max.x
};
Some(Line1::new(min, max))
}
pub fn intersection_y(&self, other: &Cuboid) -> Option<Line1> {
if !self.y_intersects(other) {
return None;
}
let min = if self.min.y > other.min.y {
self.min.y
} else {
other.min.y
};
let max = if self.max.y < other.max.y {
self.max.y
} else {
other.max.y
};
Some(Line1::new(min, max))
}
pub fn intersection_z(&self, other: &Cuboid) -> Option<Line1> {
if !self.z_intersects(other) {
return None;
}
let min = if self.min.z > other.min.z {
self.min.z
} else {
other.min.z
};
let max = if self.max.z < other.max.z {
self.max.z
} else {
other.max.z
};
Some(Line1::new(min, max))
}
}