获取地球上两个坐标之间的距离

Get distance between 2 coordinates on globe

我尝试使用 here

中的公式计算两个坐标之间的距离

坐标为1.5378236000、110.3372347000和1.5395056000、110.3373156000。

不知何故,结果大不相同。我相信 "dist1" 在 KM 中,但不确定 "dist2"。

select 6371 * acos( cos( radians(1.5378236000) ) * cos( radians( 1.5395056000 ) ) * 
cos( radians( 1.5378236000 ) - radians(110.3373156000) ) 
+ sin( radians(1.5378236000) ) * sin( radians( 1.5395056000 ) ) ) AS dis1,
GetDistance(1.5378236000, 110.3372347000, 1.5395056000, 110.3373156000) as dis2 

结果 dist1: 12091.536526805385
dist2: 0.11190

获取距离函数

CREATE DEFINER=`root`@`localhost` FUNCTION `GetDistance`(
 lat1  numeric (9,6),
 lon1  numeric (9,6),
 lat2  numeric (9,6),
 lon2  numeric (9,6)
) RETURNS decimal(10,5)
    READS SQL DATA
BEGIN
/* http://www.codecodex.com/wiki/Calculate_distance_between_two_points_on_a_globe#MySQL */
  DECLARE  x  decimal (20,10);
  DECLARE  pi  decimal (21,20);
  SET  pi = 3.14159265358979323846;
  SET  x = sin( lat1 * pi/180 ) * sin( lat2 * pi/180  ) + cos(
 lat1 *pi/180 ) * cos( lat2 * pi/180 ) * cos(  abs( (lon2 * pi/180) -
 (lon1 *pi/180) ) );
  SET  x = acos( x );
  RETURN  ( 1.852 * 60.0 * ((x/pi)*180) ) / 1.609344;
END

第一个函数获取长距离(如果你绕地球走很远的距离)

第二个是抄近路的距离。

看那两个点,离的很近。这就像环游世界只是为了过马路。 :D

第二个距离仍然以公里为单位,只是很短。地球的周长刚刚超过 12,000 公里。

这是准确的方法

    public static double elongation(double longitude1, double latitude1, 
            double longitude2, double latitude2)
    {
        return Math.Acos(1 - 2 * (hav(latitude1 - latitude2)
            + Math.Cos(RAD * latitude1) * math.Cos(RAD * latitude2)
            * hav(longitude1 - longitude2))) / RAD;
    }

当函数 "hav" 为

    static public double hav(double x)
    {
        return 0.5 - 0.5 * Math.Cos(RAD * x);
    }

你的第一个表达式有错误。您正在计算纬度和经度之间差异的余弦值。在那个术语中,您应该计算起始经度和结束经度之间的差异。

用于计算纬度和经度点对之间距离的余弦定律(或半正弦)公式是这样的:

   DEGREES(ACOS(COS(RADIANS(lat1)) * COS(RADIANS(lat2)) *
                COS(RADIANS(long1) - RADIANS(long2)) +
                SIN(RADIANS(lat1)) * SIN(RADIANS(lat2))))

这会产生以度为单位的结果。

你问题中的第一个表达式采用这种形式。如您所见,您的公式正确,但您插入的参数不正确。

 6371 * acos( cos( radians(lat1)) * cos( radians( long1 )) * /*should be lat1, lat 2*/
              cos( radians( lat1) - radians(long1 ))         /*should be long1,long2*/
              sin( radians(lat1) ) * sin( radians(long2 )))  /*should be lat1, lat2 */

您的第一个点似乎位于马来西亚古晋,就在 Green 街和 Ahmad Zaidi 街交界处的南边。第二点是那里以北的一个街区。 (根据你的第二个结果,它在北边大约 112m)。请注意,我编写的距离公式以弧度为单位。你给它 lat/long 度数点,它 returns 度数距离。为了将度数转换为千米(一种更有用的测量方法),您需要知道每度有多少千米。

请注意,您的公式版本包含幻数 6371。这会将 ACOS() 函数产生的弧度转换为度数,然后转换为千米,使用常数 111.195 公里/度。这是一个可接受的值;地球在赤道处有点凸起。

此外,您的存储函数在同一术语中有一个不必要的 ABS。由于十进制运算,它的效率也非常低。 MySQL 使用 DOUBLE(ieee 64 位浮点数)算法进行所有计算,但它的编码方式需要大量浪费且可能会丢失精度的来回十进制转换。

如果您使用的是商业级 GPS 坐标,32 位 FLOAT 算法就足够精确了。

这是对此 material 的详尽解释。 http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/