* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * */ namespace libgpx; use \DomainException; use \DateTimeInterface; /** * A geographic point. * * @see https://www.topografix.com/GPX/1/1/#type_wptType * * @author Andy Street */ class Point extends DataType implements Geographic { /** * The latitude of the point. * * @var float */ protected $lat; /** * The longitude of the point. * * @var float */ protected $lon; /** * Elevation (in meters) of the point. * * @var float */ protected $ele; /** * Creation/modification timestamp for element. * * Date and time in are in Univeral Coordinated Time (UTC), not local time! * Conforms to ISO 8601 specification for date/time representation. * Fractional seconds are allowed for millisecond timing in tracklogs. * * @var DateTimeInterface */ protected $time; /** * Magnetic variation (in degrees) at the point. * * @var float */ protected $magvar; /** * Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. * As defined in NMEA GGA message. * * @var float */ protected $geoidheight; /** * Text of GPS symbol name. * * For interchange with other programs, use the exact spelling of the symbol * as displayed on the GPS. If the GPS abbreviates words, spell them out. * * @var string */ protected $symbol; /** * Type of GPS fix. * * "none", "2d", "3d", "dgps" or "pps". * * None means GPS had no fix. To signify "the fix info is unknown, leave out * fixType entirely. pps = military signal used. * * @var string */ protected $fix; /** * Number of satellites used to calculate the GPX fix. * * @var int */ protected $satellites; /** * Horizontal dilution of precision. * * @var float */ protected $hdop; /** * Vertical dilution of precision. * * @var float */ protected $vdop; /** * Position dilution of precision. * * @var float */ protected $pdop; /** * Number of seconds since last DGPS update. * * @var float */ protected $ageofdgpsdata; /** * ID of DGPS station used in differential correction. * * @var int */ protected $dgpsid; /** * Create a new point. * * @param float $lat Latitude * @param float $lon Longitude * @throws DomainException If not a valid latitude or longitude. */ public function __construct(float $lat, float $lon) { $this->setLatitude($lat); $this->setLongitude($lon); } /** * Fetch the latitude of the point. * * @return float */ public function getLatitude() { return $this->lat; } /** * Set the latitude of the point. * * @param float $lat Latitude * @return void * @throws DomainException If not a valid latitude. */ public function setLatitude(float $lat) { if ($lat < -90 || $lat > 90) throw new DomainException( sprintf('Value %s is not in the range -90-+90.', $lat) ); $this->lat = $lat; } /** * Fetch the longitude of the point. * * @return float */ public function getLongitude() { return $this->lon; } /** * Set the longitude of the point. * * @param float $lon Longitude * @return void * @throws DomainException If not a valid longitude. */ public function setLongitude(float $lon) { if ($lon < -180 || $lon > 180) throw new DomainException( sprintf('Value %s is not in the range -180-+180.', $lon) ); $this->lon = $lon; } /** * Fetch the elevation of the point. * * @return float|null The elevation in meters or null if not set. */ public function getEle() { return $this->ele; } /** * Set the elevation of the point. * * @param float $ele The elevation in meters or null to delete. * @return void */ public function setEle(float $ele = null) { $this->ele = $ele; } /** * Fetch the creation time of the point. * * @return DateTimeInterface|null The time or null if not set. */ public function getTime() { return $this->time; } /** * Set the creation time of the point. * * @param DateTimeInterface $time The creation time or null to delete. * @return void */ public function setTime(DateTimeInterface $time = null) { $this->time = $time; } /** * Fetch the magnetic variation. * * @return float|null The magnetic variation in degrees or null if not set. */ public function getMagvar() { return $this->magvar; } /** * Set the magnetic variation. * * @param float $magvar The magnetic variation in degrees or null to delete. * @return void * @throws DomainException if not in range 0 <= value < 360 */ public function setMagvar(float $magvar = null) { if ( $magvar !== null && ($magvar < 0 || $magvar >= 360) ) { throw new DomainException( sprintf('Value %s is not in the range 0 <= value < 360.', $lon) ); } $this->magvar = $magvar; } /** * Fetch the geoid height at the point. * * @return float The geoid height in meters. */ public function getGeoidHeight() { return $this->geoidheight; } /** * Set the geoid height at the point. * * @param float $geoidheight The geoid height in meters. * @return void */ public function setGeoidHeight(float $geoidheight = null) { $this->geoidheight = $geoidheight; } /** * Fetch the waypoint symbol. * * @return string|null The symbol or null if not set. */ public function getSymbol() { return $this->symbol; } /** * Set the symbol representing this point. * * @param string $symbol The name of the symbol or null to delete. * @return void */ public function setSymbol(string $symbol = null) { $this->symbol = $symbol; } /** * Fetch the fix type for this point. * * @return string|null The fix type or null if not set. */ public function getFix() { return $this->fix; } /** * Set the fix type. * * @param string $fix "none", "2d", "3d", "dgps", "pps" or null to delete. * @return void * @throws DomainException If an invalid fix type is passed. */ public function setFix(string $fix = null) { if ($fix !== null && !in_array($fix, ['none', '2d', '3d', 'dgps', 'pps'])) throw new DomainException(sprintf('Unknown fix type "%s"', $fix)); $this->fix = $fix; } /** * Fetch the number of satellites used to calculate the fix. * * @return int The number of satellites or null if not set. */ public function getSatellites() { return $this->satellites; } /** * Set the number of satellites used to calculate the fix. * * @param int $satellites The number if satellites or null to delete. * @return void * @throws DomainException If $satellites < 0 */ public function setSatellites(int $satellites = null) { if ($satellites !== null && $satellites < 0) throw new DomainException( sprintf('Satellites must be >= 0 but got %s', $satellites) ); $this->satellites = $satellites; } /** * Fetch the hdop of the point. * * @return float|null The hdop or null if not set. */ public function getHdop() { return $this->hdop; } /** * Set the hdop of the point. * * @param float $hdop The hdop or null to delete. * @return void */ public function setHdop(float $hdop = null) { $this->hdop = $hdop; } /** * Fetch the vdop of the point. * * @return float|null The vdop or null if not set. */ public function getVdop() { return $this->vdop; } /** * Set the vdop of the point. * * @param float $vdop The vdop or null to delete. * @return void */ public function setVdop(float $vdop = null) { $this->vdop = $vdop; } /** * Fetch the pdop of the point. * * @return float|null The pdop or null if not set. */ public function getPdop() { return $this->pdop; } /** * Set the pdop of the point. * * @param float $pdop The pdop or null to delete. * @return void */ public function setPdop(float $pdop = null) { $this->pdop = $pdop; } /** * Fetch the age of the DGPS data. * * @return float The age of DGPS data in seconds or null if not set. */ public function getAgeOfDGPSData() { return $this->ageofdgpsdata; } /** * Set the age of the DGPS data. * * @param float $ageofdgpsdata The age in seconds or null to delete. * @return void */ public function setAgeOfDGPSData(float $ageofdgpsdata = null) { $this->ageofdgpsdata = $ageofdgpsdata; } /** * Fetch the id of the DGPS station. * * @return int The DGPS id or null if not set. */ public function getDGPSId() { return $this->dgpsid; } /** * Set the id of the DGPS station. * * @param int $dgpsid The station id. * @return void * @throws DomainException If the station id < 0 or > 1023. */ public function setDGPSId(int $dgpsid = null) { if ($dgpsid !== null && ($dgpsid < 0 || $dgpsid > 1023)) throw new DomainException( sprintf('DGPS id must be >= 0 and <= 1023 but got %s', $dgpsid) ); return $this->dgpsid = $dgpsid; } /** * Fetch a bounding box that covers the feature. * * @return Bounds|null A bounding box covering the extent of the feature or * null if not applicable. */ public function getBounds() { return new Bounds($this->lat, $this->lon, $this->lat, $this->lon); } /** * Fetch the length of a point. * * Note: Length is the distance between two points so calling this function * on a single point makes little sense. It is implemented to complete * the `Geographic` interface and will always return a value of 0. * * @return float The length in meters. */ public function getLength() { return 0.0; } /** * Find the distance to another point. * * @param Point $point The point to find the distance to. * @return float The distance in meters. */ public function distanceTo(Point $point) { return libgpx::distance( $this->lat, $this->lon, $point->getLatitude(), $point->getLongitude() ); } }