Movable Type Home Page

Movable Type Scripts


Convert between Latitude/Longitude &
UTM coordinates / MGRS grid references

The Universal Transverse Mercator coordinate system is a global system of grid-based mapping references.

UTM is in fact a set of 60 separate ‘transverse Mercator’ projections,1 covering 60 longitudinal zones each 6° wide. It covers latitudes spanning 80°S to 84°N (the poles are covered by the separate ‘UPS’ system). Latitude/longitude points are converted to eastings and northings measured in metres along (an ellipsoidal model of) the earth’s surface.

Functional demo

Enter (WGS84) latitude/longitude, UTM coordinates, or MGRS/NATO grid reference into the test boxes to try out the calculations (values are updated automatically on entry):

Lat/Long
UTM coordinate
MGRS grid reference
Grid convergence
Point scale factor

Lat/long as: deg/min/sec decimal degrees;
UTM to: m mm;
MGRS digits.

UTM

A Universal Transverse Mercator coordinate comprises a zone number, a hemisphere (N/S), an easting and a northing. Eastings are referenced from the central meridian of each zone, & northings from the equator, both in metres. To avoid negative numbers, ‘false eastings’ and ‘false northings’ are used:

Geokov has a good explanation.

Norway/Svalbard: the designers of UTM made two exceptions to the rule. The part of zone 31 covering western Norway is transferred to zone 32, and the zones covering Svalbard are tweaked to keep Svalbard in two zones (it’s easier to understand looking at a map). These widened zones are viable partly because zones are much narrower so far north, so little precision is lost in merging them.

Note that UTM coordinates get rounded, not truncated (unlike MGRS grid references).

MGRS

The Military Grid Reference System is an alternative way of representing UTM coordinates.

Instead of having monotonic eastings for a zone, and northings measured to/from the equator, zones are divided into latitude bands, then into 100km grid squares identified by letter-pairs, then eastings and northings within each 100km grid square.

Hence the UTM coordinate 31 N 303760 5787415 is equivalent to an MGRS grid reference of 31U CT 03760 87415.

Depending on the map scale or scope of interest the GZD, and even the 100km square identification, may be dropped. Similarly, depending on the accuracy required, the easting and northing may be given to 10 digits (specifying metres), to 8 digits, to 6 digits, or to just 4 digits (specifying kilometre squares).

Since UTM coordinates have to indicate which hemisphere they are in, it is important not to confuse the hemisphere indicator with a UTM ‘latitude band’ (since latitude bands also include ‘N’ and ‘S’). In these scripts, UTM coordinates have a space between the zone and the hemisphere indicator, and no 100km square indicator.

Note that MGRS grid references get truncated, not rounded (unlike UTM coordinates).

Accuracy

These scripts to calculate UTM eastings/northings from geodetic latitude/longitude and vice-versa implement Karney’s method, which (in the order n6 version used) gives results “accurate to 5 nm for distances up to 3,900 km from the central meridian” (improving on more familiar earlier methods from Snyder/Thomas/USDMA).

Such accuracy is laudable, but does open further issues. The now-ubiquitous geocentric global datum WGS-84 (World Geodetic System 1984) has no ‘physical realisation’ – it is not tied to geodetic groundstations, just to satellites – and is defined to be accurate to no better than around ±1 metre (good enough for most of us!).

A central problem is that at an accuracy of better than ±1 metre, plate tectonic movements become significant. Simplifying somewhat (well, actually, a lot!), the ITRS was developed, with ‘epoch’-dependant ITRFs, where the latitude/longitude coordinate of a position will vary over time.

Various ‘static’ reference frames are also defined for various continents – NAD-83 for North America, ETRS89 for Europe, GDA94 for Australia, etc – within which latitude/longitude coordinates remain fixed (at least to centimetre or so accuracy, major earthquake events excepted). These reference frames have ‘epoch’-dependant mappings to ITRF datums. (Due to plate tectonics, ETRS89 shifts against ITRF by about 25mm/year; GDA94 by around 80mm/year).

So if you are using the calculations given here to convert between geodetic latitude/longitude coordinates and UTM grid references, you can assure your users they have no accuracy concerns – but you may have a major task explaining datums and reference frames to them.

Remarkably, this accuracy comes in a very simple & concise implementation; having entirely failed even to begin to understand the mathematics, I find it a source of wonder that such an involved derivation can result in such a simple implementation – just a few dozen lines of code (though for those with better maths skills than mine, it seems well explained in Karney’s paper).

Performance

Using Chrome on a middling Core i5 PC, a latitude-longitude / UTM conversion takes around 0.01 – 0.02 milliseconds (hence around 50,000 – 100,000 per second).

Example usage of UTM / MGRS libraries

To convert a UTM coordinate to a (WGS-84) latitude/longitude point:

    <script type="module">
        import Utm from 'https://cdn.jsdelivr.net/npm/geodesy@2/utm.js';
        const utmCoord = Utm.parse('31 N 303189 5787193');
        const latLongP = utmCoord.toLatLon();
        console.log(latLongP.toString('d', 2)); // '52.20°N, 000.12°E'
    </script>

To convert a (WGS-84) latitude/longitude point to a UTM coordinate:

    <script type="module">
        import { LatLon } from 'https://cdn.jsdelivr.net/npm/geodesy@2/utm.js';
        const latLongP = new LatLon(52.2, 0.12);
        const utmCoord = latLongP.toUtm();
        console.log(utmCoord.toString()); // '31 N 303189 5787193'
    </script>

To convert an MGRS grid reference to a (WGS-84) latitude/longitude point:

    <script type="module">
        import Mgrs from 'https://cdn.jsdelivr.net/npm/geodesy@2/mgrs.js';
        const mgrsGrid = Mgrs.parse('31U CT 03189 87193');
        const utmCoord = mgrsGrid.toUtm();
        const latLongP = utmCoord.toLatLon();
        console.log(latLongP.toString('d', 2)); // '52.20°N, 000.12°E'
    </script>

To convert a (WGS-84) latitude/longitude point to an MGRS grid reference:

    <script type="module">
        import { LatLon } from 'https://cdn.jsdelivr.net/npm/geodesy@2/mgrs.js';
        const latLongP = new LatLon(52.2, 0.12);
        const utmCoord = latLongP.toUtm();
        const mgrsGRef = utmCoord.toMgrs();
        console.log(mgrsGRef.toString()); // '31U CT 03189 87193'
    </script>

See UTM and MGRS documentation for full details.


See below for the JavaScript source code, also available on GitHub. Full documentation is available, as well as a test suite

Note I use Greek letters in variables representing maths symbols conventionally presented as Greek letters (also primes ʹ U+02B9 & ʺ U+02BA): I value the great benefit in legibility over the minor inconvenience in typing (if you encounter any problems, ensure your <head> includes <meta charset="utf-8">, and/or use UTF-8 encoding when saving files).

With its untyped C-style syntax, JavaScript reads remarkably close to pseudo-code: exposing the algorithms with a minimum of syntactic distractions. These functions should be simple to translate into other languages if required, though can also be used as-is in browsers and Node.js.

For convenience & clarity, I have extended the base JavaScript Number object with toRadians() and toDegrees() methods: I don’t see great likelihood of conflicts, as these are ubiquitous operations.

OSI MIT License I offer these scripts for free use and adaptation to balance my debt to the open-source info-verse. You are welcome to re-use these scripts [under an MIT licence, without any warranty express or implied] provided solely that you retain my copyright notice and a link to this page.

If you need any advice or development work done, I am available for consultancy.

If you have any queries or find any problems, contact me at ku.oc.epyt-elbavom@oeg-stpircs.

© 2014–2020 Chris Veness