Thursday, February 27, 2014

Leaflet LatLng objects, get bearings

Holy cow, it's been a month since my last posting. I've been working on lots of stuff, but not a lot of it boils down to "how to" sorts of postings. But here's one I dug out of my current project.


So, you have a Leaflet LatLng object (say, your current location) and a second LatLng object (say, the candy store). You'll find these functions helpful:
L.LatLng.prototype.bearingTo = function(other) {
    var d2r  = L.LatLng.DEG_TO_RAD;
    var r2d  = L.LatLng.RAD_TO_DEG;
    var lat1 = this.lat * d2r;
    var lat2 = other.lat * d2r;
    var dLon = (other.lng-this.lng) * d2r;
    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 = Math.atan2(y, x);
    brng = parseInt( brng * r2d );
    brng = (brng + 360) % 360;
    return brng;
};

L.LatLng.prototype.bearingWordTo = function(other) {
    var bearing = this.bearingTo(other);
    var bearingword = '';
    if      (bearing >=  22 && bearing <=  67) bearingword = 'NE';
    else if (bearing >=  67 && bearing <= 112) bearingword =  'E';
    else if (bearing >= 112 && bearing <= 157) bearingword = 'SE';
    else if (bearing >= 157 && bearing <= 202) bearingword =  'S';
    else if (bearing >= 202 && bearing <= 247) bearingword = 'SW';
    else if (bearing >= 247 && bearing <= 292) bearingword =  'W';
    else if (bearing >= 292 && bearing <= 337) bearingword = 'NW';
    else if (bearing >= 337 || bearing <=  22) bearingword =  'N';
    return bearingword;
};
After adding these, you can easily get the bearing as either a compass heading or a cardinal direction. This looks super spiffy in a mobile application:
var whichway = here.bearingWordTo(candyshop);
var howfar = (here.distanceTo(candyshop) / 1609.34).toFixed(2);
alert("Candy is " + howfar + " miles, to the " + whichway );

See more on Github:
https://github.com/gregallensworth/Leaflet/blob/master/LatLng_Bearings.js