1use euclid::Point2D;
8use num_traits::Num;
9use partial_min_max::{max as partial_max, min as partial_min};
10use std::fmt;
11
12#[derive(Clone, PartialEq)]
17pub struct Aabb<T, U = euclid::UnknownUnit> {
18 min: Point2D<T, U>,
19 max: Point2D<T, U>,
20}
21
22impl<T, U> fmt::Debug for Aabb<T, U>
23where
24 T: fmt::Debug,
25{
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 f.debug_struct("Aabb")
28 .field("min", &self.min)
29 .field("max", &self.max)
30 .finish()
31 }
32}
33
34impl<T, U> Aabb<T, U>
35where
36 T: Copy + Num + PartialOrd,
37{
38 #[inline]
42 pub fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Aabb<T, U> {
43 assert!(min.x <= max.x);
44 assert!(min.y <= max.y);
45 Aabb { min, max }
46 }
47
48 pub fn for_vertices<I>(vertices: I) -> Aabb<T, U>
55 where
56 I: IntoIterator<Item = Point2D<T, U>>,
57 {
58 let mut vertices = vertices.into_iter();
59 let first = vertices
60 .next()
61 .expect("Must have at least one vertex to create a bounding box");
62 let mut min = first;
63 let mut max = first;
64 for v in vertices {
65 min.x = partial_min(min.x, v.x);
66 min.y = partial_min(min.y, v.y);
67 max.x = partial_max(max.x, v.x);
68 max.y = partial_max(max.y, v.y);
69 }
70 Aabb::new(min, max)
71 }
72
73 #[inline]
75 pub fn min(&self) -> Point2D<T, U> {
76 self.min
77 }
78
79 #[inline]
81 pub fn max(&self) -> Point2D<T, U> {
82 self.max
83 }
84
85 #[inline]
87 pub fn width(&self) -> T {
88 self.max.x - self.min.x
89 }
90
91 #[inline]
93 pub fn height(&self) -> T {
94 self.max.y - self.min.y
95 }
96
97 #[inline]
99 pub fn area(&self) -> T {
100 (self.max.x - self.min.x) * (self.max.y - self.min.y)
101 }
102
103 #[inline]
105 pub fn join(&self, other: &Aabb<T, U>) -> Aabb<T, U> {
106 let min = Point2D::new(
107 partial_min(self.min.x, other.min.x),
108 partial_min(self.min.y, other.min.y),
109 );
110 let max = Point2D::new(
111 partial_max(self.max.x, other.max.x),
112 partial_max(self.max.y, other.max.y),
113 );
114 Aabb::new(min, max)
115 }
116
117 pub fn contains(&self, other: &Aabb<T, U>) -> bool {
119 other.min.x >= self.min.x
120 && other.max.x <= self.max.x
121 && other.min.y >= self.min.y
122 && other.max.y <= self.max.y
123 }
124
125 pub fn contains_point(&self, p: euclid::Point2D<T, U>) -> bool {
127 p.x >= self.min.x && p.x <= self.max.x && p.y >= self.min.y && p.y <= self.max.y
128 }
129
130 pub fn intersects(&self, other: &Aabb<T, U>) -> bool {
132 self.max.x > other.min.x
133 && self.min.x < other.max.x
134 && self.max.y > other.min.y
135 && self.min.y < other.max.y
136 }
137}
138
139#[derive(Debug, Default)]
141pub struct AabbTree<T, U, V> {
142 root: Option<AabbTreeNode<T, U, V>>,
143}
144
145#[derive(Debug)]
146enum AabbTreeNode<T, U, V> {
147 Branch(AabbTreeBranch<T, U, V>),
148 Leaf(AabbTreeLeaf<T, U, V>),
149}
150
151#[derive(Debug)]
152struct AabbTreeBranch<T, U, V> {
153 aabb: Aabb<T, U>,
154 children: Box<(AabbTreeNode<T, U, V>, AabbTreeNode<T, U, V>)>,
155}
156
157#[derive(Debug)]
158struct AabbTreeLeaf<T, U, V> {
159 aabb: Aabb<T, U>,
160 value: V,
161}
162
163impl<T, U, V> AabbTree<T, U, V>
164where
165 T: Copy + Num + PartialOrd,
166{
167 #[inline]
169 pub fn new() -> AabbTree<T, U, V> {
170 AabbTree { root: None }
171 }
172
173 pub fn insert(&mut self, aabb: Aabb<T, U>, value: V) {
175 let leaf = AabbTreeLeaf { aabb, value };
176 self.root = Some(if let Some(r) = self.root.take() {
177 r.insert(leaf)
178 } else {
179 AabbTreeNode::Leaf(leaf)
180 });
181 }
182
183 pub fn iter_overlapping(&self, aabb: Aabb<T, U>) -> IterOverlapping<T, U, V> {
207 let stack = self
208 .root
209 .iter()
210 .filter(|n| n.aabb().intersects(&aabb))
211 .collect();
212 IterOverlapping { aabb, stack }
213 }
214
215 #[inline]
217 pub fn any_overlap(&self, aabb: Aabb<T, U>) -> bool {
218 self.iter_overlapping(aabb).next().is_some()
219 }
220}
221
222impl<T, U, V> AabbTreeNode<T, U, V>
223where
224 T: Copy + Num + PartialOrd,
225{
226 fn aabb(&self) -> &Aabb<T, U> {
227 match self {
228 AabbTreeNode::Leaf(l) => &l.aabb,
229 AabbTreeNode::Branch(b) => &b.aabb,
230 }
231 }
232
233 fn insert(self, leaf: AabbTreeLeaf<T, U, V>) -> AabbTreeNode<T, U, V> {
234 match self {
235 AabbTreeNode::Leaf(l) => AabbTreeNode::Branch(AabbTreeBranch {
236 aabb: l.aabb.join(&leaf.aabb),
237 children: Box::new((AabbTreeNode::Leaf(l), AabbTreeNode::Leaf(leaf))),
238 }),
239 AabbTreeNode::Branch(branch) => {
240 let combined_aabb = branch.aabb.join(&leaf.aabb);
241 let two = T::one() + T::one();
242 let new_parent_cost = two * combined_aabb.area();
243 let min_push_down_cost = two * (combined_aabb.area() - branch.aabb.area());
244
245 let left_cost = match branch.children.0 {
246 AabbTreeNode::Leaf(ref l) => {
247 l.aabb.join(&leaf.aabb).area() + min_push_down_cost
248 }
249 AabbTreeNode::Branch(ref b) => {
250 b.aabb.join(&leaf.aabb).area() - b.aabb.area() + min_push_down_cost
251 }
252 };
253
254 let right_cost = match branch.children.1 {
255 AabbTreeNode::Leaf(ref l) => {
256 l.aabb.join(&leaf.aabb).area() + min_push_down_cost
257 }
258 AabbTreeNode::Branch(ref b) => {
259 b.aabb.join(&leaf.aabb).area() - b.aabb.area() + min_push_down_cost
260 }
261 };
262
263 AabbTreeNode::Branch(AabbTreeBranch {
264 aabb: combined_aabb,
265 children: Box::new(
266 if new_parent_cost < left_cost && new_parent_cost < right_cost {
267 (AabbTreeNode::Leaf(leaf), AabbTreeNode::Branch(branch))
268 } else if left_cost < right_cost {
269 (branch.children.0.insert(leaf), branch.children.1)
270 } else {
271 (branch.children.0, branch.children.1.insert(leaf))
272 },
273 ),
274 })
275 }
276 }
277 }
278}
279
280#[derive(Debug, Clone)]
284pub struct IterOverlapping<'a, T, U, V> {
285 aabb: Aabb<T, U>,
286 stack: Vec<&'a AabbTreeNode<T, U, V>>,
287}
288
289impl<'a, T, U, V> Iterator for IterOverlapping<'a, T, U, V>
290where
291 T: Copy + Num + PartialOrd,
292{
293 type Item = (&'a Aabb<T, U>, &'a V);
294
295 fn next(&mut self) -> Option<Self::Item> {
296 loop {
297 match self.stack.pop() {
298 None => return None,
299 Some(AabbTreeNode::Leaf(l)) => {
300 debug_assert!(l.aabb.intersects(&self.aabb));
301 return Some((&l.aabb, &l.value));
302 }
303 Some(AabbTreeNode::Branch(b)) => {
304 if self.aabb.intersects(b.children.0.aabb()) {
305 self.stack.push(&b.children.0);
306 }
307 if self.aabb.intersects(b.children.1.aabb()) {
308 self.stack.push(&b.children.1);
309 }
310 }
311 }
312 }
313 }
314}
315
316pub trait ToAabb<T, U> {
324 fn to_aabb(&self) -> Aabb<T, U>;
326}