-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathGeo3x3.class.st
94 lines (82 loc) · 2.24 KB
/
Geo3x3.class.st
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
"
https://code4sabae.github.io/geo3x3-map/
"
Class {
#name : #Geo3x3,
#superclass : #Object,
#category : #'Geo3x3-codec'
}
{ #category : #decoding }
Geo3x3 class >> coords: code [
| pos x y u2 |
pos := self decode: code.
x := pos first.
y := pos second.
u2 := pos fourth / 2.
^ {y - u2. x - u2. y - u2. x + u2. y + u2. x + u2. y + u2. x - u2}
]
{ #category : #decoding }
Geo3x3 class >> decode: codeIntOrStr [
| code firstChar isW unit lat lng level |
code := nil.
(codeIntOrStr isKindOf: Integer)
ifTrue: [code := codeIntOrStr < 0
ifTrue: ['W', codeIntOrStr negated]
ifFalse: ['E', codeIntOrStr]
].
((codeIntOrStr isKindOf: String) and: [codeIntOrStr notEmpty])
ifTrue: [code := codeIntOrStr].
code ifNil: [^ self error: 'invalid code'].
firstChar := code first.
isW := '-W' includes: firstChar.
(isW or: ['+E' includes: firstChar]) ifTrue: [code := code allButFirst].
unit := 180.0.
lat := 0.0.
lng := 0.0.
level := 1.
[:exit | code do: [:digitChar |
| n |
n := digitChar digitValue.
n = 0 ifTrue: [exit value].
unit := unit / 3.
n := n - 1.
lng := lng + (n \\ 3 * unit).
lat := lat + (n // 3 * unit).
level := level + 1
]] valueWithExit.
lat := lat + (unit / 2).
lng := lng + (unit / 2).
lat := lat - 90.
isW ifTrue: [lng := lng - 180.0].
^ {lat. lng. level. unit}
]
{ #category : #encoding }
Geo3x3 class >> encodeLatitude: latNum andLongitude: lngNum withLevel: level [
| lat lng |
level < 1 ifTrue: [^''].
lat := latNum asFloat.
lng := lngNum asFloat.
^String streamContents: [:ss |
| unit |
ss nextPut: (lng >= 0 ifTrue: [$E] ifFalse: [lng := lng + 180. $W]).
lat := lat + 90.
unit := 180.0.
level - 1 timesRepeat: [
| x y |
unit := unit / 3.
x := (lng / unit) truncated.
y := (lat / unit) truncated.
x + (y * 3) + 1 printOn: ss.
lng := lng - (x * unit).
lat := lat - (y * unit)
]
]
]
{ #category : #encoding }
Geo3x3 class >> encodeToIntFromLatitude: lat andLongitude: lng withLevel: level [
| code result |
code := self encodeLatitude: lat andLongitude: lng withLevel: level.
result := code allButFirst asInteger.
code first == $W ifTrue: [result := result negated].
^ result
]