1#![deny(missing_docs)]
2
3extern crate euclid;
10extern crate fnv;
11extern crate smallvec;
12
13use euclid::{TypedPoint2D, TypedRect, TypedSize2D};
14use fnv::FnvHashMap;
15use smallvec::{Array, SmallVec};
16use std::cmp::Ord;
17
18type Rect<S> = TypedRect<f32, S>;
19type Point<S> = TypedPoint2D<f32, S>;
20
21pub trait Spatial<S> {
26 fn aabb(&self) -> Rect<S>;
28}
29
30pub type QueryResult<B> = Result<(), B>;
32
33#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, Debug)]
40pub struct ItemId(u32);
41
42#[derive(Debug, Clone)]
43struct QuadTreeConfig {
44 allow_duplicates: bool,
45 max_children: usize,
46 min_children: usize,
47 max_depth: usize,
48 epsilon: f32,
49}
50
51#[derive(Clone)]
54pub struct QuadTree<T, S, A: Array<Item = (ItemId, Rect<S>)>> {
55 root: QuadNode<S, A>,
56 config: QuadTreeConfig,
57 id: u32,
58 elements: FnvHashMap<ItemId, (T, Rect<S>)>,
59}
60
61enum QuadNode<S, A: Array<Item = (ItemId, Rect<S>)>> {
62 Branch {
63 aabb: Rect<S>,
64 element_count: usize,
65 depth: usize,
66 in_all: SmallVec<A>,
67 children: [(Rect<S>, Box<QuadNode<S, A>>); 4],
68 },
69 Leaf {
70 aabb: Rect<S>,
71 depth: usize,
72 elements: SmallVec<A>,
73 },
74}
75
76impl<S, A: Array<Item = (ItemId, Rect<S>)>> Clone for QuadNode<S, A> {
77 fn clone(&self) -> QuadNode<S, A> {
78 match self {
79 &QuadNode::Branch {
80 ref aabb,
81 ref children,
82 ref in_all,
83 ref element_count,
84 ref depth,
85 } => {
86 let children = [
87 children[0].clone(),
88 children[1].clone(),
89 children[2].clone(),
90 children[3].clone(),
91 ];
92 QuadNode::Branch {
93 aabb: aabb.clone(),
94 children: children,
95 in_all: in_all.clone(),
96 element_count: element_count.clone(),
97 depth: depth.clone(),
98 }
99 }
100 &QuadNode::Leaf {
101 ref aabb,
102 ref elements,
103 ref depth,
104 } => QuadNode::Leaf {
105 aabb: aabb.clone(),
106 elements: elements.clone(),
107 depth: depth.clone(),
108 },
109 }
110 }
111}
112
113impl<T, S, A: Array<Item = (ItemId, Rect<S>)>> QuadTree<T, S, A> {
114 pub fn new(
126 size: Rect<S>,
127 allow_duplicates: bool,
128 min_children: usize,
129 max_children: usize,
130 max_depth: usize,
131 size_hint: usize,
132 ) -> QuadTree<T, S, A> {
133 QuadTree {
134 root: QuadNode::Leaf {
135 aabb: size,
136 elements: SmallVec::new(),
137 depth: 0,
138 },
139 config: QuadTreeConfig {
140 allow_duplicates: allow_duplicates,
141 max_children: max_children,
142 min_children: min_children,
143 max_depth: max_depth,
144 epsilon: 0.0001,
145 },
146 id: 0,
147 elements: std::collections::HashMap::with_capacity_and_hasher(
148 size_hint,
149 Default::default(),
150 ),
151 }
152 }
153
154 pub fn default(size: Rect<S>, size_hint: usize) -> QuadTree<T, S, A> {
163 QuadTree::new(size, true, 4, 16, 8, size_hint)
164 }
165
166 pub fn insert_with_box(&mut self, t: T, aabb: Rect<S>) -> Option<ItemId> {
168 debug_assert!(self.bounding_box().contains(&aabb.origin));
169 debug_assert!(self.bounding_box().contains(&aabb.bottom_right()));
170
171 let &mut QuadTree {
172 ref mut root,
173 ref config,
174 ref mut id,
175 ref mut elements,
176 } = self;
177
178 let item_id = ItemId(*id);
179 *id += 1;
180
181 if root.insert(item_id, aabb, config) {
182 elements.insert(item_id, (t, aabb));
183 return Some(item_id);
184 } else {
185 return None;
186 }
187 }
188
189 pub fn first(&self) -> Option<ItemId> {
192 self.elements.iter().next().map(|(id, _)| *id)
193 }
194
195 pub fn insert(&mut self, t: T) -> Option<ItemId>
197 where
198 T: Spatial<S>,
199 {
200 let b = t.aabb();
201 self.insert_with_box(t, b)
202 }
203
204 pub fn get(&self, id: ItemId) -> Option<&T> {
207 self.elements.get(&id).map(|&(ref a, _)| a)
208 }
209
210 pub fn query(&self, bounding_box: Rect<S>) -> SmallVec<[(&T, Rect<S>, ItemId); 3]>
214 where
215 T: ::std::fmt::Debug,
216 {
217 let mut out: SmallVec<[(_, _, _); 3]> = Default::default();
218 let _ = self.root
219 .query::<(), _>(bounding_box, &self.config, &mut |id, bb| {
220 out.push((&self.elements.get(&id).unwrap().0, bb, id));
221 Ok(())
222 });
223 out.sort_by_key(|&(_, _, id)| id);
224 out.dedup_by_key(|&mut (_, _, id)| id);
225 out
226 }
227
228 pub fn custom_query<'a, B, F>(&'a self, query_aabb: Rect<S>, on_find: &mut F) -> QueryResult<B>
231 where
232 F: FnMut(ItemId, Rect<S>) -> QueryResult<B>,
233 {
234 self.root.query(query_aabb, &self.config, on_find)
235 }
236
237 pub fn remove(&mut self, item_id: ItemId) -> Option<(T, Rect<S>)> {
241 match self.elements.remove(&item_id) {
242 Some((item, aabb)) => {
243 self.root.remove(item_id, aabb, &self.config);
244 Some((item, aabb))
245 }
246 None => None,
247 }
248 }
249
250 pub fn iter(&self) -> ::std::collections::hash_map::Iter<ItemId, (T, Rect<S>)> {
252 self.elements.iter()
253 }
254
255 pub fn inspect<F: FnMut(&Rect<S>, usize, bool)>(&self, mut f: F) {
263 self.root.inspect(&mut f);
264 }
265
266 pub fn len(&self) -> usize {
268 self.elements.len()
269 }
270
271 pub fn is_empty(&self) -> bool {
273 self.elements.is_empty()
274 }
275
276 pub fn bounding_box(&self) -> Rect<S> {
279 self.root.bounding_box()
280 }
281}
282
283impl<S, A: Array<Item = (ItemId, Rect<S>)>> QuadNode<S, A> {
284 fn bounding_box(&self) -> Rect<S> {
285 match self {
286 &QuadNode::Branch { ref aabb, .. } => aabb.clone(),
287 &QuadNode::Leaf { ref aabb, .. } => aabb.clone(),
288 }
289 }
290
291 fn new_leaf(aabb: Rect<S>, depth: usize) -> QuadNode<S, A> {
292 QuadNode::Leaf {
293 aabb: aabb,
294 elements: SmallVec::new(),
295 depth: depth,
296 }
297 }
298
299 fn inspect<F: FnMut(&Rect<S>, usize, bool)>(&self, f: &mut F) {
300 match self {
301 &QuadNode::Branch {
302 depth,
303 ref aabb,
304 ref children,
305 ..
306 } => {
307 f(aabb, depth, false);
308 for child in children {
309 child.1.inspect(f);
310 }
311 }
312 &QuadNode::Leaf {
313 depth, ref aabb, ..
314 } => {
315 f(aabb, depth, true);
316 }
317 }
318 }
319
320 fn insert(&mut self, item_id: ItemId, item_aabb: Rect<S>, config: &QuadTreeConfig) -> bool {
321 let mut into = None;
322 let mut did_insert = false;
323 match self {
324 &mut QuadNode::Branch {
325 ref aabb,
326 ref mut in_all,
327 ref mut children,
328 ref mut element_count,
329 ..
330 } => {
331 if item_aabb.contains(&midpoint(*aabb)) {
332 if config.allow_duplicates
335 || !in_all
336 .iter()
337 .any(|&(_, e_bb)| close_to_rect(e_bb, item_aabb, config.epsilon))
338 {
339 in_all.push((item_id, item_aabb));
340 did_insert = true;
341 *element_count += 1;
342 }
343 } else {
344 for &mut (aabb, ref mut child) in children {
345 if my_intersects(aabb, item_aabb)
346 || close_to_rect(aabb, item_aabb, config.epsilon)
347 {
348 if child.insert(item_id, item_aabb, config) {
349 *element_count += 1;
350 did_insert = true;
351 }
352 }
353 }
354 }
355 }
356
357 &mut QuadNode::Leaf {
358 aabb,
359 ref mut elements,
360 ref depth,
361 } => {
362 if elements.len() == config.max_children && *depth != config.max_depth {
363 let mut extracted_children = SmallVec::new();
365 ::std::mem::swap(&mut extracted_children, elements);
366 extracted_children.push((item_id, item_aabb));
367 did_insert = true;
368
369 let split = split_quad(aabb);
370 into = Some((
371 extracted_children,
372 QuadNode::Branch {
373 aabb: aabb,
374 in_all: SmallVec::new(),
375 children: [
376 (split[0], Box::new(QuadNode::new_leaf(split[0], depth + 1))),
377 (split[1], Box::new(QuadNode::new_leaf(split[1], depth + 1))),
378 (split[2], Box::new(QuadNode::new_leaf(split[2], depth + 1))),
379 (split[3], Box::new(QuadNode::new_leaf(split[3], depth + 1))),
380 ],
381 element_count: 0,
382 depth: *depth,
383 },
384 ));
385 } else {
386 if config.allow_duplicates
387 || !elements
388 .iter()
389 .any(|&(_, e_bb)| close_to_rect(e_bb, item_aabb, config.epsilon))
390 {
391 elements.push((item_id, item_aabb));
392 did_insert = true;
393 }
394 }
395 }
396 }
397
398 if let Some((extracted_children, new_node)) = into {
403 *self = new_node;
404 for (child_id, child_aabb) in extracted_children {
405 self.insert(child_id, child_aabb, config);
406 }
407 }
408 if !did_insert {
409 panic!(
410 "didn't insert {:?} into {:?}",
411 item_aabb,
412 self.bounding_box()
413 );
414 }
415 did_insert
416 }
417
418 fn remove(&mut self, item_id: ItemId, item_aabb: Rect<S>, config: &QuadTreeConfig) -> bool {
419 fn remove_from<S, A: Array<Item = (ItemId, Rect<S>)>>(
420 v: &mut SmallVec<A>,
421 item: ItemId,
422 ) -> bool {
423 if let Some(index) = v.iter().position(|a| a.0 == item) {
424 v.swap_remove(index);
425 true
426 } else {
427 false
428 }
429 }
430
431 let mut compact = None;
432 let removed = match self {
433 &mut QuadNode::Branch {
434 ref depth,
435 ref aabb,
436 ref mut in_all,
437 ref mut children,
438 ref mut element_count,
439 ..
440 } => {
441 let mut did_remove = false;
442
443 if item_aabb.contains(&midpoint(*aabb)) {
444 did_remove = remove_from(in_all, item_id);
445 } else {
446 for &mut (child_aabb, ref mut child_tree) in children {
447 if my_intersects(child_aabb, item_aabb)
448 || close_to_rect(child_aabb, item_aabb, config.epsilon)
449 {
450 did_remove |= child_tree.remove(item_id, item_aabb, config);
451 }
452 }
453 }
454
455 if did_remove {
456 *element_count -= 1;
457 if *element_count < config.min_children {
458 compact = Some((*element_count, *aabb, *depth));
459 }
460 }
461 did_remove
462 }
463
464 &mut QuadNode::Leaf {
465 ref mut elements, ..
466 } => remove_from(elements, item_id),
467 };
468
469 if let Some((size, aabb, depth)) = compact {
470 let mut elements: SmallVec<A> = SmallVec::with_capacity(size);
471 self.query::<(), _>(aabb, config, &mut |id, bb| {
472 elements.push((id, bb));
473 Ok(())
474 }).ok();
475 elements.sort_by(|&(id1, _), &(ref id2, _)| id1.cmp(id2));
476 elements.dedup();
477 *self = QuadNode::Leaf {
478 aabb: aabb,
479 elements: elements,
480 depth: depth,
481 };
482 }
483 removed
484 }
485
486 fn query<B, F>(
487 &self,
488 query_aabb: Rect<S>,
489 config: &QuadTreeConfig,
490 on_find: &mut F,
491 ) -> QueryResult<B>
492 where
493 F: FnMut(ItemId, Rect<S>) -> QueryResult<B>,
494 {
495 fn match_all<B, S, F, A: Array<Item = (ItemId, Rect<S>)>>(
496 elements: &SmallVec<A>,
497 query_aabb: Rect<S>,
498 on_find: &mut F,
499 config: &QuadTreeConfig,
500 ) -> QueryResult<B>
501 where
502 F: FnMut(ItemId, Rect<S>) -> QueryResult<B>,
503 {
504 for &(child_id, child_aabb) in elements {
505 if my_intersects(query_aabb, child_aabb)
506 || close_to_rect(query_aabb, child_aabb, config.epsilon)
507 {
508 on_find(child_id, child_aabb)?;
509 }
510 }
511 Ok(())
512 }
513
514 match self {
515 &QuadNode::Branch {
516 ref in_all,
517 ref children,
518 ..
519 } => {
520 match_all(in_all, query_aabb, on_find, config)?;
521
522 for &(child_aabb, ref child_tree) in children {
523 if my_intersects(query_aabb, child_aabb) {
524 child_tree.query(query_aabb, config, on_find)?;
525 }
526 }
527 }
528 &QuadNode::Leaf { ref elements, .. } => {
529 match_all(elements, query_aabb, on_find, config)?
530 }
531 }
532 Ok(())
533 }
534}
535
536impl<S> Spatial<S> for Rect<S> {
537 fn aabb(&self) -> Rect<S> {
538 *self
539 }
540}
541
542impl<S> Spatial<S> for Point<S> {
543 fn aabb(&self) -> Rect<S> {
544 Rect::new(*self, TypedSize2D::new(0.0, 0.0))
545 }
546}
547
548fn midpoint<S>(rect: Rect<S>) -> Point<S> {
549 let origin = rect.origin;
550 let half = rect.size.to_vector() / 2.0;
551 origin + half
552}
553
554fn my_intersects<S>(a: Rect<S>, b: Rect<S>) -> bool {
555 a.intersects(&b) || a.contains(&b.origin) || a.contains(&b.bottom_right())
556}
557
558fn split_quad<S>(rect: Rect<S>) -> [Rect<S>; 4] {
559 use euclid::vec2;
560 let origin = rect.origin;
561 let half = rect.size / 2.0;
562
563 [
564 Rect::new(origin, half),
565 Rect::new(origin + vec2(half.width, 0.0), half),
566 Rect::new(origin + vec2(0.0, half.height), half),
567 Rect::new(origin + vec2(half.width, half.height), half),
568 ]
569}
570
571fn close_to_point<S>(a: Point<S>, b: Point<S>, epsilon: f32) -> bool {
572 (a.x - b.x).abs() < epsilon && (a.y - b.y).abs() < epsilon
573}
574fn close_to_rect<S>(a: Rect<S>, b: Rect<S>, epsilon: f32) -> bool {
575 close_to_point(a.origin, b.origin, epsilon)
576 && close_to_point(a.bottom_right(), b.bottom_right(), epsilon)
577}
578
579#[test]
580fn weird_case() {
581 use euclid::*;
582 let bb = Rect::new(point2(0.0, 0.0), vec2(10.0, 10.0).to_size());
583 let query = Rect::new(point2(20.0, 0.0), vec2(1.0, 0.0).to_size());
584 assert!(!my_intersects(bb, query));
585}
586
587#[test]
588fn test_boundary_conditions() {
589 use euclid::*;
590
591 let total = Rect::new(point2(0.0, 0.0), vec2(10.0, 10.0).to_size());
592 let quads = split_quad(total);
593 let config = QuadTreeConfig {
594 allow_duplicates: true,
595 max_children: 200,
596 min_children: 0,
597 max_depth: 5,
598 epsilon: 0.001,
599 };
600
601 let mut branch: QuadNode<_, [(ItemId, Rect<_>); 32]> = QuadNode::Branch {
602 aabb: total,
603 in_all: SmallVec::new(),
604 element_count: 0,
605 depth: 1,
606 children: [
607 (
608 quads[0],
609 Box::new(QuadNode::Leaf {
610 aabb: quads[0],
611 elements: SmallVec::new(),
612 depth: 2,
613 }),
614 ),
615 (
616 quads[1],
617 Box::new(QuadNode::Leaf {
618 aabb: quads[1],
619 elements: SmallVec::new(),
620 depth: 2,
621 }),
622 ),
623 (
624 quads[2],
625 Box::new(QuadNode::Leaf {
626 aabb: quads[2],
627 elements: SmallVec::new(),
628 depth: 2,
629 }),
630 ),
631 (
632 quads[3],
633 Box::new(QuadNode::Leaf {
634 aabb: quads[3],
635 elements: SmallVec::new(),
636 depth: 2,
637 }),
638 ),
639 ],
640 };
641
642 assert!(branch.insert(
644 ItemId(0),
645 Rect::new(point2(0.0, 0.0), vec2(0.0, 0.0).to_size()),
646 &config
647 ));
648 assert!(branch.insert(
650 ItemId(0),
651 Rect::new(point2(5.0, 5.0), vec2(0.0, 0.0).to_size()),
652 &config
653 ));
654}
655
656impl<T: ::std::fmt::Debug, S, A: Array<Item = (ItemId, Rect<S>)>> ::std::fmt::Debug
657 for QuadTree<T, S, A>
658{
659 fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
660 formatter
661 .debug_struct("QuadTree")
662 .field("root", &self.root)
663 .field("config", &self.config)
664 .field("id", &self.id)
665 .field("elements", &self.elements)
666 .finish()
667 }
668}
669
670impl<S, A: Array<Item = (ItemId, Rect<S>)>> ::std::fmt::Debug for QuadNode<S, A> {
671 fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
672 match self {
673 &QuadNode::Branch {
674 ref aabb,
675 ref children,
676 ref in_all,
677 ref element_count,
678 ref depth,
679 } => formatter
680 .debug_struct("QuadNode")
681 .field("aabb", aabb)
682 .field("children", children)
683 .field("in_all", in_all)
684 .field("element_count", element_count)
685 .field("depth", depth)
686 .finish(),
687
688 &QuadNode::Leaf {
689 ref aabb,
690 ref elements,
691 ref depth,
692 } => formatter
693 .debug_struct("QuadNode")
694 .field("aabb", aabb)
695 .field("elements", elements)
696 .field("depth", depth)
697 .finish(),
698 }
699 }
700}