* * 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 \ArrayAccess; use \Countable; use \DomainException; use \IteratorAggregate; /** * The GPX route type. * * @see https://www.topografix.com/GPX/1/1/#type_rteType * * @author Andy Street */ class Route extends DataType implements Geographic, ArrayAccess, Countable, IteratorAggregate { /** * GPS route number. * * @var int */ protected $number; /** * A list of route points. * * @var DoublyLinkedList (Point) */ protected $points; /** * Fetch the route number. * * @return int|null The route number or null if not set. */ public function getNumber() { return $this->number; } /** * Set the number of the route. * * @param int $number The route number or null to delete. * @return void * @throws DomainException If the number is < 0 */ public function setNumber(int $number = null) { if ($number !== null && $number < 0) throw new DomainException( sprintf('Number must be >= 0 but got "%s"', $number) ); $this->number = $number; } /** * Fetch an ordered list of route points. * * @param boolean $create Create the list if it does not already exist. * @return TypedDoublyLinkedList|null A list of route points. */ public function getPoints(bool $create = true) { if ($create && $this->points === null) $this->points = new TypedDoublyLinkedList('libgpx\Point'); return $this->points; } /** * 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() { $result = null; if ($this->points !== null) { foreach ($this->points as $point) { $bounds = $point->getBounds(); if ($result === null) { $result = $bounds; } else { $result->extend($bounds); } } } return $result; } /** * Fetch the length of a route. * * @return float The length in meters. */ public function getLength() { $length = 0; $points = $this->getPoints(false); if ($points !== null && !$points->isEmpty()) { $last_point = null; foreach ($points as $current_point) { if ($last_point !== null) $length += libgpx::distance( $last_point->getLatitude(), $last_point->getLongitude(), $current_point->getLatitude(), $current_point->getLongitude() ); $last_point = $current_point; } } return $length; } /** * Check if an offset holds a value. * * @see ArrayAccess::offsetExists * * @param mixed $offset The offset to search * @return boolean */ public function offsetExists($offset) { return $this->getPoints()->offsetExists($offset); } /** * Fetch a point from this route. * * @see ArrayAccess::offsetGet * * @param mixed $offset The offset to retrieve * @return Point */ public function offsetGet($offset) { return $this->getPoints()->offsetGet($offset); } /** * Set the point at an offset. * * @see ArrayAccess::offsetSet * * @param mixed $offset Where to store the point. * @param Point $value The point to store. * @return void */ public function offsetSet($offset, $value) { return $this->getPoints()->offsetSet($offset, $value); } /** * Remove a point. * * @see ArrayAccess::offsetUnset * * @param mixed $offset Which point to remove * @return void */ public function offsetUnset($offset) { return $this->getPoints()->offsetUnset($offset); } /** * Count the number of points in this route. * * @return int */ public function count() { return ($this->points === null ? 0 : $this->points->count()); } /** * Fetch an iterator for the points contained in this route. * * @return \Iterator */ public function getIterator() { return $this->getPoints(); } }