4 people like it.

Finding nearest airplane to a location

Given a location as a float tuple (latitude, longitude) it will return the plane closest nearby as a JsonValue using the OpenSky API. For fun also demonstrating some operator overloading with (-->) between two coordinates. I'm new to these functional languages, so please feel free to update the solution with interesting refactortings and whatnot.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
#r "FSharp.Data.dll"
open System
open FSharp.Data

let (-->) (lat1,lon1) (lat2,lon2) =
    let deg2rad deg = deg * (Math.PI/180.)
    let (dLat,dLon) = deg2rad (abs (lat1-lat2)), deg2rad (abs(lon1-lon2))
    let a =
        (sin(dLat / 2.)) * (sin(dLat / 2.)) +
        (cos(deg2rad(lat1))) * (cos(deg2rad(lat2))) *
        (sin(dLon/2.)) * (sin(dLon/2.))
    6371. * (2. * (atan2 (sqrt a) (sqrt (1. - a))))

let nearestPlane location : JsonValue =
    let url = "https://opensky-network.org/api/states/all"
    let valueJSON = JsonValue.Load(url)
    let n = Array.length (valueJSON.["states"].AsArray())
    let rec findPlane i recordPlane recordDistance =
        if i = n then recordPlane
        else
            let state = valueJSON.["states"].[i]
            if state.[5] = JsonValue.Null || state.[6] = JsonValue.Null then
                findPlane (i+1) recordPlane recordDistance 
            else 
                let distance = location --> (state.[6].AsFloat(), state.[5].AsFloat())
                if recordDistance > distance then
                    findPlane (i+1) state distance
                else findPlane (i+1) recordPlane recordDistance
    findPlane 0 (JsonValue.Null) (1e99)

//Examples:
nearestPlane (51.507351, -0.127758)     //-- London
nearestPlane (48.860731, 2.342342)      //-- Paris
nearestPlane (35.708628, 139.731891)    //-- Tokyo
namespace System
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
val lat1 : float
val lon1 : float
val lat2 : float
val lon2 : float
val deg2rad : (float -> float)
val deg : float
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 Math.PI = 3.14159265359
val dLat : float
val dLon : float
val abs : value:'T -> 'T (requires member Abs)

Full name: Microsoft.FSharp.Core.Operators.abs
val a : float
val sin : value:'T -> 'T (requires member Sin)

Full name: Microsoft.FSharp.Core.Operators.sin
val cos : value:'T -> 'T (requires member Cos)

Full name: Microsoft.FSharp.Core.Operators.cos
val atan2 : y:'T1 -> x:'T1 -> 'T2 (requires member Atan2)

Full name: Microsoft.FSharp.Core.Operators.atan2
val sqrt : value:'T -> 'U (requires member Sqrt)

Full name: Microsoft.FSharp.Core.Operators.sqrt
val nearestPlane : float * float -> JsonValue

Full name: Script.nearestPlane
val location : float * float
type JsonValue =
  | String of string
  | Number of decimal
  | Float of float
  | Record of properties: (string * JsonValue) []
  | Array of elements: JsonValue []
  | Boolean of bool
  | Null
  member Request : uri:string * ?httpMethod:string * ?headers:seq<string * string> -> HttpResponse
  member RequestAsync : uri:string * ?httpMethod:string * ?headers:seq<string * string> -> Async<HttpResponse>
  override ToString : unit -> string
  member ToString : saveOptions:JsonSaveOptions -> string
  member WriteTo : w:TextWriter * saveOptions:JsonSaveOptions -> unit
  static member AsyncLoad : uri:string * ?cultureInfo:CultureInfo -> Async<JsonValue>
  static member private JsonStringEncodeTo : w:TextWriter -> value:string -> unit
  static member Load : uri:string * ?cultureInfo:CultureInfo -> JsonValue
  static member Load : reader:TextReader * ?cultureInfo:CultureInfo -> JsonValue
  static member Load : stream:Stream * ?cultureInfo:CultureInfo -> JsonValue
  static member Parse : text:string * ?cultureInfo:CultureInfo -> JsonValue
  static member ParseMultiple : text:string * ?cultureInfo:CultureInfo -> seq<JsonValue>
  static member ParseSample : text:string * ?cultureInfo:CultureInfo -> JsonValue

Full name: FSharp.Data.JsonValue
val url : string
val valueJSON : JsonValue
static member JsonValue.Load : uri:string * ?cultureInfo:Globalization.CultureInfo -> JsonValue
static member JsonValue.Load : reader:IO.TextReader * ?cultureInfo:Globalization.CultureInfo -> JsonValue
static member JsonValue.Load : stream:IO.Stream * ?cultureInfo:Globalization.CultureInfo -> JsonValue
val n : int
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val length : array:'T [] -> int

Full name: Microsoft.FSharp.Collections.Array.length
val findPlane : (int -> JsonValue -> float -> JsonValue)
val i : int
val recordPlane : JsonValue
val recordDistance : float
val state : JsonValue
union case JsonValue.Null: JsonValue
val distance : float

More information

Link:http://fssnip.net/7Vk
Posted:5 years ago
Author:Johan Irvall
Tags: distance , json , operator overloading