Fast reverse geocoding with offline-geocoder

Inakos
2 min readJan 18, 2017

--

Sometimes, you can find yourself having to reverse geocode a large bunch of points. That is, finding an address from a coordinate pair (latitude and longitude). Some time ago, I found myself in that situation: we were developing an app containing a pretty big dataset of locations, having a latitude and a longitude, but lacking an address.

What you usually do is buy a service to reverse geocode your data. However, this is slow and expensive, and sometimes all you need is an approximate address, a city, to put the place in the map. We found ourselves in that scenario. We did not need high precision, we only wanted to know where, in a general sense, the locations belonged.

So, with such requirements in mind, we built the offline-geocoder gem. This gem contains a pretty large dataset of cities (over 138000 entries). Each entry contains city coordinates, name, administrative unit, and country. Offline-geocoder uses the awesome gem kdtree to create a kd tree with all this data in order to find the nearest neighbor for a specific pair of coordinates. A kd tree is a data structure that recursively partitions the world in order to rapidly answer nearest neighbor queries. A generic kd tree can support any number of dimensions, and can return either the nearest neighbor or a set of N nearest neighbors.

Searching through this kd tree is blazingly fast. Once you enter a coordinate pair, the gem can return the nearest city instantly. For instance, in my machine (a 4 core i7) offline-geocoder can find more than 181.000 locations per second.

Using this gem is pretty easy too. You can install it in the usual fashion:

  • Add this line to your application’s Gemfile:
gem 'offline_geocoder'

Then execute:

$ bundle
  • Or install it yourself as:
  • $ gem install offline_geocoder

Once that is done, you can use it like this:

require "offline_geocoder"geocoder = OfflineGeocoder.newresults = geocoder.search(51.5214588, -0.1729636)p results

The above code will output this:

{
:lat=>51.51116,
:lon=>-0.18426,
:name=>"Bayswater",
:admin1=>"England",
:admin2=>"Greater London",
:cc=>"GB",
:country=>"United Kingdom"
}

And… That’s it! I do hope this gem can find many uses and solve many headaches and problems. As always, if you have any suggestions or further questions related to this, please leave a comment or find me and my friends at inaka.github.io.

--

--