Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Great Circle Distance question

I am familiar with the formula to calculate the Great Circle Distance between two points.

i.e.

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

What I need though, is the reverse of this. Given a starting point, a distance, and a simple cardinal NSEW direction, to calculate the position of the destination point. It's been a long time since I was in a math class. ;)

like image 840
Pax Avatar asked Apr 21 '09 14:04

Pax


People also ask

What is the great circle Question Answer?

Detailed Solution The correct answer is The Equator. A Great Circle is any circle that circumnavigates the Earth and passes through the center of the Earth. A great circle always divides the Earth in half, thus the Equator is a great circle (but no other latitudes) and all lines of longitude are great circles.

What is great circle distance used for?

The great circle distance is useful to evaluate the shortest path when intercontinental distances are concerned. It follows the sphericity of the globe; any shortest route is the one following the curve of the planet, along the parallels.

Why is a great circle the shortest distance?

It's because planes travel along the shortest route in a 3-dimensional space.

What is great circle example?

The Equator is another of the Earth's great circles. If you were to cut into the Earth right on its Equator, you'd have two equal halves: the Northern and Southern Hemispheres. The Equator is the only east-west line that is a great circle.

What is the longest distance from one end of a circle to the other?

Diameter: The longest distance from one end of a circle to the other. The diameter = 2 × radius (d = 2r). Circumference: The distance around the circle.

What is great circle distance in aviation?

The great-circle distance or orthodromic distance is the shortest distance between two points on the surface of a sphere, measured along the surface of the sphere.


1 Answers

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

}
like image 92
Pax Avatar answered Oct 17 '22 15:10

Pax