@@ -150,7 +150,7 @@ def get_tiles(self, layer='default', tileset=None,
150
150
151
151
storage_srid = get_crs_from_uri (self .storage_crs ).to_string ()
152
152
out_srid = get_crs_from_uri (tileset_schema .crs ).to_string ()
153
- envelope = func . ST_TileEnvelope (z , x , y ). label ( 'bounds' )
153
+ envelope = self . get_envelope (z , y , x , tileset )
154
154
155
155
geom_column = getattr (self .table_model , self .geom )
156
156
geom_filter = geom_column .intersects (
@@ -254,5 +254,40 @@ def get_default_metadata(self, dataset, server_url, layer, tileset,
254
254
255
255
return content .model_dump (exclude_none = True )
256
256
257
+ @staticmethod
258
+ def get_envelope (z , y , x , tileset ):
259
+ """
260
+ Calculate the Tile bounding box of a tile at zoom z, y, x.
261
+
262
+ WorldCRS84Quad tiles have:
263
+ - origin top-left (y=0 is north)
264
+ - full lon: -180 to 180
265
+
266
+ :param tileset: mvt tileset
267
+ :param z: z index
268
+ :param y: y index
269
+ :param x: x index
270
+
271
+ :returns: SQL Alchemy Tile Envelope
272
+ """
273
+
274
+ if tileset == TileMatrixSetEnum .WORLDCRS84QUAD .value .tileMatrixSet :
275
+
276
+ tile_size = 180 / 2 ** z
277
+
278
+ xmin = tile_size * x - 180
279
+ ymax = tile_size * - y + 90
280
+
281
+ # getting bottom-right coordinates of the tile
282
+ xmax = xmin + tile_size
283
+ ymin = ymax - tile_size
284
+
285
+ envelope = ST_MakeEnvelope (xmin , ymin , xmax , ymax , 4326 )
286
+
287
+ else :
288
+ envelope = ST_TileEnvelope (z , x , y )
289
+
290
+ return envelope .label ('bounds' )
291
+
257
292
def __repr__ (self ):
258
293
return f'<MVTPostgreSQLProvider> { self .data } '
0 commit comments