Skip to content

Geocoding provides function to find cities according to latitude/longitude coordinates.

License

Notifications You must be signed in to change notification settings

davidjulien/erlang-geocoding

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Geocoding does not rely on any external API. It relies on an internal (huge) database of 165,602 coordinates corresponding to cities of more than 500 inhabitants (see Data sources for more details).

Compile, test and try

Compilation:

rebar compile

Tests:

rebar eunit

Usage:

> erl -pa _build/default/lib/geocoding/ebin/ 
Erlang/OTP 23 [erts-11.1.8] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe] [dtrace]

Eshell V11.1.8  (abort with ^G)
1> application:start(geocoding).
ok

2> geocoding:reverse(48.857929, 2.346707).
{ok,{2988507,europe,fr,<<"Paris">>,525.451956}}

3> geocoding:distance({48.857929, 2.346707}, {40.7630463, -73.973527}).
5832947

4> geocoding:lookup('FR', <<"paris">>).
{ok,{2988507,{48.85341,2.3488},europe,'FR',<<"Paris">>}}

geocoding:reverse/2 returns the geoname id, continent name, country code (ISO 3166-1 alpha-2), city name, distance between city center and provided coordinates.

Installation

Erlang (rebar3):

{deps, [
  {geocoding, "0.4.0"}}
]}

Elixir (mix):

defp deps do
  [
    {:geocoding, "~> 0.4.0"}
  ]
end

Database rebuilding

An escript allows to rebuild your cities.txt data from geonames. It will fetch the last version of cities500.zip, unzip it, filter out city with too low population, and build continent name. It will generate a cities.txt.new file. Existing citiers.txt will not be erased.

> ./scripts/cities_builder.escript

If you want to replace your cities.txt, add --replace parameter. Old cities.txt will be renamed to cities.txt.old.

> ./scripts/cities_builder.escript --replace

Technical information

Algorithm

Reverse geocoding is done thanks to a k-d tree algorithm. We use Martin F. Krafft implementation. Original source code is here: https://github.com/kbranigan/libkdtree/tree/master/kdtree%2B%2B . It is embeded in an erlang driver.

From latitude/longitude coordinates, geocoding finds the nearest point in our locations database. Associated data are returned, as well as a distance between provided coordinates and real coordinates. Since reverse geocoding relies only on coordinates, strange behaviour may occured when a big city is near a small one: a point inside the big city and near its border may be associated to the small city because the small city coordinates will be nearest than the big city coordinates.

Data sources

All locations data come from https://www.geonames.org database (http://download.geonames.org/export/dump/cities500.zip - 2024-12-05):

  • Locations without population have been excluded.
  • PPLX (section of populated places) and PPLA5 (seat of a fifth-order administrative division) have been excluded.
  • Fields have been reduced to: geonameId, latitude, longitude, country code (ISO-3166), standard name. A 6th fields have been added between longitude and country code: continent. Each field is separated by a tabulation.

Example:

2988507 48.85341        2.3488  europe  FR      Paris

Each location is associated to one of the following continents:

  • africa (africa and islands nearby like Madagascar, Canary, La Réunion...)
  • antarctica (only one country)
  • asia (including russian cities after Ural Mountains)
  • europe (including russian cities before Ural Mountains)
  • oceania (including Australia continent and pacific islands)
  • north america
  • south america

Missing locations may be added on request.

About

Geocoding provides function to find cities according to latitude/longitude coordinates.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published