private function inverseVincenty(Coordinate $point1, Coordinate $point2)
{
$φ1 = deg2rad($point1->getLat());
$φ2 = deg2rad($point2->getLat());
$λ1 = deg2rad($point1->getLng());
$λ2 = deg2rad($point2->getLng());
$a = $point1->getEllipsoid()->getA();
$b = $point1->getEllipsoid()->getB();
$f = 1 / $point1->getEllipsoid()->getF();
$L = $λ2 - $λ1;
$tanU1 = (1 - $f) * tan($φ1);
$cosU1 = 1 / sqrt(1 + $tanU1 * $tanU1);
$sinU1 = $tanU1 * $cosU1;
$tanU2 = (1 - $f) * tan($φ2);
$cosU2 = 1 / sqrt(1 + $tanU2 * $tanU2);
$sinU2 = $tanU2 * $cosU2;
$λ = $L;
$iterations = 0;
do {
$sinλ = sin($λ);
$cosλ = cos($λ);
$sinSqσ = $cosU2 * $sinλ * ($cosU2 * $sinλ) + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ);
$sinσ = sqrt($sinSqσ);
if ($sinσ == 0) {
return 0;
}
$cosσ = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosλ;
$σ = atan2($sinσ, $cosσ);
$sinα = $cosU1 * $cosU2 * $sinλ / $sinσ;
$cosSqα = 1 - $sinα * $sinα;
$cos2σM = 0;
if ($cosSqα !== 0.0) {
$cos2σM = $cosσ - 2 * $sinU1 * $sinU2 / $cosSqα;
}
$C = $f / 16 * $cosSqα * (4 + $f * (4 - 3 * $cosSqα));
$λp = $λ;
$λ = $L + (1 - $C) * $f * $sinα * ($σ + $C * $sinσ * ($cos2σM + $C * $cosσ * (-1 + 2 * $cos2σM * $cos2σM)));
} while (abs($λ - $λp) > 1.0E-12 && ++$iterations < 200);
if ($iterations >= 200) {
throw new NotConvergingException('Inverse Vincenty Formula did not converge');
}
$uSq = $cosSqα * ($a * $a - $b * $b) / ($b * $b);
$A = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq)));
$B = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq)));
$Δσ = $B * $sinσ * ($cos2σM + $B / 4 * ($cosσ * (-1 + 2 * $cos2σM * $cos2σM) - $B / 6 * $cos2σM * (-3 + 4 * $sinσ * $sinσ) * (-3 + 4 * $cos2σM * $cos2σM)));
$s = $b * $A * ($σ - $Δσ);
$α1 = atan2($cosU2 * $sinλ, $cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ);
$α2 = atan2($cosU1 * $sinλ, -$sinU1 * $cosU2 + $cosU1 * $sinU2 * $cosλ);
$α1 = fmod($α1 + 2 * M_PI, 2 * M_PI);
$α2 = fmod($α2 + 2 * M_PI, 2 * M_PI);
$s = round($s, 3);
return ['distance' => $s, 'bearing_initial' => rad2deg($α1), 'bearing_final' => rad2deg($α2)];
}