全栈小学生 4b682cbf17 uupdate admin
2023-10-10 16:52:54 +08:00

90 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Location\Bearing;
use InvalidArgumentException;
use Location\Coordinate;
/**
* Calculation of bearing between two points using a
* simple spherical model of the earth.
*
* @author Marcus Jaschen <mjaschen@gmail.com>
*/
class BearingSpherical implements BearingInterface
{
/**
* Earth radius in meters.
*/
private const EARTH_RADIUS = 6371009.0;
/**
* This method calculates the initial bearing (forward azimut) between
* the two given points.
*
* @param Coordinate $point1
* @param Coordinate $point2
*
* @return float Bearing Angle in degrees
*/
public function calculateBearing(Coordinate $point1, Coordinate $point2): float
{
$lat1 = deg2rad($point1->getLat());
$lat2 = deg2rad($point2->getLat());
$lng1 = deg2rad($point1->getLng());
$lng2 = deg2rad($point2->getLng());
$y = sin($lng2 - $lng1) * cos($lat2);
$x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($lng2 - $lng1);
$bearing = rad2deg(atan2($y, $x));
if ($bearing < 0) {
$bearing = fmod($bearing + 360, 360);
}
return $bearing;
}
/**
* Calculates the final bearing between the two points.
*
* @param Coordinate $point1
* @param Coordinate $point2
*
* @return float
*/
public function calculateFinalBearing(Coordinate $point1, Coordinate $point2): float
{
$initialBearing = $this->calculateBearing($point2, $point1);
return fmod($initialBearing + 180, 360);
}
/**
* Calculates a destination point for the given point, bearing angle,
* and distance.
*
* @param Coordinate $point
* @param float $bearing the bearing angle between 0 and 360 degrees
* @param float $distance the distance to the destination point in meters
*
* @return Coordinate
* @throws InvalidArgumentException
*/
public function calculateDestination(Coordinate $point, float $bearing, float $distance): Coordinate
{
$D = $distance / self::EARTH_RADIUS;
$B = deg2rad($bearing);
= deg2rad($point->getLat());
= deg2rad($point->getLng());
= asin(sin() * cos($D) + cos() * sin($D) * cos($B));
= + atan2(sin($B) * sin($D) * cos(), cos($D) - sin() * sin());
return new Coordinate(rad2deg(), rad2deg());
}
}