Haversine公式的结果不同

时间:2012-02-25 17:01:39

标签: mysql geolocation geospatial geo

我正在使用mysql来计算接近度,为此我创建了一个名为distance的过程,如下所示但是该过程不能正常工作但是sql语句正在工作,所以这里有什么不同,因为我猜两个Haversine formulas但没有给我正确的结果。我真的don't know wht i am missing in formula one.

我的表的数据结构如下

公式一

id  varchar(100)    
userid  varchar(100)    
username varchar(100)
currLoc point           
radius  int(10)

表示公式二

id  varchar(30)
userid  varchar(30)
username varchar(40)
lat float(10,6)
lan float(10,6)
radius  varchar(100)

一级方程式: reference

sql statement to execute distance function

SELECT userid, username, distance(userstatus.currLoc, 
 GeomFromText('POINT(23.039574  72.56602)')) AS cdist 
    FROM userstatus HAVING cdist <= 0.6 ORDER BY cdist LIMIT 10


 RETURN 6371 * 2 *
    ASIN( SQRT(POWER(SIN(RADIANS(ABS(X(a)) - ABS(X(b)))), 2) + 
               COS(RADIANS(ABS(X(a)))) * COS(RADIANS(ABS(X(b)))) *
                    POWER(SIN(RADIANS(Y(a) - Y(b))), 2)));

公式二: reference

SELECT *,(((acos(sin((23.039574*pi()/180)) * 

        sin((lat *pi()/180))+cos((23.039574*pi()/180)) * 

         cos((lat *pi()/180)) * cos(((72.56602- lon)*pi()/180))))*

     180/pi())*60*1.1515*1.609344) as distance

FROM status HAVING distance <= 0.6

这里0.6是以公里为单位的半径

1 个答案:

答案 0 :(得分:3)

表达式的一个版本是使用ABS(X(a))等,而另一个版本则不是。使用ABS的人是可疑的。你不能忽视角度上的标志。你会在世界某些地区得到不同的结果(例如靠近赤道或本初子午线,或靠近两极)。

你的常数也不同。

60*1.1515*1.609344

VS

6371 * 2

一个表达涉及SQRT,另一个表示不涉及。

一个表达式涉及ASIN,另一个表达式使用ACOS。

两者之间基本上没有任何共同点......

参见维基百科'Haversine Formula'的讨论,特别是当点之间的距离很小时对数值稳定性的参考。

您还可以通过将您使用的公式分成几行来提高人们帮助您的机会。

例如:

 RETURN 6371 * 2 *
        ASIN( SQRT(POWER(SIN(RADIANS(ABS(X(a)) - ABS(X(b)))), 2) + 
                   COS(RADIANS(ABS(X(a)))) * COS(RADIANS(ABS(X(b)))) *
                        POWER(SIN(RADIANS(Y(a) - Y(b))), 2)));

(((acos(sin((23.039574*pi()/180)) * sin((lat *pi()/180)) +
        cos((23.039574*pi()/180)) * cos((lat *pi()/180)) *
        cos(((72.56602-lan)*pi()/180))
       )
   ) * 180/pi()) * 60 * 1.1515 * 1.609344)

后者引用'lan';那意味着'lon'?在第二个示例中,您似乎已将两个位置中的一个编码为23.039574°N和72.56602°W,而latlan来自SQL查询中的表。