-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProj4.GaussKruger.pas
165 lines (137 loc) · 4.35 KB
/
Proj4.GaussKruger.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
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
unit Proj4.GaussKruger;
interface
type
TGaussKrugerCoord = record
Zone: Integer;
IsNorth: Boolean;
X: Double;
Y: Double;
end;
TGaussKruger = class
private
FGeogInit: AnsiString;
FProjInitFmt: AnsiString;
protected
function GetGeogInit: AnsiString; virtual;
function GetProjInit(const AZone: Integer; const AIsNorth: Boolean): AnsiString; virtual;
public
class function geog_long_to_zone(const ALon: Double): Integer; inline;
class function zone_to_geog_lon(const AZone: Integer): Double; inline;
function wgs84_to_geog(var ALon, ALat: Double): Boolean; inline;
function geog_to_wgs84(var ALon, ALat: Double): Boolean; inline;
function geog_to_proj(const ALon, ALat: Double; out ACoord: TGaussKrugerCoord): Boolean;
function wgs84_to_proj(const ALon, ALat: Double; out ACoord: TGaussKrugerCoord): Boolean;
function proj_to_wgs84(const ACoord: TGaussKrugerCoord; out ALon, ALat: Double): Boolean;
function proj_to_geog(const ACoord: TGaussKrugerCoord; out ALon, ALat: Double): Boolean;
public
constructor Create(
const AGeogInit: AnsiString;
const AProjInitFmt: AnsiString
);
end;
TGaussKrugerFactory = record
class function BuildSK42: TGaussKruger; static;
class function BuildGSK2011: TGaussKruger; static;
end;
implementation
uses
Math,
SysUtils,
Proj4.Defines,
Proj4.Utils;
{ TGaussKruger }
constructor TGaussKruger.Create(
const AGeogInit: AnsiString;
const AProjInitFmt: AnsiString
);
begin
inherited Create;
FGeogInit := AGeogInit;
FProjInitFmt := AProjInitFmt;
end;
class function TGaussKruger.geog_long_to_zone(const ALon: Double): Integer;
begin
if ALon > 0 then begin
Result := Floor(ALon / 6) + 1;
end else begin
Result := Floor((180 + ALon) / 6) + 30 + 1;
end;
end;
class function TGaussKruger.zone_to_geog_lon(const AZone: Integer): Double;
begin
Result := (AZone - 1) * 6;
if AZone > 30 then begin
Result := Result - 360;
end;
end;
function TGaussKruger.GetGeogInit: AnsiString;
begin
Result := FGeogInit;
end;
function TGaussKruger.GetProjInit(const AZone: Integer; const AIsNorth: Boolean): AnsiString;
var
lon_0: Integer;
x_0, y_0: Integer;
begin
lon_0 := AZone * 6 - 3;
if AZone > 30 then begin
lon_0 := lon_0 - 360;
end;
x_0 := AZone * 1000000 + 500000;
if AIsNorth then begin
y_0 := 0;
end else begin
y_0 := 10000000;
end;
Result := AnsiString(Format(FProjInitFmt, [lon_0, x_0, y_0]));
end;
function TGaussKruger.wgs84_to_geog(var ALon, ALat: Double): Boolean;
begin
Result := geodetic_cs_to_cs(wgs_84, GetGeogInit, ALon, ALat);
end;
function TGaussKruger.geog_to_wgs84(var ALon, ALat: Double): Boolean;
begin
Result := geodetic_cs_to_cs(GetGeogInit, wgs_84, ALon, ALat);
end;
function TGaussKruger.geog_to_proj(const ALon, ALat: Double; out ACoord: TGaussKrugerCoord): Boolean;
var
VInitStr: AnsiString;
begin
ACoord.Zone := geog_long_to_zone(ALon);
ACoord.IsNorth := ALat >= 0;
VInitStr := GetProjInit(ACoord.Zone, ACoord.IsNorth);
Result := geodetic_cs_to_projected_cs(GetGeogInit, VInitStr, ALon, ALat, ACoord.X, ACoord.Y);
end;
function TGaussKruger.wgs84_to_proj(const ALon, ALat: Double; out ACoord: TGaussKrugerCoord): Boolean;
var
VLon, VLat: Double;
begin
VLon := ALon;
VLat := ALat;
Result :=
geodetic_cs_to_cs(wgs_84, GetGeogInit, VLon, VLat) and
geog_to_proj(VLon, VLat, ACoord);
end;
function TGaussKruger.proj_to_wgs84(const ACoord: TGaussKrugerCoord; out ALon, ALat: Double): Boolean;
begin
Result :=
proj_to_geog(ACoord, ALon, ALat) and
geodetic_cs_to_cs(GetGeogInit, wgs_84, ALon, ALat);
end;
function TGaussKruger.proj_to_geog(const ACoord: TGaussKrugerCoord; out ALon, ALat: Double): Boolean;
var
VInitStr: AnsiString;
begin
VInitStr := GetProjInit(ACoord.Zone, ACoord.IsNorth);
Result := projected_cs_to_geodetic_cs(VInitStr, GetGeogInit, ACoord.X, ACoord.Y, ALon, ALat);
end;
{ TGaussKrugerFactory }
class function TGaussKrugerFactory.BuildSK42: TGaussKruger;
begin
Result := TGaussKruger.Create(sk_42, sk_42_gauss_kruger_fmt);
end;
class function TGaussKrugerFactory.BuildGSK2011: TGaussKruger;
begin
Result := TGaussKruger.Create(gsk_2011, gsk_2011_gauss_kruger_fmt);
end;
end.