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