写在前边
复制的一个内部分享,所以可能更偏向PPT性质,本文提出的问题,在末尾参考材料中都会有所提及,包括更深层次的实现原理和各大API对于GeoHash的优化。感兴趣的读者可以拓展看一下。
START
GeoHash是一种地址编码,可以将二维的经纬度编码成遵循“最左匹配原则”的字符串,在LBS(Location Based Services)服务中具有非常广泛的用途。
一、坐标系
经纬度🌏
- 经度:
-
- 0°经线:本初子午线
- 东经:0~180°
- 西经:0~180°
- 纬度:
-
- 北纬:0~90°
- 南纬:0~90°
- 纬度相同的情况下
-
- 经度每隔0.00001度,距离相差约1米;
- 每隔0.0001度,距离相差约10米;
- 每隔0.001度,距离相差约100米;
- 每隔0.01度,距离相差约1000米;
- 每隔0.1度,距离相差约10000米。
- 经度相同的情况下
-
- 纬度每隔0.00001度,距离相差约1.1米;
- 每隔0.0001度,距离相差约11米;
- 每隔0.001度,距离相差约111米;
- 每隔0.01度,距离相差约1113米;
- 每隔0.1度,距离相差约11132米。
地理坐标系
定义
是一种利用三度空间的球面来定义地球上的空间的球面坐标系统,能够标示地球上的任何一个位置。
单位
经纬度,如:东方明珠电视塔的经纬度是121.499718,31.239698
分类
- 大地水准面
-
- 用平静的海面描述地球
- 地心坐标系
-
- 以地球质心为旋转椭球面的中心的坐标系
- 参心坐标系:挪移质心,使局部的表面与某一地区的地形更加吻合。
- 投影坐标系:地理坐标系按照一定的数学法则将地球椭球面的经纬网投影到平面上,称为投影坐标系。
常见的地理坐标系
名称 | 简介 | 应用范围 |
WGS-84坐标系 | World Geodetic System-1984,既1984年的全球坐标系统。是目前应用最为广泛的坐标系统,只要跟GPS定位相关,使用的都是WGS84坐标系. | GPS、谷歌、OSM、前端脚本库(leaflet、mapbox、openlayer) |
CGCS2000坐标系 | 2000国家大地坐标系,是我国当前最新的国家大地坐标系。非高精度的大多数情况下,我们可以认为WGS84坐标系=CGCS2000坐标系。 | |
GCJ02 火星坐标系 | 为了数据安全和保密,通过地形图非线性保密处理算法(俗称火星加密)加密过的WGS84坐标系,与WGS84坐标系之间的偏差大概在50-700m左右。 | 国内大部分地图底图(高德、腾讯)和矢量数据(图商的LBS服务和Android手机的定位数据) |
BD09坐标系 | 百度地图使用的地心坐标系,在GCJ02的基础上,做了二次加密。 | 百度地图 |
小工具⚙️
地图坐标系转换 - 在线工具
高德地图API
二、设计题👀
某APP和某品牌签订了广告合同,要求如下:
双11期间,用户打开APP时,如果当前定位所在地附近3公里内有品牌体验门店存在,开屏广告展示该品牌的广告素材。
相关信息:
- 全国100家品牌体验店的经纬度信息(火星坐标系);
- 开屏广告素材;
请给出你的设计思路:
... ...
进阶:假如门店数量达到1000、1W、10W。现有的设计会有什么问题,怎么解决?
尝试设计一个适用于此类场景,数据检索的索引?
三、GeoHash
是什么?空间索引Base32
GeoHash是一种地址编码,可以将二维的经纬度编码转换成一维字符串,每一个字符串代表了一块矩形区域,表示某一个点的大概位置。该区域内所有的点共享相同的GeoHash。
算法
1.切分区间
以纬度为例,按照初始区间范围纬度[-90,90],分为左右区间,计算目标纬度分别落在左区间还是右区间,左0右1;
循环上述步骤
序号 | 纬度范围 | 编码:0 | 编码:1 | 31.239698的区间编码 |
1 | (-90, 90) | (-90, 0.0) | (0.0, 90) | 1 |
2 | (0.0, 90) | (0.0, 45.0) | (45.0, 90) | 0 |
3 | (0.0, 45.0) | (0.0, 22.5) | (22.5, 45.0) | 1 |
4 | (22.5, 45.0) | (22.5, 33.75) | (33.75, 45.0) | 0 |
5 | (22.5, 33.75) | (22.5, 28.125) | (28.125, 33.75) | 1 |
6 | (28.125, 33.75) | (28.125, 30.9375) | (30.9375, 33.75) | 1 |
7 | (30.9375, 33.75) | (30.9375,32.34375) | (32.34375,33.75) | 0 |
8 | (30.9375,32.34375) | (30.9375,31.640625) | (31.640625,32.34375) | 0 |
9 | (30.9375,31.640625) | (30.9375,31.2890625) | (31.2890625,31.640625) | 0 |
10 | (30.9375,31.2890625) | (30.9375,31.11328125) | (31.11328125,31.2890625) | 1 |
... | ... | ... | ... | ... |
由上表得出东方明珠纬度(31.239698)产生的编码为:
101011000110111
同理可得经度产生的编码为:
110101100110011
2.合并经纬度编码
按照经度占偶数位,纬度占奇数位的原则,合并经纬度的二进制编码;
111001100111100000111100011111
3.Base32编码
按照每5位一组,分成6组,每组计算其对应的十进制数值,按照Base32进行编码;
Base32编码表的其中一种如下,是用0-9、b-z(去掉a, i, l, o)这32个字母进行编码
编码过程:
11100 11001 11100 00011 11000 11111
28(w) 25(t) 28(w) 3(3) 24(s) 31(z)
由此可得,东方明珠的GeoHash值为:wtw3sz(12ktu1)
优点
- 使用字符串表示经纬度,展示效果会更好一些;
- 在数据库中给坐标点提供了另一种存储方式。在数据存储时可以简化为只为一列做索引;
- Geohash是一种前缀编码,前缀相同的坐标点,位置相近。通过前缀提供了高性能的邻近位置POI查询,而邻近位置POI查询是LBS服务的核心能力。
- Geohash表示的是一个矩形区域。使用者既能表明自己大致位置,又不至于暴露精确坐标,有助于隐私保护;
-
- 相应的,字符串越长,表示的范围就越精确;
小工具⚙️
Geohash Converter
经纬度距离计算 - 开发工具箱
Geohash Explorer
四、存在的问题
精度问题
GeoHash长度与精度之间的对应关系如下:
如何实现附近LBS检索
五、相关API
Redis GEO | 菜鸟教程
Geohash 单元查询 | Elasticsearch: 权威指南 | Elastic
Geospatial Queries — MongoDB Manual
如何选择?
六、应用场景
附近的“人”
将用户位置与商家、酒店等地理位置信息匹配,提供推荐服务;
地理围栏
对某个区域进行监控,当有物体进入或离开该区域时进行警报;
地理位置索引
将地理位置信息编码为字符串,可以在数据库中快速检索某个范围内的地理位置信息;
地图导航、位置服务;
地理位置可视化
地图展示、热力图等;
数据分析、数据挖掘等
借贷业务中,通过地理位置信息透视用户群特征及分析借贷风险;
七、总结
- 了解GeoHash的原理
- 熟悉相关API
- 了解GeoHash的应用场景
Haversine公式
📚 参考资料
- GIS专业知识~地理坐标系(GCS)
- 国内常用地图坐标系
- 【推荐】GIS专业知识~火星坐标系
- 为什么需要空间索引?
- 空间索引之GeoHash
- Elasticsearch 在地理信息空间索引的探索和演进
- geohash-java
- 讲讲KD-Tree
- Lucene系列(16)工具类之kdb Bkd树原理概述 - 腾讯云开发者社区-腾讯云
- K-D树、K-D-B树、B-K-D树_bkd树_Holmofy的博客-CSDN博客