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