二,Geohash

  在介绍Geohash之前,先简单介绍一下经纬度概念。为了明确表示世界各地在地球上的位置,将地球看成一个基于经纬度线的坐标系。纬线就是平行于赤道平面的那些平面的周线,经线就是连接南北两极的大圆线的半圆弧。纬度分为北纬(正),南纬(负),赤道所在的纬度值为0。经度以本初子午线界(本初子午线经度为0),分为东经(正),西经(负)。故纬度范围可表示为[-90o, 0o),(0o, 90o],经度范围可表示为[-180o, 0o),(0o, 180o]。

  我们可以将经度和纬度看成二维坐标系中的两个纬度,横轴表示经度,纵轴表示纬度,那么所表示的区域如下所示:

  

图 1

  如上图所示,我们可以将整个区域逐步通过两条直线进行细分。例如:首先我们可以将原区域分成[(0, 0),(180, 0),(0, 90),(180, 90)],[(0, 0),(-180, 0),(0, 90),(-180, 90)],[(0, 0),(-180, 0),(0, -90),(-180, -90)],[(0, 0),(180, 0),(0, -90),(180, -90)]等四个区域,我们可以将这四个区域中的点分别按照该点所在的区域进行编码。具体的编码方式为先水平方向(经度)后竖直方向(纬度),以水平方向(经度)为例,它被竖直中轴线一分为二,那么右侧的编码为1,左侧的编码为0;同理,在竖直方向,上测的编码为1,下测的编码为0;依照这种规则,那么处于右上区域的点在第一次划分后的编码为11(如上图中A,E编码后的前两位),处于左上区域的点在第一次划分后的编码为01(如上图中B编码后的前两位),同理,第一次划分后C的编码为00,D的编码为10。

  接下来对第一次划分后的四个区域重复上述过程,以第一次划分后的右上区域为例,可以将这个区域继续分为四个小区域,编码方式和第一次相同,根据这四个小区域在其所处的直接大区域中的方位进行编码,即这四个小区域中右侧的两个小区域水平编码为1(经度),左侧的两个小区域水平编码(经度)为0,上测的两个小区域的竖向编码为1,下测的两个小区域的竖向编码为0。所以,A第二次划分的编码为11,E第二次划分的编码为00。那么经过两次划分之后,A的编码为11 11,E的编码为11 00(即按照划分次序将每次的子编码进行拼接,如A第一次为11,第二次为11,故A两次划分之后编码为1111,同理E为1100)。明白了上述原理之后,我们可以根据上述原理将整个区域继续进行划分,就可以得到给定某一点更精确的编码值。

  上述划分的过程是我个人对Geohash编码思想的一种直观的理解,对任意一对经度、纬度值(lon,lat),我们可以根据上述原理将其编码为0、1所组成的串,然后将所得串按照base32进行编码。

  例如,对于经纬度值(116.3906,39.9232),我们可以将经纬度按照上述原理转换成如下0、1序列

图 2

  

图 3

  所得序列为:

    经度0、1编码后的序列为:1 1 0 1 0 0 1 0 1 1 0 0 0 1 0

    纬度0、1编码后的序列为:1 0 1 1 1 0 0 0 1 1 0 0 0 1 1

    合并经度、纬度0、1编码后的序列得到,经纬度(116.3906,39.9232)的0、1编码序列:

图 4

    注意:

    1. 在所得经纬度编码中,偶数位存放经度编码,奇数为存放纬度编码(编码位序号从0开始计数,所以第一位是偶数位)      

  接下来对所得的经纬度0、1编码后的序列进行base32编码,base32编码对应表如下:

图 5

  所以上述序列经过base32编码后为:wx4g0e,即(116.3906,39.9232)geohash编码为wx4g0e(经度为6)

  

  接下来,我们进一步理解Geohash编码。Geohash其实就是将整个地图或者某个分割所得的区域进行一次划分,由于采用的是base32编码方式,即Geohash中的每一个字母或者数字(如wx4g0e中的w)都是由5bits组成(2^5 = 32, base32),这5bits可以有32中不同的组合(0~31),这样我们可以将整个地图区域分为32个区域,通过00000 ~ 11111来标识这32个区域。第一次对地图划分后的情况如下图所示(每个区域中的编号对应于该区域所对应的编码):

图 6

  也许有些读者对于上图中各区域的编号很难理解,我们不妨从Geohash的编码方式中找原因。因为Geohash的0、1串序列是经度0、1序列和纬度0、1序列中的数字交替进行排列的,如图4所示,在图4中,偶数位对应的序列为经度序列(0标识第一位),奇数位对应的序列为纬度序列,那么在进行第一次划分时,Geohash0、1序列中的前5个bits(11100),那么这5bits中有3bits是表示经度,2bits表示纬度,所以第一次划分时,是将经度划分成8个区段(2^3 = 8),将纬度划分为4个区段(2^2 = 4),这样就形成了32个区域。那么为什么第一次划分后每个区域对应的序号是上图中那样呢?那么下面这个图就可以详细说明。

图 7

  同理,可以按照第一次划分所采用的方式对第一次划分所得的32个区域各自再次划分,如下图所示:

图 8

  细心的读者会发现对第一次划分所得编号为S的区域再次进行划分后,所得的是8x4的32个区域,而不是如同第一次划分中的4x8的32个区域,这是为什么呢?这个也需要从Geohash的0、1序列来解释,因为Geohash的0、1序列的第一个5bits表示第一次划分,第二个5bits表示第二次划分,但是两者不同的是,在第一个5bit中有3bits(0,2,4)表示经度,2bits(1,3)表示纬度,而在第二个5bits中,有2bits(6,8)表示经度,3bits(5,7,9)表示纬度,所以应该是8x4的32个区域。每个区域对应的序号如下图所示:

  

图 9

posted on 2013-02-05 15:02  muson  阅读(594)  评论(0编辑  收藏  举报