Check if coordinates have the same ellipsoid.
public static checkCoordinatesEllipsoid ( League\Geotools\Coordinate\CoordinateInterface $a, League\Geotools\Coordinate\CoordinateInterface $b ) | ||
$a | League\Geotools\Coordinate\CoordinateInterface | A coordinate. |
$b | League\Geotools\Coordinate\CoordinateInterface | A coordinate. |
/** * Returns the half-way point / coordinate along a great circle * path between the origin and the destination coordinates. * * @return CoordinateInterface */ public function middle() { Ellipsoid::checkCoordinatesEllipsoid($this->from, $this->to); $latA = deg2rad($this->from->getLatitude()); $lngA = deg2rad($this->from->getLongitude()); $latB = deg2rad($this->to->getLatitude()); $lngB = deg2rad($this->to->getLongitude()); $bx = cos($latB) * cos($lngB - $lngA); $by = cos($latB) * sin($lngB - $lngA); $lat3 = rad2deg(atan2(sin($latA) + sin($latB), sqrt((cos($latA) + $bx) * (cos($latA) + $bx) + $by * $by))); $lng3 = rad2deg($lngA + atan2($by, cos($latA) + $bx)); return new Coordinate(array($lat3, $lng3), $this->from->getEllipsoid()); }
/** * Returns geodetic distance between between two coordinates using Vincenty inverse * formula for ellipsoids which is accurate to within 0.5mm. * @see http://www.movable-type.co.uk/scripts/latlong-vincenty.html * * @return double The distance in meters */ public function vincenty() { Ellipsoid::checkCoordinatesEllipsoid($this->from, $this->to); $a = $this->from->getEllipsoid()->getA(); $b = $this->from->getEllipsoid()->getB(); $f = 1 / $this->from->getEllipsoid()->getInvF(); $lL = deg2rad($this->to->getLongitude() - $this->from->getLongitude()); $u1 = atan((1 - $f) * tan(deg2rad($this->from->getLatitude()))); $u2 = atan((1 - $f) * tan(deg2rad($this->to->getLatitude()))); $sinU1 = sin($u1); $cosU1 = cos($u1); $sinU2 = sin($u2); $cosU2 = cos($u2); $lambda = $lL; $iterLimit = 100; do { $sinLambda = sin($lambda); $cosLambda = cos($lambda); $sinSigma = sqrt($cosU2 * $sinLambda * ($cosU2 * $sinLambda) + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda)); if (0.0 === $sinSigma) { return 0.0; // co-incident points } $cosSigma = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosLambda; $sigma = atan2($sinSigma, $cosSigma); $sinAlpha = $cosU1 * $cosU2 * $sinLambda / $sinSigma; $cosSqAlpha = 1 - $sinAlpha * $sinAlpha; if ($cosSqAlpha != 0.0) { $cos2SigmaM = $cosSigma - 2 * $sinU1 * $sinU2 / $cosSqAlpha; } else { $cos2SigmaM = 0.0; } $cC = $f / 16 * $cosSqAlpha * (4 + $f * (4 - 3 * $cosSqAlpha)); $lambdaP = $lambda; $lambda = $lL + (1 - $cC) * $f * $sinAlpha * ($sigma + $cC * $sinSigma * ($cos2SigmaM + $cC * $cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM))); } while (abs($lambda - $lambdaP) > 1.0E-12 && --$iterLimit > 0); // @codeCoverageIgnoreStart if (0 === $iterLimit) { throw new NotConvergingException('Vincenty formula failed to converge !'); } // @codeCoverageIgnoreEnd $uSq = $cosSqAlpha * ($a * $a - $b * $b) / ($b * $b); $aA = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq))); $bB = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq))); $deltaSigma = $bB * $sinSigma * ($cos2SigmaM + $bB / 4 * ($cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM) - $bB / 6 * $cos2SigmaM * (-3 + 4 * $sinSigma * $sinSigma) * (-3 + 4 * $cos2SigmaM * $cos2SigmaM))); $s = $b * $aA * ($sigma - $deltaSigma); return $this->convertToUserUnit($s); }