Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱
随笔 - 172, 文章 - 0, 评论 - 257, 引用 - 0
数据加载中……

通过两个点的经纬度计算距离

最近开始做一个类似gis的东西. 需要求一些经纬度相关的值..

看了通过两个点的经纬度计算距离这篇,据说是Google里扒来的算法,于是决定验证一下。
通过计算发现非常正确。
用30,120和31,121两个坐标点进行验证,同Mapinfo中计算的结果非常的相近。
后来又把坐标系直接当成直角坐标系来计算,发现误差很大。
于是仍然用直角坐标系方法来计算,给纬度加上了个0.86的参数,这样计算下来和结果相近。




c#代码
private const double EARTH_RADIUS = 6378.137; //地球半径
private static double rad(double d)
{
   return d * Math.PI / 180.0;
}

public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
   double radLat1 = rad(lat1);
   double radLat2 = rad(lat2);
   double a = radLat1 - radLat2;
   double b = rad(lng1) - rad(lng2);
   double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a/2),2) +
    Math.Cos(radLat1)*Math.Cos(radLat2)*Math.Pow(Math.Sin(b/2),2)));
   s = s * EARTH_RADIUS;
   s = Math.Round(s * 10000) / 10000;
   return s;
}


vb代码

Const EARTH_RADIUS = 6378.137
Const Pi = 3.1415926535898

Function rad(ByVal d As Double) As Double
rad = d * Pi / 180
End Function

Function GetDistance(lat1 As Double, lng1 As Double, lat2 As Double, lng2 As Double) As Double
Dim radlat1 As Double, radlat2 As Double
Dim a As Double, b As Double, s As Double, Temp As Double
radlat1 = rad(lat1)
radlat2 = rad(lat2)
a = radlat1 - radlat2
b = rad(lng1) - rad(lng2)
Temp = Sqr(Sin(a / 2) ^ 2 + Cos(radlat1) * Cos(radlat2) * Sin(b / 2) ^ 2)
s = 2 * Atn(Temp / Sqr(-Temp * Temp + 1))     '没有反正弦函数,网上找了个
s = s * EARTH_RADIUS
GetDistance = s
End Function

Private Sub Command1_Click()
Text5.Text = Str(GetDistance(Val(Text1.Text), Val(Text2.Text), Val(Text3.Text), Val(Text4.Text)))
End Sub

Private Sub Command2_Click()
Text5.Text = Str((Sqr((Val(Text3.Text) - Val(Text1.Text)) ^ 2 + (Val(Text4.Text) - Val(Text2.Text)) ^ 2)) * 111.3199338)
End Sub

Private Sub Command3_Click()
Text5.Text = Str((Sqr((Val(Text3.Text) * 0.86 - Val(Text1.Text) * 0.86) ^ 2 + (Val(Text4.Text) - Val(Text2.Text)) ^ 2)) * 111.3199338)
End Sub



同纬度计算比较简单

A(60,30),B(60,90)两点之间,此段代码和我用余弦定理算出来的结果很一致。
余弦定理的步骤是:1、算A、B弦长:地球半径R*cos(经度差60)=R/2;
2、算角AOB,O为地球圆心,利用余弦定理,
cosAOB=(2R*R-(R/2)^2) /2*R*R=7/8;
3、弧AB的长为:R*arc cos(7/8);求毕



原理:

地球赤道上环绕地球一周走一圈共40075.04公里,而@一圈分成360°,而每1°(度)有60,每一度一秒在赤道上的长度计算如下:

  40075.04km/360°=111.31955km

  111.31955km/60=1.8553258km=1855.3m

  而每一分又有60秒,每一秒就代表1855.3m/60=30.92m

  任意两点距离计算公式为

  d=111.12cos{1/[sinΦAsinΦB十cosΦAcosΦBcos(λB—λA)]}

  其中A点经度,纬度分别为λA和ΦA,B点的经度、纬度分别为λB和ΦB,d为距离。


posted on 2008-02-28 15:18 Khan 阅读(16243) 评论(11)  编辑 收藏 引用 所属分类: GCC/G++跨平台开发Java周边技术

评论

# re: 通过两个点的经纬度计算距离  回复  更多评论   

公式不准
2008-07-10 09:51 | Mr.Fan

# re: 通过两个点的经纬度计算距离  回复  更多评论   

没对
2008-08-05 21:42 |

# re: 通过两个点的经纬度计算距离  回复  更多评论   

公式 d=111.12cos{1/[sinΦAsinΦB十cosΦAcosΦBcos(λB—λA)]} 肯定是错的:cos 的值在-1 到 1 之间,111.12cos{...} 其绝对值不超过111.12.
这个公式算出的结果意味着任意两点之间的距离小于111.12.
2008-09-23 22:58 | huang

# re: 通过两个点的经纬度计算距离  回复  更多评论   

没有参考价值
2009-08-27 15:28 | guoke

# re: 通过两个点的经纬度计算距离[未登录]  回复  更多评论   

public static void main(String args[]) {
double latA=rad(36.6),lngA=rad(116.4);
double latB=rad(36.7),lngB=rad(116.4);
//double d=111.12*Math.cos(1/(Math.sin(latA)*Math.sin(latB)+Math.cos(latA)*Math.cos(latB)*Math.cos(lngB-lngA)));
double d=2*Math.asin(Math.sqrt(Math.pow(Math.sin((latA-latB)/2), 2)+Math.cos(latA)*Math.cos(latB)*Math.pow(Math.sin((lngA-lngB)/2), 2)))*6378.137;
System.out.println(d);


}

private static double rad(double d){
return d * Math.PI / 180.0;
}
2009-12-18 10:32 | bo

# re: 通过两个点的经纬度计算距离  回复  更多评论   

请问返回的是千米吗?
2011-08-17 12:02 | 香香

# re: 通过两个点的经纬度计算距离  回复  更多评论   

这个是我的QQ 等楼主有空了 能告诉我一下吗
2011-08-17 12:03 | 香香

# re: 通过两个点的经纬度计算距离  回复  更多评论   

1608036033
2011-08-17 12:03 | 香香

# re: 通过两个点的经纬度计算距离[未登录]  回复  更多评论   

@huang
那个貌似是Asin 吧,怎么可能会只在在-1~1
2011-08-27 16:22 | 1

# re: 通过两个点的经纬度计算距离[未登录]  回复  更多评论   

@香香


最后经过一个 round 应该是千米 吧
2011-08-27 16:23 | 1

# re: 通过两个点的经纬度计算距离  回复  更多评论   

你好 ,我看过可以用两个标志物计算经纬度的
2011-10-12 23:26 | 洛丽塔

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理