GEOHash原理总结

GEOHash算法

经纬度范围

纬度:[90S, 90N] -> [-90, 90]
经度:[180W, 180E] -> [-180, 180]

编码示例

第一步:经纬度处理

以经纬度值:(116.389550, 39.928167)进行算法说明,对纬度39.928167进行逼近编码 (地球纬度区间是[-90,90])

  1. 区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定39.928167属于右区间[0,90],给标记为1
  2. 接着将区间[0,90]进行二分为 [0,45),[45,90],可以确定39.928167属于左区间 [0,45),给标记为0
  3. 递归上述过程39.928167总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167
  4. 如果给定的纬度x(39.928167)属于左区间,则记录0,如果属于右区间则记录1,序列的长度跟给定的区间划分次数有关,如下图

划分过程

第二步:合并经纬度处理结果

合并:偶数位放经度,奇数位放纬度,把2串编码组合生成新串如下图
合并经纬度处理结果

第三步:对合并结果进行base32编码

上面两步没啥疑问,但是在这一步,网上的各种资料给出的base32编码所省略的字母不同,比如有的说会是用字母A-Z和数字2-7,有的说是数字0-9,字母不要a,i,l,o,但是原理都一样,对合并结果每5个二进制位进行组合然后进行编码。例如这个示例中使用这个编码:
编码
然后对11100 11101 00100 01111 0000 01101转成十进制,对应着28、29、4、15,0,13 十进制对应的base32编码就是wx4g0e。这样一个经纬度坐标就变成了一个区域坐标(看精度,精度越高越准确,但是精度低也可以保护用户地址信息安全:
在这里插入图片描述
现在,对于整个地球来说分成了32个区域:
在这里插入图片描述
这是Geohash计算出的第一个字符对应的地区,每个地区应该也是按照32个区域继续划分。

GeoHash缺陷

如图所示,我们将二进制编码的结果填写到空间中,当将空间划分为四块时候,编码的顺序分别是左下角00,左上角01,右下脚10,右上角11,也就是类似于Z的曲线,当我们递归的将各个块分解成更小的子块时,编码的顺序是自相似的(分形),每一个子快也形成Z曲线,这种类型的曲线被称为Peano空间填充曲线。

这种类型的空间填充曲线的优点是将二维空间转换成一维曲线(事实上是分形维),对大部分而言,编码相似的距离也相近,但Peano空间填充曲线最大的缺点就是突变性,有些编码相邻但距离却相差很远,比如0111与1000,编码是相邻的,但距离相差很大。
在这里插入图片描述
除Peano空间填充曲线外,还有很多空间填充曲线,如图所示,其中效果公认较好是Hilbert空间填充曲线,相较于Peano曲线而言,Hilbert曲线没有较大的突变。但是由于Peano曲线实现更加简单,在使用的时候配合一定的解决手段,可以很好的满足大部分需求,因此TD内部Geohash算法采用的是Peano空间填充曲线。

在这里插入图片描述

GeoHash的特点

Geohash比直接用经纬度的高效很多,而且使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。

GeoHash用一个字符串表示经度和纬度两个坐标。在数据库中可以实现在一列上应用索引(某些情况下无法在两列上同时应用索引)

GeoHash表示的并不是一个点,而是一个矩形区域。

GeoHash编码的前缀可以表示更大的区域。例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。 这个特性可以用于附近地点搜索。

编码越长,表示的范围越小,位置也越精确。因此我们就可以通过比较GeoHash匹配的位数来判断两个点之间的大概距离。

判断点与多边形的关系

https://blog.csdn.net/okiwilldoit/article/details/118897109

计算

理解了geohash算法的基本原理之后,本节将介绍一个实际应用中常见的场景:计算围栏范围内所有的Geohash编码。该场景封装为函数可以表示如下:输入组成围栏的点经纬度坐标集合和指定的geohash长度,输出一组geohash编码。

    `public static Set getHashByFence(List points, int length)`

具体算法步骤如下:

  1. 输入围栏点坐标集合List points和指定的geohash长度length

  2. 计算围栏的外包矩形的左上角和右下角坐标lat_min、lat_max、lng_min、lng_max

  3. 根据lat_min、lat_max、lng_min、lng_max,计算外包矩形对角定点的距离d

  4. 以外包矩形中心点为圆心,以d/2为半径做一个圆,计算圆覆盖范围内的geohash

    4.1 获取圆的外包矩形左上角和右下角定点坐标经纬度,存储到double[] locs

    4.2 根据geohash字符长度计算该长度geohash编码对应的经纬度间隔(latA,lngA)

    4.3 根据latA和lngA,计算出locs组成的矩形的左上角和右下角定点的经纬度,在geohash划分的网格的索引(也就是第几个),分别记为lat_min,lat_max,lng_min,lng_max

    4.4 计算lat_min,lat_max,lng_min,lng_max对应范围内左右geohash的二进制编码,然后将经纬度二进制编码uncode为geohash字符编码,保存为Set sets

  5. 剔除sets中geohash编码对应矩形的中心点不在points围栏范围内的geohash,得到最终的geohash结果集

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值