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

Copy Source
Copy Link
Tools:

measures and type declerations

1: [<Measure>] type rad
2: [<Measure>] type deg
3: [<Measure>] type km
4: type Location = { Latitude : float<deg>; Longitude : float<deg> }

calculation with haversine-formula

 1: let GreatCircleDistance<[<Measure>] 'u> (R : float<'u>) (p1 : Location) (p2 : Location) =
 2:     let degToRad (x : float<deg>) = System.Math.PI * x / 180.0<deg/rad>
 3: 
 4:     let sq x = x * x
 5:     // take the sin of the half and square the result
 6:     let sinSqHf (a : float<rad>) = (System.Math.Sin >> sq) (a / 2.0<rad>)
 7:     let cos (a : float<deg>) = System.Math.Cos (degToRad a / 1.0<rad>)
 8: 
 9:     let dLat = (p2.Latitude - p1.Latitude) |> degToRad
10:     let dLon = (p2.Longitude - p1.Longitude) |> degToRad
11: 
12:     let a = sinSqHf dLat + cos p1.Latitude * cos p2.Latitude * sinSqHf dLon
13:     let c = 2.0 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1.0-a))
14: 
15:     R * c

using the mean-earth-radius

1: let GreatCircleDistanceOnEarth = GreatCircleDistance 6371.0<km>

example

1: let p1 = { Latitude = 53.147222222222222222222222222222<deg>; Longitude = 0.96666666666666666666666666666667<deg> }
2: 
3: let p2 = { Latitude = 52.204444444444444444444444444444<deg>; Longitude = 0.14055555555555555555555555555556<deg> }
4: 
5: GreatCircleDistanceOnEarth p1 p2
Multiple items
module Measure

from Microsoft.FSharp.Math

--------------------

type MeasureAttribute =
  class
    inherit System.Attribute
    new : unit -> MeasureAttribute
  end

Full name: Microsoft.FSharp.Core.MeasureAttribute

  type: MeasureAttribute
  implements: System.Runtime.InteropServices._Attribute
  inherits: System.Attribute
[<Measure>]
type rad

Full name: Snippet.rad
[<Measure>]
type deg

Full name: Snippet.deg
[<Measure>]
type km

Full name: Snippet.km
type Location =
  {Latitude: float<deg>;
   Longitude: float<deg>;}

Full name: Snippet.Location

  type: Location
  implements: System.IEquatable<Location>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Location>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
Location.Latitude: float<deg>
Multiple items
val float : 'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------

type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>

  type: float<'Measure>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'Measure>>
  implements: System.IEquatable<float<'Measure>>
  inherits: System.ValueType


--------------------

type float = System.Double

Full name: Microsoft.FSharp.Core.float

  type: float
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float>
  implements: System.IEquatable<float>
  inherits: System.ValueType
Location.Longitude: float<deg>
val GreatCircleDistance : float<'u> -> Location -> Location -> float<'u>

Full name: Snippet.GreatCircleDistance
Multiple items
val R : float<'u>

  type: float<'u>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'u>>
  implements: System.IEquatable<float<'u>>
  inherits: System.ValueType


--------------------

val R : float<'u>

  type: float<'u>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'u>>
  implements: System.IEquatable<float<'u>>
  inherits: System.ValueType
val p1 : Location

  type: Location
  implements: System.IEquatable<Location>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Location>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val p2 : Location

  type: Location
  implements: System.IEquatable<Location>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Location>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val degToRad : (float<deg> -> float<rad>)
val x : float<deg>

  type: float<deg>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<deg>>
  implements: System.IEquatable<float<deg>>
  inherits: System.ValueType
namespace System
type Math =
  class
    static val PI : float
    static val E : float
    static member Abs : System.SByte -> System.SByte
    static member Abs : int16 -> int16
    static member Abs : int -> int
    static member Abs : int64 -> int64
    static member Abs : float32 -> float32
    static member Abs : float -> float
    static member Abs : decimal -> decimal
    static member Acos : float -> float
    static member Asin : float -> float
    static member Atan : float -> float
    static member Atan2 : float * float -> float
    static member BigMul : int * int -> int64
    static member Ceiling : decimal -> decimal
    static member Ceiling : float -> float
    static member Cos : float -> float
    static member Cosh : float -> float
    static member DivRem : int * int * int -> int
    static member DivRem : int64 * int64 * int64 -> int64
    static member Exp : float -> float
    static member Floor : decimal -> decimal
    static member Floor : float -> float
    static member IEEERemainder : float * float -> float
    static member Log : float -> float
    static member Log : float * float -> float
    static member Log10 : float -> float
    static member Max : System.SByte * System.SByte -> System.SByte
    static member Max : System.Byte * System.Byte -> System.Byte
    static member Max : int16 * int16 -> int16
    static member Max : uint16 * uint16 -> uint16
    static member Max : int * int -> int
    static member Max : uint32 * uint32 -> uint32
    static member Max : int64 * int64 -> int64
    static member Max : uint64 * uint64 -> uint64
    static member Max : float32 * float32 -> float32
    static member Max : float * float -> float
    static member Max : decimal * decimal -> decimal
    static member Min : System.SByte * System.SByte -> System.SByte
    static member Min : System.Byte * System.Byte -> System.Byte
    static member Min : int16 * int16 -> int16
    static member Min : uint16 * uint16 -> uint16
    static member Min : int * int -> int
    static member Min : uint32 * uint32 -> uint32
    static member Min : int64 * int64 -> int64
    static member Min : uint64 * uint64 -> uint64
    static member Min : float32 * float32 -> float32
    static member Min : float * float -> float
    static member Min : decimal * decimal -> decimal
    static member Pow : float * float -> float
    static member Round : float -> float
    static member Round : decimal -> decimal
    static member Round : float * int -> float
    static member Round : float * System.MidpointRounding -> float
    static member Round : decimal * int -> decimal
    static member Round : decimal * System.MidpointRounding -> decimal
    static member Round : float * int * System.MidpointRounding -> float
    static member Round : decimal * int * System.MidpointRounding -> decimal
    static member Sign : System.SByte -> int
    static member Sign : int16 -> int
    static member Sign : int -> int
    static member Sign : int64 -> int
    static member Sign : float32 -> int
    static member Sign : float -> int
    static member Sign : decimal -> int
    static member Sin : float -> float
    static member Sinh : float -> float
    static member Sqrt : float -> float
    static member Tan : float -> float
    static member Tanh : float -> float
    static member Truncate : decimal -> decimal
    static member Truncate : float -> float
  end

Full name: System.Math
field System.Math.PI = 3.14159265359
val sq : (float -> float)
val x : float

  type: float
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float>
  implements: System.IEquatable<float>
  inherits: System.ValueType
val sinSqHf : (float<rad> -> float)
val a : float<rad>

  type: float<rad>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<rad>>
  implements: System.IEquatable<float<rad>>
  inherits: System.ValueType
System.Math.Sin(a: float) : float
val cos : (float<deg> -> float)
val a : float<deg>

  type: float<deg>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<deg>>
  implements: System.IEquatable<float<deg>>
  inherits: System.ValueType
System.Math.Cos(d: float) : float
val dLat : float<rad>

  type: float<rad>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<rad>>
  implements: System.IEquatable<float<rad>>
  inherits: System.ValueType
val dLon : float<rad>

  type: float<rad>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<rad>>
  implements: System.IEquatable<float<rad>>
  inherits: System.ValueType
val a : float

  type: float
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float>
  implements: System.IEquatable<float>
  inherits: System.ValueType
val c : float

  type: float
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float>
  implements: System.IEquatable<float>
  inherits: System.ValueType
System.Math.Atan2(y: float, x: float) : float
System.Math.Sqrt(d: float) : float
val R : float<'u>

  type: float<'u>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'u>>
  implements: System.IEquatable<float<'u>>
  inherits: System.ValueType
val GreatCircleDistanceOnEarth : (Location -> Location -> float<km>)

Full name: Snippet.GreatCircleDistanceOnEarth
val p1 : Location

Full name: Snippet.p1

  type: Location
  implements: System.IEquatable<Location>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Location>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val p2 : Location

Full name: Snippet.p2

  type: Location
  implements: System.IEquatable<Location>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Location>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable

More information

Link: http://fssnip.net/4a
Posted: 3 years ago
Author: Carsten König
Tags: Geocomputing; Haversine formula