我有一个名为 flags
的表,其中包含一个名为 coordinates
的列,该列充满了 MySQL“点”。我需要执行一个查询,根据半径为 100 米的经纬度位置获取圆圈内的所有标志。
从使用的角度来看,这是基于用户的位置。比如手机端会给出用户的经纬度位置,然后传给这部分API。然后由 API 在用户周围创建一个半径为 100 米的不可见圆圈,然后返回该圆圈中的标志。
这是 API 的这一部分,我不确定如何创建,因为我不确定如何使用 SQL 来创建这个不可见的圆并仅选择此半径内的点。
这可能吗?是否有 MySQL 空间函数可以帮助我做到这一点?
我相信 Buffer()
函数可以做到这一点,但我找不到任何关于如何使用它的文档(例如 SQL 示例)。理想情况下,我需要一个答案,告诉我如何使用这个功能或最接近它的功能。在我将这些坐标存储为地理空间点的地方,我应该使用地理空间函数来执行我要求的操作以最大限度地提高效率。
标志表:
- 编号
- 坐标
- 姓名
示例行:
1 | [几何 - 25B] |坚韧AB
对于标志表,我有纬度、经度位置以及东向和北向 (UTM)
用户的位置只是标准的纬度/经度,但我有一个可以将这个位置转换为 UTM 的库
最佳答案
MySQL 中没有支持纬度/经度距离计算的地理空间扩展函数。 There is as of MySQL 5.7 .
您要求地球表面的邻近圆。您在问题中提到您的 flags
表中的每一行都有纬度/经度值,还有 universal transverse Mercator (UTM) 几个不同 UTM zones 之一的预测值.如果我没记错我的 UK Ordnance Survey map ,UTM 可用于在这些 map 上定位项目。
计算 UTM 中同一区域中两点之间的距离是一件简单的事情:笛卡尔距离可以解决问题。但是,当点位于不同区域时,该计算不起作用。
因此,对于您问题中描述的应用程序,有必要使用 Great Circle Distance ,它是使用 haversine 或其他合适的公式计算的。
MySQL 增加了地理空间扩展,支持将各种平面形状(点、折线、多边形等)表示为几何图元的方法。 MySQL 5.6 实现了一个未记录的距离函数 st_distance(p1, p2)
。但是,此函数返回笛卡尔距离。所以它完全不适合基于纬度和经度的计算。在温带纬度地区,纬度对向的表面距离(南北)几乎是经度(东西)的两倍,因为纬度线在靠近两极的地方靠得更近。
因此,圆形邻近度公式需要使用真实的纬度和经度。
在您的应用程序中,您可以使用如下查询找到给定 latpoint,longpoint
十法定英里范围内的所有 flags
点:
SELECT id, coordinates, name, r,
units * DEGREES(ACOS(LEAST(1.0, COS(RADIANS(latpoint))
* COS(RADIANS(latitude))
* COS(RADIANS(longpoint) - RADIANS(longitude))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(latitude))))) AS distance
FROM flags
JOIN (
SELECT 42.81 AS latpoint, -70.81 AS longpoint,
10.0 AS r, 69.0 AS units
) AS p ON (1=1)
WHERE MbrContains(GeomFromText (
CONCAT('LINESTRING(',
latpoint-(r/units),' ',
longpoint-(r /(units* COS(RADIANS(latpoint)))),
',',
latpoint+(r/units) ,' ',
longpoint+(r /(units * COS(RADIANS(latpoint)))),
')')), coordinates)
如果要搜索20公里以内的点,修改这行查询
20.0 AS r, 69.0 AS units
以这个为例
20.0 AS r, 111.045 AS units
r
是您要搜索的半径。 units
是地球表面每度纬度的距离单位(英里、公里、弗隆,任何你想要的)。
此查询使用边界纬度/经度和 MbrContains
来排除绝对离起点太远的点,然后使用大圆距离公式生成剩余点的距离。一个explanation of all this can be found here .如果您的表使用 MyISAM 访问方法并具有空间索引,MbrContains
将利用该索引让您快速搜索。
最后,上面的查询选择了矩形内的所有点。要将范围缩小到仅圆圈中的点,并按接近程度对它们进行排序,请像这样包装查询:
SELECT id, coordinates, name
FROM (
/* the query above, paste it in here */
) AS d
WHERE d.distance <= d.r
ORDER BY d.distance ASC
关于mysql - 使用 MySQL 空间扩展来选择圆内的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21168380/