space_partitioning/quadtree/
quadtree.rs

1use crate::intersections::IntersectsWith;
2use crate::quadtree::aabb::AABB;
3use crate::quadtree::centered_aabb::CenteredAABB;
4use crate::quadtree::error::InsertError;
5use crate::quadtree::free_list::{self, FreeList, IndexType};
6use crate::quadtree::node::Node;
7use crate::quadtree::node_data::{NodeData, NodeIndexType};
8use crate::quadtree::node_info::NodeInfo;
9use crate::quadtree::node_list::NodeList;
10use crate::quadtree::quad_rect::QuadRect;
11use crate::quadtree::quadrants::Quadrants;
12use crate::quadtree::quadtree_element::QuadTreeElementNode;
13pub use crate::quadtree::quadtree_element::{ElementIdType, QuadTreeElement};
14use smallvec::SmallVec;
15
16// TODO: Add range query: Query using intersect_aabb() or intersect_generic()
17
18#[derive(Debug, Eq, PartialEq, Copy, Clone)]
19enum FindLeafHint {
20    /// A tree query, e.g. an intersection test.
21    /// These queries need to visit all leaves.
22    Query,
23    /// A tree mutation, i.e. insert or remove.
24    /// These queries skip exploration of child nodes whenever possible.
25    Mutate,
26}
27
28/// A QuadTree implementation as described in [Efficient Quadtrees](https://stackoverflow.com/a/48330314/195651).
29///
30/// # Remarks
31/// This tree uses integral coordinates only in order to speed up box-box intersection tests.
32pub struct QuadTree<ElementId = u32>
33where
34    ElementId: ElementIdType,
35{
36    /// Stores all the IDs fo the elements in the quadtree.
37    /// An element is only inserted once to the quadtree no matter how many cells it occupies.
38    element_ids: FreeList<ElementId>,
39    /// Stores all the rectangles of the elements in the quadtree.
40    /// An element is only inserted once to the quadtree no matter how many cells it occupies.
41    element_rects: FreeList<AABB>,
42    /// Stores all the element nodes in the quadtree.
43    /// For each cell occupied by a `QuadTreeElement`, we store
44    /// a `QuadTreeElementNode`.
45    element_nodes: FreeList<QuadTreeElementNode>,
46    /// Stores all the nodes in the quadtree. The first node in this
47    /// sequence is always the root.
48    nodes: Vec<Node>,
49    /// Stores the quadtree extents.
50    root_rect: QuadRect,
51    /// Stores the first free node in the quadtree to be reclaimed as 4
52    /// contiguous nodes at once. A value of `free_list::SENTINEL` indicates that the free
53    /// list is empty, at which point we simply insert 4 nodes to the
54    /// back of the nodes array.
55    free_node: free_list::IndexType,
56    /// Stores the maximum number of elements allowed before a node splits.
57    max_num_elements: u32,
58    /// We use this value to determine whether a node can be split.
59    smallest_cell_size: u32,
60    /// Stores the maximum depth allowed for the quadtree.
61    max_depth: u8,
62}
63
64impl<ElementId> QuadTree<ElementId>
65where
66    ElementId: ElementIdType,
67{
68    pub fn default() -> Self {
69        Self::new(QuadRect::default(), 8, 16, 1)
70    }
71
72    pub fn new(
73        root_rect: QuadRect,
74        max_depth: u8,
75        max_num_elements: u32,
76        smallest_cell_size: u32,
77    ) -> Self {
78        assert!(max_num_elements > 0);
79        assert!(smallest_cell_size > 0);
80        Self {
81            element_ids: FreeList::default(),
82            element_rects: FreeList::default(),
83            element_nodes: FreeList::default(),
84            nodes: vec![Node::default()],
85            root_rect,
86            free_node: free_list::SENTINEL,
87            max_depth,
88            max_num_elements,
89            smallest_cell_size,
90        }
91    }
92
93    pub fn insert(&mut self, element: QuadTreeElement<ElementId>) -> Result<(), InsertError> {
94        let element_coords = &element.rect;
95        if !self.root_rect.contains(element_coords) {
96            return Err(InsertError::OutOfBounds);
97        }
98
99        let max_num_elements = self.max_num_elements;
100
101        // Insert the actual element.
102        let element_idx = self.element_ids.insert(element.id);
103        let element_rect_idx = self.element_rects.insert(element.rect);
104        debug_assert_eq!(element_idx, element_rect_idx);
105
106        let mut to_process: SmallVec<[NodeData; 128]> =
107            smallvec::smallvec![self.get_root_node_data()];
108
109        while !to_process.is_empty() {
110            let node_data = to_process.pop().unwrap();
111
112            // Find the leaves
113            let mut leaves = NodeList::default(); // TODO: extract / pool?
114            self.find_leaves_aabb_fn(
115                node_data,
116                element_coords,
117                FindLeafHint::Mutate,
118                |_rect, nd| {
119                    leaves.push_back(nd);
120                },
121            );
122
123            // TODO: Execute in the callback
124            while !leaves.is_empty() {
125                let leaf = leaves.pop_back();
126
127                let (element_count, first_child_or_element) = {
128                    let node = &self.nodes[leaf.index as usize];
129                    debug_assert!(node.is_leaf());
130                    (node.element_count, node.first_child_or_element)
131                };
132
133                let can_split = leaf.can_split_further(self.smallest_cell_size, self.max_depth);
134                let node_is_full = element_count >= max_num_elements;
135
136                let must_store_element = !node_is_full || !can_split;
137                if must_store_element {
138                    // This leaf takes the element reference without further splitting.
139                    let element_node_idx = self.element_nodes.insert(QuadTreeElementNode {
140                        element_idx,
141                        next: first_child_or_element,
142                    });
143                    let node = &mut self.nodes[leaf.index as usize];
144                    node.first_child_or_element = element_node_idx;
145                    node.element_count += 1;
146                } else {
147                    // At this point we have to split the current node.
148                    // We push the leaf back onto the stack in order to try to
149                    // find a better insertion candidate from there.
150                    self.distribute_elements_to_child_nodes(&leaf);
151                    to_process.push(leaf);
152                }
153            }
154        }
155
156        Ok(())
157    }
158
159    /// Splits the specified [`parent`] node into four and distributes its
160    /// elements onto the newly created children.
161    fn distribute_elements_to_child_nodes(&mut self, parent: &NodeData) {
162        let first_child_index = self.ensure_child_nodes_exist();
163
164        let node = &mut self.nodes[parent.index as usize];
165        let mut element_node_index = node.get_first_element_node_index();
166        node.make_branch(first_child_index);
167
168        let mx = parent.crect.center_x;
169        let my = parent.crect.center_y;
170
171        // For each element in the list ...
172        while element_node_index != free_list::SENTINEL {
173            let element_node = unsafe { *self.element_nodes.at(element_node_index) };
174            let element = unsafe { *self.element_rects.at(element_node.element_idx) };
175
176            self.assign_element_to_child_nodes(
177                mx,
178                my,
179                first_child_index,
180                element_node.element_idx,
181                &element,
182            );
183
184            // The element was assigned to the child nodes - the former node
185            // can be removed (since the former leaf doesn't exist anymore).
186            self.element_nodes.erase(element_node_index);
187
188            element_node_index = element_node.next;
189        }
190    }
191
192    /// Recycles child nodes from the free list or creates
193    /// new child nodes if needed.
194    fn ensure_child_nodes_exist(&mut self) -> u32 {
195        if self.free_node != free_list::SENTINEL {
196            let node_index = self.free_node;
197            let next_free_node = self.nodes[node_index as usize].first_child_or_element;
198            self.nodes[node_index as usize] = Node::default();
199            self.free_node = next_free_node;
200            node_index
201        } else {
202            let node_index = self.nodes.len() as IndexType;
203            // The first node captures all elements spanning more than one child.
204            self.nodes.push(Node::default());
205            // The four childs.
206            for _ in 0..4 {
207                self.nodes.push(Node::default());
208            }
209            node_index
210        }
211    }
212
213    /// Assigns an element to the child nodes starting at `first_child_index`.
214    ///
215    /// # Params
216    /// * [`mx`] - The center X coordinate of the parent node.
217    /// * [`my`] - The center Y coordinate of the parent node.
218    /// * [`first_child_index`] - The index of the first child node.
219    /// * [`element_index`] - The index of the element.
220    /// * [`element`] - The element data.
221    fn assign_element_to_child_nodes(
222        &mut self,
223        mx: i32,
224        my: i32,
225        first_child_index: free_list::IndexType,
226        element_index: free_list::IndexType,
227        element_rect: &AABB,
228    ) {
229        let insert_left = element_rect.tl.x <= mx;
230        let insert_right = element_rect.br.x > mx;
231        let insert_top = element_rect.tl.y <= my;
232        let insert_bottom = element_rect.br.y > my;
233
234        // If an element covers more than one child node, we store it separately.
235        let covers_many = (insert_top & insert_bottom) | (insert_left & insert_right);
236        if covers_many {
237            self.insert_element_in_child_node(first_child_index + 0, element_index);
238            return;
239        }
240
241        // At this point, exactly one of the quadrants is selected.
242        debug_assert!(
243            (insert_top & insert_left)
244                || (insert_top & insert_right)
245                || (insert_bottom & insert_left)
246                || (insert_bottom && insert_right)
247        );
248        if insert_top & insert_left {
249            self.insert_element_in_child_node(first_child_index + 1, element_index);
250        } else if insert_top & insert_right {
251            self.insert_element_in_child_node(first_child_index + 2, element_index);
252        } else if insert_bottom & insert_left {
253            self.insert_element_in_child_node(first_child_index + 3, element_index);
254        } else if insert_bottom & insert_right {
255            self.insert_element_in_child_node(first_child_index + 4, element_index);
256        }
257    }
258
259    fn insert_element_in_child_node(&mut self, child_index: u32, element: free_list::IndexType) {
260        let node = &mut self.nodes[child_index as usize];
261        let element_node_index = self.element_nodes.insert(QuadTreeElementNode {
262            element_idx: element,
263            next: node.first_child_or_element,
264        });
265        node.first_child_or_element = element_node_index;
266        node.element_count += 1;
267    }
268
269    /// Removes the specified element.
270    ///
271    /// # Remarks
272    /// The element is located using its bounding box and identified using the ID.
273    /// Because of that, the bounding box of the element must not change until is was
274    /// removed from the tree.
275    ///
276    /// # Arguments
277    /// * [`element`] - The element to remove.
278    pub fn remove(&mut self, element: &QuadTreeElement<ElementId>) -> bool {
279        // Find the leaves containing the node.
280        let element_coords = &element.rect;
281        let root = self.get_root_node_data();
282
283        // The index of the element (if it was found).
284        let mut found_element_idx = free_list::SENTINEL;
285
286        let mut leaves = NodeList::default(); // TODO: extract / pool?
287        self.find_leaves_aabb_fn(root, element_coords, FindLeafHint::Mutate, |_rect, nd| {
288            leaves.push_back(nd);
289        });
290
291        // TODO: Execute in the callback?
292        while !leaves.is_empty() {
293            let leaf = leaves.pop_back();
294            let leaf_node_data = self.nodes[leaf.index as usize];
295
296            // The user may try to remove an element that was not in the tree (anymore).
297            if leaf_node_data.element_count == 0 {
298                continue;
299            }
300
301            // Used for debug assertion.
302            let mut element_found = false;
303
304            // Find the element in question.
305            let mut element_node_idx = leaf_node_data.first_child_or_element;
306            let mut prev_element_node_idx = element_node_idx;
307            let mut new_first_child_or_element = element_node_idx;
308
309            while element_node_idx != free_list::SENTINEL {
310                let elem_node = *unsafe { self.element_nodes.at(element_node_idx) };
311                let elem_id = unsafe { self.element_ids.at(elem_node.element_idx) };
312
313                if *elem_id == element.id {
314                    debug_assert!(!element_found);
315                    element_found = true;
316
317                    // If the element to be deleted is the first element,
318                    // we need to update the leaf.
319                    if leaf_node_data.first_child_or_element == element_node_idx {
320                        new_first_child_or_element = elem_node.next;
321                    }
322
323                    // Update the previous node if it exists.
324                    if element_node_idx != prev_element_node_idx {
325                        unsafe { self.element_nodes.at_mut(prev_element_node_idx) }.next =
326                            elem_node.next;
327                    }
328
329                    // Remove the reference from this leaf and
330                    // keep track of the element index in the list.
331                    self.element_nodes.erase(element_node_idx);
332                    debug_assert!(
333                        found_element_idx == free_list::SENTINEL
334                            || found_element_idx == elem_node.element_idx
335                    );
336                    found_element_idx = elem_node.element_idx;
337                }
338
339                prev_element_node_idx = element_node_idx;
340                element_node_idx = elem_node.next;
341
342                // We assume that a user never inserts the same element
343                // twice, therefore there is no need to visit the other
344                // elements of this node if we found the correct one.
345                //
346                // To assert that elements are only inserted once (per node),
347                // we allow further iteration during debugging.
348                #[cfg(not(debug_assertions))]
349                if element_found {
350                    break;
351                }
352            }
353
354            // Update the leaf node itself.
355            let node = &mut self.nodes[leaf.index as usize];
356            node.first_child_or_element = new_first_child_or_element;
357
358            // The user may try to remove an element that was not in the tree (anymore).
359            if element_found {
360                debug_assert!(node.element_count > 0);
361                node.element_count -= 1;
362            }
363        }
364
365        if found_element_idx != free_list::SENTINEL {
366            self.element_ids.erase(found_element_idx);
367            self.element_rects.erase(found_element_idx);
368            true
369        } else {
370            false
371        }
372    }
373
374    // TODO: Prefer specialization, see https://github.com/rust-lang/rust/issues/31844
375    fn find_leaves_aabb_fn<F>(
376        &self,
377        root: NodeData,
378        rect: &AABB,
379        hint: FindLeafHint,
380        mut callback: F,
381    ) where
382        F: FnMut(&AABB, NodeData),
383    {
384        let mut to_process = NodeList::default();
385        to_process.push_back(root);
386
387        while to_process.len() > 0 {
388            let nd = to_process.pop_back();
389
390            // If this node is a leaf, insert it to the list.
391            if self.nodes[nd.index as usize].is_leaf() {
392                callback(rect, nd);
393                continue;
394            }
395
396            let fc = self.nodes[nd.index as usize].get_first_child_node_index();
397
398            // Otherwise push the children that intersect the rectangle.
399            let quadrants = nd.crect.explore_quadrants_aabb(rect);
400            Self::collect_relevant_quadrants(&mut to_process, &nd, fc, quadrants, hint)
401        }
402    }
403
404    // TODO: Prefer specialization, see https://github.com/rust-lang/rust/issues/31844
405    fn find_leaves_generic_fn<T, F>(&self, root: NodeData, element: &T, mut callback: F)
406    where
407        T: IntersectsWith<AABB>,
408        F: FnMut(NodeData),
409    {
410        let mut to_process = NodeList::default();
411        to_process.push_back(root);
412
413        while to_process.len() > 0 {
414            let nd = to_process.pop_back();
415
416            // If this node is a leaf, insert it to the list.
417            if self.nodes[nd.index as usize].is_leaf() {
418                callback(nd);
419                continue;
420            }
421
422            let fc = self.nodes[nd.index as usize].get_first_child_node_index();
423
424            // Otherwise push the children that intersect the rectangle.
425            let quadrants = nd.crect.explore_quadrants_generic(element);
426            Self::collect_relevant_quadrants(
427                &mut to_process,
428                &nd,
429                fc,
430                quadrants,
431                FindLeafHint::Query,
432            )
433        }
434    }
435
436    /// Visits all leaf nodes in the tree, passing the node information to the provided closure.
437    pub fn visit_leaves<F>(&self, mut visit: F)
438    where
439        F: FnMut(NodeInfo),
440    {
441        let mut to_process = NodeList::default();
442        to_process.push_back(self.get_root_node_data());
443
444        while to_process.len() > 0 {
445            let nd = to_process.pop_back();
446
447            // If the index is divisible by 5, this node is referring to the
448            // parent itself. We skip enumerating this one since the proper child
449            // nodes will be enumerated individually.
450            // We subtract one to account for the root node.
451            let is_this_node = nd.index > 0 && ((nd.index - 1) % 5) == 0;
452            if is_this_node {
453                debug_assert!(self.nodes[nd.index as usize].is_leaf());
454                continue;
455            }
456
457            let node = &self.nodes[nd.index as usize];
458            if node.is_leaf() {
459                visit(NodeInfo::from(nd, node.element_count));
460                continue;
461            }
462
463            let fc = self.nodes[nd.index as usize].get_first_child_node_index();
464            Self::collect_relevant_quadrants(
465                &mut to_process,
466                &nd,
467                fc,
468                Quadrants::all(),
469                FindLeafHint::Query,
470            )
471        }
472    }
473
474    /// Collects the relevant quadrant nodes.
475    #[inline]
476    fn collect_relevant_quadrants(
477        to_process: &mut NodeList,
478        nd: &NodeData,
479        first_child_id: u32,
480        quadrants: Quadrants,
481        hint: FindLeafHint,
482    ) {
483        // Opportunistically calculate the new child rects.
484        // With inlining in place the compiler should be able to simplify some calculations.
485        let split_quadrants = nd.crect.split_quadrants();
486
487        match hint {
488            FindLeafHint::Query => Self::collect_relevant_quadrants_for_query(
489                to_process,
490                nd.depth,
491                first_child_id,
492                quadrants,
493                &split_quadrants,
494            ),
495            FindLeafHint::Mutate => Self::collect_relevant_quadrants_for_mutation(
496                to_process,
497                nd.depth,
498                first_child_id,
499                quadrants,
500                &split_quadrants,
501            ),
502        }
503    }
504
505    /// Like [`collect_relevant_quadrants_for_query()`] but optimized for mutations (inserts, deletes).
506    fn collect_relevant_quadrants_for_mutation(
507        to_process: &mut NodeList,
508        depth: u8,
509        first_child_id: u32,
510        quadrants: Quadrants,
511        split_quadrants: &[CenteredAABB; 5],
512    ) {
513        let offset = quadrants.mutation_index();
514        debug_assert!(offset <= 4);
515
516        // The "this" node at offset 0 cannot be split.
517        let can_split = offset > 0;
518
519        // The child depth only increases for the non-"this" node.
520        let child_depth = depth + (1 - quadrants.this() as u8);
521
522        to_process.push_back(NodeData::new(
523            split_quadrants[offset as usize],
524            first_child_id + offset,
525            child_depth,
526            can_split,
527        ));
528    }
529
530    /// Like [`collect_relevant_quadrants_for_mutation()`] but optimized for queries.
531    fn collect_relevant_quadrants_for_query(
532        to_process: &mut NodeList,
533        depth: u8,
534        first_child_id: u32,
535        quadrants: Quadrants,
536        split_quadrants: &[CenteredAABB; 5],
537    ) {
538        let child_depth = depth + 1;
539
540        for offset in (1..=4).rev() {
541            if quadrants.at(offset) {
542                to_process.push_back(NodeData::new(
543                    split_quadrants[offset as usize],
544                    first_child_id + offset as u32,
545                    child_depth,
546                    true,
547                ));
548            }
549        }
550
551        // In intersection tests we always need to explore the self node.
552        to_process.push_back(NodeData::new(
553            split_quadrants[0],
554            first_child_id + 0,
555            // The "this" node is at the same depth and cannot split.
556            depth,
557            false,
558        ));
559    }
560
561    /// Prunes unused child nodes from the tree.
562    ///
563    /// # Remarks
564    /// The tree is never pruned automatically for performance reasons. Call
565    /// this method after all elements were removed or updated.
566    pub fn cleanup(&mut self) -> bool {
567        // Only process the root if it is not a leaf.
568        if self.nodes[0].is_leaf() {
569            return false;
570        }
571
572        let mut tree_compacted = false;
573
574        // Initialize the stack of nodes to be processed with the index of the root node.
575        // TODO: revisit the small list size, check element count
576        let mut to_process: SmallVec<[NodeIndexType; 128]> = smallvec::smallvec![0];
577
578        while !to_process.is_empty() {
579            let node_index = to_process.pop().unwrap();
580            let first_child_index = self.nodes[node_index as usize].get_first_child_node_index();
581
582            // Loop through the children.
583            let mut num_empty_leaves = 0usize;
584            for j in 0..5 {
585                let child_index = first_child_index + j;
586                let child = &self.nodes[child_index as usize];
587
588                // TODO: Compact nodes when the number of elements in child is less than allowed maximum.
589
590                // Increment empty leaf count if the child is an empty
591                // leaf. Otherwise if the child is a branch, add it to
592                // the stack to be processed in the next iteration.
593                if child.is_empty() {
594                    num_empty_leaves += 1;
595                } else if child.is_branch() {
596                    to_process.push(child_index);
597                }
598            }
599
600            // If all the children were empty leaves, remove them and
601            // make this node the new empty leaf.
602            if num_empty_leaves == 5 {
603                // Push all 5 children to the free list.
604                // (We don't change the indexes of the 2nd to 4th child because
605                // child nodes are always processed together.)
606                self.nodes[first_child_index as usize].first_child_or_element = self.free_node;
607                self.free_node = first_child_index;
608
609                // Make this node the new empty leaf.
610                self.nodes[node_index as usize].make_empty_leaf();
611
612                tree_compacted = true;
613            }
614        }
615
616        tree_compacted
617    }
618
619    /// Counts the total number of references. This number should be at least
620    /// the number of elements inserted; it will be higher if elements
621    /// span multiple cells.
622    #[allow(dead_code)]
623    pub(crate) fn count_element_references(&self) -> usize {
624        let mut to_process: SmallVec<[usize; 128]> = smallvec::smallvec![0];
625        let mut count = 0usize;
626        while !to_process.is_empty() {
627            let index = to_process.pop().unwrap();
628            let node = &self.nodes[index];
629            if node.is_branch() {
630                for j in 0..5 {
631                    to_process.push((node.first_child_or_element + j) as usize);
632                }
633            } else {
634                count += node.element_count as usize;
635            }
636        }
637
638        debug_assert!(count >= self.element_ids.debug_len());
639        debug_assert!(count >= self.element_rects.debug_len());
640        count
641    }
642
643    #[inline]
644    fn get_root_node_data(&self) -> NodeData {
645        NodeData::new_from_root(&self.root_rect, true)
646    }
647
648    /// Returns the set of IDs that occupy space within the
649    /// specified bounding box.
650    ///
651    /// # Arguments
652    /// * [`rect`] - The rectangle to test for.
653    #[inline]
654    pub fn intersect_aabb(&self, rect: &AABB) -> Vec<ElementId> {
655        let root = self.get_root_node_data();
656        let mut node_set = Vec::with_capacity(128);
657
658        self.find_leaves_aabb_fn(root, rect, FindLeafHint::Query, |rect, nd| {
659            self.intersect_from_leaf(rect, nd, &mut |id| {
660                node_set.push(id);
661            });
662        });
663
664        node_set
665    }
666
667    /// Calls a function for each ID that occupies space within the
668    /// specified bounding box. The function may be called multiple
669    /// times for the same ID.
670    ///
671    /// # Arguments
672    /// * [`rect`] - The rectangle to test for.
673    /// * [`candidate_fn`] - The function called for each candidate element's ID.
674    #[inline]
675    pub fn intersect_aabb_fn<F>(&self, rect: &AABB, mut candidate_fn: F)
676    where
677        F: FnMut(ElementId),
678    {
679        let root = self.get_root_node_data();
680        self.find_leaves_aabb_fn(root, rect, FindLeafHint::Query, move |rect, nd| {
681            self.intersect_from_leaf(rect, nd, &mut |id| {
682                candidate_fn(id);
683            });
684        });
685    }
686
687    /// Returns the set of IDs that occupy space within the
688    /// specified bounding box.
689    ///
690    /// # Arguments
691    /// * [`element`] - The element to test for.
692    #[inline]
693    pub fn intersect_generic<T>(&self, element: &T) -> Vec<ElementId>
694    where
695        T: IntersectsWith<AABB>,
696    {
697        let root = self.get_root_node_data();
698        let mut node_set = Vec::with_capacity(128);
699
700        self.find_leaves_generic_fn(root, element, |nd| {
701            self.intersect_from_leaf(element, nd, &mut |id| {
702                node_set.push(id);
703            });
704        });
705
706        // TODO: Ensure no element occurs twice
707        node_set
708    }
709
710    /// Calls a function for each ID that occupies space within the
711    /// specified bounding box. The function may be called multiple
712    /// times for the same ID.
713    ///
714    /// # Arguments
715    /// * [`element`] - The element to test for.
716    /// * [`candidate_fn`] - The function called for each candidate element's ID.
717    #[inline]
718    pub fn intersect_generic_fn<T, F>(&self, element: &T, mut candidate_fn: F)
719    where
720        T: IntersectsWith<AABB>,
721        F: FnMut(ElementId),
722    {
723        let root = self.get_root_node_data();
724        self.find_leaves_generic_fn(root, element, move |nd| {
725            self.intersect_from_leaf(element, nd, &mut |id| {
726                candidate_fn(id);
727            });
728        });
729    }
730
731    #[inline]
732    fn intersect_from_leaf<T, F>(&self, element: &T, leaf_data: NodeData, mut candidate_fn: F)
733    where
734        T: IntersectsWith<AABB>,
735        F: FnMut(ElementId),
736    {
737        let leaf = self.nodes[leaf_data.index as usize];
738        debug_assert!(leaf.is_leaf());
739
740        let mut elem_node_idx = leaf.first_child_or_element;
741        while elem_node_idx != free_list::SENTINEL {
742            let elem_node = unsafe { self.element_nodes.at(elem_node_idx) };
743            let elem_rect = unsafe { self.element_rects.at(elem_node.element_idx) };
744
745            // Depending on the size of the quadrant, the candidate element
746            // might still not be covered by the search rectangle.
747            if element.intersects_with(&elem_rect) {
748                let elem_id = *unsafe { self.element_ids.at(elem_node.element_idx) };
749                candidate_fn(elem_id);
750            }
751
752            elem_node_idx = elem_node.next;
753        }
754    }
755
756    /// Collects all element IDs stored in the tree by visiting all cells.
757    #[allow(dead_code)]
758    pub(crate) fn collect_ids(&self) -> Vec<ElementId> {
759        let aabb: AABB = self.root_rect.into();
760        self.intersect_aabb(&aabb)
761    }
762}
763
764#[cfg(test)]
765pub(crate) fn build_test_tree() -> QuadTree {
766    let quad_rect = QuadRect::new(-20, -20, 40, 40);
767    let mut tree = QuadTree::new(quad_rect, 1, 1, 1);
768    // top-left
769    tree.insert(QuadTreeElement::new(1000, AABB::new(-15, -15, -5, -5)))
770        .expect("insert should work");
771    tree.insert(QuadTreeElement::new(1001, AABB::new(-20, -20, -18, -18)))
772        .expect("insert should work");
773    // top-right
774    tree.insert(QuadTreeElement::new(2000, AABB::new(5, -15, 15, -5)))
775        .expect("insert should work");
776    // bottom-left
777    tree.insert(QuadTreeElement::new(3000, AABB::new(-15, 5, -5, 15)))
778        .expect("insert should work");
779    // bottom-right
780    tree.insert(QuadTreeElement::new(4000, AABB::new(5, 5, 15, 15)))
781        .expect("insert should work");
782    // center
783    tree.insert(QuadTreeElement::new(5000, AABB::new(-5, -5, 5, 5)))
784        .expect("insert should work");
785
786    // The depth of 1 limits the tree to four quadrants.
787    // Each of the first five elements creates a single reference
788    // in each of the quadrants. The "center" element covers
789    // all four quadrants, and therefore adds another four references.
790    assert_eq!(tree.count_element_references(), 6);
791
792    // Ensure we have the exact elements inserted.
793    let inserted_ids = tree.collect_ids();
794    assert_eq!(inserted_ids.len(), 6);
795    assert!(inserted_ids.contains(&1000));
796    assert!(inserted_ids.contains(&1001));
797    assert!(inserted_ids.contains(&2000));
798    assert!(inserted_ids.contains(&3000));
799    assert!(inserted_ids.contains(&4000));
800    assert!(inserted_ids.contains(&5000));
801
802    tree
803}
804
805#[cfg(test)]
806mod test {
807    use super::*;
808
809    #[test]
810    fn cleanup_works() {
811        let quad_rect = QuadRect::new(-20, -20, 40, 40);
812        let mut tree = QuadTree::new(quad_rect, 1, 1, 1);
813        // top-left
814        tree.insert(QuadTreeElement::new(1000, AABB::new(-15, -15, -5, -5)))
815            .expect("insert should work");
816        tree.insert(QuadTreeElement::new(1001, AABB::new(-20, -20, -18, -18)))
817            .expect("insert should work");
818        // top-right
819        tree.insert(QuadTreeElement::new(2000, AABB::new(5, -15, 15, -5)))
820            .expect("insert should work");
821        // bottom-left
822        tree.insert(QuadTreeElement::new(3000, AABB::new(-15, 5, -5, 15)))
823            .expect("insert should work");
824        // bottom-right
825        tree.insert(QuadTreeElement::new(4000, AABB::new(5, 5, 15, 15)))
826            .expect("insert should work");
827
828        // Similar to index test.
829        assert_eq!(tree.collect_ids().len(), 5);
830
831        // center
832        tree.insert(QuadTreeElement::new(5000, AABB::new(-5, -5, 5, 5)))
833            .expect("insert should work");
834
835        // Similar to index test.
836        assert_eq!(tree.collect_ids().len(), 6);
837        assert_eq!(tree.count_element_references(), 6);
838
839        // Erase the all elements.
840        assert!(tree.remove(&QuadTreeElement::new(1000, AABB::new(-15, -15, -5, -5))));
841        assert!(tree.remove(&QuadTreeElement::new(1001, AABB::new(-20, -20, -18, -18))));
842        assert!(tree.remove(&QuadTreeElement::new(2000, AABB::new(5, -15, 15, -5))));
843        assert!(tree.remove(&QuadTreeElement::new(3000, AABB::new(-15, 5, -5, 15))));
844        assert!(tree.remove(&QuadTreeElement::new(4000, AABB::new(5, 5, 15, 15))));
845        assert!(tree.remove(&QuadTreeElement::new(5000, AABB::new(-5, -5, 5, 5))));
846        assert_eq!(tree.collect_ids().len(), 0);
847        assert_eq!(tree.count_element_references(), 0);
848
849        // Since cleanup wasn't called yet, the root is still considered a branch
850        // with four child nodes.
851        assert!(tree.nodes[0].is_branch());
852        assert_eq!(tree.nodes[0].first_child_or_element, 1);
853
854        // Cleanup does something now.
855        assert!(tree.cleanup());
856
857        // Since all four child nodes of the root were empty,
858        // cleanup has removed them. The root node is now a leaf
859        // with zero elements.
860        assert!(tree.nodes[0].is_leaf());
861        assert_eq!(tree.nodes[0].element_count, 0);
862    }
863}