-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathgeo3x3.pas
87 lines (79 loc) · 1.76 KB
/
geo3x3.pas
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
{$mode objfpc}
unit geo3x3;
interface
type
latlnglevelunit = array of real;
function Geo3x3_encode(lat: real; lng: real; level: integer): string;
function Geo3x3_decode(code: string): latlnglevelunit; static;
implementation
uses
sysutils,
math;
function Geo3x3_encode(lat: real; lng: real; level: integer): string;
var
unitsize: real;
i: integer;
x: integer;
y: integer;
begin
if level < 1 then
result := ''
else
begin
result := 'E';
if lng < 0.0 then
begin
result := 'W';
lng := lng + 180.0;
end;
lat := lat + 90.0; { 180:the North Pole, 0:the South Pole }
unitsize := 180.0;
for i := 1 to level - 1 do
begin
unitsize := unitsize / 3.0;
x := Floor(lng / unitsize);
y := Floor(lat / unitsize);
result := result + IntToStr(x + y * 3 + 1);
lng := lng - x * unitsize;
lat := lat - y * unitsize;
end
end
end;
function Geo3x3_decode(code: string): latlnglevelunit; static;
var
flg: boolean;
unitsize: real;
lat: real;
lng: real;
level: integer;
n: integer;
i: integer;
begin
if length(code) = 0 then
result := [0, 0, 0, 0]
else
begin
flg := integer(code[1]) = 87; { ascii code of "W" }
unitsize := 180.0;
lat := 0.0;
lng := 0.0;
level := 1;
for i := 1 to length(code) - 1 do
begin
n := integer(code[i + 1]) - 49; { ascii code of "1" }
if (n < 0) or (n > 9) then
break;
unitsize := unitsize / 3.0;
lng := lng + (n mod 3) * unitsize;
lat := lat + Floor(n / 3) * unitsize;
level := level + 1;
end;
lat := lat + unitsize / 2.0;
lng := lng + unitsize / 2.0;
lat := lat - 90.0;
if flg then
lng := lng - 180.0;
result := [ lat, lng, level, unitsize];
end;
end;
end.