Contents

Maidenhead Locators

Calculating Maidenhead Locators from Latitude and Longitude

Contents
Updated on 2021-03-12

Maidenhead Locators

Comprise 4 pairs of characters, each pair representing Longitude, Latitude.

AB12cd34

Where -

  • A & B are Base 18 (A..R)
  • 1 & 2 are Base 10 (0..9)
  • c & d are Base 24 (a..x)
  • 3 & 4 are Base 10 (0..9)

Giving a total range in each direction of 0..43199

Calculation

To calculate using integer arithmatic, scale to 0..43199

1
2
lon = int((longitude + 180) * 120)
lat = int((latitude + 90) * 240)

Using int is fine, each square runs from 0 to 0.9999… so drop the non-integer part.

Then break down

1
2
3
4
5
6
lon1 = int(lon/2400)
lon = lon % 2400
lon2 = int(lon/240)
lon = lon % 240
lon3 = int(lon/10)
lon4 = lon % 10

(And the same for lat)

Convert the 2nd and 4th to Strings, and the 1st and 3rd to letters (1st uppercase, 3rd lowercase)

Extending The CLLocacion class to return Maidenhead strings -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
extension CLLocation {
    var latitude: Double {
        return self.coordinate.latitude
    }
    var longitude: Double {
        return self.coordinate.longitude
    }
    var maidenhead: String {

        // Derive Maidenhead locator from lattitude and longditude

        let upper = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X"]
        let lower = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x"]

        // Convert latitute and longitude into positive integers ranging 0..43199

        var lat = Int((self.coordinate.latitude + 90.0) * 240)
        var lon = Int((self.coordinate.longitude + 180.0) * 120)

        // First component is base 18. (A..R) - 43200 / 18 leaves 2400

        let lat1 = upper[Int(lat / 2400)]
        let lon1 = upper[Int(lon / 2400)]

        lat = lat % 2400  // keep the remainders
        lon = lon % 2400

        // Second component is base 10 (0..9) - 2400 / 10 leaves 240

        let lat2 = String(Int(lat / 240))
        let lon2 = String(Int(lon / 240))

        lat = lat % 240  // keep the remainders
        lon = lon % 240

        // Third component is base 24 (a..x) - 240 / 24 = 10

        let lat3 = lower[Int(lat / 10)]
        let lon3 = lower[Int(lon / 10)]

        // Final component is the remaining base 10

        let lat4 = String(lat % 10)
        let lon4 = String(lon % 10)

        return lon1 + lat1 + lon2 + lat2 + lon3 + lat3 + lon4 + lat4
    }
}