Haversine Formula仍无效

时间:2014-11-03 06:58:03

标签: javascript

我使用harversine公式来计算点是否在圆的内部/外部,但是它仍然响应了圆内部的点,它必须在圆外。看看我的代码。

    var xp = 7.070562277980709;  // point_lat
    var yp = 125.60755640475463;  // point_long
    var radius = 63.942490126300555;  // radius
    var xc = 7.070479805752504;  // circle_lat
    var yc = 125.60851603754577; // circle_lon

    var r       =   radius / 1000; // convert meter to kilometer
    var dlat    =   (xp - xc) * (Math.PI / 180);
    var dlng    =   (yp - yc) * (Math.PI / 180);
    var a       =   ((Math.sin(dlat / 2)) * (Math.sin(dlat / 2)));
    var b       =   ((Math.cos(xp * (Math.PI / 180))) * (Math.cos(xc * (Math.PI / 180))));
    var c       =   ((Math.sin(dlng / 2)) * (Math.sin(dlng / 2)));
    var d       =   a + (b * c);

    var e       =   2 * Math.atan2(Math.sqrt(d), Math.sqrt(1 - d));
    var f       =   r * e;
    if (f < r) {
        alert('INSIDE');
    } else if(f > r) {
        alert('OUTSIDE');
    }

此功能应提醒我&#34; OUTSIDE&#34;。这段代码怎么了?谢谢你的帮助。

所有积分均由谷歌地图提供。谷歌地图半径的默认单位是米,这就是为什么我把它转换成公里。

2 个答案:

答案 0 :(得分:1)

在您使用的公式中,半径是地球的半径。该公式给出了地球表面两点之间的大圆(即最短)距离。

使用63.942490126300555作为半径,然后将其除以1,000,得到 f 0.0000010667905687961212 km或0.001 m或1 mm。

r (例如6,371)的更合适的值代替 f 为0.10629117978319975 km,或106.291米。

以另一种方式计算,因为坐标靠近赤道,你可以将距离计算为地球周长的一部分并使用普通三角法。

使用40,000公里的周长,纬度差为0.0000824722282057877度,即:

dLat = 40,000 km * 0.0000824722282057877 / 360

dLat = 0.009163580911754189 km
     = 9.164 m

和经度:

dLong = 0.0009596327911367553;
dist  = 40000 * 0.0009596327911367553 / 360;
      = 0.10662586568186169 km
      = 106.626 m

还有一些基本的触发:

dist = sqrt(9.164^2 + 106.626^2)
     = 0.10629117978319975 km
     = 106.291 m

这与其他结果非常接近。您可以非常成功地使用该方法进行小距离,只需将经度差异得出的距离乘以纬度的余弦(因为当您靠近极点时,角距会变短)。

我的评论只是挖掘你的“米”的拼写。 : - )

修改

这是一个根据Movable Type Scripts上的Haversine公式返回大圆距离的函数:

// Return the great circle distance between two points on
// the Earth's surface given their latitude and longitude in
// decimal degrees. Only approximate.
function greatCircleDistance(lat0, lon0, lat1, lon1) {

  // Approximate Earth radius
  var earthRadius = 6.371e3;  // 6,371,000 m

  // Convert args to radians
  for (var i=arguments.length; i; ) {
    arguments[--i] = arguments[i] * Math.PI/180;
  }

  // Do calculation
  var dLat = lat1 - lat0;
  var dLon = lon1 - lon0;

  var a = Math.pow(Math.sin(dLat/2),2) +
          Math.cos(lat0) * Math.cos(lat1) *
          Math.pow(Math.sin(dLon/2),2);

  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return earthRadius * c;
}

var xp = 7.070562277980709;   // point_lat
var yp = 125.60755640475463;  // point_long

var xc = 7.070479805752504;   // circle_lat
var yc = 125.60851603754577;  // circle_lon

console.log(greatCircleDistance(xp, yp, xc, yc)); // 0.10629117978188952

所以你可以这样做:

if ( greatCircleDistance(xp, yp, xc, yc) > 63) { 
  console.log('outside');
} else {
  console.log('inside');
}

答案 1 :(得分:1)

很明显,您的Harversine计算是正确的,它等于google map api static method computeDistanceBetween 返回的结果。这是一个fiddle

但是,您的逻辑意味着要检查点是否存在的球体半径和半径都是相同的。
要获得预期的输出,您必须为问题空间建模,如下所示

  • R:球体半径
  • 球体表面
  • p1,p2 ......:点(纬度,长坐标)
  • r:检查p2是否在距离范围内&#39; r&#39; p1其中r&amp; R在同一单位

基于以上所述,您需要实现以下逻辑

var e = calculate haversine of the central angle for point p1 and p2  
var d = e * R;//where R is the radius of sphere, and the d would be great circle distance
if( d < r){// check whether p1 exists within r distance of p2
  //point is inside
}
else{
    //point is outside
}

请注意,Haversine公式不仅适用于地球距离,更适用于球体。但是,正确性可能会根据所考虑的点的大小和位置而有所不同。