2013-09-18 3 views
60

В настоящее время я использую функцию ниже, и это показывает немного неправильно. Согласно Google Maps, расстояние между these coordinates (с 59.3293371,13.4877472 до 59.3225525,13.4619422) составляет 2,2 километра, а функция показывает 1,6 километра. Как я могу сделать функцию Чака на правильном расстоянии?Функция для вычисления расстояния между двумя координатами показывает неправильные

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/

+1

возможно дубликат [Как рассчитать расстояние между двумя точками широты и долготы?] (Http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two- широта-долгота-точки) – Phillip

ответ

90

Что вы используете называются haversine formula, который вычисляет расстояние между двумя точками на сфере по прямому. Указанная вами карта Google Maps показывает расстояние в 2,2 км, потому что это не прямая линия.

Wolphram Alpha - отличный ресурс для проведения географических расчетов, а также показывает расстояние 1.652 km between these two points.

Drive distance vs. straight line distance (red line mine).

Если вы ищете расстояние прямолинейного (по прямым файлам), ваша функция работает правильно. Если вы хотите ехать (расстояние на велосипеде или расстояние общественного транспорта или расстояние пешком), вам нужно будет использовать API сопоставления (Google или Bing), чтобы получить соответствующий маршрут, который будет включать в себя расстояние.

Кстати, API Карт Google предоставляет упакованный метод для сферического расстояния в своем google.maps.geometry.spherical namespace (ищите computeDistanceBetween). Вероятно, это лучше, чем сворачивать ваши собственные (для начала он использует более точное значение радиуса Земли).

Для разборчивых среди нас, когда я говорю «прямолинейное расстояние», я имею в виду «прямую линию на сфере», которая на самом деле является изогнутой линией (то есть расстоянием большого круга), курс.

+1

Вот почему! Большое спасибо за хороший ответ :) – Erik

+1

Мое удовольствие! Было весело ответить. –

+1

Это прекрасный ответ.Я говорю красиво, потому что предоставленные детали слишком хороши для понимания разницы даже для новичков, подобных мне. – Supreet

35

я написал аналогичное уравнение перед - тестировал, а также получил 1,6 км.

Карты google отображают расстояние до DRIVING.

Ваша функция вычисляется по прямой (прямолинейное расстояние).

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; 
    } 
3

Попробуйте это. Это в 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 

Edit Преобразованный функция в 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 = (a-b)/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); 
    } 
+0

причина для downvote? – Noorul

+4

这个 问题 问 了 JavaScript 的 答案 .. Вы должны преобразовать его в английский :) –

+2

добавил javascript версию – Noorul

6

Дерек работал хорошо для меня, и я просто превратили его в 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; 
} 
Смежные вопросы