ooRexx logo
   1: #!/usr/bin/env rexx
   2: /*------------------------------------------------------------------*/
   3: /* Routine to retrieve an address from a latitude/longitude pair    */          
   4: /* by utilizing the facilities provided by:                         */    
   5: /*                                                                  */
   6: /* https://nominatim.openstreetmap.org                              */
   7: /*                                                                  */
   8: /* @param   latitude  - in decimal degrees                          */
   9: /*                                                                  */
  10: /* @param   longitude - in deicmal degrees                          */
  11: /*                                                                  */
  12: /* @param   language  - in odes like "en", "de", "nl" etc.  see:    */
  13: /*                                                                  */
  14: /* https://wiki.openstreetmap.org/wiki/Nominatim/Country_Codes      */
  15: /*                                                                  */
  16: /* @param   level     - the level of detail of the result:          */
  17: /*                                                                  */
  18: /*                      3  - country                                */
  19: /*                      4  - state                                  */
  20: /*                      8  - county                                 */
  21: /*                      10 - city                                   */
  22: /*                      14 - suburb                                 */
  23: /*                      16 - major streets                          */
  24: /*                      17 - major and minor streets                */
  25: /*                      18 - building                               */
  26: /*                                                                  */
  27: /* @returns address   - such as 1600 Pennsylvania Avenue Washin.... */
  28: /*                                                                  */
  29: /* Can be invoked from the command line:                            */
  30: /*                                                                  */
  31: /*       "nominatim_address_from_latlon.orx" lat lon lvl            */
  32: /*                                                                  */
  33: /* Or as a subroutine or function:                                  */
  34: /*                                                                  */
  35: /*       call nominatim_address_from_latlon lat, lon, lvl           */    
  36: /*                                                                  */
  37: /*       nominatim_address_from_latlon(lat, lon, lvl)               */   
  38: /*                                                                  */
  39: /* The latter two should use a:                                     */
  40: /*                                                                  */
  41: /*   ::requires "nominatim_address_from_latlon.orx"                 */
  42: /*                                                                  */
  43: /* For ooRexx 5.0.0 or later only                                   */
  44: /*                                                                  */
  45: /*------------------------------------------------------------------*/
  46: /*                                                                  */
  47: /* Originally by Ruurd J. Idenburg                                  */
  48: /*                                                                  */
  49: /* No copyright, no licence, no guarantees or warrantees, be it     */
  50: /* explicit, implicit or whatever. Usage is totally and completely  */
  51: /* at the users own risk, the author shall not be liable for any    */ 
  52: /* damages whatsoever, for any reason whatsoever.                   */
  53: /*                                                                  */
  54: /* Please keep this comment block intact when modifying this code   */
  55: /* and add a note with date and a description.                      */
  56: /*                                                                  */
  57: /*------------------------------------------------------------------*/
  58: /*                                                                  */
  59: /* 2021/05/02 - Initial version                                     */
  60: /*                                                                  */
  61: /*------------------------------------------------------------------*/
  62: 
  63: parse source os how me
  64: if how=="COMMAND" then do
  65:   if .sysCArgs[3]==.nil then .sysCArgs[3] = "nl"
  66:   if .sysCArgs[4]==.nil then .sysCArgs[4] = 16
  67:   address = nominatim_address_from_latlon(.sysCArgs[1],-
  68:                                           .sysCArgs[2],-
  69:                                           .sysCArgs[3],-
  70:                                           .sysCArgs[4])
  71:   say address
  72: end
  73: exit
  74: 
  75: ::routine nominatim_address_from_latlon public
  76: use strict arg lat, lon, lng="nl", lvl=16
  77: /*------------------------------------------------------------------*/
  78: /* nominatim appreciates a non standard https-header for User_Agent */
  79: /* I have mine stored as an linux environment variable via .profile */
  80: /* but it can be hardcoded as well of course.                       */
  81: /*------------------------------------------------------------------*/
  82: myAgent = value("USER_AGENT", ,"ENVIRONMENT")
  83: /*------------------------------------------------------------------*/
  84: /* nominatim appreciates an e-mail address in case of frequent and  */
  85: /* multiple requests. I keep mine as a Linux environment variable,  */
  86: /* but it can be hardcoded as well of course.                       */
  87: /*------------------------------------------------------------------*/
  88: myEmail = value("MY_EMAIL", ,"ENVIRONMENT")
  89: /*------------------------------------------------------------------*/
  90: /* nominatim usage guidelines suggest not to issue more than one    */
  91: /* request per second, so we'll wait 1 second before issueing the   */
  92: /* request for the case we do multiple requests in a short period.  */
  93: /*------------------------------------------------------------------*/
  94: call sysSleep(1)
  95: /*------------------------------------------------------------------*/
  96: /* We use the (new in ooRexx 5.0.0) "ADDRESS SYSTEM WITH" keyword   */
  97: /* instruction to issue the request via "CURL" (https://curl.se/)   */
  98: /*------------------------------------------------------------------*/
  99: jsonArray = .array~new
 100: -- Direct output from CURL to an array   
 101: address system with output using (jsonArray)
 102: "curl -s -A "myAgent" 'https://nominatim.openstreetmap.org/reverse?"-
 103:        "format=json&lat="lat"&lon="lon"&zoom="lvl"&addressdetails=1"-
 104:        "&limit=1&accept-language="lng"&email="myEmail"'"
 105: -- Switch output back to normal
 106: address system with output normal
 107: -- Uncomment to see the whole result from CURL
 108: --say jsonArray
 109: -- Create the ooRexx (.directory) equivalent of the JSON
 110: rexx = .json~new()~fromJSON(jsonArray~toString("C"))
 111: address = ""
 112: -- Without error
 113: if \rexx~hasindex("error")then do
 114:   address = rexx["display_name"]
 115: end
 116: -- With error
 117: else do
 118:   address = "ERROR: "
 119:   do e over rexx["error"]
 120:     address ||= rexx["error"][e]" " 
 121:   end
 122: end
 123: if address = "" then address = "UNKNOWN"
 124: return address
 125: 
 126: ::routine addr_from_latlon public
 127: lng = arg(3)
 128: lvl = arg(4)
 129: if lng=="" then lng = "en"
 130: if lvl=="" then lvl = 16
 131: return nominatim_address_from_latlon(arg(1), arg(2), lng, lvl)
 132:   
 133: ::requires json.cls
All content © Ruurd Idenburg, 2007–2025, except where marked otherwise. All rights reserved. This page is primarily for non-commercial use only. The Idenburg website records no personal information and sets no ‘cookies’. This site is hosted on my on server at my home, falling under Dutch (privacy) laws.

This page updated on Wed, 28 May 2025 10:38:18 +0200.