Created
February 4, 2010 12:53
-
-
Save yuribossa/294599 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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