seekia/imported/geodist/geodist.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
}