Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geohashing - recursively find neighbors of neighbors

I am now looking for an elegant algorithm to recursively find neighbors of neighbors with the geohashing algorithm (http://www.geohash.org).
Basically take a central geohash, and then get the first 'ring' of same-size hashes around it (8 elements), then, in the next step, get the next ring around the first etc. etc. Have you heard of an elegant way to do so?

Brute force could be to take each neighbor and get their neighbors simply ignoring the massive overlap. Neighbors around one central geohash has been solved many times (here e.g. in Ruby: http://github.com/masuidrive/pr_geohash/blob/master/lib/pr_geohash.rb)

Edit for clarification: Current solution, with passing in a center key and a direction, like this (with corresponding lookup-tables):

  def adjacent(geohash, dir)
    base, lastChr = geohash[0..-2], geohash[-1,1]
    type = (geohash.length % 2)==1 ? :odd : :even
    if BORDERS[dir][type].include?(lastChr)
      base = adjacent(base, dir)
    end
    base + BASE32[NEIGHBORS[dir][type].index(lastChr),1]
  end

(extract from Yuichiro MASUI's lib)

I say this approach will get ugly soon, because directions gets ugly once we are in ring two or three. The algorithm would ideally simply take two parameters, the center area and the distance from 0 being the center geohash only (["u0m"] and 1 being the first ring made of 8 geohashes of the same size around it (=> [["u0t", "u0w"], ["u0q", "u0n"], ["u0j", "u0h"], ["u0k", "u0s"]]). two being the second ring with 16 areas around the first ring etc.

Do you see any way to deduce the 'rings' from the bits in an elegant way?

like image 305
itsme Avatar asked Jun 10 '10 20:06

itsme


1 Answers

That depends on what you mean by Neighbor. I'm assuming this is being used in the context of a proximity search. In that case I would think that your best bet would be to search from the outermost ring inward.

Assume you can find the outermost set (longest proximity) in the searchable Universe. Store that as the new Universe and then find the next inner set in that Universe. This search should subtract that inner set from the Universe. Store the old Universe (the outermost ring) and repeat this process until you hit the center. Each search after the first one will reduce your search area and give you a ring.

like image 157
philosodad Avatar answered Sep 18 '22 17:09

philosodad