当前位置:  开发笔记 > 编程语言 > 正文

计算2个GPS坐标之间的距离

如何解决《计算2个GPS坐标之间的距离》经验,为你挑选了12个好方法。

如何计算两个GPS坐标之间的距离(使用纬度和经度)?



1> cletus..:

按纬度和经度计算两个坐标之间的距离,包括Javascript实现.

西部南部地区都是负面的.记住分数和秒数都在60以上,所以S31 30'是-31.50度.

不要忘记将度数转换为弧度.许多语言都有这个功能.或者它的简单计算:radians = degrees * PI / 180.

function degreesToRadians(degrees) {
  return degrees * Math.PI / 180;
}

function distanceInKmBetweenEarthCoordinates(lat1, lon1, lat2, lon2) {
  var earthRadiusKm = 6371;

  var dLat = degreesToRadians(lat2-lat1);
  var dLon = degreesToRadians(lon2-lon1);

  lat1 = degreesToRadians(lat1);
  lat2 = degreesToRadians(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)); 
  return earthRadiusKm * c;
}

以下是一些用法示例:

distanceInKmBetweenCoordinates(0,0,0,0)//相同点之间的距离应为0 0 distanceInKmBetweenCoordinates(51.5,0,38.8,-77.1)//从伦敦到阿灵顿5918.185064088764


如果有人,特别是那些不寻找行尾注释的人,正盯着这个公式并寻找一个距离单位,则单位为km.:)
如果不明显,则toRad()方法是对**Number**原型的自定义,例如:`Number.prototype.toRad = function(){return this*(Math.PI/180); }; `.或者,如下所示,您可以将"(Math.PI/2)"替换为0.0174532925199433(......您认为必要的精度)以提高性能.
对于英制单位(英里),你可以将`earthRadiusKm`改为`var earthRadiusMiles = 3959;`,fyi.

2> 小智..:

寻找与谷歌的bersine; 这是我的解决方案:

#include 
#include "haversine.h"

#define d2r (M_PI / 180.0)

//calculate haversine distance for linear distance
double haversine_km(double lat1, double long1, double lat2, double long2)
{
    double dlong = (long2 - long1) * d2r;
    double dlat = (lat2 - lat1) * d2r;
    double a = pow(sin(dlat/2.0), 2) + cos(lat1*d2r) * cos(lat2*d2r) * pow(sin(dlong/2.0), 2);
    double c = 2 * atan2(sqrt(a), sqrt(1-a));
    double d = 6367 * c;

    return d;
}

double haversine_mi(double lat1, double long1, double lat2, double long2)
{
    double dlong = (long2 - long1) * d2r;
    double dlat = (lat2 - lat1) * d2r;
    double a = pow(sin(dlat/2.0), 2) + cos(lat1*d2r) * cos(lat2*d2r) * pow(sin(dlong/2.0), 2);
    double c = 2 * atan2(sqrt(a), sqrt(1-a));
    double d = 3956 * c; 

    return d;
}


是的,或者只是使用60后的编译器.
没有必要"优化"(M_PI/180.0)到没有上下文就没有人理解的常数.编译器为您计算这些固定的术语!
您可以使用0.0174532925199433替换(M_PI/180.0)以获得更好的性能.
在性能方面:人们可以只计算一次sin(dlat/2.0),将其存储在变量a1中,而不是pow(,2),使用a1*a1会更好.对于其他战俘(,2)也是如此.
@TõnuSamuel非常感谢你的评论.对此,我真的非常感激.有意义的是,启用了优化的编译器(-O)可以预先计算常量的操作,使手动折叠无效.我有空的时候会测试一下.

3> 小智..:

C#版本的Haversine

double _eQuatorialEarthRadius = 6378.1370D;
double _d2r = (Math.PI / 180D);

private int HaversineInM(double lat1, double long1, double lat2, double long2)
{
    return (int)(1000D * HaversineInKM(lat1, long1, lat2, long2));
}

private double HaversineInKM(double lat1, double long1, double lat2, double long2)
{
    double dlong = (long2 - long1) * _d2r;
    double dlat = (lat2 - lat1) * _d2r;
    double a = Math.Pow(Math.Sin(dlat / 2D), 2D) + Math.Cos(lat1 * _d2r) * Math.Cos(lat2 * _d2r) * Math.Pow(Math.Sin(dlong / 2D), 2D);
    double c = 2D * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1D - a));
    double d = _eQuatorialEarthRadius * c;

    return d;
}

这是一个.NET小提琴,所以你可以用你自己的Lat/Longs来测试它.


.Net Framework有一个构建方法GeoCoordinate.GetDistanceTo.必须引用程序集System.Device.MSDN文章https://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate.getdistanceto%28v=vs.110%29.aspx

4> Paulo Miguel..:

Java版本的Haversine算法基于Roman Makarov对此主题的回复

public class HaversineAlgorithm {

    static final double _eQuatorialEarthRadius = 6378.1370D;
    static final double _d2r = (Math.PI / 180D);

    public static int HaversineInM(double lat1, double long1, double lat2, double long2) {
        return (int) (1000D * HaversineInKM(lat1, long1, lat2, long2));
    }

    public static double HaversineInKM(double lat1, double long1, double lat2, double long2) {
        double dlong = (long2 - long1) * _d2r;
        double dlat = (lat2 - lat1) * _d2r;
        double a = Math.pow(Math.sin(dlat / 2D), 2D) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r)
                * Math.pow(Math.sin(dlong / 2D), 2D);
        double c = 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a));
        double d = _eQuatorialEarthRadius * c;

        return d;
    }

}



5> 小智..:

这在SQL Server 2008中非常容易使用地理类型.

SELECT geography::Point(lat1, lon1, 4326).STDistance(geography::Point(lat2, lon2, 4326))
-- computes distance in meters using eliptical model, accurate to the mm

4326是WGS84 elipsoidal Earth模型的SRID



6> seanb..:

这取决于你需要它的准确度,如果你需要精确定位,最好用一个椭球来看一个算法,而不是像Vincenty算法这样精确到mm的球体.http://en.wikipedia.org/wiki/Vincenty%27s_algorithm



7> 小智..:

这是我使用的Python中的Haversine函数:

from math import pi,sqrt,sin,cos,atan2

def haversine(pos1, pos2):
    lat1 = float(pos1['lat'])
    long1 = float(pos1['long'])
    lat2 = float(pos2['lat'])
    long2 = float(pos2['long'])

    degree_to_rad = float(pi / 180.0)

    d_lat = (lat2 - lat1) * degree_to_rad
    d_long = (long2 - long1) * degree_to_rad

    a = pow(sin(d_lat / 2), 2) + cos(lat1 * degree_to_rad) * cos(lat2 * degree_to_rad) * pow(sin(d_long / 2), 2)
    c = 2 * atan2(sqrt(a), sqrt(1 - a))
    km = 6367 * c
    mi = 3956 * c

    return {"km":km, "miles":mi}


在PyPI中有一个包:https://pypi.python.org/pypi/haversine

8> Mike Chamber..:

这里是C#(lat和long弧度):

double CalculateGreatCircleDistance(double lat1, double long1, double lat2, double long2, double radius)
{
    return radius * Math.Acos(
        Math.Sin(lat1) * Math.Sin(lat2)
        + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(long2 - long1));
}

如果lat和long以度为单位,则除以180/PI转换为弧度.



9> quape..:

PHP版本:

(deg2rad()如果您的坐标已经是弧度,请删除所有.)

$R = 6371; // km
$dLat = deg2rad($lat2-$lat1);
$dLon = deg2rad($lon2-$lon1);
$lat1 = deg2rad($lat1);
$lat2 = deg2rad($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;



10> Salvador Dal..:

我需要为我的项目计算点之间的很多距离,所以我继续尝试优化代码,我在这里找到了.平均而言,在不同的浏览器中,我的新实现运行速度比最受欢迎的答案快2倍.

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并在此处查看结果.

最近我需要在python中做同样的事情,所以这里有一个python实现:

from math import cos, asin, sqrt
def distance(lat1, lon1, lat2, lon2):
    p = 0.017453292519943295
    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))

并且为了完整起见:在wiki上的Haversine.



11> 小智..:

一个T-SQL函数,用于按中心距离选择记录

Create Function  [dbo].[DistanceInMiles] 
 (  @fromLatitude float ,
    @fromLongitude float ,
    @toLatitude float, 
    @toLongitude float
  )
   returns float
AS 
BEGIN
declare @distance float

select @distance = cast((3963 * ACOS(round(COS(RADIANS(90-@fromLatitude))*COS(RADIANS(90-@toLatitude))+ 
SIN(RADIANS(90-@fromLatitude))*SIN(RADIANS(90-@toLatitude))*COS(RADIANS(@fromLongitude-@toLongitude)),15)) 
)as float) 
  return  round(@distance,1)
END



12> 小智..:

如果你需要更准确的东西,那么看看这个.

Vincenty的公式是用于大地测量的两种相关迭代方法,用于计算由Thaddeus Vincenty(1975a)开发的球体表面上两点之间的距离.它们是基于地球的形状是扁球体的假设,因此比假定球形地球的大圆距离等方法更精确.

第一个(直接)方法计算距离另一个点的给定距离和方位角(方向)的点的位置.第二种(逆)方法计算两个给定点之间的地理距离和方位角.它们已被广泛用于大地测量,因为它们精确到地球椭球上0.5毫米(0.020英寸)以内.

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有