I've been Slippy Tiles Wiki page for equations to convert lat/long values (given via the user) to tile references, and then work with the data relating to the tile.
My problem is the wiki's equation always does one of the following:
-
Returns a location 20+ miles away from my given lat/long. The range is ~18 miles to 200+ miles, no consistency.
-
Returns absolutely nothing, and the tile_row value (XXXXX) is always off by a considerable amount. This ranges from 40 (10810 instead of 10850) to 300+ (10417 in stead of 10817).
This happens for all lat longs, sourced from varying online mapping tools. So far I've tested this with Google Maps, OSM's own browsing tool and used lat/long generation tools for random locations across the UK.
Here's my code so far:
public void UserQuery()
{
Console.Write("Please enter a latitude value: ");
double userLat = Convert.ToDouble(Console.ReadLine());
Console.Write("Please enter a longitude value: ");
double userLong = Convert.ToDouble(Console.ReadLine());
_merc.TileLat = Math.Floor((1.0 - Math.Log(Math.Tan(DegreesToRadians(userLat)) + 1.0 / Math.Cos(DegreesToRadians(userLat))) / Math.PI) * (1 << ZoomLevel));
_merc.TileLong = Math.Floor((userLong + 180.0) / 360.0 * (1 << ZoomLevel));
}
private double DegreesToRadians(double angle)
{
return Math.PI * angle / 180;
}
The longitude value works perfectly everytime, it's just in there for reference.
The wiki's version of the equation is:
((1.0 - Math.Log(Math.Tan(lat * Math.PI / 180.0) +
1.0 / Math.Cos(lat * Math.PI / 180.0)) / Math.PI) / 2.0 * (1 << zoom));
but my problem is that the last / 2
before bitshifting returns a value half of what's generally expected, so 5308
instead of 10616
. In terms of changes made to the equation, that's the only difference. I created a small method to work out radians => degrees because the original was hard to read and track (problems with brackets).
Thanks for any help in advance, this has put me at a standstill for upwards of 2 days now.
asked
06 Jul '16, 11:08
JamesGould
196●9●10●20
accept rate:
33%
Looking at the history, I see a large number of edits by a wiki editor who has caused problems with equations in the past (the one who used "coherent variant names" in a comment).
I'd suggest looking back in the history http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenames&action=history , finding a version before their first edit, and using the equations from there.
If that works, paste those equations into the current page.
@SomeoneElse thank you so much. Thishad me and a few colleagues confused, I thought I was being an idiot and not using the given equation properly but if it's incorrect in the CE wiki then I can see why it'd be a problem. On the hunt I go...
@SomeoneElse tried and used the equations past said wiki user (my god a lot of edits) and the result has been the same. I was informed on SO that bitshifting wasn't the same as using
Math.Pow(2, zoomLevel)
so I tried the older equations with both and the result remained the same, for reference.Did you mix up lat and lon by chance? Also take a look at WebCalc which produces valid results and (roughly) uses the JavaScript example code from the Wiki. It might help while debugging your application.
@scai I don't believe so no. I swapped the equations around and it came back with both the lat and long incorrect, rather than just the lat. I queried the same UK based lat/long in WebCalc and the result was the same as my application, but it doesn't exist in the database. Even all values, not taking the zoom_level as a parameter gave me back 0 results.
WebCalc returned the same values as your application? Please tell us your exact input and output.
@scai correct it did. My inputs are
lat: 52.298059
,long: -0.1275920
using zoom 14- these should resolve to 10 Downing Street, London.The output for the values are:
X: 8186
(tile column) andY: 5448
(tile row). I'm using a UK based .mbtiles file from osm2vectortiles.org. My SQL query is:string query = string.Format("SELECT tile_data FROM tiles WHERE zoom_level = {0} AND tile_column = {1} AND tile_row = {2}", ZoomLevel, _merc.TileLong, _merc.TileLat);
Nope, lat 52.2981 lon -0.1276 is not in London. 10 Downing Street, London is lat 51.50345 lon -0.12710 and has tile 261958/174348 for zoom level 19 and 8186/5448 for zoom level 14.
@scai I honestly have no idea what's going on. I just queried the lat/long you gave me above for downing street and it's given me a tile about 100 miles away. Do OSM provide their own vector tiles that I can query using SQL or something similar? I can't tell if it's my code or the data I'm using that's the issue.
No, OSM doesn't provide vector tiles. To be exact, OSM doesn't provide any tiles at all, just map data. And the official tile server for OSM provides just raster tiles.
Regarding WebCalc and the numbers from my previous comment: If I enter these numbers into WebCalc (zoom 14, lon -0.12710, lat 51.50345) then it correctly returns 8186 for X and 5448 for Y.
@scai if I use those lat/longs above and query the tile in the osm2vectortiles.org united_kingdom.mbtiles file, it gives back data from west sussex, about 50 miles south of the lat long query location. Is that going to be a problem with my code or a problem with the data? This is all using zoom level 14.
Silly question - but are you sure that the data in united_kingdom.mbtiles is correct (i.e. are you aware of anyone using it and creating maps with it), and are you sure that the "slippy map tilenames" page also applies to data in it?
@SomeoneElse me and a collegaue have just gone through it all and came to the same concluson - the data is wrong. We couldn't find a source for the database used in WebCalc (if you know it please tell me!) so I'm using the data I have right now (sourced from osm2vectortiles) and start working on figuring out lat long tile values from the max/min bounds of the DB.
It is possible that mbtiles are based on a different calculation model. The algorithms from the slippy map tilenames page apply to OSM's raster map tiles and can be completely wrong for other tiles.
@scai ah that would make a lot of sense as to why they're working with the online browser and not the db I've got. I'll get cracking, thank you both for your help.