Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
42.11% |
24 / 57 |
|
90.00% |
9 / 10 |
CRAP | |
0.00% |
0 / 1 |
Globe | |
42.11% |
24 / 57 |
|
90.00% |
9 / 10 |
65.68 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
2 | |||
getData | |
8.33% |
3 / 36 |
|
0.00% |
0 / 1 |
5.08 | |||
getName | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getRadius | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMinLongitude | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMaxLongitude | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getEastSign | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isKnown | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
equalsTo | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
coordinatesAreValid | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 |
1 | <?php |
2 | |
3 | namespace GeoData; |
4 | |
5 | /** |
6 | * Immutable representation of a celestial body |
7 | */ |
8 | class Globe { |
9 | |
10 | public const EARTH = 'earth'; |
11 | |
12 | private string $name; |
13 | |
14 | /** @var float|null */ |
15 | private $radius; |
16 | |
17 | /** @var float Defaults to -360 for unknown globes, or to 0 for known globes */ |
18 | private $minLon = -360; |
19 | |
20 | /** @var float Defaults to +360 for unknown globes */ |
21 | private $maxLon = 360; |
22 | |
23 | /** @var int Sign for values going to the East, either -1 or +1 */ |
24 | private $east = +1; |
25 | |
26 | private bool $known = false; |
27 | |
28 | /** |
29 | * @param string $name Internal globe name |
30 | */ |
31 | public function __construct( string $name = self::EARTH ) { |
32 | global $wgGlobes; |
33 | |
34 | $this->name = $name; |
35 | |
36 | $data = $wgGlobes[$name] ?? self::getData()[$name] ?? null; |
37 | if ( $data !== null ) { |
38 | $this->radius = $data['radius'] ?? null; |
39 | $this->minLon = $data['lon'][0] ?? 0; |
40 | $this->maxLon = $data['lon'][1] ?? $this->minLon + 360; |
41 | $this->east = $data['east'] ?? +1; |
42 | $this->known = true; |
43 | } |
44 | } |
45 | |
46 | /** |
47 | * @return array[] |
48 | */ |
49 | private static function getData(): array { |
50 | static $data = []; |
51 | if ( $data ) { |
52 | return $data; |
53 | } |
54 | |
55 | $earth = [ 'lon' => [ -180, 180 ], 'east' => +1 ]; |
56 | $east360 = [ 'lon' => [ 0, 360 ], 'east' => +1 ]; |
57 | $west360 = [ 'lon' => [ 0, 360 ], 'east' => -1 ]; |
58 | |
59 | /** |
60 | * Format: |
61 | * 'lon' => Array of minimum and maximum longitude, defaults to [ 0, 360 ] |
62 | * 'east' => If values going to the East are positive or negative, defaults to +1 |
63 | * 'radius' => mean radius in meters (optional) |
64 | * Coordinate systems mostly taken from http://planetarynames.wr.usgs.gov/TargetCoordinates |
65 | * Radii taken from Wikipedia. Globes that are too irregular in shape don't have radius set. |
66 | */ |
67 | $data = [ |
68 | self::EARTH => $earth + [ 'radius' => Math::EARTH_RADIUS ], |
69 | 'mercury' => $west360 + [ 'radius' => 2439700.0 ], |
70 | 'venus' => $east360 + [ 'radius' => 6051800.0 ], |
71 | 'moon' => $earth + [ 'radius' => 1737100.0 ], |
72 | // Assuming MDIM 2.1 |
73 | 'mars' => $east360 + [ 'radius' => 3389500.0 ], |
74 | 'phobos' => $west360, |
75 | 'deimos' => $west360, |
76 | // 'ceres' => ???, |
77 | // 'vesta' => ???, |
78 | 'ganymede' => $west360 + [ 'radius' => 2634100.0 ], |
79 | 'callisto' => $west360 + [ 'radius' => 2410300.0 ], |
80 | 'io' => $west360 + [ 'radius' => 1821600.0 ], |
81 | 'europa' => $west360 + [ 'radius' => 1560800.0 ], |
82 | 'mimas' => $west360 + [ 'radius' => 198200.0 ], |
83 | 'enceladus' => $west360 + [ 'radius' => 252100.0 ], |
84 | 'tethys' => $west360 + [ 'radius' => 531100.0 ], |
85 | 'dione' => $west360 + [ 'radius' => 561400.0 ], |
86 | 'rhea' => $west360 + [ 'radius' => 763800.0 ], |
87 | 'titan' => $west360 + [ 'radius' => 2575500.0 ], |
88 | 'hyperion' => $west360, |
89 | 'iapetus' => $west360 + [ 'radius' => 734500.0 ], |
90 | 'phoebe' => $west360, |
91 | 'miranda' => $east360 + [ 'radius' => 235800.0 ], |
92 | 'ariel' => $east360 + [ 'radius' => 578900.0 ], |
93 | 'umbriel' => $east360 + [ 'radius' => 584700.0 ], |
94 | 'titania' => $east360 + [ 'radius' => 788400.0 ], |
95 | 'oberon' => $east360 + [ 'radius' => 761400.0 ], |
96 | 'triton' => $east360 + [ 'radius' => 1353400.0 ], |
97 | // ??? |
98 | 'pluto' => $east360 + [ 'radius' => 1187000.0 ], |
99 | ]; |
100 | |
101 | return $data; |
102 | } |
103 | |
104 | /** |
105 | * Globe internal name |
106 | */ |
107 | public function getName(): string { |
108 | return $this->name; |
109 | } |
110 | |
111 | /** |
112 | * Returns globe radius or null if it's not known |
113 | * @return float|null |
114 | */ |
115 | public function getRadius() { |
116 | return $this->radius; |
117 | } |
118 | |
119 | /** |
120 | * Returns minimum longitude |
121 | * @return float |
122 | */ |
123 | public function getMinLongitude() { |
124 | return $this->minLon; |
125 | } |
126 | |
127 | /** |
128 | * Returns maximum longitude |
129 | * @return float |
130 | */ |
131 | public function getMaxLongitude() { |
132 | return $this->maxLon; |
133 | } |
134 | |
135 | /** |
136 | * Returns the sign of East |
137 | * @return int |
138 | */ |
139 | public function getEastSign() { |
140 | return $this->east; |
141 | } |
142 | |
143 | /** |
144 | * Returns whether this globe is registered (and hence, we know its properties) |
145 | */ |
146 | public function isKnown(): bool { |
147 | return $this->known; |
148 | } |
149 | |
150 | /** |
151 | * Compares this globe to another |
152 | */ |
153 | public function equalsTo( Globe $other ): bool { |
154 | return $this->name === $other->name; |
155 | } |
156 | |
157 | /** |
158 | * Checks whether given coordinates are valid |
159 | * @param int|float|string $lat |
160 | * @param int|float|string $lon |
161 | */ |
162 | public function coordinatesAreValid( $lat, $lon ): bool { |
163 | if ( !is_numeric( $lat ) || !is_numeric( $lon ) ) { |
164 | return false; |
165 | } |
166 | $lat = (float)$lat; |
167 | $lon = (float)$lon; |
168 | |
169 | return $lon >= $this->minLon && $lon <= $this->maxLon |
170 | && abs( $lat ) <= 90; |
171 | } |
172 | } |