]>
Commit | Line | Data |
---|---|---|
f528d248 AS |
1 | <?php |
2 | /** | |
3 | * point.php | |
4 | * | |
5 | * Copyright 2018 Andy Street <andy@street.me.uk> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
20 | * MA 02110-1301, USA. | |
21 | * | |
22 | * | |
23 | */ | |
24 | ||
25 | namespace libgpx; | |
26 | ||
27 | use \DomainException; | |
28 | use \DateTimeInterface; | |
29 | ||
30 | /** | |
31 | * A geographic point. | |
32 | * | |
33 | * @see https://www.topografix.com/GPX/1/1/#type_wptType | |
34 | * | |
35 | * @author Andy Street <andy@street.me.uk> | |
36 | */ | |
09a36623 | 37 | class Point extends DataType implements Geographic |
f528d248 AS |
38 | { |
39 | ||
40 | /** | |
41 | * The latitude of the point. | |
42 | * | |
43 | * @var float | |
44 | */ | |
45 | protected $lat; | |
46 | ||
47 | /** | |
48 | * The longitude of the point. | |
49 | * | |
50 | * @var float | |
51 | */ | |
52 | protected $lon; | |
53 | ||
54 | /** | |
55 | * Elevation (in meters) of the point. | |
56 | * | |
57 | * @var float | |
58 | */ | |
59 | protected $ele; | |
60 | ||
61 | /** | |
62 | * Creation/modification timestamp for element. | |
63 | * | |
64 | * Date and time in are in Univeral Coordinated Time (UTC), not local time! | |
65 | * Conforms to ISO 8601 specification for date/time representation. | |
66 | * Fractional seconds are allowed for millisecond timing in tracklogs. | |
67 | * | |
68 | * @var DateTimeInterface | |
69 | */ | |
70 | protected $time; | |
71 | ||
72 | /** | |
73 | * Magnetic variation (in degrees) at the point. | |
74 | * | |
75 | * @var float | |
76 | */ | |
77 | protected $magvar; | |
78 | ||
79 | /** | |
80 | * Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. | |
81 | * As defined in NMEA GGA message. | |
82 | * | |
83 | * @var float | |
84 | */ | |
85 | protected $geoidheight; | |
86 | ||
f528d248 AS |
87 | /** |
88 | * Text of GPS symbol name. | |
89 | * | |
90 | * For interchange with other programs, use the exact spelling of the symbol | |
91 | * as displayed on the GPS. If the GPS abbreviates words, spell them out. | |
92 | * | |
93 | * @var string | |
94 | */ | |
95 | protected $symbol; | |
96 | ||
f528d248 AS |
97 | /** |
98 | * Type of GPS fix. | |
99 | * | |
100 | * "none", "2d", "3d", "dgps" or "pps". | |
101 | * | |
102 | * None means GPS had no fix. To signify "the fix info is unknown, leave out | |
103 | * fixType entirely. pps = military signal used. | |
104 | * | |
105 | * @var string | |
106 | */ | |
107 | protected $fix; | |
108 | ||
109 | /** | |
110 | * Number of satellites used to calculate the GPX fix. | |
111 | * | |
112 | * @var int | |
113 | */ | |
114 | protected $satellites; | |
115 | ||
116 | /** | |
117 | * Horizontal dilution of precision. | |
118 | * | |
119 | * @var float | |
120 | */ | |
121 | protected $hdop; | |
122 | ||
123 | /** | |
124 | * Vertical dilution of precision. | |
125 | * | |
126 | * @var float | |
127 | */ | |
128 | protected $vdop; | |
129 | ||
130 | /** | |
131 | * Position dilution of precision. | |
132 | * | |
133 | * @var float | |
134 | */ | |
135 | protected $pdop; | |
136 | ||
137 | /** | |
138 | * Number of seconds since last DGPS update. | |
139 | * | |
140 | * @var float | |
141 | */ | |
142 | protected $ageofdgpsdata; | |
143 | ||
144 | /** | |
145 | * ID of DGPS station used in differential correction. | |
146 | * | |
147 | * @var int | |
148 | */ | |
149 | protected $dgpsid; | |
150 | ||
f528d248 AS |
151 | /** |
152 | * Create a new point. | |
153 | * | |
154 | * @param float $lat Latitude | |
155 | * @param float $lon Longitude | |
156 | * @throws DomainException If not a valid latitude or longitude. | |
157 | */ | |
158 | public function __construct(float $lat, float $lon) | |
159 | { | |
160 | $this->setLatitude($lat); | |
161 | $this->setLongitude($lon); | |
162 | } | |
163 | ||
164 | /** | |
165 | * Fetch the latitude of the point. | |
166 | * | |
167 | * @return float | |
168 | */ | |
169 | public function getLatitude() | |
170 | { | |
171 | return $this->lat; | |
172 | } | |
173 | ||
174 | /** | |
175 | * Set the latitude of the point. | |
176 | * | |
177 | * @param float $lat Latitude | |
178 | * @return void | |
179 | * @throws DomainException If not a valid latitude. | |
180 | */ | |
181 | public function setLatitude(float $lat) | |
182 | { | |
183 | if ($lat < -90 || $lat > 90) | |
184 | throw new DomainException( | |
185 | sprintf('Value %s is not in the range -90-+90.', $lat) | |
186 | ); | |
187 | $this->lat = $lat; | |
188 | } | |
189 | ||
190 | /** | |
191 | * Fetch the longitude of the point. | |
192 | * | |
193 | * @return float | |
194 | */ | |
195 | public function getLongitude() | |
196 | { | |
197 | return $this->lon; | |
198 | } | |
199 | ||
200 | /** | |
201 | * Set the longitude of the point. | |
202 | * | |
203 | * @param float $lon Longitude | |
204 | * @return void | |
205 | * @throws DomainException If not a valid longitude. | |
206 | */ | |
207 | public function setLongitude(float $lon) | |
208 | { | |
209 | if ($lon < -180 || $lon > 180) | |
210 | throw new DomainException( | |
211 | sprintf('Value %s is not in the range -180-+180.', $lon) | |
212 | ); | |
213 | $this->lon = $lon; | |
214 | } | |
215 | ||
216 | /** | |
217 | * Fetch the elevation of the point. | |
218 | * | |
219 | * @return float|null The elevation in meters or null if not set. | |
220 | */ | |
221 | public function getEle() | |
222 | { | |
223 | return $this->ele; | |
224 | } | |
225 | ||
226 | /** | |
227 | * Set the elevation of the point. | |
228 | * | |
229 | * @param float $ele The elevation in meters or null to delete. | |
230 | * @return void | |
231 | */ | |
232 | public function setEle(float $ele = null) | |
233 | { | |
234 | $this->ele = $ele; | |
235 | } | |
236 | ||
237 | /** | |
238 | * Fetch the creation time of the point. | |
239 | * | |
240 | * @return DateTimeInterface|null The time or null if not set. | |
241 | */ | |
242 | public function getTime() | |
243 | { | |
244 | return $this->time; | |
245 | } | |
246 | ||
247 | /** | |
248 | * Set the creation time of the point. | |
249 | * | |
250 | * @param DateTimeInterface $time The creation time or null to delete. | |
251 | * @return void | |
252 | */ | |
253 | public function setTime(DateTimeInterface $time = null) | |
254 | { | |
255 | $this->time = $time; | |
256 | } | |
257 | ||
258 | /** | |
259 | * Fetch the magnetic variation. | |
260 | * | |
261 | * @return float|null The magnetic variation in degrees or null if not set. | |
262 | */ | |
263 | public function getMagvar() | |
264 | { | |
265 | return $this->magvar; | |
266 | } | |
267 | ||
268 | /** | |
269 | * Set the magnetic variation. | |
270 | * | |
271 | * @param float $magvar The magnetic variation in degrees or null to delete. | |
272 | * @return void | |
273 | * @throws DomainException if not in range 0 <= value < 360 | |
274 | */ | |
275 | public function setMagvar(float $magvar = null) | |
276 | { | |
277 | if ( | |
278 | $magvar !== null | |
279 | && ($magvar < 0 || $magvar >= 360) | |
280 | ) { | |
281 | throw new DomainException( | |
282 | sprintf('Value %s is not in the range 0 <= value < 360.', $lon) | |
283 | ); | |
284 | } | |
285 | $this->magvar = $magvar; | |
286 | } | |
287 | ||
288 | /** | |
289 | * Fetch the geoid height at the point. | |
290 | * | |
291 | * @return float The geoid height in meters. | |
292 | */ | |
293 | public function getGeoidHeight() | |
294 | { | |
295 | return $this->geoidheight; | |
296 | } | |
297 | ||
298 | /** | |
299 | * Set the geoid height at the point. | |
300 | * | |
301 | * @param float $geoidheight The geoid height in meters. | |
302 | * @return void | |
303 | */ | |
304 | public function setGeoidHeight(float $geoidheight = null) | |
305 | { | |
306 | $this->geoidheight = $geoidheight; | |
307 | } | |
308 | ||
f528d248 AS |
309 | /** |
310 | * Fetch the waypoint symbol. | |
311 | * | |
312 | * @return string|null The symbol or null if not set. | |
313 | */ | |
314 | public function getSymbol() | |
315 | { | |
316 | return $this->symbol; | |
317 | } | |
318 | ||
319 | /** | |
320 | * Set the symbol representing this point. | |
321 | * | |
322 | * @param string $symbol The name of the symbol or null to delete. | |
323 | * @return void | |
324 | */ | |
325 | public function setSymbol(string $symbol = null) | |
326 | { | |
327 | $this->symbol = $symbol; | |
328 | } | |
329 | ||
f528d248 AS |
330 | /** |
331 | * Fetch the fix type for this point. | |
332 | * | |
333 | * @return string|null The fix type or null if not set. | |
334 | */ | |
335 | public function getFix() | |
336 | { | |
337 | return $this->fix; | |
338 | } | |
339 | ||
340 | /** | |
341 | * Set the fix type. | |
342 | * | |
343 | * @param string $fix "none", "2d", "3d", "dgps", "pps" or null to delete. | |
344 | * @return void | |
345 | * @throws DomainException If an invalid fix type is passed. | |
346 | */ | |
347 | public function setFix(string $fix = null) | |
348 | { | |
349 | if ($fix !== null && !in_array($fix, ['none', '2d', '3d', 'dgps', 'pps'])) | |
350 | throw new DomainException(sprintf('Unknown fix type "%s"', $fix)); | |
351 | $this->fix = $fix; | |
352 | } | |
353 | ||
354 | /** | |
355 | * Fetch the number of satellites used to calculate the fix. | |
356 | * | |
357 | * @return int The number of satellites or null if not set. | |
358 | */ | |
359 | public function getSatellites() | |
360 | { | |
361 | return $this->satellites; | |
362 | } | |
363 | ||
364 | /** | |
365 | * Set the number of satellites used to calculate the fix. | |
366 | * | |
367 | * @param int $satellites The number if satellites or null to delete. | |
368 | * @return void | |
369 | * @throws DomainException If $satellites < 0 | |
370 | */ | |
371 | public function setSatellites(int $satellites = null) | |
372 | { | |
373 | if ($satellites !== null && $satellites < 0) | |
374 | throw new DomainException( | |
375 | sprintf('Satellites must be >= 0 but got %s', $satellites) | |
376 | ); | |
377 | $this->satellites = $satellites; | |
378 | } | |
379 | ||
380 | /** | |
381 | * Fetch the hdop of the point. | |
382 | * | |
383 | * @return float|null The hdop or null if not set. | |
384 | */ | |
385 | public function getHdop() | |
386 | { | |
387 | return $this->hdop; | |
388 | } | |
389 | ||
390 | /** | |
391 | * Set the hdop of the point. | |
392 | * | |
393 | * @param float $hdop The hdop or null to delete. | |
394 | * @return void | |
395 | */ | |
396 | public function setHdop(float $hdop = null) | |
397 | { | |
398 | $this->hdop = $hdop; | |
399 | } | |
400 | ||
401 | /** | |
402 | * Fetch the vdop of the point. | |
403 | * | |
404 | * @return float|null The vdop or null if not set. | |
405 | */ | |
406 | public function getVdop() | |
407 | { | |
408 | return $this->vdop; | |
409 | } | |
410 | ||
411 | /** | |
412 | * Set the vdop of the point. | |
413 | * | |
414 | * @param float $vdop The vdop or null to delete. | |
415 | * @return void | |
416 | */ | |
417 | public function setVdop(float $vdop = null) | |
418 | { | |
419 | $this->vdop = $vdop; | |
420 | } | |
421 | ||
422 | /** | |
423 | * Fetch the pdop of the point. | |
424 | * | |
425 | * @return float|null The pdop or null if not set. | |
426 | */ | |
427 | public function getPdop() | |
428 | { | |
429 | return $this->pdop; | |
430 | } | |
431 | ||
432 | /** | |
433 | * Set the pdop of the point. | |
434 | * | |
435 | * @param float $pdop The pdop or null to delete. | |
436 | * @return void | |
437 | */ | |
438 | public function setPdop(float $pdop = null) | |
439 | { | |
440 | $this->pdop = $pdop; | |
441 | } | |
442 | ||
443 | /** | |
444 | * Fetch the age of the DGPS data. | |
445 | * | |
446 | * @return float The age of DGPS data in seconds or null if not set. | |
447 | */ | |
448 | public function getAgeOfDGPSData() | |
449 | { | |
450 | return $this->ageofdgpsdata; | |
451 | } | |
452 | ||
453 | /** | |
454 | * Set the age of the DGPS data. | |
455 | * | |
456 | * @param float $ageofdgpsdata The age in seconds or null to delete. | |
457 | * @return void | |
458 | */ | |
459 | public function setAgeOfDGPSData(float $ageofdgpsdata = null) | |
460 | { | |
461 | $this->ageofdgpsdata = $ageofdgpsdata; | |
462 | } | |
463 | ||
464 | /** | |
465 | * Fetch the id of the DGPS station. | |
466 | * | |
467 | * @return int The DGPS id or null if not set. | |
468 | */ | |
469 | public function getDGPSId() | |
470 | { | |
471 | return $this->dgpsid; | |
472 | } | |
473 | ||
474 | /** | |
475 | * Set the id of the DGPS station. | |
476 | * | |
477 | * @param int $dgpsid The station id. | |
478 | * @return void | |
479 | * @throws DomainException If the station id < 0 or > 1023. | |
480 | */ | |
481 | public function setDGPSId(int $dgpsid = null) | |
482 | { | |
483 | if ($dgpsid !== null && ($dgpsid < 0 || $dgpsid > 1023)) | |
484 | throw new DomainException( | |
485 | sprintf('DGPS id must be >= 0 and <= 1023 but got %s', $dgpsid) | |
486 | ); | |
487 | return $this->dgpsid = $dgpsid; | |
488 | } | |
489 | ||
f528d248 AS |
490 | /** |
491 | * Fetch a bounding box that covers the feature. | |
492 | * | |
493 | * @return Bounds|null A bounding box covering the extent of the feature or | |
494 | * null if not applicable. | |
495 | */ | |
496 | public function getBounds() | |
497 | { | |
498 | return new Bounds($this->lat, $this->lon, $this->lat, $this->lon); | |
499 | } | |
d23d8f6f AS |
500 | |
501 | /** | |
502 | * Fetch the length of a point. | |
503 | * | |
504 | * Note: Length is the distance between two points so calling this function | |
505 | * on a single point makes little sense. It is implemented to complete | |
506 | * the `Geographic` interface and will always return a value of 0. | |
507 | * | |
508 | * @return float The length in meters. | |
509 | */ | |
510 | public function getLength() | |
511 | { | |
512 | return 0.0; | |
513 | } | |
514 | ||
515 | /** | |
516 | * Find the distance to another point. | |
517 | * | |
518 | * @param Point $point The point to find the distance to. | |
519 | * @return float The distance in meters. | |
520 | */ | |
521 | public function distanceTo(Point $point) | |
522 | { | |
523 | return libgpx::distance( | |
524 | $this->lat, | |
525 | $this->lon, | |
526 | $point->getLatitude(), | |
527 | $point->getLongitude() | |
528 | ); | |
529 | } | |
530 | ||
f528d248 | 531 | } |