1 #pragma once
2
3 #include <mbgl/util/constants.hpp>
4
5 #include <cstdint>
6 #include <array>
7 #include <tuple>
8 #include <forward_list>
9 #include <algorithm>
10 #include <iosfwd>
11 #include <cassert>
12
13 namespace mbgl {
14
15 class OverscaledTileID;
16 class CanonicalTileID;
17 class UnwrappedTileID;
18
19 // Has integer z/x/y coordinates
20 // All tiles must be derived from 0/0/0 (=no tiles outside of the main tile pyramid)
21 // Used for requesting data; represents data tiles that exist out there.
22 // z is never larger than the source's maxzoom
23 class CanonicalTileID {
24 public:
25 CanonicalTileID(uint8_t z, uint32_t x, uint32_t y);
26 bool operator==(const CanonicalTileID&) const;
27 bool operator!=(const CanonicalTileID&) const;
28 bool operator<(const CanonicalTileID&) const;
29 bool isChildOf(const CanonicalTileID&) const;
30 CanonicalTileID scaledTo(uint8_t z) const;
31 std::array<CanonicalTileID, 4> children() const;
32
33 uint8_t z;
34 uint32_t x;
35 uint32_t y;
36 };
37
38 ::std::ostream& operator<<(::std::ostream& os, const CanonicalTileID& rhs);
39 namespace util {
40 std::string toString(const CanonicalTileID&);
41 } // namespace util
42
43 // Has integer z/x/y coordinates
44 // overscaledZ describes the zoom level this tile is intented to represent, e.g. when parsing data
45 // z is never larger than the source's maxzoom
46 // z/x/y describe the
47 class OverscaledTileID {
48 public:
49 OverscaledTileID(uint8_t overscaledZ, int16_t wrap, CanonicalTileID);
50 OverscaledTileID(uint8_t overscaledZ, int16_t wrap, uint8_t z, uint32_t x, uint32_t y);
51 OverscaledTileID(uint8_t z, uint32_t x, uint32_t y);
52 explicit OverscaledTileID(const CanonicalTileID&);
53 explicit OverscaledTileID(CanonicalTileID&&);
54 bool operator==(const OverscaledTileID&) const;
55 bool operator!=(const OverscaledTileID&) const;
56 bool operator<(const OverscaledTileID&) const;
57 bool isChildOf(const OverscaledTileID&) const;
58 uint32_t overscaleFactor() const;
59 OverscaledTileID scaledTo(uint8_t z) const;
60 UnwrappedTileID toUnwrapped() const;
61 OverscaledTileID unwrapTo(int16_t wrap);
62
63 uint8_t overscaledZ;
64 int16_t wrap;
65 CanonicalTileID canonical;
66 };
67
68 ::std::ostream& operator<<(::std::ostream& os, const OverscaledTileID& rhs);
69 namespace util {
70 std::string toString(const OverscaledTileID&);
71 } // namespace util
72
73 // Has integer z/x/y coordinates
74 // wrap describes tiles that are left/right of the main tile pyramid, e.g. when wrapping the world
75 // Used for describing what position tiles are getting rendered at (= calc the matrix)
76 // z is never larger than the source's maxzoom
77 class UnwrappedTileID {
78 public:
79 UnwrappedTileID(uint8_t z, int64_t x, int64_t y);
80 UnwrappedTileID(int16_t wrap, CanonicalTileID);
81 bool operator==(const UnwrappedTileID&) const;
82 bool operator!=(const UnwrappedTileID&) const;
83 bool operator<(const UnwrappedTileID&) const;
84 bool isChildOf(const UnwrappedTileID&) const;
85 std::array<UnwrappedTileID, 4> children() const;
86 OverscaledTileID overscaleTo(uint8_t z) const;
87 float pixelsToTileUnits(float pixelValue, float zoom) const;
88 UnwrappedTileID unwrapTo(int16_t wrap);
89
90 int16_t wrap;
91 CanonicalTileID canonical;
92 };
93
94 ::std::ostream& operator<<(::std::ostream& os, const UnwrappedTileID& rhs);
95 namespace util {
96 std::string toString(const UnwrappedTileID&);
97 } // namespace util
98
CanonicalTileID(uint8_t z_,uint32_t x_,uint32_t y_)99 inline CanonicalTileID::CanonicalTileID(uint8_t z_, uint32_t x_, uint32_t y_) : z(z_), x(x_), y(y_) {
100 assert(z <= 32);
101 assert(x < (1ull << z));
102 assert(y < (1ull << z));
103 }
104
operator ==(const CanonicalTileID & rhs) const105 inline bool CanonicalTileID::operator==(const CanonicalTileID& rhs) const {
106 return z == rhs.z && x == rhs.x && y == rhs.y;
107 }
108
operator !=(const CanonicalTileID & rhs) const109 inline bool CanonicalTileID::operator!=(const CanonicalTileID& rhs) const {
110 return z != rhs.z || x != rhs.x || y != rhs.y;
111 }
112
operator <(const CanonicalTileID & rhs) const113 inline bool CanonicalTileID::operator<(const CanonicalTileID& rhs) const {
114 return std::tie(z, x, y) < std::tie(rhs.z, rhs.x, rhs.y);
115 }
116
isChildOf(const CanonicalTileID & parent) const117 inline bool CanonicalTileID::isChildOf(const CanonicalTileID& parent) const {
118 // We're first testing for z == 0, to avoid a 32 bit shift, which is undefined.
119 return parent.z == 0 ||
120 (parent.z < z && parent.x == (x >> (z - parent.z)) && parent.y == (y >> (z - parent.z)));
121 }
122
scaledTo(uint8_t targetZ) const123 inline CanonicalTileID CanonicalTileID::scaledTo(uint8_t targetZ) const {
124 if (targetZ <= z) {
125 return { targetZ, x >> (z - targetZ), y >> (z - targetZ) }; // parent or same
126 } else {
127 return { targetZ, x << (targetZ - z), y << (targetZ - z) }; // child
128 }
129 }
130
children() const131 inline std::array<CanonicalTileID, 4> CanonicalTileID::children() const {
132 const uint8_t childZ = z + 1;
133 const uint32_t childX = x * 2;
134 const uint32_t childY = y * 2;
135 return { {
136 { childZ, childX, childY },
137 { childZ, childX, childY + 1 },
138 { childZ, childX + 1, childY },
139 { childZ, childX + 1, childY + 1 },
140 } };
141 }
142
OverscaledTileID(uint8_t overscaledZ_,int16_t wrap_,CanonicalTileID canonical_)143 inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, CanonicalTileID canonical_)
144 : overscaledZ(overscaledZ_), wrap(wrap_), canonical(std::move(canonical_)) {
145 assert(overscaledZ >= canonical.z);
146 }
147
OverscaledTileID(uint8_t overscaledZ_,int16_t wrap_,uint8_t z,uint32_t x,uint32_t y)148 inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, uint8_t z, uint32_t x, uint32_t y)
149 : overscaledZ(overscaledZ_), wrap(wrap_), canonical(z, x, y) {
150 assert(overscaledZ >= canonical.z);
151 }
152
OverscaledTileID(uint8_t z,uint32_t x,uint32_t y)153 inline OverscaledTileID::OverscaledTileID(uint8_t z, uint32_t x, uint32_t y)
154 : overscaledZ(z), wrap(0), canonical(z, x, y) {
155 }
156
OverscaledTileID(const CanonicalTileID & canonical_)157 inline OverscaledTileID::OverscaledTileID(const CanonicalTileID& canonical_)
158 : overscaledZ(canonical_.z), wrap(0), canonical(canonical_) {
159 assert(overscaledZ >= canonical.z);
160 }
161
OverscaledTileID(CanonicalTileID && canonical_)162 inline OverscaledTileID::OverscaledTileID(CanonicalTileID&& canonical_)
163 : overscaledZ(canonical_.z), wrap(0), canonical(std::forward<CanonicalTileID>(canonical_)) {
164 assert(overscaledZ >= canonical.z);
165 }
166
operator ==(const OverscaledTileID & rhs) const167 inline bool OverscaledTileID::operator==(const OverscaledTileID& rhs) const {
168 return overscaledZ == rhs.overscaledZ && wrap == rhs.wrap &&canonical == rhs.canonical;
169 }
170
operator !=(const OverscaledTileID & rhs) const171 inline bool OverscaledTileID::operator!=(const OverscaledTileID& rhs) const {
172 return overscaledZ != rhs.overscaledZ || wrap != rhs.wrap || canonical != rhs.canonical;
173 }
174
operator <(const OverscaledTileID & rhs) const175 inline bool OverscaledTileID::operator<(const OverscaledTileID& rhs) const {
176 return std::tie(overscaledZ, wrap, canonical) < std::tie(rhs.overscaledZ, rhs.wrap, rhs.canonical);
177 }
178
overscaleFactor() const179 inline uint32_t OverscaledTileID::overscaleFactor() const {
180 return 1u << (overscaledZ - canonical.z);
181 }
182
isChildOf(const OverscaledTileID & rhs) const183 inline bool OverscaledTileID::isChildOf(const OverscaledTileID& rhs) const {
184 return overscaledZ > rhs.overscaledZ &&
185 (canonical == rhs.canonical || canonical.isChildOf(rhs.canonical));
186 }
187
scaledTo(uint8_t z) const188 inline OverscaledTileID OverscaledTileID::scaledTo(uint8_t z) const {
189 return { z, wrap, z >= canonical.z ? canonical : canonical.scaledTo(z) };
190 }
191
toUnwrapped() const192 inline UnwrappedTileID OverscaledTileID::toUnwrapped() const {
193 return { wrap, canonical };
194 }
195
unwrapTo(int16_t newWrap)196 inline OverscaledTileID OverscaledTileID::unwrapTo(int16_t newWrap) {
197 return { overscaledZ, newWrap, canonical };
198 }
199
UnwrappedTileID(uint8_t z_,int64_t x_,int64_t y_)200 inline UnwrappedTileID::UnwrappedTileID(uint8_t z_, int64_t x_, int64_t y_)
201 : wrap((x_ < 0 ? x_ - (1ll << z_) + 1 : x_) / (1ll << z_)),
202 canonical(
203 z_,
204 static_cast<uint32_t>(x_ - wrap * (1ll << z_)),
205 y_ < 0 ? 0 : std::min(static_cast<uint32_t>(y_), static_cast<uint32_t>(1ull << z_) - 1)) {
206 }
207
UnwrappedTileID(int16_t wrap_,CanonicalTileID canonical_)208 inline UnwrappedTileID::UnwrappedTileID(int16_t wrap_, CanonicalTileID canonical_)
209 : wrap(wrap_), canonical(std::move(canonical_)) {
210 }
211
operator ==(const UnwrappedTileID & rhs) const212 inline bool UnwrappedTileID::operator==(const UnwrappedTileID& rhs) const {
213 return wrap == rhs.wrap && canonical == rhs.canonical;
214 }
215
operator !=(const UnwrappedTileID & rhs) const216 inline bool UnwrappedTileID::operator!=(const UnwrappedTileID& rhs) const {
217 return wrap != rhs.wrap || canonical != rhs.canonical;
218 }
219
operator <(const UnwrappedTileID & rhs) const220 inline bool UnwrappedTileID::operator<(const UnwrappedTileID& rhs) const {
221 return std::tie(wrap, canonical) < std::tie(rhs.wrap, rhs.canonical);
222 }
223
unwrapTo(int16_t newWrap)224 inline UnwrappedTileID UnwrappedTileID::unwrapTo(int16_t newWrap) {
225 return { newWrap, canonical };
226 }
227
isChildOf(const UnwrappedTileID & parent) const228 inline bool UnwrappedTileID::isChildOf(const UnwrappedTileID& parent) const {
229 return wrap == parent.wrap && canonical.isChildOf(parent.canonical);
230 }
231
children() const232 inline std::array<UnwrappedTileID, 4> UnwrappedTileID::children() const {
233 const uint8_t childZ = canonical.z + 1;
234 const uint32_t childX = canonical.x * 2;
235 const uint32_t childY = canonical.y * 2;
236 return { {
237 { wrap, { childZ, childX, childY } },
238 { wrap, { childZ, childX, childY + 1 } },
239 { wrap, { childZ, childX + 1, childY } },
240 { wrap, { childZ, childX + 1, childY + 1 } },
241 } };
242 }
243
overscaleTo(const uint8_t overscaledZ) const244 inline OverscaledTileID UnwrappedTileID::overscaleTo(const uint8_t overscaledZ) const {
245 assert(overscaledZ >= canonical.z);
246 return { overscaledZ, wrap, canonical };
247 }
248
pixelsToTileUnits(const float pixelValue,const float zoom) const249 inline float UnwrappedTileID::pixelsToTileUnits(const float pixelValue, const float zoom) const {
250 return pixelValue * (util::EXTENT / (util::tileSize * std::pow(2, zoom - canonical.z)));
251 }
252
253 } // namespace mbgl
254
255 namespace std {
256
257 template <>
258 struct hash<mbgl::CanonicalTileID> {
259 size_t operator()(const mbgl::CanonicalTileID& id) const;
260 };
261
262 template <>
263 struct hash<mbgl::UnwrappedTileID> {
264 size_t operator()(const mbgl::UnwrappedTileID& id) const;
265 };
266
267 template <>
268 struct hash<mbgl::OverscaledTileID> {
269 size_t operator()(const mbgl::OverscaledTileID& id) const;
270 };
271
272 } // namespace std
273
274