Skip to content

Instantly share code, notes, and snippets.

@jhurliman
Created May 10, 2021 19:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhurliman/13e8976f26f7cb53f0981c94769a3f63 to your computer and use it in GitHub Desktop.
Save jhurliman/13e8976f26f7cb53f0981c94769a3f63 to your computer and use it in GitHub Desktop.
Latitude/Longitude conversion to UTM in TypeScript
export type UTM = {
easting: number;
northing: number;
zoneNumber: number;
};
export function LatLngToUtm(
lat: number,
lng: number,
zoneNumber?: number,
a = 6378137,
eccSquared = 0.00669438
): UTM {
const lngTemp = lng;
const latRad = toRadians(lat);
const lngRad = toRadians(lngTemp);
zoneNumber ??= LatLngToUtmZone(lat, lng);
const lngOrigin = (zoneNumber - 1) * 6 - 180 + 3; // +3 puts origin in middle of zone
const lngOriginRad = toRadians(lngOrigin);
const eccPrimeSquared = eccSquared / (1 - eccSquared);
const N = a / Math.sqrt(1 - eccSquared * Math.sin(latRad) * Math.sin(latRad));
const T = Math.tan(latRad) * Math.tan(latRad);
const C = eccPrimeSquared * Math.cos(latRad) * Math.cos(latRad);
const A = Math.cos(latRad) * (lngRad - lngOriginRad);
const M =
a *
((1 -
eccSquared / 4 -
(3 * eccSquared * eccSquared) / 64 -
(5 * eccSquared * eccSquared * eccSquared) / 256) *
latRad -
((3 * eccSquared) / 8 +
(3 * eccSquared * eccSquared) / 32 +
(45 * eccSquared * eccSquared * eccSquared) / 1024) *
Math.sin(2 * latRad) +
((15 * eccSquared * eccSquared) / 256 + (45 * eccSquared * eccSquared * eccSquared) / 1024) *
Math.sin(4 * latRad) -
((35 * eccSquared * eccSquared * eccSquared) / 3072) * Math.sin(6 * latRad));
let easting =
0.9996 *
N *
(A +
((1 - T + C) * A * A * A) / 6 +
((5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A) / 120) +
500000.0;
let northing =
0.9996 *
(M +
N *
Math.tan(latRad) *
((A * A) / 2 +
((5 - T + 9 * C + 4 * C * C) * A * A * A * A) / 24 +
((61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A) / 720));
if (lat < 0) northing += 10000000.0;
return { easting, northing, zoneNumber };
}
export function LatLngToUtmZone(lat: number, lng: number): number {
if (lng >= 8 && lng <= 13 && lat > 54.5 && lat < 58) {
return 32;
} else if (lat >= 56.0 && lat < 64.0 && lng >= 3.0 && lng < 12.0) {
return 32;
}
if (lat >= 72.0 && lat < 84.0) {
if (lng >= 0.0 && lng < 9.0) {
return 31;
} else if (lng >= 9.0 && lng < 21.0) {
return 33;
} else if (lng >= 21.0 && lng < 33.0) {
return 35;
} else if (lng >= 33.0 && lng < 42.0) {
return 37;
}
}
return Math.floor((lng + 180) / 6 + 1);
}
export function getUtmZoneLetter(latitude: number): string {
if (84 >= latitude && latitude >= 72) return "X";
else if (72 > latitude && latitude >= 64) return "W";
else if (64 > latitude && latitude >= 56) return "V";
else if (56 > latitude && latitude >= 48) return "U";
else if (48 > latitude && latitude >= 40) return "T";
else if (40 > latitude && latitude >= 32) return "S";
else if (32 > latitude && latitude >= 24) return "R";
else if (24 > latitude && latitude >= 16) return "Q";
else if (16 > latitude && latitude >= 8) return "P";
else if (8 > latitude && latitude >= 0) return "N";
else if (0 > latitude && latitude >= -8) return "M";
else if (-8 > latitude && latitude >= -16) return "L";
else if (-16 > latitude && latitude >= -24) return "K";
else if (-24 > latitude && latitude >= -32) return "J";
else if (-32 > latitude && latitude >= -40) return "H";
else if (-40 > latitude && latitude >= -48) return "G";
else if (-48 > latitude && latitude >= -56) return "F";
else if (-56 > latitude && latitude >= -64) return "E";
else if (-64 > latitude && latitude >= -72) return "D";
else if (-72 > latitude && latitude >= -80) return "C";
else return "Z";
}
function toRadians(deg: number): number {
return (deg * Math.PI) / 180;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment