geohash.go (1678B)
1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "strconv" 7 ) 8 9 // I wrote this script a long time ago and I copied an example algorithm from the internet 10 // I can't find that source now, but another example implementation can be seen here: 11 // https://www.movable-type.co.uk/scripts/geohash.html 12 13 const BASE_32 string = "0123456789bcdefghjkmnpqrstuvwxyz" 14 15 func printHelp() { 16 fmt.Println("Usage:") 17 fmt.Println(" geohash lat lon [precision]") 18 } 19 20 func main() { 21 if len(os.Args) < 3 { 22 printHelp() 23 os.Exit(1) 24 } 25 26 var lat string = os.Args[1] 27 var lon string = os.Args[2] 28 var precision string = "12" 29 if len(os.Args) == 4 { 30 precision = os.Args[3] 31 } 32 33 fmt.Println(encode(lat, lon, precision)) 34 } 35 36 func getFloat64(input string) float64 { 37 res, err := strconv.ParseFloat(input, 64) 38 if err != nil { 39 panic(err) 40 } 41 return res 42 } 43 44 func getInt(input string) int { 45 res, err := strconv.Atoi(input) 46 if err != nil { 47 panic(err) 48 } 49 return res 50 } 51 52 func encode(latInput, lonInput, precisionInput string) string { 53 var lat float64 = getFloat64(latInput) 54 var lon float64 = getFloat64(lonInput) 55 var precision int = getInt(precisionInput) 56 57 var n, s int = 0, 0 58 var o bool = true 59 var r, c, d, l float64 = -90, 90, -180, 180 60 var encodedString string = "" 61 62 for len(encodedString) < precision { 63 if o { 64 var e2 float64 = (d + l) / 2 65 if lon >= e2 { 66 n = 2 * n + 1 67 d = e2 68 } else { 69 n = n * 2 70 l = e2 71 } 72 } else { 73 var t2 float64 = (r + c) / 2 74 if lat >= t2 { 75 n = 2 * n + 1 76 r = t2 77 } else { 78 n = n * 2 79 c = t2 80 } 81 } 82 o = !o 83 s++ 84 if s == 5 { 85 encodedString = encodedString + string(BASE_32[n]) 86 s = 0 87 n = 0 88 } 89 } 90 91 return encodedString 92 }