1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Oc\Repository; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Class Coordinate |
7
|
|
|
* |
8
|
|
|
* @package Oc\Repository |
9
|
|
|
*/ |
10
|
|
|
class CoordinatesRepository |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var float |
14
|
|
|
*/ |
15
|
|
|
private $nLat = 0; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @var float |
19
|
|
|
*/ |
20
|
|
|
private $nLon = 0; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Coordinate constructor. |
24
|
|
|
* |
25
|
|
|
* @param $nNewLat |
26
|
|
|
* @param $nNewLon |
27
|
|
|
*/ |
28
|
|
|
public function __construct(float $nNewLat = 0, float $nNewLon = 0) |
29
|
|
|
{ |
30
|
|
|
$this->nLat = $nNewLat; |
|
|
|
|
31
|
|
|
$this->nLon = $nNewLon; |
|
|
|
|
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/* get-Functions return array([lat] => string, [lon] => string) |
35
|
|
|
*/ |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @param float $nNewLat |
39
|
|
|
* @param float $nNewLon |
40
|
|
|
*/ |
41
|
|
|
public function setLatLon(float $nNewLat, float $nNewLon) |
42
|
|
|
{ |
43
|
|
|
$this->nLat = $nNewLat; |
44
|
|
|
$this->nLon = $nNewLon; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* float |
49
|
|
|
* |
50
|
|
|
* @return array |
51
|
|
|
*/ |
52
|
|
|
public function getFloat() |
53
|
|
|
: array |
54
|
|
|
{ |
55
|
|
|
return [ |
56
|
|
|
'lat' => $this->nLat, |
57
|
|
|
'lon' => $this->nLon, |
58
|
|
|
]; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Decimal: d.ddddd° |
63
|
|
|
* |
64
|
|
|
* @return string[] |
65
|
|
|
*/ |
66
|
|
|
public function getDecimal() |
67
|
|
|
: array |
68
|
|
|
{ |
69
|
|
|
if ($this->nLat < 0) { |
70
|
|
|
$sLat = 'S' . sprintf('%08.5f', - $this->nLat) . '°'; |
71
|
|
|
} else { |
72
|
|
|
$sLat = 'N' . sprintf('%08.5f', $this->nLat) . '°'; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
if ($this->nLon < 0) { |
76
|
|
|
$sLon = 'W' . sprintf('%09.5f', - $this->nLon) . '°'; |
77
|
|
|
} else { |
78
|
|
|
$sLon = 'E' . sprintf('%09.5f', $this->nLon) . '°'; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
return [ |
82
|
|
|
'lat' => $sLat, |
83
|
|
|
'lon' => $sLon, |
84
|
|
|
]; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Degree Minute: d° mm.mmm |
89
|
|
|
* |
90
|
|
|
* @param false $hideMinutFractions |
91
|
|
|
* |
92
|
|
|
* @return string[] |
93
|
|
|
*/ |
94
|
|
|
public function getDegreeMinutes($hideMinutFractions = false) |
95
|
|
|
: array { |
96
|
|
|
$minute_format = ($hideMinutFractions ? '%02.0f.***' : '%06.3f'); |
97
|
|
|
|
98
|
|
|
// Ocprop: ([N|S].*?)' |
99
|
|
|
$nLat = $this->nLat; |
100
|
|
|
$bLatN = ($nLat < 0) ? false : true; |
101
|
|
|
if (!$bLatN) { |
102
|
|
|
$nLat = - $nLat; |
103
|
|
|
} |
104
|
|
|
$nLatDeg = floor($nLat); |
105
|
|
|
$nLatMin = ($nLat - $nLatDeg) * 60; |
106
|
|
View Code Duplication |
if ($bLatN) { |
107
|
|
|
$sLat = 'N' . sprintf('%02d', $nLatDeg) . '° ' . sprintf($minute_format, $nLatMin) . '\''; |
108
|
|
|
} else { |
109
|
|
|
$sLat = 'S' . sprintf('%02d', $nLatDeg) . '° ' . sprintf($minute_format, $nLatMin) . '\''; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
// Ocprop: ([E|W].*?)' |
113
|
|
|
$nLon = $this->nLon; |
114
|
|
|
$bLonE = ($nLon < 0) ? false : true; |
115
|
|
|
if (!$bLonE) { |
116
|
|
|
$nLon = - $nLon; |
117
|
|
|
} |
118
|
|
|
$nLonDeg = floor($nLon); |
119
|
|
|
$nLonMin = ($nLon - $nLonDeg) * 60; |
120
|
|
View Code Duplication |
if ($bLonE) { |
121
|
|
|
$sLon = 'E' . sprintf('%03d', $nLonDeg) . '° ' . sprintf($minute_format, $nLonMin) . '\''; |
122
|
|
|
} else { |
123
|
|
|
$sLon = 'W' . sprintf('%03d', $nLonDeg) . '° ' . sprintf($minute_format, $nLonMin) . '\''; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
return [ |
127
|
|
|
'lat' => $sLat, |
128
|
|
|
'lon' => $sLon, |
129
|
|
|
]; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Degree Minute Second: dd° mm' ss'' |
134
|
|
|
* |
135
|
|
|
* @return string[] |
136
|
|
|
*/ |
137
|
|
|
public function getDegreeMinutesSeconds() |
138
|
|
|
: array |
139
|
|
|
{ |
140
|
|
|
$nLat = $this->nLat; |
141
|
|
|
$bLatN = ($nLat < 0) ? false : true; |
142
|
|
|
if (!$bLatN) { |
143
|
|
|
$nLat = - $nLat; |
144
|
|
|
} |
145
|
|
|
$nLatDeg = floor($nLat); |
146
|
|
|
$nLatMin = ($nLat - $nLatDeg) * 60; |
147
|
|
|
$nLatSec = $nLatMin - floor($nLatMin); |
148
|
|
|
$nLatMin = ($nLatMin - $nLatSec); |
149
|
|
|
$nLatSec = $nLatSec * 60; |
150
|
|
|
$sLat = $bLatN ? 'N' : 'S'; |
151
|
|
|
$sLat .= sprintf("%02d° %02d' %02d''", $nLatDeg, $nLatMin, $nLatSec); |
152
|
|
|
|
153
|
|
|
$nLon = $this->nLon; |
154
|
|
|
$bLonE = ($nLon < 0) ? false : true; |
155
|
|
|
if (!$bLonE) { |
156
|
|
|
$nLon = - $nLon; |
157
|
|
|
} |
158
|
|
|
$nLonDeg = floor($nLon); |
159
|
|
|
$nLonMin = ($nLon - $nLonDeg) * 60; |
160
|
|
|
$nLonSec = $nLonMin - floor($nLonMin); |
161
|
|
|
$nLonMin -= $nLonSec; |
162
|
|
|
$nLonSec *= 60; |
163
|
|
|
$sLon = $bLonE ? 'E' : 'W'; |
164
|
|
|
$sLon .= sprintf("%03d° %02d' %02d''", $nLonDeg, $nLonMin, $nLonSec); |
165
|
|
|
|
166
|
|
|
return [ |
167
|
|
|
'lat' => $sLat, |
168
|
|
|
'lon' => $sLon, |
169
|
|
|
]; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* UTM, returns array(zone, letter, north, east) |
174
|
|
|
* |
175
|
|
|
* @return array|string[] |
176
|
|
|
*/ |
177
|
|
View Code Duplication |
public function getUTM() |
|
|
|
|
178
|
|
|
: array |
179
|
|
|
{ |
180
|
|
|
/* Copyright (c) 2006, HELMUT H. HEIMEIER |
181
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
182
|
|
|
copy of this software and associated documentation files (the "Software"), |
183
|
|
|
to deal in the Software without restriction, including without limitation |
184
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
185
|
|
|
and/or sell copies of the Software, and to permit persons to whom the |
186
|
|
|
Software is furnished to do so, subject to the following conditions: |
187
|
|
|
The above copyright notice and this permission notice shall be included |
188
|
|
|
in all copies or substantial portions of the Software.*/ |
189
|
|
|
|
190
|
|
|
/* Die Funktion wandelt geographische Koordinaten in UTM Koordinaten |
191
|
|
|
um. Geographische Länge lw und Breite bw müssen im WGS84 Datum |
192
|
|
|
gegeben sein. Berechnet werden UTM Zone, Ostwert ew und Nordwert nw.*/ |
193
|
|
|
|
194
|
|
|
//Geographische Länge lw und Breite bw im WGS84 Datum |
195
|
|
|
if ($this->nLon == 0 || $this->nLat == 0) { |
196
|
|
|
return [ |
197
|
|
|
'zone' => '', |
198
|
|
|
'letter' => '', |
199
|
|
|
'north' => 'N ' . 0, |
200
|
|
|
'east' => 'E ' . 0, |
201
|
|
|
]; |
202
|
|
|
} |
203
|
|
|
if ($this->nLon <= - 180 || $this->nLon > 180 || $this->nLat <= - 80 || $this->nLat >= 84) { |
204
|
|
|
// Werte nicht im Bereich des UTM Systems -180° <= nLon < +180°, -80° < nLat < 84° N |
205
|
|
|
return [ |
206
|
|
|
'', |
207
|
|
|
'', |
208
|
|
|
0, |
209
|
|
|
0, |
210
|
|
|
]; |
211
|
|
|
} |
212
|
|
|
$lw = (float) $this->nLon; |
213
|
|
|
$bw = (float) $this->nLat; |
214
|
|
|
|
215
|
|
|
//WGS84 Datum |
216
|
|
|
//Große Halbachse a und Abplattung f |
217
|
|
|
$a = 6378137.000; |
218
|
|
|
$f = 3.35281068e-3; |
219
|
|
|
$b_sel = 'CDEFGHJKLMNPQRSTUVWXX'; |
220
|
|
|
|
221
|
|
|
//Polkrümmungshalbmesser c |
222
|
|
|
$c = $a / (1 - $f); |
223
|
|
|
|
224
|
|
|
//Quadrat der zweiten numerischen Exzentrizität |
225
|
|
|
$ex2 = (2 * $f - $f * $f) / ((1 - $f) * (1 - $f)); |
226
|
|
|
$ex4 = $ex2 * $ex2; |
227
|
|
|
$ex6 = $ex4 * $ex2; |
228
|
|
|
$ex8 = $ex4 * $ex4; |
229
|
|
|
|
230
|
|
|
//Koeffizienten zur Berechnung der Meridianbogenlänge |
231
|
|
|
$e0 = $c * (pi() / 180) * (1 - 3 * $ex2 / 4 + 45 * $ex4 / 64 - 175 * $ex6 / 256 + 11025 * $ex8 / 16384); |
232
|
|
|
$e2 = $c * (- 3 * $ex2 / 8 + 15 * $ex4 / 32 - 525 * $ex6 / 1024 + 2205 * $ex8 / 4096); |
233
|
|
|
$e4 = $c * (15 * $ex4 / 256 - 105 * $ex6 / 1024 + 2205 * $ex8 / 16384); |
234
|
|
|
$e6 = $c * (- 35 * $ex6 / 3072 + 315 * $ex8 / 12288); |
235
|
|
|
|
236
|
|
|
//Längenzone lz und Breitenzone (Band) bz |
237
|
|
|
$lzn = intval(($lw + 180) / 6) + 1; |
238
|
|
|
|
239
|
|
|
if ($bw >= 56.0 && $bw < 64.0 && $lw >= 3.0 && $lw < 12.0) { |
240
|
|
|
$lzn = 32; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
// Special zones for Svalbard. |
244
|
|
|
if ($bw >= 72.0 && $bw < 84.0) { |
245
|
|
|
if ($lw >= 0.0 && $lw < 9.0) { |
246
|
|
|
$lzn = 31; |
247
|
|
|
} elseif ($lw >= 9.0 && $lw < 21.0) { |
248
|
|
|
$lzn = 33; |
249
|
|
|
} elseif ($lw >= 21.0 && $lw < 33.0) { |
250
|
|
|
$lzn = 35; |
251
|
|
|
} elseif ($lw >= 33.0 && $lw < 42.0) { |
252
|
|
|
$lzn = 37; |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
$lz = "$lzn"; |
257
|
|
|
if ($lzn < 10) { |
258
|
|
|
$lz = '0' . $lzn; |
259
|
|
|
} |
260
|
|
|
$bd = (int) (1 + ($bw + 80) / 8); |
261
|
|
|
$bz = substr($b_sel, $bd - 1, 1); |
262
|
|
|
|
263
|
|
|
//Geographische Breite in Radianten br |
264
|
|
|
$br = $bw * pi() / 180; |
265
|
|
|
|
266
|
|
|
$tan1 = tan($br); |
267
|
|
|
$tan2 = $tan1 * $tan1; |
268
|
|
|
$tan4 = $tan2 * $tan2; |
269
|
|
|
|
270
|
|
|
$cos1 = cos($br); |
271
|
|
|
$cos2 = $cos1 * $cos1; |
272
|
|
|
$cos4 = $cos2 * $cos2; |
273
|
|
|
$cos3 = $cos2 * $cos1; |
274
|
|
|
$cos5 = $cos4 * $cos1; |
275
|
|
|
|
276
|
|
|
$etasq = $ex2 * $cos2; |
277
|
|
|
|
278
|
|
|
//Querkrümmungshalbmesser nd |
279
|
|
|
$nd = $c / sqrt(1 + $etasq); |
280
|
|
|
|
281
|
|
|
//Meridianbogenlänge g aus gegebener geographischer Breite bw |
282
|
|
|
$g = ($e0 * $bw) + ($e2 * sin(2 * $br)) + ($e4 * sin(4 * $br)) + ($e6 * sin(6 * $br)); |
283
|
|
|
|
284
|
|
|
//Längendifferenz dl zum Bezugsmeridian lh |
285
|
|
|
$lh = ($lzn - 30) * 6 - 3; |
286
|
|
|
$dl = ($lw - $lh) * pi() / 180; |
287
|
|
|
$dl2 = $dl * $dl; |
288
|
|
|
$dl4 = $dl2 * $dl2; |
289
|
|
|
$dl3 = $dl2 * $dl; |
290
|
|
|
$dl5 = $dl4 * $dl; |
291
|
|
|
|
292
|
|
|
//Maßstabsfaktor auf dem Bezugsmeridian bei UTM Koordinaten m = 0.9996 |
293
|
|
|
//Nordwert nw und Ostwert ew als Funktion von geographischer Breite und Länge |
294
|
|
|
|
295
|
|
|
if ($bw < 0) { |
296
|
|
|
$nw = 10e6 + 0.9996 * ($g + $nd * $cos2 * $tan1 * $dl2 / 2 + |
297
|
|
|
$nd * $cos4 * $tan1 * (5 - $tan2 + 9 * $etasq) * $dl4 / 24); |
298
|
|
|
} else { |
299
|
|
|
$nw = 0.9996 * ($g + $nd * $cos2 * $tan1 * $dl2 / 2 + |
300
|
|
|
$nd * $cos4 * $tan1 * (5 - $tan2 + 9 * $etasq) * $dl4 / 24); |
301
|
|
|
} |
302
|
|
|
$ew = 0.9996 * ($nd * $cos1 * $dl + $nd * $cos3 * (1 - $tan2 + $etasq) * $dl3 / 6 + |
303
|
|
|
$nd * $cos5 * (5 - 18 * $tan2 + $tan4) * $dl5 / 120) + 500000; |
304
|
|
|
|
305
|
|
|
$nk = $nw - (int) $nw; |
306
|
|
|
if ($nk < 0.5) { |
307
|
|
|
$nw = '' . (int) $nw; |
308
|
|
|
} else { |
309
|
|
|
$nw = '' . ((int) $nw + 1); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
while (strlen($nw) < 7) { |
313
|
|
|
$nw = '0' . $nw; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
$nk = $ew - (int) $ew; |
317
|
|
|
if ($nk < 0.5) { |
318
|
|
|
$ew = '0' . (int) $ew; |
319
|
|
|
} else { |
320
|
|
|
$ew = '0' . intval($ew + 1); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
return [ |
324
|
|
|
'zone' => $lz, |
325
|
|
|
'letter' => $bz, |
326
|
|
|
'north' => 'N' . floor($nw), |
327
|
|
|
'east' => 'E' . floor($ew), |
328
|
|
|
]; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Gauß Krüger |
333
|
|
|
* |
334
|
|
|
* @return string |
335
|
|
|
*/ |
336
|
|
View Code Duplication |
public function getGK() |
|
|
|
|
337
|
|
|
: string |
338
|
|
|
{ |
339
|
|
|
$pdResult = $this->wgs2pot($this->nLat, $this->nLon); |
340
|
|
|
$result = $this->geo2gk($pdResult[1], $pdResult[0]); |
341
|
|
|
|
342
|
|
|
return 'R ' . floor($result[0]) . ' H ' . floor($result[1]); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* @param $bw |
347
|
|
|
* @param $lw |
348
|
|
|
* |
349
|
|
|
* @return float[] |
350
|
|
|
*/ |
351
|
|
View Code Duplication |
public function wgs2pot($bw, $lw) |
|
|
|
|
352
|
|
|
: array { |
353
|
|
|
/* Copyright (c) 2006, HELMUT H. HEIMEIER |
354
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
355
|
|
|
copy of this software and associated documentation files (the "Software"), |
356
|
|
|
to deal in the Software without restriction, including without limitation |
357
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
358
|
|
|
and/or sell copies of the Software, and to permit persons to whom the |
359
|
|
|
Software is furnished to do so, subject to the following conditions: |
360
|
|
|
The above copyright notice and this permission notice shall be included |
361
|
|
|
in all copies or substantial portions of the Software.*/ |
362
|
|
|
|
363
|
|
|
/* Die Funktion verschiebt das Kartenbezugssystem (map datum) vom |
364
|
|
|
WGS84 Datum (World Geodetic System 84) zum in Deutschland |
365
|
|
|
gebräuchlichen Potsdam-Datum. Geographische Länge lw und Breite |
366
|
|
|
bw gemessen in grad auf dem WGS84 Ellipsoid müssen |
367
|
|
|
gegeben sein. Ausgegeben werden geographische Länge lp |
368
|
|
|
und Breite bp (in grad) auf dem Bessel-Ellipsoid. |
369
|
|
|
Bei der Transformation werden die Ellipsoidachsen parallel |
370
|
|
|
verschoben um dx = -606 m, dy = -23 m und dz = -413 m.*/ |
371
|
|
|
|
372
|
|
|
// Geographische Länge lw und Breite bw im WGS84 Datum |
373
|
|
|
if ($lw == '' || $bw == '') { |
374
|
|
|
return [ |
375
|
|
|
0, |
376
|
|
|
0, |
377
|
|
|
]; |
378
|
|
|
} |
379
|
|
|
$lw = (float) $lw; |
380
|
|
|
$bw = (float) $bw; |
381
|
|
|
|
382
|
|
|
// Quellsystem WGS 84 Datum |
383
|
|
|
// Große Halbachse a und Abplattung fq |
384
|
|
|
$a = 6378137.000; |
385
|
|
|
$fq = 3.35281066e-3; |
386
|
|
|
|
387
|
|
|
// Zielsystem Potsdam Datum |
388
|
|
|
// Abplattung f |
389
|
|
|
$f = $fq - 1.003748e-5; |
390
|
|
|
|
391
|
|
|
// Parameter für datum shift |
392
|
|
|
$dx = - 606; |
393
|
|
|
$dy = - 23; |
394
|
|
|
$dz = - 413; |
395
|
|
|
|
396
|
|
|
// Quadrat der ersten numerischen Exzentrizität in Quell- und Zielsystem |
397
|
|
|
$e2q = (2 * $fq - $fq * $fq); |
398
|
|
|
$e2 = (2 * $f - $f * $f); |
399
|
|
|
|
400
|
|
|
// Breite und Länge in Radianten |
401
|
|
|
$b1 = $bw * (pi() / 180); |
402
|
|
|
$l1 = $lw * (pi() / 180); |
403
|
|
|
|
404
|
|
|
// Querkrümmungshalbmesser nd |
405
|
|
|
$nd = $a / sqrt(1 - $e2q * sin($b1) * sin($b1)); |
406
|
|
|
|
407
|
|
|
// Kartesische Koordinaten des Quellsystems WGS84 |
408
|
|
|
$xw = $nd * cos($b1) * cos($l1); |
409
|
|
|
$yw = $nd * cos($b1) * sin($l1); |
410
|
|
|
$zw = (1 - $e2q) * $nd * sin($b1); |
411
|
|
|
|
412
|
|
|
// Kartesische Koordinaten des Zielsystems (datum shift) Potsdam |
413
|
|
|
$x = $xw + $dx; |
414
|
|
|
$y = $yw + $dy; |
415
|
|
|
$z = $zw + $dz; |
416
|
|
|
|
417
|
|
|
// Berechnung von Breite und Länge im Zielsystem |
418
|
|
|
$rb = sqrt($x * $x + $y * $y); |
419
|
|
|
$b2 = (180 / pi()) * atan(($z / $rb) / (1 - $e2)); |
420
|
|
|
|
421
|
|
|
if ($x > 0) { |
422
|
|
|
$l2 = (180 / pi()) * atan($y / $x); |
423
|
|
|
} elseif ($x < 0 && $y > 0) { |
424
|
|
|
$l2 = (180 / pi()) * atan($y / $x) + 180; |
425
|
|
|
} else { |
426
|
|
|
$l2 = (180 / pi()) * atan($y / $x) - 180; |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return [ |
430
|
|
|
$l2, |
431
|
|
|
$b2, |
432
|
|
|
]; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* @param $bp |
437
|
|
|
* @param $lp |
438
|
|
|
* |
439
|
|
|
* @return int[] |
440
|
|
|
*/ |
441
|
|
View Code Duplication |
public function geo2gk($bp, $lp) |
|
|
|
|
442
|
|
|
{ |
443
|
|
|
/* Copyright (c) 2006, HELMUT H. HEIMEIER |
444
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
445
|
|
|
copy of this software and associated documentation files (the "Software"), |
446
|
|
|
to deal in the Software without restriction, including without limitation |
447
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
448
|
|
|
and/or sell copies of the Software, and to permit persons to whom the |
449
|
|
|
Software is furnished to do so, subject to the following conditions: |
450
|
|
|
The above copyright notice and this permission notice shall be included |
451
|
|
|
in all copies or substantial portions of the Software.*/ |
452
|
|
|
|
453
|
|
|
/* Die Funktion wandelt geographische Koordinaten in GK Koordinaten |
454
|
|
|
um. Geographische Länge lp und Breite bp müssen im Potsdam Datum |
455
|
|
|
gegeben sein. Berechnet werden Rechtswert rw und Hochwert hw.*/ |
456
|
|
|
|
457
|
|
|
//Geographische Länge lp und Breite bp im Potsdam Datum |
458
|
|
|
if ($lp == '' || $bp == '') { |
459
|
|
|
return [ |
460
|
|
|
0, |
461
|
|
|
0, |
462
|
|
|
]; |
463
|
|
|
} |
464
|
|
|
$lp = (float) $lp; |
465
|
|
|
$bp = (float) $bp; |
466
|
|
|
|
467
|
|
|
// Potsdam Datum |
468
|
|
|
// Große Halbachse a und Abplattung f |
469
|
|
|
$a = 6377397.155; // + $falseeasting; |
470
|
|
|
$f = 3.34277321e-3; |
471
|
|
|
|
472
|
|
|
// Polkrümmungshalbmesser c |
473
|
|
|
$c = $a / (1 - $f); |
474
|
|
|
|
475
|
|
|
// Quadrat der zweiten numerischen Exzentrizität |
476
|
|
|
$ex2 = (2 * $f - $f * $f) / ((1 - $f) * (1 - $f)); |
477
|
|
|
$ex4 = $ex2 * $ex2; |
478
|
|
|
$ex6 = $ex4 * $ex2; |
479
|
|
|
$ex8 = $ex4 * $ex4; |
480
|
|
|
|
481
|
|
|
// Koeffizienten zur Berechnung der Meridianbogenlänge |
482
|
|
|
$e0 = $c * (pi() / 180) * (1 - 3 * $ex2 / 4 + 45 * $ex4 / 64 - 175 * $ex6 / 256 + 11025 * $ex8 / 16384); |
483
|
|
|
$e2 = $c * (- 3 * $ex2 / 8 + 15 * $ex4 / 32 - 525 * $ex6 / 1024 + 2205 * $ex8 / 4096); |
484
|
|
|
$e4 = $c * (15 * $ex4 / 256 - 105 * $ex6 / 1024 + 2205 * $ex8 / 16384); |
485
|
|
|
$e6 = $c * (- 35 * $ex6 / 3072 + 315 * $ex8 / 12288); |
486
|
|
|
|
487
|
|
|
// Breite in Radianten |
488
|
|
|
$br = $bp * pi() / 180; |
489
|
|
|
|
490
|
|
|
$tan1 = tan($br); |
491
|
|
|
$tan2 = $tan1 * $tan1; |
492
|
|
|
$tan4 = $tan2 * $tan2; |
493
|
|
|
|
494
|
|
|
$cos1 = cos($br); |
495
|
|
|
$cos2 = $cos1 * $cos1; |
496
|
|
|
$cos4 = $cos2 * $cos2; |
497
|
|
|
$cos3 = $cos2 * $cos1; |
498
|
|
|
$cos5 = $cos4 * $cos1; |
499
|
|
|
|
500
|
|
|
$etasq = $ex2 * $cos2; |
501
|
|
|
|
502
|
|
|
// Querkrümmungshalbmesser nd |
503
|
|
|
$nd = $c / sqrt(1 + $etasq); |
504
|
|
|
|
505
|
|
|
// Meridianbogenlänge g aus gegebener geographischer Breite bp |
506
|
|
|
$g = $e0 * $bp + $e2 * sin(2 * $br) + $e4 * sin(4 * $br) + $e6 * sin(6 * $br); |
507
|
|
|
|
508
|
|
|
// Längendifferenz dl zum Bezugsmeridian lh |
509
|
|
|
$kz = round($lp / 3); |
510
|
|
|
$lh = $kz * 3; |
511
|
|
|
$dl = ($lp - $lh) * pi() / 180; |
512
|
|
|
$dl2 = $dl * $dl; |
513
|
|
|
$dl4 = $dl2 * $dl2; |
514
|
|
|
$dl3 = $dl2 * $dl; |
515
|
|
|
$dl5 = $dl4 * $dl; |
516
|
|
|
|
517
|
|
|
// Hochwert hw und Rechtswert rw als Funktion von geographischer Breite und Länge |
518
|
|
|
$hw = ($g + $nd * $cos2 * $tan1 * $dl2 / 2 + $nd * $cos4 * $tan1 * (5 - $tan2 + 9 * $etasq) |
519
|
|
|
* $dl4 / 24); |
520
|
|
|
$rw = ($nd * $cos1 * $dl + $nd * $cos3 * (1 - $tan2 + $etasq) * $dl3 / 6 + |
521
|
|
|
$nd * $cos5 * (5 - 18 * $tan2 + $tan4) * $dl5 / 120 + $kz * 1e6 + 500000); |
522
|
|
|
|
523
|
|
|
$nk = $hw - (int) $hw; |
524
|
|
|
if ($nk < 0.5) { |
525
|
|
|
$hw = (int) $hw; |
526
|
|
|
} else { |
527
|
|
|
$hw = ((int) $hw) + 1; |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
$nk = $rw - (int) $rw; |
531
|
|
|
if ($nk < 0.5) { |
532
|
|
|
$rw = (int) $rw; |
533
|
|
|
} else { |
534
|
|
|
$rw = (int) ($rw + 1); |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
return [ |
538
|
|
|
$rw, |
539
|
|
|
$hw, |
540
|
|
|
]; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* RD Dutch Grid |
545
|
|
|
* |
546
|
|
|
* @return string |
547
|
|
|
*/ |
548
|
|
View Code Duplication |
public function getRD() |
|
|
|
|
549
|
|
|
: string |
550
|
|
|
{ |
551
|
|
|
// X0,Y0 Base RD coordinates Amersfoort |
552
|
|
|
$rdx_base = 155000; |
553
|
|
|
$rdy_base = 463000; |
554
|
|
|
// ?0, ?0 Same base, but as wgs84 coordinates |
555
|
|
|
$lat_base = 52.15517440; |
556
|
|
|
$lon_base = 5.38720621; |
557
|
|
|
|
558
|
|
|
for ($i = 0; $i <= 6; $i ++) { |
559
|
|
|
for ($j = 0; $j <= 5; $j ++) { |
560
|
|
|
$rpq[$i][$j] = 0; |
|
|
|
|
561
|
|
|
$spq[$i][$j] = 0; |
|
|
|
|
562
|
|
|
} |
563
|
|
|
} |
564
|
|
|
//#coefficients |
565
|
|
|
$rpq[0][1] = 190094.945; |
|
|
|
|
566
|
|
|
$rpq[1][1] = - 11832.228; |
567
|
|
|
$rpq[2][1] = - 114.221; |
568
|
|
|
$rpq[0][3] = - 32.391; |
569
|
|
|
$rpq[1][0] = - 0.705; |
570
|
|
|
$rpq[3][1] = - 2.340; |
571
|
|
|
$rpq[1][3] = - 0.608; |
572
|
|
|
$rpq[0][2] = - 0.008; |
573
|
|
|
$rpq[2][3] = 0.148; |
574
|
|
|
|
575
|
|
|
$spq[1][0] = 309056.544; |
|
|
|
|
576
|
|
|
$spq[0][2] = 3638.893; |
577
|
|
|
$spq[2][0] = 73.077; |
578
|
|
|
$spq[1][2] = - 157.984; |
579
|
|
|
$spq[3][0] = 59.788; |
580
|
|
|
$spq[0][1] = 0.433; |
581
|
|
|
$spq[2][2] = - 6.439; |
582
|
|
|
$spq[1][1] = - 0.032; |
583
|
|
|
$spq[0][4] = 0.092; |
584
|
|
|
$spq[1][4] = - 0.054; |
585
|
|
|
|
586
|
|
|
// Calculate X, Y of origin |
587
|
|
|
$latDiff = $this->nLat - $lat_base; |
588
|
|
|
$dlat = 0.36 * $latDiff; |
589
|
|
|
$lonDiff = $this->nLon - $lon_base; |
590
|
|
|
$dlon = 0.36 * $lonDiff; |
591
|
|
|
$xOrigin = 0; |
592
|
|
|
$yOrigin = 0; |
593
|
|
|
|
594
|
|
|
for ($q = 0; $q <= 5; $q ++) { |
595
|
|
|
for ($p = 0; $p <= 6; $p ++) { |
596
|
|
|
$xOrigin = $xOrigin + ($rpq[$p][$q] * ((pow($dlat, $p)) * (pow($dlon, $q)))); |
597
|
|
|
$yOrigin = $yOrigin + ($spq[$p][$q] * ((pow($dlat, $p)) * (pow($dlon, $q)))); |
598
|
|
|
} |
599
|
|
|
} |
600
|
|
|
$xOrigin = $xOrigin + $rdx_base; |
601
|
|
|
$yOrigin = $yOrigin + $rdy_base; |
602
|
|
|
|
603
|
|
|
return 'X ' . floor($xOrigin) . ' Y ' . floor($yOrigin); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* QTH Locator |
608
|
|
|
* |
609
|
|
|
* @return string |
610
|
|
|
*/ |
611
|
|
View Code Duplication |
public function getQTH() |
|
|
|
|
612
|
|
|
: string |
613
|
|
|
{ |
614
|
|
|
$lon = $this->nLon; |
615
|
|
|
$lat = $this->nLat; |
616
|
|
|
|
617
|
|
|
$lon += 180; |
618
|
|
|
$l[0] = floor($lon / 20); |
|
|
|
|
619
|
|
|
$lon -= 20 * $l[0]; |
620
|
|
|
$l[2] = floor($lon / 2); |
621
|
|
|
$lon -= 2 * $l[2]; |
622
|
|
|
$l[4] = floor($lon * 60 / 5); |
623
|
|
|
|
624
|
|
|
$lat += 90; |
625
|
|
|
$l[1] = floor($lat / 10); |
626
|
|
|
$lat -= 10 * $l[1]; |
627
|
|
|
$l[3] = floor($lat); |
628
|
|
|
$lat -= $l[3]; |
629
|
|
|
$l[5] = floor($lat * 120 / 5); |
630
|
|
|
|
631
|
|
|
return sprintf('%c%c%c%c%c%c', $l[0] + 65, $l[1] + 65, $l[2] + 48, $l[3] + 48, $l[4] + 65, $l[5] + 65); |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
/** |
635
|
|
|
* SwissGrid CH1903 |
636
|
|
|
* |
637
|
|
|
* @return string[] |
638
|
|
|
*/ |
639
|
|
View Code Duplication |
public function getSwissGrid() |
|
|
|
|
640
|
|
|
{ |
641
|
|
|
$nLat = $this->nLat * 3600; |
642
|
|
|
$nLon = $this->nLon * 3600; |
643
|
|
|
|
644
|
|
|
// Quelle: http://www.swisstopo.admin.ch/internet/swisstopo/de/home/apps/calc.html |
645
|
|
|
// Hilfsgrössen |
646
|
|
|
$b = ($nLat - 169028.66) / 10000.0; |
647
|
|
|
$l = ($nLon - 26782.5) / 10000.0; |
648
|
|
|
|
649
|
|
|
// Nord x |
650
|
|
|
$x = 200147.07 + 308807.95 * $b + 3745.25 * $l * $l + 76.63 * $b * $b + 119.79 * $b * $b * $b - 194.56 * $b * $l * $l; |
651
|
|
|
$x = floor($x); |
652
|
|
|
|
653
|
|
|
// Ost y |
654
|
|
|
$y = 600072.37 + 211455.93 * $l - 10938.51 * $l * $b - 0.36 * $l * $b * $b - 44.54 * $l * $l * $l; |
655
|
|
|
$y = floor($y); |
656
|
|
|
|
657
|
|
|
// Namen: "CH1903", "Schweizer Landeskoordinaten" oder "Swiss Grid" |
658
|
|
|
$swissgrid = "$y / $x"; |
659
|
|
|
// Karten Links |
660
|
|
|
$mapplus = "<a href=\"http://www.mapplus.ch/frame.php?map=&x=$y&y=$x&zl=13\" target=\"_blank\">MapPlus</a>"; |
661
|
|
|
$mapsearch = "<a href=\"http://map.search.ch/$y,$x\" target=\"_blank\">map.search.ch</a>"; |
662
|
|
|
|
663
|
|
|
return [ |
664
|
|
|
'coord' => $swissgrid, |
665
|
|
|
$mapplus, |
666
|
|
|
$mapsearch, |
667
|
|
|
]; |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* @param $name |
672
|
|
|
* |
673
|
|
|
* @return false|float|int|mixed |
674
|
|
|
*/ |
675
|
|
|
// TODO: aktuell braucht's diese Funktion nicht, aber ev. zuküntig wieder? |
676
|
|
View Code Duplication |
public static function parseRequestLat($name) |
|
|
|
|
677
|
|
|
{ |
678
|
|
|
if (!isset($_REQUEST[$name . 'NS']) || !isset($_REQUEST[$name . 'Lat']) || !isset($_REQUEST[$name . 'LatMin'])) { |
679
|
|
|
return false; |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
$coordNS = $_REQUEST[$name . 'NS']; |
683
|
|
|
$coordLat = $_REQUEST[$name . 'Lat'] + 0; |
684
|
|
|
$coordLatMin = str_replace(',', '.', $_REQUEST[$name . 'LatMin']) + 0; |
685
|
|
|
|
686
|
|
|
$lat = $coordLat + $coordLatMin / 60; |
687
|
|
|
if ($coordNS == 'S') { |
688
|
|
|
$lat = - $lat; |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
return $lat; |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
/** |
695
|
|
|
* @param $name |
696
|
|
|
* |
697
|
|
|
* @return false|float|int|mixed |
698
|
|
|
*/ |
699
|
|
|
// TODO: aktuell braucht's diese Funktion nicht, aber ev. zuküntig wieder? |
700
|
|
View Code Duplication |
public static function parseRequestLon($name) |
|
|
|
|
701
|
|
|
{ |
702
|
|
|
if (!isset($_REQUEST[$name . 'EW']) || !isset($_REQUEST[$name . 'Lon']) || !isset($_REQUEST[$name . 'LonMin'])) { |
703
|
|
|
return false; |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
$coordEW = $_REQUEST[$name . 'EW']; |
707
|
|
|
$coordLon = $_REQUEST[$name . 'Lon'] + 0; |
708
|
|
|
$coordLonMin = str_replace(',', '.', $_REQUEST[$name . 'LonMin']) + 0; |
709
|
|
|
|
710
|
|
|
$lon = $coordLon + $coordLonMin / 60; |
711
|
|
|
if ($coordEW == 'W') { |
712
|
|
|
$lon = - $lon; |
713
|
|
|
} |
714
|
|
|
|
715
|
|
|
return $lon; |
716
|
|
|
} |
717
|
|
|
|
718
|
|
|
/** |
719
|
|
|
* What3Words |
720
|
|
|
* |
721
|
|
|
* @param $language |
722
|
|
|
* |
723
|
|
|
* @return false|mixed |
724
|
|
|
*/ |
725
|
|
|
public function getW3W($language = 'en') |
726
|
|
|
{ |
727
|
|
|
if (!$_ENV['W3W_API']) { |
728
|
|
|
return false; |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
$params = [ |
732
|
|
|
'key' => $_ENV['W3W_API'], |
733
|
|
|
'coordinates' => sprintf('%f,%f', $this->nLat, $this->nLon), |
734
|
|
|
'language' => strtolower($language), |
735
|
|
|
]; |
736
|
|
|
$params_str = http_build_query($params); |
737
|
|
|
|
738
|
|
|
$result = @file_get_contents('https://api.what3words.com/v3/convert-to-3wa?' . $params_str); |
739
|
|
|
if ($result === false) { |
740
|
|
|
return false; |
741
|
|
|
} |
742
|
|
|
|
743
|
|
|
$json = json_decode($result, true); |
744
|
|
|
if (!isset($json['words'])) { |
745
|
|
|
return false; |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
return $json['words']; |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
public function getAllCoordinatesFormatsAsArray(float $newLat = null, float $newLon = null) |
752
|
|
|
: array |
753
|
|
|
{ |
754
|
|
|
if (($newLat != null) && ($newLon != null)) |
755
|
|
|
$this->setLatLon($newLat, $newLon); |
756
|
|
|
|
757
|
|
|
return [ |
758
|
|
|
'coord_Decimal' => $this->getDecimal(), |
759
|
|
|
'coord_DM' => $this->getDegreeMinutes(), |
760
|
|
|
'coord_DMS' => $this->getDegreeMinutesSeconds(), |
761
|
|
|
'coord_GK' => $this->getGK(), |
762
|
|
|
'coord_QTH' => $this->getQTH(), |
763
|
|
|
'coord_RD' => $this->getRD(), |
764
|
|
|
'coord_CH1903' => $this->getSwissGrid(), |
765
|
|
|
'coord_UTM' => $this->getUTM(), |
766
|
|
|
'coord_W3Wde' => $this->getW3W('de'), |
767
|
|
|
'coord_W3Wen' => $this->getW3W(), |
768
|
|
|
]; |
769
|
|
|
} |
770
|
|
|
} |
771
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.