Issue with calculating compass bearing between two GPS coordinates

Give this a try, I can't for the life of me remember where I got it though...

    /**
     * Calculate the bearing between two positions as a value from 0-360
     *
     * @param lat1 - The latitude of the first position
     * @param lng1 - The longitude of the first position
     * @param lat2 - The latitude of the second position
     * @param lng2 - The longitude of the second position
     *
     * @return int - The bearing between 0 and 360
     */
    bearing : function (lat1,lng1,lat2,lng2) {
        var dLon = (lng2-lng1);
        var y = Math.sin(dLon) * Math.cos(lat2);
        var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
        var brng = this._toDeg(Math.atan2(y, x));
        return 360 - ((brng + 360) % 360);
    },

   /**
     * Since not all browsers implement this we have our own utility that will
     * convert from degrees into radians
     *
     * @param deg - The degrees to be converted into radians
     * @return radians
     */
    _toRad : function(deg) {
         return deg * Math.PI / 180;
    },

    /**
     * Since not all browsers implement this we have our own utility that will
     * convert from radians into degrees
     *
     * @param rad - The radians to be converted into degrees
     * @return degrees
     */
    _toDeg : function(rad) {
        return rad * 180 / Math.PI;
    },

This is an edit of the accepted answer with some modifications which made it work for me (mainly the use of toRad function on lat,lng values).

    var geo = {
        /**
         * Calculate the bearing between two positions as a value from 0-360
         *
         * @param lat1 - The latitude of the first position
         * @param lng1 - The longitude of the first position
         * @param lat2 - The latitude of the second position
         * @param lng2 - The longitude of the second position
         *
         * @return int - The bearing between 0 and 360
         */
        bearing : function (lat1,lng1,lat2,lng2) {
            var dLon = this._toRad(lng2-lng1);
            var y = Math.sin(dLon) * Math.cos(this._toRad(lat2));
            var x = Math.cos(this._toRad(lat1))*Math.sin(this._toRad(lat2)) - Math.sin(this._toRad(lat1))*Math.cos(this._toRad(lat2))*Math.cos(dLon);
            var brng = this._toDeg(Math.atan2(y, x));
            return ((brng + 360) % 360);
        },

       /**
         * Since not all browsers implement this we have our own utility that will
         * convert from degrees into radians
         *
         * @param deg - The degrees to be converted into radians
         * @return radians
         */
        _toRad : function(deg) {
             return deg * Math.PI / 180;
        },

        /**
         * Since not all browsers implement this we have our own utility that will
         * convert from radians into degrees
         *
         * @param rad - The radians to be converted into degrees
         * @return degrees
         */
        _toDeg : function(rad) {
            return rad * 180 / Math.PI;
        },
    };

    /** Usage **/
    var myInitialBearing = geo.bearing(0,0,45,45);

Find theory and online calculator at: http://www.movable-type.co.uk/scripts/latlong.html


If you want a very rough method for short distances, you can use an Earth radius of 6,378,137m (the length of the semi-major axis of the WGS84 spheroid) to calculate the sides of the triangle based on the difference in latitude and longitude. Then calculate the appropriate bearing. It will be a true bearing, but likely close enough over short distances.

You'll need to leave it up to users to work out the local magnetic declination.

e.g. for your example:

startLat  = 43.6822
startLong = -70.450769

endLat  = 43.682211
endLong = -70.45070

diff lat  = 0.000011 = 1.22m
diff long = 0.000069 = 7.68m

The end point is north and east of the start, so the bearing can be found by:

tan a = 7.68 / 1.22
    a = 81°

So the direction is about East by North.

This should probably be in a mapping and surveying thread. Once you've got the maths worked out, come here for the solution.

Edit

To convert degrees of latitude to metres, first calculate the Earth circumference at the equator (or any great circle):

c = 2πR where r = 6378137m
  = 40,075,000 (approx)

Then get the ratio of the circumference out of 360°:

dist = c * deg / 360
     = 40,075,000m * 0.000011° / 360°
     = 1.223m

For longitude, the distance narrows as the latitude approaches the pole, so the same formula is used and the result multiplied by the cosine of the latitude:

     = 40,075,000m * 0.000069° / 360° * cos(0.000011°)
     = 7.681m

The value for the Earth radius is not necessarily accurate, the Earth isn't a perfect sphere (it's an oblate spheroid, sort of pear shaped). Different approximations are used in different places for greater accuracy, but the one I've used should be good enough.