-
Notifications
You must be signed in to change notification settings - Fork 14
/
distance.go
67 lines (55 loc) · 1.51 KB
/
distance.go
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
61
62
63
64
65
66
67
package cluster
import (
"math"
)
const (
// DegreeRad is coefficient to translate from degrees to radians
DegreeRad = math.Pi / 180.0
// EarthR is earth radius in km
EarthR = 6371.0
)
// DistanceSpherical is a spherical (optimized) distance between two points
//
// Result is distance in kilometers
func DistanceSpherical(p1, p2 *Point) float64 {
v1 := (p1[1] - p2[1]) * DegreeRad
v1 = v1 * v1
v2 := (p1[0] - p2[0]) * DegreeRad * math.Cos((p1[1]+p2[1])/2.0*DegreeRad)
v2 = v2 * v2
return EarthR * math.Sqrt(v1+v2)
}
// FastSine caclulates sinus approximated to parabola
//
// Taken from: http://forum.devmaster.net/t/fast-and-accurate-sine-cosine/9648
func FastSine(x float64) float64 {
const (
B = 4 / math.Pi
C = -4 / (math.Pi * math.Pi)
P = 0.225
)
if x > math.Pi || x < -math.Pi {
panic("out of range")
}
y := B*x + C*x*math.Abs(x)
return P*(y*math.Abs(y)-y) + y
}
// FastCos calculates cosinus from sinus
func FastCos(x float64) float64 {
x += math.Pi / 2.0
for x > math.Pi {
x -= 2 * math.Pi
}
return FastSine(x)
}
// DistanceSphericalFast calculates spherical distance with fast cosine
// without sqrt and normalization to Earth radius/radians
//
// To get real distance in km, take sqrt and multiply result by EarthR*DegreeRad
//
// In this library eps (distance) is adjusted so that we don't need
// to do sqrt and multiplication
func DistanceSphericalFast(p1, p2 *Point) float64 {
v1 := (p1[1] - p2[1])
v2 := (p1[0] - p2[0]) * FastCos((p1[1]+p2[1])/2.0*DegreeRad)
return v1*v1 + v2*v2
}