حساب المسافة بين اثنين من خط العرض-خط الطول النقاط ؟ (Haversine الصيغة)

StackOverflow https://stackoverflow.com/questions/27928

سؤال

كيف يمكنني حساب المسافة بين نقطتين المحدد من قبل خط العرض و خط الطول ؟

للتوضيح, أود المسافة بالكيلومترات;النقاط استخدام نظام WGS84 و أود أن نفهم النسبية دقة من الأساليب المتاحة.

هل كانت مفيدة؟

المحلول

هذا الرابط قد يكون من المفيد لك ، كما تفاصيل استخدام Haversine الصيغة لحساب المسافة.

مقتطفات:

هذا البرنامج النصي [في جافا سكريبت] يحسب الدائرة العظمى المسافات بين نقطتين – هذا هو أقصر مسافة أكثر من سطح الأرض باستخدام 'Haversine' الصيغة.

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)
}

نصائح أخرى

أنا في حاجة إلى حساب الكثير من المسافات بين النقاط ، لذلك ذهبت إلى الأمام و حاول تحسين التعليمات البرمجية ، لقد وجدت هنا.في المتوسط في مختلف المتصفحات الجديد التنفيذ يعمل 2 مرات أسرع من أكثر upvoted الإجابة.

function distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

يمكنك أن تلعب مع jsPerf ونرى النتائج هنا.

في الآونة الأخيرة كنت بحاجة إلى أن تفعل الشيء نفسه في بيثون ، حتى هنا هو تنفيذ الثعبان:

from math import cos, asin, sqrt
def distance(lat1, lon1, lat2, lon2):
    p = 0.017453292519943295     #Pi/180
    a = 0.5 - cos((lat2 - lat1) * p)/2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2
    return 12742 * asin(sqrt(a)) #2*R*asin...

ومن أجل اكتمال: Haversine على ويكي.

هنا هو C# تنفيذ:

static class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIUS = 6378.16;

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(
        double lon1,
        double lat1,
        double lon2,
        double lat2)
    {
        double dlon = Radians(lon2 - lon1);
        double dlat = Radians(lat2 - lat1);

        double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
        double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        return angle * RADIUS;
    }

}

هنا هو جافا تنفيذ Haversine الصيغة.

public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
  double venueLat, double venueLng) {

    double latDistance = Math.toRadians(userLat - venueLat);
    double lngDistance = Math.toRadians(userLng - venueLng);

    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
      + Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
      * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);

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

    return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}

نلاحظ أن هنا نحن التقريب الجواب إلى أقرب كم.

شكرا جزيلا على كل هذا.أنا استخدم التعليمات البرمجية التالية في الهدف-C فون التطبيق:

const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

        double dlon = convertToRadians(place2.longitude - place1.longitude);
        double dlat = convertToRadians(place2.latitude - place1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
        double angle = 2 * asin(sqrt(a));

        return angle * RADIO;
}

خطوط الطول والعرض في عشري.لم أكن استخدام مين() عن كمافي() الدعوة المسافات التي أنا باستخدام صغيرة جدا لدرجة أنها لا تتطلب ذلك.

أنه أعطى إجابات غير صحيحة حتى مررت في القيم في راديان - الآن انها الى حد كبير نفس القيم التي تم الحصول عليها من أبل خريطة التطبيق :-)

إضافية التحديث:

إذا كنت تستخدم iOS4 أو في وقت لاحق ثم أبل توفر بعض الطرق للقيام بذلك حتى نفس الوظائف يتحقق مع:

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

    MKMapPoint  start, finish;


    start = MKMapPointForCoordinate(place1);
    finish = MKMapPointForCoordinate(place2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

هذا هو بسيط PHP وظيفة من شأنها أن تعطي معقول جدا التقريب (تحت +/-1% وهامش الخطأ).

<?php
function distance($lat1, $lon1, $lat2, $lon2) {

    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lon1 *= $pi80;
    $lat2 *= $pi80;
    $lon2 *= $pi80;

    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlon = $lon2 - $lon1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;

    //echo '<br/>'.$km;
    return $km;
}
?>

كما قلت من قبل ؛ الأرض ليست كروية.هو مثل قديم البيسبول أن علامة [مكغوير] قررت الممارسة مع - هو الكامل من الخدوش والصدمات.أبسط العمليات الحسابية (مثل هذا) التعامل معها مثل المجال.

أساليب مختلفة قد تكون أكثر أو أقل دقة وفقا أين أنت في هذا غير النظامية بيضوي الشكل و كم نقاطك (أقرب هم أصغر مطلقة خطأ هامش).أكثر دقة التوقعات الخاصة بك ، وأكثر تعقيدا الرياضيات.

لمزيد من المعلومات: ويكيبيديا المسافة الجغرافية

أنا هنا آخر العمل على سبيل المثال.

قائمة جميع النقاط في الجدول وجود مسافة بين نقطة معينة (نستخدم نقطة عشوائية - اللات:45.20327 طويلة:23.7806) أقل من 50 كم ، مع خطوط الطول والعرض في الخلية (الجدول الحقول coord_lat و coord_long):

قائمة بجميع بعد المسافة<50 في كم (يعتبر نصف قطر الأرض 6371 كم):

SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta 
FROM obiective 
WHERE coord_lat<>'' 
    AND coord_long<>'' 
HAVING distanta<50 
ORDER BY distanta desc

المثال أعلاه تم اختباره في الخلية 5.0.95 و 5.5.16 (لينكس).

في إجابات أخرى تنفيذية في هو في عداد المفقودين.

حساب المسافة بين نقطتين هي واضحة تماما مع distm وظيفة من geosphere الحزمة:

distm(p1, p2, fun = distHaversine)

حيث:

p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid 

كما أن الأرض ليست كروية تماما ، Vincenty معادلة القطع الناقص هو على الأرجح أفضل طريقة لحساب المسافات.وهكذا في geosphere الحزمة يمكنك استخدام ثم:

distm(p1, p2, fun = distVincentyEllipsoid)

طبعا ليس لديك بالضرورة إلى استخدام geosphere حزمة يمكنك أيضا حساب المسافة في قاعدة R مع وظيفة:

hav.dist <- function(long1, lat1, long2, lat2) {
  R <- 6371
  diff.long <- (long2 - long1)
  diff.lat <- (lat2 - lat1)
  a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
  b <- 2 * asin(pmin(1, sqrt(a))) 
  d = R * b
  return(d)
}

على haversine هو بالتأكيد جيدة صيغة ربما معظم الحالات إجابات أخرى تشمل بالفعل لذلك لن تأخذ مساحة.ولكن من المهم أن نلاحظ أنه لا يهم ما يستخدم صيغة (نعم وليس واحدة فقط).بسبب مجموعة واسعة من دقة ممكنة فضلا عن حساب الوقت المطلوب.اختيار الصيغة يتطلب أكثر قليلا من التفكير مجرد عدم التفكير في الإجابة.

هذا المنشور من شخص في وكالة ناسا ، هو أفضل واحد لقد وجدت في مناقشة الخيارات

http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

على سبيل المثال ، إذا كنت مجرد فرز الصفوف من خلال المسافة في دائرة نصف قطرها 100 ميل.الأرض مسطحة الصيغة سوف يكون أسرع بكثير من haversine.

HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/

a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;

لاحظت أن هناك واحد فقط التمام واحدة الجذر التربيعي.مقابل 9 منهم على Haversine الصيغة.

يمكنك استخدام بناء في CLLocationDistance لحساب هذا:

CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]

- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
    CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
    return distanceInMeters;
}

في حالة إذا كنت تريد كيلومترا فقط القسمة على 1000.

أنا لا أحب إضافة بعد آخر الجواب ، ولكن خرائط جوجل API v. 3 كروية الهندسة (وأكثر).بعد تحويل WGS84 إلى الدرجات العشرية يمكنك القيام بذلك:

<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>  

distance = google.maps.geometry.spherical.computeDistanceBetween(
    new google.maps.LatLng(fromLat, fromLng), 
    new google.maps.LatLng(toLat, toLng));

لا كلمة عن مدى دقة جوجل الحسابات أو حتى ما يستخدم نموذج (على الرغم من أنه لا يقول "كروية" بدلا من "geoid".بالمناسبة "خط مستقيم" المسافة ستكون مختلفة عن المسافة إذا كان أحد يسافر على سطح الأرض وهو ما يبدو أن الجميع افتراض.

بيثون implimentation الأصل هو مركز الولايات المتحدة متجاورة.

from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)

للحصول على الجواب في كم ببساطة تعيين ميل=false.

يمكن أن يكون هناك حل أبسط وأكثر الصحيح:محيط الأرض هو 40000 كم عند خط الاستواء حوالي 37,000 على غرينيتش (أو أي خط الطول) دورة.وبالتالي:

pythagoras = function (lat1, lon1, lat2, lon2) {
   function sqr(x) {return x * x;}
   function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}

   var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
   var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
   var dy = 37000000.0 * (lat1 - lat2) / 360.0;

   return Math.sqrt(sqr(dx) + sqr(dy));
};

أوافق على أنه ينبغي أن يكون على ما يرام ضبطها كما أنا نفسي قال أنه الاهليلجي ، حتى نصف قطر أن يكون مضروبا في جيب تمام يختلف.ولكن هذا قليلا أكثر دقة.مقارنة مع خرائط جوجل و لم تقلل من خطأ كبير.

كل الإجابات أعلاه يفترض أن الأرض كرة.ومع ذلك ، فإن أكثر دقة التقريب أن يكون ذلك من أحد كروي مفلطح.

a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km

def Distance(lat1, lons1, lat2, lons2):
    lat1=math.radians(lat1)
    lons1=math.radians(lons1)
    R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
    x1=R*math.cos(lat1)*math.cos(lons1)
    y1=R*math.cos(lat1)*math.sin(lons1)
    z1=R*math.sin(lat1)

    lat2=math.radians(lat2)
    lons2=math.radians(lons2)
    R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
    x2=R*math.cos(lat2)*math.cos(lons2)
    y2=R*math.cos(lat2)*math.sin(lons2)
    z2=R*math.sin(lat2)

    return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5

هنا نسخة مطبوعة على الآلة الكاتبة تنفيذ Haversine الصيغة

static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
    var deg2Rad = deg => {
        return deg * Math.PI / 180;
    }

    var r = 6371; // Radius of the earth in km
    var dLat = deg2Rad(lat2 - lat1);   
    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;
}

هذا البرنامج النصي [PHP] يحسب المسافات بين نقطتين.

public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
        $lat1 = $source[0];
        $lon1 = $source[1];
        $lat2 = $dest[0];
        $lon2 = $dest[1];

        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        if ($unit == "K") {
            return ($miles * 1.609344);
        }
        else if ($unit == "M")
        {
            return ($miles * 1.609344 * 1000);
        }
        else if ($unit == "N") {
            return ($miles * 0.8684);
        } 
        else {
            return $miles;
        }
    }

هنا هو SQL تنفيذ لحساب المسافة في كم ،

SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) * 
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) * 
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5  ORDER BY distance LIMIT 0 , 5;

لحساب المسافة بين نقطتين على سطح الكرة تحتاج إلى القيام الدائرة الكبرى الحساب.

هناك عدد من C/C++ المكتبات إلى مساعدة مع خريطة الإسقاط في MapTools إذا كنت بحاجة إلى reproject الخاص بك المسافات على سطح مستو.للقيام بذلك سوف تحتاج الإسقاط سلسلة من مختلف أنظمة الإحداثيات.

قد تجد أيضا MapWindow أداة مفيدة في تصور نقطة.كما المفتوحة المصدر مفيدة دليل كيفية استخدام proj.dll المكتبة التي يبدو أن النواة مفتوحة المصدر الإسقاط المكتبة.

هنا الجواب المقبول تنفيذ استدار إلى جافا في حالة أي شخص يحتاج إليها.

package com.project529.garage.util;


/**
 * Mean radius.
 */
private static double EARTH_RADIUS = 6371;

/**
 * Returns the distance between two sets of latitudes and longitudes in meters.
 * <p/>
 * Based from the following JavaScript SO answer:
 * http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
 * which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
 */
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
    double dLat = toRadians(lat2 - lat1);
    double dLon = toRadians(lon2 - lon1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = EARTH_RADIUS * c;

    return d;
}

public double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
}

كما أشار إلى حساب دقيق ينبغي أن تأخذ في الاعتبار أن الأرض ليست كرة مثالية.هنا بعض المقارنات من خوارزميات مختلفة عرضت هنا:

geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km

geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km

geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km

geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km

على مسافات صغيرة ، Keerthana خوارزمية لا يبدو أن يتزامن مع ذلك من خرائط جوجل.خرائط جوجل لا يبدو أن تتبع أي خوارزمية بسيطة ، مما يشير إلى أنه قد يكون الأسلوب الأكثر دقة هنا.

على أية حال هنا هو جافا سكريبت تنفيذ Keerthana خوارزمية:

function geoDistance(lat1, lng1, lat2, lng2){
    const a = 6378.137; // equitorial radius in km
    const b = 6356.752; // polar radius in km

    var sq = x => (x*x);
    var sqr = x => Math.sqrt(x);
    var cos = x => Math.cos(x);
    var sin = x => Math.sin(x);
    var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));

    lat1 = lat1 * Math.PI / 180;
    lng1 = lng1 * Math.PI / 180;
    lat2 = lat2 * Math.PI / 180;
    lng2 = lng2 * Math.PI / 180;

    var R1 = radius(lat1);
    var x1 = R1*cos(lat1)*cos(lng1);
    var y1 = R1*cos(lat1)*sin(lng1);
    var z1 = R1*sin(lat1);

    var R2 = radius(lat2);
    var x2 = R2*cos(lat2)*cos(lng2);
    var y2 = R2*cos(lat2)*sin(lng2);
    var z2 = R2*sin(lat2);

    return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}

هنا هو تنفيذ VB.NET, هذا التطبيق سوف تعطيك النتيجة في كم أو ميل على أساس قيمة تعداد يمكنك تمرير.

Public Enum DistanceType
    Miles
    KiloMeters
End Enum

Public Structure Position
    Public Latitude As Double
    Public Longitude As Double
End Structure

Public Class Haversine

    Public Function Distance(Pos1 As Position,
                             Pos2 As Position,
                             DistType As DistanceType) As Double

        Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)

        Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)

        Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)

        Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)

        Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))

        Dim result As Double = R * c

        Return result

    End Function

    Private Function toRadian(val As Double) As Double

        Return (Math.PI / 180) * val

    End Function

End Class

أنا المكثف حساب إلى أسفل من خلال تبسيط الصيغة.

هنا هو في روبي:

include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }

# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
  from, to = coord_radians[from], coord_radians[to]
  cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
  sines_product = sin(to[:lat]) * sin(from[:lat])
  return earth_radius_mi * acos(cosines_product + sines_product)
end
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
  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; 
  var miles = d / 1.609344; 

if ( units == 'km' ) {  
return d; 
 } else {
return miles;
}}

تشاك الحل صالحة ميل أيضا.

هنا هو بلدي جافا تنفيذ لحساب المسافة عبر الدرجات العشرية بعد بعض البحث.اعتدت يعني نصف قطرها من العالم (من ويكيبيديا) في كم.إذا كنت تريد نتيجة ميل ثم استخدام العالم في دائرة نصف قطرها ميل.

public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2) 
{
  double earthRadius = 6371.0d; // KM: use mile here if you want mile result

  double dLat = toRadian(lat2 - lat1);
  double dLng = toRadian(lng2 - lng1);

  double a = Math.pow(Math.sin(dLat/2), 2)  + 
          Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) * 
          Math.pow(Math.sin(dLng/2), 2);

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

  return earthRadius * c; // returns result kilometers
}

public static double toRadian(double degrees) 
{
  return (degrees * Math.PI) / 180.0d;
}

في الخلية استخدام الدالة التالية تمرير المعلمات باستخدام POINT(LONG,LAT)

CREATE FUNCTION `distance`(a POINT, b POINT)
 RETURNS double
    DETERMINISTIC
BEGIN

RETURN

GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters

END;
function getDistanceFromLatLonInKm(position1, position2) {
    "use strict";
    var deg2rad = function (deg) { return deg * (Math.PI / 180); },
        R = 6371,
        dLat = deg2rad(position2.lat - position1.lat),
        dLng = deg2rad(position2.lng - position1.lng),
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(position1.lat))
            * Math.cos(deg2rad(position1.lat))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2),
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

console.log(getDistanceFromLatLonInKm(
    {lat: 48.7931459, lng: 1.9483572},
    {lat: 48.827167, lng: 2.2459745}
));

هنا مثال في بوستجرس sql (في كم على بعد أميال النسخة استبدال 1.609344 قبل 0.8684 الإصدار)

CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat  

float, blng  float)
  RETURNS float AS
$BODY$
DECLARE
    v_distance float;
BEGIN

    v_distance = asin( sqrt(
            sin(radians(blat-alat)/2)^2 
                + (
                    (sin(radians(blng-alng)/2)^2) *
                    cos(radians(alat)) *
                    cos(radians(blat))
                )
          )
        ) * cast('7926.3352' as float) * cast('1.609344' as float) ;


    RETURN v_distance;
END 
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;

هناك مثال جيد هنا لحساب المسافة مع PHP http://www.geodatasource.com/developers/php :

 function distance($lat1, $lon1, $lat2, $lon2, $unit) {

     $theta = $lon1 - $lon2;
     $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
     $dist = acos($dist);
     $dist = rad2deg($dist);
     $miles = $dist * 60 * 1.1515;
     $unit = strtoupper($unit);

     if ($unit == "K") {
         return ($miles * 1.609344);
     } else if ($unit == "N") {
          return ($miles * 0.8684);
     } else {
          return $miles;
     }
 }

لدي مشكلة مع الرياضيات.درجة في لوا...إذا كان أي شخص يعرف إصلاح يرجى تنظيف هذا الرمز!

في هذه الأثناء هنا تنفيذ Haversine في لوا (استخدام هذا مع رديس!)

function calcDist(lat1, lon1, lat2, lon2)
    lat1= lat1*0.0174532925
    lat2= lat2*0.0174532925
    lon1= lon1*0.0174532925
    lon2= lon2*0.0174532925

    dlon = lon2-lon1
    dlat = lat2-lat1

    a = math.pow(math.sin(dlat/2),2) + math.cos(lat1) * math.cos(lat2) * math.pow(math.sin(dlon/2),2)
    c = 2 * math.asin(math.sqrt(a))
    dist = 6371 * c      -- multiply by 0.621371 to convert to miles
    return dist
end

هتاف!

هنا آخر تحويلها إلى روبي كود:

include Math
#Note: from/to = [lat, long]

def get_distance_in_km(from, to)
  radians = lambda { |deg| deg * Math.PI / 180 }
  radius = 6371 # Radius of the earth in kilometer
  dLat = radians[to[0]-from[0]]
  dLon = radians[to[1]-from[1]]

  cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)

  c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product)) 
  return radius * c # Distance in kilometer
end
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top