views:

356

answers:

3

I have a from location (latitude, longitude) and to location (latitude, longitude). After calculating, it should show me what would be the nearest way to go from using a compass. The following is PHP code to do that, but its showing the wrong direction, I need little help on this.

function GreatCircleDirection ($OrigLat, $DestLat, $OrigLong, $DestLong, $Distance)
{
    $Result = 0.0;

    $L1 = deg2rad($OrigLat);
    $L2 = deg2rad($DestLat);
    $D = deg2rad($Distance / 60); # divide by 60 for nautical miles NM to degree

    $I1 = deg2rad($OrigLong);
    $I2 = deg2rad($DestLong);
    $Dlong = $I1 - $I2;

    $A = sin($L2) - cos($D + $L1 - pi() / 2);
    $B = acos($A / (cos($L1) * sin($D)) + 1);

    if ((abs($Dlong) < pi() and $Dlong < 0) or (abs($Dlong) > pi() and $Dlong > 0))
    {
        //$B = (2 * pi()) - $B;
    }

    $Result = $B;
    return rad2deg($Result);
}


function GreatCircleDistance ($OrigLat , $DestLat, $OrigLong, $DestLong)
    {
        $L1 = deg2rad($OrigLat);
        $L2 = deg2rad($DestLat);
        $I1 = deg2rad($OrigLong);
        $I2 = deg2rad($DestLong);

        $D = acos(cos($L1 - $L2) - (1 - cos($I1 - $I2)) * cos($L1) * cos($L2));
        # One degree of such an arc on the earth's surface is 60 international nautical miles NM
        return rad2deg($D * 60);
    }

Bug on if condition: this is the values in the if condition of greatCircleDirection function, need to know what to change to fix it.

if (0.57700585070933 < 3.1415926535898 and 0.57700585070933 < 0) or (0.57700585070933 > 3.1415926535898 and 0.57700585070933 > 0)

example:

from lat: 33.71, 
to lat: 21, 
from long: 73.06, 
to long: 40 , 
distance: 1908.842544944
direction 104.96527938779  (direction should be 255.87 or so)
A: 

Perhaps the worked examples, under "Using the Sine Rule", at http://www.krysstal.com/sphertrig.html will help.

M. S. B.
+1  A: 

Well, your distance calculation checks out. But I see that the answer you get for the initial bearing is (0+105)mod360 rather than (0-105)mod360 (approximately) so I suspect a wrong sign somewhere in the if statement in your GreatCircleDirection function.

High Performance Mark
yes you are right, that if condition is wrong.. can you help me to fix it, i have no idea what to do to fix it.
Basit
this is if condition: (0.57700585070933 < 3.1415926535898 and 0.57700585070933 < 0) or (0.57700585070933 > 3.1415926535898 and 0.57700585070933 > 0)
Basit
should i change the greater and lesser signs opposite? would that work? but mainly, would that be accurate right thing to do in the calculation?
Basit
@basit: Try it and find out.
BlueRaja - Danny Pflughoeft
+1  A: 

Computing the distance is unnecessary; it simply adds more operations and can introduces more numerical errors. Using your style of coding, something like this should work:

function GreatCircleDirection($OrigLat, $OrigLong, $DestLat, $DestLong)
{   
   $L1 = deg2rad($OrigLat);
   $I1 = deg2rad($OrigLong);
   $L2 = deg2rad($DestLat);
   $I2 = deg2rad($DestLong);
   return rad2deg(atan2((sin($I2-$I1),cos($L1)*tan($L2)-sin($L1)*cos($I2-$I1)));
}

The atan2 function takes care of identifying the correct quadrant for the direction, and gives you the angle between -180 to 180 measured from true North, e.g., GreaterCircleDirection(39,-77,21,40) evaluates to 56.76 degrees. Sign convention used: latitudes are positive when north, negative when south; longitudes are positive when east, negative when west.

The calculation is discussed in, among other places, http://patriot.net/~abdali/ftp/qibla.pdf.

Kamal Abdali