Determining Lat/Long bounds for Cesium Map Tiles - What projection to use?

I am trying to generate map tiles based on data we have stored in a DB and serve them up to Cesium using an UrlTemplateImageryProvider. For each map tile, I need to know the lat/long bounds in order to find matching data. I'm using the same tile scheme as Google Maps with a request like http://host/tiles/zoom/x/y. Initially I've been using the equations to convert these map tile coordinates into lat/long bounds found here: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_bounding_box but now I'm wondering if this is not the correct projection to be using.

For starters, all the Web Mercator documentation I see says that Tile 0,0 @ zoom lvl 0 should cover the entire world. That's not what I see with Cesium (there are 2 tiles at zoom level 0). That said, my calculations seem to work for zoom levels 0,1,2, and 3, but as I go to Zoom level 4, the Latitude calculation starts to move south. If I plot my generated lat, long point on a 2D Google Map, they look correct, but I can clearly see that the tiles requested by cesium have different bounds. So I am now assuming I'm just using the wrong projection to calculate the tile bounds.

I've also tried the calculations here: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
converting from pixes, to meters, to lat/long but they seem to be the same results as the web mercator calculations.

So can anyone help me figure out how to calculate a Lat/Long bounding box for the tiles requested by Cesium?

Thanks
Andrew

Yeah, I can tell you that Cesium’s client-side tile management expects that level 0 will have two tiles covering the world. I did some research on generating datasets a while back and noted that, but can’t find where I wrote it up at the moment.

Is there some specific reason why you’re trying to do the lat/lon calculations yourself, rather than letting Cesium produce the proper z/x/y requests and you just ensure you have matching tiles at those values? Or am I misunderstanding what you’re trying to do?

I am letting Cesium make the z/x/y request to my custom map tile server. My map tile server is then trying to convert the z/x/y into lat/lon so that I can query our DB based on that region, get results, and then return a tile with the corresponding data for that area. Let me know if that doesn’t make sense.

Yeah, I think so. Sort of. So you have a bunch of lat/lon based stuff in a DB, and you are trying to return that as metadata? And return a matching map tile? Or just a tile? Are these tiles pre-generated, or something you’re trying to create on the fly, like a just-in-time rendered “points of interest”-type image or something?

Ya, I’m trying to generate a Heat Map based on the location data within our DB. So I need to query for counts in each region and then generate a heat map tile. They are being created on the fly each time cesium requests the tile because the parameters for the heatmap could be different for each user.

Okay, that clarifies things a bit.

Not sure if I have a specific answer for you. I can tell you that there’s some variations on tiling schemes out there. Google apparently uses 1x1 at level 0, but 2x1 is another frequently used approach. Uh… some relevant keywords to look for are “EPSG:4326”, “Plate Carree”, and “2x1”, and some related links are at http://gis.stackexchange.com/questions/51906/leaflet-and-epsg-4326-projections , https://github.com/Leaflet/Leaflet/issues/1207 , https://github.com/Leaflet/Leaflet/issues/2540 , http://mapserver.org/mapcache/services.html , and http://osgeo-org.1560.x6.nabble.com/MapCache-and-the-GoogleCRS84Quad-TileMatrixSet-td5045603.html . You may also want to glance in the Cesium source at /Source/Core/GeographicTilingScheme.js.

There may also be some relevant code in the gdal2tiles.py open-source script, of which there are a gazillion forks floating around. The “main” version technically lives inside of GDAL’s codebase at https://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/scripts/gdal2tiles.py , although it’s apparently not been maintained much. Should have some useful code, I think.

UrlTemplateImageryProvider uses GeographicTilingScheme by default, which has two tiles at the root. If you want to use Web Mercator, construct it with “tilingScheme: new Cesium.WebMercatorTilingScheme()”.

Actually, sorry, I’m mistaken, UrlTemplateImageryProvider defaults to Web Mercator, not Geographic. As long as you’re not specifying GeographicTilingScheme explicitly, I’m not sure why you’d see two tiles at the root. Maybe share the code you’re using to construct the UrlTemplateImageryProvider?

Kevin

Oh man…I want to punch myself in the face. I had copied the URLTemplateImageryProvider config from the samples which used the GeographicTilingScheme! So I removed that so it uses the WebMercatorTilingScheme and voila! It works! Thanks for getting me to re-check the simple things.