Geo encoding a location Part 3

  • Antony Pinchbeck
  • 2020-09-11
  • Elixir

Project source code: https://github.com/antp/locations

GEO encoding an address

Before an address can be located, the user needs a mechanism to enter an address. A Phoenix LiveView UI is included in the project to enable the entering, editing, deletion and geolocating of an address.

Once a location is saved, the user can select the get Map button to trigger the GEO location process.

This starts with a call to the location context Locations.get_map_for(location) function. This delegates to the following module to perform the encoding.

defmodule Locations.Location.GetMapFor do
   alias Locations.GeoEncode.{
    Address,
    Lookup,
    Nominatim
  }

  def call(location) do
    address = Address.build_address(location)

    case Lookup.geoencode(address) do
      {:ok, 200, response} ->
        Nominatim.get_location(response)

      other ->
        other
    end
  end
end

The responsibilities of the three modules Address, Lookup and Nominatim are simple and they cooperate to obtain the geographical information.

  • The Address module, purely converts a location to a query string to be used by Nominatim.
  • The Lookup module queries the Nominatim service and on success converts the result from JSON to an elixir struct.
  • The Nominatim module, extracts the features from the data returned from the lookup stage.

Any errors are returned to the caller. In most cases this will be because the user has an error in the entered address.

The code for these modules can be found in lib\locations\geo_encode.

By creating the struct:

%{
    addr1: “Dinton Village Hall”,
    addr2: “Upton Road”,
    city: “Dinton”,
    country:  “Buckinghamshire”
    postcode: “HP17 8UQ”,
    country: “United Kingdom”
}

And passing it to locations.get_map_for, the following is returned.

{:ok,
 [
   %{
     "bbox" => [-0.8943214, 51.7903516, -0.8939829, 51.7905312],
     "geometry" => %{
       "coordinates" => [-0.8941397157675615, 51.7904389],
       "type" => "Point"
     },
     "properties" => %{
       "category" => "amenity",
       "display_name" => "Dinton Village Hall, Upton Road, Dinton-with-Ford and Upton, Dinton, Buckinghamshire, South East, England, HP17 8UQ, United Kingdom",
       "importance" => 1.1309999999999998,
       "osm_id" => 602254458,
       "osm_type" => "way",
       "place_id" => 209962616,
       "place_rank" => 30,
       "type" => "community_centre"
     },
     "type" => "Feature"
   }
 ]}

At this point no data is saved to the database. In this simple case, with only one location, there are no decisions to be made and the map with its location marker can be displayed. For multiple features, user interaction is required.

Next: How to display the map.

© 2001 - 2020 Component X Software Limited All rights reserved.

Lynx: 2.4.5