質問

私は 2 点間の大圏距離を計算する公式に精通しています。

つまり

<?php
$theta = $lon1 - $lon2; 
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
$dist = acos($dist); 
$dist = rad2deg($dist); 
//convert degrees to distance depending on units desired
?>

ただし、必要なのはこれの逆です。開始点、距離、単純な基本的な NSEW 方向が与えられると、目的点の位置が計算されます。久しぶりに数学の授業を受けました。;)

役に立ちましたか?

解決

ここで私が見つけC実装は、PHPに変換するためにかなり簡単である必要があります。

#define KmPerDegree         111.12000071117
#define DegreesPerKm        (1.0/KmPerDegree)
#define PI                  M_PI
#define TwoPI               (M_PI+M_PI)
#define HalfPI              M_PI_2
#define RadiansPerDegree    (PI/180.0)
#define DegreesPerRadian    (180.0/PI)
#define copysign(x,y)       (((y)<0.0)?-fabs(x):fabs(x))
#define NGT1(x)             (fabs(x)>1.0?copysign(1.0,x):(x))
#define ArcCos(x)           (fabs(x)>1?quiet_nan():acos(x))
#define hav(x)              ((1.0-cos(x))*0.5)              /* haversine */
#define ahav(x)             (ArcCos(NGT1(1.0-((x)*2.0))))   /* arc haversine */
#define sec(x)              (1.0/cos(x))                    /* secant */
#define csc(x)              (1.0/sin(x))                    /* cosecant */

/*
**  GreatCirclePos() --
**
**  Compute ending position from course and great-circle distance.
**
**  Given a starting latitude (decimal), the initial great-circle
**  course and a distance along the course track, compute the ending
**  position (decimal latitude and longitude).
**  This is the inverse function to GreatCircleDist).
*/
void
GreatCirclePos(dist, course, slt, slg, xlt, xlg)
    double  dist;   /* -> great-circle distance (km) */
    double  course; /* -> initial great-circle course (degrees) */
    double  slt;    /* -> starting decimal latitude (-S) */
    double  slg;    /* -> starting decimal longitude(-W) */
    double  *xlt;   /* <- ending decimal latitude (-S) */
    double  *xlg;   /* <- ending decimal longitude(-W) */
{
    double  c, d, dLo, L1, L2, coL1, coL2, l;

    if (dist > KmPerDegree*180.0) {
        course -= 180.0;
        if (course < 0.0) course += 360.0;
        dist    = KmPerDegree*360.0-dist;
    }
    if (course > 180.0) course -= 360.0;
    c    = course*RadiansPerDegree;
    d    = dist*DegreesPerKm*RadiansPerDegree;
    L1   = slt*RadiansPerDegree;
    slg *= RadiansPerDegree;
    coL1 = (90.0-slt)*RadiansPerDegree;
    coL2 = ahav(hav(c)/(sec(L1)*csc(d))+hav(d-coL1));
    L2   = HalfPI-coL2;
    l    = L2-L1;
    if ((dLo=(cos(L1)*cos(L2))) != 0.0)
        dLo  = ahav((hav(d)-hav(l))/dLo);
    if (c < 0.0) dLo = -dLo;
    slg += dLo;
    if (slg < -PI)
        slg += TwoPI;
    else if (slg > PI)
        slg -= TwoPI;

    *xlt = L2*DegreesPerRadian;
    *xlg = slg*DegreesPerRadian;

} /* GreatCirclePos() */
  

ソース: http://sam.ucsd.edu/sio210/propseawater/ ppsw_c / gcdist.cする

他のヒント

これは誰のためにここに好奇心ちょうどので、自分の質問に答えるために、チャドバーチが提供するC関数から変換してPHPクラスます:

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));
    }

}

これは、私が思うだろう、そしてあなた自身を生成し、半正矢のフォーミュラをバックアウトするのは難しいだろう。

第1の角度は(あなたはそれがまっすぐだと思うが、それは湾曲さ)表面に「直線」を旅行することにより、地球のコアから生成されます。

ラジアン=弧の長さ/半径の角度。 角度= ArcLen / 6371キロ

緯度は、あなたの角度の単なる「垂直」(北/南)コンポーネント簡単にする必要があります。

LAT1 +コス(ベアリング)*アングル

経度部門は緯度によって異なります。だから硬くなります。あなたが使用することになります:

SIN(ベアリング)*角(イーストと負として定義される)経度方向の角度を見つけるが、その緯度に戻って実際の経度に変換することはより困難になるであろう。

セクションを参照してください 始点からの距離と方位を指定した終点 このウェブサイト: http://www.movable-type.co.uk/scripts/latlong.html

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top