Web mapping tools using tiles use a variant of the Mercator Projection.
This can lead to some significant distortions: you can see this for yourself by zooming out in google maps, and scrolling around. The scale (bottom right) will change, depending on where you are on the globe. Locally, the distortion is not too bad, but tiles from different areas of the globe cannot be directly compared.
Internally, the projection maps the whole globe (between latitudes about -85 to 85 degrees) to a unit square:
In [1]:
import tilemapbase
tilemapbase.start_logging()
tilemapbase.tiles.build_OSM().get_tile(0,0,0)
Out[1]:
The standards EPSG:3857 or EPSG:3785 are mentioned in relation to the "web mercator" projection.
The following (reproduced in tilemapbase) shows that the projections are the same, up to a rescaling, and flipping the y axis.
(It is curious to compare the text in the above two links, which to a causual reader might warn against using 3857 while 3785 is fine; they are both identical...)
In [2]:
import pyproj
p3857 = pyproj.Proj({"init": "epsg:3857"})
p3785 = pyproj.Proj({"init": "epsg:3785"})
In [3]:
scale = 20037508.342789244
def rescale(x, y):
return ((x - 0.5) * 2 * scale, (0.5 - y) * 2 * scale)
import random, math
diffs = []
for _ in range(10000):
x = random.random() * 360 - 180
y = random.random() * 170 - 85
assert p3857(x, y) == p3785(x, y)
xx, yy = p3857(x, y)
xxx, yyy = rescale(*tilemapbase.project(x, y))
diffs.append( math.sqrt((xx - xxx)**2 + (yy - yyy)**2) )
In [4]:
max(diffs), sum(diffs) / 10000
Out[4]:
To support the Ordance Survey (raster) tiles, we need to use the Ordnance Survey National Grid.
transform method of pyproj. CreditFor example:
Further information: https://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/formats-for-developers.html
In [5]:
import pyproj, functools
bng = pyproj.Proj(init="epsg:27700")
wgs84 = pyproj.Proj(init="epsg:4326")
def project(lon, lat):
return pyproj.transform(wgs84, bng, lon, lat)
print(project(-1.55532, 53.80474))
print(project(-5.71808, 50.06942))
print(project(-3.02516, 58.64389))
In [ ]: