1use bytemuck::cast_slice_mut;
2use geo_traits::{CoordTrait, RectTrait};
3
4use crate::indices::MutableIndices;
5use crate::r#type::IndexableNum;
6use crate::rtree::constants::VERSION;
7use crate::rtree::index::{RTree, RTreeMetadata};
8use crate::rtree::sort::{Sort, SortParams};
9
10pub const DEFAULT_RTREE_NODE_SIZE: u16 = 16;
12
13pub struct RTreeBuilder<N: IndexableNum> {
26 data: Vec<u8>,
28 metadata: RTreeMetadata<N>,
29 pos: usize,
30 min_x: N,
31 min_y: N,
32 max_x: N,
33 max_y: N,
34}
35
36impl<N: IndexableNum> RTreeBuilder<N> {
37 pub fn new(num_items: u32) -> Self {
39 Self::new_with_node_size(num_items, DEFAULT_RTREE_NODE_SIZE)
40 }
41
42 pub fn new_with_node_size(num_items: u32, node_size: u16) -> Self {
44 let metadata = RTreeMetadata::new(num_items, node_size);
45 Self::from_metadata(metadata)
46 }
47
48 pub fn from_metadata(metadata: RTreeMetadata<N>) -> Self {
50 let mut data = vec![0; metadata.data_buffer_length()];
51
52 data[0] = 0xfb;
54 data[1] = (VERSION << 4) + N::TYPE_INDEX;
55 cast_slice_mut(&mut data[2..4])[0] = metadata.node_size();
56 cast_slice_mut(&mut data[4..8])[0] = metadata.num_items();
57
58 Self {
59 data,
60 metadata,
61 pos: 0,
62 min_x: N::max_value(),
63 min_y: N::max_value(),
64 max_x: N::min_value(),
65 max_y: N::min_value(),
66 }
67 }
68
69 pub fn metadata(&self) -> &RTreeMetadata<N> {
71 &self.metadata
72 }
73
74 #[inline]
81 pub fn add(&mut self, min_x: N, min_y: N, max_x: N, max_y: N) -> u32 {
82 let index = self.pos >> 2;
83 let (boxes, mut indices) = split_data_borrow(&mut self.data, &self.metadata);
84
85 indices.set(index, index);
86 boxes[self.pos] = min_x;
87 self.pos += 1;
88 boxes[self.pos] = min_y;
89 self.pos += 1;
90 boxes[self.pos] = max_x;
91 self.pos += 1;
92 boxes[self.pos] = max_y;
93 self.pos += 1;
94
95 if min_x < self.min_x {
96 self.min_x = min_x
97 };
98 if min_y < self.min_y {
99 self.min_y = min_y
100 };
101 if max_x > self.max_x {
102 self.max_x = max_x
103 };
104 if max_y > self.max_y {
105 self.max_y = max_y
106 };
107
108 index.try_into().unwrap()
109 }
110
111 #[inline]
118 pub fn add_rect(&mut self, rect: &impl RectTrait<T = N>) -> u32 {
119 self.add(
120 rect.min().x(),
121 rect.min().y(),
122 rect.max().x(),
123 rect.max().y(),
124 )
125 }
126
127 pub fn finish<S: Sort<N>>(mut self) -> RTree<N> {
135 assert_eq!(
136 self.pos >> 2,
137 self.metadata.num_items() as usize,
138 "Added {} items when expected {}.",
139 self.pos >> 2,
140 self.metadata.num_items()
141 );
142
143 let (boxes, mut indices) = split_data_borrow(&mut self.data, &self.metadata);
144
145 if self.metadata.num_items() <= 1 {
146 return RTree {
148 buffer: self.data,
149 metadata: self.metadata,
150 };
151 }
152
153 if self.metadata.num_items() as usize <= self.metadata.node_size() as usize {
154 boxes[self.pos] = self.min_x;
156 self.pos += 1;
157 boxes[self.pos] = self.min_y;
158 self.pos += 1;
159 boxes[self.pos] = self.max_x;
160 self.pos += 1;
161 boxes[self.pos] = self.max_y;
162 self.pos += 1;
163
164 return RTree {
165 buffer: self.data,
166 metadata: self.metadata,
167 };
168 }
169
170 let mut sort_params = SortParams {
171 num_items: self.metadata.num_items() as usize,
172 node_size: self.metadata.node_size() as usize,
173 min_x: self.min_x,
174 min_y: self.min_y,
175 max_x: self.max_x,
176 max_y: self.max_y,
177 };
178 S::sort(&mut sort_params, boxes, &mut indices);
179
180 {
181 let mut pos = 0;
183 for end in self.metadata.level_bounds()[..self.metadata.level_bounds().len() - 1].iter()
184 {
185 while pos < *end {
186 let node_index = pos;
187
188 let mut node_min_x = boxes[pos];
190 pos += 1;
191 let mut node_min_y = boxes[pos];
192 pos += 1;
193 let mut node_max_x = boxes[pos];
194 pos += 1;
195 let mut node_max_y = boxes[pos];
196 pos += 1;
197 for _ in 1..self.metadata.node_size() {
198 if pos >= *end {
199 break;
200 }
201
202 if boxes[pos] < node_min_x {
203 node_min_x = boxes[pos];
204 }
205 pos += 1;
206 if boxes[pos] < node_min_y {
207 node_min_y = boxes[pos];
208 }
209 pos += 1;
210 if boxes[pos] > node_max_x {
211 node_max_x = boxes[pos]
212 }
213 pos += 1;
214 if boxes[pos] > node_max_y {
215 node_max_y = boxes[pos]
216 }
217 pos += 1;
218 }
219
220 indices.set(self.pos >> 2, node_index);
222 boxes[self.pos] = node_min_x;
223 self.pos += 1;
224 boxes[self.pos] = node_min_y;
225 self.pos += 1;
226 boxes[self.pos] = node_max_x;
227 self.pos += 1;
228 boxes[self.pos] = node_max_y;
229 self.pos += 1;
230 }
231 }
232 }
233
234 RTree {
235 buffer: self.data,
236 metadata: self.metadata,
237 }
238 }
239}
240
241fn split_data_borrow<'a, N: IndexableNum>(
243 data: &'a mut [u8],
244 metadata: &'a RTreeMetadata<N>,
245) -> (&'a mut [N], MutableIndices<'a>) {
246 let (boxes_buf, indices_buf) = data[8..].split_at_mut(metadata.nodes_byte_length);
247 debug_assert_eq!(indices_buf.len(), metadata.indices_byte_length);
248
249 let boxes = cast_slice_mut(boxes_buf);
250 let indices = MutableIndices::new(indices_buf, metadata.num_nodes());
251 (boxes, indices)
252}
253
254#[cfg(test)]
255mod test {
256 use crate::rtree::sort::{HilbertSort, STRSort};
257 use crate::rtree::RTreeIndex;
258
259 use super::*;
260
261 #[test]
262 fn does_not_panic_length_1_tree() {
263 let mut builder = RTreeBuilder::<f64>::new(1);
264 builder.add(-20., -20., 1020., 1020.);
265 let tree = builder.finish::<HilbertSort>();
266 let result = tree.search(0., 0., 0., 0.);
267 assert_eq!(result, vec![0]);
268 }
269
270 #[test]
271 fn build_str_index_with_various_items() {
272 let num_items_arr = [0, 1, 4, 8, 16, 20, 40, 80];
273 for num_items in num_items_arr {
274 build_index_with_various_items::<STRSort>(num_items);
275 }
276 }
277
278 #[test]
279 fn build_hilbert_index_with_various_items() {
280 let num_items_arr = [0, 1, 4, 8, 16, 20, 40, 80];
281 for num_items in num_items_arr {
282 build_index_with_various_items::<HilbertSort>(num_items);
283 }
284 }
285
286 fn build_index_with_various_items<S: Sort<f64>>(num_items: u32) {
287 let mut builder = RTreeBuilder::<f64>::new(num_items);
288 for i in 0..num_items {
289 builder.add(i as f64, i as f64, i as f64, i as f64);
290 }
291 let tree = builder.finish::<S>();
292 assert_eq!(tree.num_items(), num_items);
293 if num_items == 0 {
294 assert!(tree.search(0., 0., 0., 0.).is_empty());
295 } else {
296 for i in 0..num_items {
297 let results = tree.search(i as f64, i as f64, i as f64, i as f64);
298 assert_eq!(results, vec![i]);
299 }
300 }
301 }
302}