如何计算两个GPS坐标之间的距离(使用经纬度)?
当前回答
一个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
其他回答
飞镖版本
Haversine Algorithm。
import 'dart:math';
class GeoUtils {
static double _degreesToRadians(degrees) {
return degrees * pi / 180;
}
static double 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 = sin(dLat/2) * sin(dLat/2) +
sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2);
var c = 2 * atan2(sqrt(a), sqrt(1-a));
return earthRadiusKm * c;
}
}
基于Roman Makarov对这个线程的回复的Java版本的Haversine算法
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;
}
}
Unity版本c#
Haversine Algorithm。
public float Distance(float lat1, float lon1, float lat2, float lon2)
{
var earthRadiusKm = 6371;
var dLat = (lat2 - lat1) * Mathf.Rad2Deg;
var dLon = (lon2 - lon1) * Mathf.Rad2Deg;
var a = Mathf.Sin(dLat / 2) * Mathf.Sin(dLat / 2) +
Mathf.Sin(dLon / 2) * Mathf.Sin(dLon / 2) *
Mathf.Cos(lat1 * Mathf.Rad2Deg) * Mathf.Cos(lat2 * Mathf.Rad2Deg);
var c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1 - a));
return earthRadiusKm * c;
}
在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椭球地球模型的SRID
我把上面的答案用在Scala程序中
import java.lang.Math.{atan2, cos, sin, sqrt}
def latLonDistance(lat1: Double, lon1: Double)(lat2: Double, lon2: Double): Double = {
val earthRadiusKm = 6371
val dLat = (lat2 - lat1).toRadians
val dLon = (lon2 - lon1).toRadians
val latRad1 = lat1.toRadians
val latRad2 = lat2.toRadians
val a = sin(dLat / 2) * sin(dLat / 2) + sin(dLon / 2) * sin(dLon / 2) * cos(latRad1) * cos(latRad2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
earthRadiusKm * c
}
我对函数进行了压缩,以便能够轻松地生成具有两个固定位置之一的函数,并且只需要一对lat/lon来生成距离。