72 lines
2.2 KiB
Go
72 lines
2.2 KiB
Go
|
|
// geodist is a package created by jftuga
|
|
// Repository: github.com/jftuga/geodist
|
|
// It is used to calculate distance between latitude/longitude points
|
|
|
|
package geodist
|
|
|
|
import "seekia/internal/helpers"
|
|
import "errors"
|
|
|
|
import "math"
|
|
|
|
// The below function is adapted from github.com/jftuga/geodist
|
|
|
|
// HaversineDistance returns the distance (in miles) 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.
|
|
//
|
|
// https://en.wikipedia.org/wiki/Haversine_formula
|
|
|
|
//Outputs:
|
|
// -float64: Distance in kilometers
|
|
// -error
|
|
func GetDistanceBetweenCoordinates(aCoordinateLatitude float64, aCoordinateLongitude float64, bCoordinateLatitude float64, bCoordinateLongitude float64) (float64, error) {
|
|
|
|
aLatitudeIsValid := helpers.VerifyLatitude(aCoordinateLatitude)
|
|
if (aLatitudeIsValid == false){
|
|
return 0, errors.New("GetDistanceBetweenCoordinates called with invalid aCoordinateLatitude.")
|
|
}
|
|
aLongitudeIsValid := helpers.VerifyLongitude(aCoordinateLongitude)
|
|
if (aLongitudeIsValid == false){
|
|
return 0, errors.New("GetDistanceBetweenCoordinates called with invalid aCoordinateLongitude.")
|
|
}
|
|
|
|
bLatitudeIsValid := helpers.VerifyLatitude(bCoordinateLatitude)
|
|
if (bLatitudeIsValid == false){
|
|
return 0, errors.New("GetDistanceBetweenCoordinates called with invalid bCoordinateLatitude.")
|
|
}
|
|
bLongitudeIsValid := helpers.VerifyLongitude(bCoordinateLongitude)
|
|
if (bLongitudeIsValid == false){
|
|
return 0, errors.New("GetDistanceBetweenCoordinates called with invalid bCoordinateLongitude.")
|
|
}
|
|
|
|
// Convert to radians
|
|
|
|
piRad := math.Pi / 180
|
|
|
|
la1 := aCoordinateLatitude * piRad
|
|
lo1 := aCoordinateLongitude * piRad
|
|
la2 := bCoordinateLatitude * piRad
|
|
lo2 := bCoordinateLongitude * piRad
|
|
|
|
r := float64(6378100) // Earth radius in meters
|
|
|
|
// haversin(θ) function
|
|
hsin := func(theta float64) float64 {
|
|
result := math.Pow(math.Sin(theta/2), 2)
|
|
return result
|
|
}
|
|
|
|
h := hsin(la2-la1) + math.Cos(la1) * math.Cos(la2) * hsin(lo2-lo1)
|
|
|
|
meters := 2 * r * math.Asin(math.Sqrt(h))
|
|
kilometers := meters / 1000
|
|
|
|
return kilometers, nil
|
|
}
|
|
|
|
|