use core::cmp::Ordering;
use core::fmt;
use core::ops::Add;
use core::ops::AddAssign;
use core::ops::Bound;
use core::ops::Range;
use core::ops::RangeBounds;
use core::ops::RangeInclusive;
use core::ops::Sub;
use core::ops::SubAssign;
#[cfg(feature = "random")]
use rand::distributions::uniform::SampleUniform;
#[cfg(feature = "random")]
use rand::Rng;
use crate::layout::Points;
use crate::p2d;
use crate::p3d;
use crate::p4d;
use crate::Integer;
use crate::Layout;
use crate::Layout2d;
use crate::Layout3d;
use crate::Layout4d;
use crate::Point;
use crate::Point2d;
use crate::Point3d;
use crate::Point4d;
use crate::Vec2d;
use crate::Vec3d;
use crate::Vec4d;
use crate::Vector;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct BBox<S: Integer, V: Vector<S>> {
min: Point<S, V>,
max: Point<S, V>,
}
pub type BBox2d<S = i64> = BBox<S, Vec2d<S>>;
pub type BBox3d<S = i64> = BBox<S, Vec3d<S>>;
pub type BBox4d<S = i64> = BBox<S, Vec4d<S>>;
impl<S, V> BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
pub fn new(origin: Point<S, V>, size: V) -> BBox<S, V> {
let min = origin;
let max = Point::with(|i| origin[i] + size[i] - S::one());
assert!(size.as_slice().iter().all(|&c| c > S::zero()));
BBox { min, max }
}
#[deprecated = "Use `from` instead."]
pub fn from_point(p: Point<S, V>) -> BBox<S, V> {
BBox { min: p, max: p }
}
#[deprecated = "Use `from_corners` instead."]
pub fn from_points(p0: Point<S, V>, p1: Point<S, V>) -> BBox<S, V> {
let min = p0.min(p1);
let max = p0.max(p1);
BBox { min, max }
}
pub fn from_corners(p0: Point<S, V>, p1: Point<S, V>) -> BBox<S, V> {
let min = p0.min(p1);
let max = p0.max(p1);
BBox { min, max }
}
pub fn enclosing<'a, II>(ii: II) -> Option<BBox<S, V>>
where
S: 'a,
V: 'a,
II: IntoIterator<Item = &'a Point<S, V>>,
{
let mut iter = ii.into_iter();
if let Some(p0) = iter.next() {
let mut bbox = BBox::from(*p0);
for p in iter {
bbox.extend_to(*p);
}
Some(bbox)
} else {
None
}
}
pub fn min(&self) -> Point<S, V> {
self.min
}
pub fn max(&self) -> Point<S, V> {
self.max
}
pub fn lengths(&self) -> V {
self.max - self.min + V::ones()
}
pub fn volume(&self) -> usize
where
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
self.lengths()
.as_slice()
.iter()
.map(|&len| len.to_usize())
.product()
}
pub fn center(&self) -> Point<S, V> {
Point::<S, V>::from((self.min.to_vec() + self.max.to_vec()) / S::two())
}
pub fn lub(&self, other: &BBox<S, V>) -> BBox<S, V> {
let min = self.min().min(other.min());
let max = self.max().max(other.max());
BBox { min, max }
}
pub fn intersection(&self, other: &BBox<S, V>) -> Option<BBox<S, V>> {
let min = self.min().max(other.min());
let max = self.max().min(other.max());
match min.componentwise_cmp(&max) {
Some(Ordering::Less) | Some(Ordering::Equal) => Some(BBox { min, max }),
_ => None,
}
}
pub fn extended_to(&self, p: Point<S, V>) -> BBox<S, V> {
let min = self.min().min(p);
let max = self.max().max(p);
BBox { min, max }
}
pub fn extend_to(&mut self, p: Point<S, V>) {
self.min = self.min().min(p);
self.max = self.max().max(p);
}
pub fn clamp(&self, p: Point<S, V>) -> Point<S, V> {
p.max(self.min).min(self.max)
}
pub fn contains(&self, p: &Point<S, V>) -> bool {
self.clamp(*p) == *p
}
}
impl<S> BBox2d<S>
where
S: Integer,
{
#[deprecated = "Use `bb2d` instead."]
pub fn from_bounds(x_start: S, x_end: S, y_start: S, y_end: S) -> BBox2d<S> {
assert!(x_start <= x_end && y_start <= y_end);
let min = p2d(x_start, y_start);
let max = p2d(x_end - S::one(), y_end - S::one());
BBox { min, max }
}
pub fn x_start(&self) -> S {
self.min.x()
}
pub fn x_end(&self) -> S {
self.max.x() + S::one()
}
pub fn x_min(&self) -> S {
self.min.x()
}
pub fn x_max(&self) -> S {
self.max.x()
}
pub fn y_start(&self) -> S {
self.min.y()
}
pub fn y_end(&self) -> S {
self.max.y() + S::one()
}
pub fn y_min(&self) -> S {
self.min.y()
}
pub fn y_max(&self) -> S {
self.max.y()
}
pub fn x_len(&self) -> S {
self.max.x() - self.min.x() + S::one()
}
pub fn y_len(&self) -> S {
self.max.y() - self.min.y() + S::one()
}
pub fn area(&self) -> usize
where
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
self.volume()
}
pub fn x_range(&self) -> Range<S> {
self.x_start()..self.x_end()
}
pub fn y_range(&self) -> Range<S> {
self.y_start()..self.y_end()
}
pub fn iter(&self) -> Points<S, Vec2d<S>, Layout2d<S>>
where
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
Layout2d::new(*self).points()
}
#[cfg(feature = "random")]
pub fn random_point<R>(&self, rng: &mut R) -> Point2d<S>
where
R: Rng,
S: SampleUniform,
{
let x = rng.gen_range(self.x_range());
let y = rng.gen_range(self.y_range());
p2d(x, y)
}
}
impl<S> BBox3d<S>
where
S: Integer,
{
pub fn x_start(&self) -> S {
self.min.x()
}
pub fn x_end(&self) -> S {
self.max.x() + S::one()
}
pub fn x_min(&self) -> S {
self.min.x()
}
pub fn x_max(&self) -> S {
self.max.x()
}
pub fn y_start(&self) -> S {
self.min.y()
}
pub fn y_end(&self) -> S {
self.max.y() + S::one()
}
pub fn y_min(&self) -> S {
self.min.y()
}
pub fn y_max(&self) -> S {
self.max.y()
}
pub fn z_start(&self) -> S {
self.min.z()
}
pub fn z_end(&self) -> S {
self.max.z() + S::one()
}
pub fn z_min(&self) -> S {
self.min.z()
}
pub fn z_max(&self) -> S {
self.max.z()
}
pub fn x_len(&self) -> S {
self.max.x() - self.min.x() + S::one()
}
pub fn y_len(&self) -> S {
self.max.y() - self.min.y() + S::one()
}
pub fn z_len(&self) -> S {
self.max.z() - self.min.z() + S::one()
}
pub fn x_range(&self) -> Range<S> {
self.x_start()..self.x_end()
}
pub fn y_range(&self) -> Range<S> {
self.y_start()..self.y_end()
}
pub fn z_range(&self) -> Range<S> {
self.z_start()..self.z_end()
}
pub fn iter(&self) -> Points<S, Vec3d<S>, Layout3d<S>>
where
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
Layout3d::new(*self).points()
}
#[cfg(feature = "random")]
pub fn random_point<R>(&self, rng: &mut R) -> Point3d<S>
where
R: Rng,
S: SampleUniform,
{
let x = rng.gen_range(self.x_range());
let y = rng.gen_range(self.y_range());
let z = rng.gen_range(self.z_range());
p3d(x, y, z)
}
}
impl<S> BBox4d<S>
where
S: Integer,
{
pub fn x_start(&self) -> S {
self.min.x()
}
pub fn x_end(&self) -> S {
self.max.x() + S::one()
}
pub fn x_min(&self) -> S {
self.min.x()
}
pub fn x_max(&self) -> S {
self.max.x()
}
pub fn y_start(&self) -> S {
self.min.y()
}
pub fn y_end(&self) -> S {
self.max.y() + S::one()
}
pub fn y_min(&self) -> S {
self.min.y()
}
pub fn y_max(&self) -> S {
self.max.y()
}
pub fn z_start(&self) -> S {
self.min.z()
}
pub fn z_end(&self) -> S {
self.max.z() + S::one()
}
pub fn z_min(&self) -> S {
self.min.z()
}
pub fn z_max(&self) -> S {
self.max.z()
}
pub fn w_start(&self) -> S {
self.min.w()
}
pub fn w_end(&self) -> S {
self.max.w() + S::one()
}
pub fn w_min(&self) -> S {
self.min.w()
}
pub fn w_max(&self) -> S {
self.max.w()
}
pub fn x_len(&self) -> S {
self.max.x() - self.min.x() + S::one()
}
pub fn y_len(&self) -> S {
self.max.y() - self.min.y() + S::one()
}
pub fn z_len(&self) -> S {
self.max.z() - self.min.z() + S::one()
}
pub fn w_len(&self) -> S {
self.max.w() - self.min.w() + S::one()
}
pub fn x_range(&self) -> Range<S> {
self.x_start()..self.x_end()
}
pub fn y_range(&self) -> Range<S> {
self.y_start()..self.y_end()
}
pub fn z_range(&self) -> Range<S> {
self.z_start()..self.z_end()
}
pub fn w_range(&self) -> Range<S> {
self.w_start()..self.w_end()
}
pub fn iter(&self) -> Points<S, Vec4d<S>, Layout4d<S>>
where
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
Layout4d::new(*self).points()
}
#[cfg(feature = "random")]
pub fn random_point<R>(&self, rng: &mut R) -> Point4d<S>
where
R: Rng,
S: SampleUniform,
{
let x = rng.gen_range(self.x_range());
let y = rng.gen_range(self.y_range());
let z = rng.gen_range(self.z_range());
let w = rng.gen_range(self.w_range());
p4d(x, y, z, w)
}
}
fn to_range_inclusive<S, R>(r: R) -> RangeInclusive<S>
where
S: Integer,
R: RangeBounds<S>,
{
let start = match r.start_bound() {
Bound::Included(s) => *s,
Bound::Excluded(s) => *s + S::one(),
Bound::Unbounded => panic!("unbounded ranges are not allowed"),
};
let end = match r.end_bound() {
Bound::Included(s) => *s,
Bound::Excluded(s) => *s - S::one(),
Bound::Unbounded => panic!("unbounded ranges are not allowed"),
};
assert!(start <= end);
start..=end
}
pub fn bb2d<S, RX, RY>(rx: RX, ry: RY) -> BBox2d<S>
where
S: Integer,
RX: RangeBounds<S>,
RY: RangeBounds<S>,
{
let rx = to_range_inclusive(rx);
let ry = to_range_inclusive(ry);
let min = p2d(*rx.start(), *ry.start());
let max = p2d(*rx.end(), *ry.end());
BBox { min, max }
}
pub fn bb3d<S, RX, RY, RZ>(rx: RX, ry: RY, rz: RZ) -> BBox3d<S>
where
S: Integer,
RX: RangeBounds<S>,
RY: RangeBounds<S>,
RZ: RangeBounds<S>,
{
let rx = to_range_inclusive(rx);
let ry = to_range_inclusive(ry);
let rz = to_range_inclusive(rz);
let min = p3d(*rx.start(), *ry.start(), *rz.start());
let max = p3d(*rx.end(), *ry.end(), *rz.end());
BBox { min, max }
}
pub fn bb4d<S, RX, RY, RZ, RW>(rx: RX, ry: RY, rz: RZ, rw: RW) -> BBox4d<S>
where
S: Integer,
RX: RangeBounds<S>,
RY: RangeBounds<S>,
RZ: RangeBounds<S>,
RW: RangeBounds<S>,
{
let rx = to_range_inclusive(rx);
let ry = to_range_inclusive(ry);
let rz = to_range_inclusive(rz);
let rw = to_range_inclusive(rw);
let min = p4d(*rx.start(), *ry.start(), *rz.start(), *rw.start());
let max = p4d(*rx.end(), *ry.end(), *rz.end(), *rw.end());
BBox { min, max }
}
impl<S, V> From<Point<S, V>> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
fn from(p: Point<S, V>) -> BBox<S, V> {
BBox { min: p, max: p }
}
}
impl<S> IntoIterator for BBox<S, Vec2d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point2d<S>;
type IntoIter = Points<S, Vec2d<S>, Layout2d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout2d::new(self).into_points()
}
}
impl<'a, S> IntoIterator for &'a BBox<S, Vec2d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point2d<S>;
type IntoIter = Points<S, Vec2d<S>, Layout2d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout2d::new(*self).into_points()
}
}
impl<S> IntoIterator for BBox<S, Vec3d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point3d<S>;
type IntoIter = Points<S, Vec3d<S>, Layout3d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout3d::new(self).into_points()
}
}
impl<'a, S> IntoIterator for &'a BBox<S, Vec3d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point3d<S>;
type IntoIter = Points<S, Vec3d<S>, Layout3d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout3d::new(*self).into_points()
}
}
impl<S> IntoIterator for BBox<S, Vec4d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point4d<S>;
type IntoIter = Points<S, Vec4d<S>, Layout4d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout4d::new(self).into_points()
}
}
impl<'a, S> IntoIterator for &'a BBox<S, Vec4d<S>>
where
S: Integer,
usize: TryFrom<S>,
<usize as TryFrom<S>>::Error: fmt::Debug,
{
type Item = Point4d<S>;
type IntoIter = Points<S, Vec4d<S>, Layout4d<S>>;
fn into_iter(self) -> Self::IntoIter {
Layout4d::new(*self).into_points()
}
}
impl<S, V> Add<V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn add(self, v: V) -> BBox<S, V> {
BBox::new(self.min() + v, self.lengths())
}
}
impl<'a, S, V> Add<&'a V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn add(self, v: &'a V) -> BBox<S, V> {
BBox::new(self.min() + v, self.lengths())
}
}
impl<'a, S, V> Add<V> for &'a BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn add(self, v: V) -> BBox<S, V> {
BBox::new(self.min() + v, self.lengths())
}
}
impl<'a, S, V> Add<&'a V> for &'a BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn add(self, v: &'a V) -> BBox<S, V> {
BBox::new(self.min() + v, self.lengths())
}
}
impl<S, V> Sub<V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn sub(self, v: V) -> BBox<S, V> {
BBox::new(self.min() - v, self.lengths())
}
}
impl<'a, S, V> Sub<&'a V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn sub(self, v: &'a V) -> BBox<S, V> {
BBox::new(self.min() - v, self.lengths())
}
}
impl<'a, S, V> Sub<V> for &'a BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn sub(self, v: V) -> BBox<S, V> {
BBox::new(self.min() - v, self.lengths())
}
}
impl<'a, S, V> Sub<&'a V> for &'a BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
type Output = BBox<S, V>;
fn sub(self, v: &'a V) -> BBox<S, V> {
BBox::new(self.min() - v, self.lengths())
}
}
impl<S, V> AddAssign<V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
fn add_assign(&mut self, other: V) {
self.min += other;
self.max += other;
}
}
impl<'a, S, V> AddAssign<&'a V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
fn add_assign(&mut self, other: &'a V) {
self.min += other;
self.max += other;
}
}
impl<S, V> SubAssign<V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
fn sub_assign(&mut self, other: V) {
self.min -= other;
self.max -= other;
}
}
impl<'a, S, V> SubAssign<&'a V> for BBox<S, V>
where
S: Integer,
V: Vector<S>,
{
fn sub_assign(&mut self, other: &'a V) {
self.min -= other;
self.max -= other;
}
}
#[cfg(test)]
mod tests {
use core::ops::Bound::Excluded;
use crate::bb2d;
use crate::bb3d;
use crate::bb4d;
use crate::p2d;
use crate::p3d;
use crate::p4d;
use crate::v2d;
use crate::v3d;
use crate::v4d;
use crate::BBox2d;
#[cfg(feature = "random")]
use rand::rngs::StdRng;
#[cfg(feature = "random")]
use rand::SeedableRng;
#[test]
fn test_new() {
let bb = BBox2d::new(p2d(-2, 3), v2d(1, 2));
assert_eq!(bb2d(-2..-1, 3..5), bb);
}
#[test]
#[allow(deprecated)]
fn test_from_point() {
let bb = BBox2d::from_point(p2d(-2, 3));
assert_eq!(bb2d(-2..=-2, 3..=3), bb);
}
#[test]
#[allow(deprecated)]
fn test_from_points() {
let bb = BBox2d::from_points(p2d(-2, 3), p2d(4, 7));
assert_eq!(bb2d(-2..=4, 3..=7), bb);
}
#[test]
fn test_from_corners() {
let bb = BBox2d::from_corners(p2d(-2, 3), p2d(4, 7));
assert_eq!(bb2d(-2..=4, 3..=7), bb);
}
#[test]
fn test_enclosing() {
let bb = BBox2d::enclosing(&vec![p2d(-2, 3), p2d(4, 7)]);
assert_eq!(Some(bb2d(-2..=4, 3..=7)), bb);
}
#[test]
fn test_enclosing_empty() {
let bb = <BBox2d<i64>>::enclosing(&vec![]);
assert_eq!(None, bb);
}
#[test]
fn test_min_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(p2d(-2, -1), bb.min());
}
#[test]
fn test_min_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(p3d(-2, -1, 1), bb.min());
}
#[test]
fn test_min_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(p4d(-2, -1, 1, -5), bb.min());
}
#[test]
fn test_max_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(p2d(2, 1), bb.max());
}
#[test]
fn test_max_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(p3d(2, 1, 3), bb.max());
}
#[test]
fn test_max_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(p4d(2, 1, 3, -3), bb.max());
}
#[test]
fn test_lengths_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(v2d(5, 3), bb.lengths());
}
#[test]
fn test_lengths_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(v3d(5, 3, 3), bb.lengths());
}
#[test]
fn test_lengths_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(v4d(5, 3, 3, 3), bb.lengths());
}
#[test]
fn test_volume_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(15, bb.volume());
}
#[test]
fn test_volume_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(45, bb.volume());
}
#[test]
fn test_volume_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(135, bb.volume());
}
#[test]
fn test_lub() {
let bb0 = bb2d(-2..3, -1..2);
let bb1 = bb2d(-5..4, 2..5);
assert_eq!(bb2d(-5..4, -1..5), bb0.lub(&bb1));
}
#[test]
fn test_intersection_nonempty() {
let bb0 = bb2d(-2..=3, -1..=2);
let bb1 = bb2d(-5..=4, 0..=5);
assert_eq!(Some(bb2d(-2..=3, 0..=2)), bb0.intersection(&bb1));
}
#[test]
fn test_intersection_empty() {
let bb0 = bb2d(-2..3, -1..2);
let bb1 = bb2d(-5..4, 2..5);
assert_eq!(None, bb0.intersection(&bb1));
}
#[test]
fn test_extend_to() {
let mut bb = bb2d(-2..3, -1..2);
let p = p2d(3, 4);
bb.extend_to(p);
assert_eq!(bb2d(-2..4, -1..5), bb);
}
#[test]
fn test_extended_to() {
let bb = bb2d(-2..3, -1..2);
let p = p2d(3, 4);
assert_eq!(bb2d(-2..4, -1..5), bb.extended_to(p));
}
#[test]
fn test_x_start_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(-2, bb.x_start());
}
#[test]
fn test_x_start_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(-2, bb.x_start());
}
#[test]
fn test_x_start_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-2, bb.x_start());
}
#[test]
fn test_x_end_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(3, bb.x_end());
}
#[test]
fn test_x_end_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(3, bb.x_end());
}
#[test]
fn test_x_end_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(3, bb.x_end());
}
#[test]
fn test_x_min_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(-2, bb.x_min());
}
#[test]
fn test_x_min_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(-2, bb.x_min());
}
#[test]
fn test_x_min_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(-2, bb.x_min());
}
#[test]
fn test_x_max_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(2, bb.x_max());
}
#[test]
fn test_x_max_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(2, bb.x_max());
}
#[test]
fn test_x_max_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(2, bb.x_max());
}
#[test]
fn test_y_start_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(-1, bb.y_start());
}
#[test]
fn test_y_start_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(-1, bb.y_start());
}
#[test]
fn test_y_start_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-1, bb.y_start());
}
#[test]
fn test_y_end_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(2, bb.y_end());
}
#[test]
fn test_y_end_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(2, bb.y_end());
}
#[test]
fn test_y_end_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(2, bb.y_end());
}
#[test]
fn test_y_min_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(-1, bb.y_min());
}
#[test]
fn test_y_min_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(-1, bb.y_min());
}
#[test]
fn test_y_min_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(-1, bb.y_min());
}
#[test]
fn test_y_max_2d() {
let bb = bb2d(-2..=2, -1..=1);
assert_eq!(1, bb.y_max());
}
#[test]
fn test_y_max_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(1, bb.y_max());
}
#[test]
fn test_y_max_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(1, bb.y_max());
}
#[test]
fn test_z_start_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(1, bb.z_start());
}
#[test]
fn test_z_start_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(1, bb.z_start());
}
#[test]
fn test_z_end_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(4, bb.z_end());
}
#[test]
fn test_z_end_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(4, bb.z_end());
}
#[test]
fn test_z_min_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(1, bb.z_min());
}
#[test]
fn test_z_min_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(1, bb.z_min());
}
#[test]
fn test_z_max_3d() {
let bb = bb3d(-2..=2, -1..=1, 1..=3);
assert_eq!(3, bb.z_max());
}
#[test]
fn test_z_max_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(3, bb.z_max());
}
#[test]
fn test_w_start_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-5, bb.w_start());
}
#[test]
fn test_w_end_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-2, bb.w_end());
}
#[test]
fn test_w_min_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(-5, bb.w_min());
}
#[test]
fn test_w_max_4d() {
let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
assert_eq!(-3, bb.w_max());
}
#[test]
fn test_x_len_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(5, bb.x_len());
}
#[test]
fn test_x_len_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(5, bb.x_len());
}
#[test]
fn test_x_len_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(5, bb.x_len());
}
#[test]
fn test_y_len_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(3, bb.y_len());
}
#[test]
fn test_y_len_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(3, bb.y_len());
}
#[test]
fn test_y_len_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(3, bb.y_len());
}
#[test]
fn test_z_len_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(3, bb.z_len());
}
#[test]
fn test_z_len_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(3, bb.z_len());
}
#[test]
fn test_w_len_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(3, bb.w_len());
}
#[test]
fn test_area() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(15, bb.area());
}
#[test]
fn test_contains() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(bb.contains(&p2d(0, 0)), true);
assert_eq!(bb.contains(&p2d(-2, 0)), true);
assert_eq!(bb.contains(&p2d(-3, 0)), false);
assert_eq!(bb.contains(&p2d(2, 0)), true);
assert_eq!(bb.contains(&p2d(3, 0)), false);
assert_eq!(bb.contains(&p2d(0, -1)), true);
assert_eq!(bb.contains(&p2d(0, -2)), false);
assert_eq!(bb.contains(&p2d(0, 1)), true);
assert_eq!(bb.contains(&p2d(0, 2)), false);
}
#[test]
fn test_x_range_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(-2..3, bb.x_range());
}
#[test]
fn test_x_range_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(-2..3, bb.x_range());
}
#[test]
fn test_x_range_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-2..3, bb.x_range());
}
#[test]
fn test_y_range_2d() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(-1..2, bb.y_range());
}
#[test]
fn test_y_range_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(-1..2, bb.y_range());
}
#[test]
fn test_y_range_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-1..2, bb.y_range());
}
#[test]
fn test_z_range_3d() {
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(1..4, bb.z_range());
}
#[test]
fn test_z_range_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(1..4, bb.z_range());
}
#[test]
fn test_w_range_4d() {
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(-5..-2, bb.w_range());
}
#[test]
fn test_center() {
let bb = bb2d(-2..3, -1..2);
assert_eq!(p2d(0, 0), bb.center());
}
#[cfg(feature = "random")]
#[test]
fn test_random_point_2d() {
let mut rng = StdRng::seed_from_u64(42);
let bb = bb2d(-2..3, -1..2);
assert_eq!(p2d(-1, 0), bb.random_point(&mut rng));
}
#[cfg(feature = "random")]
#[test]
fn test_random_point_3d() {
let mut rng = StdRng::seed_from_u64(42);
let bb = bb3d(-2..3, -1..2, 1..4);
assert_eq!(p3d(-1, 0, 3), bb.random_point(&mut rng));
}
#[cfg(feature = "random")]
#[test]
fn test_random_point_4d() {
let mut rng = StdRng::seed_from_u64(42);
let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
assert_eq!(p4d(-1, 0, 3, -4), bb.random_point(&mut rng));
}
#[test]
fn test_bb2d_incl() {
let bb = bb2d(0..=2, 1..=4);
assert_eq!(bb2d(0..3, 1..5), bb)
}
#[test]
fn test_bb2d_excl() {
let bb = bb2d((Excluded(-1), Excluded(3)), (Excluded(0), Excluded(5)));
assert_eq!(bb2d(0..3, 1..5), bb)
}
#[test]
fn test_bb3d_incl() {
let bb = bb3d(0..=2, 1..=4, 2..=6);
assert_eq!(bb3d(0..3, 1..5, 2..7), bb)
}
#[test]
fn test_bb3d_excl() {
let bb = bb3d(
(Excluded(-1), Excluded(3)),
(Excluded(0), Excluded(5)),
(Excluded(1), Excluded(7)),
);
assert_eq!(bb3d(0..3, 1..5, 2..7), bb)
}
#[test]
fn test_bb4d_incl() {
let bb = bb4d(0..=2, 1..=4, 2..=6, 3..=8);
assert_eq!(bb4d(0..3, 1..5, 2..7, 3..9), bb)
}
#[test]
fn test_bb4d_excl() {
let bb = bb4d(
(Excluded(-1), Excluded(3)),
(Excluded(0), Excluded(5)),
(Excluded(1), Excluded(7)),
(Excluded(2), Excluded(9)),
);
assert_eq!(bb4d(0..3, 1..5, 2..7, 3..9), bb)
}
#[test]
fn test_from() {
let bb = BBox2d::from(p2d(-2, 3));
assert_eq!(bb2d(-2..=-2, 3..=3), bb);
}
#[test]
fn test_iter_2d() {
let bb = bb2d(1..=2, -1..=0);
let v = bb.iter().collect::<Vec<_>>();
assert_eq!(vec![p2d(1, -1), p2d(2, -1), p2d(1, 0), p2d(2, 0)], v);
}
#[test]
fn test_iter_3d() {
let bb = bb3d(1..=2, -1..=0, -2..=-1);
let v = bb.iter().collect::<Vec<_>>();
assert_eq!(
vec![
p3d(1, -1, -2),
p3d(2, -1, -2),
p3d(1, 0, -2),
p3d(2, 0, -2),
p3d(1, -1, -1),
p3d(2, -1, -1),
p3d(1, 0, -1),
p3d(2, 0, -1),
],
v
);
}
#[test]
fn test_iter_4d() {
let bb = bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
let v = bb.iter().collect::<Vec<_>>();
assert_eq!(
vec![
p4d(1, -1, -2, 3),
p4d(2, -1, -2, 3),
p4d(1, 0, -2, 3),
p4d(2, 0, -2, 3),
p4d(1, -1, -1, 3),
p4d(2, -1, -1, 3),
p4d(1, 0, -1, 3),
p4d(2, 0, -1, 3),
p4d(1, -1, -2, 4),
p4d(2, -1, -2, 4),
p4d(1, 0, -2, 4),
p4d(2, 0, -2, 4),
p4d(1, -1, -1, 4),
p4d(2, -1, -1, 4),
p4d(1, 0, -1, 4),
p4d(2, 0, -1, 4),
],
v
);
}
#[test]
fn test_exact_size_iterator_2d_owned() {
let bb = bb2d(1..=2, -1..=0);
let mut it = bb.into_iter();
assert_eq!((4, Some(4)), it.size_hint());
assert_eq!(4, it.len());
let p = it.next();
assert_eq!(Some(p2d(1, -1)), p);
assert_eq!((3, Some(3)), it.size_hint());
assert_eq!(3, it.len());
}
#[test]
fn test_exact_size_iterator_2d_ref() {
let bb = &bb2d(1..=2, -1..=0);
let mut it = bb.into_iter();
assert_eq!((4, Some(4)), it.size_hint());
assert_eq!(4, it.len());
let p = it.next();
assert_eq!(Some(p2d(1, -1)), p);
assert_eq!((3, Some(3)), it.size_hint());
assert_eq!(3, it.len());
}
#[test]
fn test_exact_size_iterator_3d_owned() {
let bb = bb3d(1..=2, -1..=0, -2..=-1);
let mut it = bb.into_iter();
assert_eq!((8, Some(8)), it.size_hint());
assert_eq!(8, it.len());
let p = it.next();
assert_eq!(Some(p3d(1, -1, -2)), p);
assert_eq!((7, Some(7)), it.size_hint());
assert_eq!(7, it.len());
}
#[test]
fn test_exact_size_iterator_3d_ref() {
let bb = &bb3d(1..=2, -1..=0, -2..=-1);
let mut it = bb.into_iter();
assert_eq!((8, Some(8)), it.size_hint());
assert_eq!(8, it.len());
let p = it.next();
assert_eq!(Some(p3d(1, -1, -2)), p);
assert_eq!((7, Some(7)), it.size_hint());
assert_eq!(7, it.len());
}
#[test]
fn test_exact_size_iterator_4d_owned() {
let bb = bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
let mut it = bb.into_iter();
assert_eq!((16, Some(16)), it.size_hint());
assert_eq!(16, it.len());
let p = it.next();
assert_eq!(Some(p4d(1, -1, -2, 3)), p);
assert_eq!((15, Some(15)), it.size_hint());
assert_eq!(15, it.len());
}
#[test]
fn test_exact_size_iterator_4d_ref() {
let bb = &bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
let mut it = bb.into_iter();
assert_eq!((16, Some(16)), it.size_hint());
assert_eq!(16, it.len());
let p = it.next();
assert_eq!(Some(p4d(1, -1, -2, 3)), p);
assert_eq!((15, Some(15)), it.size_hint());
assert_eq!(15, it.len());
}
#[test]
fn test_add_2d() {
let bb = bb2d(-2..3, -1..2);
let v = v2d(3, 7);
assert_eq!(bb2d(1..6, 6..9), bb + v);
assert_eq!(bb2d(1..6, 6..9), bb + &v);
assert_eq!(bb2d(1..6, 6..9), &bb + v);
assert_eq!(bb2d(1..6, 6..9), &bb + &v);
}
#[test]
fn test_sub_2d() {
let bb = bb2d(-2..3, -1..2);
let v = v2d(-3, -7);
assert_eq!(bb2d(1..6, 6..9), bb - v);
assert_eq!(bb2d(1..6, 6..9), bb - &v);
assert_eq!(bb2d(1..6, 6..9), &bb - v);
assert_eq!(bb2d(1..6, 6..9), &bb - &v);
}
#[test]
fn test_add_assign_2d() {
let mut bb = bb2d(-2..3, -1..2);
let v = v2d(3, 7);
bb += v;
assert_eq!(bb2d(1..6, 6..9), bb);
bb += &v;
assert_eq!(bb2d(4..9, 13..16), bb);
}
#[test]
fn test_sub_assign_2d() {
let mut bb = bb2d(-2..3, -1..2);
let v = v2d(-3, -7);
bb -= v;
assert_eq!(bb2d(1..6, 6..9), bb);
bb -= &v;
assert_eq!(bb2d(4..9, 13..16), bb);
}
}