1 use crate::point::{max_inline, Point, PointExt};
2 use crate::{Envelope, RTreeObject};
3 use num_traits::{Bounded, One, Signed, Zero};
4 
5 #[cfg(feature = "serde")]
6 use serde::{Deserialize, Serialize};
7 
8 /// An n-dimensional axis aligned bounding box (AABB).
9 ///
10 /// An object's AABB is the smallest box totally encompassing an object
11 /// while being aligned to the current coordinate system.
12 /// Although these structures are commonly called bounding _boxes_, they exist in any
13 /// dimension.
14 ///
15 /// Note that AABBs cannot be inserted into r-trees. Use the
16 /// [Rectangle](primitives/struct.Rectangle.html) struct for this purpose.
17 ///
18 /// # Type arguments
19 /// `P`: The struct is generic over which point type is used. Using an n-dimensional point
20 /// type will result in an n-dimensional bounding box.
21 #[derive(Clone, Debug, Copy, PartialEq, Eq, Ord, PartialOrd)]
22 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23 pub struct AABB<P>
24 where
25     P: Point,
26 {
27     lower: P,
28     upper: P,
29 }
30 
31 impl<P> AABB<P>
32 where
33     P: Point,
34 {
35     /// Returns the AABB encompassing a single point.
from_point(p: P) -> Self36     pub fn from_point(p: P) -> Self {
37         AABB { lower: p, upper: p }
38     }
39 
40     /// Returns the AABB's lower corner.
41     ///
42     /// This is the point contained within the AABB with the smallest coordinate value in each
43     /// dimension.
lower(&self) -> P44     pub fn lower(&self) -> P {
45         self.lower
46     }
47 
48     /// Returns the AABB's upper corner.
49     ///
50     /// This is the point contained within the AABB with the largest coordinate value in each
51     /// dimension.
upper(&self) -> P52     pub fn upper(&self) -> P {
53         self.upper
54     }
55 
56     /// Creates a new AABB encompassing two points.
from_corners(p1: P, p2: P) -> Self57     pub fn from_corners(p1: P, p2: P) -> Self {
58         AABB {
59             lower: p1.min_point(&p2),
60             upper: p1.max_point(&p2),
61         }
62     }
63 
64     /// Creates a new AABB encompassing a collection of points.
from_points<'a, I>(i: I) -> Self where I: IntoIterator<Item = &'a P> + 'a, P: 'a,65     pub fn from_points<'a, I>(i: I) -> Self
66     where
67         I: IntoIterator<Item = &'a P> + 'a,
68         P: 'a,
69     {
70         i.into_iter()
71             .fold(Self::new_empty(), |aabb, p| aabb.add_point(p))
72     }
73 
74     /// Returns the AABB that contains `self` and another point.
add_point(&self, point: &P) -> Self75     fn add_point(&self, point: &P) -> Self {
76         AABB {
77             lower: self.lower.min_point(point),
78             upper: self.upper.max_point(point),
79         }
80     }
81 
82     /// Returns the point within this AABB closest to a given point.
83     ///
84     /// If `point` is contained within the AABB, `point` will be returned.
min_point(&self, point: &P) -> P85     pub fn min_point(&self, point: &P) -> P {
86         self.upper.min_point(&self.lower.max_point(point))
87     }
88 
89     /// Returns the squared distance to the AABB's [min_point](#method.min_point).
distance_2(&self, point: &P) -> P::Scalar90     pub fn distance_2(&self, point: &P) -> P::Scalar {
91         if self.contains_point(point) {
92             Zero::zero()
93         } else {
94             self.min_point(point).sub(point).length_2()
95         }
96     }
97 }
98 
99 impl<P> Envelope for AABB<P>
100 where
101     P: Point,
102 {
103     type Point = P;
104 
new_empty() -> Self105     fn new_empty() -> Self {
106         new_empty()
107     }
108 
contains_point(&self, point: &P) -> bool109     fn contains_point(&self, point: &P) -> bool {
110         self.lower.all_component_wise(point, |x, y| x <= y)
111             && self.upper.all_component_wise(point, |x, y| x >= y)
112     }
113 
contains_envelope(&self, other: &Self) -> bool114     fn contains_envelope(&self, other: &Self) -> bool {
115         self.lower.all_component_wise(&other.lower, |l, r| l <= r)
116             && self.upper.all_component_wise(&other.upper, |l, r| l >= r)
117     }
118 
merge(&mut self, other: &Self)119     fn merge(&mut self, other: &Self) {
120         self.lower = self.lower.min_point(&other.lower);
121         self.upper = self.upper.max_point(&other.upper);
122     }
123 
merged(&self, other: &Self) -> Self124     fn merged(&self, other: &Self) -> Self {
125         AABB {
126             lower: self.lower.min_point(&other.lower),
127             upper: self.upper.max_point(&other.upper),
128         }
129     }
130 
intersects(&self, other: &Self) -> bool131     fn intersects(&self, other: &Self) -> bool {
132         self.lower.all_component_wise(&other.upper, |l, r| l <= r)
133             && self.upper.all_component_wise(&other.lower, |l, r| l >= r)
134     }
135 
area(&self) -> P::Scalar136     fn area(&self) -> P::Scalar {
137         let zero = P::Scalar::zero();
138         let one = P::Scalar::one();
139         let diag = self.upper.sub(&self.lower);
140         diag.fold(one, |acc, cur| max_inline(cur, zero) * acc)
141     }
142 
distance_2(&self, point: &P) -> P::Scalar143     fn distance_2(&self, point: &P) -> P::Scalar {
144         self.distance_2(point)
145     }
146 
min_max_dist_2(&self, point: &P) -> <P as Point>::Scalar147     fn min_max_dist_2(&self, point: &P) -> <P as Point>::Scalar {
148         let l = self.lower.sub(point);
149         let u = self.upper.sub(point);
150         let (mut min, mut max) = (P::new(), P::new());
151         for i in 0..P::DIMENSIONS {
152             if l.nth(i).abs() < u.nth(i).abs() {
153                 *min.nth_mut(i) = l.nth(i);
154                 *max.nth_mut(i) = u.nth(i);
155             } else {
156                 *min.nth_mut(i) = u.nth(i);
157                 *max.nth_mut(i) = l.nth(i);
158             }
159         }
160         let mut result = Zero::zero();
161         for i in 0..P::DIMENSIONS {
162             let mut p = max;
163             // Only set one component to the minimum distance
164             *p.nth_mut(i) = min.nth(i);
165             let new_dist = p.length_2();
166             if new_dist < result || i == 0 {
167                 result = new_dist
168             }
169         }
170         result
171     }
172 
center(&self) -> Self::Point173     fn center(&self) -> Self::Point {
174         let one = <Self::Point as Point>::Scalar::one();
175         let two = one + one;
176         self.lower.component_wise(&self.upper, |x, y| (x + y) / two)
177     }
178 
intersection_area(&self, other: &Self) -> <Self::Point as Point>::Scalar179     fn intersection_area(&self, other: &Self) -> <Self::Point as Point>::Scalar {
180         AABB {
181             lower: self.lower.max_point(&other.lower),
182             upper: self.upper.min_point(&other.upper),
183         }
184         .area()
185     }
186 
perimeter_value(&self) -> P::Scalar187     fn perimeter_value(&self) -> P::Scalar {
188         let diag = self.upper.sub(&self.lower);
189         let zero = P::Scalar::zero();
190         max_inline(diag.fold(zero, |acc, value| acc + value), zero)
191     }
192 
sort_envelopes<T: RTreeObject<Envelope = Self>>(axis: usize, envelopes: &mut [T])193     fn sort_envelopes<T: RTreeObject<Envelope = Self>>(axis: usize, envelopes: &mut [T]) {
194         envelopes.sort_by(|l, r| {
195             l.envelope()
196                 .lower
197                 .nth(axis)
198                 .partial_cmp(&r.envelope().lower.nth(axis))
199                 .unwrap()
200         });
201     }
202 
partition_envelopes<T: RTreeObject<Envelope = Self>>( axis: usize, envelopes: &mut [T], selection_size: usize, )203     fn partition_envelopes<T: RTreeObject<Envelope = Self>>(
204         axis: usize,
205         envelopes: &mut [T],
206         selection_size: usize,
207     ) {
208         ::pdqselect::select_by(envelopes, selection_size, |l, r| {
209             l.envelope()
210                 .lower
211                 .nth(axis)
212                 .partial_cmp(&r.envelope().lower.nth(axis))
213                 .unwrap()
214         });
215     }
216 }
217 
new_empty<P: Point>() -> AABB<P>218 fn new_empty<P: Point>() -> AABB<P> {
219     let max = P::Scalar::max_value();
220     let min = P::Scalar::min_value();
221     AABB {
222         lower: P::from_value(max),
223         upper: P::from_value(min),
224     }
225 }
226