1use crate::bbox::WebBBox;
2use crate::{
3 BBox, LngLat, Tile, TileZBox, flipy, neighbors, neighbors_wrap_x, xyz2rmid,
4};
5
6#[cfg(feature = "pmtiles")]
7use crate::pmtiles;
8
9pub trait TileLike {
11 fn x(&self) -> u32;
13
14 fn y(&self) -> u32;
16
17 fn z(&self) -> u8;
19
20 #[must_use]
22 fn zoom(&self) -> u8 {
23 self.z()
24 }
25
26 fn yflip(&self) -> u32 {
28 flipy(self.y(), self.z())
29 }
30
31 fn flipy(&self) -> u32 {
33 flipy(self.y(), self.z())
34 }
35
36 fn yup(&self) -> u32 {
37 flipy(self.y(), self.z())
38 }
39
40 fn xyz_str_fslash(&self) -> String {
41 format!("{}/{}/{}", self.x(), self.y(), self.z())
42 }
43
44 fn zxy_str_fslash(&self) -> String {
45 format!("{}/{}/{}", self.z(), self.x(), self.y())
46 }
47
48 fn xyz_str_sep(&self, sep: &str) -> String {
49 format!("{}{}{}{}{}", self.x(), sep, self.y(), sep, self.z())
50 }
51
52 fn zxy_str_sep(&self, sep: &str) -> String {
53 format!("{}{}{}{}{}", self.z(), sep, self.x(), sep, self.y())
54 }
55
56 #[must_use]
58 fn tile(&self) -> Tile {
59 Tile::new(self.x(), self.y(), self.z())
60 }
61
62 #[must_use]
64 fn valid(&self) -> bool {
65 crate::valid(self.x(), self.y(), self.z())
66 }
67
68 #[must_use]
70 fn ul(&self) -> LngLat {
71 crate::ul(self.x(), self.y(), self.z())
72 }
73
74 #[must_use]
76 fn ur(&self) -> LngLat {
77 crate::ul(self.x() + 1, self.y(), self.z())
78 }
79
80 #[must_use]
82 fn lr(&self) -> LngLat {
83 crate::ul(self.x() + 1, self.y() + 1, self.z())
84 }
85
86 #[must_use]
88 fn ll(&self) -> LngLat {
89 crate::ul(self.x(), self.y() + 1, self.z())
90 }
91
92 #[must_use]
94 fn quadkey(&self) -> String {
95 crate::xyz2quadkey(self.x(), self.y(), self.z())
96 }
97
98 #[must_use]
100 fn qk(&self) -> String {
101 crate::xyz2quadkey(self.x(), self.y(), self.z())
102 }
103
104 #[cfg(feature = "pmtiles")]
106 #[must_use]
107 fn pmtileid(&self) -> u64 {
108 pmtiles::xyz2pmid(self.x(), self.y(), self.z())
109 }
110
111 #[cfg(feature = "pmtiles")]
113 #[must_use]
114 fn pmid(&self) -> u64 {
115 self.pmtileid()
116 }
117
118 #[must_use]
120 fn row_major_id(&self) -> u64 {
121 xyz2rmid(self.x(), self.y(), self.z())
122 }
123
124 #[must_use]
126 fn rmid(&self) -> u64 {
127 self.row_major_id()
128 }
129
130 #[must_use]
132 fn bbox(&self) -> (f64, f64, f64, f64) {
133 let ul = self.ul();
134 let lr = self.lr();
135 (ul.lng(), lr.lat(), lr.lng(), ul.lat())
136 }
137
138 #[must_use]
139 fn geobbox(&self) -> BBox {
140 let ul = self.ul();
141 let lr = self.lr();
142 BBox::new(ul.lng(), lr.lat(), lr.lng(), ul.lat())
143 }
144
145 #[must_use]
146 fn webbbox(&self) -> WebBBox {
147 self.geobbox().into()
148 }
149
150 #[must_use]
151 fn bbox_string(&self) -> String {
152 let (w, s, e, n) = self.bbox();
153 format!("[{w},{s},{e},{n}]")
154 }
155
156 #[must_use]
158 fn center(&self) -> LngLat {
159 let ul = self.ul();
160 let lr = self.lr();
161 LngLat::new(
162 f64::midpoint(ul.lng(), lr.lng()),
163 f64::midpoint(ul.lat(), lr.lat()),
164 )
165 }
166
167 #[must_use]
169 fn json_arr(&self) -> String {
170 format!("[{}, {}, {}]", self.x(), self.y(), self.z())
171 }
172
173 #[must_use]
175 fn json_arr_min(&self) -> String {
176 format!("[{},{},{}]", self.x(), self.y(), self.z())
177 }
178
179 #[must_use]
181 fn json_obj(&self) -> String {
182 format!(
183 "{{\"x\":{}, \"y\":{}, \"z\":{}}}",
184 self.x(),
185 self.y(),
186 self.z()
187 )
188 }
189
190 #[must_use]
192 fn json(&self) -> String {
193 self.json_obj()
194 }
195
196 #[must_use]
198 fn tuple_string(&self) -> String {
199 format!("({}, {}, {})", self.x(), self.y(), self.z())
200 }
201
202 #[must_use]
204 fn mbtiles_sql_where(&self) -> String {
205 format!(
210 "(zoom_level = {} AND tile_column = {} AND tile_row = {})",
211 self.z(),
212 self.x(),
213 flipy(self.y(), self.z())
214 )
215 }
216
217 #[must_use]
219 fn zbox(&self) -> TileZBox {
220 TileZBox::from_tile(self)
221 }
222
223 #[must_use]
225 fn children_zbox(&self, depth: Option<u8>) -> TileZBox {
226 let d = depth.unwrap_or(1);
227 let target_zoom = self.z() + d;
228 let mut zbox = TileZBox::from_tile(self);
229 while zbox.z() < target_zoom {
230 zbox = zbox.zoom_in();
231 }
232 zbox
233 }
234
235 #[must_use]
237 fn neighbors(&self, wrapx: bool) -> Vec<Tile> {
238 if wrapx {
239 neighbors_wrap_x(self.x(), self.y(), self.z())
240 } else {
241 neighbors(self.x(), self.y(), self.z())
242 }
243 }
244}