1use serde::Serialize;
8
9#[derive(Debug, Clone, Copy, PartialEq)]
23pub struct TileRect {
24 pub zoom: u8,
26 pub min_x: u32,
28 pub min_y: u32,
30 pub max_x: u32,
32 pub max_y: u32,
34}
35
36impl Serialize for TileRect {
37 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38 where
39 S: serde::ser::Serializer,
40 {
41 serializer.collect_str(&format!(
42 "{}: ({},{}) - ({},{})",
43 self.zoom, self.min_x, self.min_y, self.max_x, self.max_y
44 ))
45 }
46}
47
48impl TileRect {
49 #[must_use]
71 pub fn new(zoom: u8, min_x: u32, min_y: u32, max_x: u32, max_y: u32) -> Self {
72 assert!(min_x <= max_x);
73 assert!(min_y <= max_y);
74 TileRect {
75 zoom,
76 min_x,
77 min_y,
78 max_x,
79 max_y,
80 }
81 }
82
83 #[must_use]
101 pub fn is_overlapping(&self, other: &Self) -> bool {
102 self.zoom == other.zoom
103 && self.min_x <= other.max_x
104 && self.max_x >= other.min_x
105 && self.min_y <= other.max_y
106 && self.max_y >= other.min_y
107 }
108
109 #[must_use]
123 pub fn size(&self) -> u64 {
124 u64::from(self.max_x - self.min_x + 1) * u64::from(self.max_y - self.min_y + 1)
125 }
126
127 fn get_non_overlapping(&self, o: &Self) -> [Option<Self>; 4] {
134 let mut result = [None, None, None, None];
135 assert_eq!(self.zoom, o.zoom);
136 if o.min_x < self.min_x {
137 let min_x = self.min_x - 1;
139 result[0] = Some(TileRect::new(o.zoom, o.min_x, o.min_y, min_x, o.max_y));
140 }
141 if o.max_x > self.max_x {
142 let max_x = self.max_x + 1;
144 result[1] = Some(TileRect::new(o.zoom, max_x, o.min_y, o.max_x, o.max_y));
145 }
146 if o.min_y < self.min_y {
147 let min_x = o.min_x.max(self.min_x);
149 let max_x = o.max_x.min(self.max_x);
150 result[2] = Some(TileRect::new(o.zoom, min_x, o.min_y, max_x, self.min_y - 1));
151 }
152 if o.max_y > self.max_y {
153 let min_x = o.min_x.max(self.min_x);
155 let max_x = o.max_x.min(self.max_x);
156 result[3] = Some(TileRect::new(o.zoom, min_x, self.max_y + 1, max_x, o.max_y));
157 }
158 result
159 }
160}
161
162pub fn append_rect(rectangles: &mut Vec<TileRect>, new_rect: TileRect) {
181 for rect in rectangles.iter() {
182 if rect.is_overlapping(&new_rect) {
183 for new_rect in rect.get_non_overlapping(&new_rect).into_iter().flatten() {
185 append_rect(rectangles, new_rect);
186 }
187 return;
189 }
190 }
191 rectangles.push(new_rect);
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 fn append(rectangles: &mut Vec<TileRect>, new_rect: TileRect) {
200 append_rect(rectangles, new_rect);
201 for (i, r1) in rectangles.iter().enumerate() {
203 for (j, r2) in rectangles.iter().enumerate() {
204 if i != j {
205 assert!(!r1.is_overlapping(r2));
206 }
207 }
208 }
209 }
210
211 #[test]
212 fn test_len() {
213 assert_eq!(1, TileRect::new(0, 0, 0, 0, 0).size());
214 assert_eq!(4, TileRect::new(0, 0, 0, 1, 1).size());
215 assert_eq!(15, TileRect::new(0, 2, 3, 4, 7).size());
216 }
217
218 #[test]
219 fn test_tile_range_is_overlapping() {
220 let r1 = TileRect::new(0, 0, 0, 0, 0);
221 let r2 = TileRect::new(0, 0, 0, 0, 0);
222 assert!(r1.is_overlapping(&r2));
223
224 let r1 = TileRect::new(0, 0, 0, 0, 0);
225 let r2 = TileRect::new(0, 1, 1, 1, 1);
226 assert!(!r1.is_overlapping(&r2));
227
228 let r1 = TileRect::new(0, 0, 0, 1, 1);
229 let r2 = TileRect::new(0, 1, 1, 2, 2);
230 assert!(r1.is_overlapping(&r2));
231
232 let r1 = TileRect::new(0, 0, 0, 2, 2);
233 let r2 = TileRect::new(0, 1, 1, 1, 1);
234 assert!(r1.is_overlapping(&r2));
235
236 let center = TileRect::new(0, 4, 4, 6, 6);
237
238 assert!(center.is_overlapping(&TileRect::new(0, 3, 5, 5, 5)));
239 assert!(center.is_overlapping(&TileRect::new(0, 5, 3, 5, 5)));
240 assert!(center.is_overlapping(&TileRect::new(0, 5, 5, 7, 5)));
241 assert!(center.is_overlapping(&TileRect::new(0, 5, 5, 5, 7)));
242
243 assert!(!center.is_overlapping(&TileRect::new(0, 3, 5, 3, 5)));
244 assert!(!center.is_overlapping(&TileRect::new(0, 5, 3, 5, 3)));
245 assert!(!center.is_overlapping(&TileRect::new(0, 7, 5, 7, 5)));
246 assert!(!center.is_overlapping(&TileRect::new(0, 5, 7, 5, 7)));
247 }
248
249 #[test]
250 fn test_append_single() {
251 let mut rectangles = Vec::new();
252 append(&mut rectangles, TileRect::new(0, 0, 0, 0, 0));
253 assert_eq!(rectangles, vec![TileRect::new(0, 0, 0, 0, 0)]);
254
255 append(&mut rectangles, TileRect::new(0, 0, 0, 0, 0));
256 assert_eq!(rectangles, vec![TileRect::new(0, 0, 0, 0, 0)]);
257
258 append(&mut rectangles, TileRect::new(0, 1, 0, 1, 1));
259 assert_eq!(
260 rectangles,
261 vec![TileRect::new(0, 0, 0, 0, 0), TileRect::new(0, 1, 0, 1, 1),]
262 );
263
264 append(&mut rectangles, TileRect::new(0, 0, 0, 1, 1));
265 assert_eq!(
266 rectangles,
267 vec![
268 TileRect::new(0, 0, 0, 0, 0),
269 TileRect::new(0, 1, 0, 1, 1),
270 TileRect::new(0, 0, 1, 0, 1)
271 ]
272 );
273 }
274
275 #[test]
276 fn test_append_multiple() {
277 let mut rectangles = Vec::new();
278 append(&mut rectangles, TileRect::new(0, 2, 2, 4, 4));
279 assert_eq!(rectangles, vec![TileRect::new(0, 2, 2, 4, 4)]);
280
281 append(&mut rectangles, TileRect::new(0, 1, 3, 3, 3));
282 assert_eq!(
283 rectangles,
284 vec![TileRect::new(0, 2, 2, 4, 4), TileRect::new(0, 1, 3, 1, 3),]
285 );
286
287 append(&mut rectangles, TileRect::new(0, 3, 1, 3, 3));
288 assert_eq!(
289 rectangles,
290 vec![
291 TileRect::new(0, 2, 2, 4, 4),
292 TileRect::new(0, 1, 3, 1, 3),
293 TileRect::new(0, 3, 1, 3, 1),
294 ]
295 );
296
297 append(&mut rectangles, TileRect::new(0, 3, 3, 5, 3));
298 assert_eq!(
299 rectangles,
300 vec![
301 TileRect::new(0, 2, 2, 4, 4),
302 TileRect::new(0, 1, 3, 1, 3),
303 TileRect::new(0, 3, 1, 3, 1),
304 TileRect::new(0, 5, 3, 5, 3),
305 ]
306 );
307
308 append(&mut rectangles, TileRect::new(0, 3, 3, 3, 5));
309 assert_eq!(
310 rectangles,
311 vec![
312 TileRect::new(0, 2, 2, 4, 4),
313 TileRect::new(0, 1, 3, 1, 3),
314 TileRect::new(0, 3, 1, 3, 1),
315 TileRect::new(0, 5, 3, 5, 3),
316 TileRect::new(0, 3, 5, 3, 5),
317 ]
318 );
319
320 append(&mut rectangles, TileRect::new(0, 3, 3, 5, 5));
321 assert_eq!(
322 rectangles,
323 vec![
324 TileRect::new(0, 2, 2, 4, 4),
325 TileRect::new(0, 1, 3, 1, 3),
326 TileRect::new(0, 3, 1, 3, 1),
327 TileRect::new(0, 5, 3, 5, 3),
328 TileRect::new(0, 3, 5, 3, 5),
329 TileRect::new(0, 5, 4, 5, 5),
330 TileRect::new(0, 4, 5, 4, 5),
331 ]
332 );
333
334 append(&mut rectangles, TileRect::new(0, 1, 1, 3, 3));
335 assert_eq!(
336 rectangles,
337 vec![
338 TileRect::new(0, 2, 2, 4, 4),
339 TileRect::new(0, 1, 3, 1, 3),
340 TileRect::new(0, 3, 1, 3, 1),
341 TileRect::new(0, 5, 3, 5, 3),
342 TileRect::new(0, 3, 5, 3, 5),
343 TileRect::new(0, 5, 4, 5, 5),
344 TileRect::new(0, 4, 5, 4, 5),
345 TileRect::new(0, 1, 1, 1, 2),
346 TileRect::new(0, 2, 1, 2, 1),
347 ]
348 );
349 }
350}