Skip to content

Commit a6d601f

Browse files
committed
feat: add haversineDistance
1 parent 6356202 commit a6d601f

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

maths/haversine_distance.nim

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Haversine formula
2+
3+
import std/[math]
4+
5+
func haversineDistance(latitudeA, longitudeA, latitudeB,
6+
longitudeB: float): float =
7+
## returns the length of the shortest path connecting the input points on an unit sphere.
8+
## The input points are represented by their spherical/geographical coordinates.
9+
let dLatitude = latitudeB - latitudeA
10+
let dLongitude = longitudeB - longitudeA
11+
let a = sin(dLatitude / 2.0)^2+cos(latitudeA)*cos(latitudeB)*sin(dLongitude / 2.0)^2
12+
return 2.0*arcsin(sqrt(a))
13+
14+
when isMainModule:
15+
import std/[unittest, sequtils, strformat]
16+
suite "haversineDistance":
17+
const testCases = [
18+
(0.0, 0.0, 0.0, 0.0, 0.0),
19+
(0.0, 0.0, PI / 2.0, 0.0, PI / 2.0),
20+
(-PI / 2.0, 0.0, PI / 2.0, 0.0, PI),
21+
(0.0, 0.0, 0.0, PI / 2.0, PI / 2.0),
22+
(0.0, -PI / 2.0, 0.0, PI / 2.0, PI),
23+
(1.0, -PI / 2.0, -1.0, PI / 2.0, PI),
24+
(2.0, -PI / 2.0, -2.0, PI / 2.0, PI),
25+
(3.0, -PI / 2.0, -3.0, PI / 2.0, PI),
26+
(3.0, -PI / 2.0 + 0.5, -3.0, PI / 2.0 + 0.5, PI),
27+
(0.0, 0.0, 0.0, PI, PI),
28+
(PI / 2.0, 1.0, PI / 2.0, 2.0, 0.0),
29+
(-PI / 2.0, 1.0, -PI / 2.0, 2.0, 0.0),
30+
(0.0, 0.0, -PI / 4.0, 0.0, PI / 4.0),
31+
(0.0, 1.0, PI / 4.0, 1.0, PI / 4.0),
32+
(-PI / 2.0, 0.0, -PI / 4.0, 0.0, PI / 4.0),
33+
(-PI / 2.0, 0.0, -PI / 4.0, 0.6, PI / 4.0),
34+
(-PI / 2.0, 3.0, -PI / 4.0, 0.2, PI / 4.0),
35+
].mapIt:
36+
(id: fmt"posA=({it[0]}, {it[1]}), posB=({it[2]}, {it[3]})",
37+
latitudeA: it[0], longitudeA: it[1],
38+
latitudeB: it[2], longitudeB: it[3],
39+
expected: it[4])
40+
41+
func close(a, b: float): bool =
42+
return abs(a-b) < 0.0000001
43+
44+
for tc in testCases:
45+
test tc.id:
46+
checkpoint("returns expected result")
47+
check close(haversineDistance(tc.latitudeA, tc.longitudeA, tc.latitudeB,
48+
tc.longitudeB), tc.expected)
49+
check close(haversineDistance(tc.latitudeB, tc.longitudeB, tc.latitudeA,
50+
tc.longitudeA), tc.expected)

0 commit comments

Comments
 (0)