/*
 * Calculate distance (in km) between two points specified by latitude/longitude with Haversine formula
 *
 * from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine",
 *       Sky and Telescope, vol 68, no 2, 1984
 *       http://www.census.gov/cgi-bin/geo/gisfaq?Q5.1
 */

function distHaversine(p1, p2) {
  var R = 6371; // earth's mean radius in km
  var dLat  = p2.latRadians() - p1.latRadians();
  var dLong = p2.lngRadians() - p1.lngRadians();

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(p1.latRadians()) * Math.cos(p2.latRadians()) * Math.sin(dLong/2) * Math.sin(dLong/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;

  return d;
}


/*
 * calculate (initial) bearing (in radians clockwise) between two points
 *
 * from: Ed Williams' Aviation Formulary, http://williams.best.vwh.net/avform.htm#Crs
 */
function bearing(p1, p2) {
  var y = Math.sin(p2.lngRadians()-p1.lngRadians()) * Math.cos(p2.latRadians());
  var x = Math.cos(p1.latRadians())*Math.sin(p2.latRadians()) -
    Math.sin(p1.latRadians())*Math.cos(p2.latRadians())*Math.cos(p2.lngRadians()-p1.lngRadians());
  return Math.atan2(y, x);
}

/*
 * convert radians to (signed) degrees, minutes, seconds; eg -0.1rad = -000°05'44"
 */
function radToDegMinSec(rad) {
  return (rad<0?'-':'') + _dms(rad);
}


/*
 * convert radians to compass bearing - 0°-360° rather than +ve/-ve
 */
function radToBrng(rad) {
  return radToDegMinSec((rad+2*Math.PI) % (2*Math.PI));
}


/*
 * convert radians to deg/min/sec, with no sign or compass dirn (internal use)
 */
function _dms(rad) {
  var d = Math.abs(rad * 180 / Math.PI);
  d += 1/7200;  // add ½ second for rounding
  var deg = Math.floor(d);
  var min = Math.floor((d-deg)*60);
  var sec = Math.floor((d-deg-min/60)*3600);
  // add leading zeros if required
  if (deg<100) deg = '0' + deg; if (deg<10) deg = '0' + deg;
  if (min<10) min = '0' + min;
  if (sec<10) sec = '0' + sec;
  return deg + '\u00B0' + min + '\u2032' + sec + '\u2033';
}