Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

I need to calculate the distance between two lat/lng coordinate pairs. In addition, If given an initial lat/lng coordinate, angle of travel, and distance, I need to calculate the resulting lat/lng coordinate.

  • $f(lat1, lng1, lat2, lng2) = what (angle, distance)$
  • $f(lat1, lng1, angle, distance) = what (lat1, lng1)$

I come from a programming background so please bear with my lack of exposure to math notation.

share|improve this question

1 Answer 1

up vote 1 down vote accepted

Here is a jsfiddle which appears to work: as you can see, I tested it by feeding the output of one function into the other. The azimuth ("angle" in your notation) is calculated as described in Wikipedia. The second function assumes that the trajectory of motion is an arc of a great circle (aka geodesic, aka shortest path on the sphere). In particular, this means that starting in London and going initially to the east (azimuth 90 degrees), you will actually be going southeast soon. If one maintained constant azimuth during the travel, the resulting trajectory would not be a geodesic but a loxodromic curve.

In case something happens to jsfiddle, here is the code. (By the way, I am sure that this particular problem has been solved many times, in various languages and in better ways than I did here.)

function f(lat1, lng1, lat2, lng2) {
    // convert angles to radians 
    var Lat1 = lat1 * Math.PI / 180;
    var Lng1 = lng1 * Math.PI / 180;
    var Lat2 = lat2 * Math.PI / 180;
    var Lng2 = lng2 * Math.PI / 180;
    // find cartesian coordinates
    var x1 = Math.cos(Lat1) * Math.cos(Lng1);
    var y1 = Math.cos(Lat1) * Math.sin(Lng1);
    var z1 = Math.sin(Lat1);
    var x2 = Math.cos(Lat2) * Math.cos(Lng2);
    var y2 = Math.cos(Lat2) * Math.sin(Lng2);
    var z2 = Math.sin(Lat2);
    // vector from initial to terminal point
    var xv = x2 - x1;
    var yv = y2 - y1;
    var zv = z2 - z1;
    // distance 
    var distanceChordal = Math.sqrt(xv * xv + yv * yv + zv * zv);
    var distance = 2 * Math.asin(distanceChordal / 2);
    // magic formula for azimuth from  http://en.wikipedia.org/wiki/Azimuth
    var Azimuth = Math.atan(Math.sin(Lng2 - Lng1) / (Math.cos(Lat1) * Math.tan(Lat2) - Math.sin(Lat1) * Math.cos(Lng2 - Lng1)));
    if (lat2 < lat1) {
        Azimuth = Azimuth + Math.PI;
    }
    // output 
    var azimuth = Azimuth * 180 / Math.PI;
    document.write("<p>From latitude ", lat1, " and longitude ", lng1, ", to latitude ", lat2, " and longitude ", lng2, ":</p>");
    document.write("<p>Distance is ", distance, " (times the radius). Azimuth is ", azimuth, " degrees.</p><hr>");
}

function g(lat1, lng1, azimuth, distance) {
    // convert angles to radians 
    var Lat1 = lat1 * Math.PI / 180;
    var Lng1 = lng1 * Math.PI / 180;
    var Azimuth = azimuth * Math.PI / 180;
    // find cartesian coordinates
    var x1 = Math.cos(Lat1) * Math.cos(Lng1);
    var y1 = Math.cos(Lat1) * Math.sin(Lng1);
    var z1 = Math.sin(Lat1);
    // unit vectors pointing East and North
    var xEast = -y1 / Math.sqrt(x1 * x1 + y1 * y1);
    var yEast = x1 / Math.sqrt(x1 * x1 + y1 * y1);
    var zEast = 0;
    var xNorth = -x1 * z1 / Math.sqrt(x1 * x1 + y1 * y1);
    var yNorth = -y1 * z1 / Math.sqrt(x1 * x1 + y1 * y1);
    var zNorth = Math.sqrt(x1 * x1 + y1 * y1);
    // unit vector with the given azimuth angle
    var xv = xNorth * Math.cos(Azimuth) + xEast * Math.sin(Azimuth);
    var yv = yNorth * Math.cos(Azimuth) + yEast * Math.sin(Azimuth);
    var zv = zNorth * Math.cos(Azimuth) + zEast * Math.sin(Azimuth);
    // terminal point in Cartesian coordinates
    var x2 = x1 * Math.cos(distance) + xv * Math.sin(distance);
    var y2 = y1 * Math.cos(distance) + yv * Math.sin(distance);
    var z2 = z1 * Math.cos(distance) + zv * Math.sin(distance);
    // terminal point in spherical coordinates
    var lat2 = Math.asin(z2) * 180 / Math.PI;
    var lng2 = Math.atan2(y2, x2) * 180 / Math.PI;
    // output 
    document.write("<p>From latitude ", lat1, " and longitude ", lng1, ", starting with azimuth ", azimuth, " and going for distance ", distance, " (times the radius):</p>");
    document.write("<p>New latitude is ", lat2, " degrees. New longitude is ", lng2, " degrees.</p>");
}

f(24, 53, -55, 30);
g(24, 53, 193, 1.42);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.