对一组经纬度进行 GeoHash 编码时,我们要先对经度和纬度分别编码,然后再把经纬度各自的编码组合成一个最终编码。
对于一个地理位置信息来说,它的经度范围是[-180,180]。GeoHash 编码会把一个经度值编码成一个 N 位的二进制值,我们来对经度范围[-180,180]做 N 次的二分区操作,其中 N 可以自定义。
在进行第一次二分区时,经度范围[-180,180]会被分成两个子区间:[-180,0) 和[0,180](左、右分区)。查看一下要编码的经度值落在了左分区还是右分区。如果是落在左分区,用 0 表示;如果落在右分区,就用 1 表示。这样一来,每做完一次二分区,得到 1 位编码值。
再对经度值所属的分区再做一次二分区,同时再次查看经度值落在了二分区后的左分区还是右分区,按照刚才的规则再做 1 位编码。当做完 N 次的二分区后,经度值就可以用一个 N bit 的数来表示了。
假设要编码的经度值是 116.37,用 5 位编码值(也就是 N=5,做 5 次分区)。
-
第一次二分区:把经度区间[-180,180]分成了左分区[-180,0] 和右分区[0,180],此时,经度值 116.37 是属于右分区[0,180],用 1 表示第一次二分区后的编码值。
-
第二次二分区:把经度值 116.37 所属的[0,180]区间,分成[0,90] 和[90, 180]。此时,经度值 116.37 还是属于右分区[90,180],所以,第二次分区后的编码值仍然为 1。
-
第三次二分区:对[90,180]进行二分区,分成[90,135]和[135, 180],经度值 116.37 落在了分区后的左分区[90, 135] 中,所以,第三次分区后的编码值就是 0
-
第四次二分钱区: 对[90, 135] 进行二分区,分成[90,112.5]和[112.5,135],经度值 116.37 落在了分区后的右分区[112.5,135]中,所以,第四次分区后的编码值就是 1
-
第五次二分钱区: 对[112.5,135] 进行二分区,分成[112.5, 123.75]和[123.75,135], 经度值 116.37 落在了分区后的左分区[112.5, 123.75]中,所以,第五次分区后的编码值就是 0
做完 5 次分区后,把经度值 116.37 定位在[112.5, 123.75]这个区间,并且得到了经度值的 5 位编码值,即 11010
和对经度的一样,只是纬度的范围是[-90,90],下面这张表显示了对纬度值 39.86 的编码过程。
当一组经纬度值都编完码后,再把它们的各自编码值组合在一起,组合的规则是:最终编码值的偶数位上依次是经度的编码值,奇数位上依次是纬度的编码值,其中,偶数位从 0 开始,奇数位从 1 开始。
计算的经纬度(116.37,39.86)的各自编码值是 11010 和 10111,组合之后,第 0 位是经度的第 0 位 1,第 1 位是纬度的第 0 位 1,第 2 位是经度的第 1 位 1,第 3 位是纬度的第 1 位 0,以此类推,就能得到最终编码值 1110011101
用了 GeoHash 编码后,原来无法用一个权重分数表示的一组经纬度(116.37,39.86)就可以用 1110011101 这一个值来表示