Skip to content

Instantly share code, notes, and snippets.

@yuribossa
Created February 4, 2010 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuribossa/294599 to your computer and use it in GitHub Desktop.
Save yuribossa/294599 to your computer and use it in GitHub Desktop.
# -*- coding: utf8 -*-
# GeoHash decode and encode library
base32 = {
'0': '00000',
'1': '00001',
'2': '00010',
'3': '00011',
'4': '00100',
'5': '00101',
'6': '00110',
'7': '00111',
'8': '01000',
'9': '01001',
'b': '01010',
'c': '01011',
'd': '01100',
'e': '01101',
'f': '01110',
'g': '01111',
'h': '10000',
'j': '10001',
'k': '10010',
'm': '10011',
'n': '10100',
'p': '10101',
'q': '10110',
'r': '10111',
's': '11000',
't': '11001',
'u': '11010',
'v': '11011',
'w': '11100',
'x': '11101',
'y': '11110',
'z': '11111'
}
class GeoHash():
def decode(self, geohash_str):
# 緯度経度の範囲を求める
def dehash(bit_array, min, max):
for bit in bit_array:
if bit:
min = (max + min) / 2.0
else:
max = (max + min) / 2.0
return (min, max)
# 二進数文字列に変換する
bit_array = []
for str in geohash_str:
bit_array.append(base32[str])
# 偶数bitと奇数bitに分割する
longtitude_bit_array = [] # 偶数bit
latitude_bit_array = [] # 奇数bit
i = 0
for bit in bit_array:
if i % 2 == 0:
longtitude_bit_array.append(bit[0])
latitude_bit_array.append(bit[1])
longtitude_bit_array.append(bit[2])
latitude_bit_array.append(bit[3])
longtitude_bit_array.append(bit[4])
else:
latitude_bit_array.append(bit[0])
longtitude_bit_array.append(bit[1])
latitude_bit_array.append(bit[2])
longtitude_bit_array.append(bit[3])
latitude_bit_array.append(bit[4])
i += 1
latitude_bit_array = map(int, latitude_bit_array)
longtitude_bit_array = map(int, longtitude_bit_array)
latitude = dehash(latitude_bit_array, -90.0, 90.0)
longtitude = dehash(longtitude_bit_array, -180.0, 180.0)
return {'latitude': latitude, 'longtitude': longtitude}
def encode(self, latitude, longtitude, str_len):
# 緯度または経度の二進数文字列を求める
def as_bit(val, bit_len, min, max):
bit_array = []
for i in range(bit_len):
mid = (max + min) / 2.0
if val > mid:
bit_array.append('1')
min = mid
else:
bit_array.append('0')
max = mid
return bit_array
# 緯度と経度の二進数文字列を求める
lat_len = str_len * 5 / 2
lng_len = str_len * 5 / 2
if str_len % 2 == 1:
lng_len += 1
latitude_bit_array = as_bit(latitude, lat_len, -90.0, 90.0)
longtitude_bit_array = as_bit(longtitude, lng_len, -180.0, 180.0)
# 5桁ごとにまとめる
mixed_bit_array = []
bit_array = []
for i in range(str_len*5):
if i % 2 == 0:
mixed_bit_array.append(longtitude_bit_array.pop(0))
else:
mixed_bit_array.append(latitude_bit_array.pop(0))
if (i+1) % 5 == 0:
bit_array.append(''.join(mixed_bit_array))
mixed_bit_array = []
# Base32に変換する
geohash_str = []
for bit in bit_array:
for k, v in base32.iteritems():
if bit == v:
geohash_str.append(k)
return ''.join(geohash_str)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment