jerakeen.tumblr

I'm Tom Insam and I still can't decide where I want to host my content. More about me.

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 }"
More Information