-
Notifications
You must be signed in to change notification settings - Fork 6
/
geo.cljc
60 lines (50 loc) · 1.39 KB
/
geo.cljc
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(ns axel-f.excel.geo)
(def earth-radius 6371.0)
(defn to-radians
"Converts an angle measured in degrees to an approximately
equivalent angle measured in radians."
[x]
#?(:clj (Math/toRadians x)
:cljs (* x (/ Math/PI 180))))
(defn asin
"Returns the arc sine of `x`."
[x]
(Math/asin x))
(defn sin
"Returns the sine of `x`."
[x]
(Math/sin x))
(defn cos
"Returns the cosine of `x`."
[x]
(Math/cos x))
(defn sqrt
"Returns the square root of `x`."
[x]
(Math/sqrt x))
(defn distance
"Returns the distance from `point-1` to `point-2`, in km using the
Haversine formula."
[[lat-1 lon-1] [lat-2 lon-2]]
(let [d-lat (to-radians (- lat-2 lat-1))
d-lon (to-radians (- lon-2 lon-1))
lat-1 (to-radians lat-1)
lat-2 (to-radians lat-2)
a (+ (* (sin (/ d-lat 2))
(sin (/ d-lat 2)))
(* (sin (/ d-lon 2))
(sin (/ d-lon 2))
(cos lat-1)
(cos lat-2)))]
(* earth-radius 2 (asin (sqrt a)))))
(defn geo-distance*
"Calculate the distance for the path described as a list of geo points. Each point must a tuple of two float numbers."
[& ^{:doc "Collection of coordinates"} points]
(->> points
flatten
(partition 2)
(partition 2 1)
(reduce #(+ %1 (apply distance %2)) 0)))
(def geo-distance #'geo-distance*)
(def env
{"GEO" {"DISTANCE" geo-distance}})