Last active
April 13, 2025 16:59
-
-
Save ianrenton/9ede79e9f6b196a423a0530dafe66538 to your computer and use it in GitHub Desktop.
Arbitrary precision Maidenhead grid to lat/lon conversion in JavaScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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