Source

utils/geo.js

/**
 * Calculates the distance between two coordinates
 * Copied from generic.inc.php "DistanceTerrestre"
 * @param {*} la1
 * @param {*} lo1
 * @param {*} la2
 * @param {*} lo2
 * @returns
 */
export function getTerrestrialDistance(la1, lo1, la2, lo2) {
  return calcCrow(la1, lo1, la2, lo2)

  function isZero(x) {
    return Math.abs(x) < 0.00000001
  }

  let cosLa1 = 0.0
  let sinLa1 = 0.0
  let cosLo1 = 0.0
  let sinLo1 = 0.0
  let cosLa2 = 0.0
  let sinLa2 = 0.0
  let cosLo2 = 0.0
  let sinLo2 = 0.0
  let coef = 0.0
  let u = 0.0
  let v = 0.0
  let w = 0.0
  let x1 = 0.0
  let y1 = 0.0
  let z1 = 0.0
  let x2 = 0.0
  let y2 = 0.0
  let z2 = 0.0
  let cosT = 0.0
  let sinT = 0.0
  let teta = 0.0
  let terre = 0.0

  terre = 6367616
  coef = Math.PI / (3600 * 180 * 3000)
  cosLa1 = Math.cos(la1 * coef)
  sinLa1 = Math.sin(la1 * coef)
  cosLa2 = Math.cos(la2 * coef)
  sinLa2 = Math.sin(la2 * coef)
  cosLo1 = Math.cos(lo1 * coef)
  sinLo1 = Math.sin(lo1 * coef)
  cosLo2 = Math.cos(lo2 * coef)
  sinLo2 = Math.sin(lo2 * coef)
  x1 = cosLa1 * cosLo1
  y1 = cosLa1 * sinLo1
  z1 = sinLa1
  x2 = cosLa2 * cosLo2
  y2 = cosLa2 * sinLo2
  z2 = sinLa2
  u = y1 * z2 - y2 * z1
  v = z1 * x2 - z2 * x1
  w = x1 * y2 - x2 * y1
  cosT = x1 * x2 + y1 * y2 + z1 * z2
  sinT = Math.sqrt(Math.pow(u, 2) + Math.pow(v, 2) + Math.pow(w, 2))
  if (isZero(cosT)) {
    teta = Math.PI / 2
  } else {
    isZero(sinT) ? (teta = 0) : (teta = Math.atan(sinT / cosT))
    if (cosT < 0 && teta < 0) teta = teta + Math.PI
  }
  return Math.abs(teta) * terre
}

function calcCrow(lat1, lon1, lat2, lon2) {
  var R = 6371 // km
  var dLat = toRad(lat2 - lat1)
  var dLon = toRad(lon2 - lon1)
  lat1 = toRad(lat1)
  lat2 = toRad(lat2)

  var a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2)
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
  var d = R * c
  return d
}

// Converts numeric degrees to radians
function toRad(Value) {
  return (Value * Math.PI) / 180
}