使用纬度和经度计算地点之间的距离






4.46/5 (29投票s)
根据它们的纬度和经度计算两个地点之间的距离。
引言
这段代码是“快速抢夺”系列的一部分。 我相信有很多其他程序员也希望将代码提供给其他人使用,但不想花费数小时来创建一篇完整的“CodeProject”文章。 这是尝试看看我是否能将一些有用的代码提供给其他程序员,并在10分钟内完成。 我鼓励其他人参与“快速抢夺”。
基本规则是:
- 应该是一个解决简单问题的 C# 类。
- 不要浪费读者的时间在 GUI 方面和“
OnClick
”方法上。 - 如果可能的话,将其制作成一个带有“
Main()
”的控制台应用程序,以说明其功能。
这个系列的目的在于展示可用的预制类或技术,它们解决实际问题,而无需深入研究其工作原理。 也就是说,谁真的关心 System.Collections.ArrayList
的工作原理,你只需要使用它。
请充分注释代码,以便真正关心(并且有时间)的人能够理解底层的算法。
使用代码
我想要一个 .NET 类,它可以告诉我两个地点之间的距离。 网络上有各种各样的代码片段试图用 JavaScript 来做这件事,但程序员显然无法将算法与 GUI 分开。 这是我尝试创建一个纯粹的非 GUI 类,它可以计算两个地点之间的距离。
using System;
using System.Text;
public class CDistanceBetweenLocations
{
public static double Calc(double Lat1,
double Long1, double Lat2, double Long2)
{
/*
The Haversine formula according to Dr. Math.
http://mathforum.org/library/drmath/view/51879.html
dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2(sqrt(a), sqrt(1-a))
d = R * c
Where
* dlon is the change in longitude
* dlat is the change in latitude
* c is the great circle distance in Radians.
* R is the radius of a spherical Earth.
* The locations of the two points in
spherical coordinates (longitude and
latitude) are lon1,lat1 and lon2, lat2.
*/
double dDistance = Double.MinValue;
double dLat1InRad = Lat1 * (Math.PI / 180.0);
double dLong1InRad = Long1 * (Math.PI / 180.0);
double dLat2InRad = Lat2 * (Math.PI / 180.0);
double dLong2InRad = Long2 * (Math.PI / 180.0);
double dLongitude = dLong2InRad - dLong1InRad;
double dLatitude = dLat2InRad - dLat1InRad;
// Intermediate result a.
double a = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) +
Math.Cos(dLat1InRad) * Math.Cos(dLat2InRad) *
Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);
// Intermediate result c (great circle distance in Radians).
double c = 2.0 * Math.Asin(Math.Sqrt(a));
// Distance.
// const Double kEarthRadiusMiles = 3956.0;
const Double kEarthRadiusKms = 6376.5;
dDistance = kEarthRadiusKms * c;
return dDistance;
}
public static double Calc(string NS1, double Lat1, double Lat1Min,
string EW1, double Long1, double Long1Min, string NS2,
double Lat2, double Lat2Min, string EW2,
double Long2, double Long2Min)
{
double NS1Sign = NS1.ToUpper() == "N" ? 1.0 : -1.0;
double EW1Sign = EW1.ToUpper() == "E" ? 1.0 : -1.0;
double NS2Sign = NS2.ToUpper() == "N" ? 1.0 : -1.0;
double EW2Sign = EW2.ToUpper() == "E" ? 1.0 : -1.0;
return (Calc(
(Lat1 + (Lat1Min / 60)) * NS1Sign,
(Long1 + (Long1Min / 60)) * EW1Sign,
(Lat2 + (Lat2Min / 60)) * NS2Sign,
(Long2 + (Long2Min / 60)) * EW2Sign
));
}
public static void Main(string[] args)
{
if (args.Length < 12)
{
System.Console.WriteLine("usage: DistanceBetweenLocations" +
" N 43 35.500 W 80 27.800 N 43 35.925 W 80 28.318");
return;
}
System.Console.WriteLine(Calc(
args[0],
System.Double.Parse(args[1]),
System.Double.Parse(args[2]),
args[3],
System.Double.Parse(args[4]),
System.Double.Parse(args[5]),
args[6],
System.Double.Parse(args[7]),
System.Double.Parse(args[8]),
args[9],
System.Double.Parse(args[10]),
System.Double.Parse(args[11])));
}
}
这里有一个 MS-SQL 用户定义函数。 我一直不明白为什么这种数学功能会在 SQL Server 中,直到现在! 你可以使用这个函数在查询语句中找到最近的 Tim Horton's!!!
CREATE FUNCTION [dbo].[DistanceBetween] (@Lat1 as real,
@Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN
DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1 * (PI()/180.0);
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1 * (PI()/180.0);
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2 * (PI()/180.0);
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 * (PI()/180.0);
DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad)
* COS (@dLat2InRad)
* SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5; /* kms */
DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END
好的,第一个花费了我超过 10 分钟,但下一个不会了。