]> git.street.me.uk Git - andy/gpx.git/blob - src/libgpx/route.php
Add length measurement to geographic classes
[andy/gpx.git] / src / libgpx / route.php
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
25 namespace libgpx;
26
27 use \DomainException;
28
29 /**
30  * The GPX route type.
31  *
32  * @see https://www.topografix.com/GPX/1/1/#type_rteType
33  *
34  * @author Andy Street <andy@street.me.uk>
35  */
36 class Route extends DataType implements Geographic
37 {
38
39   /**
40    * GPS route number.
41    *
42    * @var int
43    */
44   protected $number;
45
46   /**
47    * A list of route points.
48    *
49    * @var DoublyLinkedList (Point)
50    */
51   protected $points;
52
53   /**
54    * Fetch the route number.
55    *
56    * @return int|null The route number or null if not set.
57    */
58   public function getNumber()
59   {
60     return $this->number;
61   }
62
63   /**
64    * Set the number of the route.
65    *
66    * @param int $number The route number or null to delete.
67    * @return void
68    * @throws DomainException If the number is < 0
69    */
70   public function setNumber(int $number = null)
71   {
72     if ($number !== null && $number < 0)
73       throw new DomainException(
74         sprintf('Number must be >= 0 but got "%s"', $number)
75       );
76     $this->number = $number;
77   }
78
79   /**
80    * Fetch an ordered list of route points.
81    *
82    * @param boolean $create Create the list if it does not already exist.
83    * @return TypedDoublyLinkedList|null A list of route points.
84    */
85   public function getPoints(bool $create = true)
86   {
87     if ($create && $this->points === null)
88       $this->points = new TypedDoublyLinkedList('libgpx\Point');
89     return $this->points;
90   }
91
92   /**
93    * Fetch a bounding box that covers the feature.
94    *
95    * @return Bounds|null A bounding box covering the extent of the feature or
96    *         null if not applicable.
97    */
98   public function getBounds()
99   {
100     $result = null;
101     if ($this->points !== null) {
102       foreach ($this->points as $point) {
103         $bounds = $point->getBounds();
104         $result = ($result === null ? $bounds : $result->extend($bounds));
105       }
106     }
107     return $result;
108   }
109
110   /**
111    * Fetch the length of a route.
112    *
113    * @return float The length in meters.
114    */
115   public function getLength()
116   {
117     $length = 0;
118     $points = $this->getPoints(false);
119     if ($points !== null && !$points->isEmpty()) {
120       $last_point = null;
121       foreach ($points as $current_point) {
122         if ($last_point !== null)
123           $length += libgpx::distance(
124             $last_point->getLatitude(),
125             $last_point->getLongitude(),
126             $current_point->getLatitude(),
127             $current_point->getLongitude()
128           );
129         $last_point = $current_point;
130       }
131     }
132     return $length;
133   }
134
135 }