グリッドとしても座標表現としても使える Geohash

自由に使える経緯度の符号化法 Geohash がグリッドとしても座標表現としても使えてうれしいです。

Geohash とは?

Geohash (http://en.wikipedia.org/wiki/Geohash) が色々と使われているようです(http://zcologia.com/news/759/geohash-and-bigtable/) 。
この Geohash、ビット列を経度・緯度の順に交代に2分割するように解釈し、BASE32 で符号化するもので、Wikipedia の短い記事で仕様が完結しており、自由に使えます。

この Geohash、よく考えられていると思います。Geohash は点を表現するものですが、その点と同じ Geohash を持つ面のグリッドであると解釈することも簡単です。グリッドと座標の表現を、Geohash 一つで済ますことができます。

Geohash のグリッドの大きさ=座標の分解能は?

Geohash 1文字が空間を5回2分割するので、グリッドの大きさはあまり選べないのですが、その大きさがなかなか都合が良いのです。次のプログラムで調べてみました。

(1..16).map {|i|
  lng_bit = (5 * i / 2.0).ceil
  lat_bit = (5 * i / 2.0).floor
  lng_grid_size = sprintf("%6.6f", 360.0 * 60 * 60 / 2 ** lng_bit)
  lat_grid_size = sprintf("%6.6f", 180.0 * 60 * 60 / 2 ** lat_bit)
  [i, lng_bit, lat_bit, lng_grid_size, lat_grid_size]
}.each do |r|
  print "|#{r.join('|')}|\n"
end

その結果は、次のとおりになります:

Geohash文字数 経度方向の2分割回数 緯度方向の2分割回数 経度方向のグリッド辺長(秒) 経度方向のグリッド辺長(秒)
1 3 2 162000.000000 162000.000000
2 5 5 40500.000000 20250.000000
3 8 7 5062.500000 5062.500000
4 10 10 1265.625000 632.812500
5 13 12 158.203125 158.203125
6 15 15 39.550781 19.775391
7 18 17 4.943848 4.943848
8 20 20 1.235962 0.617981
9 23 22 0.154495 0.154495
10 25 25 0.038624 0.019312
11 28 27 0.004828 0.004828
12 30 30 0.001207 0.000603
13 33 32 0.000151 0.000151
14 35 35 0.000038 0.000019
15 38 37 0.000005 0.000005
16 40 40 0.000001 0.000001

Geohash 文字数が奇数であれば、経緯度座標系で正方格子になり、偶数であれば"横長"の格子になります。この"横長"さは、投影のことを考えると多少緩和されます。Geohash を空間インデクスっぽく使うのであれば、グリッドの大きさを基準に考えればよいでしょう。

Geohash6グリッド・Geohash16座標

例えば、旅行スケールの地図データであれば、Geohash 6 文字でグリッドを切れば、それは40秒 x 20秒メッシュですので良い大きさのグリッドとなりそうです。座標表現としては、通常の用途では 10 文字あれば十分でしょうし、かなりの精度を求める場合でも、15、16文字あたりを考えておけば、少なくとも10万分の1秒程度の有効数字を持つことになりそうです。