天天看点

使用geohash的几个要点

文章目录

      • geohash是什么?怎么生成?
      • geohash的填充曲线是唯一的——Peano空间填充曲线
      • geohash的长度,位数和空间精度

geohash是什么?怎么生成?

  1. geohash采用的是base32编码.即Geohash中的每一个字母或者数字(如wx4g0e中的w)都是由5bits组成(2^5 = 32,base32),这5bits可以有32中不同的组合(0~31),这样我们可以将整个地图区域分为32个区域,通过00000 ~ 11111来标识这32个区域。
    使用geohash的几个要点
    使用geohash的几个要点
  2. Geohash的0、1串序列是经度0、1序列和纬度0、1序列中的数字交替进行排列的,偶数位对应的序列为经度序列,奇数位对应的序列为纬度序列(这里应该是从0开始排列,也就是第一位是经度,下标为0)。在进行第一次划分时,Geohash0、1序列中的前5个bits(11100),那么这5bits中有3bits是表示经度,2bits表示纬度,所以第一次划分时,是将经度划分成8个区段(2^3 = 8),将纬度划分为4个区段(2^2 = 4),这样就形成了32个区域。所以上图中横向8个格子,纵向4个格子,一共32个格子。
    使用geohash的几个要点
  3. 同样的,对于第二位geohash是在第一位geohash划分的格子的基础上再重新划分。同样的,第二位geohash也是代表的5位,不同的是第二位geohash是从第5位开始(下标从0开始)。也就是代表3位是纬度,2位是经度。

纬度

使用geohash的几个要点

经度

使用geohash的几个要点

第二位geohash编码

使用geohash的几个要点
使用geohash的几个要点

geohash的填充曲线是唯一的——Peano空间填充曲线

网上为了介绍geohash的填充曲线,会介绍填充曲线的由来,并且会提到几种不同的填充曲线,如下图:

使用geohash的几个要点

但是要明确的是,按照geohash的编码规则,填充曲线是唯一的

使用geohash的几个要点
使用geohash的几个要点

geohash的长度,位数和空间精度

geohash有一个三者的对照表:

使用geohash的几个要点

不同长度的geohash格子对应的长和宽对照表

使用geohash的几个要点

有两种方法指定geohash精度

  • 一个是指定geohash码的长度。这种编码精度控制方式理解起来简单。对于经度,其各个geohash字符代表的编码位数依次是:3,2,3,2 ……。所以我们看上面的长,宽表。不同位数的geohash的宽度依次是:50009.4,1252.3,156.5……其前后倍数之间的关系依次是:4,8,4,8,4……。对于维度而言类似。

    python的包Geohash就是采用的这种方式:

import Geohash as gs
print(gs.encode(39.928167, 116.389550, 1))
print(gs.encode(39.928167, 116.389550, 2))

#输出
w
wx
           
  • 第二种精度控制方式就是0,1码的位数。如果精度位数是1-5 可以生成1位geohash码,6-10 可以生成2位geohash码。以此类推。这就产生一个问题:

    在geohash位数一样的情况下(例如geohash码长度为2),对于同一个坐标点,不同精度对应的geohash是一样的吗?

    换句话说,对于同一个点,采用6位精度和10位精度生成的geohash码一样吗?
import org.locationtech.geomesa.utils.geohash.GeoHash;

public class HashTest {
    public static void main(String[] args) {
        System.out.println(GeoHash.apply(116.389550, 39.928167, 6).hash());
        System.out.println(GeoHash.apply(116.389550, 39.928167, 7).hash());
        System.out.println(GeoHash.apply(116.389550, 39.928167, 8).hash());
        System.out.println(GeoHash.apply(116.389550, 39.928167, 9).hash());
        System.out.println(GeoHash.apply(116.389550, 39.928167, 10).hash());
        /*
        输出
        wh
        ws
        ww
        ww
        wx
        * */
    }
}
           

由上面的输出看出,完全不一样。也就是同一个坐标点,对于可能对应长度相同但内容不同的geohash码,但是,不同的geohash的前缀是相同的。所以实际使用过程中geohash长度要比预期设置要大一位。比如要使用2位geohash,那就把精度设为11-15.这样会生成3位geohash.然后把尾部一位截去。

继续阅读