To answer my own question just so it's here for anyone curious, a PHP class as converted from the C function provided by Chad Birch:
class GreatCircle
{
/*
* Find a point a certain distance and vector away from an initial point
* converted from c function found at: http://sam.ucsd.edu/sio210/propseawater/ppsw_c/gcdist.c
*
* @param int distance in meters
* @param double direction in degrees i.e. 0 = North, 90 = East, etc.
* @param double lon starting longitude
* @param double lat starting latitude
* @return array ('lon' => $lon, 'lat' => $lat)
*/
public static function getPositionByDistance($distance, $direction, $lon, $lat)
{
$metersPerDegree = 111120.00071117;
$degreesPerMeter = 1.0 / $metersPerDegree;
$radiansPerDegree = pi() / 180.0;
$degreesPerRadian = 180.0 / pi();
if ($distance > $metersPerDegree*180)
{
$direction -= 180.0;
if ($direction < 0.0)
{
$direction += 360.0;
}
$distance = $metersPerDegree * 360.0 - $distance;
}
if ($direction > 180.0)
{
$direction -= 360.0;
}
$c = $direction * $radiansPerDegree;
$d = $distance * $degreesPerMeter * $radiansPerDegree;
$L1 = $lat * $radiansPerDegree;
$lon *= $radiansPerDegree;
$coL1 = (90.0 - $lat) * $radiansPerDegree;
$coL2 = self::ahav(self::hav($c) / (self::sec($L1) * self::csc($d)) + self::hav($d - $coL1));
$L2 = (pi() / 2) - $coL2;
$l = $L2 - $L1;
$dLo = (cos($L1) * cos($L2));
if ($dLo != 0.0)
{
$dLo = self::ahav((self::hav($d) - self::hav($l)) / $dLo);
}
if ($c < 0.0)
{
$dLo = -$dLo;
}
$lon += $dLo;
if ($lon < -pi())
{
$lon += 2 * pi();
}
elseif ($lon > pi())
{
$lon -= 2 * pi();
}
$xlat = $L2 * $degreesPerRadian;
$xlon = $lon * $degreesPerRadian;
return array('lon' => $xlon, 'lat' => $xlat);
}
/*
* copy the sign
*/
private static function copysign($x, $y)
{
return ((($y) < 0.0) ? - abs($x) : abs($x));
}
/*
* not greater than 1
*/
private static function ngt1($x)
{
return (abs($x) > 1.0 ? self::copysign(1.0 , $x) : ($x));
}
/*
* haversine
*/
private static function hav($x)
{
return ((1.0 - cos($x)) * 0.5);
}
/*
* arc haversine
*/
private static function ahav($x)
{
return acos(self::ngt1(1.0 - ($x * 2.0)));
}
/*
* secant
*/
private static function sec($x)
{
return (1.0 / cos($x));
}
/*
* cosecant
*/
private static function csc($x)
{
return (1.0 / sin($x));
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…