搜索范围纬度/经度坐标

Posted

技术标签:

【中文标题】搜索范围纬度/经度坐标【英文标题】:Search for range Latitude/Longitude coordinates 【发布时间】:2011-08-18 18:58:51 【问题描述】:

这个脚本有效,但我确信有更好的方法来解决这个问题。我已经尝试使用 mysql gis 功能存储它们,任何其他建议都会有所帮助。

$vicinity = .001;

$lat_ceiling = floatval($lat) + floatval($vicinity);
$lat_floor =  floatval($lat) - floatval($vicinity);
$lng_ceiling = floatval($lng) + floatval($vicinity);
$lng_floor =  floatval($lng) - floatval($vicinity);

$query = "SELECT * FROM `geolocations` WHERE".
            "`latitude` <= '".$lat_ceiling."' AND `latitude` >= '". $lat_floor ."' AND `longitude` <= '".$lng_ceiling."' AND `longitude` >= '". $lng_floor ."'  "; 

【问题讨论】:

告诉我们这段代码应该做什么。 这应该适用于小距离。 【参考方案1】:

您所做的某些版本是正确的,但我认为您可能想要使用实际的几何类型,特别是如果您在 MyISAM 上并且可以创建 R-Tree 空间索引。您可以拥有任何受支持类型的列(即pointpolygon),或包罗万象的geometry 类型:

mysql> create table spatial_table (id int, my_spots point, my_polygons geometry);
Query OK, 0 rows affected (0.06 sec)

然后用WKT语法查询更新:

mysql> insert into spatial_table values (1, GeomFromText('POINT(1 1)'), GeomFromText('POLYGON((1 1, 2 2, 0 2, 1 1))'));
Query OK, 1 row affected (0.00 sec)

mysql> insert into spatial_table values (1, GeomFromText('POINT(10 10)'), GeomFromText('POLYGON((10 10, 20 20, 0 20, 10 10))') );
Query OK, 1 row affected (0.00 sec)

然后您可以针对具有终止点 point1 = 经度 - 增量,经度 - 增量,y = 经度 + 增量,纬度 + 增量的线串的最小边界矩形进行查询(即附近),即此处带有 + - 1:

mysql> select * from spatial_table where MBRContains(GeomFromText('LINESTRING(9 9, 11 11)'), my_spots);
+------+---------------------------+-----------------------------------------------------------------------------------+
| id   | my_spots                  | my_polygons                                                                       |
+------+---------------------------+-----------------------------------------------------------------------------------+
|    1 |              $@      $@ |                    $@      $@      4@      4@              4@      $@      $@ |
+------+---------------------------+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

这将比在代表经度和纬度的一堆浮点数上执行算术要好得多。顺便说一句,在旧金山的位置,以下常量非常适合在公里和度经度和纬度之间进行转换(即,如果您想要圣克鲁斯的干净方形地图):

lonf 0.01132221938
latf 0.0090215040

也就是说,(x +- 2*lonf, y +- 2*latf) 为您的兴趣点周围 2 公里宽的男孩提供相关的 $lat_floor 等值。

【讨论】:

您知道地理扩展是否比使用我的方法更快或您自己计算空间索引?地理扩展用于索引坐标是什么? z曲线?希尔伯特曲线? R-Tree 空间索引和mysql MBRContains 的速成课澄清了很多。谢谢! 能否请您跟进我的下一个问题的答案。 ***.com/questions/7115106/… MyISAM 上的地理扩展是一个 R-Tree,不确定是 Hilbert R-Tree 还是其他东西——但如果你只是在 InnoDB 上添加一个空间索引,它实际上会给你一个 B-Tree,这对于查找单个点来说大多是可以的,而不是其他的。如果我要尝试推出自己的地理索引,为了简单起见,我可能会使用某种 geohash,我认为它的行为类似于你的上一个示例。 @bvmou:geohash 是 xkbd 使用的众所周知的算法,它是某种 z 曲线。我可以向您展示如何使用希尔伯特曲线和四键来获取不完整四键的所有位置。【参考方案2】:

我看不出你的做法有什么问题,但这可能会更干净一点:

SELECT *
FROM `geolocations`
WHERE
    `latitude` BETWEEN $lat - $vicinity AND $lat + $vicinity
    AND
    `longitude` BETWEEN $lng - $vicinity AND $lng + $vicinity

【讨论】:

【参考方案3】:

PostGIS 是 PostgreSQL 数据库的附加组件,用于管理地理数据。它有一个距离函数:http://postgis.refractions.net/documentation/manual-1.3/ch06.html#id2574517

【讨论】:

阅读会有所帮助:“我已经……尝试使用 MySQL gis 存储它们……任何其他建议都会有所帮助【参考方案4】:

如果您正在寻找 harvesine 公式的近似值,您可能想要使用空间索引或空间填充曲线。 sfc 是一种四叉树和类似分形的数据结构,将 2d 复杂度降低到 1d 复杂度。这是一条完全填充空间的曲线,也是一种细分地图的巧妙算法。除了计算索引,您还可以嵌套图块并累积一个四键并使用标准 mysql 字符串运算符在此键中搜索。例如,如果您有一个四键 11111222233334444,您可以搜索 1111* 以查找此节点及其下方或右侧的所有键 => 位置对。

【讨论】:

以上是关于搜索范围纬度/经度坐标的主要内容,如果未能解决你的问题,请参考以下文章

检查经纬度列表是不是在范围内

MySQL选择范围内的坐标

计算半径内的 100 英里

计算指定区域的经纬度范围

sql怎么将一系列点经纬度坐标匹配到某市

百度地图 移动坐标显示该坐标周围对应的信息