Questo post ha più di 1 anno. Il contenuto potrebbe essere obsoleto, non più completamente accessibile o mancante di alcune informazioni.
Ecco un esempio di utilizzazione del widget P4A Google Maps per creare una mappa di riferimenti (negozi, magazzini, ecc) che siano compresi in un certo raggio di distanza in Km, a partire da un indirizzo prestabilito.
Ho cercato di utilizzare il widget di Alberto Galanti senza effettuare nessuna modifica al codice originale. Ho scelto, quindi di implementare un metodo che fornisce la georeferenza della località che funge da centro, per poi effettuare, attraverso una query, la selezione degli indirizzi compresi nel raggio di distanze prestabilito.
L’esempio utilizzato, per comodità, è lo stesso indicato dalla guida di Google Maps in questo articolo.
I passi principali prima di procedere:
- Scaricare il widget P4A Google Maps qui
- Creare un archivio di riferimenti che abbiano un indirizzo nel formato accettato da Google Maps (Es.: “Piazza Venezia, Roma, Italia”)
- Georeferenziare tutti gli indirizzi (trovare latitudine e longitudine)
Utilizzando MySQL, la struttura dell’archivio suggerita da Google è questa:
1 2 3 4 5 6 7 8 | CREATE TABLE `markers` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(60) NOT NULL, `address` VARCHAR(80) NOT NULL, `lat` FLOAT(10,6) NOT NULL, `lng` FLOAT(10,6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; |
Per comodità potete scaricare l’sql completo dei dati di esempio di Google qui
Nel caso non si conoscano già le coordinate dei riferimenti, è possibile utilizzare il metodo suggerito in questo articolo sempre da Google. Questo sistema permette di aggiornare direttamente i dati di un database MySQL con le coordinate fornite da Google Maps per tutti gli indirizzi memorizzati.
La selezione dei record che sono compresi in un reggio di distanza in Km prefissato, avviene tramite una query che utilizza la formula della triangolazione sferica:
cos p = cos a cos b + sen a sen b cos φ,
per maggiori dettagli potete leggere questo post.
Ecco la query in pratica:
1 2 3 4 5 6 7 8 | SELECT address, name, lat, lng, ( 6371 * acos( cos( radians('Center_latitude')) * cos( radians( lat )) * cos( radians( lng ) - radians('Center_longitude')) + sin( radians('Center_latitude')) * sin( radians( lat )))) AS distance FROM markers HAVING distance < 'Radius' ORDER BY distance |
dove 'Center_latitude'
è la latitudine del centro, 'Center_longitude'
è la longitudine del centro e 'Radius'
è il raggio in km dal centro.
Ed ecco dunque, il codice della maschera P4A:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | class GoogleMap extends P4A_Mask { function GoogleMap() { parent::P4A_Mask(); $this->setTitle("Google Map Store Locator Test"); // Frame $this->build("p4a_frame", "frame"); $this->frame->setWidth(800); //la chiave per localhost è disponibile nel file p4a_map.php $coordArray = $this->getLocationCoordinates("Mountain View, CA", "Inserire_chiave_Google"); $radius = 12; // DB Source $this->build("p4a_db_source", "source"); $query = "SELECT address, name, lat, lng, CONCAT_WS(' ', name, address) AS info, (6371 * acos(cos(radians('$coordArray[2]')) * cos(radians(lat)) * cos( radians(lng) - radians('$coordArray[3]')) + sin( radians('$coordArray[2]')) * sin( radians(lat)))) AS distance FROM markers HAVING distance < '$radius' ORDER BY distance"; $this->source->setQuery($query); $this->source->setPk("id"); $this->source->load(); // map $map =& $this->build("p4a_map","mappa"); $map->setCenter("Mountain View, CA"); $map->setZoom(10); $map->setWidth(750); $map->setHeight(500); // markers from datasource $map->setSourceAddressField("address"); //$map->setSourceDescriptionField("distance"); $map->setSourceDescriptionField("info"); $map->setSource($this->source); // Layout $this->frame->anchorCenter($map); // Display $this->display("main", $this->frame); } /* * Return the coordinates of the location. * @param $location valid Google Maps address of a location. * @param $googleMapKey key for accessing Google Maps. * @return array element[0] = status, element[2] = lat, element[3] = long */ function getLocationCoordinates($location, $googleMapKey) { $base_url = "http://maps.google.com/maps/geo?output=csv&key=".$googleMapKey; $request_url = $base_url."&q=".urlencode($location); $csv = file_get_contents($request_url); if ($csv) { $csvSplit = split(",", $csv); } else{ $csvSplit = array(); } return $csvSplit; } } |
Note:
La query crea la sorgente dati per i markers, che vengono evidenziati automaticamente dalla classe p4a_map
.
Al posto delle info, potete visualizzare la distanza di ogni marker dal centro (nell’esempio: “Mountain View, CA”) utilizzando l’istruzione: $map->setSourceDescriptionField("distance");
.
Il metodo getLocationCoordinates()
recupera le coordinate del centro per poter poi comporre la query.
La chiave per l’accesso a Google Map è quella valida per un server tipo “localhost” e la trovate all’interno del file: p4a_map.php che si trova nella directory libraries. Per avere quella per un dominio pubblico è necessario farla generare a Google Maps qui.
Non ho fatto controlli di errore, ad esempio per quanto riguarda la risposta del metodo getLocationCoordinates()
sarebbe opportuno controllare che l’array non sia vuoto e anche lo status della risposta di Google Maps, e si dovrebbe anche limitare il risultato della query al numero di markers massimo gestiti dal widget (17 se non ricordo male…).
Download
Il widget con la maschera sopra descritta è scaricabile qui
Conclusioni:
Il risultato è già soddisfacente, anche se un po’ grezzo, ma credo ci siano molti margini di miglioramento per questo tipo di utilizzo di Google Maps in P4A. Spero di avere tempo per affinare ulteriormente sia questo programma che il widget, per renderlo utilizzabile anche per idee diverse! Suggerimenti e consigli sono molto ben accetti!!
Riferimenti ed approfondimenti: