How do I calculate distance between two GPS coordinates (using latitude and longitude)?
如何计算两个GPS坐标之间的距离(使用纬度和经度)?
25 个解决方案
#1
292
Calculate the distance between two coordinates by latitude and longitude, including a Javascript implementation.
通过纬度和经度计算两个坐标之间的距离,包括一个Javascript实现。
West and South locations are negative. Remember minutes and seconds are out of 60 so S31 30' is -31.50 degrees.
西部和南部的位置是负的。记住,分钟和秒都是60,所以S31 30是-31。50度。
Don't forget to convert degrees to radians. Many languages have this function. Or its a simple calculation: radians = degrees * PI / 180
.
别忘了把学位转换成弧度。许多语言都有这个功能。或者它是一个简单的计算:弧度=度* / 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;
}
Here are some examples of usage:
这里有一些用法的例子:
distanceInKmBetweenCoordinates(0,0,0,0) // Distance between same points should be 0 0 distanceInKmBetweenCoordinates(51.5, 0, 38.8, -77.1) // From London to Arlington 5918.185064088764
从伦敦到阿灵顿(Arlington)的51.5、0、38.8、-77.1之间的距离(51.5、0、38.8、-77.1)之间的距离应该为0。
#2
58
Look for haversine with Google; here is my solution:
寻找带有谷歌的哈弗林;这是我的解决方案:
#include <math.h>
#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;
}
#3
33
C# Version of Haversine
半正矢的c#版本
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;
}
Here's a .NET Fiddle of this, so you can test it out with your own Lat/Longs.
这里有一个。net的小提琴,你可以用自己的Lat/Longs进行测试。
#4
18
Java Version of Haversine Algorithm based on Roman Makarov`s reply to this thread
基于Roman Makarov对该线程的回复的Haversine算法的Java版本。
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
17
This is very easy to do with geography type in SQL Server 2008.
这与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 is SRID for WGS84 elipsoidal Earth model
4326是SRID的WGS84的eli地球模型。
#6
15
It depends on how accurate you need it to be, if you need pinpoint accuracy, is best to look at an algorithm with uses an ellipsoid, rather than a sphere, such as Vincenty's algorithm, which is accurate to the mm. http://en.wikipedia.org/wiki/Vincenty%27s_algorithm
它取决于你需要精确到什么程度,如果你需要精确的精确度,最好的方法是使用一个椭圆体,而不是一个球,比如Vincenty的算法,它是精确到mm. http://en.wikipedia.org/wiki/Vincenty%27s_algorithm。
#7
11
Here it is in C# (lat and long in radians):
这里是c# (lat和long in radians):
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));
}
If your lat and long are in degrees then divide by 180/PI to convert to radians.
如果你的lat和long都在华氏度,然后除以180/PI,转换成弧度。
#8
10
Here's a Haversine function in Python that I use:
这是我使用的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}
#9
8
PHP version:
PHP版本:
(Remove all deg2rad()
if your coordinates are already in radians.)
(删除所有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
7
A T-SQL function, that I use to select records by distance for a center
一个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
#11
5
If you need something more accurate then have a look at this.
如果你需要更精确的东西,那就看看这个。
Vincenty's formulae are two related iterative methods used in geodesy to calculate the distance between two points on the surface of a spheroid, developed by Thaddeus Vincenty (1975a) They are based on the assumption that the figure of the Earth is an oblate spheroid, and hence are more accurate than methods such as great-circle distance which assume a spherical Earth.
Vincenty公式是两个相关的迭代方法用于大地测量计算两点之间的距离在球体表面,由撒迪厄斯Vincenty(1975)他们都是基于假设地球的图是一个扁球,从而更准确的方法如地球大圆距离它假定一个球形。
The first (direct) method computes the location of a point which is a given distance and azimuth (direction) from another point. The second (inverse) method computes the geographical distance and azimuth between two given points. They have been widely used in geodesy because they are accurate to within 0.5 mm (0.020″) on the Earth ellipsoid.
第一个(直接)方法计算一个点的位置,它是从另一个点的给定距离和方位(方向)。第二个(逆)方法计算两个给定点之间的地理距离和方位角。它们在大地测量中得到了广泛的应用,因为它们在地球椭球体上精确到0.5毫米(0.020英寸)。
#12
5
I needed to calculate a lot of distances between the points for my project, so I went ahead and tried to optimize the code, I have found here. On average in different browsers my new implementation runs 2 times faster than the most upvoted answer.
我需要计算项目的各个点之间的距离,所以我继续尝试优化代码,我在这里找到了。平均而言,在不同的浏览器中,我的新实现运行速度是最优的答案的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
}
You can play with my jsPerf and see the results here.
你可以和我的jsPerf玩,看看结果。
Recently I needed to do the same in python, so here is a python implementation:
最近,我需要在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))
And for the sake of completeness: Haversine on wiki.
为了完整性,在*上。
#13
4
I. Regarding "Breadcrumbs" method
关于“面包屑”的方法
- Earth radius is different on different Lat. This must be taken into consideration in Haversine algorithm.
- 地球半径在不同的纬度上是不同的。在Haversine算法中必须考虑到这一点。
- Consider Bearing change, which turns straight lines to arches (which are longer)
- 考虑方位变化,它会把直线变成拱形(较长)
- Taking Speed change into account will turn arches to spirals (which are longer or shorter than arches)
- 把速度变化考虑进去,就会把弓形变成螺旋形(它比拱门长或短)
- Altitude change will turn flat spirals to 3D spirals (which are longer again). This is very important for hilly areas.
- 高度的变化将使平面螺旋上升到三维螺旋(这是更长的时间)。这对丘陵地区非常重要。
Below see the function in C which takes #1 and #2 into account:
以下是在C中使用#1和#2的函数:
double calcDistanceByHaversine(double rLat1, double rLon1, double rHeading1,
double rLat2, double rLon2, double rHeading2){
double rDLatRad = 0.0;
double rDLonRad = 0.0;
double rLat1Rad = 0.0;
double rLat2Rad = 0.0;
double a = 0.0;
double c = 0.0;
double rResult = 0.0;
double rEarthRadius = 0.0;
double rDHeading = 0.0;
double rDHeadingRad = 0.0;
if ((rLat1 < -90.0) || (rLat1 > 90.0) || (rLat2 < -90.0) || (rLat2 > 90.0)
|| (rLon1 < -180.0) || (rLon1 > 180.0) || (rLon2 < -180.0)
|| (rLon2 > 180.0)) {
return -1;
};
rDLatRad = (rLat2 - rLat1) * DEGREE_TO_RADIANS;
rDLonRad = (rLon2 - rLon1) * DEGREE_TO_RADIANS;
rLat1Rad = rLat1 * DEGREE_TO_RADIANS;
rLat2Rad = rLat2 * DEGREE_TO_RADIANS;
a = sin(rDLatRad / 2) * sin(rDLatRad / 2) + sin(rDLonRad / 2) * sin(
rDLonRad / 2) * cos(rLat1Rad) * cos(rLat2Rad);
if (a == 0.0) {
return 0.0;
}
c = 2 * atan2(sqrt(a), sqrt(1 - a));
rEarthRadius = 6378.1370 - (21.3847 * 90.0 / ((fabs(rLat1) + fabs(rLat2))
/ 2.0));
rResult = rEarthRadius * c;
// Chord to Arc Correction based on Heading changes. Important for routes with many turns and U-turns
if ((rHeading1 >= 0.0) && (rHeading1 < 360.0) && (rHeading2 >= 0.0)
&& (rHeading2 < 360.0)) {
rDHeading = fabs(rHeading1 - rHeading2);
if (rDHeading > 180.0) {
rDHeading -= 180.0;
}
rDHeadingRad = rDHeading * DEGREE_TO_RADIANS;
if (rDHeading > 5.0) {
rResult = rResult * (rDHeadingRad / (2.0 * sin(rDHeadingRad / 2)));
} else {
rResult = rResult / cos(rDHeadingRad);
}
}
return rResult;
}
II. There is an easier way which gives pretty good results.
二世。有一种更简单的方法,可以得到很好的结果。
By Average Speed.
由平均速度。
Trip_distance = Trip_average_speed * Trip_time
Trip_distance = Trip_average_speed * Trip_time。
Since GPS Speed is detected by Doppler effect and is not directly related to [Lon,Lat] it can be at least considered as secondary (backup or correction) if not as main distance calculation method.
由于GPS速度是由多普勒效应探测到的,且与[Lon,Lat]没有直接相关,因此,它至少可以被认为是次要的(备份或校正),而不是主要的距离计算方法。
#14
3
private double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
private double GetDistance(double lat1, double lon1, double lat2, double lon2)
{
//code for Distance in Kilo Meter
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Abs(Math.Round(rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000, 0));
return (dist);
}
private double GetDirection(double lat1, double lon1, double lat2, double lon2)
{
//code for Direction in Degrees
double dlat = deg2rad(lat1) - deg2rad(lat2);
double dlon = deg2rad(lon1) - deg2rad(lon2);
double y = Math.Sin(dlon) * Math.Cos(lat2);
double x = Math.Cos(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) - Math.Sin(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(dlon);
double direct = Math.Round(rad2deg(Math.Atan2(y, x)), 0);
if (direct < 0)
direct = direct + 360;
return (direct);
}
private double GetSpeed(double lat1, double lon1, double lat2, double lon2, DateTime CurTime, DateTime PrevTime)
{
//code for speed in Kilo Meter/Hour
TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
double TimeDifferenceInSeconds = Math.Round(TimeDifference.TotalSeconds, 0);
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344;
double Speed = Math.Abs(Math.Round((dist / Math.Abs(TimeDifferenceInSeconds)) * 60 * 60, 0));
return (Speed);
}
private double GetDuration(DateTime CurTime, DateTime PrevTime)
{
//code for speed in Kilo Meter/Hour
TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
double TimeDifferenceInSeconds = Math.Abs(Math.Round(TimeDifference.TotalSeconds, 0));
return (TimeDifferenceInSeconds);
}
#15
3
This is version from "Henry Vilinskiy" adapted for MySQL and Kilometers:
这是“Henry Vilinskiy”的版本,适用于MySQL和公里:
CREATE FUNCTION `CalculateDistanceInKm`(
fromLatitude float,
fromLongitude float,
toLatitude float,
toLongitude float
) RETURNS float
BEGIN
declare distance float;
select
6367 * ACOS(
round(
COS(RADIANS(90-fromLatitude)) *
COS(RADIANS(90-toLatitude)) +
SIN(RADIANS(90-fromLatitude)) *
SIN(RADIANS(90-toLatitude)) *
COS(RADIANS(fromLongitude-toLongitude))
,15)
)
into distance;
return round(distance,3);
END;
#16
2
This Lua code is adapted from stuff found on Wikipedia and in Robert Lipe's GPSbabel tool:
这个Lua代码是根据*和Robert Lipe的GPSbabel工具中发现的东西改编的:
local EARTH_RAD = 6378137.0
-- earth's radius in meters (official geoid datum, not 20,000km / pi)
local radmiles = EARTH_RAD*100.0/2.54/12.0/5280.0;
-- earth's radius in miles
local multipliers = {
radians = 1, miles = radmiles, mi = radmiles, feet = radmiles * 5280,
meters = EARTH_RAD, m = EARTH_RAD, km = EARTH_RAD / 1000,
degrees = 360 / (2 * math.pi), min = 60 * 360 / (2 * math.pi)
}
function gcdist(pt1, pt2, units) -- return distance in radians or given units
--- this formula works best for points close together or antipodal
--- rounding error strikes when distance is one-quarter Earth's circumference
--- (ref: wikipedia Great-circle distance)
if not pt1.radians then pt1 = rad(pt1) end
if not pt2.radians then pt2 = rad(pt2) end
local sdlat = sin((pt1.lat - pt2.lat) / 2.0);
local sdlon = sin((pt1.lon - pt2.lon) / 2.0);
local res = sqrt(sdlat * sdlat + cos(pt1.lat) * cos(pt2.lat) * sdlon * sdlon);
res = res > 1 and 1 or res < -1 and -1 or res
res = 2 * asin(res);
if units then return res * assert(multipliers[units])
else return res
end
end
#17
2
I recently had to do the same thing. I found this website to be very helpful explaining spherical trig with examples that were easy to follow along with.
我最近也做了同样的事情。我发现这个网站对解释球形三角函数很有帮助,而且很容易理解。
#18
2
you can find a implementation of this (with some good explanation) in F# on fssnip
您可以在fssnip的f#中找到这个(有一些好的解释)的实现。
here are the important parts:
以下是重要的部分:
let GreatCircleDistance<[<Measure>] 'u> (R : float<'u>) (p1 : Location) (p2 : Location) =
let degToRad (x : float<deg>) = System.Math.PI * x / 180.0<deg/rad>
let sq x = x * x
// take the sin of the half and square the result
let sinSqHf (a : float<rad>) = (System.Math.Sin >> sq) (a / 2.0<rad>)
let cos (a : float<deg>) = System.Math.Cos (degToRad a / 1.0<rad>)
let dLat = (p2.Latitude - p1.Latitude) |> degToRad
let dLon = (p2.Longitude - p1.Longitude) |> degToRad
let a = sinSqHf dLat + cos p1.Latitude * cos p2.Latitude * sinSqHf dLon
let c = 2.0 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1.0-a))
R * c
#19
2
I needed to implement this in PowerShell, hope it can help someone else. Some notes about this method
我需要在PowerShell中实现这个功能,希望它能帮助别人。关于这个方法的一些注释。
- Don't split any of the lines or the calculation will be wrong
- 不要分割任何一条线,否则计算将是错误的。
- To calculate in KM remove the * 1000 in the calculation of $distance
- 在KM内计算,去掉* 1000,计算$distance。
- Change $earthsRadius = 3963.19059 and remove * 1000 in the calculation of $distance the to calulate the distance in miles
- 更改$earthsRadius = 3963.19059,并在计算$distance时删除* 1000,以计算里程的距离。
-
I'm using Haversine, as other posts have pointed out Vincenty's formulae is much more accurate
我用的是Haversine,其他的帖子都指出Vincenty的公式更准确。
Function MetresDistanceBetweenTwoGPSCoordinates($latitude1, $longitude1, $latitude2, $longitude2) { $Rad = ([math]::PI / 180); $earthsRadius = 6378.1370 # Earth's Radius in KM $dLat = ($latitude2 - $latitude1) * $Rad $dLon = ($longitude2 - $longitude1) * $Rad $latitude1 = $latitude1 * $Rad $latitude2 = $latitude2 * $Rad $a = [math]::Sin($dLat / 2) * [math]::Sin($dLat / 2) + [math]::Sin($dLon / 2) * [math]::Sin($dLon / 2) * [math]::Cos($latitude1) * [math]::Cos($latitude2) $c = 2 * [math]::ATan2([math]::Sqrt($a), [math]::Sqrt(1-$a)) $distance = [math]::Round($earthsRadius * $c * 1000, 0) #Multiple by 1000 to get metres Return $distance }
#20
2
If you're using .NET don't reivent the wheel. See System.Device.Location. Credit to fnx in the comments in another answer.
如果你在使用。net,不要重复使用。看到System.Device.Location。在另一个答案的评论中,对fnx的信任。
using System.Device.Location;
double lat1 = 45.421527862548828D;
double long1 = -75.697189331054688D;
double lat2 = 53.64135D;
double long2 = -113.59273D;
GeoCoordinate geo1 = new GeoCoordinate(lat1, long1);
GeoCoordinate geo2 = new GeoCoordinate(lat2, long2);
double distance = geo1.GetDistanceTo(geo2);
#21
2
here is the Swift implementation from the answer
下面是答案的快速实现。
func degreesToRadians(degrees: Double) -> Double {
return degrees * Double.pi / 180
}
func distanceInKmBetweenEarthCoordinates(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
let earthRadiusKm: Double = 6371
let dLat = degreesToRadians(degrees: lat2 - lat1)
let dLon = degreesToRadians(degrees: lon2 - lon1)
let lat1 = degreesToRadians(degrees: lat1)
let lat2 = degreesToRadians(degrees: lat2)
let a = sin(dLat/2) * sin(dLat/2) +
sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2)
let c = 2 * atan2(sqrt(a), sqrt(1 - a))
return earthRadiusKm * c
}
#22
2
i took the top answer and used it in a Scala program
我选择了顶部的答案,并在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
}
i curried the function in order to be able to easily produce functions that have one of the two locations fixed and require only a pair of lat/lon to produce distance.
我对这个函数进行了限制,以便能够很容易地生成具有两个位置之一的函数,并且只需要一对lat/lon来产生距离。
#23
1
I guess you want it along the curvature of the earth. Your two points and the center of the earth are on a plane. The center of the earth is the center of a circle on that plane and the two points are (roughly) on the perimeter of that circle. From that you can calculate the distance by finding out what the angle from one point to the other is.
我猜你想要它沿着地球的曲度。你的两点和地球的中心在一个平面上。地球的中心是这个平面上一个圆的中心,这两个点(大概)在这个圆的周长上。你可以通过找出从一个点到另一个点的角度来计算距离。
If the points are not the same heights, or if you need to take into account that the earth is not a perfect sphere it gets a little more difficult.
如果这些点不是相同的高度,或者你需要考虑到地球不是一个完美的球体,它会变得更加困难。
#24
1
// Maybe a typo error ?
We have an unused variable dlon in GetDirection,
I assume
//可能是输入错误?我们有一个未使用的变量dlon在GetDirection中。
double y = Math.Sin(dlon) * Math.Cos(lat2);
// cannot use degrees in Cos ?
should be
应该是
double y = Math.Sin(dlon) * Math.Cos(dlat);
#25
1
Scala version
Scala版本
def deg2rad(deg: Double) = deg * Math.PI / 180.0
def rad2deg(rad: Double) = rad / Math.PI * 180.0
def getDistanceMeters(lat1: Double, lon1: Double, lat2: Double, lon2: Double) = {
val theta = lon1 - lon2
val dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) *
Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta))
Math.abs(
Math.round(
rad2deg(Math.acos(dist)) * 60 * 1.1515 * 1.609344 * 1000)
)
}
#1
292
Calculate the distance between two coordinates by latitude and longitude, including a Javascript implementation.
通过纬度和经度计算两个坐标之间的距离,包括一个Javascript实现。
West and South locations are negative. Remember minutes and seconds are out of 60 so S31 30' is -31.50 degrees.
西部和南部的位置是负的。记住,分钟和秒都是60,所以S31 30是-31。50度。
Don't forget to convert degrees to radians. Many languages have this function. Or its a simple calculation: radians = degrees * PI / 180
.
别忘了把学位转换成弧度。许多语言都有这个功能。或者它是一个简单的计算:弧度=度* / 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;
}
Here are some examples of usage:
这里有一些用法的例子:
distanceInKmBetweenCoordinates(0,0,0,0) // Distance between same points should be 0 0 distanceInKmBetweenCoordinates(51.5, 0, 38.8, -77.1) // From London to Arlington 5918.185064088764
从伦敦到阿灵顿(Arlington)的51.5、0、38.8、-77.1之间的距离(51.5、0、38.8、-77.1)之间的距离应该为0。
#2
58
Look for haversine with Google; here is my solution:
寻找带有谷歌的哈弗林;这是我的解决方案:
#include <math.h>
#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;
}
#3
33
C# Version of Haversine
半正矢的c#版本
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;
}
Here's a .NET Fiddle of this, so you can test it out with your own Lat/Longs.
这里有一个。net的小提琴,你可以用自己的Lat/Longs进行测试。
#4
18
Java Version of Haversine Algorithm based on Roman Makarov`s reply to this thread
基于Roman Makarov对该线程的回复的Haversine算法的Java版本。
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
17
This is very easy to do with geography type in SQL Server 2008.
这与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 is SRID for WGS84 elipsoidal Earth model
4326是SRID的WGS84的eli地球模型。
#6
15
It depends on how accurate you need it to be, if you need pinpoint accuracy, is best to look at an algorithm with uses an ellipsoid, rather than a sphere, such as Vincenty's algorithm, which is accurate to the mm. http://en.wikipedia.org/wiki/Vincenty%27s_algorithm
它取决于你需要精确到什么程度,如果你需要精确的精确度,最好的方法是使用一个椭圆体,而不是一个球,比如Vincenty的算法,它是精确到mm. http://en.wikipedia.org/wiki/Vincenty%27s_algorithm。
#7
11
Here it is in C# (lat and long in radians):
这里是c# (lat和long in radians):
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));
}
If your lat and long are in degrees then divide by 180/PI to convert to radians.
如果你的lat和long都在华氏度,然后除以180/PI,转换成弧度。
#8
10
Here's a Haversine function in Python that I use:
这是我使用的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}
#9
8
PHP version:
PHP版本:
(Remove all deg2rad()
if your coordinates are already in radians.)
(删除所有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
7
A T-SQL function, that I use to select records by distance for a center
一个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
#11
5
If you need something more accurate then have a look at this.
如果你需要更精确的东西,那就看看这个。
Vincenty's formulae are two related iterative methods used in geodesy to calculate the distance between two points on the surface of a spheroid, developed by Thaddeus Vincenty (1975a) They are based on the assumption that the figure of the Earth is an oblate spheroid, and hence are more accurate than methods such as great-circle distance which assume a spherical Earth.
Vincenty公式是两个相关的迭代方法用于大地测量计算两点之间的距离在球体表面,由撒迪厄斯Vincenty(1975)他们都是基于假设地球的图是一个扁球,从而更准确的方法如地球大圆距离它假定一个球形。
The first (direct) method computes the location of a point which is a given distance and azimuth (direction) from another point. The second (inverse) method computes the geographical distance and azimuth between two given points. They have been widely used in geodesy because they are accurate to within 0.5 mm (0.020″) on the Earth ellipsoid.
第一个(直接)方法计算一个点的位置,它是从另一个点的给定距离和方位(方向)。第二个(逆)方法计算两个给定点之间的地理距离和方位角。它们在大地测量中得到了广泛的应用,因为它们在地球椭球体上精确到0.5毫米(0.020英寸)。
#12
5
I needed to calculate a lot of distances between the points for my project, so I went ahead and tried to optimize the code, I have found here. On average in different browsers my new implementation runs 2 times faster than the most upvoted answer.
我需要计算项目的各个点之间的距离,所以我继续尝试优化代码,我在这里找到了。平均而言,在不同的浏览器中,我的新实现运行速度是最优的答案的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
}
You can play with my jsPerf and see the results here.
你可以和我的jsPerf玩,看看结果。
Recently I needed to do the same in python, so here is a python implementation:
最近,我需要在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))
And for the sake of completeness: Haversine on wiki.
为了完整性,在*上。
#13
4
I. Regarding "Breadcrumbs" method
关于“面包屑”的方法
- Earth radius is different on different Lat. This must be taken into consideration in Haversine algorithm.
- 地球半径在不同的纬度上是不同的。在Haversine算法中必须考虑到这一点。
- Consider Bearing change, which turns straight lines to arches (which are longer)
- 考虑方位变化,它会把直线变成拱形(较长)
- Taking Speed change into account will turn arches to spirals (which are longer or shorter than arches)
- 把速度变化考虑进去,就会把弓形变成螺旋形(它比拱门长或短)
- Altitude change will turn flat spirals to 3D spirals (which are longer again). This is very important for hilly areas.
- 高度的变化将使平面螺旋上升到三维螺旋(这是更长的时间)。这对丘陵地区非常重要。
Below see the function in C which takes #1 and #2 into account:
以下是在C中使用#1和#2的函数:
double calcDistanceByHaversine(double rLat1, double rLon1, double rHeading1,
double rLat2, double rLon2, double rHeading2){
double rDLatRad = 0.0;
double rDLonRad = 0.0;
double rLat1Rad = 0.0;
double rLat2Rad = 0.0;
double a = 0.0;
double c = 0.0;
double rResult = 0.0;
double rEarthRadius = 0.0;
double rDHeading = 0.0;
double rDHeadingRad = 0.0;
if ((rLat1 < -90.0) || (rLat1 > 90.0) || (rLat2 < -90.0) || (rLat2 > 90.0)
|| (rLon1 < -180.0) || (rLon1 > 180.0) || (rLon2 < -180.0)
|| (rLon2 > 180.0)) {
return -1;
};
rDLatRad = (rLat2 - rLat1) * DEGREE_TO_RADIANS;
rDLonRad = (rLon2 - rLon1) * DEGREE_TO_RADIANS;
rLat1Rad = rLat1 * DEGREE_TO_RADIANS;
rLat2Rad = rLat2 * DEGREE_TO_RADIANS;
a = sin(rDLatRad / 2) * sin(rDLatRad / 2) + sin(rDLonRad / 2) * sin(
rDLonRad / 2) * cos(rLat1Rad) * cos(rLat2Rad);
if (a == 0.0) {
return 0.0;
}
c = 2 * atan2(sqrt(a), sqrt(1 - a));
rEarthRadius = 6378.1370 - (21.3847 * 90.0 / ((fabs(rLat1) + fabs(rLat2))
/ 2.0));
rResult = rEarthRadius * c;
// Chord to Arc Correction based on Heading changes. Important for routes with many turns and U-turns
if ((rHeading1 >= 0.0) && (rHeading1 < 360.0) && (rHeading2 >= 0.0)
&& (rHeading2 < 360.0)) {
rDHeading = fabs(rHeading1 - rHeading2);
if (rDHeading > 180.0) {
rDHeading -= 180.0;
}
rDHeadingRad = rDHeading * DEGREE_TO_RADIANS;
if (rDHeading > 5.0) {
rResult = rResult * (rDHeadingRad / (2.0 * sin(rDHeadingRad / 2)));
} else {
rResult = rResult / cos(rDHeadingRad);
}
}
return rResult;
}
II. There is an easier way which gives pretty good results.
二世。有一种更简单的方法,可以得到很好的结果。
By Average Speed.
由平均速度。
Trip_distance = Trip_average_speed * Trip_time
Trip_distance = Trip_average_speed * Trip_time。
Since GPS Speed is detected by Doppler effect and is not directly related to [Lon,Lat] it can be at least considered as secondary (backup or correction) if not as main distance calculation method.
由于GPS速度是由多普勒效应探测到的,且与[Lon,Lat]没有直接相关,因此,它至少可以被认为是次要的(备份或校正),而不是主要的距离计算方法。
#14
3
private double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
private double GetDistance(double lat1, double lon1, double lat2, double lon2)
{
//code for Distance in Kilo Meter
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Abs(Math.Round(rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000, 0));
return (dist);
}
private double GetDirection(double lat1, double lon1, double lat2, double lon2)
{
//code for Direction in Degrees
double dlat = deg2rad(lat1) - deg2rad(lat2);
double dlon = deg2rad(lon1) - deg2rad(lon2);
double y = Math.Sin(dlon) * Math.Cos(lat2);
double x = Math.Cos(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) - Math.Sin(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(dlon);
double direct = Math.Round(rad2deg(Math.Atan2(y, x)), 0);
if (direct < 0)
direct = direct + 360;
return (direct);
}
private double GetSpeed(double lat1, double lon1, double lat2, double lon2, DateTime CurTime, DateTime PrevTime)
{
//code for speed in Kilo Meter/Hour
TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
double TimeDifferenceInSeconds = Math.Round(TimeDifference.TotalSeconds, 0);
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344;
double Speed = Math.Abs(Math.Round((dist / Math.Abs(TimeDifferenceInSeconds)) * 60 * 60, 0));
return (Speed);
}
private double GetDuration(DateTime CurTime, DateTime PrevTime)
{
//code for speed in Kilo Meter/Hour
TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
double TimeDifferenceInSeconds = Math.Abs(Math.Round(TimeDifference.TotalSeconds, 0));
return (TimeDifferenceInSeconds);
}
#15
3
This is version from "Henry Vilinskiy" adapted for MySQL and Kilometers:
这是“Henry Vilinskiy”的版本,适用于MySQL和公里:
CREATE FUNCTION `CalculateDistanceInKm`(
fromLatitude float,
fromLongitude float,
toLatitude float,
toLongitude float
) RETURNS float
BEGIN
declare distance float;
select
6367 * ACOS(
round(
COS(RADIANS(90-fromLatitude)) *
COS(RADIANS(90-toLatitude)) +
SIN(RADIANS(90-fromLatitude)) *
SIN(RADIANS(90-toLatitude)) *
COS(RADIANS(fromLongitude-toLongitude))
,15)
)
into distance;
return round(distance,3);
END;
#16
2
This Lua code is adapted from stuff found on Wikipedia and in Robert Lipe's GPSbabel tool:
这个Lua代码是根据*和Robert Lipe的GPSbabel工具中发现的东西改编的:
local EARTH_RAD = 6378137.0
-- earth's radius in meters (official geoid datum, not 20,000km / pi)
local radmiles = EARTH_RAD*100.0/2.54/12.0/5280.0;
-- earth's radius in miles
local multipliers = {
radians = 1, miles = radmiles, mi = radmiles, feet = radmiles * 5280,
meters = EARTH_RAD, m = EARTH_RAD, km = EARTH_RAD / 1000,
degrees = 360 / (2 * math.pi), min = 60 * 360 / (2 * math.pi)
}
function gcdist(pt1, pt2, units) -- return distance in radians or given units
--- this formula works best for points close together or antipodal
--- rounding error strikes when distance is one-quarter Earth's circumference
--- (ref: wikipedia Great-circle distance)
if not pt1.radians then pt1 = rad(pt1) end
if not pt2.radians then pt2 = rad(pt2) end
local sdlat = sin((pt1.lat - pt2.lat) / 2.0);
local sdlon = sin((pt1.lon - pt2.lon) / 2.0);
local res = sqrt(sdlat * sdlat + cos(pt1.lat) * cos(pt2.lat) * sdlon * sdlon);
res = res > 1 and 1 or res < -1 and -1 or res
res = 2 * asin(res);
if units then return res * assert(multipliers[units])
else return res
end
end
#17
2
I recently had to do the same thing. I found this website to be very helpful explaining spherical trig with examples that were easy to follow along with.
我最近也做了同样的事情。我发现这个网站对解释球形三角函数很有帮助,而且很容易理解。
#18
2
you can find a implementation of this (with some good explanation) in F# on fssnip
您可以在fssnip的f#中找到这个(有一些好的解释)的实现。
here are the important parts:
以下是重要的部分:
let GreatCircleDistance<[<Measure>] 'u> (R : float<'u>) (p1 : Location) (p2 : Location) =
let degToRad (x : float<deg>) = System.Math.PI * x / 180.0<deg/rad>
let sq x = x * x
// take the sin of the half and square the result
let sinSqHf (a : float<rad>) = (System.Math.Sin >> sq) (a / 2.0<rad>)
let cos (a : float<deg>) = System.Math.Cos (degToRad a / 1.0<rad>)
let dLat = (p2.Latitude - p1.Latitude) |> degToRad
let dLon = (p2.Longitude - p1.Longitude) |> degToRad
let a = sinSqHf dLat + cos p1.Latitude * cos p2.Latitude * sinSqHf dLon
let c = 2.0 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1.0-a))
R * c
#19
2
I needed to implement this in PowerShell, hope it can help someone else. Some notes about this method
我需要在PowerShell中实现这个功能,希望它能帮助别人。关于这个方法的一些注释。
- Don't split any of the lines or the calculation will be wrong
- 不要分割任何一条线,否则计算将是错误的。
- To calculate in KM remove the * 1000 in the calculation of $distance
- 在KM内计算,去掉* 1000,计算$distance。
- Change $earthsRadius = 3963.19059 and remove * 1000 in the calculation of $distance the to calulate the distance in miles
- 更改$earthsRadius = 3963.19059,并在计算$distance时删除* 1000,以计算里程的距离。
-
I'm using Haversine, as other posts have pointed out Vincenty's formulae is much more accurate
我用的是Haversine,其他的帖子都指出Vincenty的公式更准确。
Function MetresDistanceBetweenTwoGPSCoordinates($latitude1, $longitude1, $latitude2, $longitude2) { $Rad = ([math]::PI / 180); $earthsRadius = 6378.1370 # Earth's Radius in KM $dLat = ($latitude2 - $latitude1) * $Rad $dLon = ($longitude2 - $longitude1) * $Rad $latitude1 = $latitude1 * $Rad $latitude2 = $latitude2 * $Rad $a = [math]::Sin($dLat / 2) * [math]::Sin($dLat / 2) + [math]::Sin($dLon / 2) * [math]::Sin($dLon / 2) * [math]::Cos($latitude1) * [math]::Cos($latitude2) $c = 2 * [math]::ATan2([math]::Sqrt($a), [math]::Sqrt(1-$a)) $distance = [math]::Round($earthsRadius * $c * 1000, 0) #Multiple by 1000 to get metres Return $distance }
#20
2
If you're using .NET don't reivent the wheel. See System.Device.Location. Credit to fnx in the comments in another answer.
如果你在使用。net,不要重复使用。看到System.Device.Location。在另一个答案的评论中,对fnx的信任。
using System.Device.Location;
double lat1 = 45.421527862548828D;
double long1 = -75.697189331054688D;
double lat2 = 53.64135D;
double long2 = -113.59273D;
GeoCoordinate geo1 = new GeoCoordinate(lat1, long1);
GeoCoordinate geo2 = new GeoCoordinate(lat2, long2);
double distance = geo1.GetDistanceTo(geo2);
#21
2
here is the Swift implementation from the answer
下面是答案的快速实现。
func degreesToRadians(degrees: Double) -> Double {
return degrees * Double.pi / 180
}
func distanceInKmBetweenEarthCoordinates(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
let earthRadiusKm: Double = 6371
let dLat = degreesToRadians(degrees: lat2 - lat1)
let dLon = degreesToRadians(degrees: lon2 - lon1)
let lat1 = degreesToRadians(degrees: lat1)
let lat2 = degreesToRadians(degrees: lat2)
let a = sin(dLat/2) * sin(dLat/2) +
sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2)
let c = 2 * atan2(sqrt(a), sqrt(1 - a))
return earthRadiusKm * c
}
#22
2
i took the top answer and used it in a Scala program
我选择了顶部的答案,并在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
}
i curried the function in order to be able to easily produce functions that have one of the two locations fixed and require only a pair of lat/lon to produce distance.
我对这个函数进行了限制,以便能够很容易地生成具有两个位置之一的函数,并且只需要一对lat/lon来产生距离。
#23
1
I guess you want it along the curvature of the earth. Your two points and the center of the earth are on a plane. The center of the earth is the center of a circle on that plane and the two points are (roughly) on the perimeter of that circle. From that you can calculate the distance by finding out what the angle from one point to the other is.
我猜你想要它沿着地球的曲度。你的两点和地球的中心在一个平面上。地球的中心是这个平面上一个圆的中心,这两个点(大概)在这个圆的周长上。你可以通过找出从一个点到另一个点的角度来计算距离。
If the points are not the same heights, or if you need to take into account that the earth is not a perfect sphere it gets a little more difficult.
如果这些点不是相同的高度,或者你需要考虑到地球不是一个完美的球体,它会变得更加困难。
#24
1
// Maybe a typo error ?
We have an unused variable dlon in GetDirection,
I assume
//可能是输入错误?我们有一个未使用的变量dlon在GetDirection中。
double y = Math.Sin(dlon) * Math.Cos(lat2);
// cannot use degrees in Cos ?
should be
应该是
double y = Math.Sin(dlon) * Math.Cos(dlat);
#25
1
Scala version
Scala版本
def deg2rad(deg: Double) = deg * Math.PI / 180.0
def rad2deg(rad: Double) = rad / Math.PI * 180.0
def getDistanceMeters(lat1: Double, lon1: Double, lat2: Double, lon2: Double) = {
val theta = lon1 - lon2
val dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) *
Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta))
Math.abs(
Math.round(
rad2deg(Math.acos(dist)) * 60 * 1.1515 * 1.609344 * 1000)
)
}