1. 简介
地理位置(经纬度坐标对)编码为字母数字串,将空间分为网格形状每个网格使用一个编码,是Z阶曲线的众多应用之一。
2. 编码原理
(1) 首先根据区域划分的精度大小选择Geohash的字符串的长度,合理将地图网格化;
(2) 将经纬度进行二分法编码,得到符合精度要求的二进制结果;
(3) 按照奇数位置放经度,偶数位置放纬度的规则,生成新的字符串,根据从左到右的顺序,每5位二进制数字转换为十进制数字,最后按照Geohash字母映射表,将十进制数字转换为Geohash字符串完成编码。
2.1 选择合适的字符串长度将地图网格化
Geohash的字符串长度可以表示区域的精度,字符串长度越长表示的区域范围越小,精度更高,误差更小,Geohash能够提供任意精度的分段级别。一般分级从1-12级。
一旦选定 cell (矩形区域的精度)的宽和高,那么 Geohash 字符串的长度就确定下来了。这样就可以把地图分成了一个个的矩形区域。选定Geohash字符串的长度后,根据下表可知,经纬度所对应的二进制的位数也是确定的。
2.2 经纬度二分编码
假设选取字符串长度为6的矩形来网格化某张地图,已知的经纬度是[31.1932993, 121.43960190000007],利用二分法,纬度[-90,90],经度[-180,180]逐渐二分,根据1分配右区间,0分配左区间的原则,以此类推,直到精度符合要求为止,将经纬度编码为二进制,具体的操作步骤如下:
先处理纬度。地球的纬度区间是[-90,90]。把这个区间分为2部分,即[-90,0),[0,90]。31.1932993位于(0,90]区间,即右区间,标记为1。然后继续把(0,90]区间二分,分为[0,45),[45,90],31.1932993位于[0,45)区间,即左区间,标记为0。一直划分下去。
再处理经度,一样的处理方式。地球经度区间是[-180,180]
2.3 交叉混合进行base32编码
纬度产生的二进制是101011000101110,经度产生的二进制是110101100101101,按照“奇数位放经度,偶数位放纬度”的规则,(经度纬度经度纬度…)重新交叉组合经度和纬度的二进制串,生成新的二进制串:111001100111100000110011110110,最后一步就是把这个最终的字符串转换成字符,对应需要查找 base-32 的表。每5位二进制映射为1个十进制数字,11100 11001 11100 00011 00111 10110转换成十进制是 28 25 28 3 7 22,查下表,编码得到最终结果,wtw37q。
(用0-9、b-z(去掉a, i, l, o)这32个字母和数字进行base32编码。)
3. 优缺点
3.1 优点
(1)利用Z阶曲线进行编码。而Z阶曲线可以将二维或者多维空间里的所有点都转换成一维曲线。并且 Z 阶曲线还具有局部保序性。
(2)利用前缀匹配,提高查询搜素效率。两个geohash编码之间的公共前缀越长,在空间越接近。反之不一定成立,在空间上接近,公共前缀可能短。
(3)编码得到的结果是一个矩形网格区域范围,有助于隐私保护。
3.2 缺点
由于Z阶曲线的特性,如果选择不好合适的网格大小,在边缘场景进行邻近点匹配搜索时容易出错,
解决办法:把这个网格周围8个网格的geohash编码都计算出来,将周围八个矩形块范围内的点同时检索出来,再根据实际的相对距离进行过滤。
4. 几何表示
Z阶曲线:下图中标注出来的蓝色的点点。每两个点虽然是相邻的,但是距离相隔很远。看右下角的图,两个数值邻近红色的点两者距离几乎达到了整个正方形的边长。两个数值邻近绿色的点也达到了正方形的一半的长度。
Z阶曲线与经纬度的对应
5. 参考资料
维基百科:
https://en.wikipedia.org/w/index.php?title=Geohash&oldid=121182075
geohash和s2,空间填充曲线:
https://halfrost.com/go_spatial_search/#toc-1
Geohash编码:https://zhuanlan.zhihu.com/p/386445188#:~:text=GeoHash%E4%BD%9C,%E4%B8%AA%E7%BC%96%E7%A0%81%E8%BF%9B%E8%A1%8C%E8%A1%A8%E7%A4%BA%E3%80%82
GeoHash原理以及代码实现:
https://blog.csdn.net/qq_43777978/article/details/116426235