]> git.street.me.uk Git - andy/gpx.git/blame - src/libgpx/route.php
Fix: PeakStream fails to function correctly after the first file
[andy/gpx.git] / src / libgpx / route.php
CommitLineData
f17d2566
AS
1<?php
2/**
3 * route.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
25namespace libgpx;
26
893cb1f3
AS
27use \ArrayAccess;
28use \Countable;
f17d2566 29use \DomainException;
893cb1f3 30use \IteratorAggregate;
f17d2566
AS
31
32/**
33 * The GPX route type.
34 *
35 * @see https://www.topografix.com/GPX/1/1/#type_rteType
36 *
37 * @author Andy Street <andy@street.me.uk>
38 */
893cb1f3
AS
39class Route extends DataType
40 implements Geographic, ArrayAccess, Countable, IteratorAggregate
f17d2566
AS
41{
42
f17d2566
AS
43 /**
44 * GPS route number.
45 *
46 * @var int
47 */
48 protected $number;
49
f17d2566
AS
50 /**
51 * A list of route points.
52 *
53 * @var DoublyLinkedList (Point)
54 */
55 protected $points;
56
f17d2566
AS
57 /**
58 * Fetch the route number.
59 *
60 * @return int|null The route number or null if not set.
61 */
62 public function getNumber()
63 {
64 return $this->number;
65 }
66
67 /**
68 * Set the number of the route.
69 *
70 * @param int $number The route number or null to delete.
71 * @return void
72 * @throws DomainException If the number is < 0
73 */
74 public function setNumber(int $number = null)
75 {
76 if ($number !== null && $number < 0)
77 throw new DomainException(
78 sprintf('Number must be >= 0 but got "%s"', $number)
79 );
80 $this->number = $number;
81 }
82
f17d2566
AS
83 /**
84 * Fetch an ordered list of route points.
85 *
86 * @param boolean $create Create the list if it does not already exist.
87 * @return TypedDoublyLinkedList|null A list of route points.
88 */
89 public function getPoints(bool $create = true)
90 {
91 if ($create && $this->points === null)
92 $this->points = new TypedDoublyLinkedList('libgpx\Point');
93 return $this->points;
94 }
95
96 /**
97 * Fetch a bounding box that covers the feature.
98 *
99 * @return Bounds|null A bounding box covering the extent of the feature or
100 * null if not applicable.
101 */
102 public function getBounds()
103 {
104 $result = null;
105 if ($this->points !== null) {
106 foreach ($this->points as $point) {
107 $bounds = $point->getBounds();
108 $result = ($result === null ? $bounds : $result->extend($bounds));
109 }
110 }
111 return $result;
112 }
113
d23d8f6f
AS
114 /**
115 * Fetch the length of a route.
116 *
117 * @return float The length in meters.
118 */
119 public function getLength()
120 {
121 $length = 0;
122 $points = $this->getPoints(false);
123 if ($points !== null && !$points->isEmpty()) {
124 $last_point = null;
125 foreach ($points as $current_point) {
126 if ($last_point !== null)
127 $length += libgpx::distance(
128 $last_point->getLatitude(),
129 $last_point->getLongitude(),
130 $current_point->getLatitude(),
131 $current_point->getLongitude()
132 );
133 $last_point = $current_point;
134 }
135 }
136 return $length;
137 }
138
893cb1f3
AS
139 /**
140 * Check if an offset holds a value.
141 *
142 * @see ArrayAccess::offsetExists
143 *
144 * @param mixed $offset The offset to search
145 * @return boolean
146 */
147 public function offsetExists($offset)
148 {
149 return $this->getPoints()->offsetExists($offset);
150 }
151
152 /**
153 * Fetch a point from this route.
154 *
155 * @see ArrayAccess::offsetGet
156 *
157 * @param mixed $offset The offset to retrieve
158 * @return Point
159 */
160 public function offsetGet($offset)
161 {
162 return $this->getPoints()->offsetGet($offset);
163 }
164
165 /**
166 * Set the point at an offset.
167 *
168 * @see ArrayAccess::offsetSet
169 *
170 * @param mixed $offset Where to store the point.
171 * @param Point $value The point to store.
172 * @return void
173 */
174 public function offsetSet($offset, $value)
175 {
176 return $this->getPoints()->offsetSet($offset, $value);
177 }
178
179 /**
180 * Remove a point.
181 *
182 * @see ArrayAccess::offsetUnset
183 *
184 * @param mixed $offset Which point to remove
185 * @return void
186 */
187 public function offsetUnset($offset)
188 {
189 return $this->getPoints()->offsetUnset($offset);
190 }
191
192 /**
193 * Count the number of points in this route.
194 *
195 * @return int
196 */
197 public function count()
198 {
199 return ($this->points === null ? 0 : $this->points->count());
200 }
201
202 /**
203 * Fetch an iterator for the points contained in this route.
204 *
205 * @return \Iterator
206 */
207 public function getIterator() {
208 return $this->getPoints();
209 }
210
f17d2566 211}