Geohash算法

用户附近位置计算

经纬度与物理距离介绍

经纬度是经度与纬度的合称组成一个坐标系统,称为地理坐标系统,它是一种利用三度空间的球面来定义地球上的空间的球面坐标系统,能够标示地球上的任何一个位置

img

在一定误差范围内,通常情况下,经纬线和米的换算为:经度或者纬度0.00001度,约等于1米。以下表格列出更细致的换算关系:

在纬度相等的情况下在经度相等的情况下
经度每隔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米。

地图坐标系

WGS84坐标系地球坐标系,国际通用坐标系
GCJ02坐标系火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图 使用
BD09坐标系百度坐标系,GCJ02坐标系加密后的坐标系

注:如果使用GCJ-02坐标系,Geohash函数和距离计算函数理论上都应在WGS84坐标系下使用,在火星坐标系下会存在一定的偏差,主要是火星坐标系的加偏处理带来的,经过查阅资料及抽样测试,认为该误差在可接受范围内。

Geohash算法介绍

GeoHash是空间索引的一种方式,其基本原理是将地球理解为一个二维平面,通过把二维的空间经纬度数据编码为一个字符串,可以把平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码。

以GeoHash方式建立空间索引,可以提高对空间poi数据进行经纬度检索的效率。

编码规则为:先将纬度范围(-90, 90)平分成两个区间(-90, 0)和(0, 90),如果目标维度位于前一个区间,则编码为0,否则编码为1,然后根据目标纬度所落的区间再平均分成两个区间进行编码,以此类推,直到精度满足要求,经度也用同样的算法,对(-180, 180)依次细分,然后合并经度和纬度的编码,奇数位放纬度,偶数位放经度,组成一串新的二进制编码,按照Base32进行编码。

示例

以当前所在办公区【两江国际】的位置坐标为例, 经纬度为(104.059684,30.559545)

第一步:将经纬度转换为二进制

序号纬度范围划分区间0划分区间130.559545所属区间
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)0
7(28.125, 30.9375)(28.125, 29.53125)(29.53125, 30.9375)1
8(29.53125, 30.9375)(29.53125, 30.234375)(30.234375, 30.9375)1
9(30.234375, 30.9375)(30.234375, 30.5859375)(30.5859375, 30.9375)0
10(30.234375, 30.5859375)(30.234375, 30.41015625)(30.41015625, 30.5859375)1
11(30.41015625, 30.5859375)(30.41015625, 30.498046875)(30.498046875, 30.5859375)1
12(30.498046875, 30.5859375)(30.498046875, 30.541992188)(30.541992188, 30.5859375)1
13(30.541992188, 30.5859375)(30.541992188, 30.563964844)(30.563964844, 30.5859375)0
14(30.541992188, 30.563964844)(30.541992188, 30.552978516)(30.552978516, 30.563964844)1
15(30.552978516, 30.563964844)(30.552978516, 30.55847168)(30.55847168, 30.563964844)1

最后得到维度的二进制编码为:101010110111011, 用同样的方式可以得到精度(104.059684)的二进制编码:110010011111111

第二步:将经纬度的二进制编码合并

从偶数0开始,经度占偶数位,纬度占奇数位。

序号01234567891011121314151617181920212223242526272829
编码111001001100011110111111101111

第三步:将合并后的二进制数做Base32编码

按照每5位一组,分成6组,每组计算其对应的十进制数值,按照Base32进行编码。

Base32编码表的其中一种如下,是用0-9、b-z(去掉a, i, l, o)这32个字母进行编码.

img

11100 10011 00011 11011 11111 01111
28(w) 19(m) 3(3)  27(v) 31(z) 15(g)

最终得到的经纬度编码为:wm3vzg

如上文二进制编码的计算过程,如果递归的次数越大,则生成的二进制编码越长,因此生成的geohash编码越长,位置越精确。目前Geohash使用的精度说明如下:

img

GeoHash用一个字符串表示经度和纬度两个坐标, 比直接用经纬度的高效很多,而且使用者可以发布地址编码,既能表明自己位于某位置附近,又不至于暴露自己的精确坐标,有助于隐私保护。

编码过程中,通过二分范围匹配的方式来决定某个经纬坐标是编码为1还是0,因此某些邻近坐标的编码是相同的,因此GeoHash表示的并不是一个点,而是一个矩形区域。 GeoHash编码的前缀可以表示更大的区域。例如wm3vzg,它的前缀wm3vz表示包含编码wm3vzg在内的更大范围。 这个特性可以用于附近地点搜索。

如果把某个区域或整个地图上的地理位置都按照Geohash编码,则会得到一个网格,编码递归粒度越细,网格的矩形区域越小,geohash编码的长度越大,则Geohash编码越精确。 不同的编码长度,生成的网格与实际地理的精度如下(Geohash字符串编码长度对应网格大小)

字符串长度网格宽度网格高度
15000Km5000Km
21250Km625Km
3156Km156Km
439.1Km19.5Km
54.89Km4.89Km
61.22Km0.61Km
7153m153m
838.2m19.1m
94.77m4.77m
101.19m0.596m

Geohash编码与网格

当前选取的编码长度为6,因此一个网格实际的地理差异在1.2公里与0.6公里,示例中两江国际对应的网格大致效果如图:

img

邻近网格位置推算

结论

根据Geohash的编码规则将经纬度分解到二进制,结合地理常识,中心网格在南北(上下)方向上体现为纬度的变化,往北则维度的二进制加1,往南则维度的二进制减1,在东西(左右)方向上体现为经度的变化,往东则经度的二进制加1,往西则减1,可以计算出上下左右四个网格经纬度的二进制编码,再将加减得出的经纬度两两组合,计算出左上、左下、右上和右下四个网格的经纬度二进制编码,从而就可以根据Geohash的编码规则计算出周围八个网格的字符串。

正向推导

以Geohash编码长度为6为基础,网格的宽高与实际距离换算为:1.2Km*0.6Km.

参考上文提到的,在经度相同情况下,每隔0.001度,距离相差约111米。0.6Km换算为纬度为:0.005405405。

当前两江国际粗粒度的wgs84坐标(104.05503,30.562251), 纬度二进制编码:101010110111011,经度二进制编码:110010011111111, Geohash值为:wm3vzg

正北方向近邻的网格维度为增加一个网格的高度,即纬度增加0.005405405,为:30.562251 + 0.005405405 = 30.567656405, 转换为二进制编码后为(可用工具快速转换):101010110111100

正好是原纬度的二进制编码101010110111011 加1后的结果(101010110111011 + 000000000000001 = 101010110111100)

反向推导

当前两江国际粗粒度的wgs84坐标(104.05503,30.562251), 纬度二进制编码:101010110111011,经度二进制编码:110010011111111, Geohash值为:wm3vzg

基于当前坐标的网格,正北方向近邻的网格N,其纬度二进制加1后为:101010110111100,经度不变,其Geohash值为:wm3vzu

通过http://geohash.co/ 反向转换其经纬坐标为:(104.0570068359375,30.56671142578125)

通过https://www.box3.cn/tools/lbs.html 查询2个坐标的实际位置,误差在531m(符合精度范围)

img

邻近8个网格位置计算

**Geohash编码:**wm3vzs纬度二进制编码:101010110111100经度二进制编码:110010011111110公式:(Lat_bin + 1, Lon_bin - 1)**Geohash编码:**wm3vzu纬度二进制编码:101010110111100经度二进制编码:110100101101010公式:(Lat_bin + 1, Lon_bin)**Geohash编码:**wm6jbh纬度二进制编码:101010110111100经度二进制编码:110010100000000公式:(Lat_bin + 1, Lon_bin + 1)
**Geohash编码:**wm3vze纬度二进制编码:101010110111011经度二进制编码:110010011111110公式:(Lat_bin, Lon_bin - 1)**Geohash编码:**wm3vzg纬度二进制编码:101010110111011经度二进制编码:110010011111111公式:(Lat_bin, Lon_bin)**Geohash编码:**wm6jb5纬度二进制编码:101010110111011经度二进制编码:110010100000000公式:(Lat_bin, Lon_bin + 1)
**Geohash编码:**wm3vzd纬度二进制编码:101010110111010经度二进制编码:110010011111110公式:(Lat_bin - 1, Lon_bin - 1)**Geohash编码:**wm3vzf纬度二进制编码:101010110111010经度二进制编码:110010011111111公式:(Lat_bin - 1, Lon_bin)**Geohash编码:**wm6jb4纬度二进制编码:101010110111010经度二进制编码:110010100000000公式:(Lat_bin - 1, Lon_bin + 1)
附近3公里网格模型

img

青色代表:用户位置的网格编码,红色代表:附近附近3公里的网格编码

要在Python中实现geohash算法,你可以使用geohash库。首先,你需要确保已经安装了geohash库。你可以使用pip命令进行安装,命令如下:pip install geohash。如果安装成功后,仍然无法导入geohash模块并提示ImportError: No module named 'geohash'的错误,你可以尝试以下方法进行修复:将Geohash文件名改为geohash,然后在geohash文件夹下的__init__.py文件中将from geohash import decode_exactly, decode, encode改为from .geohash import decode_exactly, decode, encode(在geohash前面加一个'.')。这样应该可以解决导入模块的问题。[1] 一旦你成功导入了geohash库,你就可以使用它来进行geohash算法的实现。例如,你可以使用decode_exactly函数来将geohash字符串解码为经度和纬度的坐标。例如,你可以使用以下代码来解码geohash字符串"wm6nc":print(geohash.decode_exactly("wm6nc")),这将返回一个包含经度、纬度、经度精度和纬度精度的元组。(30.73974609375, 104.12841796875, 0.02197265625, 0.02197265625)[2] geohash库还提供了其他功能模块,如距离度量和几何计算。距离度量模块提供了与距离相关的函数,如distance和dimensions。几何模块提供了将多边形转换为geohash列表的函数,如polygon_to_geohashgeohash_to_polygon。这些功能可以帮助你在地理区域中进行近似地理差异的计算。你可以使用shapely库进行几何计算[3]。 综上所述,要在Python中实现geohash算法,你可以使用geohash库,并根据需要使用其提供的不同功能模块。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Usher_Ou

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

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

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

打赏作者

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

抵扣说明:

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

余额充值