Author: Paolo Lulli <paolo@lulli.net>
Explore geo query capabilities
server/geo/distances.go | 41 ++++++++++++++++++++++++++++++++++++++ server/geo/distances_test.go | 26 ++++++++++++++++++++++++
diff --git a/server/geo/distances.go b/server/geo/distances.go new file mode 100644 index 0000000000000000000000000000000000000000..94f7a0e323f9a42e48f947288d9e6f9e7c9c7dcf --- /dev/null +++ b/server/geo/distances.go @@ -0,0 +1,41 @@ +package geo + +import "math" + +type coordinate struct { + lat float64 + lon float64 +} + +// haversin(θ) function +func hsin(theta float64) float64 { + return math.Pow(math.Sin(theta/2), 2) +} + +// Distance function returns the distance (in meters) between two points of +// +// a given longitude and latitude relatively accurately (using a spherical +// approximation of the Earth) through the Haversin Distance Formula for +// great arc distance on a sphere with accuracy for small distances +// +// point coordinates are supplied in degrees and converted into rad. in the func +// +// distance returned is meters +// http://en.wikipedia.org/wiki/Haversine_formula +func Distance(coordinate1, coordinate2 coordinate) float64 { + // convert to radians + // must cast radius as float to multiply later + + var la1, lo1, la2, lo2, r float64 + la1 = coordinate1.lat * math.Pi / 180 + lo1 = coordinate1.lon * math.Pi / 180 + la2 = coordinate2.lat * math.Pi / 180 + lo2 = coordinate2.lon * math.Pi / 180 + + r = 6378100 // Earth radius in meters + + // calculate + h := hsin(la2-la1) + math.Cos(la1)*math.Cos(la2)*hsin(lo2-lo1) + + return 2 * r * math.Asin(math.Sqrt(h)) +} diff --git a/server/geo/distances_test.go b/server/geo/distances_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6c6b983bf8a4d1673fdd3e5b00a21ae5531f9e90 --- /dev/null +++ b/server/geo/distances_test.go @@ -0,0 +1,26 @@ +package geo + +import ( + "fmt" + "testing" +) + +func TestDistance(t *testing.T) { + + winnipeg := coordinate{49.895077, -97.138451} + regina := coordinate{50.445210, -104.618896} + + result := Distance(winnipeg, regina) + + fmt.Printf("%f\n", result) +} + +func TestGenerateAllNodes(t *testing.T) { + for lon := -180; lon <= 180; lon += 10 { + for lat := -90; lat <= 90; lat += 10 { + fmt.Printf("Lon: %d Lat: %d\n", lon, lat) + } + fmt.Printf("\n") + // lon += 10 + } +}