Come abbiamo visto qualche mese fa in un articolo, Google Maps ci mette a disposizione un sistema per trasformare un indirizzo civico in coordinate geografiche (cioè latitudine e longitudine). Alla pagina linkate troverete un link completo da scaricare.
Ma, una volta che abbiamo recuperato latitudine e longitudine, come facciamo a trovare la distanza tra due punti geografici?
Ancora: come facciamo a trovare il numero di aziende che si trovano a una certa distanza dal punto geografico passato?
Situazioni simili si possono presentare, per esempio, se dobbiamo realizzare un sito di e-commerce (negozio online) in cui dobbiamo calcolare le spese di trasporto in base alla distanza da percorrere tra l’azienda che offre il prodotto e il compratore destinatario.
Dobbiamo inoltre distinguere il caso in cui le coordinate siano già preventivamente in nostro possesso, oppure quando una delle due coordinate ci vengono fornite dall’utente (per esempio digitando il suo indirizzo e inviandolo tramite form).
I due script che trovate di seguito mostrano due casistiche distinte:
1) recupero della distanza tra due coordinate geografiche, conoscendo di entrambe già dall’inizio latitudine e longitudine. La distanza sarà ricavata tramite formula matematica e con l’uso del linguaggio php.
2) estrazione dei punti geografici già in nostro possesso che si trovano entro una determinata distanza dalle coordinate inviateci dall’utente, per esempio tramite form. In questo caso noi avremo a disposizione, nel nostro database, un certo numero di aziende/luoghi con associate delle coordinate geografiche. Il calcolo sarà fatto direttamente in una query del database, che sarà di tipo mysql.
Distanza tra due coordinate geografiche
Il codice non ha bisogno di grandi spiegazioni. Come esempio, calcoliamo la distanza tra “Piazza Brà” e “Stazione Porta Nuova” di Verona. In questo caso ho messo in chiaro latitudine e longitudine per ognuna, ma nulla vieta che una delle coordinate siano passate dinamicamente, per esempio attraverso un form: in questo modo potremmo calcolare la distanza da un punto iniziale (da noi stabilito) a un luogo indefinito indicatoci dall’utente.
[Edit 17 dicembre 2015]: la formula, così come la query nella sezione più sotto, è stata recuperata in rete e mantenuta così come trovata.
[Edit 20luglio 2018]: il risultato della formula è espresso in miglia. Il numero “3958” rappresenta il raggio della Terra in miglia, che rcorrisponde appunto 6371 km.
Ringrazio Gurzo e Fabio per le segnalazioni (si veda nei commenti).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php //Piazza Brà, Verona $lat1=45.43936; $lon1=10.9929; //Stazione Porta Nuova, Verona $lat2=45.42928; $lon2=10.98233; $distance = (3958*3.1415926*sqrt(($lat2-$lat1)*($lat2-$lat1) + cos($lat2/57.29578)*cos($lat1/57.29578)*($lon2-$lon1)*($lon2-$lon1))/180); echo $distance; ?> |
Estrazione dei luoghi geografici entro una certa distanza da un punto stabilito
L’esempio è apparentemente più complesso del precedente, ma si tratta di specificare alcuni chiarimenti prima di iniziare:
– nel vostro database dovrà trovarsi una tabella chiamata coordinate
, che conterrà (oltre ai campi a vostra scelta) i campi latitudine
e longitudine
. In pratica si tratta di avere una lista di record che corrispondono ad aziende/luoghi a cui sono state associate le rispettive coordinate latitudine e longitudine.
– sarà l’utente a inviare, tramite form, il punto di origine. Probabilmente dovrete stabilire dei semplici campi input per inserire l’indirizzo (i soliti via, cap, paese, ecc.), perché è difficile che un utente ordinario inserisca di sua iniziativa la latitudine e la longitudine della sua abitazione: voi vi dovrete occupare di trasformare il suo indirizzo in coordinate geografiche, magari usando il link che vi ho proposto a inizio articolo. Per semplicità ho riportato la latitudine e la longitudine rispettivamente nelle variabili $_POST['lat']
e $_POST['lng']
.
Cosa fa lo script?
Una volta ottenuto il punto di origine dall’utente, il codice fa direttamente il calcolo della distanza in una query mysql ed estrae tutti quei record le cui coordinate si trovano entro 100 km dal punto di origine stesso.
Leggere il codice è più semplice che spiegarlo. Qui sotto mi limito a mostrare semplicemente la query completa.
1 2 3 4 |
<?php $query="SELECT * FROM coordinate WHERE "; $query.="TRUNCATE ( 6363 * sqrt( POW( RADIANS('".$_POST['lat']."') - RADIANS(latitude) , 2 ) + POW( RADIANS('".$_POST['lng']."') - RADIANS(longitude) , 2 ) ) , 3 ) < 100"; ?> |
Domanda 1: presumo che il calcolo della distanza restituisca una distanza in Km
Domanda 2: la formula nella query è la stessa precedente opportunamente semplificata e precalcolata?
Ciao Leonardo,
1)
Sì, il risultato è in chilometri[Edit 17 dicembre 2015]: il risultato della formula è espresso in miglia, non in km (vedi il commento di Gurzo più sotto). Errore mio 🙂
2) La formula nella query l’ho trovata prefatta tempo fa (testata e funzionante), ma a giudicare dai valori e dal risultato usati direi che si tratta dello stesso calcolo traslato affinché il database possa prenderlo. Infatti, se noti, c’è lo stesso uso della radice quadrata e dell’elevamento a potenza
In un database con un milione e più di record, questo è il modo secondo voi più efficiente? Quando cerco su maps un ristorante lui fa una query simile oppure c’è una tecnologia di data storage differente per ottimizzare? Se conoscete qualcosa indirizzatemi che sono nella cacchina 😀
Ciao Andrea,
immagino che Google utilizzi un metodo ben più sofisticato per calcolare le sue distanze su Maps, e infatti è il migliore nel suo campo XD
Quella che vedi sopra è un calcolo “casalingo”, se così possiamo dire, e calcola la distanza in linea d’aria usando le formule geometriche.
Per sistemi più complessi o più precisi dovresti affidarti alle api di Google Maps… Se ti mancano le basi all’indirizzo seguente trovi un punto di partenza:
http://www.manuelmarangoni.it/sir-bit/?p=1410
Ciao innanzitutto grazie mille per questo script molto utile pero ho un problema ovvero in due soli postcode non mi da l elenco completo delle case di cura e nn riesco a capire dove sta il problema.
I postcode in questione sn bn3 e bb5
Prego =)
Usando i due codici postali direttamente nel sito di Google Maps li trova senza problemi, quindi direi che non è questione di coordinate sbagliate.
Come recuperi l’elenco completo delle case di cura? Prova a controllare che le coordinate delle case di cura (che dovresti avere salvate nel database) siano effettivamente alla distanza stabilita, che magari non siano fuori raggio
Ciao Manuel, intanto complimenti per l’articolo.
Avrei una domanda da farti: questi calcoli da quello che ho capito sono un “metodo standard” per calcolare approssimativamente la distanza tra due punti, se io avessi necessità di calcolare la distanza precisa (quella restituita da maps via percorso stradale per intenderci, dovendo sviluppare una app per zone montane in cui la precisione è fondamentale e la distanza effettiva potrebbe essere radd-tripli con poco). Sai se Google mette a disposizione delle API per restituirmi tale distanza? Non trovo quello di cui ho bisogno.. So che devo transitare attraverso un altro web-service e quindi le prestazioni diminuiranno in base al numero di record presenti ma non trovo altre soluzioni..
Grazie intanto
Federico
Ricollegandomi al mio post qui sopra: chi cerca trova dicono 🙂
https://developers.google.com/maps/documentation/distancematrix/
Ho trovato questo servizio di google, ma dovendolo integrare in una app senza mappa (solo elenco ordinato in base a distanza) non vorrei che a lungo andare saltassero fuori problemi legati a questa dicitura:
“Use of the Distance Matrix API must relate to the display of information on a Google Map; for example, to determine origin-destination pairs that fall within a specific driving time from one another, before requesting and displaying those destinations on a map. Use of the service in an application that doesn’t display a Google map is prohibited.”
Cosa ne pensi?
Grazie ciao
Ciao Federico,
mi hai fatto scoprire un’API nuova, è la prima volta che la vedo 🙂
Molto interessante, ovviamente se non ci sono connessioni pesanti: da quello che vedo ha dei limiti nel numero di query (la versione business copre un raggio più ampio).
Da quello che vedo nell’avvertimento, quest’API deve essere utilizzata soltanto all’interno di una Google Map: l’uso senza mostrare a video la maps in teoria è illegale (non specifica se funzionerebbe lo stesso o no, ma immagino che abbia dei blocchi).
Salve, più che un commento all’articolo avrei bisogno del tuo aiuto per trovare un sistema che, converta le coordinate terrestri in uso nella seconda guerra mondiale usate dai militari Americani e Inglesi in coordinate google maps. (Lat. Long.) Un esempio lo puoi vedere sul sito di http://www.echodelta.net/mbs/eng-translator.php. In pratica un traduttore che possa essere usato senza collegamento internet. Ciao e grazie.
Ci sono sistemi per usare Google Maps in locale, offline, anche se non li ho mai testati (un esempio: http://offlinegooglemapsgooglejavascriptv3.blogspot.it/2013/05/offline-google-maps-google-javascript.html).
A ogni modo quello che cerchi tu è un po’ sofisticato. La pagina che hai messo come riferimento non si appoggia a google maps (a meno che non lo richiami in pagine interne dopo l’invio del form). Ho cercato altri dettagli in rete, ma sono script già pronti e non utilizzabili.
Quello che dovresti fare, comunque, è trovare qual è il “calcolo” per convertire il “British Modified System” in coordinate moderne: in questo modo puoi avviare la conversione manualmente e poi utilizzarle in mappe come la Google Maps.
volevo chiedervi, se anzicchè passarle io le coordinate, utilizzassi la funzione di google maps per avere longitudine e latitudine del punto in cui mi trovo, e quindi visualizzare i punti attorno a me con raggio di 5 km?
Cioè intendi visualizzare sul tuo sito la Google Maps di un punto specifico e l’area attorno entro un raggio di 5 km?
Non credo esista un parametro simile da impostare sulla Maps, ma potresti creare una mappa normale e “giocare” con i livelli di zoom fino a ottenere un’area con il raggio che ti interessa…
Ciao a tutti e grazie per queste info.
Ma, io avrei un quesito, considerato che ho una tabella con tanto di coordinate, è possibile selezionando da una mappa 3 coordinate (il minimo per creare un’area) estrapolare tutte le coordinate comprese all’interno di quell’area?
Grazie e a presto.
Ciao Max,
tra le API non so se esiste una qualche funzione già predisposta, che per esempio triangoli una posizione.
A livello di logica la butto lì: tra le tre prendi la coordinata con la longitudine maggiore e minore, e cerchi tutte le coordinate che hanno la longitudine compresa lì dentro.
Usando il range così trovato, fai la stessa cosa con la latitudine e in questo modo ti risultano i punti compresi in quell’area.
Se trovi un sistema più efficiente, faccelo sapere 🙂
Grazie del suggerimento… Ora provo e Vi farò sapere..
Buon lavoro.
Ho aspettato molto tempo per leggere qualcosa di così bello e interessante.
Grazie!
Non c’è di che 🙂
Salve Manuel,
ho letto i tuoi articoli, ben fatti….complimenti.
Non ho molta esperienza nell’ambito.
Sto realizzando un sito (con un amico) dove l’utente collegandosi (da mobile) visualizza sulla mappa i punti di interesse nelle vicinanze (salvati in un DB MySql).
Praticamente ho bisogno:
MAPPA
– stampare a video la mappa con la posizione dell’utente
– stampare sulla mappa i punti di interesse nel raggio di 5 km più o meno
FOTO
– l’utente visualizza, in ordine di distanza (la sua), le foto dei punti di interesse
I punti sono memorizzati in un DB con indirizzi fisici (via e città). è possibile ricavare da queste LATITUDINE/LONGITUDINE e salvarli nel DB?
spero in un tuo aiuto
grazie
Antonio
Ciao Antonio,
grazie per i complimenti 😉
Ho scritto anche un articolo per trasformare un indirizzo civico in coordinate geografiche, dovrebbe fare al caso vostro:
http://www.manuelmarangoni.it/sir-bit/1056/google-maps-php-trasformare-un-indirizzo-in-coordinate-latitudine-e-longitudine/
Puoi combinare i due articoli e ricavare i dati che ti servono.
Una volta ottenuto il punto di origine, puoi usare lo script qui sopra per evidenziare i punti di interesse entro una certa distanza
Grazie per la risposta …. ci proverò!!
Ora solo un’altra info.
Devo far caricare agli utenti delle foto:
– CARICARE FOTO (VISUALIZZARE L’ANTEPRIMA)
– scrivere info sulla foto (es. NOME, CITTà..)
salvare tutto in un DB
hai qualche dritta?
grazie ancora
antonio
Stai parlando di personalizzare i balloon? Prova a dare un’occhiata qua:
http://www.manuelmarangoni.it/sir-bit/788/google-maps-come-integrare-e-personalizzare-una-mappa-nel-nostro-sito-parte-1/
Trovi anche i link alla documentazione ufficiale. Puoi usare i dati salvati nel db e personalizzare il contenuto del balloon
Non intendevo quello…anche se mi sarà utile ahah
Era un’altro argomento.
Parlo di foto che l’utente carica sul sito (monumenti ecc).
Praticamente devo creare un form di upload immagini con relative info. Il tutto verrà salvato in un database.
Vorrei che a video vi visualizzi un’anteprima dell’immagine scelta (anche una miniatura) mentre l’utente compila i campi delle info.
Ovviamente con ridimensionamento automatico nel caso l’immagine fosse troppo grande.
Grazie mille per l’aiuto 🙂
Per un form base potresti prendere spunto da qua:
http://www.manuelmarangoni.it/sir-bit/1608/php-form-e-controlli-per-lupload-di-immagini-da-parte-dellutente/
Si tratta però di un form di upload base, che devi riadattare. Puoi estrapolare facilmente le informazioni delle immagini e salvarle nel database; se l’utente ha bisogno di inserire altre info, basta creargli dei campi input o textarea, che poi salverai nel db.
Nel database dovrai creare un campo per tenere traccia del nome dell’immagine (ed eventualmente della path dove si trova), così potrai recuperla quando devi stamparla a video.
Per il ridimensionamento, la cosa migliore sarebbe creare più versioni dell’immagine, con dimensioni diverse, e prendere all’occorrenza solo quella che ti serve. Ti consiglio Smartimage:
http://www.manuelmarangoni.it/sir-bit/1450/php-ridimensionare-le-immagini-con-smartimage/
perfetto… però non so se mi sono spiegato bene.
PRIMA DELL’UPLOAD (quindi prima di salvare foto e info nel DB) Vorrei che a video venga visualizzata un’anteprima dell’immagine scelta in modo che l’utente veda la foto e compili i campi delle info. POI prema il tasto UPLOAD per salvare tutto nel DB.
ora credo sia più chiaro.
Il sistema più semplice che mi viene in mente è di caricare l’immagine scelta dall’utente in una cartella temporanea e quindi di stampare a video l’anteprima di questa con i campi input da compilare.
Quando ha finito, invia i dati e tu li salvi nel db (e sposti l’immagine nella cartella “ufficiale”). Se non completa l’operazione, elimini l’immagine temporanea
Ciao e grazie per l ottimo articolo.
Il codice pero’ mi restituisce una distanza errata.
Non dovrebbe essere $distance = (6378.388*3.1415926*sqrt((…ecc ecc ?
Non capisco il significato della fromula. Grazie se vorrai aiutarmi.
Ciao !
Ciao Gurzo,
la formula l’ho recuperata da internet già pronta e usa funzioni di trigonometria. Da quanto vedo si basa sulla curva di una circonferenza e da lì riesce a calcolare la distanza in linea d’aria; ma non è il mio campo, per cui non provo nemmeno a spiegartela: servirebbe l’intervento di un qualche matematico 🙂
In ogni caso le prove che avevo fatto a suo tempo mi davano risultati abbastanza esatti. Ovviamente Google Maps userà algoritmi molto più sofisticati nel suo sito
Grazie per la risposta 🙂
Dopo altre ricerche (google) ho scoperto che la tua formula non restituisce chilometri, ma miglia.
Qui di seguito le tre costanti piu comuni (da sostituire alla bisogna):
3958.75 Miglia
6370.0 km
3440.06 MigliaNautiche
Anch’io non mi trigonometrizzo gran che, ma prendendo come riferimento una distanza nota, questi parametri sono abbastanza corretti.
Li ho trovati legati ad un modulo GPS collegabile ad arduino.
https://learn.adafruit.com/reverse-geocache-engagement-box/software
Per la conversione in radianti ho notato che molti usano (a parte tutt’ altra formula.. ) solo due decimali pure arrotondati e cioe’ 57.30 al posto di 57.29578 forse unicamente per problemi di calcolo dovuti a limiti del processore (arduino e simili), BOH !
Spero di essere stato utile a qualcuno e che qualche Pitagora spieghi nel dettaglio la fromula 🙂
Salut !
Direi che sei stato più che utile 😉
Aggiorno l’articolo, ero convinto che buttasse fuori il risultato in km
Ciao Manuel,
io ho un problema con la mappa di google. Praticamente ho un DB con indirizzi e coordinate. Attraverso la posizione dell’utente visualizzo sulla cartina i marker delle aziende più vicine a lui. Il problema è che se queste sono troppe, non apre la mappa. Ad esempio a Roma, inserendo il raggio di 2km, mi apre la mappa di google con i marker – la stessa a Milano non la apre perchè le aziende da visualizzare sono molte di più. Ho ridotto la distanza a 500 metri, funziona in entrambi i casi ma per Roma è troppo piccola come distanza in quanto mi visualizza pochissime aziende e comunque 500metri è troppo ridotta come distanza. Vorrei aumentare il raggio almeno a 2km. Come posso fare? Grazie
Ciao Antonio,
direttamente non ho mai affrontato questo problema, ma informandomi sulla rete ho trovato qualcosa che potrebbe fare al caso tuo: il clustering, e cioè il raggruppamento dei marker.
Prova a guardare qua (o, se non ne esci, cerca qualche esempio di uso dei cluster con Google Maps):
http://www.localstrategy.it/clustering-gestire-molti-marker-google-maps/
ciao Manuel,
Per quanto riguarda le mappe vorrei fare così : rilevo la posizione dell’utente e stampo i marker delle aziende a lui vicine ma se l’utente sposta la mappa si caricano in automatico altri marker più lontani dalla sua posizione.
Attualmente uso LEAFLET, la libreria open source di javascript, per evitare problemi di permessi con google. Funziona ma pensavo che spostando la mappa e visualizzare altri marker sarebbe più fruibile.
Secondo te come si potrebbe fare? Ho cercato in web ma non ho trovato nulla.
Per calcolare la posizione e stampare i marker più vicini ho usato le tue formule.
Grazie
Ciao Antonio,
così al volo ti direi di partire da un altro articolo che avevo scritto:
http://www.manuelmarangoni.it/sir-bit/1038/google-maps-cambiare-coordinate-con-un-click-sulla-mappa-o-trascinando-il-marker/
Permette di trascinare il marker e di recuperare le nuove coordinate. A quel punto dovresti riuscire a usarle per ricreare la nuova mappa.
Ciao Manuel,
Utilizzando le tue funzioni riesco ad ottenere una lista di punti compresi entro 50 KM da un indirizzo. Il problema è che devo riuscire a selezionare solo il punto più vicino tra tutti. Il tutto funziona tramite database e phpmyadmin. Come faccio ad estrarre solo il punto più vicino dalla lista dei risultati?
Grazie.
Ciao Alex,
sopra trovi anche il codice per trovare la distanza tra due coordinate geografiche. Potresti recuperare latitudine e longitudine di ogni risultato estratto e, per ognuno, calcolare la distanza da un indirizzo.
In termini di prestazioni però è molto costoso se i risultati sono numerosi… devi vedere se il procedimento può fare al caso tuo
Ciao a tutti,
la formula restituisce la distanza in miglia perchè il primo numero rappresenta il raggio terrestre di circa 6400 km appunto 3958 miglia circa. Grazie per la formula.
È vero, non ci avevo neanche pensato che potesse essere il raggio terrestre. Grazie a te per l’aiuto, ho aggiunto una nota nell’articolo