如何计算两个GPS坐标之间的距离(使用纬度和经度)?
按纬度和经度计算两个坐标之间的距离,包括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
寻找与谷歌的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; }
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来测试它.
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;
}
}
这在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
这取决于你需要它的准确度,如果你需要精确定位,最好用一个椭球来看一个算法,而不是像Vincenty算法这样精确到mm的球体.http://en.wikipedia.org/wiki/Vincenty%27s_algorithm
这是我使用的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}
这里是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转换为弧度.
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;
我需要为我的项目计算点之间的很多距离,所以我继续尝试优化代码,我在这里找到了.平均而言,在不同的浏览器中,我的新实现运行速度比最受欢迎的答案快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.
一个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
如果你需要更准确的东西,那么看看这个.
Vincenty的公式是用于大地测量的两种相关迭代方法,用于计算由Thaddeus Vincenty(1975a)开发的球体表面上两点之间的距离.它们是基于地球的形状是扁球体的假设,因此比假定球形地球的大圆距离等方法更精确.
第一个(直接)方法计算距离另一个点的给定距离和方位角(方向)的点的位置.第二种(逆)方法计算两个给定点之间的地理距离和方位角.它们已被广泛用于大地测量,因为它们精确到地球椭球上0.5毫米(0.020英寸)以内.