-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathgeo3x3.adb
115 lines (102 loc) · 2.3 KB
/
geo3x3.adb
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
with Ada.Strings.Unbounded;
package body Geo3x3 is
function Encode (PLat: in Long_Float; PLng: in Long_Float; Level: in Integer) return String is
use Ada.Strings.Unbounded;
Res: Unbounded_String;
Lat: Long_Float;
Lng: Long_Float;
Unit: Long_Float;
begin
if Level < 1 then
return "";
end if;
Lng := PLng;
Lat := PLat;
if Lng >= 0.0 then
Append (Res,'E');
else
Append (Res,'W');
Lng := Lng + 180.0;
end if;
Lat := Lat + 90.0;
Unit := 180.0;
declare
I: Integer;
X: Integer;
Y: Integer;
C: Integer;
begin
I := 1;
loop
exit when I = Level;
Unit := Unit / 3.0;
X := Integer(Long_Float'Floor(Lng / Unit));
Y := Integer(Long_Float'Floor(Lat / Unit));
C := Character'Pos('0') + X + Y * 3 + 1;
Append (Res,Character'Val(C));
Lng := Lng - Long_Float(X) * Unit;
Lat := Lat - Long_Float(Y) * Unit;
I := I + 1;
end loop;
end;
return To_String(Res);
end Encode;
function Decode (Code: in String) return WGS84 is
Lat : Long_Float;
Lng : Long_Float;
Unit : Long_Float;
Level: Integer;
begin
declare
Init : Integer;
IsWest : Boolean;
C : Character;
begin
if Code'Length = 0 then
return (0.0, 0.0, 0, 0.0);
end if;
Init := 0;
IsWest := False;
C := Code(Code'First);
if C = '-' or C = 'W' then
IsWest := True;
Init := 1;
elsif C = '+' or C = 'E' then
Init := 1;
end if;
Unit := 180.0;
Lat := 0.0;
Lng := 0.0;
Level := 1;
declare
CLen : Integer;
I : Integer;
N : Integer;
begin
CLen := Code'Length;
I := Init;
loop
exit when I = Clen;
N := Character'Pos(Code(I+Code'First)) - Character'Pos('0');
if N <= 0 or 9 < N then
I := Clen;
else
Unit := Unit / 3.0;
N := N - 1;
Lng := Lng + Long_Float(N rem 3) * Unit;
Lat := Lat + Long_Float(N / 3) * Unit;
Level := Level + 1;
I := I + 1;
end if;
end loop;
end;
Lat := Lat + Unit / 2.0;
Lng := Lng + Unit / 2.0;
Lat := Lat - 90.0;
if IsWest then
Lng := Lng -180.0;
end if;
return (Lat, Lng, Level, Unit);
end;
end Decode;
end Geo3x3;