Sunday, 23 December 2018

geoserver - How properly calculate BBox for mocked GetMap request?


I am trying to imitate GetMap requests for GeoServer and have an application which generates these requests (requests are for cached layers). The problem is that sometimes I get geowebcache-cache-result:HIT and sometimes geowebcache-cache-result:MISS with geowebcache-miss-reason:request does not align to grid(s) 'XXXX'. I understand that for these "miss" requests I have generated invalid BBox parameter. For example (pay attention to marked numbers):



...REQUEST=GetMap&BBOX=55|6|865.8627022989,6104809.344416159,55|8|155.8627022989,6106099.344416159...




results in HIT


when



...REQUEST=GetMap&BBOX=55|5|865.8627022989,6104809.344416159,55|7|155.8627022989,6106099.344416159...



results in MISS with geowebcache-miss-reason:request does not align to grid(s) 'XXXX'.


What would be the formula for generating correct BBox?


NOTE: I have checked and the generated BBox coordinates fit inside layer's and grid extent.


UPDATE: Question also could be formulated as - how to validate if BBox coordinates are aligned to the grid that is used?




Answer



The easy way to do this is to make WMTS requests instead of WMS requests since then all you need to do is specify the zoom level, row and column number to get a hit.


If you have to calculate the tile bounds you should fetch the WMTS capabilities document. Then under the layer you are asking for will be a TileMatrixSetLink that tells you the projection and limits for each level of tiles.


 
EPSG:4326


EPSG:4326:0
0
0

0
0


EPSG:4326:1
0
0
0
1



[.....]

This gives you the row and column ranges for each zoom level, don't request a tile outside these limits. Then look for the TileMatrixSet towards the end of the file that matches this name.


  
EPSG:4326
urn:ogc:def:crs:EPSG::4326

EPSG:4326:0
2.795411320143589E8

90.0 -180.0
256
256
2
1


EPSG:4326:1
1.3977056600717944E8
90.0 -180.0

256
256
4
2

[......]

Now for any zoom level, you can look up the origin of the grid and then calculate the bounds for any tile as:


pixelSize = scaleDenom * 2.8e-4 
if CRS is degrees then / by 111319 else convert from metres if needed

tileWidth = 256 * pixelSize
tileHeight = 256 * pixelSize

minX = col * tileWidth + originX
maxY = originY - row * tileHeight
maxX = minX + tileWidth
minY = maxY - tileHeight

You can see a full implementation with axis order handling and all the other exciting issues from GeoTools.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...