Geocoding

Max Kleiner
5 min readMar 2, 2022

Geocoding (also known as forward geocoding) allows you to convert one or more addresses into geographic coordinates (i.e. latitude and longitude). Geocoding will also parse the address and append additional information (e.g. if you specify a zip code, Geocodio will return the city and state corresponding the zip code as well).

Geocodio supports geocoding of addresses, cities and zip codes in various formats.

Geocodio provides bulk geocoding and reverse lookup services through a REST API. The API is able to process a single address, as well as handle bulk requests of up to 10,000 addresses. Geocoded results are returned with an accuracy score indicating the confidence Geocodio has in the accuracy of the result. Geocodio is also able to parse addresses into individual components.

Geographic coordinates of Delphi, Greece
Latitude: 38°28'45" N
Longitude: 22°29'36" E
Elevation above sea level: 560 m = 1837 ft

Geographic coordinates of Bern, Switzerland
Latitude: 46°56'53" N
Longitude: 7°26'50" E
Elevation above sea level: 549 m = 1801 ft

First I tried with Google Maps:

Then I got the message to bill something with credit card an I denied:

Exception: TJSONObject["status--\u0020You\u0020must\u0020enable\u0020Billing\u0020on\u0020the\u0020Google\u0020Cloud\u0020Project\u0020at\u0020https\u003A//console.cloud.google.com/project/_/billing/enable\u0020Learn\u0020more\u0020at\u0020https\u003A//developers.google.com/maps/gmp-get-started"] not found.

So I started with Geocodio https://www.geocod.io/docs/#geocoding and registered to get an API Key.

Geocodio’s RESTful API allows you to perform forward and reverse geocoding lookups. We support both batch requests as well as individual lookups.

You can also optionally ask for data appends such as timezone, Congressional districts or similar things of that nature.

The base API url is https://api.geocod.io/v1.7/.

All HTTP responses (including errors) are returned with JSON-formatted output. For the code I tested with Python and maXbox with an Wininet and JSON Object:

function TAddressGeoCoding4(faddr, fcountry: string): String; var Url,API_KEY, source: string; jo, locate: TJSONObject; urlid: TIdURI; fLat,fLong: double; begin urlid:= TIdURI.create(''); API_KEY:='785b4141b...................'; //get your own one please if fcountry <> '' then Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+ fAddr+'&country='+fcountry+'&api_key='+API_KEY) else Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+ fAddr+'&api_key='+API_KEY); jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil)); try jo.getString('input') locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location'); source:= jo.getJSONArray('results').getJSONObject(0).getString('source'); //geometry.getJSONObject('coordinates'); fLat:= locate.getDouble('lat') fLong:= locate.getDouble('lng'); result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]); except Xraise(Exception.Create(jo.getString('error'))); finally jo.Free; urlid.free; end; end;

You can test your REST-Call direct in the browser with: https://api.geocod.io/v1.7/geocode?q=cologne&api_key=785b4141b&#8230;

Or you choose a map one tester online: https://www.geoapify.com/geocoding-api

One note to the code function above. We pass and adress and optional the country (to prevent name conflicts) to get the coordinates from the location:

In most cases, the standard output format would be used. In certain situations, it can however be beneficial to work with a JSON structure that is specifically designed for your use case.

writeln(TAddressGeoCoding4('Ontario','Canada'));>>> Coordinates: lat 50.445 lng -86.047 :CanVec+ by Natural Resources Canada

The intersting part is jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil)); with the constructor to pass the httpget2 which returns the json result in one line to the json-object.

If a JSON object is posted, you can specify a custom key for each element of your choice. This can be useful to match queries up with your existing data after the request is complete. If using a JSON array, results are guaranteed to be returned in the same order as they are requested.

Reverse geocoding is the process of converting latitude and longitude into a street address.

Geocodio will find matching street(s) and determine the correct house number based on the location. Note that Geocodio does not guarantee to return a valid house number; it is our closest approximation.

After some calls we get an overview of the usage:

The Geocodio API implements the concept of “warnings”. This is meant to assist and guide developers when implementing our API. But I checked also the error as Json field in the try except catch. To prevent misleading, inconsistent or duplicated locations like Cologne, Paris or Bern all over the world we should also check the source as identity authentication too:

try jo.getString('input') locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location'); source:= jo.getJSONArray('results').getJSONObject(0).getString('source'); fLat:= locate.getDouble('lat') fLong:= locate.getDouble('lng'); result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]); except Xraise(Exception.Create(jo.getString('error'))); finally

If a city is provided without a state, Geocodio will automatically guess and add the state based on what it is most likely to be. Geocodio also understands shorthands for both streets and cities, for example NYC, SF, etc., are acceptable city names.

All results come with an address_components dictionary. This is an overview of all of the possible keys that you may find. The API is public for more insights:

https://github.com/Geocodio/openapi-spec/blob/master/geocodio-api.yml

The Geocodio API is continuously improved. Most updates require no changes for API users, but in some cases we might have to introduce breaking changes. Each geocoded result is returned with an accuracy score, which is a decimal number ranging from 0.00 to 1.00. This score is generated by the internal Geocodio engine based on how accurate the result is believed to be. The higher the score, the better the result. Results are always returned ordered by accuracy score.

More docs on: https://www.geocod.io/docs/#geocoding

OpenStreetMap

With OpenStreetMap the call is easy just to get an https and a preconfigured user-agent to provide:

var winsets: TNetUtilsSettings; destfile: widestring; msst: TStringstream;

url:= urlid.URLEncode('https://nominatim.openstreetmap.org/search?format=json&q=fAddr);
winsets.UserAgent:= Cuseragent;
msst:= TStringStream.create('');
writeln(botostr(InetDownload(Url, msst, Nil)));
jo:= TJSONObject.Create4(msst.datastring);
writeln(jo.getstring('lat'));

and the output:

[{"place_id":282193469,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":62578,"boundingbox":["50.8304399","51.0849743","6.7725303","7.162028"],"lat":"50.938361","lon":"6.959974","display_name":"Cologne, North Rhine-Westphalia, Germany","class":"boundary","type":"administrative","importance":0.9006323589104861,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"}]

Originally published at http://maxbox4.wordpress.com on March 2, 2022.

OpenStreetMap (OSM) is a collaborative project to create a free editable map of the world. It is built by a community of mappers that contribute and maintain OSM data.

This endpoint is used to reverse geocode, this is, generate an address from a latitude and a longitude. This is the format of the request:

with TWinApiDownload.create do begin
Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1';
Url:= 'https://nominatim.openstreetmap.org/reverse?lat='
+flots(flat)+'&lon='+flots(flong)+'&zoom=10&format=json';
Download1(rest);

with
TJSONObject.create4(rest) do begin
writeln('display_name: '+getstring('display_name'));
free;
end;
free; //ApiDownload
end;

--

--

Max Kleiner

Max Kleiner's professional environment is in the areas of OOP, UML and coding - among other things as a trainer, developer and consultant.