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

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


当前回答

下面是SQL实现,以km为单位计算距离,

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;

要获得通过编程语言实现的更多细节,您可以浏览这里给出的php脚本

其他回答

要计算球体上两点之间的距离,你需要做大圆计算。

如果你需要将距离重新投影到平面上,MapTools中有许多C/ c++库可以帮助你进行地图投影。要做到这一点,你需要不同坐标系的投影字符串。

你可能还会发现MapWindow是一个可视化点的有用工具。此外,由于它是开源的,它是如何使用project.dll库的有用指南,它似乎是核心的开源投影库。

我不喜欢添加另一个答案,但谷歌地图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));

关于谷歌的计算有多精确,甚至使用了什么模型都没有任何消息(尽管它说的是“球面”而不是“大地水准面”。顺便说一下,“直线”距离显然不同于一个人在地球表面旅行的距离,而这似乎是每个人都在假设的。

下面是一个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
  }

你可以用Haversine公式计算它,它是:

a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)
c = 2 ⋅ atan2( √a, √(1−a) )
d = R ⋅ c

下面给出了一个计算两点之间距离的例子

假设我要计算从新德里到伦敦的距离,那么我该如何使用这个公式:

New delhi co-ordinates= 28.7041° N, 77.1025° E
London co-ordinates= 51.5074° N, 0.1278° W

var R = 6371e3; // metres
var φ1 = 28.7041.toRadians();
var φ2 = 51.5074.toRadians();
var Δφ = (51.5074-28.7041).toRadians();
var Δλ = (0.1278-77.1025).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c; // metres
d = d/1000; // km

下面是Haversine公式的java实现。

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

请注意,这里我们将答案四舍五入到最近的km。