tile_grid/wmts/
grid_iterator.rs

1//
2// Copyright (c) Pirmin Kalberer. All rights reserved.
3// Licensed under the MIT License. See LICENSE file in the project root for full license information.
4//
5
6//! Grid iterators
7
8use crate::wmts::grid::ExtentInt;
9
10/// Level-by-level iterator
11pub struct GridIterator {
12    z: u8,
13    x: u32,
14    y: u32,
15    maxz: u8,
16    limits: Vec<ExtentInt>,
17    finished: bool,
18}
19
20impl GridIterator {
21    pub fn new(minz: u8, maxz: u8, limits: Vec<ExtentInt>) -> GridIterator {
22        if minz <= maxz && limits.len() > minz as usize {
23            let limit = &limits[minz as usize];
24            let maxz = std::cmp::min(maxz, limits.len() as u8 - 1);
25            GridIterator {
26                z: minz,
27                x: limit.minx,
28                y: limit.miny,
29                maxz,
30                limits,
31                finished: false,
32            }
33        } else {
34            // Return "empty" iterator for invalid parameters
35            GridIterator {
36                z: 0,
37                x: 0,
38                y: 0,
39                maxz: 0,
40                limits: Vec::new(),
41                finished: true,
42            }
43        }
44    }
45}
46
47impl Iterator for GridIterator {
48    /// Current cell index `(z, x, y)`
49    type Item = (u8, u32, u32);
50
51    fn next(&mut self) -> Option<Self::Item> {
52        if self.finished {
53            return None;
54        }
55        let current = (self.z, self.x, self.y);
56        let limit = &self.limits[self.z as usize];
57        if self.y < limit.maxy - 1 {
58            self.y += 1;
59        } else if self.x < limit.maxx - 1 {
60            self.x += 1;
61            self.y = limit.miny;
62        } else if self.z < self.maxz {
63            self.z += 1;
64            let limit = &self.limits[self.z as usize];
65            self.x = limit.minx;
66            self.y = limit.miny;
67        } else {
68            self.finished = true;
69        }
70        Some(current)
71    }
72}
73
74#[test]
75fn test_mercator_iter() {
76    use crate::wmts::grid::Grid;
77    let grid = Grid::web_mercator();
78    let tile_limits = grid.tile_limits(grid.extent.clone(), 0);
79    let griditer = GridIterator::new(0, 2, tile_limits);
80    let cells = griditer.collect::<Vec<_>>();
81    assert_eq!(
82        cells,
83        vec![
84            (0, 0, 0),
85            (1, 0, 0),
86            (1, 0, 1),
87            (1, 1, 0),
88            (1, 1, 1),
89            (2, 0, 0),
90            (2, 0, 1),
91            (2, 0, 2),
92            (2, 0, 3),
93            (2, 1, 0),
94            (2, 1, 1),
95            (2, 1, 2),
96            (2, 1, 3),
97            (2, 2, 0),
98            (2, 2, 1),
99            (2, 2, 2),
100            (2, 2, 3),
101            (2, 3, 0),
102            (2, 3, 1),
103            (2, 3, 2),
104            (2, 3, 3)
105        ]
106    );
107
108    let tile_limits = grid.tile_limits(grid.extent.clone(), 0);
109    let griditer = GridIterator::new(1, 2, tile_limits);
110    let cells = griditer.collect::<Vec<_>>();
111    assert_eq!(
112        cells,
113        vec![
114            (1, 0, 0),
115            (1, 0, 1),
116            (1, 1, 0),
117            (1, 1, 1),
118            (2, 0, 0),
119            (2, 0, 1),
120            (2, 0, 2),
121            (2, 0, 3),
122            (2, 1, 0),
123            (2, 1, 1),
124            (2, 1, 2),
125            (2, 1, 3),
126            (2, 2, 0),
127            (2, 2, 1),
128            (2, 2, 2),
129            (2, 2, 3),
130            (2, 3, 0),
131            (2, 3, 1),
132            (2, 3, 2),
133            (2, 3, 3)
134        ]
135    );
136
137    let tile_limits = grid.tile_limits(grid.extent.clone(), 0);
138    let griditer = GridIterator::new(0, 0, tile_limits);
139    let cells = griditer.collect::<Vec<_>>();
140    assert_eq!(cells, vec![(0, 0, 0)]);
141}
142
143#[test]
144fn test_bad_params() {
145    use crate::wmts::grid::Grid;
146    let grid = Grid::web_mercator();
147
148    // missing tile_limits
149    let griditer = GridIterator::new(0, 10, Vec::new());
150    let cells = griditer.collect::<Vec<_>>();
151    assert_eq!(cells, vec![]);
152
153    // minz > maxz
154    let tile_limits = grid.tile_limits(grid.extent.clone(), 0);
155    let griditer = GridIterator::new(3, 2, tile_limits);
156    let cells = griditer.collect::<Vec<_>>();
157    assert_eq!(cells, vec![]);
158
159    // maxz >= tile_limits.len()
160    let griditer = GridIterator::new(
161        0,
162        2,
163        vec![
164            ExtentInt {
165                minx: 0,
166                miny: 0,
167                maxx: 1,
168                maxy: 1,
169            },
170            ExtentInt {
171                minx: 0,
172                miny: 0,
173                maxx: 2,
174                maxy: 2,
175            },
176        ],
177    );
178    let cells = griditer.collect::<Vec<_>>();
179    assert_eq!(
180        cells,
181        vec![(0, 0, 0), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
182    );
183
184    // minz >= tile_limits.len()
185    let griditer = GridIterator::new(
186        1,
187        2,
188        vec![ExtentInt {
189            minx: 0,
190            miny: 0,
191            maxx: 1,
192            maxy: 1,
193        }],
194    );
195    let cells = griditer.collect::<Vec<_>>();
196    assert_eq!(cells, vec![]);
197}