Decoding Geohashes in pure Ruby
Wrote this for work, threw it away again in favour of using an actual gem that someone else will maintain,
but I thought I'd put it here anyway, because it might be useful. Also, the gem is written in C and therefore
hard to deploy sometimes.
#!/usr/bin/env ruby
# pure-ruby geohash decoding function
# default is the example from http://en.wikipedia.org/wiki/Geohash
geohash = ARGV[0] || "ezs42"
# convert geohash into a bit sequence
map = "0123456789bcdefghjkmnpqrstuvwxyz" # silly custom base32 mapping
bits = geohash.split("").map{|c|
i = map.index(c) or raise("bad geohash (#{c} not permitted)")
sprintf("%05s", i.to_s(2)).gsub(" ","0").split("")
}.flatten
# even bits are longitude, odd bits are latitude.
# probably a better way of doing this part, feels non-ruby-like..
lat_bits = []
lng_bits = []
bits.each_with_index{|b,i|
if i % 2 == 1
lat_bits << b
else
lng_bits << b
end
}
# subdivide the world according to the bit sequences
def decode(bits, range)
range = [ range.to_f * -1, range.to_f ]
for b in bits
if b == "1"
range[0] = (range[0] + range[1])/2
else
range[1] = (range[0] + range[1])/2
end
end
return range
end
lat_range = decode( lat_bits, 90 )
lng_range = decode( lng_bits, 180 )
puts "lat is range #{ lat_range.inspect }"
puts "lng is range #{ lng_range.inspect }"