Completed
Push — master ( 69bbac...c6a45b )
by Dragos
03:11
created

TrackPoint::extensions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace SportTrackerConnector\Core\Workout;
6
7
use SportTrackerConnector\Core\Workout\Extension\ExtensionInterface;
8
9
/**
10
 * A point in a track.
11
 */
12
class TrackPoint
13
{
14
    /**
15
     * Latitude of the point.
16
     *
17
     * @var float
18
     */
19
    protected $latitude;
20
21
    /**
22
     * Longitude of the point.
23
     *
24
     * @var float
25
     */
26
    protected $longitude;
27
28
    /**
29
     * The distance in meters from start to this point.
30
     *
31
     * @var float
32
     */
33
    protected $distance;
34
35
    /**
36
     * Elevation of the point.
37
     *
38
     * @var float
39
     */
40
    protected $elevation;
41
42
    /**
43
     * The time for the point.
44
     *
45
     * @var \DateTime
46
     */
47
    protected $dateTime;
48
49
    /**
50
     * Array of extensions.
51
     *
52
     * @var ExtensionInterface[]
53
     */
54
    protected $extensions = array();
55
56
    /**
57
     * @param float $latitude The latitude.
58
     * @param float $longitude The longitude.
59
     * @param \DateTime $dateTime The date and time of the point.
60
     */
61
    public function __construct(float $latitude, float $longitude, \DateTime $dateTime)
62
    {
63
        $this->latitude = $latitude;
64
        $this->longitude = $longitude;
65
        $this->dateTime = $dateTime;
66
    }
67
68
    /**
69
     * Set the elevation.
70
     *
71
     * @param float $elevation The elevation.
72
     */
73
    public function setElevation(float $elevation)
74
    {
75
        $this->elevation = $elevation;
76
    }
77
78
    /**
79
     * Get the elevation.
80
     *
81
     * @return float
82
     */
83
    public function getElevation() : float
84
    {
85
        return $this->elevation;
86
    }
87
88
    /**
89
     * Set the extensions.
90
     *
91
     * @param ExtensionInterface[] $extensions The extensions to set.
92
     */
93
    public function setExtensions(array $extensions)
94
    {
95
        $this->extensions = array();
96
        foreach ($extensions as $extension) {
97
            $this->addExtension($extension);
98
        }
99
    }
100
101
    /**
102
     * Get the extensions.
103
     *
104
     * @return ExtensionInterface[]
105
     */
106
    public function extensions()
107
    {
108
        return $this->extensions;
109
    }
110
111
    /**
112
     * Add an extension to the workout.
113
     *
114
     * @param ExtensionInterface $extension The extension to add.
115
     */
116
    public function addExtension(ExtensionInterface $extension)
117
    {
118
        $this->extensions[$extension::ID()] = $extension;
119
    }
120
121
    /**
122
     * Check if an extension is present.
123
     *
124
     * @param string $idExtension The ID of the extension.
125
     * @return boolean
126
     */
127
    public function hasExtension($idExtension)
128
    {
129
        return array_key_exists($idExtension, $this->extensions);
130
    }
131
132
    /**
133
     * Get an extension by ID.
134
     *
135
     * @param string $idExtension The ID of the extension.
136
     * @return ExtensionInterface
137
     * @throws \OutOfBoundsException If the extension is not found.
138
     */
139
    public function extension($idExtension)
140
    {
141
        if ($this->hasExtension($idExtension) !== true) {
142
            throw new \OutOfBoundsException(sprintf('Extension "%s" not found.', $idExtension));
143
        }
144
145
        return $this->extensions[$idExtension];
146
    }
147
148
    /**
149
     * Get the latitude.
150
     *
151
     * @return float
152
     */
153
    public function latitude() : float
154
    {
155
        return $this->latitude;
156
    }
157
158
    /**
159
     * Get the longitude.
160
     *
161
     * @return float
162
     */
163
    public function longitude() : float
164
    {
165
        return $this->longitude;
166
    }
167
168
    /**
169
     * Get the date time of the point.
170
     *
171
     * @return \DateTime
172
     */
173
    public function dateTime() : \DateTime
174
    {
175
        return $this->dateTime;
176
    }
177
178
    /**
179
     * Set the distance from start to this point.
180
     *
181
     * @param float $distance The distance from start to this point.
182
     */
183
    public function setDistance($distance)
184
    {
185
        if ($distance !== null) {
186
            $distance = (float)$distance;
187
        }
188
189
        $this->distance = $distance;
190
    }
191
192
    /**
193
     * Check if the point has a distance set from start to this point.
194
     *
195
     * @return boolean
196
     */
197
    public function hasDistance() : bool
198
    {
199
        return $this->distance !== null;
200
    }
201
202
    /**
203
     * Get the distance from start to this point.
204
     *
205
     * @return float
206
     */
207
    public function getDistance()
208
    {
209
        return $this->distance;
210
    }
211
212
    /**
213
     * Get the distance between this point and another point in meters.
214
     *
215
     * @param TrackPoint $trackPoint The other point.
216
     * @return float The distance in meters.
217
     */
218
    public function distance(TrackPoint $trackPoint)  : float
219
    {
220
        $earthRadius = 6371000;
221
222
        $latFrom = deg2rad($this->latitude());
223
        $lonFrom = deg2rad($this->longitude());
224
        $latTo = deg2rad($trackPoint->latitude());
225
        $lonTo = deg2rad($trackPoint->longitude());
226
227
        $latDelta = $latTo - $latFrom;
228
        $lonDelta = $lonTo - $lonFrom;
229
230
        $angle = 2 * asin(
231
                sqrt(
232
                    pow(sin($latDelta / 2), 2) +
233
                    cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)
234
                )
235
            );
236
237
        return $angle * $earthRadius;
238
    }
239
240
    /**
241
     * Get the speed between this point and another point in km/h.
242
     *
243
     * @param TrackPoint $trackPoint The other point.
244
     * @return float
245
     */
246
    public function speed(TrackPoint $trackPoint)  : float
247
    {
248
        $start = $this->dateTime();
249
        $end = $trackPoint->dateTime();
250
        $dateDiff = $start->diff($end);
251
        $secondsDifference = $dateDiff->days * 86400 + $dateDiff->h * 3600 + $dateDiff->i * 60 + $dateDiff->s;
252
253
        if ($secondsDifference === 0) {
254
            return 0.0;
255
        }
256
257
        if ($this->hasDistance() === true && $trackPoint->hasDistance()) {
258
            $distance = abs($this->getDistance() - $trackPoint->getDistance());
259
        } else {
260
            $distance = $this->distance($trackPoint);
261
        }
262
263
        return ($distance / $secondsDifference) * 3.6;
264
    }
265
}
266