关于地图GIS的一次实践整理(下) Redis的GIS实践

【上一篇文章地址:】 关于地图GIS开发事项的一次实践整理(上)

Redis的中关于Gis地图工具实践

Redis的中关于Gis地图工具主要在Geo命令中
在这里插入图片描述

GEOADD 添加地理信息元素

介绍

【语法】

GEOADD key longitude latitude member [longitude latitude member ...]

geoadd keyName 经度1 纬度1 第一个坐标名称 经度2 纬度2 第二个坐标名称

【描述】
时间复杂度:每一个元素添加是O(log(N)) ,N是sorted set的元素数量。

将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。

该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:

有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
当坐标位置超出上述指定范围时,该命令将会返回一个错误。

测试
添加key名称为city,包含合肥和上海的坐标信息的数据
geoadd  city 117.233279 31.827974 "hefei" 121.480922  31.232054 "shanghai"

它的底层数据是使用sorted set,那么我们就可以通过sorted set的相关命令
【查看添加的数据】

查询键名称为city的全部数据,-1表示最后一位
zrange city 0  -1

GEODIST 返回两个给定位置之间的距离

介绍

语法:

GEODIST key member1 member2 [unit]

时间复杂度:O(log(N))
功能描述:返回两个给定位置之间的距离。

【说明】
如果两个位置之间的其中一个不存在, 那么命令返回空值。
指定单位的参数 unit 必须是以下单位的其中一个:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。

GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

测试
geoadd  city 117.233279 31.827974 "hefei" 121.480922  31.232054 "shanghai"
geodist city  hefei shanghai

在这里插入图片描述
单位是米,换算是KM大约400多千米

GEOPOS 返回地理空间的经纬度

介绍

【语法】

GEOPOS key member [member ...]

【描述】
时间复杂度:O(log(N))
从key里返回所有给定位置元素的位置(经度和纬度)。

给定一个sorted set表示的空间索引,密集使用 geoadd 命令,它以获得指定成员的坐标往往是有益的。当空间索引填充通过 geoadd 的坐标转换成一个52位Geohash,所以返回的坐标可能不完全以添加元素的,但小的错误可能会出台。
因为 GEOPOS 命令接受可变数量的位置元素作为输入, 所以即使用户只给定了一个位置元素, 命令也会返回数组回复。

测试
返回键值为city的成员中hefei的经纬度
geopos city hefei

在这里插入图片描述

返回键值为city的成员中hefei和shanghai的经纬度
geopos city hefei shanghai

在这里插入图片描述
【注意】:我们存储的经纬度和geopos返回的经纬度可能存在一些微小的偏差,需要注意,一般不影响实际的使用,除非要求高精度。
在这里插入图片描述

GEORADIUS 查询指定半径内所有的地理空间元素的集合
介绍

【语法】

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]  [asc| desc]

时间复杂度:O(N+log(M))
以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

范围可以使用以下其中一个单位:

m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
在给定以下可选项时, 命令会返回额外的信息:

WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
WITHCOORD: 将位置元素的经度和维度也一并返回。
WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:

ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。
DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。
在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。

测试

这里我以合肥高新区蜀西湖为测试中心点,选择几个周围的点进行测试。
在这里插入图片描述

// 存储测试数据
geoadd  region  117.130313 31.84504 "shuxihu"  117.143635 31.838962 "chanyeyuan"  117.143635 31.838962 "shiyanxiaoxue"  117.123423 31.842912 "aolai"  117.207504 31.879882 "zhiwuyuan" 

// 查询距离117.130313 31.84504半径1000米地点信息
georadius region 117.130313 31.84504 1000 m

在这里插入图片描述
下面使用下可选参数

// 查询指定坐标表半径范围10KM范围内数据,并展示距离、坐标、并按照距离由由近到远排序,只显示前3个
georadius region 117.130313 31.84504 10 km  WITHDIST WITHCOORD   count 3  asc

GEORADIUSBYMEMBER 查询指定半径内匹配到的最大距离的一个地理空间元素

介绍

【语法】
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

时间复杂度:O(N+log(M))

这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。
简单来说两个区别就是一个根据任意的经纬度坐标查询,一个根据已录入的坐标点关联名称来查询
指定成员的位置被用作查询的中心。

测试

继续使用刚才的数据,将命令修改为georadiusbymember ,并将中心点经纬度修改为已保存的成员名称,其他参数一样

georadiusbymember region  shuxihu 10 km  WITHDIST WITHCOORD   count 3  asc

在这里插入图片描述

常见的经纬度体系

百度地图:BD09
腾讯地图:GCJ02
高德地图:GCJ02
谷歌中国地图:GCJ02
微信小程序地图:GCJ02

不同只是只是坐标系不一样,高德,是gcj-02,百度是在gcj-02的基础上再加密,谷歌是wgs84就是原始gps坐标。
WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
GCJ02:又称火星坐标系,是由中国国家测绘局制定的地理坐标系统,是由WGS84加密后得到的坐标系。
BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标

GeoHash核心原理解析

参考:

https://www.cnblogs.com/LBSer/p/3310455.html

小结

【1】注意所构建的几何图形是否需要考虑边线和顶点的问题,在很多的实现中默认是不把顶点包括在图形范围内的,需要注意。
【2】使用AWT绘图工具辅助实现一定要注意提供数据的顺序问题。建议使用AWT先在面板上绘制出对应的图形样式,先预览下,确保没有问题。
【3】不仅仅是针对AWT使用注意顺序问题,使用其他算法实现也是如此。
【4】精力有限,关于MySQL和ElasticSearch两个常用数据库的GIS实践就没有尝试了,当然也是因为目前没有更多的工作方面应用,暂不需要过多的实践,只需要了解到有这样组件,在后面有相应的场景再去实践了解下。
【5】使用合适的工具或者算法去解决问题,比如附近的人类似的需求,这种就完全可以利用redis的GEORADIUS命令帮我们实现。
【6】对于经纬度的使用需要注意各个平台标准差异,需要根据实际情况进行转换。
【7】对于基于关系型数据库的经纬度检索和计算,如果数据量很大的话,那么处理效率就会很低,那么对于这种情况就可以参考GeoHash算法优化地图地点的检索,上面的介绍的Redis就是基于这种方式实现的。
【8】对于一些前端方面的几何计算,可以参考或直接使用百度或者高德提供的API工具方法,使用方式也很简单,正确性也很可靠,也提高了我们开发效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZWZhangYu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值