Passed
Push — master ( afd872...5de271 )
by Marius
58s queued 12s
created

GlobeMath   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 2
dl 0
loc 102
ccs 38
cts 38
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeGlobe() 0 7 3
A normalizeGlobeCoordinate() 0 7 1
A normalizeGlobeLatLong() 0 12 3
B normalizeLatLong() 0 27 8
A getNormalizedLongitude() 0 10 3
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace DataValues\Geo;
6
7
use DataValues\Geo\Values\GlobeCoordinateValue;
8
use DataValues\Geo\Values\LatLongValue;
9
10
/**
11
 * Logical and mathematical helper functions for normalizations and calculations with
12
 * GlobeCoordinateValue objects.
13
 *
14
 * @since 0.2
15
 *
16
 * @license GPL-2.0-or-later
17
 * @author Thiemo Kreuz
18
 */
19
class GlobeMath {
20
21
	/**
22
	 * @todo Move this constant next to GlobeCoordinateValue::GLOBE_EARTH?
23
	 */
24
	public const GLOBE_MOON = 'http://www.wikidata.org/entity/Q405';
25
26
	/**
27
	 * @param string|null $globe IRI of a globe.
28
	 *
29
	 * @return string Normalized IRI, defaults to 'http://www.wikidata.org/entity/Q2'.
30
	 */
31 93
	public function normalizeGlobe( ?string $globe ) {
32 93
		if ( !is_string( $globe ) || $globe === '' ) {
33 45
			return GlobeCoordinateValue::GLOBE_EARTH;
34
		}
35
36 48
		return $globe;
37
	}
38
39
	/**
40
	 * Normalizes latitude to [-90°..+90°]. Normalizes longitude to [-180°..+180°[ on Earth and
41
	 * Moon and to [0°..+360°[ on all other globes.
42
	 * @see http://planetarynames.wr.usgs.gov/TargetCoordinates
43
	 *
44
	 * @param GlobeCoordinateValue $value
45
	 *
46
	 * @return GlobeCoordinateValue
47
	 */
48 45
	public function normalizeGlobeCoordinate( GlobeCoordinateValue $value ): GlobeCoordinateValue {
49 45
		return new GlobeCoordinateValue(
50 45
			$this->normalizeGlobeLatLong( $value->getLatLong(), $value->getGlobe() ),
51 45
			$value->getPrecision(),
52 45
			$value->getGlobe()
53
		);
54
	}
55
56
	/**
57
	 * @param LatLongValue $value
58
	 * @param string|null $globe
59
	 *
60
	 * @return LatLongValue
61
	 */
62 90
	public function normalizeGlobeLatLong( LatLongValue $value, string $globe = null ): LatLongValue {
63 90
		switch ( $this->normalizeGlobe( $globe ) ) {
64
			case GlobeCoordinateValue::GLOBE_EARTH:
65 4
			case self::GLOBE_MOON:
66 86
				$minimumLongitude = -180;
67 86
				break;
68
			default:
69 4
				$minimumLongitude = 0;
70
		}
71
72 90
		return $this->normalizeLatLong( $value, $minimumLongitude );
73
	}
74
75
	/**
76
	 * @param LatLongValue $value
77
	 * @param float $minimumLongitude
78
	 *
79
	 * @return LatLongValue
80
	 */
81 135
	public function normalizeLatLong( LatLongValue $value, float $minimumLongitude = -180.0 ): LatLongValue {
82 135
		$lon = $this->getNormalizedLongitude( $value->getLongitude(), $minimumLongitude );
83 135
		$lat = $value->getLatitude();
84
85 135
		if ( $lat >= 270 ) {
86
			// Same side of the globe, on the southern hemisphere.
87 12
			$lat -= 360;
88 123
		} elseif ( $lat <= -270 ) {
89
			// Same side of the globe, on the northern hemisphere.
90 15
			$lat += 360;
91 108
		} elseif ( $lat > 90 ) {
92
			// Other side of the globe
93 33
			$lat = 180 - $lat;
94 33
			$lon += $lon - 180 >= $minimumLongitude ? -180 : 180;
95 75
		} elseif ( $lat < -90 ) {
96
			// Other side of the globe
97 18
			$lat = -180 - $lat;
98 18
			$lon += $lon - 180 >= $minimumLongitude ? -180 : 180;
99
		}
100
101
		// North/south pole
102 135
		if ( abs( $lat ) === 90.0 ) {
103 21
			$lon = 0;
104
		}
105
106 135
		return new LatLongValue( $lat, $lon );
107
	}
108
109 135
	private function getNormalizedLongitude( float $longitude, float $minimumLongitude ): float {
110
		// Normalize to [-180°..+180°[ on Earth/Moon, [0°..+360°[ on other globes.
111 135
		if ( $longitude >= $minimumLongitude + 360 ) {
112 42
			$longitude -= 360;
113 93
		} elseif ( $longitude < $minimumLongitude ) {
114 18
			$longitude += 360;
115
		}
116
117 135
		return $longitude;
118
	}
119
120
}
121