计算两个坐标之间距离的函数显示错误

我目前正在使用下面的function,它显示了一个小错误。 根据谷歌地图, 这些坐标之间的距离(从59.3293371,13.4877472到59.3225525,13.4619422)是2,2公里,而function显示为1.6公里。 我怎样才能使查克的function显示正确的距离?

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) { var R = 6371; // Radius of the earth in km var dLat = deg2rad(lat2-lat1); // deg2rad below var dLon = deg2rad(lon2-lon1); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(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; // Distance in km return d; } function deg2rad(deg) { return deg * (Math.PI/180) } 

jsFiddle: http : //jsfiddle.net/edgren/gAHJB/

你所使用的叫做半正规公式 ,它计算一个球体上的两点之间的距离, 就像乌鸦一样 。 您提供的Google地图链接显示的距离为2.2公里,因为它不是一条直线。

Wolphram Alpha是进行地理计算的极好资源, 在这两点之间也显示了1.652公里的距离。

驾驶距离与直线距离(红线雷)。

如果您正在寻找直线距离(如乌鸦文件),您的function正常工作。 如果你想要的是驾驶距离(或骑自行车的距离或公共交通距离或步行距离),你将不得不使用一个映射API( 谷歌或Bing是最stream行的)来获得适当的路线,其中将包括距离。

顺便提一下,Google Maps API在其google.maps.geometry.spherical名称空间 (查找computeDistanceBetween )中提供了球形距离的打包方法。 这可能比滚动自己更好(对于初学者来说,它使用更精确的地球半径值)。

对于我们中间的挑剔,当我说“直线距离”时,我指的是“球体上的直线”,当然这实际上是一条曲线(即大圆距)。

我之前写过一个类似的方程 – testing它也得到了1.6公里。

你谷歌地图显示驾驶距离。

您的function正在计算为乌鸦(直线距离)。

 alert(calcCrow(59.3293371,13.4877472,59.3225525,13.4619422).toFixed(1)); //This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km) function calcCrow(lat1, lon1, lat2, lon2) { var R = 6371; // km var dLat = toRad(lat2-lat1); var dLon = toRad(lon2-lon1); var lat1 = toRad(lat1); var 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; } 

Derek的解决scheme对我来说工作得很好,我只是简单地把它转换成PHP,希望能帮助别人。

 function calcCrow($lat1, $lon1, $lat2, $lon2){ $R = 6371; // km $dLat = toRad($lat2-$lat1); $dLon = toRad($lon2-$lon1); $lat1 = toRad($lat1); $lat2 = toRad($lat2); $a = sin($dLat/2) * sin($dLat/2) +sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); $d = $R * $c; return $d; } // Converts numeric degrees to radians function toRad($Value) { return $Value * pi() / 180; } 

尝试这个。 这是在VB.net,你需要将其转换为Javascript。 该函数在十进制分钟内接受参数。

  Private Function calculateDistance(ByVal long1 As String, ByVal lat1 As String, ByVal long2 As String, ByVal lat2 As String) As Double long1 = Double.Parse(long1) lat1 = Double.Parse(lat1) long2 = Double.Parse(long2) lat2 = Double.Parse(lat2) 'conversion to radian lat1 = (lat1 * 2.0 * Math.PI) / 60.0 / 360.0 long1 = (long1 * 2.0 * Math.PI) / 60.0 / 360.0 lat2 = (lat2 * 2.0 * Math.PI) / 60.0 / 360.0 long2 = (long2 * 2.0 * Math.PI) / 60.0 / 360.0 ' use to different earth axis length Dim a As Double = 6378137.0 ' Earth Major Axis (WGS84) Dim b As Double = 6356752.3142 ' Minor Axis Dim f As Double = (a - b) / a ' "Flattening" Dim e As Double = 2.0 * f - f * f ' "Eccentricity" Dim beta As Double = (a / Math.Sqrt(1.0 - e * Math.Sin(lat1) * Math.Sin(lat1))) Dim cos As Double = Math.Cos(lat1) Dim x As Double = beta * cos * Math.Cos(long1) Dim y As Double = beta * cos * Math.Sin(long1) Dim z As Double = beta * (1 - e) * Math.Sin(lat1) beta = (a / Math.Sqrt(1.0 - e * Math.Sin(lat2) * Math.Sin(lat2))) cos = Math.Cos(lat2) x -= (beta * cos * Math.Cos(long2)) y -= (beta * cos * Math.Sin(long2)) z -= (beta * (1 - e) * Math.Sin(lat2)) Return Math.Sqrt((x * x) + (y * y) + (z * z)) End Function 

编辑 JavaScript中的转换函数

 function calculateDistance(lat1, long1, lat2, long2) { //radians lat1 = (lat1 * 2.0 * Math.PI) / 60.0 / 360.0; long1 = (long1 * 2.0 * Math.PI) / 60.0 / 360.0; lat2 = (lat2 * 2.0 * Math.PI) / 60.0 / 360.0; long2 = (long2 * 2.0 * Math.PI) / 60.0 / 360.0; // use to different earth axis length var a = 6378137.0; // Earth Major Axis (WGS84) var b = 6356752.3142; // Minor Axis var f = (ab) / a; // "Flattening" var e = 2.0*f - f*f; // "Eccentricity" var beta = (a / Math.sqrt( 1.0 - e * Math.sin( lat1 ) * Math.sin( lat1 ))); var cos = Math.cos( lat1 ); var x = beta * cos * Math.cos( long1 ); var y = beta * cos * Math.sin( long1 ); var z = beta * ( 1 - e ) * Math.sin( lat1 ); beta = ( a / Math.sqrt( 1.0 - e * Math.sin( lat2 ) * Math.sin( lat2 ))); cos = Math.cos( lat2 ); x -= (beta * cos * Math.cos( long2 )); y -= (beta * cos * Math.sin( long2 )); z -= (beta * (1 - e) * Math.sin( lat2 )); return (Math.sqrt( (x*x) + (y*y) + (z*z) )/1000); }