老衛帶你學---Geohash算法原理及實現

Geohash算法就是將經緯度編碼,將二維變一維,給地址位置分區的一種算法。

基本原理

GeoHash是一種地址編碼方法。他能夠把二維的空間經緯度數據編碼成一個字符串

我們知道,經度範圍是東經180到西經180,緯度範圍是南緯90到北緯90,我們設定西經爲負,南緯爲負,所以地球上的經度範圍就是[-180, 180],緯度範圍就是[-90,90]。如果以本初子午線、赤道爲界,地球可以分成4個部分。

如果緯度範圍[-90°, 0°)用二進制0代表,(0°, 90°]用二進制1代表,經度範圍[-180°, 0°)用二進制0代表,(0°, 180°]用二進制1代表,那麼地球可以分成如下4個部分

在這裏插入圖片描述

如果在小塊範圍內遞歸對半劃分呢?

在這裏插入圖片描述

可以看到,劃分的區域更多了,也更精確了。geohash算法就是基於這種思想,劃分的次數更多,區域更多,區域面積更小了。通過將經緯度編碼,給地理位置分區

Geohash算法

Geohash算法一共有三步。

首先將經緯度變成二進制。

比如這樣一個點(39.923201, 116.390705)
緯度的範圍是(-90,90),其中間值爲0。對於緯度39.923201,在區間(0,90)中,因此得到一個1;(0,90)區間的中間值爲45度,緯度39.923201小於45,因此得到一個0,依次計算下去,即可得到緯度的二進制表示,如下表:
在這裏插入圖片描述

最後得到緯度的二進制表示爲:

  10111000110001111001

同理可以得到經度116.390705的二進制表示爲:

  11010010110001000100

第2步,就是將經緯度合併。

經度佔偶數位,緯度佔奇數位,注意,0也是偶數位。

  11100 11101 00100 01111 00000 01101 01011 00001

第3步,按照Base32進行編碼

Base32編碼表的其中一種如下,是用0-9、b-z(去掉a, i, l, o)這32個字母進行編碼。具體操作是先將上一步得到的合併後二進制轉換爲10進制數據,然後對應生成Base32碼。需要注意的是,將5個二進制位轉換成一個base32碼。上例最終得到的值爲

  wx4g0ec1

Geohash比直接用經緯度的高效很多,而且使用者可以發佈地址編碼,既能表明自己位於北海公園附近,又不至於暴露自己的精確座標,有助於隱私保護。

GeoHash用一個字符串表示經度和緯度兩個座標。在數據庫中可以實現在一列上應用索引(某些情況下無法在兩列上同時應用索引)

  • GeoHash表示的並不是一個點,而是一個矩形區域
  • GeoHash編碼的前綴可以表示更大的區域。例如wx4g0ec1,它的前綴wx4g0e表示包含編碼wx4g0ec1在內的更大範圍。 這個特性可以用於附近地點搜索
    編碼越長,表示的範圍越小,位置也越精確。因此我們就可以通過比較
  • GeoHash匹配的位數來判斷兩個點之間的大概距離。

在這裏插入圖片描述

問題

geohash算法有兩個問題。首先是邊緣問題。

在這裏插入圖片描述

如圖,如果車在紅點位置,區域內還有一個黃點。相鄰區域內的綠點明顯離紅點更近。但因爲黃點的編碼和紅點一樣,最終找到的將是黃點。這就有問題了。

要解決這個問題,很簡單,只要再查找周邊8個區域內的點,看哪個離自己更近即可。

另外就是曲線突變問題。

本文第2張圖片比較好地解釋了這個問題。其中0111和1000兩個編碼非常相近,但它們的實際距離確很遠。所以編碼相近的兩個單位,並不一定真實距離很近,這需要實際計算兩個點的距離才行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章