Web Mercator Projection
Coordinates of places around the world are given in latitude and longitude. They are expressed in degrees and look like this: . This post is a short explanation of them and how to convert them to meters.
Worth knowing
A reference ellipsoid approximates the shape of the Earth – almost a sphere but slightly flattened. A geodetic datum provides the reference framework for coordinates such as longitude () and latitude ().
The Mercator projection is cylindrical and conformal, meaning it preserves local angles. The poles project infinitely far away. The usual Web Mercator tile scheme clips latitude to to make the projected world a square.
On web, starting with Google Maps, another very similar projection, called Web Mercator, is used. What makes it different from the standard one is that while it uses the same coordinates from the WGS84 standard, it projects them as if they were defined on a sphere. It might sound like a bad idea to completely abandon the notion of Earth being not a perfect sphere. Turns out, it doesn’t really matter compared to the distortion created by the Mercator itself. And it makes the math much easier.
Web Mercator is used by, just to name a few, Google Maps, Bing Maps, Apple Maps, OpenStreetMap. Pretty much the whole web map industry. So unless for a special use case, there’s little reason to go back to the standard one.
The formulas
Now the most interesting part – the formulas for translating degrees to projected meters. Keep in mind that these are not ground distances. The local scale grows as we move away from the Equator.
Variables
– semi-major axis of the ellipsoid (radius at the Equator)
– eccentricity of the ellipsoid (shape of the ellipsoid)
– latitude (in radians)
– longitude (in radians)
Mercator
Web Mercator
The TypeScript code for doing the conversion using Web Mercator goes like this (it includes conversion from degrees to radians):
const RADIUS = 6378137.0;
function degreesToMeters(lat: number, lng: number) {
return {
x: (RADIUS * lng * Math.PI) / 180.0,
y: RADIUS * Math.atanh(Math.sin((lat * Math.PI) / 180.0)),
};
}
If you want to convert back, from meters to degrees, here is an inverted function:
function metersToDegrees(x: number, y: number) {
return {
lng: ((x / RADIUS) * 180.0) / Math.PI,
lat: (Math.asin(Math.tanh(y / RADIUS)) * 180.0) / Math.PI,
};
}
Cool resources
- NGA’s Position on ’Web-Mercator’ – I owe them the most readable formulas for conversion on the Internet.
- Implications of Web Mercator and Its Use in Online Mapping – cool paper that taught me the difference between the (Web) Mercator.
- Wolfram Alpha on the inverse of hyperbolic tangent – thanks to them I learned about the
atanh()and stopped converting to other form using .