已知两个点的经纬度,计算两个点之间的距离(两种办法) 您所在的位置:网站首页 求纬度长度的公式 已知两个点的经纬度,计算两个点之间的距离(两种办法)

已知两个点的经纬度,计算两个点之间的距离(两种办法)

2024-07-16 18:17| 来源: 网络整理| 查看: 265

网上淘来了两种办法,一种是haversine公式,

另一种算法,是求球面两点连线弧长的夹角,然后求出弧长

方法:

#include "math.h" #include "stdio.h" #include "stdlib.h" #include "unistd.h" static double HaverSin(double theta) { double v = sin(theta / 2); return v * v; } //haversine公式 static double Distance(double lata,double loga, double latb,double logb) { double EARTH_RADIUS = 6371.0; double PI = 3.14; double dis = 0; double lat_a = 0.0; double lat_b = 0.0; double log_a = 0.0; double log_b = 0.0; //用haversine公式计算球面两点间的距离。 //转弧度 lat_a = lata * PI / 180; lat_b = latb * PI / 180; log_a = loga * PI / 180; log_b = logb * PI / 180; //差值 double vLon = fabs(log_a - log_b); double vLat = fabs(lat_a - lat_b); //h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。 double h = HaverSin(vLat) + cos(lat_a) * cos(lat_b) * HaverSin(vLon); dis = 2 * EARTH_RADIUS * asin(sqrt(h)); return dis; } // static double Distance2(double lata, double loga, double latb, double logb) { double EARTH_RADIUS = 6371.0; double PI = 3.14; double distance = 0.0; double lat_a = 0.0; double lat_b = 0.0; double log_a = 0.0; double log_b = 0.0; //转弧度 lat_a = lata * PI / 180; lat_b = latb * PI / 180; log_a = loga * PI / 180; log_b = logb * PI / 180; double dis = cos(lat_b) * cos(lat_a) * cos(log_b -log_a) + sin(lat_a) * sin(lat_b); distance = EARTH_RADIUS * acos(dis); return distance; } int main(void) { while(1) { double distance = 0; distance = Distance(-35.468245, -110.459545, 35.467873, 110.459519);//16326.509 printf("distance: %lf\n",distance); distance = Distance(35.468245, 110.459545, -35.467873, 110.459519);//7882.759 printf("distance: %lf\n",distance); distance = Distance(43, 28, 88, 62);//5042.73 printf("distance: %lf\n",distance); distance = Distance(28, 43, 62, 88);//4998.83 printf("distance: %lf\n",distance); distance = Distance(22.535562, 113.946085, 22.535562, 113.9461);//0.002 printf("distance: %lf\n",distance); distance = Distance(22.535562, 113.946085, 22.535562, 113.946);//0.009 printf("distance: %lf\n",distance); distance = Distance(23.70281595, 117.1759528, 23.70507779,117.2345917);//5.975 printf("distance: %lf\n",distance); distance = Distance(23.70281595, 117.1759528, 2, 2);//12457.64 printf("distance: %lf\n",distance); distance = Distance(30.05, 106.1667, 29.15344, 104.6143);//180.169 printf("distance: %lf\n",distance); distance = Distance(28.86483, 121.1463, 28.86444, 121.1455);//0.089 printf("distance: %lf\n",distance); distance = Distance(43.5645, 81.9229, 43, 91);//737.045 printf("distance: %lf\n",distance); distance = Distance(37.48, 29.09, 36, 35);//551.593 printf("distance: %lf\n\n",distance); distance = Distance2(-35.468245, -110.459545, 35.467873, 110.459519);//16326.509 printf("distance: %lf\n",distance); distance = Distance2(35.468245, 110.459545, -35.467873, 110.459519);//7882.759 printf("distance: %lf\n",distance); distance = Distance2(43, 28, 88, 62); printf("distance: %lf\n",distance); distance = Distance2(28, 43, 62, 88); printf("distance: %lf\n",distance); distance = Distance2(22.535562, 113.946085, 22.535562, 113.9461); printf("distance: %lf\n",distance); distance = Distance2(22.535562, 113.946085, 22.535562, 113.946); printf("distance: %lf\n",distance); distance = Distance2(23.70281595, 117.1759528, 23.70507779, 117.2345917); printf("distance: %lf\n",distance); distance = Distance2(23.70281595, 117.1759528, 2, 2); printf("distance: %lf\n",distance); distance = Distance2(30.05, 106.1667, 29.15344, 104.6143); printf("distance: %lf\n",distance); distance = Distance2(28.86483, 121.1463, 28.86444, 121.1455); printf("distance: %lf\n",distance); distance = Distance2(43.5645, 81.9229, 43, 91); printf("distance: %lf\n",distance); distance = Distance2(37.48, 29.09, 36, 35); printf("distance: %lf\n\n",distance); //sleep(3); break; } return 0; }

ubuntu测试结果:

ning@ning-virtual-machine:~/proj/harversin$ g++ harversin.c ning@ning-virtual-machine:~/proj/harversin$ ./a.out distance: 16345.841375 distance: 7883.737691 distance: 5041.292612 distance: 4997.779018 distance: 0.001540 distance: 0.008726 distance: 5.973073 distance: 12452.776520 distance: 180.105172 distance: 0.089125 distance: 736.971269 distance: 551.462296 distance: 16345.841375 distance: 7883.737691 distance: 5041.292612 distance: 4997.779018 distance: 0.001543 distance: 0.008727 distance: 5.973073 distance: 12452.776520 distance: 180.105172 distance: 0.089125 distance: 736.971269 distance: 551.462296

方法一 根据2个经纬度点,计算这2个经纬度点之间的距离(通过经度纬度得到距离) - 莫水千流 - 博客园

球面上任意两点之间的距离计算公式可以参考维基百科上的下述文章。

Great-circle distanceHaversine formula

值得一提的是,维基百科推荐使用Haversine公式,理由是Great-circle distance公式用到了大量余弦函数, 而两点间距离很短时(比如地球表面上相距几百米的两点),余弦函数会得出0.999...的结果, 会导致较大的舍入误差。而Haversine公式采用了正弦函数,即使距离很小,也能保持足够的有效数字。 以前采用三角函数表计算时的确会有这个问题,但经过实际验证,采用计算机来计算时,两个公式的区别不大。 稳妥起见,这里还是采用Haversine公式。

其中

R为地球半径,可取平均值 6371km;φ1, φ2 表示两点的纬度;Δλ 表示两点经度的差值。

根据2个经纬度坐标,距离计算函数

公式来历:

VERSINE(F)=1-cos(F)

Haversine名字来历是Ha-VERSINE,即Half-Versine ,表示sin的一半的意思。

hav(A) = (1-cos(A))/2 = sin(A/2)* sin(A/2)

推倒过程:

如下一个半径为1 的圆,O是圆心,A、B是弦(chord)。角度AOB=theta。则角度AOC=theta/2。OC是垂直于AB的垂线(perpendicular)。AC长度是sin(theta/2),AB长度是2*sin(theta/2)。

(图1)

如下地球图所示,假设半径R为1,O是球心,A (lat1,lon1) 和 B (lat2,lon2) 是我们感兴趣的2个点。2跟经度线 lon1,lon2相交于北极(north pole)N。EF所在的线是赤道(equator)。ACBD是平面上的等腰梯形的四个顶点(vertice)。AC和DB的弦(直线)在图上没有画出。CD的位置是:C (lat2,lon1) and D (lat1,lon2)。角度AOC是A点与C点的纬度差 dlat。角度EOF是经度E点和经度F点的差dlon。

(图2)

弦AC的长度,参照图1的方式,那么是AC=2*sin(dlat/2),弦BD也是一样的长度。

E、F 2个点是赤道上的2个点,它们的纬度是0。EF的距离是EF=2*sin(dlon/2)

A、D2个点所在的纬度是lat1。AD所在纬度的圆平面的半径是cos(lat1)。从A作一条垂线(perpendicular)到OE为AG,AO是球半径,则OG=cos(lat1),即A、D所在纬度圆圈的半径(AO`)。

这时候,AD的弦长AD= 2*sin(dlon/2)*cos(lat1),类似的可以推出CB的长度= CB=2*sin(dlon/2)*cos(lat2)

下面看一下如何求AB的长度,回到平面等腰梯形,如下图:

(图3)

AH是到CB的垂线(perpendicular),CH= (CB-AD)/2。

根据勾股定理(Pythagorean theorem): 【^2表示2的平方】

AH^2 = AC^2 - CH^2

       = AC^2 - (CB-AD)^2/4

HB 的长度是HB=AD+CH = AD+(CB-AD)/2 = (CB+AD)/2,根据勾股定理得到:

  AB^2 = AH^2 + HB^2

       = AC^2 - (CB-AD)^2/4 + (CB+AD)^2/4

       = AC^2 + CB*AD

根据前面球面上的求经纬距离的方式,我们已经得到 AC、AD和CB的长度,代入公式得到:

  AB^2 = 4*(sin^2(dlat/2) + 4*cos(lat1)*cos(lat2)*sin^2(dlon/2))

假设中间值h 是AB长度一半的平方,如下

  h = (AB/2)^2

    = (sin^2(dlat/2)) + cos(lat1) * cos(lat2) * sin^2(dlon/2)

  (请参看代码里的h)

最后一步,是求得代表AB长度的角度AOB。参照图1的方式,我们可以知道

(图4)

设AC=

,根据勾股定理(Pythagorean theorem)得到:

OC= 

= sqrt(OA^2 - AC^2)

         = 

= sqrt(1-a)   // sqrt表示开根号

如果设c是角AOB的度数值。

tan(



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有