-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdecompress.go
125 lines (105 loc) · 2.52 KB
/
decompress.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package maidenhead
import (
"errors"
"strconv"
"strings"
)
type Coordinate struct {
Lat float64
Lng float64
}
type SquareCoordinate struct {
Center Coordinate
TopLeft Coordinate
TopRight Coordinate
BottomLeft Coordinate
BottomRight Coordinate
}
// GridCenter returns the center of the square grid
func GridCenter(locator string) (float64, float64, error) {
locatorLength := len(locator)
if locatorLength%2 != 0 {
return 0, 0, errors.New("locator must be even")
}
if locatorLength == 0 {
return 0, 0, errors.New("locator must not be empty")
}
if locatorLength > maxSteps*2 {
return 0, 0, errors.New("locator must be less than 10 characters")
}
locator = strings.ToUpper(locator)
lng := -lngEastwardGreenwich
lat := -latSouthPole
step := 0
for step < maxSteps {
start := step * 2
end := start + 1
eS := end + 1
if eS > len(locator) {
break
}
tmpLat, tmpLng, err := subLocatorDecode(locator[start:end], locator[end:eS], step)
if err != nil {
return 0, 0, err
}
lat += tmpLat
lng += tmpLng
step++
}
//decrement step
step--
lat += latDivider[step] / 2.0
lng += lngDivider[step] / 2.0
return lat, lng, nil
}
func subLocatorDecode(subLocatorLng, subLocatorLat string, step int) (float64, float64, error) {
var lat, lng float64
if (step % 2) == 0 {
lng = float64(alphaMap[subLocatorLng])
lat = float64(alphaMap[subLocatorLat])
} else {
iValue, err := strconv.Atoi(subLocatorLng)
if err != nil {
return 0, 0, errors.New("invalid locator format")
}
lng = float64(iValue)
iValue, err = strconv.Atoi(subLocatorLat)
if err != nil {
return 0, 0, errors.New("invalid locator format")
}
lat = float64(iValue)
}
lng *= lngDivider[step]
lat *= latDivider[step]
return lat, lng, nil
}
// Square returns the coordinates of the vertices of the square grid
func Square(locator string) (SquareCoordinate, error) {
centerLat, centerLng, err := GridCenter(locator)
if err != nil {
return SquareCoordinate{}, err
}
pos := len(locator)/2 - 1
return SquareCoordinate{
Center: Coordinate{
Lat: centerLat,
Lng: centerLng,
},
TopLeft: Coordinate{
Lat: centerLat + latDivider[pos]/2,
Lng: centerLng - lngDivider[pos]/2,
},
TopRight: Coordinate{
Lat: centerLat + latDivider[pos]/2,
Lng: centerLng + lngDivider[pos]/2,
},
BottomLeft: Coordinate{
Lat: centerLat - latDivider[pos]/2,
Lng: centerLng - lngDivider[pos]/2,
},
BottomRight: Coordinate{
Lat: centerLat - latDivider[pos]/2,
Lng: centerLng + lngDivider[pos]/2,
},
}, nil
}