Domanda

mi è familiare con la formula per calcolare la distanza ortodromica tra due punti.

cioè.

<?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
?>

Che cosa ho bisogno, però, è il contrario di questo. Dato un punto di partenza, la distanza, e un semplice cardinale direzione NSEO, per calcolare la posizione del punto di destinazione. E 'passato molto tempo da quando ero in una classe di matematica. ;)

È stato utile?

Soluzione

Ecco un'implementazione C che ho trovato, dovrebbe essere abbastanza semplice da tradurre in 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() */
  

Fonte: http://sam.ucsd.edu/sio210/propseawater/ ppsw_c / gcdist.c

Altri suggerimenti

Per rispondere alla mia domanda proprio così è qui per chiunque sia curioso, una classe PHP come convertito dalla funzione C fornita da 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));
    }

}

Sarebbe più difficile fare marcia indietro la fomula Haversine, quindi generare il proprio, penserei.

In primo luogo l'angolo generato dal nucleo della Terra viaggiando una linea "retta" sulla superficie (si pensa che è dritto, ma è curvatura).

angolo in radianti = Lunghezza arco / raggio. Angolo = arcLen / 6371 km

Latitude dovrebbe essere facile, solo la "verticale" (nord / sud) componente del vostro angolo.

Lat1 + Cos (cuscinetto) * Angolo

divisioni Longitudine variano a seconda della latitudine. In modo che diventa più difficile. Si potrebbe usare:

Sin (cuscinetto) * Angolo (con Est definito come negativo) per trovare l'angolo in direzione longitudine, ma riconversione effettiva longitudine a quella latitudine sarebbe stato più difficile.

Si veda la sezione punto Destinazione data distanza e la direzione da punto di partenza su questo sito: http://www.movable-type.co.uk/scripts/latlong.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top