F#: GPS Midpoint and Distance functions

I scoured the internet and hacked together some F# functions.

These functions include the following:
1. Calculate distance between two coordinates
2. Calculate midpoint between two coordinates

Here’s the code I cobbled together:

namespace CourierDispatch.Domain

open System
open CourierDispatch.Language

module GPS =

    let convertToRadians(angle:double)          = (Math.PI / 180.0) * angle
    let convertRadiansToDegrees(radians:double) = (180.0 / Math.PI) * radians

    let midpoint (lat1':double) (lon1':double) (lat2':double) (lon2':double) =

        let dLon = convertToRadians(lon2' - lon1')

        let lat1 = convertToRadians(lat1')
        let lat2 = convertToRadians(lat2')
        let lon1 = convertToRadians(lon1')

        let bx = Math.Cos(lat2) * Math.Cos(dLon)
        let by = Math.Cos(lat2) * Math.Sin(dLon)

        let lat3 = Math.Atan2(Math.Sin(lat1) + Math.Sin(lat2), Math.Sqrt((Math.Cos(lat1) + bx) * (Math.Cos(lat1) + bx) + by * by))
        let lon3 = lon1 + Math.Atan2(by, Math.Cos(lat1) + bx)

        (convertRadiansToDegrees(lat3), convertRadiansToDegrees(lon3))

    let calculateDistance (p1Latitude,p1Longitude) (p2Latitude,p2Longitude) =

        let r    = 6371.0
        let dLat = convertToRadians (p2Latitude  - p1Latitude) 
        let dLon = convertToRadians (p2Longitude - p1Longitude)
        let lat1 = convertToRadians p1Latitude
        let lat2 = convertToRadians p2Latitude

        let a = Math.Sin(dLat/2.0) * Math.Sin(dLat/2.0) +
                Math.Sin(dLon/2.0) * Math.Sin(dLon/2.0) * Math.Cos(lat1) * Math.Cos(lat2)

        let c = 2.0 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1.0-a))
        let kilometers = r * c
        let miles      = (float)kilometers * 0.621371

    let withinMilesRadius (miles:float) (coordinate1:Coordinate) (coordinate2:Coordinate) =
        let p1 = coordinate1.Latitude,coordinate1.Longitude
        let p2 = coordinate2.Latitude,coordinate2.Longitude

        calculateDistance p1 p2 <= miles

    let within3MileRadius = withinMilesRadius 3.0

One Reply to “F#: GPS Midpoint and Distance functions”

  1. Are you using this? https://en.wikipedia.org/wiki/Haversine_formula

    Or did you find an even more accurate model?

    I think it would be nice if you added some comments with links to your sources.

    Also, I would be careful about introducing floats in the middle of the calculations, because the rounding errors might add up to something significant. For instance, the convertToRadians function returns a float unless you use double Math.PI.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: