5 * Copyright 2018 Andy Street <andy@street.me.uk>
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.
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.
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,
28 use \DateTimeInterface;
33 * @see https://www.topografix.com/GPX/1/1/#type_wptType
35 * @author Andy Street <andy@street.me.uk>
37 class Point extends DataType implements Geographic
41 * The latitude of the point.
48 * The longitude of the point.
55 * Elevation (in meters) of the point.
62 * Creation/modification timestamp for element.
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.
68 * @var DateTimeInterface
73 * Magnetic variation (in degrees) at the point.
80 * Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid.
81 * As defined in NMEA GGA message.
85 protected $geoidheight;
88 * Text of GPS symbol name.
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.
100 * "none", "2d", "3d", "dgps" or "pps".
102 * None means GPS had no fix. To signify "the fix info is unknown, leave out
103 * fixType entirely. pps = military signal used.
110 * Number of satellites used to calculate the GPX fix.
114 protected $satellites;
117 * Horizontal dilution of precision.
124 * Vertical dilution of precision.
131 * Position dilution of precision.
138 * Number of seconds since last DGPS update.
142 protected $ageofdgpsdata;
145 * ID of DGPS station used in differential correction.
152 * Create a new point.
154 * @param float $lat Latitude
155 * @param float $lon Longitude
156 * @throws DomainException If not a valid latitude or longitude.
158 public function __construct(float $lat, float $lon)
160 $this->setLatitude($lat);
161 $this->setLongitude($lon);
165 * Fetch the latitude of the point.
169 public function getLatitude()
175 * Set the latitude of the point.
177 * @param float $lat Latitude
179 * @throws DomainException If not a valid latitude.
181 public function setLatitude(float $lat)
183 if ($lat < -90 || $lat > 90)
184 throw new DomainException(
185 sprintf('Value %s is not in the range -90-+90.', $lat)
191 * Fetch the longitude of the point.
195 public function getLongitude()
201 * Set the longitude of the point.
203 * @param float $lon Longitude
205 * @throws DomainException If not a valid longitude.
207 public function setLongitude(float $lon)
209 if ($lon < -180 || $lon > 180)
210 throw new DomainException(
211 sprintf('Value %s is not in the range -180-+180.', $lon)
217 * Fetch the elevation of the point.
219 * @return float|null The elevation in meters or null if not set.
221 public function getEle()
227 * Set the elevation of the point.
229 * @param float $ele The elevation in meters or null to delete.
232 public function setEle(float $ele = null)
238 * Fetch the creation time of the point.
240 * @return DateTimeInterface|null The time or null if not set.
242 public function getTime()
248 * Set the creation time of the point.
250 * @param DateTimeInterface $time The creation time or null to delete.
253 public function setTime(DateTimeInterface $time = null)
259 * Fetch the magnetic variation.
261 * @return float|null The magnetic variation in degrees or null if not set.
263 public function getMagvar()
265 return $this->magvar;
269 * Set the magnetic variation.
271 * @param float $magvar The magnetic variation in degrees or null to delete.
273 * @throws DomainException if not in range 0 <= value < 360
275 public function setMagvar(float $magvar = null)
279 && ($magvar < 0 || $magvar >= 360)
281 throw new DomainException(
282 sprintf('Value %s is not in the range 0 <= value < 360.', $lon)
285 $this->magvar = $magvar;
289 * Fetch the geoid height at the point.
291 * @return float The geoid height in meters.
293 public function getGeoidHeight()
295 return $this->geoidheight;
299 * Set the geoid height at the point.
301 * @param float $geoidheight The geoid height in meters.
304 public function setGeoidHeight(float $geoidheight = null)
306 $this->geoidheight = $geoidheight;
310 * Fetch the waypoint symbol.
312 * @return string|null The symbol or null if not set.
314 public function getSymbol()
316 return $this->symbol;
320 * Set the symbol representing this point.
322 * @param string $symbol The name of the symbol or null to delete.
325 public function setSymbol(string $symbol = null)
327 $this->symbol = $symbol;
331 * Fetch the fix type for this point.
333 * @return string|null The fix type or null if not set.
335 public function getFix()
343 * @param string $fix "none", "2d", "3d", "dgps", "pps" or null to delete.
345 * @throws DomainException If an invalid fix type is passed.
347 public function setFix(string $fix = null)
349 if ($fix !== null && !in_array($fix, ['none', '2d', '3d', 'dgps', 'pps']))
350 throw new DomainException(sprintf('Unknown fix type "%s"', $fix));
355 * Fetch the number of satellites used to calculate the fix.
357 * @return int The number of satellites or null if not set.
359 public function getSatellites()
361 return $this->satellites;
365 * Set the number of satellites used to calculate the fix.
367 * @param int $satellites The number if satellites or null to delete.
369 * @throws DomainException If $satellites < 0
371 public function setSatellites(int $satellites = null)
373 if ($satellites !== null && $satellites < 0)
374 throw new DomainException(
375 sprintf('Satellites must be >= 0 but got %s', $satellites)
377 $this->satellites = $satellites;
381 * Fetch the hdop of the point.
383 * @return float|null The hdop or null if not set.
385 public function getHdop()
391 * Set the hdop of the point.
393 * @param float $hdop The hdop or null to delete.
396 public function setHdop(float $hdop = null)
402 * Fetch the vdop of the point.
404 * @return float|null The vdop or null if not set.
406 public function getVdop()
412 * Set the vdop of the point.
414 * @param float $vdop The vdop or null to delete.
417 public function setVdop(float $vdop = null)
423 * Fetch the pdop of the point.
425 * @return float|null The pdop or null if not set.
427 public function getPdop()
433 * Set the pdop of the point.
435 * @param float $pdop The pdop or null to delete.
438 public function setPdop(float $pdop = null)
444 * Fetch the age of the DGPS data.
446 * @return float The age of DGPS data in seconds or null if not set.
448 public function getAgeOfDGPSData()
450 return $this->ageofdgpsdata;
454 * Set the age of the DGPS data.
456 * @param float $ageofdgpsdata The age in seconds or null to delete.
459 public function setAgeOfDGPSData(float $ageofdgpsdata = null)
461 $this->ageofdgpsdata = $ageofdgpsdata;
465 * Fetch the id of the DGPS station.
467 * @return int The DGPS id or null if not set.
469 public function getDGPSId()
471 return $this->dgpsid;
475 * Set the id of the DGPS station.
477 * @param int $dgpsid The station id.
479 * @throws DomainException If the station id < 0 or > 1023.
481 public function setDGPSId(int $dgpsid = null)
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)
487 return $this->dgpsid = $dgpsid;
491 * Fetch a bounding box that covers the feature.
493 * @return Bounds|null A bounding box covering the extent of the feature or
494 * null if not applicable.
496 public function getBounds()
498 return new Bounds($this->lat, $this->lon, $this->lat, $this->lon);
502 * Fetch the length of a point.
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.
508 * @return float The length in meters.
510 public function getLength()
516 * Find the distance to another point.
518 * @param Point $point The point to find the distance to.
519 * @return float The distance in meters.
521 public function distanceTo(Point $point)
523 return libgpx::distance(
526 $point->getLatitude(),
527 $point->getLongitude()