Total Complexity | 50 |
Total Lines | 432 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 1 | Features | 0 |
Complex classes like Geodesic often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Geodesic, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class Geodesic |
||
41 | { |
||
42 | private float $a; |
||
43 | private float $b; |
||
44 | private float $f; |
||
45 | private float $f1; |
||
46 | private float $e2; |
||
47 | private float $ep2; |
||
48 | private float $n; |
||
49 | |||
50 | /** |
||
51 | * @var float[] |
||
52 | */ |
||
53 | private array $a3Coefficients; |
||
54 | |||
55 | /** |
||
56 | * @var float[] |
||
57 | */ |
||
58 | private array $c3Coefficients; |
||
59 | |||
60 | public function __construct(Ellipsoid $ellipsoid) |
||
61 | { |
||
62 | $this->a = $ellipsoid->getSemiMajorAxis()->asMetres()->getValue(); |
||
63 | $this->b = $ellipsoid->getSemiMinorAxis()->asMetres()->getValue(); |
||
64 | $this->f = $ellipsoid->getFlattening(); |
||
65 | $this->f1 = 1 - $this->f; |
||
66 | $this->e2 = $ellipsoid->getEccentricitySquared(); |
||
67 | $this->ep2 = $this->e2 / $this->f1 ** 2; |
||
68 | $this->n = $this->f / (2 - $this->f); |
||
69 | $this->a3Coefficients = $this->a3Coefficients(); |
||
70 | $this->c3Coefficients = $this->c3Coefficients(); |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * @return float[] |
||
75 | */ |
||
76 | private function a3Coefficients(): array |
||
77 | { |
||
78 | $A3x = []; |
||
79 | $coeff = [ |
||
80 | -3, 128, |
||
81 | -2, -3, 64, |
||
82 | -1, -3, -1, 16, |
||
83 | 3, -1, -2, 8, |
||
84 | 1, -1, 2, |
||
85 | 1, 1, |
||
86 | ]; |
||
87 | $o = 0; |
||
88 | $k = 0; |
||
89 | foreach (range(5, 0, -1) as $j) { |
||
90 | $m = min(5 - $j, $j); |
||
91 | $A3x[$k] = polyVal($m, $coeff, $o, $this->n) / $coeff[$o + $m + 1]; |
||
92 | ++$k; |
||
93 | $o += $m + 2; |
||
94 | } |
||
95 | |||
96 | return $A3x; |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * @return float[] |
||
101 | */ |
||
102 | private function c3Coefficients(): array |
||
103 | { |
||
104 | $C3x = []; |
||
105 | |||
106 | $coeff = [ |
||
107 | 3, 128, |
||
108 | 2, 5, 128, |
||
109 | -1, 3, 3, 64, |
||
110 | -1, 0, 1, 8, |
||
111 | -1, 1, 4, |
||
112 | 5, 256, |
||
113 | 1, 3, 128, |
||
114 | -3, -2, 3, 64, |
||
115 | 1, -3, 2, 32, |
||
116 | 7, 512, |
||
117 | -10, 9, 384, |
||
118 | 5, -9, 5, 192, |
||
119 | 7, 512, |
||
120 | -14, 7, 512, |
||
121 | 21, 2560, |
||
122 | ]; |
||
123 | $o = 0; |
||
124 | $k = 0; |
||
125 | foreach (range(1, 5) as $l) { |
||
126 | foreach (range(5, $l, -1) as $j) { |
||
127 | $m = min(5 - $j, $j); |
||
128 | $C3x[$k] = polyVal($m, $coeff, $o, $this->n) / $coeff[$o + $m + 1]; // @phpstan-ignore binaryOp.invalid |
||
129 | ++$k; |
||
130 | $o += $m + 2; |
||
131 | } |
||
132 | } |
||
133 | |||
134 | return $C3x; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @return float[] |
||
139 | */ |
||
140 | private function c3(float $eps): array |
||
141 | { |
||
142 | $c = []; |
||
143 | $mult = 1; |
||
144 | $o = 0; |
||
145 | foreach (range(1, 5) as $l) { |
||
146 | $m = 5 - $l; |
||
147 | $mult *= $eps; |
||
148 | $c[$l] = $mult * polyVal($m, $this->c3Coefficients, $o, $eps); |
||
149 | $o += $m + 1; |
||
150 | } |
||
151 | |||
152 | return $c; |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * @return float[] |
||
157 | */ |
||
158 | private function lengths( |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * @return float[] |
||
186 | */ |
||
187 | private function inverseStart( |
||
188 | float $sbet1, |
||
189 | float $cbet1, |
||
190 | float $sbet2, |
||
191 | float $cbet2, |
||
192 | float $lam12, |
||
193 | float $slam12, |
||
194 | float $clam12, |
||
195 | ): array { |
||
196 | $sig12 = -1; |
||
197 | $dnm = 1; |
||
198 | $sbet12 = $sbet2 * $cbet1 - $cbet2 * $sbet1; |
||
199 | $cbet12 = $cbet2 * $cbet1 + $sbet2 * $sbet1; |
||
200 | $sbet12a = $sbet2 * $cbet1; |
||
201 | $sbet12a += $cbet2 * $sbet1; |
||
202 | |||
203 | $shortline = ($cbet12 >= 0 && $sbet12 < 0.5 && $cbet2 * $lam12 < 0.5); |
||
204 | if ($shortline) { |
||
205 | $sbetm2 = ($sbet1 + $sbet2) ** 2; |
||
206 | $sbetm2 /= $sbetm2 + ($cbet1 + $cbet2) ** 2; |
||
207 | $dnm = sqrt(1 + $this->ep2 * $sbetm2); |
||
208 | $omg12 = $lam12 / ($this->f1 * $dnm); |
||
209 | $somg12 = sin($omg12); |
||
210 | $comg12 = cos($omg12); |
||
211 | } else { |
||
212 | $somg12 = $slam12; |
||
213 | $comg12 = $clam12; |
||
214 | } |
||
215 | $salp1 = $cbet2 * $somg12; |
||
216 | $calp1 = $comg12 >= 0 ? |
||
217 | $sbet12 + $cbet2 * $sbet1 * $somg12 ** 2 / (1 + $comg12) : $sbet12a - $cbet2 * $sbet1 * $somg12 ** 2 / (1 - $comg12); |
||
218 | |||
219 | $ssig12 = hypot($salp1, $calp1); |
||
220 | $csig12 = $sbet1 * $sbet2 + $cbet1 * $cbet2 * $comg12; |
||
221 | |||
222 | if ($shortline && $ssig12 < PHP_FLOAT_EPSILON) { |
||
223 | $sig12 = atan2($ssig12, $csig12); |
||
224 | } elseif (!(abs($this->n) >= 0.1 || $csig12 >= 0 || $ssig12 >= 6 * abs($this->n) * M_PI * $cbet1 ** 2)) { |
||
225 | $lam12x = atan2(-$slam12, -$clam12); |
||
226 | $k2 = $sbet1 ** 2 * $this->ep2; |
||
227 | $eps = $k2 / (2 * (1 + sqrt(1 + $k2)) + $k2); |
||
228 | $lamscale = $this->f * $cbet1 * polyVal(5, $this->a3Coefficients, 0, $eps) * M_PI; |
||
229 | $betscale = $lamscale * $cbet1; |
||
230 | $x = $lam12x / $lamscale; |
||
231 | $y = $sbet12a / $betscale; |
||
232 | |||
233 | if ($y > -PHP_FLOAT_EPSILON && $x > -1 - PHP_FLOAT_EPSILON) { |
||
234 | $salp1 = min(1.0, -$x); |
||
235 | $calp1 = -sqrt(1 - $salp1 ** 2); |
||
236 | } else { |
||
237 | $k = astroid($x, $y); |
||
238 | $omg12a = $lamscale * ($this->f >= 0 ? -$x * $k / (1 + $k) : -$y * (1 + $k) / $k); |
||
239 | $somg12 = sin($omg12a); |
||
240 | $comg12 = -cos($omg12a); |
||
241 | $salp1 = $cbet2 * $somg12; |
||
242 | $calp1 = $sbet12a - $cbet2 * $sbet1 * $somg12 ** 2 / (1 - $comg12); |
||
243 | } |
||
244 | } |
||
245 | if (!($salp1 <= 0)) { |
||
246 | [$salp1, $calp1] = normalise($salp1, $calp1); |
||
247 | } else { |
||
248 | $salp1 = 1; |
||
249 | $calp1 = 0; |
||
250 | } |
||
251 | |||
252 | return [$sig12, $salp1, $calp1, $dnm]; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @return float[] |
||
257 | */ |
||
258 | private function lambda( |
||
259 | float $sbet1, |
||
260 | float $cbet1, |
||
261 | float $dn1, |
||
262 | float $sbet2, |
||
263 | float $cbet2, |
||
264 | float $dn2, |
||
265 | float $salp1, |
||
266 | float $calp1, |
||
267 | float $slam120, |
||
268 | float $clam120, |
||
269 | ): array { |
||
270 | if ($sbet1 == 0 && $calp1 == 0) { |
||
271 | $calp1 = -PHP_FLOAT_MIN; |
||
272 | } |
||
273 | |||
274 | $salp0 = $salp1 * $cbet1; |
||
275 | $calp0 = hypot($calp1, $salp1 * $sbet1); |
||
276 | |||
277 | $ssig1 = $sbet1; |
||
278 | $somg1 = $salp0 * $sbet1; |
||
279 | $csig1 = $comg1 = $calp1 * $cbet1; |
||
280 | [$ssig1, $csig1] = normalise($ssig1, $csig1); |
||
281 | |||
282 | $calp2 = $cbet2 !== $cbet1 || abs($sbet2) !== -$sbet1 ? |
||
283 | sqrt(($calp1 * $cbet1) ** 2 + ($cbet1 < -$sbet1 ? |
||
284 | ($cbet2 - $cbet1) * ($cbet1 + $cbet2) : |
||
285 | ($sbet1 - $sbet2) * ($sbet1 + $sbet2))) / |
||
286 | $cbet2 : abs($calp1); |
||
287 | |||
288 | $ssig2 = $sbet2; |
||
289 | $somg2 = $salp0 * $sbet2; |
||
290 | $csig2 = $comg2 = $calp2 * $cbet2; |
||
291 | [$ssig2, $csig2] = normalise($ssig2, $csig2); |
||
292 | |||
293 | $sig12 = atan2( |
||
294 | max(0.0, $csig1 * $ssig2 - $ssig1 * $csig2), |
||
295 | $csig1 * $csig2 + $ssig1 * $ssig2 |
||
296 | ); |
||
297 | |||
298 | $somg12 = max(0.0, $comg1 * $somg2 - $somg1 * $comg2); |
||
299 | $comg12 = $comg1 * $comg2 + $somg1 * $somg2; |
||
300 | $eta = atan2( |
||
301 | $somg12 * $clam120 - $comg12 * $slam120, |
||
302 | $comg12 * $clam120 + $somg12 * $slam120 |
||
303 | ); |
||
304 | |||
305 | $k2 = $calp0 ** 2 * $this->ep2; |
||
306 | $eps = $k2 / (2 * (1 + sqrt(1 + $k2)) + $k2); |
||
307 | $C3a = $this->c3($eps); |
||
308 | $B312 = (sinCosSeries($ssig2, $csig2, $C3a) - sinCosSeries($ssig1, $csig1, $C3a)); |
||
309 | $domg12 = -$this->f * polyVal(5, $this->a3Coefficients, 0, $eps) * $salp0 * ($sig12 + $B312); |
||
310 | $lam12 = $eta + $domg12; |
||
311 | |||
312 | if ($calp2 == 0) { |
||
313 | $dlam12 = -2 * $this->f1 * $dn1 / $sbet1; |
||
314 | } else { |
||
315 | [, $dlam12] = $this->lengths( |
||
316 | $eps, |
||
317 | $sig12, |
||
318 | $ssig1, |
||
319 | $csig1, |
||
320 | $dn1, |
||
321 | $ssig2, |
||
322 | $csig2, |
||
323 | $dn2, |
||
324 | ); |
||
325 | $dlam12 *= $this->f1 / ($calp2 * $cbet2); |
||
326 | } |
||
327 | |||
328 | return [$lam12, $sig12, $ssig1, $csig1, $ssig2, $csig2, $eps, $dlam12]; |
||
329 | } |
||
330 | |||
331 | public function distance(GeographicValue $from, GeographicValue $to): Length |
||
472 | } |
||
473 | } |
||
474 | |||
475 | function copySign(float $x, float $y): float |
||
476 | { |
||
477 | if ($y >= 0) { |
||
478 | return abs($x); |
||
673 |