Skip to content

Instantly share code, notes, and snippets.

@ianrenton
Last active April 13, 2025 16:59
Show Gist options
  • Save ianrenton/9ede79e9f6b196a423a0530dafe66538 to your computer and use it in GitHub Desktop.
Save ianrenton/9ede79e9f6b196a423a0530dafe66538 to your computer and use it in GitHub Desktop.
Arbitrary precision Maidenhead grid to lat/lon conversion in JavaScript
// Convert a Maidenhead grid reference of arbitrary previcision to lat/long.
function latLonForGrid(grid) {
// Make sure we are in upper case so our maths works. Case is arbitrary for Maidenhead references
grid = grid.toUpperCase();
// Return null if our Maidenhead string is invalid or too short
let len = grid.length;
if (len <= 0 || (len % 2) !== 0) {
return null;
}
let lat = 0.0; // aggregated latitude
let lon = 0.0; // aggregated longitude
let latCellSize = 10; // Size in degrees latitude of the current cell. Starts at 20 and gets smaller as the calculation progresses
let lonCellSize = 20; // Size in degrees longitude of the current cell. Starts at 20 and gets smaller as the calculation progresses
let latCellNo; // grid latitude cell number this time
let lonCellNo; // grid longitude cell number this time
// Iterate through blocks (two-character sections)
for (let block = 0; block * 2 < len; block += 1) {
if (block % 2 === 0) {
// Letters in this block
lonCellNo = grid.charCodeAt(block * 2) - 'A'.charCodeAt(0);
latCellNo = grid.charCodeAt(block * 2 + 1) - 'A'.charCodeAt(0);
} else {
// Numbers in this block
lonCellNo = parseInt(grid.charAt(block * 2));
latCellNo = parseInt(grid.charAt(block * 2+1));
}
// Aggregate the angles
lat += latCellNo * latCellSize;
lon += lonCellNo * lonCellSize;
// Reduce the cell size for the next block, unless we are on the last cell. If we are on the last cell, instead
// move the position into the middle of the cell rather than its south-west corner.
if (block * 2 < len - 2) {
// Still have more work to do, so reduce the cell size
if (block % 2 === 0) {
// Just dealt with letters, next block will be numbers so cells will be 1/10 the current size
latCellSize = latCellSize / 10.0;
lonCellSize = lonCellSize / 10.0;
} else {
// Just dealt with numbers, next block will be letters so cells will be 1/24 the current size
latCellSize = latCellSize / 24.0;
lonCellSize = lonCellSize / 24.0;
}
} else {
// This is the last block, so move the marker to the middle.
lat += latCellSize / 2;
lon += lonCellSize / 2;
}
}
// Offset back to (-180, -90) where the grid starts
lon -= 180.0;
lat -= 90.0;
return [lat, lon];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment