Skip to main content

osmic_repl/
dirty.rs

1use std::collections::HashSet;
2
3use osmic_core::bbox::BBox;
4use osmic_core::tile::TileCoord;
5use osmic_core::tile::Zoom;
6use osmic_geo::projection::bbox_to_tile_range;
7
8/// Tracks which tiles need regeneration after feature changes.
9pub struct DirtyTileSet {
10    dirty: HashSet<TileCoord>,
11}
12
13impl DirtyTileSet {
14    pub fn new() -> Self {
15        Self {
16            dirty: HashSet::new(),
17        }
18    }
19
20    /// Mark all tiles overlapping the given bounding box as dirty
21    /// across the specified zoom range.
22    pub fn mark_bbox(&mut self, bbox: &BBox, min_zoom: u8, max_zoom: u8) {
23        for z in min_zoom..=max_zoom {
24            let (min_x, min_y, max_x, max_y) = bbox_to_tile_range(bbox, z);
25            for y in min_y..=max_y {
26                for x in min_x..=max_x {
27                    self.dirty.insert(TileCoord::new(x, y, Zoom::new(z)));
28                }
29            }
30        }
31    }
32
33    /// Iterator over all dirty tiles.
34    pub fn tiles(&self) -> impl Iterator<Item = &TileCoord> {
35        self.dirty.iter()
36    }
37
38    /// Number of dirty tiles.
39    pub fn len(&self) -> usize {
40        self.dirty.len()
41    }
42
43    /// Whether there are no dirty tiles.
44    pub fn is_empty(&self) -> bool {
45        self.dirty.is_empty()
46    }
47
48    pub fn clear(&mut self) {
49        self.dirty.clear();
50    }
51}
52
53impl Default for DirtyTileSet {
54    fn default() -> Self {
55        Self::new()
56    }
57}