计算两个经纬度点之间的距离? (Haversine公式)

时间:2020-03-05 18:43:16  来源:igfitidea点击:

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

为了澄清起见,我想要以千米为单位的距离;这些要点使用WGS84系统,我想了解可用方法的相对准确性。

解决方案

回答

该链接可能会对我们有所帮助,因为它详细说明了使用Haversine公式计算距离的方法。

摘抄:

This script [in Javascript] calculates great-circle distances between the two points –
  that is, the shortest distance over the earth’s surface – using the
  ‘Haversine’ formula.
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)
}

回答

而是取决于我们想要的精度以及定义纬度和经度的基准。非常非常近似地,我们进行了一些球形的触发,但是校正地球不是球形的事实会使公式变得更加复杂。

回答

要计算球面上两个点之间的距离,我们需要进行"大圆"计算。

如果需要将距离重新投影到平面上,有许多C / C ++库可帮助MapTools进行地图投影。为此,我们将需要各种坐标系的投影字符串。

我们可能还会发现MapWindow是可视化这些点的有用工具。作为其开源,它也是如何使用proj.dll库的有用指南,该库似乎是核心的开源投影库。

回答

这是一个实现:

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

回答

非常感谢所有这些。我在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(),因为我使用的距离非常小,以至于他们不需要它。

直到我在Radians中传递值之前,它给出的答案都是错误的,现在它与从Apple的Map应用程序获取的值几乎相同:-)

额外更新:

如果我们使用的是iOS4或者更高版本,则Apple提供了一些方法来执行此操作,因此可以使用以下方法实现相同的功能:

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

    MKMapPoint  start, finish;

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

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}