GeoHash 的二进制编码和划分过程详解
GeoHash 的编码过程是通过将地理坐标(经度和纬度)转化为二进制数值,并将它们交替合并,最终生成一个基于二进制的编码。这一过程本质上是通过 逐步划分经纬度的范围 来实现的,每次划分都会生成一个二进制值,最终将这些二进制值交替组合来表示地理位置。
以下是 GeoHash 编码过程中二进制划分的详细步骤和解释:
1. 初始经纬度范围
GeoHash 编码过程从定义地球的经纬度范围开始:
- 经度范围:
[-180, 180]
- 纬度范围:
[-90, 90]
我们要将这些范围不断细分,直到达到需要的精度。
2. 二进制划分过程
GeoHash 的二进制编码基于 二分法,每次将经纬度范围一分为二。通过选择左半边或右半边(对于经度)或上半边或下半边(对于纬度)来确定最终的经纬度位置。
2.1 经度划分
- 经度的范围是
[-180°, 180°]
。每次划分都会选择其中的左半部分或右半部分,并根据选择产生一个二进制位。 - 每次选择:
-
- 如果位置在中线的左边,选择左半边(表示为 0)。
- 如果位置在中线的右边,选择右半边(表示为 1)。
2.2 纬度划分
- 纬度的范围是
[-90°, 90°]
,同样的规则适用:
-
- 如果位置在中线的下方,选择下半边(表示为 0)。
- 如果位置在中线的上方,选择上半边(表示为 1)。
2.3 逐步划分的示例
假设我们有一个地理坐标 (latitude = 40.748817, longitude = -73.985428)
,并希望编码为 GeoHash。我们会逐步划分经纬度范围,直到达到所需的精度。
3. 详细的二进制编码步骤
让我们以经纬度 (latitude = 40.748817, longitude = -73.985428)
为例,演示详细的二进制划分过程。
3.1 经度的二进制划分
- 经度的初始范围是
[-180, 180]
。
-
- 中线是 0。
- 由于
longitude = -73.985428
,它位于中线的左侧,所以选择左半边(即范围[-180, 0]
)。 - 记录二进制值:0。
- 新的经度范围是
[-180, 0]
,中线是 -90。
-
- 由于
longitude = -73.985428
,它在中线的右侧,所以选择右半边(即范围[-90, 0]
)。 - 记录二进制值:1。
- 由于
- 新的经度范围是
[-90, 0]
,中线是 -45。
-
- 由于
longitude = -73.985428
,它在中线的左侧,所以选择左半边(即范围[-90, -45]
)。 - 记录二进制值:0。
- 由于
- 新的经度范围是
[-90, -45]
,中线是 -67.5。
-
- 由于
longitude = -73.985428
,它在中线的左侧,所以选择左半边(即范围[-90, -67.5]
)。 - 记录二进制值:0。
- 由于
- 新的经度范围是
[-90, -67.5]
,中线是 -78.75。
-
- 由于
longitude = -73.985428
,它在中线的右侧,所以选择右半边(即范围[-78.75, -67.5]
)。 - 记录二进制值:1。
- 由于
- 新的经度范围是
[-78.75, -67.5]
,中线是 -73.125。
-
- 由于
longitude = -73.985428
,它在中线的左侧,所以选择左半边(即范围[-78.75, -73.125]
)。 - 记录二进制值:0。
- 由于
- 新的经度范围是
[-78.75, -73.125]
,中线是 -75.9375。
-
- 由于
longitude = -73.985428
,它在中线的右侧,所以选择右半边(即范围[-75.9375, -73.125]
)。 - 记录二进制值:1。
- 由于
继续类似的划分,最终得到经度的二进制值(经过多次划分后,得到的二进制位数决定了 GeoHash 的精度)。
3.2 纬度的二进制划分
- 纬度的初始范围是
[-90, 90]
。
-
- 中线是 0。
- 由于
latitude = 40.748817
,它位于中线的右侧,所以选择右半边(即范围[0, 90]
)。 - 记录二进制值:1。
- 新的纬度范围是
[0, 90]
,中线是 45。
-
- 由于
latitude = 40.748817
,它位于中线的左侧,所以选择左半边(即范围[0, 45]
)。 - 记录二进制值:0。
- 由于
- 新的纬度范围是
[0, 45]
,中线是 22.5。
-
- 由于
latitude = 40.748817
,它位于中线的右侧,所以选择右半边(即范围[22.5, 45]
)。 - 记录二进制值:1。
- 由于
- 新的纬度范围是
[22.5, 45]
,中线是 33.75。
-
- 由于
latitude = 40.748817
,它位于中线的右侧,所以选择右半边(即范围[33.75, 45]
)。 - 记录二进制值:1。
- 由于
继续类似的划分,最终得到纬度的二进制值。
4. 交替合并经纬度二进制值
经过以上步骤,你将得到两个二进制数:一个用于表示经度,一个用于表示纬度。接下来,GeoHash 将交替合并这些二进制位。
假设我们已经得到了以下的二进制值:
- 经度:
0100100010100001...
- 纬度:
110101011101...
GeoHash 的编码将这些二进制值交替合并,如下所示:
经度位 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 ...
纬度位 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 0 ...
合并后的二进制位:010010001110101011011100101101...
5. 转换为 Base32 编码
最终,交替合并后的二进制值将被切割成 5 位一组,然后每组用 Base32 编码映射为一个字符。
例如,01001
可能映射为字符 q
,11010
映射为 8
,以此类推。
最终的 GeoHash 编码结果是一个 Base32 编码的字符串,通常会是类似 9q8yy
的格式。
6. 总结
GeoHash 的二进制编码过程可以分为以下几个步骤:
- 划分经纬度范围:通过不断地将经纬度范围划分为更小的区域。
- 生成二进制值:每次划分都会生成一个二进制位,表示该位置是否落在当前区间的左侧或右侧。
- 交替合并二进制位:将经度和纬度的二进制位交替合并,形成一个长的二进制串。
- 转换为 Base32:将长二进制串按 5 位一组转换为 Base32 字符,从而得到最终的 GeoHash 编码。
通过调整二进制串的长度,你可以控制 GeoHash 的精度,精度越高,GeoHash 字符串的长度越长,表示的地理位置就越精确。