计算两个地理编码之间距离的公式是什么?我在这个网站上看到了一些答案,但他们基本上说要依赖 SQL Server 08 功能,我还没有使用 08。任何帮助,将不胜感激。
9 回答
使用地球的近似值和Haversine公式。您可以在以下 url 上获得 javascript 版本,您可以将其翻译成您选择的语言:
在这里查看 SQL Server 2000 版本SQL Server 邮政编码纬度/经度接近距离搜索
这将在 c# 中为您完成。
在命名空间中放置这些:
public enum DistanceType { Miles, Kilometers };
public struct Position
{
public double Latitude;
public double Longitude;
}
class Haversine
{
public double Distance(Position pos1, Position pos2, DistanceType type)
{
double preDlat = pos2.Latitude - pos1.Latitude;
double preDlon = pos2.Longitude - pos1.Longitude;
double R = (type == DistanceType.Miles) ? 3960 : 6371;
double dLat = this.toRadian(preDlat);
double dLon = this.toRadian(preDlon);
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Cos(this.toRadian(pos1.Latitude)) * Math.Cos(this.toRadian(pos2.Latitude)) *
Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)));
double d = R * c;
return d;
}
private double toRadian(double val)
{
return (Math.PI / 180) * val;
}
然后在主代码中使用这些:
Position pos1 = new Position();
pos1.Latitude = Convert.ToDouble(hotelx.latitude);
pos1.Longitude = Convert.ToDouble(hotelx.longitude);
Position pos2 = new Position();
pos2.Latitude = Convert.ToDouble(lat);
pos2.Longitude = Convert.ToDouble(lng);
Haversine calc = new Haversine();
double result = calc.Distance(pos1, pos2, DistanceType.Miles);
如果
- 你知道这两个点是“相距不远”
- 并且您可以容忍“相当小的”错误。
然后,考虑地球在两点之间是平的:
- 纬度方向的距离差为
EarthRadius * latitude difference
- 经度方向的距离差为
EarthRadius * longitude difference * cos(latitude)
。我们乘以是cos(lat)
因为如果纬度发生变化,经度度不会产生相同的公里距离。由于 P1 和 P2 接近,因此 cos(latP1) 与 cos(latP2) 接近 - 然后是毕达哥拉斯
在 JavaScript 中:
function ClosePointsDistance(latP1, lngP1, latP2, lngP2) {
var d2r = Math.PI / 180,
R=6371; // Earth Radius in km
latP1 *= d2r; lngP1 *= d2r; latP2 *= d2r; lngP2 *= d2r; // convert to radians
dlat = latP2 - latP1,
dlng = (lngP2 - lngP1) * Math.cos(latP1);
return R * Math.sqrt( dlat*dlat + dlng*dlng );
}
我在巴黎和奥尔良(法国)之间进行了测试:公式找到了 110.9 公里,而(精确的)Haversine 公式找到了 111.0 公里。
!!!注意 0 子午线附近的情况(你可以移动它):如果 P1 在 Lng 359,P2 在 Lng 0,函数会认为它们异常远!
这里其他人提供的勾股定理不太适用。
最好的、简单的答案是将地球近似为一个球体(它实际上是一个稍微扁平的球体,但这非常接近)。例如,在 Haskell 中,您可能会使用以下内容,但数学几乎可以转录为任何内容:
distRadians (lat1,lon1) (lat2,lon2) =
radius_of_earth *
acos (cos lat1 * cos lon1 * cos lat2 * cos lon2 +
cos lat1 * sin lon1 * cos lat2 * sin lon2 +
sin lat1 * sin lat2) where
radius_of_earth = 6378 -- kilometers
distDegrees a b = distRadians (coord2rad a) (coord2rad b) where
deg2rad d = d * pi / 180
coord2rad (lat,lon) = (deg2rad lat, deg2rad lon)
distRadians
要求您的角度以弧度表示。
distDegrees
是一个辅助函数,可以以度为单位获取纬度和经度。
有关此公式推导的更多信息,请参阅此系列文章。
如果您真的需要假设地球是椭球体而获得的额外精度,请参阅此常见问题解答:http ://www.movable-type.co.uk/scripts/gis-faq-5.1.html
如果您使用的是 sql server,这是一种方法。
CREATE function dist (@Lat1 varchar(50), @Lng1 varchar(50),@Lat2 varchar(50), @Lng2 varchar(50))
returns float
as
begin
declare @p1 geography
declare @p2 geography
set @p1 = geography::STGeomFromText('POINT('+ @Lng1+' '+ @Lat1 +')', 4326)
set @p2 = geography::STGeomFromText('POINT('+ @Lng2+' '+ @Lat2 +')', 4326)
return @p1.STDistance(@p2)
end
您正在寻找球体上两点之间的大圆路径的长度。尝试在 Google 上查找“大圆路径”或“大圆距离”。
对不起,我什至不知道你在哪个国家。我们是在谈论 Easting and Northings(英国,Ordance Survey 系统)还是 Lat/Long 或其他一些系统?如果我们在谈论东移和北移,那么您可以使用
sqr((x1-x2)^2 + (y1-y2)^2)
这不允许地球是球体这一事实,但对于短距离,您将不会注意。我们在工作中使用它来测量县内各点之间的距离。
请注意您使用多长时间的网格参考。我认为 8 位数的参考会给你以米为单位的距离。如果没有其他人提供,我将能够在下周的工作中得到明确的答案。
勾股定理?