1use std::ops::Range;
2use crate::SpatialPartitioner;
3use crate::util::in_range;
4
5pub struct QuadTree<Data: Copy> {
6 node: QuadTreeNode<Data>,
7
8 capacity: u16,
9
10 x: Range<f64>,
11 y: Range<f64>,
12
13 count: usize,
14}
15
16impl<Data: Copy> QuadTree<Data> {
17 pub fn with_capacity(x: Range<f64>, y: Range<f64>, capacity: u16) -> QuadTree<Data> {
25 QuadTree {
26 node: QuadTreeNode::new(((x.end - x.start) / 2.0, (y.end - y.start) / 2.0), ((x.end - x.start), (y.end - y.start)), capacity),
27 capacity,
28 x,
29 y,
30 count: 0,
31 }
32 }
33
34 pub fn node(&self) -> &QuadTreeNode<Data> {
40 &self.node
41 }
42}
43
44impl<Data: Copy> SpatialPartitioner<Data> for QuadTree<Data> {
45 fn new(x: Range<f64>, y: Range<f64>) -> Self {
49 QuadTree::with_capacity(x, y, 50)
50 }
51
52 fn insert(&mut self, position: (f64, f64), data: Data) {
53 if position.0 < self.x.start || position.0 >= self.x.end || position.1 < self.y.start || position.1 >= self.y.end {
54 panic!("tried to insert position into QuadTree which was out of bounce")
55 }
56
57 self.insert_unchecked(position, data);
58 }
59
60 fn insert_unchecked(&mut self, position: (f64, f64), data: Data) {
61 self.count += 1;
62 self.node.insert(position, data);
63 }
64
65 fn count(&self) -> usize {
66 self.count
67 }
68
69 fn clear(&mut self) {
70 self.node = QuadTreeNode::new(((self.x.start - self.x.end) / 2.0, (self.y.start - self.y.end) / 2.0), ((self.x.start - self.x.end), (self.y.start - self.y.end)), self.capacity);
71 self.count = 0;
72 }
73
74 fn in_circle(&self, position: (f64, f64), radius: f64) -> Vec<Data> {
75 let mut data = Vec::new();
76
77 self.node.in_circle(position, radius, &mut data, false);
78
79 data
80 }
81}
82
83pub struct QuadTreeNode<Data: Copy> {
84 data: Vec<((f64, f64), Data)>,
85 capacity: u16,
86
87 is_full: bool,
88
89 nodes: Option<Box<[QuadTreeNode<Data>; 4]>>,
90
91 center: (f64, f64),
92 size: (f64, f64),
93}
94
95impl<Data: Copy> QuadTreeNode<Data> {
96 pub fn nodes(&self) -> &Option<Box<[QuadTreeNode<Data>; 4]>> {
102 &self.nodes
103 }
104
105 pub fn data(&self) -> &Vec<((f64, f64), Data)> {
111 &self.data
112 }
113
114 pub fn center(&self) -> (f64, f64) {
120 self.center
121 }
122
123 pub fn size(&self) -> (f64, f64) {
129 self.size
130 }
131
132 fn new(center: (f64, f64), size: (f64, f64), capacity: u16) -> QuadTreeNode<Data> {
133 QuadTreeNode {
134 data: Vec::new(),
135 nodes: None,
136 center,
137 size,
138 capacity,
139
140 is_full: false,
141 }
142 }
143
144 fn insert(&mut self, position: (f64, f64), data: Data) {
145 if !self.is_full {
146 self.data.push((position, data));
147
148 if self.data.len() >= self.capacity as usize {
149 self.is_full = true;
150
151 self.nodes = Some(Box::new([
152 QuadTreeNode::new((self.center.0 - self.size.0 / 2.0, self.center.1 - self.size.1 / 2.0), (self.size.0 / 2.0, self.size.1 / 2.0), self.capacity),
153 QuadTreeNode::new((self.center.0 - self.size.0 / 2.0, self.center.1 + self.size.1 / 2.0), (self.size.0 / 2.0, self.size.1 / 2.0), self.capacity),
154 QuadTreeNode::new((self.center.0 + self.size.0 / 2.0, self.center.1 - self.size.1 / 2.0), (self.size.0 / 2.0, self.size.1 / 2.0), self.capacity),
155 QuadTreeNode::new((self.center.0 + self.size.0 / 2.0, self.center.1 + self.size.1 / 2.0), (self.size.0 / 2.0, self.size.1 / 2.0), self.capacity),
156 ]))
157 }
158 } else {
159 let i = self.get_index(position);
160 self.nodes.as_mut().unwrap()[i].insert(position, data);
161 }
162 }
163
164 fn in_circle(&self, position: (f64, f64), radius: f64, data: &mut Vec<Data>, in_circle: bool) {
165 if in_circle || (self.data.len() > 4 && self.in_box(position, radius)) {
166 data.reserve(self.data.len());
167
168 data.extend(self.data.iter().map(|x| x.1));
169
170 if self.nodes.is_none() {
171 return;
172 }
173
174 self.nodes.as_ref().unwrap()[0].in_circle(position, radius, data, true);
175 self.nodes.as_ref().unwrap()[1].in_circle(position, radius, data, true);
176 self.nodes.as_ref().unwrap()[2].in_circle(position, radius, data, true);
177 self.nodes.as_ref().unwrap()[3].in_circle(position, radius, data, true);
178 } else {
179 for elements in &self.data {
180 if in_range(elements.0, position, radius) {
181 data.push(elements.1)
182 }
183 }
184
185 if self.nodes.is_none() {
186 return;
187 }
188
189 let mut indexes = [false; 4];
190
191 indexes[self.get_index((position.0 - radius, position.1 - radius))] = true;
192 indexes[self.get_index((position.0 - radius, position.1 + radius))] = true;
193 indexes[self.get_index((position.0 + radius, position.1 - radius))] = true;
194 indexes[self.get_index((position.0 + radius, position.1 + radius))] = true;
195
196 for (i, bool) in indexes.iter().enumerate() {
197 if *bool {
198 self.nodes.as_ref().unwrap()[i].in_circle(position, radius, data, false);
199 }
200 }
201 }
202 }
203
204 fn in_box(&self, location: (f64, f64), radius: f64) -> bool {
205 if in_range(location, (self.center.0 - self.size.0, self.center.1 + self.size.1), radius)
206 && in_range(location, (self.center.0 + self.size.0, self.center.1 + self.size.1), radius)
207 && in_range(location, (self.center.0 - self.size.0, self.center.1 - self.size.1), radius)
208 && in_range(location, (self.center.0 + self.size.0, self.center.1 - self.size.1), radius) {
209 return true;
210 }
211
212 false
213 }
214
215 fn get_index(&self, location: (f64, f64)) -> usize {
216 if self.center.0 > location.0 {
217 if self.center.1 > location.1 {
218 0
219 } else {
220 1
221 }
222 } else if self.center.1 > location.1 {
223 2
224 } else {
225 3
226 }
227 }
228}