5

我有一个 MySQL 表,其中包含纬度、经度、用户 ID 和半径列。当用户提供他当前的位置(纬度,经度)以及半径时,我想查询表以根据两个半径为他提供重叠的位置。

例如,如果用户给我的纬度是 12.5;经度73.5,半径5英里;我应该能够检索两个半径重叠的 MySQL 表中的所有条目。

我最初的想法是为数据库中的每个 lat、long 创建一个边界框(基于半径),然后根据这个边界框查询传入的位置详细信息。这种方法正确吗?如果我走这条路,有什么我应该担心的吗?任何能指导我正确方向的帮助将不胜感激。

PS:下面的链接是我用作参考的。

http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates

4

2 回答 2

4

像这样的东西应该可以解决问题:

SELECT 
    *
FROM
    YOUR_TABLE
WHERE
    SQRT((input_lat - db_lat) * (input_lat - db_lat) + (input_long - db_long) * (input_long - db_long)) <= input_radius

我用这个:两点之间的距离

只有一件事:将半径转换为与坐标相同的单位

链接的内容(以防万一)

这个小操作计算两点之间的距离。该例程可以在任意数量的维度上工作,因此您可以将其冷应用到 2D 或 3D。

在 2D 中定义两个点。点 1 在 (x1, y1) 和点 2 在 (x2, y2)。

xd = x2-x1
yd = y2-y1
Distance = SquareRoot(xd*xd + yd*yd)

在 3D 中定义两个点。点 1 在 (x1, y1, z1) 和点 2 在 (x2, y2, z2)。

xd = x2-x1
yd = y2-y1
zd = z2-z1
Distance = SquareRoot(xd*xd + yd*yd + zd*zd)

如您所见,这需要您执行平方根。如果您想编写快速代码,应该像瘟疫一样避免平方根。仅在确实需要时才执行平方根。

避免平方根的方法:如果您不需要非常精确的距离,可以使用查找表来计算。

例如,如果您正在执行球体之间的碰撞检测,而您只想知道两个球体是否发生了碰撞,那么您就不需要使用平方根。只需更改一段代码

来自:如果 SquareRoot(xd xd + yd yd) < 直径

to: if (xd xd + yd yd) < (直径*直径)

于 2013-12-31T11:28:10.260 回答
1

那是欧几里得距离,而不是大圆距离,这是必须用来制作 5 英里半径的距离,因为这是地图使用的距离。用户离地球赤道越远,欧几里得距离对大圆的误差越大。

更好的解决方案是使用新的 mysql gis 函数,但它仍然会很慢,除非您执行子查询:找到最近的欧几里得(甚至曼哈顿)点,然后计算这些点的距离。

另外,请记住距离函数是单调的,因此您可以不用最终的平方根。

于 2015-12-30T18:49:11.810 回答