module Geohash

Constants

BASE32
BORDERS
NEIGHBORS
VERSION

Public Instance Methods

adjacent(geohash, dir) click to toggle source

Calculate adjacent geohashes

@params {String} geohash @params {Symbol} dir - one of :right, :left, :top, :bottom

@return {String} adjacent geohash

# File lib/geohash_ruby.rb, line 136
def adjacent(geohash, dir)
  return @@adjacent_cache[dir][geohash] if @@adjacent_cache[dir][geohash]

  head, last = geohash[0..-2], geohash[-1]
  parity = geohash.length & 1

  head = adjacent(head, dir) if BORDERS[dir][parity].include?(last)

  # NOTICE: do not use append `<<` instead of `+=`
  head += BASE32[NEIGHBORS[dir][parity].index(last)]

  @@adjacent_cache[dir][geohash] = head
end
decode(geohash) click to toggle source

Decode geohash into bounding box of latitudes and longitudes

@params {String} geohash - geohash code

@return {[[Float]]} decoded bounding box

[
  [north_latitude, west_longitude],
  [south_latitude, east_longitude]
]
# File lib/geohash_ruby.rb, line 53
def decode(geohash)
  bounds = [[-90.0, +90.0], [-180.0, +180.0]]

  geohash.downcase.each_char.with_index do |c, i|
    d = BASE32.index c

    5.times do |j|
      bit = (d & (1 << (4 - j))) >> (4 - j)
      k = (~i & 1) ^ (j & 1)
      bounds[k][bit ^ 1] = (bounds[k][0] + bounds[k][1]) / 2
    end
  end

  bounds.transpose
end
encode(latitude, longitude, precision = 12) click to toggle source

Encode latitude and longitude into geohash

@params {Float} latitude @params {Float} longitude @params {Integer} precision - scale from 1 to 12

@return {String} geohash string

# File lib/geohash_ruby.rb, line 78
def encode(latitude, longitude, precision = 12)
  mids = [latitude, longitude]
  bounds = [[-90.0, +90.0], [-180.0, +180.0]]

  geohash = ''

  precision.times do |i|
    d = 0

    5.times do |j|
      k = (~i & 1) ^ (j & 1)
      mid = (bounds[k][0] + bounds[k][1]) / 2
      bit = mids[k] > mid ? 1 : 0
      bounds[k][bit ^ 1] = mid
      d |= bit << (4 - j)
    end

    geohash << BASE32[d]
  end

  geohash
end
neighbors(geohash) click to toggle source

Calculate neighbors geohash

@params {String} geohash

@return {[String]} neighbors array

# File lib/geohash_ruby.rb, line 108
def neighbors(geohash)
  return @@neighbors_cache[geohash] if @@neighbors_cache[geohash]

  # walk path:
  #
  # 8   1 - 2
  # |   |   |
  # 7   B   3
  # |       |
  # 6 - 5 - 4
  #
  @@neighbors_cache[geohash] = walk geohash, [
    :top,
    :right,
    :bottom, :bottom,
    :left, :left,
    :top, :top
  ]
end
walk(base, path) click to toggle source

Walk down

@params {String} base - base geohash to begin walk @params {[Symbol]} path - directions to walk with

@return {[String]} result geohashes of the walk

# File lib/geohash_ruby.rb, line 158
def walk(base, path)
  path.map { |dir| base = adjacent(base, dir) }
end