Geolocalizzazione di indirizzi (geocoding) con PHP o jQuery e Nominatim di OpenStreetMap

Geolocalizzare
Geolocalizzare

La definizione di geolocalizzazione è ben descritta su Wikipedia:

La geolocalizzazione è l’identificazione della posizione geografica nel mondo reale di un dato oggetto, come ad esempio un telefono cellulare o un computer connesso o meno ad Internet, secondo varie possibili tecniche.

Dunque, si tratta di convertire in coordinate geografiche un dato oggetto, che più frequentemente è un indirizzo di un edificio o di un terreno, ecc. E’ anche possibile ottenere le coordinate di un comune o di una qualsiasi località. Mediante l’azione inversa (reverse geocoding) è invece possibile determinare la toponomastica dalle coordinate geografiche.

Alcuni anni fa avevo scritto degli articoli su come utilizzare il servizio di Google: Google Maps API. Purtroppo Google ha cambiato frequentemente sia gli strumenti (le API) che le policy di utilizzo quindi gli script che avevo implementato non sono più utilizzabili.

openstreetmap
Mappa OpenStreetMap

Ho trovato altri servizi alternativi che si basano sulle mappe di OpenStreetMap che, a differenza di Google, è dichiaratamente Open Data con licenza ODbl. Per la geolocalizzazione degli indirizzi esiste un servizio basato su OpenStreetMap che si chiama Nominatim che adotta condizioni di utilizzo meno stringenti di quelle di Google.

Ho preparato un paio di esempi su come utilizzare questo tool di geolocalizzazione: uno è esclusivamente client-side e utilizza script javascript / jQuery mentre l’altro è basato su uno script server-side in linguaggio PHP.

Vediamo il codice del primo esempio (in Javascript / jQuery ):

HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        <h2>Inserisci l'indirizzo di una località</h2>
        <form name='geocoding' id='geocoding' action='' method='post'>
			<label for='address'>Indirizzo:
			<input type='text' name='address' id='address' placeholder='Es: 1 Piazza del Colosseo'>
			</label><br>
			<label for='city'>Città:
			<input type='text' name='city' id='city' placeholder='Es: Roma'>
			</label><br>
			<label for='county'>Provincia:
			<input type='text' name='county' id='county' placeholder='Es: RM'>
			</label><br>
			<label for='country'>Nazione:
			<input type='text' name='country' id='country' placeholder='Es: Italy'>
			</label><br>
			<button type="submit" name='submitButton' id='submitButton'>Invia</button>
			<button type="reset" name='reset' id='reset'>Pulisci</button>
		</form>
      </div>
      <div class="one-half column" style="margin-top: 5%">
        <h4>Risultato:</h4>
		<div id='results'>
		</div>
      </div>
    </div>

Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
	$(document).ready(function(){		
		$( "#geocoding" ).submit(function( event ) {
			$('#results').html("");
			var address = $('#address').val().replace(","," ");
			address =  $.trim(address);
			var city = $('#city').val().trim();
			var county = $('#county').val().trim();
			var country = $('#country').val().trim();
			var query_string = address+","+city+","+county+","+country;
			query_string += "&format=json&limit=1&polygon=0&addressdetails=0";
			var geocodingAPI = "http://nominatim.openstreetmap.org/search?q=";
			geocodingAPI += query_string;
			$.getJSON(geocodingAPI, function (json) {
				//console.log(json);
				if ($.isEmptyObject(json)) {
					$('#results').html('<p>Nessun risultato!</p>');
				} else {
					var table = '<table>';
					$.each(json[0], function(key, value) {
						table += '<tr><td>'+key+'</td><td>'+value+'</td></tr>';
					});
					table += '</table>';
					$('#results').append(table);
					$('#results').append("<p><a href='"+geocodingAPI.replace("json","html")+"'>Vedi il risultato su OpenStreetMap</a></p>");
				}
			});	
 
		  event.preventDefault();
 
		});
 
	  $('#reset').click(function(){
			$('#results').html("");
			return true;
	  });			
	});

Ed ecco infine lo stesso form processato in PHP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id='results'>
	<?php
		if (!empty($_POST)) {
			$geocodingAPI = "http://nominatim.openstreetmap.org/search?q=";
			$_POST = array_map('clean', $_POST);
			extract($_POST);
			$address = str_replace(","," ",$address);
			$qs = $address.",".$city.",".$county.",".$country;
 
			$qs .= "&format=json&limit=1&polygon=0&addressdetails=0";
			$rs = json_decode(file_get_contents($geocodingAPI.$qs));
 
			echo "<table>\n";
			echo "<tr> <td>place_id</td> <td>".$rs[0]->place_id."</td> </tr>\n";
			echo "<tr> <td>licence</td> <td>".$rs[0]->licence."</td> </tr>\n";
			echo "<tr> <td>osm_type</td> <td>".$rs[0]->osm_type."</td> </tr>\n";
			echo "<tr> <td>osm_id</td> <td>".$rs[0]->osm_id."</td> </tr>\n";
			echo "<tr> <td>boundingbox</td> <td>".$rs[0]->boundingbox."</td> </tr>\n";
			echo "<tr> <td>lat</td> <td>".$rs[0]->lat."</td> </tr>\n";
			echo "<tr> <td>lon</td> <td>".$rs[0]->lon."</td> </tr>\n";
			echo "<tr> <td>display_name</td> <td>".$rs[0]->display_name."</td> </tr>\n";
			echo "<tr> <td>class</td> <td>".$rs[0]->class."</td> </tr>\n";
			echo "<tr> <td>type</td> <td>".$rs[0]->type."</td> </tr>\n";
			echo "<tr> <td>importance</td> <td>".$rs[0]->importance."</td> </tr>\n";
			echo "</table>\n";
 
			$linkQs = str_replace("json","html",$qs);
 
			echo "<p><a href='".$geocodingAPI.$linkQs."'>Vedi il risultato su OpenStreetMap</a></p>";
 
		}
		function clean($el)	{
			 return urlencode(strip_tags(trim($el)));
		}			
	?>
</div>

Nella querystring ho utilizzato i seguenti parametri:

qla query con l’indirizzo, la città, la provincia e la nazione
format[html|xml|json|jsonv2]
limit<integer>
polygon[0|1]
addressdetails[0|1]

la lista completa dei parametri utilizzabili è disponibile qui

Il risultato (ho utilizzato il formato json per l’output) viene fornito con questi valori (utilizzando come esempio: indirizzo: 1 Piazza del Colosseo, Città: Roma, Provincia: RM, Nazione: Italy):

place_id102590955
licenceData © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright
osm_typeway
osm_id203150440
boundingboxArray
lat41.890631
lon12.4944853
display_namePiazza del Colosseo, Monti, Municipio Roma I, Roma, RM, LAZ, 00184, Italia
classhighway
typesecondary
importance0.62

Il significato dei singoli valori è intuitivo.

Un esempio di funzionamento dello script javascript / jQuery è disponibile qui.
Un esempio di funzionamento dello script PHP è disponibile qui.

Riferimenti: