计算Cython中两个geoCode之间的距离

时间:2015-09-02 03:54:39

标签: python c google-maps geocoding cython

我的网络服务目前从google API检索地址的geoCodes。比较两个geoCode之间的距离时,我试图使用此处描述的算法http://andrew.hedges.name/experiments/haversine/ 不幸的是,它返回了不准确的值。

我有两个版本

cdef double M_PI = 3.141592653589793;
cdef double rads = (180/M_PI)

cdef double lon1 = a.geoCode[1];
cdef double lon2 = b.geoCode[1];

cdef double lat1 = a.geoCode[0];
cdef double lat2 = b.geoCode[0];

cdef double dlat = lon2 - lon1
cdef double dlon = lat2 - lat1

cdef double x  = (pow(sin(dlat/2),2)) + cos(lat1)*cos(lat2)*pow(sin(dlon/2),2);

cdef double c = 2.0 * atan2(sqrt(x), sqrt(1-x));

cdef double d = 6370.0 * c;

return d

处理的值的一个示例是

lat lon a 38.898556 -77.037852
lat lon b 38.897147 -77.043934
Difference in lat -0.00608199999999
Difference in long -0.001409
x 9.31324375062e-06
sqrt(x) 0.00305176076235
sqrt(1-x) 0.999995343367
atan2(sqrt(x),sqrt(1-x)) 1.5677445613
c 0.00610353099867
distance in kiloemters 38.8794924615

cdef double M_PI = 3.141592653589793;
cdef double rads = (180/M_PI)

cdef double lon1 = a.geoCode[1]*rads;
cdef double lon2 = b.geoCode[1]*rads;

cdef double lat1 = a.geoCode[0]*rads;
cdef double lat2 = b.geoCode[0]*rads;

cdef double dlat = lon2 - lon1
cdef double dlon = lat2 - lat1

cdef double x  = (pow(sin(dlat/2),2)) + cos(lat1)*cos(lat2)*pow(sin(dlon/2),2);

cdef double c = 2.0 * atan2(sqrt(x), sqrt(1-x));

cdef double d = 6370.0 * c;
return d

进程

lat lon a 2228.72308795 -4413.94378235
lat lon b 2228.6423582 -4414.29225528
Difference in lat -0.348472930998
Difference in long -0.0807297533338
x 0.0301717372754
sqrt(x) 0.173700136083
sqrt(1-x) 0.984798589928
atan2(sqrt(x),sqrt(1-x)) 1.39621064139
c 0.349171370807
distance in kiloemters 2224.22163204

问题是实际答案应该是0.549 km

我不确定我的做法与此公式不同

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 R is the radius of the Earth) 

1 个答案:

答案 0 :(得分:0)

我认为弧度转换是反转的(180 /π而不是π/ 180)。其余的似乎没问题。

我在我的应用程序中使用以下代码,结果很好(它是Objective-C,但类似):

// Credit:
// http://www.movable-type.co.uk/scripts/latlong.html

double R = 6371000; // metres
double phi1 = lat1 * M_PI / 180.0;
double phi2 = lat2 * M_PI / 180.0;
double deltaphi = (lat2-lat1) * M_PI / 180.0;
double deltalambda = (long2-long1) * M_PI / 180.0;

double a = sin(deltaphi/2) * sin(deltaphi/2) +
    cos(phi1) * cos(phi2) *
    sin(deltalambda/2) * sin(deltalambda/2);
double c = 2 * atan2(sqrt(a), sqrt(1.0 - a));
double d = R * c;
return d;

我的代码不使用pow()但是你的代码在这方面是正确的,因为它避免了多余的sin()计算。