1use crate::point::{max_inline, Point, PointExt};
2use crate::{Envelope, RTreeObject};
3use num_traits::{Bounded, One, Zero};
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Copy, PartialEq, Eq, Ord, PartialOrd)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct AABB<P>
24where
25 P: Point,
26{
27 lower: P,
28 upper: P,
29}
30
31impl<P> AABB<P>
32where
33 P: Point,
34{
35 pub fn from_point(p: P) -> Self {
37 AABB {
38 lower: p.clone(),
39 upper: p.clone(),
40 }
41 }
42
43 pub fn lower(&self) -> P {
48 self.lower.clone()
49 }
50
51 pub fn upper(&self) -> P {
56 self.upper.clone()
57 }
58
59 pub fn from_corners(p1: P, p2: P) -> Self {
61 AABB {
62 lower: p1.min_point(&p2),
63 upper: p1.max_point(&p2),
64 }
65 }
66
67 pub fn from_points<'a, I>(i: I) -> Self
69 where
70 I: IntoIterator<Item = &'a P> + 'a,
71 P: 'a,
72 {
73 i.into_iter()
74 .fold(Self::new_empty(), |aabb, p| aabb.add_point(p))
75 }
76
77 fn add_point(&self, point: &P) -> Self {
79 AABB {
80 lower: self.lower.min_point(point),
81 upper: self.upper.max_point(point),
82 }
83 }
84
85 pub fn min_point(&self, point: &P) -> P {
89 self.upper.min_point(&self.lower.max_point(point))
90 }
91
92 pub fn distance_2(&self, point: &P) -> P::Scalar {
94 if self.contains_point(point) {
95 Zero::zero()
96 } else {
97 self.min_point(point).sub(point).length_2()
98 }
99 }
100}
101
102impl<P> Envelope for AABB<P>
103where
104 P: Point,
105{
106 type Point = P;
107
108 fn new_empty() -> Self {
109 new_empty()
110 }
111
112 fn contains_point(&self, point: &P) -> bool {
113 self.lower.all_component_wise(point, |x, y| x <= y)
114 && self.upper.all_component_wise(point, |x, y| x >= y)
115 }
116
117 fn contains_envelope(&self, other: &Self) -> bool {
118 self.lower.all_component_wise(&other.lower, |l, r| l <= r)
119 && self.upper.all_component_wise(&other.upper, |l, r| l >= r)
120 }
121
122 fn merge(&mut self, other: &Self) {
123 self.lower = self.lower.min_point(&other.lower);
124 self.upper = self.upper.max_point(&other.upper);
125 }
126
127 fn merged(&self, other: &Self) -> Self {
128 AABB {
129 lower: self.lower.min_point(&other.lower),
130 upper: self.upper.max_point(&other.upper),
131 }
132 }
133
134 fn intersects(&self, other: &Self) -> bool {
135 self.lower.all_component_wise(&other.upper, |l, r| l <= r)
136 && self.upper.all_component_wise(&other.lower, |l, r| l >= r)
137 }
138
139 fn area(&self) -> P::Scalar {
140 let zero = P::Scalar::zero();
141 let one = P::Scalar::one();
142 let diag = self.upper.sub(&self.lower);
143 diag.fold(one, |acc, cur| max_inline(cur, zero) * acc)
144 }
145
146 fn distance_2(&self, point: &P) -> P::Scalar {
147 self.distance_2(point)
148 }
149
150 fn min_max_dist_2(&self, point: &P) -> <P as Point>::Scalar {
151 let l = self.lower.sub(point);
152 let u = self.upper.sub(point);
153 let mut max_diff = (Zero::zero(), Zero::zero(), 0); let mut result = P::new();
155
156 for i in 0..P::DIMENSIONS {
157 let mut min = l.nth(i);
158 let mut max = u.nth(i);
159 max = max * max;
160 min = min * min;
161 if max < min {
162 core::mem::swap(&mut min, &mut max);
163 }
164
165 let diff = max - min;
166 *result.nth_mut(i) = max;
167
168 if diff >= max_diff.0 {
169 max_diff = (diff, min, i);
170 }
171 }
172
173 *result.nth_mut(max_diff.2) = max_diff.1;
174 result.fold(Zero::zero(), |acc, curr| acc + curr)
175 }
176
177 fn center(&self) -> Self::Point {
178 let one = <Self::Point as Point>::Scalar::one();
179 let two = one + one;
180 self.lower.component_wise(&self.upper, |x, y| (x + y) / two)
181 }
182
183 fn intersection_area(&self, other: &Self) -> <Self::Point as Point>::Scalar {
184 AABB {
185 lower: self.lower.max_point(&other.lower),
186 upper: self.upper.min_point(&other.upper),
187 }
188 .area()
189 }
190
191 fn perimeter_value(&self) -> P::Scalar {
192 let diag = self.upper.sub(&self.lower);
193 let zero = P::Scalar::zero();
194 max_inline(diag.fold(zero, |acc, value| acc + value), zero)
195 }
196
197 fn sort_envelopes<T: RTreeObject<Envelope = Self>>(axis: usize, envelopes: &mut [T]) {
198 envelopes.sort_by(|l, r| {
199 l.envelope()
200 .lower
201 .nth(axis)
202 .partial_cmp(&r.envelope().lower.nth(axis))
203 .unwrap()
204 });
205 }
206
207 fn partition_envelopes<T: RTreeObject<Envelope = Self>>(
208 axis: usize,
209 envelopes: &mut [T],
210 selection_size: usize,
211 ) {
212 envelopes.select_nth_unstable_by(selection_size, |l, r| {
213 l.envelope()
214 .lower
215 .nth(axis)
216 .partial_cmp(&r.envelope().lower.nth(axis))
217 .unwrap()
218 });
219 }
220}
221
222fn new_empty<P: Point>() -> AABB<P> {
223 let max = P::Scalar::max_value();
224 let min = P::Scalar::min_value();
225 AABB {
226 lower: P::from_value(max),
227 upper: P::from_value(min),
228 }
229}
230
231#[cfg(test)]
232mod test {
233 use super::AABB;
234 use crate::envelope::Envelope;
235 use crate::object::PointDistance;
236
237 #[test]
241 fn test_min_max_dist_2_issue_40_regression() {
242 let a = [0.7018702292340033, 0.2121617955083932, 0.8120562975177115];
243 let b = [0.7297749764202988, 0.23020869735094462, 0.8194675310336391];
244 let aabb = AABB::from_corners(a, b);
245 let p = [0.6950876013070484, 0.220750082121574, 0.8186032137709887];
246 let corner = [a[0], b[1], a[2]];
247 assert_eq!(aabb.min_max_dist_2(&p), corner.distance_2(&p));
248 }
249}