1use crate::{
2 algebra::Vector2,
3 math::Rect,
4 pool::{Handle, Pool},
5};
6use arrayvec::ArrayVec;
7
8pub enum QuadTreeNode<T> {
9 Leaf {
10 bounds: Rect<f32>,
11 ids: Vec<T>,
12 },
13 Branch {
14 bounds: Rect<f32>,
15 leaves: [Handle<QuadTreeNode<T>>; 4],
16 },
17}
18
19fn split_rect(rect: &Rect<f32>) -> [Rect<f32>; 4] {
20 let half_size = rect.size.scale(0.5);
21 [
22 Rect {
23 position: rect.position,
24 size: half_size,
25 },
26 Rect {
27 position: Vector2::new(rect.position.x + half_size.x, rect.position.y),
28 size: half_size,
29 },
30 Rect {
31 position: rect.position + half_size,
32 size: half_size,
33 },
34 Rect {
35 position: Vector2::new(rect.position.x, rect.position.y + half_size.y),
36 size: half_size,
37 },
38 ]
39}
40
41pub struct QuadTree<T> {
42 nodes: Pool<QuadTreeNode<T>>,
43 root: Handle<QuadTreeNode<T>>,
44 split_threshold: usize,
45}
46
47impl<T> Default for QuadTree<T> {
48 fn default() -> Self {
49 Self {
50 nodes: Default::default(),
51 root: Default::default(),
52 split_threshold: 16,
53 }
54 }
55}
56
57pub trait BoundsProvider {
58 type Id: Clone;
59
60 fn bounds(&self) -> Rect<f32>;
61
62 fn id(&self) -> Self::Id;
63}
64
65pub enum QuadTreeBuildError {
66 ReachedRecursionLimit,
69}
70
71#[derive(Clone)]
72struct Entry<I: Clone> {
73 id: I,
74 bounds: Rect<f32>,
75}
76
77fn build_recursive<I: Clone>(
78 nodes: &mut Pool<QuadTreeNode<I>>,
79 bounds: Rect<f32>,
80 entries: &[Entry<I>],
81 split_threshold: usize,
82 depth: usize,
83) -> Result<Handle<QuadTreeNode<I>>, QuadTreeBuildError> {
84 if depth >= 64 {
85 Err(QuadTreeBuildError::ReachedRecursionLimit)
86 } else if entries.len() <= split_threshold {
87 Ok(nodes.spawn(QuadTreeNode::Leaf {
88 bounds,
89 ids: entries.iter().map(|e| e.id.clone()).collect::<Vec<_>>(),
90 }))
91 } else {
92 let leaf_bounds = split_rect(&bounds);
93 let mut leaves = [Handle::NONE; 4];
94
95 for (leaf, &leaf_bounds) in leaves.iter_mut().zip(leaf_bounds.iter()) {
96 let leaf_entries = entries
97 .iter()
98 .filter_map(|e| {
99 if leaf_bounds.intersects(e.bounds) {
100 Some(e.clone())
101 } else {
102 None
103 }
104 })
105 .collect::<Vec<_>>();
106
107 *leaf = build_recursive(
108 nodes,
109 leaf_bounds,
110 &leaf_entries,
111 split_threshold,
112 depth + 1,
113 )?;
114 }
115
116 Ok(nodes.spawn(QuadTreeNode::Branch { bounds, leaves }))
117 }
118}
119
120impl<I: Clone> QuadTree<I> {
121 pub fn new<T: BoundsProvider<Id = I>>(
122 root_bounds: Rect<f32>,
123 objects: impl Iterator<Item = T>,
124 split_threshold: usize,
125 ) -> Result<Self, QuadTreeBuildError> {
126 let entries = objects
127 .filter_map(|o| {
128 if root_bounds.intersects(o.bounds()) {
129 Some(Entry {
130 id: o.id(),
131 bounds: o.bounds(),
132 })
133 } else {
134 None
135 }
136 })
137 .collect::<Vec<_>>();
138
139 let mut nodes = Pool::new();
140 let root = build_recursive(&mut nodes, root_bounds, &entries, split_threshold, 0)?;
141 Ok(Self {
142 nodes,
143 root,
144 split_threshold,
145 })
146 }
147
148 pub fn point_query<S: QueryStorage<Id = I>>(&self, point: Vector2<f32>, storage: &mut S) {
149 self.point_query_recursive(self.root, point, storage)
150 }
151
152 fn point_query_recursive<S: QueryStorage<Id = I>>(
153 &self,
154 node: Handle<QuadTreeNode<I>>,
155 point: Vector2<f32>,
156 storage: &mut S,
157 ) {
158 if node.is_some() {
159 match self.nodes.borrow(node) {
160 QuadTreeNode::Leaf { bounds, ids } => {
161 if bounds.contains(point) {
162 for id in ids {
163 if !storage.try_push(id.clone()) {
164 return;
165 }
166 }
167 }
168 }
169 QuadTreeNode::Branch { bounds, leaves } => {
170 if bounds.contains(point) {
171 for &leaf in leaves {
172 self.point_query_recursive(leaf, point, storage)
173 }
174 }
175 }
176 }
177 }
178 }
179
180 pub fn split_threshold(&self) -> usize {
181 self.split_threshold
182 }
183}
184
185pub trait QueryStorage {
186 type Id;
187
188 fn try_push(&mut self, id: Self::Id) -> bool;
189
190 fn clear(&mut self);
192}
193
194impl<I> QueryStorage for Vec<I> {
195 type Id = I;
196
197 fn try_push(&mut self, intersection: I) -> bool {
198 self.push(intersection);
199 true
200 }
201
202 fn clear(&mut self) {
203 self.clear()
204 }
205}
206
207impl<I, const CAP: usize> QueryStorage for ArrayVec<I, CAP> {
208 type Id = I;
209
210 fn try_push(&mut self, intersection: I) -> bool {
211 self.try_push(intersection).is_ok()
212 }
213
214 fn clear(&mut self) {
215 self.clear()
216 }
217}
218
219#[cfg(test)]
220mod test {
221 use crate::math::Rect;
222 use crate::quadtree::{BoundsProvider, QuadTree};
223
224 struct TestObject {
225 bounds: Rect<f32>,
226 id: usize,
227 }
228
229 impl BoundsProvider for &TestObject {
230 type Id = usize;
231
232 fn bounds(&self) -> Rect<f32> {
233 self.bounds
234 }
235
236 fn id(&self) -> Self::Id {
237 self.id
238 }
239 }
240
241 #[test]
242 fn test_quad_tree() {
243 let root_bounds = Rect::new(0.0, 0.0, 200.0, 200.0);
244 let objects = vec![
245 TestObject {
246 bounds: Rect::new(10.0, 10.0, 10.0, 10.0),
247 id: 0,
248 },
249 TestObject {
250 bounds: Rect::new(10.0, 10.0, 10.0, 10.0),
251 id: 1,
252 },
253 ];
254 assert!(QuadTree::new(root_bounds, objects.iter(), 1).is_err());
256
257 let objects = vec![
258 TestObject {
259 bounds: Rect::new(10.0, 10.0, 10.0, 10.0),
260 id: 0,
261 },
262 TestObject {
263 bounds: Rect::new(20.0, 20.0, 10.0, 10.0),
264 id: 1,
265 },
266 ];
267 assert!(QuadTree::new(root_bounds, objects.iter(), 1).is_ok());
268 }
269}