4 people like it.
Like the snippet!
calculating the distance on earth (with units of measure)
calculating the distance between two locations on earth using haversine formula
see http://en.wikipedia.org/wiki/Haversine_formula
and implementing it using the posibilities of F#'s unit of measure system to avoid unit-conversion-errors concerning radians
convertet the code found here: http://www.movable-type.co.uk/scripts/latlong.html for an concrete implementation
1:
2:
3:
4:
|
[<Measure>] type rad
[<Measure>] type deg
[<Measure>] type km
type Location = { Latitude : float<deg>; Longitude : float<deg> }
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
|
let GreatCircleDistance<[<Measure>] 'u> (R : float<'u>) (p1 : Location) (p2 : Location) =
let degToRad (x : float<deg>) = System.Math.PI * x / 180.0<deg/rad>
let sq x = x * x
// take the sin of the half and square the result
let sinSqHf (a : float<rad>) = (System.Math.Sin >> sq) (a / 2.0<rad>)
let cos (a : float<deg>) = System.Math.Cos (degToRad a / 1.0<rad>)
let dLat = (p2.Latitude - p1.Latitude) |> degToRad
let dLon = (p2.Longitude - p1.Longitude) |> degToRad
let a = sinSqHf dLat + cos p1.Latitude * cos p2.Latitude * sinSqHf dLon
let c = 2.0 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1.0-a))
R * c
|
1:
|
let GreatCircleDistanceOnEarth = GreatCircleDistance 6371.0<km>
|
1:
2:
3:
4:
5:
|
let p1 = { Latitude = 53.147222222222222222222222222222<deg>; Longitude = 0.96666666666666666666666666666667<deg> }
let p2 = { Latitude = 52.204444444444444444444444444444<deg>; Longitude = 0.14055555555555555555555555555556<deg> }
GreatCircleDistanceOnEarth p1 p2
|
Multiple items
type MeasureAttribute =
inherit Attribute
new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
--------------------
new : unit -> MeasureAttribute
[<Measure>]
type rad
Full name: Script.rad
[<Measure>]
type deg
Full name: Script.deg
[<Measure>]
type km
Full name: Script.km
type Location =
{Latitude: float<deg>;
Longitude: float<deg>;}
Full name: Script.Location
Location.Latitude: float<deg>
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
Location.Longitude: float<deg>
val GreatCircleDistance : R:float<'u> -> p1:Location -> p2:Location -> float<'u>
Full name: Script.GreatCircleDistance
val R : float<'u>
val p1 : Location
val p2 : Location
val degToRad : (float<deg> -> float<rad>)
val x : float<deg>
namespace System
type Math =
static val PI : float
static val E : float
static member Abs : value:sbyte -> sbyte + 6 overloads
static member Acos : d:float -> float
static member Asin : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member BigMul : a:int * b:int -> int64
static member Ceiling : d:decimal -> decimal + 1 overload
static member Cos : d:float -> float
...
Full name: System.Math
field System.Math.PI = 3.14159265359
val sq : (float -> float)
val x : float
val sinSqHf : (float<rad> -> float)
val a : float<rad>
System.Math.Sin(a: float) : float
val cos : (float<deg> -> float)
val a : float<deg>
System.Math.Cos(d: float) : float
val dLat : float<rad>
val dLon : float<rad>
val a : float
val c : float
System.Math.Atan2(y: float, x: float) : float
System.Math.Sqrt(d: float) : float
val GreatCircleDistanceOnEarth : (Location -> Location -> float<km>)
Full name: Script.GreatCircleDistanceOnEarth
val p1 : Location
Full name: Script.p1
val p2 : Location
Full name: Script.p2
More information