在Javascript中使用Haversine公式

Cre*_*hts 29 javascript haversine

我正在尝试使用Haversine距离公式(如此处所示:http://www.movable-type.co.uk/scripts/latlong.html)但我无法使其工作,请参阅以下代码

    function test() { 
    var lat2 = 42.741; 
    var lon2 = -71.3161; 
    var lat1 = 42.806911; 
    var lon1 = -71.290611; 

    var R = 6371; // km 
    //has a problem with the .toRad() method below.
    var dLat = (lat2-lat1).toRad();  
    var dLon = (lon2-lon1).toRad();  
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
                    Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
                    Math.sin(dLon/2) * Math.sin(dLon/2);  
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    var d = R * c; 

    alert(d); 
}
Run Code Online (Sandbox Code Playgroud)

错误是:

Uncaught TypeError: Object -0.06591099999999983 has no method 'toRad' 
Run Code Online (Sandbox Code Playgroud)

据我所知,因为它需要做以下事情:

Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
Run Code Online (Sandbox Code Playgroud)

但是当我把它放在函数下面时,它仍会返回相同的错误消息.如何使用辅助方法?或者是否有另一种方法来对其进行编码以使其工作?谢谢!

tal*_*kol 41

这段代码有效:

Number.prototype.toRad = function() {
   return this * Math.PI / 180;
}

var lat2 = 42.741; 
var lon2 = -71.3161; 
var lat1 = 42.806911; 
var lon1 = -71.290611; 

var R = 6371; // km 
//has a problem with the .toRad() method below.
var x1 = lat2-lat1;
var dLat = x1.toRad();  
var x2 = lon2-lon1;
var dLon = x2.toRad();  
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
                Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
                Math.sin(dLon/2) * Math.sin(dLon/2);  
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c; 

alert(d);
Run Code Online (Sandbox Code Playgroud)

注意我是如何定义x1和x2的.在以下网址玩游戏:https://tinker.io/3f794


Nat*_*ppi 24

这是基于3个其他答案的重构函数!

请注意,coords参数是[经度,纬度].

function haversineDistance(coords1, coords2, isMiles) {
  function toRad(x) {
    return x * Math.PI / 180;
  }

  var lon1 = coords1[0];
  var lat1 = coords1[1];

  var lon2 = coords2[0];
  var lat2 = coords2[1];

  var R = 6371; // km

  var x1 = lat2 - lat1;
  var dLat = toRad(x1);
  var x2 = lon2 - lon1;
  var dLon = toRad(x2)
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;

  if(isMiles) d /= 1.60934;

  return d;
}
Run Code Online (Sandbox Code Playgroud)


tal*_*kol 13

为什么不尝试直接的解决方案呢?而不是扩展Number原型,只需将toRad定义为常规函数:

function toRad(x) {
   return x * Math.PI / 180;
}
Run Code Online (Sandbox Code Playgroud)

然后toRad到处打电话:

var dLat = toRad(lat2-lat1); 
Run Code Online (Sandbox Code Playgroud)

扩展Number原型并不总是按预期工作.例如,调用123.toRad()不起作用.我认为,如果你做得var x1 = lat2 - lat1; x1.toRad();比做得好(lat2-lat1).toRad()


Har*_*ner 11

ES6 JavaScript/NodeJS重构版本:

/**
 * Calculates the haversine distance between point A, and B.
 * @param {number[]} latlngA [lat, lng] point A
 * @param {number[]} latlngB [lat, lng] point B
 * @param {boolean} isMiles If we are using miles, else km.
 */
const haversineDistance = (latlngA, latlngB, isMiles) => {
  const toRadian = angle => (Math.PI / 180) * angle;
  const distance = (a, b) => (Math.PI / 180) * (a - b);
  const RADIUS_OF_EARTH_IN_KM = 6371;

  let lat1 = latlngA[0];
  let lat2 = latlngB[0];
  const lon1 = latlngA[1];
  const lon2 = latlngB[1];

  const dLat = distance(lat2, lat1);
  const dLon = distance(lon2, lon1);

  lat1 = toRadian(lat1);
  lat2 = toRadian(lat2);

  // Haversine Formula
  const a =
    Math.pow(Math.sin(dLat / 2), 2) +
    Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
  const c = 2 * Math.asin(Math.sqrt(a));

  let finalDistance = RADIUS_OF_EARTH_IN_KM * c;

  if (isMiles) {
    finalDistance /= 1.60934;
  }

  return finalDistance;
};
Run Code Online (Sandbox Code Playgroud)

  • 这是我在堆栈上看到的最准确的,并且与谷歌地图完美匹配,做得很好 (3认同)