Download this file
| 1 | // Package geo turns a timezone or an IP into a point on the globe and picks |
| 2 | // the nearest of a set of AWS regions (nearest-region spec §6). It holds |
| 3 | // points only for the length of one call: nothing here stores, logs or |
| 4 | // returns a caller's coordinates. |
| 5 | package geo |
| 6 | |
| 7 | import "math" |
| 8 | |
| 9 | // Point is a latitude and longitude in degrees. |
| 10 | type Point struct{ Lat, Lon float64 } |
| 11 | |
| 12 | // earthRadiusKm is the IUGG mean Earth radius. |
| 13 | const earthRadiusKm = 6371.0088 |
| 14 | |
| 15 | // DistanceKm is the great-circle (haversine) distance between a and b. |
| 16 | func DistanceKm(a, b Point) float64 { |
| 17 | rad := func(d float64) float64 { return d * math.Pi / 180 } |
| 18 | dLat := rad(b.Lat - a.Lat) |
| 19 | dLon := rad(b.Lon - a.Lon) |
| 20 | h := math.Sin(dLat/2)*math.Sin(dLat/2) + |
| 21 | math.Cos(rad(a.Lat))*math.Cos(rad(b.Lat))*math.Sin(dLon/2)*math.Sin(dLon/2) |
| 22 | return 2 * earthRadiusKm * math.Asin(math.Sqrt(h)) |
| 23 | } |
| 24 | |