一篇文章掌握GeoHash

一、基本概念

地球是一个球,我们常用经纬度来表示某个点的坐标,例如:北海公园的坐标为(39.928167,116.389550)。GeoHash的基本原理就是将地球理解为一个展开的二维平面,将这个二维平面按照一定的规则划分为不同的单元格,每个单元格拥有具有唯一性的编码,如图一所示。至于这个编码如何计算,将会在后面的内容予以介绍。

一篇文章掌握GeoHash_第1张图片

图1:GeoHash原理示意图

从图中可以看出,每一个单元格的唯一性编码其实表示的是单元格所在的区域,而不是某个特定点的信息。矩形区域内的所有点共享相同的GeoHash值,这样做的目的一方面是为了保证数据的私密性,既可以大概表达位置,又不用准备描述所在位置;另一方面,则是把二维位置转换为一维数据,方便数据的缓存和检索操作。而GeoHash值的相似度则代表了距离的远近。所以,利用GeoHash的code可以快速进行空间关系判断。

二、GeoHash算法

我们都知道,地球纬度的范围是[-90, 90],经度的范围是[-180, 180]。这里我们以上面提到的北海公园坐标(39.928167,116.389550)为例演示GeoHash算法。

  • 区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定39.928167属于右区间[0,90],给标记为1;

  • 接着将区间[0,90]进行二分为[0,45),[45,90],可以确定39.928167属于左区间[0,45),给标记为0;

  • 递归上述过程39.928167总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167;

  • 如果给定的纬度x(39.928167)属于左区间,则记录0,如果属于右区间则记录1,这样随着算法的进行会产生一个序列1011100,序列的长度跟给定的区间划分次数有关。

计算过程如下图所示,最终的计算结果为 10111 00011

一篇文章掌握GeoHash_第2张图片

同样的,对经度值116.389550进行这种操作,如下图所示,最终得到的结果为11010 01011

一篇文章掌握GeoHash_第3张图片

最后,将经度放在偶数位置,纬度放在奇数位置:

 

序号

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

经度

1

 

1

 

0

 

1

 

0

 

0

 

1

 

0

 

1

 

1

 

纬度

 

1

 

0

 

1

 

1

 

1

 

0

 

0

 

0

 

1

 

1

最终得到的GeoHash的值为:11100 11101 00100 01111,按照base32编码

一篇文章掌握GeoHash_第4张图片

GeoHash的值为:28 29 4 15,最终的GeoHash值为wx4g。解码算法与上述算法相反。GeoHash划分的单元格的大小其实表示了不同的精度,精度表如下:

一篇文章掌握GeoHash_第5张图片

三、GeoHash作用

首先,geohash用一个字符串表示经度和纬度两个坐标。某些情况下无法在两列上同时应用索引(例如MySQL 4之前的版本,Google App Engine的数据层等),利用geohash,只需在一列上应用索引即可。

其次,geohash表示的并不是一个点,而是一个矩形区域。比如编码wx4g0ec19,它表示的是一个矩形区域。使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。

第三,编码的前缀可以表示更大的区域。例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。这个特性可以用于附近地点搜索。首先根据用户当前坐标计算geohash(例如wx4g0ec1)然后取其前缀进行查询(SELECT * FROM placeWHERE geohash LIKE 'wx4g0e%'),即可查询附近的所有地点。Geohash比直接用经纬度的高效很多。

具体应用:

1、Mysql使用GeoHash转换成字符串存储

2、Postgresql的PostGis插件,支持空间计算

3、Mongodb自带距离计算

4、Redis自带距离计算

5、Mysql spitial

 

你可能感兴趣的:(GIS,数据结构与算法)