use std::fmt;
use crate::core::geometry::point::Point2;
use crate::core::geometry::point::Point2i;
use crate::core::geometry::point::Point3;
use crate::core::geometry::vector::Vector2;
use crate::core::geometry::Number;
use crate::Float;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Bounds2<T>
where
T: Number,
{
pub p_min: Point2<T>,
pub p_max: Point2<T>,
}
impl<T> Default for Bounds2<T>
where
T: Number,
{
fn default() -> Self {
Self {
p_min: Point2 {
x: T::max_value(),
y: T::max_value(),
},
p_max: Point2 {
x: T::min_value(),
y: T::min_value(),
},
}
}
}
impl<T> fmt::Display for Bounds2<T>
where
T: Number,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[ {} - {} ]", self.p_min, self.p_max)
}
}
impl<T> From<[[T; 2]; 2]> for Bounds2<T>
where
T: Number,
{
fn from(ps: [[T; 2]; 2]) -> Self {
let p1 = Point2::from(ps[0]);
let p2 = Point2::from(ps[1]);
[p1, p2].into()
}
}
impl<T> From<[Point2<T>; 2]> for Bounds2<T>
where
T: Number,
{
fn from(ps: [Point2<T>; 2]) -> Self {
let (p1, p2) = (ps[0], ps[1]);
let p_min = Point2::from((
if p1.x < p2.x { p1.x } else { p2.x },
if p1.y < p2.y { p1.y } else { p2.y },
));
let p_max = Point2::from((
if p1.x > p2.x { p1.x } else { p2.x },
if p1.y > p2.y { p1.y } else { p2.y },
));
Bounds2 { p_min, p_max }
}
}
impl<T> From<(Point2<T>, Point2<T>)> for Bounds2<T>
where
T: Number,
{
fn from((p1, p2): (Point2<T>, Point2<T>)) -> Self {
let p_min = Point2::from((
if p1.x < p2.x { p1.x } else { p2.x },
if p1.y < p2.y { p1.y } else { p2.y },
));
let p_max = Point2::from((
if p1.x > p2.x { p1.x } else { p2.x },
if p1.y > p2.y { p1.y } else { p2.y },
));
Bounds2 { p_min, p_max }
}
}
impl<T> Bounds2<T>
where
T: Number,
{
pub fn diagonal(&self) -> Vector2<T> {
self.p_max - self.p_min
}
pub fn area(&self) -> T {
let d = self.p_max - self.p_min;
d.x * d.y
}
pub fn inside_exclusive(&self, p: Point2<T>) -> bool {
p.x >= self.p_min.x && p.x < self.p_max.x && p.y >= self.p_min.y && p.y < self.p_max.y
}
}
impl<T> Bounds2<T>
where
T: Number,
{
pub fn intersect(b1: &Bounds2<T>, b2: &Bounds2<T>) -> Self {
Self {
p_min: Point2::max(b1.p_min, b2.p_min),
p_max: Point2::min(b1.p_max, b2.p_max),
}
}
}
pub type Bounds2f = Bounds2<Float>;
impl From<Bounds2i> for Bounds2f {
fn from(b: Bounds2i) -> Self {
Self {
p_min: b.p_min.into(),
p_max: b.p_max.into(),
}
}
}
pub type Bounds2i = Bounds2<isize>;
impl Bounds2i {
pub fn iter(&self) -> impl Iterator<Item = Point2i> {
let x_range = self.p_min.x..self.p_max.x;
let y_range = self.p_min.y..self.p_max.y;
y_range.flat_map(move |y| x_range.clone().map(move |x| [x, y].into()))
}
}
impl From<Bounds2f> for Bounds2i {
fn from(b: Bounds2f) -> Self {
Self {
p_min: b.p_min.into(),
p_max: b.p_max.into(),
}
}
}
pub struct Bounds2iIterator {
b: Bounds2i,
p: Point2i,
}
impl Iterator for Bounds2iIterator {
type Item = Point2i;
fn next(&mut self) -> Option<Self::Item> {
self.p.x += 1;
if self.p.x == self.b.p_max.x {
self.p.x = self.b.p_min.x;
self.p.y += 1;
if self.p.x == self.b.p_max.y {
return None;
}
}
Some(self.p)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Bounds3<T> {
pub p_min: Point3<T>,
pub p_max: Point3<T>,
}
pub type Bounds3f = Bounds3<Float>;
pub type Bounds3i = Bounds3<isize>;
impl<T> From<[[T; 3]; 2]> for Bounds3<T>
where
T: Number,
{
fn from(ps: [[T; 3]; 2]) -> Self {
let p1 = Point3::from(ps[0]);
let p2 = Point3::from(ps[1]);
[p1, p2].into()
}
}
impl<T> From<[Point3<T>; 2]> for Bounds3<T>
where
T: Number,
{
fn from(ps: [Point3<T>; 2]) -> Self {
let (p1, p2) = (ps[0], ps[1]);
let p_min = Point3::from([
if p1.x < p2.x { p1.x } else { p2.x },
if p1.y < p2.y { p1.y } else { p2.y },
if p1.z < p2.z { p1.z } else { p2.z },
]);
let p_max = Point3::from([
if p1.x > p2.x { p1.x } else { p2.x },
if p1.y > p2.y { p1.y } else { p2.y },
if p1.z > p2.z { p1.z } else { p2.z },
]);
Bounds3 { p_min, p_max }
}
}
impl<T> Bounds3<T>
where
T: Number,
{
pub fn inside_exclusive(&self, p: Point3<T>) -> bool {
p.x >= self.p_min.x
&& p.x < self.p_max.x
&& p.y >= self.p_min.y
&& p.y < self.p_max.y
&& p.z >= self.p_min.z
&& p.z < self.p_max.z
}
}