如何计算由经纬度指定的两点之间的距离?

为了澄清,我想用千米来表示距离;这些点使用WGS84系统,我想了解可用方法的相对准确性。


当前回答

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

查克的解决方案,也适用于英里。

其他回答

非常感谢这一切。我在Objective-C iPhone应用程序中使用了以下代码:

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

纬度和经度是十进制的。我没有在asin()调用中使用min(),因为我使用的距离非常小,以至于它们不需要min()。

它给出了错误的答案,直到我传入弧度的值-现在它几乎与从苹果地图应用程序中获得的值相同:-)

额外的更新:

如果你使用的是iOS4或更高版本,那么苹果会提供一些方法来实现相同的功能:

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

    MKMapPoint  start, finish;


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

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

哈弗辛公式在大多数情况下都是很好的公式,其他答案已经包含了它所以我就不占用空间了。但重要的是要注意,无论使用什么公式(是的,不仅仅是一个)。因为可能的精度范围很大,以及所需的计算时间。公式的选择需要更多的思考,而不是简单的无脑答案。

这个帖子来自nasa的一个人,是我在讨论这些选项时发现的最好的一个

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

例如,如果您只是在100英里半径内按距离对行进行排序。地平公式比哈弗辛公式快得多。

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个。

计算距离——尤其是大距离——的主要挑战之一是解释地球的曲率。如果地球是平的,计算两点之间的距离就会像计算直线一样简单!哈弗辛公式包括一个常数(下面是R变量),它表示地球的半径。根据你是用英里还是公里来测量,它分别等于3956英里或6367公里。 基本公式是:

Dlon = lon2 - lon1 dat = lat2 - lat1 = (sin (dlat / 2)) ^ 2 + cos (lat1) * cos (lat2) * (sin (dlon / 2)) ^ 2 C = 2 * atan2(√(a),√(1-a)) distance = R * c(其中R为地球半径) R = 6367公里OR 3956英里

     lat1, lon1: The Latitude and Longitude of point 1 (in decimal degrees)
     lat2, lon2: The Latitude and Longitude of point 2 (in decimal degrees)
     unit: The unit of measurement in which to calculate the results where:
     'M' is statute miles (default)
     'K' is kilometers
     'N' is nautical miles

样本

function distance(lat1, lon1, lat2, lon2, unit) {
    try {
        var radlat1 = Math.PI * lat1 / 180
        var radlat2 = Math.PI * lat2 / 180
        var theta = lon1 - lon2
        var radtheta = Math.PI * theta / 180
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        dist = Math.acos(dist)
        dist = dist * 180 / Math.PI
        dist = dist * 60 * 1.1515
        if (unit == "K") {
            dist = dist * 1.609344
        }
        if (unit == "N") {
            dist = dist * 0.8684
        }
        return dist
    } catch (err) {
        console.log(err);
    }
}

仅限飞镖:

import 'dart:math' show cos, sqrt, asin;

double calculateDistance(LatLng l1, LatLng l2) {
  const p = 0.017453292519943295;
  final a = 0.5 -
      cos((l2.latitude - l1.latitude) * p) / 2 +
      cos(l1.latitude * p) *
          cos(l2.latitude * p) *
          (1 - cos((l2.longitude - l1.longitude) * p)) /
          2;
  return 12742 * asin(sqrt(a));
}

下面是一个Scala实现:

  def calculateHaversineDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double = {
    val long2 = lon2 * math.Pi / 180
    val lat2 = lat2 * math.Pi / 180
    val long1 = lon1 * math.Pi / 180
    val lat1 = lat1 * math.Pi / 180

    val dlon = long2 - long1
    val dlat = lat2 - lat1
    val a = math.pow(math.sin(dlat / 2), 2) + math.cos(lat1) * math.cos(lat2) * math.pow(math.sin(dlon / 2), 2)
    val c = 2 * math.atan2(Math.sqrt(a), math.sqrt(1 - a))
    val haversineDistance = 3961 * c // 3961 = radius of earth in miles
    haversineDistance
  }