lowdim/
bbox.rs

1//! n-dimensional bounding boxes.
2
3use core::cmp::Ordering;
4use core::fmt;
5use core::ops::Add;
6use core::ops::AddAssign;
7use core::ops::Bound;
8use core::ops::Range;
9use core::ops::RangeBounds;
10use core::ops::RangeInclusive;
11use core::ops::Sub;
12use core::ops::SubAssign;
13
14#[cfg(feature = "random")]
15use rand::distributions::uniform::SampleUniform;
16#[cfg(feature = "random")]
17use rand::Rng;
18
19use crate::layout::Points;
20use crate::p2d;
21use crate::p3d;
22use crate::p4d;
23use crate::Integer;
24use crate::Layout;
25use crate::Layout2d;
26use crate::Layout3d;
27use crate::Layout4d;
28use crate::Point;
29use crate::Point2d;
30use crate::Point3d;
31use crate::Point4d;
32use crate::Vec2d;
33use crate::Vec3d;
34use crate::Vec4d;
35use crate::Vector;
36
37/// A bounding box.
38///
39/// An axis-aligned non-empty volume of the same dimension as the space.
40#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
41pub struct BBox<S: Integer, V: Vector<S>> {
42    /// The corner of the box with the lowest coordinates.
43    min: Point<S, V>,
44    /// The corner of the box with the highest coordinates.
45    max: Point<S, V>,
46}
47
48/// A 2d bounding box.
49pub type BBox2d<S = i64> = BBox<S, Vec2d<S>>;
50/// A 3d bounding box.
51pub type BBox3d<S = i64> = BBox<S, Vec3d<S>>;
52/// A 4d bounding box.
53pub type BBox4d<S = i64> = BBox<S, Vec4d<S>>;
54
55impl<S, V> BBox<S, V>
56where
57    S: Integer,
58    V: Vector<S>,
59{
60    /// Constructs a bounding box from origin and size.
61    ///
62    /// All coordinates of `size` must be positive to make the box non-empty.
63    pub fn new(origin: Point<S, V>, size: V) -> BBox<S, V> {
64        let min = origin;
65        let max = Point::with(|i| origin[i] + size[i] - S::one());
66        assert!(size.as_slice().iter().all(|&c| c > S::zero()));
67        BBox { min, max }
68    }
69    /// Constructs a bounding box which contains a single point.
70    ///
71    /// # Example
72    /// ```
73    /// # use lowdim::p2d;
74    /// # use lowdim::bb2d;
75    /// # use lowdim::BBox2d;
76    /// let p = p2d(2, 3);
77    /// assert_eq!(bb2d(2..3, 3..4), BBox2d::from_point(p));
78    /// ```
79    #[deprecated = "Use `from` instead."]
80    pub fn from_point(p: Point<S, V>) -> BBox<S, V> {
81        BBox { min: p, max: p }
82    }
83    /// Constructs the smallest bounding box containing two points.
84    #[deprecated = "Use `from_corners` instead."]
85    pub fn from_points(p0: Point<S, V>, p1: Point<S, V>) -> BBox<S, V> {
86        let min = p0.min(p1);
87        let max = p0.max(p1);
88        BBox { min, max }
89    }
90    /// Constructs the smallest bounding box containing two points.
91    ///
92    /// # Example
93    /// ```
94    /// # use lowdim::p2d;
95    /// # use lowdim::bb2d;
96    /// # use lowdim::BBox2d;
97    /// let p0 = p2d(2, 3);
98    /// let p1 = p2d(-1, 4);
99    /// assert_eq!(bb2d(-1..3, 3..5), BBox2d::from_corners(p0, p1));
100    /// ```
101    pub fn from_corners(p0: Point<S, V>, p1: Point<S, V>) -> BBox<S, V> {
102        let min = p0.min(p1);
103        let max = p0.max(p1);
104        BBox { min, max }
105    }
106    /// Constructs the minimal bounding box containing points from an iterator,
107    /// or `None` if the iterator is empty.
108    ///
109    /// # Example
110    /// ```
111    /// # use lowdim::p2d;
112    /// # use lowdim::bb2d;
113    /// # use lowdim::BBox2d;
114    /// let points = vec![p2d(2, 3), p2d(-1, 4), p2d(1, 0)];
115    /// assert_eq!(Some(bb2d(-1..=2, 0..=4)), BBox2d::enclosing(&points));
116    /// ```
117    pub fn enclosing<'a, II>(ii: II) -> Option<BBox<S, V>>
118    where
119        S: 'a,
120        V: 'a,
121        II: IntoIterator<Item = &'a Point<S, V>>,
122    {
123        let mut iter = ii.into_iter();
124        if let Some(p0) = iter.next() {
125            let mut bbox = BBox::from(*p0);
126            for p in iter {
127                bbox.extend_to(*p);
128            }
129            Some(bbox)
130        } else {
131            None
132        }
133    }
134    /// The minimal point in the bounding box.
135    ///
136    /// # Example
137    /// ```
138    /// # use lowdim::p2d;
139    /// # use lowdim::bb2d;
140    /// # use lowdim::BBox2d;
141    /// let b = bb2d(-1..3, 3..5);
142    /// assert_eq!(p2d(-1, 3), b.min());
143    /// ```
144    pub fn min(&self) -> Point<S, V> {
145        self.min
146    }
147    /// The maximal point in the bounding box.
148    ///
149    /// # Example
150    /// ```
151    /// # use lowdim::p2d;
152    /// # use lowdim::bb2d;
153    /// # use lowdim::BBox2d;
154    /// let b = bb2d(-1..3, 3..5);
155    /// assert_eq!(p2d(2, 4), b.max());
156    /// ```
157    pub fn max(&self) -> Point<S, V> {
158        self.max
159    }
160
161    /// Returns a vector of the lengths for the coordinates.
162    ///
163    /// # Example
164    /// ```
165    /// # use lowdim::v2d;
166    /// # use lowdim::bb2d;
167    /// # use lowdim::BBox2d;
168    /// let b = bb2d(-1..3, 3..5);
169    /// assert_eq!(v2d(4, 2), b.lengths());
170    /// ```
171    pub fn lengths(&self) -> V {
172        self.max - self.min + V::ones()
173    }
174
175    /// Returns the volume of the bounding box.
176    ///
177    /// # Example
178    /// ```
179    /// # use lowdim::p2d;
180    /// # use lowdim::bb2d;
181    /// # use lowdim::BBox2d;
182    /// let b = bb2d(-1..3, 3..5);
183    /// assert_eq!(8, b.volume());
184    /// ```
185    pub fn volume(&self) -> usize
186    where
187        usize: TryFrom<S>,
188        <usize as TryFrom<S>>::Error: fmt::Debug,
189    {
190        self.lengths()
191            .as_slice()
192            .iter()
193            .map(|&len| len.to_usize())
194            .product()
195    }
196
197    /// The center point in the bounding box.
198    ///
199    /// This is only the true center of the bounding box
200    /// if the bounding box has odd dimensions.
201    /// Otherwise the coordinates of the center are rounded down.
202    ///
203    /// # Example
204    /// ```
205    /// # use lowdim::p2d;
206    /// # use lowdim::bb2d;
207    /// # use lowdim::BBox2d;
208    /// let b = bb2d(-1..4, 3..6);
209    /// assert_eq!(p2d(1, 4), b.center());
210    /// ```
211    pub fn center(&self) -> Point<S, V> {
212        Point::<S, V>::from((self.min.to_vec() + self.max.to_vec()) / S::two())
213    }
214
215    /// The least upper bound of two bounding boxes w.r.t. inclusion.
216    ///
217    /// That is, the smallest bounding box encompassing the points in the two boxes.
218    ///
219    /// # Example
220    /// ```
221    /// # use lowdim::p2d;
222    /// # use lowdim::bb2d;
223    /// # use lowdim::BBox2d;
224    /// let bb0 = bb2d(-2..3, -1..2);
225    /// let bb1 = bb2d(-5..4, 2..5);
226    /// assert_eq!(bb2d(-5..4, -1..5), bb0.lub(&bb1));
227    /// ```
228    pub fn lub(&self, other: &BBox<S, V>) -> BBox<S, V> {
229        let min = self.min().min(other.min());
230        let max = self.max().max(other.max());
231        BBox { min, max }
232    }
233
234    /// The intersection of two bounding boxes, or `None` if they don't intersect.
235    ///
236    /// # Example
237    /// ```
238    /// # use lowdim::p2d;
239    /// # use lowdim::bb2d;
240    /// # use lowdim::BBox2d;
241    /// let bb0 = bb2d(-2..=3, -1..=2);
242    /// let bb1 = bb2d(-5..=4, 0..=5);
243    /// assert_eq!(Some(bb2d(-2..=3, 0..=2)), bb0.intersection(&bb1));
244    /// ```
245    pub fn intersection(&self, other: &BBox<S, V>) -> Option<BBox<S, V>> {
246        let min = self.min().max(other.min());
247        let max = self.max().min(other.max());
248        match min.componentwise_cmp(&max) {
249            Some(Ordering::Less) | Some(Ordering::Equal) => Some(BBox { min, max }),
250            _ => None,
251        }
252    }
253
254    /// Returns the smallest bounding box encompassing this box and a given point.
255    ///
256    /// # Example
257    /// ```
258    /// # use lowdim::p2d;
259    /// # use lowdim::bb2d;
260    /// # use lowdim::BBox2d;
261    /// let bb = bb2d(-2..3, -1..2);
262    /// let p = p2d(3, 4);
263    /// assert_eq!(bb2d(-2..4, -1..5), bb.extended_to(p));
264    /// ```
265    pub fn extended_to(&self, p: Point<S, V>) -> BBox<S, V> {
266        let min = self.min().min(p);
267        let max = self.max().max(p);
268        BBox { min, max }
269    }
270
271    /// Extends this box to encompass a given point.
272    ///
273    /// # Example
274    /// ```
275    /// # use lowdim::p2d;
276    /// # use lowdim::bb2d;
277    /// # use lowdim::BBox2d;
278    /// let mut bb = bb2d(-2..3, -1..2);
279    /// let p = p2d(3, 4);
280    /// bb.extend_to(p);
281    /// assert_eq!(bb2d(-2..4, -1..5), bb);
282    /// ```
283    pub fn extend_to(&mut self, p: Point<S, V>) {
284        self.min = self.min().min(p);
285        self.max = self.max().max(p);
286    }
287
288    /// Returns the closest point inside the bounding box for a given point.
289    ///
290    /// If the point is inside the bounding box it is returned unchanged.
291    /// Otherwise the coordinates that fall outside the ranges of the box
292    /// are clamped to the closest endpoints of the ranges.
293    ///
294    /// # Example
295    /// ```
296    /// # use lowdim::p2d;
297    /// # use lowdim::bb2d;
298    /// # use lowdim::BBox2d;
299    /// let b = bb2d(-1..4, 3..6);
300    /// assert_eq!(p2d(3, 4), b.clamp(p2d(10, 4)));
301    /// ```
302    pub fn clamp(&self, p: Point<S, V>) -> Point<S, V> {
303        p.max(self.min).min(self.max)
304    }
305
306    /// Returns true if the point is inside the bounding box.
307    ///
308    /// # Example
309    /// ```
310    /// # use lowdim::p2d;
311    /// # use lowdim::bb2d;
312    /// # use lowdim::BBox2d;
313    /// let b = bb2d(-1..4, 3..6);
314    /// assert!(b.contains(&p2d(0, 4)));
315    /// assert!(!b.contains(&p2d(10, 4)));
316    /// ```
317    pub fn contains(&self, p: &Point<S, V>) -> bool {
318        self.clamp(*p) == *p
319    }
320}
321
322impl<S> BBox2d<S>
323where
324    S: Integer,
325{
326    /// Constructs a bounding box from bounds.
327    ///
328    /// As always, lower bbox are inclusive, upper bbox exclusive.
329    #[deprecated = "Use `bb2d` instead."]
330    pub fn from_bounds(x_start: S, x_end: S, y_start: S, y_end: S) -> BBox2d<S> {
331        assert!(x_start <= x_end && y_start <= y_end);
332        let min = p2d(x_start, y_start);
333        let max = p2d(x_end - S::one(), y_end - S::one());
334        BBox { min, max }
335    }
336
337    /// Returns the lower bound in the x-coordinate (inclusive).
338    pub fn x_start(&self) -> S {
339        self.min.x()
340    }
341    /// Returns the upper bound in the x-coordinate (exclusive).
342    pub fn x_end(&self) -> S {
343        self.max.x() + S::one()
344    }
345    /// Returns the lower bound in the x-coordinate (inclusive).
346    pub fn x_min(&self) -> S {
347        self.min.x()
348    }
349    /// Returns the upper bound in the x-coordinate (inclusive).
350    pub fn x_max(&self) -> S {
351        self.max.x()
352    }
353
354    /// Returns the lower bound in the y-coordinate (inclusive).
355    pub fn y_start(&self) -> S {
356        self.min.y()
357    }
358    /// Returns the upper bound in the y-coordinate (exclusive).
359    pub fn y_end(&self) -> S {
360        self.max.y() + S::one()
361    }
362    /// Returns the lower bound in the y-coordinate (inclusive).
363    pub fn y_min(&self) -> S {
364        self.min.y()
365    }
366    /// Returns the upper bound in the y-coordinate (inclusive).
367    pub fn y_max(&self) -> S {
368        self.max.y()
369    }
370
371    /// Returns the width of the bounding box.
372    pub fn x_len(&self) -> S {
373        self.max.x() - self.min.x() + S::one()
374    }
375
376    /// Returns the height of the bounding box.
377    pub fn y_len(&self) -> S {
378        self.max.y() - self.min.y() + S::one()
379    }
380
381    /// Returns the area of the bounding box.
382    pub fn area(&self) -> usize
383    where
384        usize: TryFrom<S>,
385        <usize as TryFrom<S>>::Error: fmt::Debug,
386    {
387        self.volume()
388    }
389
390    /// The range of the x coordinate
391    pub fn x_range(&self) -> Range<S> {
392        self.x_start()..self.x_end()
393    }
394    /// The range of the y coordinate
395    pub fn y_range(&self) -> Range<S> {
396        self.y_start()..self.y_end()
397    }
398
399    /// Returns an iterator over the points in the bounding box.
400    ///
401    /// Points are returned by row.
402    pub fn iter(&self) -> Points<S, Vec2d<S>, Layout2d<S>>
403    where
404        usize: TryFrom<S>,
405        <usize as TryFrom<S>>::Error: fmt::Debug,
406    {
407        Layout2d::new(*self).points()
408    }
409
410    /// Returns a random point inside the bounding box.
411    ///
412    /// Uses a uniform distribution.
413    #[cfg(feature = "random")]
414    pub fn random_point<R>(&self, rng: &mut R) -> Point2d<S>
415    where
416        R: Rng,
417        S: SampleUniform,
418    {
419        let x = rng.gen_range(self.x_range());
420        let y = rng.gen_range(self.y_range());
421        p2d(x, y)
422    }
423}
424
425impl<S> BBox3d<S>
426where
427    S: Integer,
428{
429    /// Returns the lower bound in the x-coordinate (inclusive).
430    pub fn x_start(&self) -> S {
431        self.min.x()
432    }
433    /// Returns the upper bound in the x-coordinate (exclusive).
434    pub fn x_end(&self) -> S {
435        self.max.x() + S::one()
436    }
437    /// Returns the lower bound in the x-coordinate (inclusive).
438    pub fn x_min(&self) -> S {
439        self.min.x()
440    }
441    /// Returns the upper bound in the x-coordinate (inclusive).
442    pub fn x_max(&self) -> S {
443        self.max.x()
444    }
445
446    /// Returns the lower bound in the y-coordinate (inclusive).
447    pub fn y_start(&self) -> S {
448        self.min.y()
449    }
450    /// Returns the upper bound in the y-coordinate (exclusive).
451    pub fn y_end(&self) -> S {
452        self.max.y() + S::one()
453    }
454    /// Returns the lower bound in the y-coordinate (inclusive).
455    pub fn y_min(&self) -> S {
456        self.min.y()
457    }
458    /// Returns the upper bound in the y-coordinate (inclusive).
459    pub fn y_max(&self) -> S {
460        self.max.y()
461    }
462
463    /// Returns the lower bound in the z-coordinate (inclusive).
464    pub fn z_start(&self) -> S {
465        self.min.z()
466    }
467    /// Returns the upper bound in the z-coordinate (exclusive).
468    pub fn z_end(&self) -> S {
469        self.max.z() + S::one()
470    }
471    /// Returns the lower bound in the z-coordinate (inclusive).
472    pub fn z_min(&self) -> S {
473        self.min.z()
474    }
475    /// Returns the upper bound in the z-coordinate (inclusive).
476    pub fn z_max(&self) -> S {
477        self.max.z()
478    }
479
480    /// Returns the size of the x-dimension of the bounding box.
481    pub fn x_len(&self) -> S {
482        self.max.x() - self.min.x() + S::one()
483    }
484    /// Returns the size of the y-dimension of the bounding box.
485    pub fn y_len(&self) -> S {
486        self.max.y() - self.min.y() + S::one()
487    }
488    /// Returns the size of the z-dimension of the bounding box.
489    pub fn z_len(&self) -> S {
490        self.max.z() - self.min.z() + S::one()
491    }
492
493    /// Returns the range of the x coordinate.
494    pub fn x_range(&self) -> Range<S> {
495        self.x_start()..self.x_end()
496    }
497    /// Returns the range of the y coordinate.
498    pub fn y_range(&self) -> Range<S> {
499        self.y_start()..self.y_end()
500    }
501    /// Returns the range of the z coordinate.
502    pub fn z_range(&self) -> Range<S> {
503        self.z_start()..self.z_end()
504    }
505
506    /// Returns an iterator over the points in the bounding box.
507    ///
508    /// Points are returned by row.
509    pub fn iter(&self) -> Points<S, Vec3d<S>, Layout3d<S>>
510    where
511        usize: TryFrom<S>,
512        <usize as TryFrom<S>>::Error: fmt::Debug,
513    {
514        Layout3d::new(*self).points()
515    }
516
517    /// Returns a random point inside the bounding box.
518    ///
519    /// Uses a uniform distribution.
520    #[cfg(feature = "random")]
521    pub fn random_point<R>(&self, rng: &mut R) -> Point3d<S>
522    where
523        R: Rng,
524        S: SampleUniform,
525    {
526        let x = rng.gen_range(self.x_range());
527        let y = rng.gen_range(self.y_range());
528        let z = rng.gen_range(self.z_range());
529        p3d(x, y, z)
530    }
531}
532
533impl<S> BBox4d<S>
534where
535    S: Integer,
536{
537    /// Returns the lower bound in the x-coordinate (inclusive).
538    pub fn x_start(&self) -> S {
539        self.min.x()
540    }
541    /// Returns the upper bound in the x-coordinate (exclusive).
542    pub fn x_end(&self) -> S {
543        self.max.x() + S::one()
544    }
545    /// Returns the lower bound in the x-coordinate (inclusive).
546    pub fn x_min(&self) -> S {
547        self.min.x()
548    }
549    /// Returns the upper bound in the x-coordinate (inclusive).
550    pub fn x_max(&self) -> S {
551        self.max.x()
552    }
553
554    /// Returns the lower bound in the y-coordinate (inclusive).
555    pub fn y_start(&self) -> S {
556        self.min.y()
557    }
558    /// Returns the upper bound in the y-coordinate (exclusive).
559    pub fn y_end(&self) -> S {
560        self.max.y() + S::one()
561    }
562    /// Returns the lower bound in the y-coordinate (inclusive).
563    pub fn y_min(&self) -> S {
564        self.min.y()
565    }
566    /// Returns the upper bound in the y-coordinate (inclusive).
567    pub fn y_max(&self) -> S {
568        self.max.y()
569    }
570
571    /// Returns the lower bound in the z-coordinate (inclusive).
572    pub fn z_start(&self) -> S {
573        self.min.z()
574    }
575    /// Returns the upper bound in the z-coordinate (exclusive).
576    pub fn z_end(&self) -> S {
577        self.max.z() + S::one()
578    }
579    /// Returns the lower bound in the z-coordinate (inclusive).
580    pub fn z_min(&self) -> S {
581        self.min.z()
582    }
583    /// Returns the upper bound in the z-coordinate (inclusive).
584    pub fn z_max(&self) -> S {
585        self.max.z()
586    }
587
588    /// Returns the lower bound in the w-coordinate (inclusive).
589    pub fn w_start(&self) -> S {
590        self.min.w()
591    }
592    /// Returns the upper bound in the w-coordinate (exclusive).
593    pub fn w_end(&self) -> S {
594        self.max.w() + S::one()
595    }
596    /// Returns the lower bound in the w-coordinate (inclusive).
597    pub fn w_min(&self) -> S {
598        self.min.w()
599    }
600    /// Returns the upper bound in the w-coordinate (inclusive).
601    pub fn w_max(&self) -> S {
602        self.max.w()
603    }
604
605    /// Returns the size of the x-dimension of the bounding box.
606    pub fn x_len(&self) -> S {
607        self.max.x() - self.min.x() + S::one()
608    }
609    /// Returns the size of the y-dimension of the bounding box.
610    pub fn y_len(&self) -> S {
611        self.max.y() - self.min.y() + S::one()
612    }
613    /// Returns the size of the z-dimension of the bounding box.
614    pub fn z_len(&self) -> S {
615        self.max.z() - self.min.z() + S::one()
616    }
617    /// Returns the size of the w-dimension of the bounding box.
618    pub fn w_len(&self) -> S {
619        self.max.w() - self.min.w() + S::one()
620    }
621
622    /// Returns the range of the x coordinate.
623    pub fn x_range(&self) -> Range<S> {
624        self.x_start()..self.x_end()
625    }
626    /// Returns the range of the y coordinate.
627    pub fn y_range(&self) -> Range<S> {
628        self.y_start()..self.y_end()
629    }
630    /// Returns the range of the z coordinate.
631    pub fn z_range(&self) -> Range<S> {
632        self.z_start()..self.z_end()
633    }
634    /// Returns the range of the w coordinate.
635    pub fn w_range(&self) -> Range<S> {
636        self.w_start()..self.w_end()
637    }
638
639    /// Returns an iterator over the points in the bounding box.
640    ///
641    /// Points are returned by row.
642    pub fn iter(&self) -> Points<S, Vec4d<S>, Layout4d<S>>
643    where
644        usize: TryFrom<S>,
645        <usize as TryFrom<S>>::Error: fmt::Debug,
646    {
647        Layout4d::new(*self).points()
648    }
649
650    /// Returns a random point inside the bounding box.
651    ///
652    /// Uses a uniform distribution.
653    #[cfg(feature = "random")]
654    pub fn random_point<R>(&self, rng: &mut R) -> Point4d<S>
655    where
656        R: Rng,
657        S: SampleUniform,
658    {
659        let x = rng.gen_range(self.x_range());
660        let y = rng.gen_range(self.y_range());
661        let z = rng.gen_range(self.z_range());
662        let w = rng.gen_range(self.w_range());
663        p4d(x, y, z, w)
664    }
665}
666
667fn to_range_inclusive<S, R>(r: R) -> RangeInclusive<S>
668where
669    S: Integer,
670    R: RangeBounds<S>,
671{
672    let start = match r.start_bound() {
673        Bound::Included(s) => *s,
674        Bound::Excluded(s) => *s + S::one(),
675        Bound::Unbounded => panic!("unbounded ranges are not allowed"),
676    };
677    let end = match r.end_bound() {
678        Bound::Included(s) => *s,
679        Bound::Excluded(s) => *s - S::one(),
680        Bound::Unbounded => panic!("unbounded ranges are not allowed"),
681    };
682    assert!(start <= end);
683    start..=end
684}
685
686/// Creates a 2d bounding box from ranges of x and y coordinates.
687pub fn bb2d<S, RX, RY>(rx: RX, ry: RY) -> BBox2d<S>
688where
689    S: Integer,
690    RX: RangeBounds<S>,
691    RY: RangeBounds<S>,
692{
693    let rx = to_range_inclusive(rx);
694    let ry = to_range_inclusive(ry);
695    let min = p2d(*rx.start(), *ry.start());
696    let max = p2d(*rx.end(), *ry.end());
697    BBox { min, max }
698}
699/// Creates a 3d bounding box from ranges of x, y and z coordinates.
700pub fn bb3d<S, RX, RY, RZ>(rx: RX, ry: RY, rz: RZ) -> BBox3d<S>
701where
702    S: Integer,
703    RX: RangeBounds<S>,
704    RY: RangeBounds<S>,
705    RZ: RangeBounds<S>,
706{
707    let rx = to_range_inclusive(rx);
708    let ry = to_range_inclusive(ry);
709    let rz = to_range_inclusive(rz);
710    let min = p3d(*rx.start(), *ry.start(), *rz.start());
711    let max = p3d(*rx.end(), *ry.end(), *rz.end());
712    BBox { min, max }
713}
714/// Creates a 4d bounding box from ranges of x, y, z and w coordinates.
715pub fn bb4d<S, RX, RY, RZ, RW>(rx: RX, ry: RY, rz: RZ, rw: RW) -> BBox4d<S>
716where
717    S: Integer,
718    RX: RangeBounds<S>,
719    RY: RangeBounds<S>,
720    RZ: RangeBounds<S>,
721    RW: RangeBounds<S>,
722{
723    let rx = to_range_inclusive(rx);
724    let ry = to_range_inclusive(ry);
725    let rz = to_range_inclusive(rz);
726    let rw = to_range_inclusive(rw);
727    let min = p4d(*rx.start(), *ry.start(), *rz.start(), *rw.start());
728    let max = p4d(*rx.end(), *ry.end(), *rz.end(), *rw.end());
729    BBox { min, max }
730}
731
732impl<S, V> From<Point<S, V>> for BBox<S, V>
733where
734    S: Integer,
735    V: Vector<S>,
736{
737    /// Returns the bounding box which contains a single point.
738    fn from(p: Point<S, V>) -> BBox<S, V> {
739        BBox { min: p, max: p }
740    }
741}
742
743impl<S> IntoIterator for BBox<S, Vec2d<S>>
744where
745    S: Integer,
746    usize: TryFrom<S>,
747    <usize as TryFrom<S>>::Error: fmt::Debug,
748{
749    type Item = Point2d<S>;
750
751    type IntoIter = Points<S, Vec2d<S>, Layout2d<S>>;
752
753    fn into_iter(self) -> Self::IntoIter {
754        Layout2d::new(self).into_points()
755    }
756}
757impl<'a, S> IntoIterator for &'a BBox<S, Vec2d<S>>
758where
759    S: Integer,
760    usize: TryFrom<S>,
761    <usize as TryFrom<S>>::Error: fmt::Debug,
762{
763    type Item = Point2d<S>;
764
765    type IntoIter = Points<S, Vec2d<S>, Layout2d<S>>;
766
767    fn into_iter(self) -> Self::IntoIter {
768        Layout2d::new(*self).into_points()
769    }
770}
771
772impl<S> IntoIterator for BBox<S, Vec3d<S>>
773where
774    S: Integer,
775    usize: TryFrom<S>,
776    <usize as TryFrom<S>>::Error: fmt::Debug,
777{
778    type Item = Point3d<S>;
779
780    type IntoIter = Points<S, Vec3d<S>, Layout3d<S>>;
781
782    fn into_iter(self) -> Self::IntoIter {
783        Layout3d::new(self).into_points()
784    }
785}
786impl<'a, S> IntoIterator for &'a BBox<S, Vec3d<S>>
787where
788    S: Integer,
789    usize: TryFrom<S>,
790    <usize as TryFrom<S>>::Error: fmt::Debug,
791{
792    type Item = Point3d<S>;
793
794    type IntoIter = Points<S, Vec3d<S>, Layout3d<S>>;
795
796    fn into_iter(self) -> Self::IntoIter {
797        Layout3d::new(*self).into_points()
798    }
799}
800
801impl<S> IntoIterator for BBox<S, Vec4d<S>>
802where
803    S: Integer,
804    usize: TryFrom<S>,
805    <usize as TryFrom<S>>::Error: fmt::Debug,
806{
807    type Item = Point4d<S>;
808
809    type IntoIter = Points<S, Vec4d<S>, Layout4d<S>>;
810
811    fn into_iter(self) -> Self::IntoIter {
812        Layout4d::new(self).into_points()
813    }
814}
815impl<'a, S> IntoIterator for &'a BBox<S, Vec4d<S>>
816where
817    S: Integer,
818    usize: TryFrom<S>,
819    <usize as TryFrom<S>>::Error: fmt::Debug,
820{
821    type Item = Point4d<S>;
822
823    type IntoIter = Points<S, Vec4d<S>, Layout4d<S>>;
824
825    fn into_iter(self) -> Self::IntoIter {
826        Layout4d::new(*self).into_points()
827    }
828}
829
830impl<S, V> Add<V> for BBox<S, V>
831where
832    S: Integer,
833    V: Vector<S>,
834{
835    type Output = BBox<S, V>;
836
837    fn add(self, v: V) -> BBox<S, V> {
838        BBox::new(self.min() + v, self.lengths())
839    }
840}
841impl<'a, S, V> Add<&'a V> for BBox<S, V>
842where
843    S: Integer,
844    V: Vector<S>,
845{
846    type Output = BBox<S, V>;
847
848    fn add(self, v: &'a V) -> BBox<S, V> {
849        BBox::new(self.min() + v, self.lengths())
850    }
851}
852impl<'a, S, V> Add<V> for &'a BBox<S, V>
853where
854    S: Integer,
855    V: Vector<S>,
856{
857    type Output = BBox<S, V>;
858
859    fn add(self, v: V) -> BBox<S, V> {
860        BBox::new(self.min() + v, self.lengths())
861    }
862}
863impl<'a, S, V> Add<&'a V> for &'a BBox<S, V>
864where
865    S: Integer,
866    V: Vector<S>,
867{
868    type Output = BBox<S, V>;
869
870    fn add(self, v: &'a V) -> BBox<S, V> {
871        BBox::new(self.min() + v, self.lengths())
872    }
873}
874impl<S, V> Sub<V> for BBox<S, V>
875where
876    S: Integer,
877    V: Vector<S>,
878{
879    type Output = BBox<S, V>;
880
881    fn sub(self, v: V) -> BBox<S, V> {
882        BBox::new(self.min() - v, self.lengths())
883    }
884}
885impl<'a, S, V> Sub<&'a V> for BBox<S, V>
886where
887    S: Integer,
888    V: Vector<S>,
889{
890    type Output = BBox<S, V>;
891
892    fn sub(self, v: &'a V) -> BBox<S, V> {
893        BBox::new(self.min() - v, self.lengths())
894    }
895}
896impl<'a, S, V> Sub<V> for &'a BBox<S, V>
897where
898    S: Integer,
899    V: Vector<S>,
900{
901    type Output = BBox<S, V>;
902
903    fn sub(self, v: V) -> BBox<S, V> {
904        BBox::new(self.min() - v, self.lengths())
905    }
906}
907impl<'a, S, V> Sub<&'a V> for &'a BBox<S, V>
908where
909    S: Integer,
910    V: Vector<S>,
911{
912    type Output = BBox<S, V>;
913
914    fn sub(self, v: &'a V) -> BBox<S, V> {
915        BBox::new(self.min() - v, self.lengths())
916    }
917}
918
919impl<S, V> AddAssign<V> for BBox<S, V>
920where
921    S: Integer,
922    V: Vector<S>,
923{
924    fn add_assign(&mut self, other: V) {
925        self.min += other;
926        self.max += other;
927    }
928}
929impl<'a, S, V> AddAssign<&'a V> for BBox<S, V>
930where
931    S: Integer,
932    V: Vector<S>,
933{
934    fn add_assign(&mut self, other: &'a V) {
935        self.min += other;
936        self.max += other;
937    }
938}
939
940impl<S, V> SubAssign<V> for BBox<S, V>
941where
942    S: Integer,
943    V: Vector<S>,
944{
945    fn sub_assign(&mut self, other: V) {
946        self.min -= other;
947        self.max -= other;
948    }
949}
950impl<'a, S, V> SubAssign<&'a V> for BBox<S, V>
951where
952    S: Integer,
953    V: Vector<S>,
954{
955    fn sub_assign(&mut self, other: &'a V) {
956        self.min -= other;
957        self.max -= other;
958    }
959}
960
961#[cfg(test)]
962mod tests {
963    use core::ops::Bound::Excluded;
964
965    use crate::bb2d;
966    use crate::bb3d;
967    use crate::bb4d;
968    use crate::p2d;
969    use crate::p3d;
970    use crate::p4d;
971    use crate::v2d;
972    use crate::v3d;
973    use crate::v4d;
974    use crate::BBox2d;
975
976    #[cfg(feature = "random")]
977    use rand::rngs::StdRng;
978    #[cfg(feature = "random")]
979    use rand::SeedableRng;
980
981    #[test]
982    fn test_new() {
983        let bb = BBox2d::new(p2d(-2, 3), v2d(1, 2));
984        assert_eq!(bb2d(-2..-1, 3..5), bb);
985    }
986
987    #[test]
988    #[allow(deprecated)]
989    fn test_from_point() {
990        let bb = BBox2d::from_point(p2d(-2, 3));
991        assert_eq!(bb2d(-2..=-2, 3..=3), bb);
992    }
993
994    #[test]
995    #[allow(deprecated)]
996    fn test_from_points() {
997        let bb = BBox2d::from_points(p2d(-2, 3), p2d(4, 7));
998        assert_eq!(bb2d(-2..=4, 3..=7), bb);
999    }
1000
1001    #[test]
1002    fn test_from_corners() {
1003        let bb = BBox2d::from_corners(p2d(-2, 3), p2d(4, 7));
1004        assert_eq!(bb2d(-2..=4, 3..=7), bb);
1005    }
1006
1007    #[test]
1008    fn test_enclosing() {
1009        let bb = BBox2d::enclosing(&vec![p2d(-2, 3), p2d(4, 7)]);
1010        assert_eq!(Some(bb2d(-2..=4, 3..=7)), bb);
1011    }
1012    #[test]
1013    fn test_enclosing_empty() {
1014        let bb = <BBox2d<i64>>::enclosing(&vec![]);
1015        assert_eq!(None, bb);
1016    }
1017
1018    #[test]
1019    fn test_min_2d() {
1020        let bb = bb2d(-2..=2, -1..=1);
1021        assert_eq!(p2d(-2, -1), bb.min());
1022    }
1023    #[test]
1024    fn test_min_3d() {
1025        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1026        assert_eq!(p3d(-2, -1, 1), bb.min());
1027    }
1028    #[test]
1029    fn test_min_4d() {
1030        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1031        assert_eq!(p4d(-2, -1, 1, -5), bb.min());
1032    }
1033
1034    #[test]
1035    fn test_max_2d() {
1036        let bb = bb2d(-2..=2, -1..=1);
1037        assert_eq!(p2d(2, 1), bb.max());
1038    }
1039    #[test]
1040    fn test_max_3d() {
1041        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1042        assert_eq!(p3d(2, 1, 3), bb.max());
1043    }
1044    #[test]
1045    fn test_max_4d() {
1046        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1047        assert_eq!(p4d(2, 1, 3, -3), bb.max());
1048    }
1049
1050    #[test]
1051    fn test_lengths_2d() {
1052        let bb = bb2d(-2..3, -1..2);
1053        assert_eq!(v2d(5, 3), bb.lengths());
1054    }
1055    #[test]
1056    fn test_lengths_3d() {
1057        let bb = bb3d(-2..3, -1..2, 1..4);
1058        assert_eq!(v3d(5, 3, 3), bb.lengths());
1059    }
1060    #[test]
1061    fn test_lengths_4d() {
1062        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1063        assert_eq!(v4d(5, 3, 3, 3), bb.lengths());
1064    }
1065
1066    #[test]
1067    fn test_volume_2d() {
1068        let bb = bb2d(-2..3, -1..2);
1069        assert_eq!(15, bb.volume());
1070    }
1071    #[test]
1072    fn test_volume_3d() {
1073        let bb = bb3d(-2..3, -1..2, 1..4);
1074        assert_eq!(45, bb.volume());
1075    }
1076    #[test]
1077    fn test_volume_4d() {
1078        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1079        assert_eq!(135, bb.volume());
1080    }
1081
1082    #[test]
1083    fn test_lub() {
1084        let bb0 = bb2d(-2..3, -1..2);
1085        let bb1 = bb2d(-5..4, 2..5);
1086        assert_eq!(bb2d(-5..4, -1..5), bb0.lub(&bb1));
1087    }
1088
1089    #[test]
1090    fn test_intersection_nonempty() {
1091        let bb0 = bb2d(-2..=3, -1..=2);
1092        let bb1 = bb2d(-5..=4, 0..=5);
1093        assert_eq!(Some(bb2d(-2..=3, 0..=2)), bb0.intersection(&bb1));
1094    }
1095    #[test]
1096    fn test_intersection_empty() {
1097        let bb0 = bb2d(-2..3, -1..2);
1098        let bb1 = bb2d(-5..4, 2..5);
1099        assert_eq!(None, bb0.intersection(&bb1));
1100    }
1101
1102    #[test]
1103    fn test_extend_to() {
1104        let mut bb = bb2d(-2..3, -1..2);
1105        let p = p2d(3, 4);
1106        bb.extend_to(p);
1107        assert_eq!(bb2d(-2..4, -1..5), bb);
1108    }
1109
1110    #[test]
1111    fn test_extended_to() {
1112        let bb = bb2d(-2..3, -1..2);
1113        let p = p2d(3, 4);
1114        assert_eq!(bb2d(-2..4, -1..5), bb.extended_to(p));
1115    }
1116
1117    #[test]
1118    fn test_x_start_2d() {
1119        let bb = bb2d(-2..3, -1..2);
1120        assert_eq!(-2, bb.x_start());
1121    }
1122    #[test]
1123    fn test_x_start_3d() {
1124        let bb = bb3d(-2..3, -1..2, 1..4);
1125        assert_eq!(-2, bb.x_start());
1126    }
1127    #[test]
1128    fn test_x_start_4d() {
1129        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1130        assert_eq!(-2, bb.x_start());
1131    }
1132
1133    #[test]
1134    fn test_x_end_2d() {
1135        let bb = bb2d(-2..3, -1..2);
1136        assert_eq!(3, bb.x_end());
1137    }
1138    #[test]
1139    fn test_x_end_3d() {
1140        let bb = bb3d(-2..3, -1..2, 1..4);
1141        assert_eq!(3, bb.x_end());
1142    }
1143    #[test]
1144    fn test_x_end_4d() {
1145        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1146        assert_eq!(3, bb.x_end());
1147    }
1148
1149    #[test]
1150    fn test_x_min_2d() {
1151        let bb = bb2d(-2..=2, -1..=1);
1152        assert_eq!(-2, bb.x_min());
1153    }
1154    #[test]
1155    fn test_x_min_3d() {
1156        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1157        assert_eq!(-2, bb.x_min());
1158    }
1159    #[test]
1160    fn test_x_min_4d() {
1161        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1162        assert_eq!(-2, bb.x_min());
1163    }
1164
1165    #[test]
1166    fn test_x_max_2d() {
1167        let bb = bb2d(-2..=2, -1..=1);
1168        assert_eq!(2, bb.x_max());
1169    }
1170    #[test]
1171    fn test_x_max_3d() {
1172        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1173        assert_eq!(2, bb.x_max());
1174    }
1175    #[test]
1176    fn test_x_max_4d() {
1177        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1178        assert_eq!(2, bb.x_max());
1179    }
1180
1181    #[test]
1182    fn test_y_start_2d() {
1183        let bb = bb2d(-2..3, -1..2);
1184        assert_eq!(-1, bb.y_start());
1185    }
1186    #[test]
1187    fn test_y_start_3d() {
1188        let bb = bb3d(-2..3, -1..2, 1..4);
1189        assert_eq!(-1, bb.y_start());
1190    }
1191    #[test]
1192    fn test_y_start_4d() {
1193        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1194        assert_eq!(-1, bb.y_start());
1195    }
1196
1197    #[test]
1198    fn test_y_end_2d() {
1199        let bb = bb2d(-2..3, -1..2);
1200        assert_eq!(2, bb.y_end());
1201    }
1202    #[test]
1203    fn test_y_end_3d() {
1204        let bb = bb3d(-2..3, -1..2, 1..4);
1205        assert_eq!(2, bb.y_end());
1206    }
1207    #[test]
1208    fn test_y_end_4d() {
1209        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1210        assert_eq!(2, bb.y_end());
1211    }
1212
1213    #[test]
1214    fn test_y_min_2d() {
1215        let bb = bb2d(-2..=2, -1..=1);
1216        assert_eq!(-1, bb.y_min());
1217    }
1218    #[test]
1219    fn test_y_min_3d() {
1220        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1221        assert_eq!(-1, bb.y_min());
1222    }
1223    #[test]
1224    fn test_y_min_4d() {
1225        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1226        assert_eq!(-1, bb.y_min());
1227    }
1228
1229    #[test]
1230    fn test_y_max_2d() {
1231        let bb = bb2d(-2..=2, -1..=1);
1232        assert_eq!(1, bb.y_max());
1233    }
1234    #[test]
1235    fn test_y_max_3d() {
1236        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1237        assert_eq!(1, bb.y_max());
1238    }
1239    #[test]
1240    fn test_y_max_4d() {
1241        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1242        assert_eq!(1, bb.y_max());
1243    }
1244
1245    #[test]
1246    fn test_z_start_3d() {
1247        let bb = bb3d(-2..3, -1..2, 1..4);
1248        assert_eq!(1, bb.z_start());
1249    }
1250    #[test]
1251    fn test_z_start_4d() {
1252        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1253        assert_eq!(1, bb.z_start());
1254    }
1255
1256    #[test]
1257    fn test_z_end_3d() {
1258        let bb = bb3d(-2..3, -1..2, 1..4);
1259        assert_eq!(4, bb.z_end());
1260    }
1261    #[test]
1262    fn test_z_end_4d() {
1263        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1264        assert_eq!(4, bb.z_end());
1265    }
1266
1267    #[test]
1268    fn test_z_min_3d() {
1269        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1270        assert_eq!(1, bb.z_min());
1271    }
1272    #[test]
1273    fn test_z_min_4d() {
1274        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1275        assert_eq!(1, bb.z_min());
1276    }
1277
1278    #[test]
1279    fn test_z_max_3d() {
1280        let bb = bb3d(-2..=2, -1..=1, 1..=3);
1281        assert_eq!(3, bb.z_max());
1282    }
1283    #[test]
1284    fn test_z_max_4d() {
1285        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1286        assert_eq!(3, bb.z_max());
1287    }
1288
1289    #[test]
1290    fn test_w_start_4d() {
1291        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1292        assert_eq!(-5, bb.w_start());
1293    }
1294
1295    #[test]
1296    fn test_w_end_4d() {
1297        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1298        assert_eq!(-2, bb.w_end());
1299    }
1300
1301    #[test]
1302    fn test_w_min_4d() {
1303        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1304        assert_eq!(-5, bb.w_min());
1305    }
1306
1307    #[test]
1308    fn test_w_max_4d() {
1309        let bb = bb4d(-2..=2, -1..=1, 1..=3, -5..=-3);
1310        assert_eq!(-3, bb.w_max());
1311    }
1312
1313    #[test]
1314    fn test_x_len_2d() {
1315        let bb = bb2d(-2..3, -1..2);
1316        assert_eq!(5, bb.x_len());
1317    }
1318    #[test]
1319    fn test_x_len_3d() {
1320        let bb = bb3d(-2..3, -1..2, 1..4);
1321        assert_eq!(5, bb.x_len());
1322    }
1323    #[test]
1324    fn test_x_len_4d() {
1325        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1326        assert_eq!(5, bb.x_len());
1327    }
1328
1329    #[test]
1330    fn test_y_len_2d() {
1331        let bb = bb2d(-2..3, -1..2);
1332        assert_eq!(3, bb.y_len());
1333    }
1334    #[test]
1335    fn test_y_len_3d() {
1336        let bb = bb3d(-2..3, -1..2, 1..4);
1337        assert_eq!(3, bb.y_len());
1338    }
1339    #[test]
1340    fn test_y_len_4d() {
1341        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1342        assert_eq!(3, bb.y_len());
1343    }
1344
1345    #[test]
1346    fn test_z_len_3d() {
1347        let bb = bb3d(-2..3, -1..2, 1..4);
1348        assert_eq!(3, bb.z_len());
1349    }
1350    #[test]
1351    fn test_z_len_4d() {
1352        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1353        assert_eq!(3, bb.z_len());
1354    }
1355
1356    #[test]
1357    fn test_w_len_4d() {
1358        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1359        assert_eq!(3, bb.w_len());
1360    }
1361
1362    #[test]
1363    fn test_area() {
1364        let bb = bb2d(-2..3, -1..2);
1365        assert_eq!(15, bb.area());
1366    }
1367
1368    #[test]
1369    fn test_contains() {
1370        let bb = bb2d(-2..3, -1..2);
1371        assert_eq!(bb.contains(&p2d(0, 0)), true);
1372        assert_eq!(bb.contains(&p2d(-2, 0)), true);
1373        assert_eq!(bb.contains(&p2d(-3, 0)), false);
1374        assert_eq!(bb.contains(&p2d(2, 0)), true);
1375        assert_eq!(bb.contains(&p2d(3, 0)), false);
1376        assert_eq!(bb.contains(&p2d(0, -1)), true);
1377        assert_eq!(bb.contains(&p2d(0, -2)), false);
1378        assert_eq!(bb.contains(&p2d(0, 1)), true);
1379        assert_eq!(bb.contains(&p2d(0, 2)), false);
1380    }
1381
1382    #[test]
1383    fn test_x_range_2d() {
1384        let bb = bb2d(-2..3, -1..2);
1385        assert_eq!(-2..3, bb.x_range());
1386    }
1387    #[test]
1388    fn test_x_range_3d() {
1389        let bb = bb3d(-2..3, -1..2, 1..4);
1390        assert_eq!(-2..3, bb.x_range());
1391    }
1392    #[test]
1393    fn test_x_range_4d() {
1394        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1395        assert_eq!(-2..3, bb.x_range());
1396    }
1397
1398    #[test]
1399    fn test_y_range_2d() {
1400        let bb = bb2d(-2..3, -1..2);
1401        assert_eq!(-1..2, bb.y_range());
1402    }
1403    #[test]
1404    fn test_y_range_3d() {
1405        let bb = bb3d(-2..3, -1..2, 1..4);
1406        assert_eq!(-1..2, bb.y_range());
1407    }
1408    #[test]
1409    fn test_y_range_4d() {
1410        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1411        assert_eq!(-1..2, bb.y_range());
1412    }
1413
1414    #[test]
1415    fn test_z_range_3d() {
1416        let bb = bb3d(-2..3, -1..2, 1..4);
1417        assert_eq!(1..4, bb.z_range());
1418    }
1419    #[test]
1420    fn test_z_range_4d() {
1421        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1422        assert_eq!(1..4, bb.z_range());
1423    }
1424
1425    #[test]
1426    fn test_w_range_4d() {
1427        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1428        assert_eq!(-5..-2, bb.w_range());
1429    }
1430
1431    #[test]
1432    fn test_center() {
1433        let bb = bb2d(-2..3, -1..2);
1434        assert_eq!(p2d(0, 0), bb.center());
1435    }
1436
1437    #[cfg(feature = "random")]
1438    #[test]
1439    fn test_random_point_2d() {
1440        let mut rng = StdRng::seed_from_u64(42);
1441        let bb = bb2d(-2..3, -1..2);
1442        assert_eq!(p2d(-1, 0), bb.random_point(&mut rng));
1443    }
1444    #[cfg(feature = "random")]
1445    #[test]
1446    fn test_random_point_3d() {
1447        let mut rng = StdRng::seed_from_u64(42);
1448        let bb = bb3d(-2..3, -1..2, 1..4);
1449        assert_eq!(p3d(-1, 0, 3), bb.random_point(&mut rng));
1450    }
1451    #[cfg(feature = "random")]
1452    #[test]
1453    fn test_random_point_4d() {
1454        let mut rng = StdRng::seed_from_u64(42);
1455        let bb = bb4d(-2..3, -1..2, 1..4, -5..-2);
1456        assert_eq!(p4d(-1, 0, 3, -4), bb.random_point(&mut rng));
1457    }
1458
1459    #[test]
1460    fn test_bb2d_incl() {
1461        let bb = bb2d(0..=2, 1..=4);
1462        assert_eq!(bb2d(0..3, 1..5), bb)
1463    }
1464    #[test]
1465    fn test_bb2d_excl() {
1466        let bb = bb2d((Excluded(-1), Excluded(3)), (Excluded(0), Excluded(5)));
1467        assert_eq!(bb2d(0..3, 1..5), bb)
1468    }
1469    #[test]
1470    fn test_bb3d_incl() {
1471        let bb = bb3d(0..=2, 1..=4, 2..=6);
1472        assert_eq!(bb3d(0..3, 1..5, 2..7), bb)
1473    }
1474    #[test]
1475    fn test_bb3d_excl() {
1476        let bb = bb3d(
1477            (Excluded(-1), Excluded(3)),
1478            (Excluded(0), Excluded(5)),
1479            (Excluded(1), Excluded(7)),
1480        );
1481        assert_eq!(bb3d(0..3, 1..5, 2..7), bb)
1482    }
1483    #[test]
1484    fn test_bb4d_incl() {
1485        let bb = bb4d(0..=2, 1..=4, 2..=6, 3..=8);
1486        assert_eq!(bb4d(0..3, 1..5, 2..7, 3..9), bb)
1487    }
1488    #[test]
1489    fn test_bb4d_excl() {
1490        let bb = bb4d(
1491            (Excluded(-1), Excluded(3)),
1492            (Excluded(0), Excluded(5)),
1493            (Excluded(1), Excluded(7)),
1494            (Excluded(2), Excluded(9)),
1495        );
1496        assert_eq!(bb4d(0..3, 1..5, 2..7, 3..9), bb)
1497    }
1498
1499    #[test]
1500    fn test_from() {
1501        let bb = BBox2d::from(p2d(-2, 3));
1502        assert_eq!(bb2d(-2..=-2, 3..=3), bb);
1503    }
1504
1505    #[test]
1506    fn test_iter_2d() {
1507        let bb = bb2d(1..=2, -1..=0);
1508        let v = bb.iter().collect::<Vec<_>>();
1509        assert_eq!(vec![p2d(1, -1), p2d(2, -1), p2d(1, 0), p2d(2, 0)], v);
1510    }
1511    #[test]
1512    fn test_iter_3d() {
1513        let bb = bb3d(1..=2, -1..=0, -2..=-1);
1514        let v = bb.iter().collect::<Vec<_>>();
1515        assert_eq!(
1516            vec![
1517                p3d(1, -1, -2),
1518                p3d(2, -1, -2),
1519                p3d(1, 0, -2),
1520                p3d(2, 0, -2),
1521                p3d(1, -1, -1),
1522                p3d(2, -1, -1),
1523                p3d(1, 0, -1),
1524                p3d(2, 0, -1),
1525            ],
1526            v
1527        );
1528    }
1529    #[test]
1530    fn test_iter_4d() {
1531        let bb = bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
1532        let v = bb.iter().collect::<Vec<_>>();
1533        assert_eq!(
1534            vec![
1535                p4d(1, -1, -2, 3),
1536                p4d(2, -1, -2, 3),
1537                p4d(1, 0, -2, 3),
1538                p4d(2, 0, -2, 3),
1539                p4d(1, -1, -1, 3),
1540                p4d(2, -1, -1, 3),
1541                p4d(1, 0, -1, 3),
1542                p4d(2, 0, -1, 3),
1543                p4d(1, -1, -2, 4),
1544                p4d(2, -1, -2, 4),
1545                p4d(1, 0, -2, 4),
1546                p4d(2, 0, -2, 4),
1547                p4d(1, -1, -1, 4),
1548                p4d(2, -1, -1, 4),
1549                p4d(1, 0, -1, 4),
1550                p4d(2, 0, -1, 4),
1551            ],
1552            v
1553        );
1554    }
1555
1556    #[test]
1557    fn test_exact_size_iterator_2d_owned() {
1558        let bb = bb2d(1..=2, -1..=0);
1559        let mut it = bb.into_iter();
1560        assert_eq!((4, Some(4)), it.size_hint());
1561        assert_eq!(4, it.len());
1562        let p = it.next();
1563        assert_eq!(Some(p2d(1, -1)), p);
1564        assert_eq!((3, Some(3)), it.size_hint());
1565        assert_eq!(3, it.len());
1566    }
1567    #[test]
1568    fn test_exact_size_iterator_2d_ref() {
1569        let bb = &bb2d(1..=2, -1..=0);
1570        let mut it = bb.into_iter();
1571        assert_eq!((4, Some(4)), it.size_hint());
1572        assert_eq!(4, it.len());
1573        let p = it.next();
1574        assert_eq!(Some(p2d(1, -1)), p);
1575        assert_eq!((3, Some(3)), it.size_hint());
1576        assert_eq!(3, it.len());
1577    }
1578    #[test]
1579    fn test_exact_size_iterator_3d_owned() {
1580        let bb = bb3d(1..=2, -1..=0, -2..=-1);
1581        let mut it = bb.into_iter();
1582        assert_eq!((8, Some(8)), it.size_hint());
1583        assert_eq!(8, it.len());
1584        let p = it.next();
1585        assert_eq!(Some(p3d(1, -1, -2)), p);
1586        assert_eq!((7, Some(7)), it.size_hint());
1587        assert_eq!(7, it.len());
1588    }
1589    #[test]
1590    fn test_exact_size_iterator_3d_ref() {
1591        let bb = &bb3d(1..=2, -1..=0, -2..=-1);
1592        let mut it = bb.into_iter();
1593        assert_eq!((8, Some(8)), it.size_hint());
1594        assert_eq!(8, it.len());
1595        let p = it.next();
1596        assert_eq!(Some(p3d(1, -1, -2)), p);
1597        assert_eq!((7, Some(7)), it.size_hint());
1598        assert_eq!(7, it.len());
1599    }
1600    #[test]
1601    fn test_exact_size_iterator_4d_owned() {
1602        let bb = bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
1603        let mut it = bb.into_iter();
1604        assert_eq!((16, Some(16)), it.size_hint());
1605        assert_eq!(16, it.len());
1606        let p = it.next();
1607        assert_eq!(Some(p4d(1, -1, -2, 3)), p);
1608        assert_eq!((15, Some(15)), it.size_hint());
1609        assert_eq!(15, it.len());
1610    }
1611    #[test]
1612    fn test_exact_size_iterator_4d_ref() {
1613        let bb = &bb4d(1..=2, -1..=0, -2..=-1, 3..=4);
1614        let mut it = bb.into_iter();
1615        assert_eq!((16, Some(16)), it.size_hint());
1616        assert_eq!(16, it.len());
1617        let p = it.next();
1618        assert_eq!(Some(p4d(1, -1, -2, 3)), p);
1619        assert_eq!((15, Some(15)), it.size_hint());
1620        assert_eq!(15, it.len());
1621    }
1622
1623    #[test]
1624    fn test_add_2d() {
1625        let bb = bb2d(-2..3, -1..2);
1626        let v = v2d(3, 7);
1627        assert_eq!(bb2d(1..6, 6..9), bb + v);
1628        assert_eq!(bb2d(1..6, 6..9), bb + &v);
1629        assert_eq!(bb2d(1..6, 6..9), &bb + v);
1630        assert_eq!(bb2d(1..6, 6..9), &bb + &v);
1631    }
1632
1633    #[test]
1634    fn test_sub_2d() {
1635        let bb = bb2d(-2..3, -1..2);
1636        let v = v2d(-3, -7);
1637        assert_eq!(bb2d(1..6, 6..9), bb - v);
1638        assert_eq!(bb2d(1..6, 6..9), bb - &v);
1639        assert_eq!(bb2d(1..6, 6..9), &bb - v);
1640        assert_eq!(bb2d(1..6, 6..9), &bb - &v);
1641    }
1642
1643    #[test]
1644    fn test_add_assign_2d() {
1645        let mut bb = bb2d(-2..3, -1..2);
1646        let v = v2d(3, 7);
1647        bb += v;
1648        assert_eq!(bb2d(1..6, 6..9), bb);
1649        bb += &v;
1650        assert_eq!(bb2d(4..9, 13..16), bb);
1651    }
1652
1653    #[test]
1654    fn test_sub_assign_2d() {
1655        let mut bb = bb2d(-2..3, -1..2);
1656        let v = v2d(-3, -7);
1657        bb -= v;
1658        assert_eq!(bb2d(1..6, 6..9), bb);
1659        bb -= &v;
1660        assert_eq!(bb2d(4..9, 13..16), bb);
1661    }
1662}