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


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

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

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

    GEOADD 添加地理信息元素

    介绍

    【语法】

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

    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"
    
    
    • 1
    • 2
    • 3

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

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

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

    介绍

    语法:

    GEODIST key member1 member2 [unit]
    
    • 1

    时间复杂度: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
    
    • 1
    • 2

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

    GEOPOS 返回地理空间的经纬度

    介绍

    【语法】

    GEOPOS key member [member ...]
    
    • 1

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

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

    测试

    返回键值为city的成员中hefei的经纬度
    geopos city hefei
    
    • 1
    • 2

    在这里插入图片描述

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

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

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

    介绍

    【语法】

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

    时间复杂度: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
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

    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
    
    • 1

    在这里插入图片描述

    常见的经纬度体系

    百度地图: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工具方法,使用方式也很简单,正确性也很可靠,也提高了我们开发效率。

  • 相关阅读:
    Matlab如何批量读取Excel数据?科研效率UpUp第3期
    Ps 在用鼠标滚轮缩放图片时,速度太快?
    Docker 轻量级可视化工具Portainer
    30岁之前一定要明白的道理
    Python技法:用re模块实现简易tokenizer
    四维曲面如何画?matlab
    si24r1/nrf24l01
    程序员5分钟,带你看完24岁60W年薪架构师的简历,上面竟然写着精通JVM
    XSS工具
    matlab神经网络训练方法,matlab神经网络训练图
  • 原文地址:https://blog.csdn.net/Octopus21/article/details/126108527