GeoFunctions   A
last analyzed

Complexity

Total Complexity 2

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 2
lcom 0
cbo 1
dl 0
loc 85
ccs 34
cts 34
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A calculateDistance() 0 31 1
A findDestination() 0 24 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace Maps;
6
7
use DataValues\Geo\Values\LatLongValue;
8
9
/**
10
 * Static class containing geographical functions.
11
 *
12
 * @licence GNU GPL v2+
13
 * @author Jeroen De Dauw < [email protected] >
14
 * @author Pnelnik
15
 * @author Matěj Grabovský
16
 */
17
final class GeoFunctions {
18
19
	// The approximate radius of the earth in meters, according to http://en.wikipedia.org/wiki/Earth_radius.
20
	private const EARTH_RADIUS = 6371000;
21
22
	/**
23
	 * Returns the geographical distance between two coordinates.
24
	 * See http://en.wikipedia.org/wiki/Geographical_distance
25
	 *
26
	 * @since 2.0
27
	 *
28
	 * @param LatLongValue $start
29
	 * @param LatLongValue $end
30
	 *
31
	 * @return float Distance in m.
32
	 */
33 2
	public static function calculateDistance( LatLongValue $start, LatLongValue $end ) {
34 2
		$northRad1 = deg2rad( $start->getLatitude() );
35 2
		$eastRad1 = deg2rad( $start->getLongitude() );
36
37 2
		$cosNorth1 = cos( $northRad1 );
38 2
		$cosEast1 = cos( $eastRad1 );
39
40 2
		$sinNorth1 = sin( $northRad1 );
41 2
		$sinEast1 = sin( $eastRad1 );
42
43 2
		$northRad2 = deg2rad( $end->getLatitude() );
44 2
		$eastRad2 = deg2rad( $end->getLongitude() );
45
46 2
		$cosNorth2 = cos( $northRad2 );
47 2
		$cosEast2 = cos( $eastRad2 );
48
49 2
		$sinNorth2 = sin( $northRad2 );
50 2
		$sinEast2 = sin( $eastRad2 );
51
52 2
		$term1 = $cosNorth1 * $sinEast1 - $cosNorth2 * $sinEast2;
53 2
		$term2 = $cosNorth1 * $cosEast1 - $cosNorth2 * $cosEast2;
54 2
		$term3 = $sinNorth1 - $sinNorth2;
55
56 2
		$distThruSquared = $term1 * $term1 + $term2 * $term2 + $term3 * $term3;
57
58 2
		$distance = 2 * self::EARTH_RADIUS * asin( sqrt( $distThruSquared ) / 2 );
59
60 2
		assert( $distance >= 0 );
61
62 2
		return $distance;
63
	}
64
65
	/**
66
	 * Finds a destination given a starting location, bearing and distance.
67
	 *
68
	 * @since 2.0
69
	 *
70
	 * @param LatLongValue $startingCoordinates
71
	 * @param float $bearing The initial bearing in degrees.
72
	 * @param float $distance The distance to travel in km.
73
	 *
74
	 * @return array The destination coordinates, as non-directional floats in an array with lat and lon keys.
75
	 */
76 1
	public static function findDestination( LatLongValue $startingCoordinates, $bearing, $distance ) {
77
		$startingCoordinates = [
78 1
			'lat' => deg2rad( $startingCoordinates->getLatitude() ),
79 1
			'lon' => deg2rad( $startingCoordinates->getLongitude() ),
80
		];
81
82 1
		$radBearing = deg2rad( (float)$bearing );
83 1
		$angularDistance = $distance / self::EARTH_RADIUS;
84
85 1
		$lat = asin(
86 1
			sin( $startingCoordinates['lat'] ) * cos( $angularDistance ) + cos( $startingCoordinates['lat'] ) * sin(
87 1
				$angularDistance
88 1
			) * cos( $radBearing )
89
		);
90 1
		$lon = $startingCoordinates['lon'] + atan2(
91 1
				sin( $radBearing ) * sin( $angularDistance ) * cos( $startingCoordinates['lat'] ),
92 1
				cos( $angularDistance ) - sin( $startingCoordinates['lat'] ) * sin( $lat )
93
			);
94
95
		return [
96 1
			'lat' => rad2deg( $lat ),
97 1
			'lon' => rad2deg( $lon )
98
		];
99
	}
100
101
}
102