Ho alcuni utenti registrati nella mia app Django e voglio semplicemente essere in grado di capire la distanza, geograficamente, tra due utenti in base al loro codice di avviamento postale e quindi ordinare un elenco basato su quello. Immagino che questa funzionalità non sia integrata in Django. Stavo guardando alcune opzioni e sono incappato in geodjango che sembra che potrebbe essere eccessivo per quello che sono i miei bisogni.Django - come posso trovare la distanza tra due posizioni?
risposta
Seguendo il suggerimento di tcarobruce, ecco il mio commento sopra come una risposta:
Il Zip Code Database Project ha un database di latitudini e longitudini dei codici di avviamento postale degli Stati Uniti, sia come SQL o in formato CSV. Essi forniscono inoltre il seguente codice per il calcolo della distanza (slighlty a cura di me):
from math import sin, cos, radians, degrees, acos
def calc_dist(lat_a, long_a, lat_b, long_b):
lat_a = radians(lat_a)
lat_b = radians(lat_b)
long_diff = radians(long_a - long_b)
distance = (sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(long_diff))
return degrees(acos(distance)) * 69.09
Nota che il risultato è dato in miglia terrestri.
Modifica: correzioni dovute a John Machin.
Dovresti aver resistito alla tentazione di modificare leggermente il codice originale senza testare il risultato. Vedi la mia risposta. –
http://code.google.com/apis/maps/documentation/directions/
Si potrebbe fare le indicazioni per ogni posizione. La distanza totale è data. L'API sembra emettere JSON; è possibile analizzare la risposta sul lato server o calcolare la distanza calcolata da JavaScript.
Fare questo sarebbe contrario ai termini di servizio di Google, a meno che tu non sia un cliente di Maps for Business, btw. – Jordan
Questo è un grande commento sul codice pubblicato nella risposta (attualmente accettata) da @Sven Marnach.
Codice originale dal sito web del progetto zip, con rientro a cura di me:
from math import *
def calcDist(lat_A, long_A, lat_B, long_B):
distance = (sin(radians(lat_A)) *
sin(radians(lat_B)) +
cos(radians(lat_A)) *
cos(radians(lat_B)) *
cos(radians(long_A - long_B)))
distance = (degrees(acos(distance))) * 69.09
return distance
codice scritto da Sven:
from math import sin, cos, radians, degrees
def calc_dist(lat_a, long_a, lat_b, long_b):
lat_a = radians(lat_a)
lat_b = radians(lat_b)
distance = (sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(long_a - long_b))
return degrees(acos(distance)) * 69.09
Problema 1: non funzionerà: ha bisogno di importare acos
Problema 2: RISPOSTE ERRATE: necessario convertire la differenza di longitudine in radianti nella penultima riga
Problema 3: il nome variabile "distanza" è un termine improprio estremo. Quella quantità è in realtà il cos dell'angolo tra le due linee dal centro della terra ai punti di ingresso. Passare a "cos_x"
Problema 4: non è necessario convertire l'angolo x in gradi. Semplicemente moltiplicare x per il raggio terrestre in unità scelti (km, nm, o "miglia terrestri")
Dopo aver sistemato tutto ciò, otteniamo:
from math import sin, cos, radians, acos
# http://en.wikipedia.org/wiki/Earth_radius
# """For Earth, the mean radius is 6,371.009 km (˜3,958.761 mi; ˜3,440.069 nmi)"""
EARTH_RADIUS_IN_MILES = 3958.761
def calc_dist_fixed(lat_a, long_a, lat_b, long_b):
"""all angles in degrees, result in miles"""
lat_a = radians(lat_a)
lat_b = radians(lat_b)
delta_long = radians(long_a - long_b)
cos_x = (
sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(delta_long)
)
return acos(cos_x) * EARTH_RADIUS_IN_MILES
Nota: Dopo aver sistemato i problemi 1 e 2, questo è la "legge sferica dei coseni" come di solito implementata. Va bene per applicazioni come "distanza tra due codici postali statunitensi".
Caveat 1: Non è preciso per piccole distanze come dalla porta di casa alla strada, tanto che può dare una distanza diversa da zero o sollevare un'eccezione (cos_x> 1.0) se i due punti sono identici ; questa situazione può essere speciale.
Avvertenza 2: Se i due punti sono antipodali (il percorso della linea retta passa attraverso il centro della terra), può sollevare un'eccezione (cos_x < -1,0). Chiunque sia preoccupato può controllare cos_x prima di fare acos (cos_x).
Esempio:
SFO (37,676, -122,433) a New York (40,733, -73,917)
calcDist -> 2.570,7758043869976
calc_dist -> 5038,599866130089
calc_dist_fixed -> 2570,9028268899356
A Sito web del governo degli Stati Uniti (http://www.nhc.noaa.gov/gccalc.shtml) -> 2569
Questo sito Web (http://www.timeanddate.com /worldclock/distanceresult.html?p1=179 & p2 = 224), da cui ho ottenuto le coordinate OFS e NYC, -> 2577
@Sven Marnach: riesamina il tuo codice. Ci sono esattamente due occorrenze di 'radianti', ciascuna applicata a una latitudine, nessuna a una longitudine. Riesaminare il mio codice 'radians' viene applicato UNA VOLTA alla differenza di longitudine. Prova a testare i codici e spiega perché il tuo è l'estraneo. –
@Sven Marnach: È divertente; Potrei giurare di aver visto un commento in cui hai detto che il mio codice era sbagliato. SO ha bisogno di una pista di controllo :-) –
Ci scusiamo per questo. Il commento è stato lì per qualche secondo, ma ho subito notato che mi sbagliavo. Non pensavo avresti caricato la pagina in quel piccolo intervallo di tempo :) –
Un altro modo semplice:
Sotto funzione restituisce distanza tra due posizione dopo il calcolo latitudini e longitudini da codice postale.
lat1
, long1
sono le latitudini e le longitudini della prima posizione.
lat2
, long2
sono le latitudini e le longitudini della seconda posizione.
from decimal import Decimal
from math import sin, cos, sqrt, atan2, radians
def distance(lat1, lat2, long1, long2):
r = 6373.0
lat1 = radians(lat1)
lat2 = radians(lat2)
long1 = radians(long1)
long2 = radians(long2)
d_lat = lat2 - lat1
d_long = long2 - long1
a = (sin(d_lat/2))**2 + cos(lat1) * cos(lat2) * (sin(d_long/2))**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
# distance in miles
dis = r * c
# distance in KM
dis /= 1.609344
return dis
- 1. Three.js - Come posso calcolare la distanza tra due posizioni 3D?
- 2. Distanza tra due posizioni - Google Maps
- 3. La distanza tra due posizioni non è corretta
- 4. Come ottenere una distanza dritta tra due posizioni in Android?
- 5. Come posso calcolare la distanza tra due punti in MkMapview?
- 6. Come posso ottenere la distanza tra due punti per latlng?
- 7. Come trovare la distanza dalla latitudine e dalla longitudine di due posizioni?
- 8. Android Maps v2 API ... Come calcolare la distanza tra due posizioni (Lat, lunga)
- 9. Ottieni la distanza tra due punti geografici
- 10. Modifica la distanza tra due espressioni regolari
- 11. Modifica la distanza tra due grafici
- 12. Calcola la distanza tra due puntatori grezzi
- 13. MongoDB stampa la distanza tra due punti
- 14. distanza calcolare Android tra due luoghi
- 15. distanza fisica tra due luoghi
- 16. Android - Distanza tra due città
- 17. Come ottenere la distanza tra due punti in Android?
- 18. Come misurare la distanza in metri tra due CLLocations?
- 19. Calcola la distanza in (x, y) tra due punti GPS
- 20. Distanza minima tra due segmenti di linea
- 21. Come trovare la sottostringa tra due stringhe?
- 22. OpenLayers: come calcolare la distanza tra due punti?
- 23. Come misurare la distanza tra due dispositivi iPhone tramite Bluetooth?
- 24. distanza tra due forme/aree in Java?
- 25. Distanza di ritorno tra due posizioni in SQL Server 2008 utilizzando latitudine e longitudine
- 26. Trova la distanza tra due DIV usando jQuery?
- 27. Regola la distanza solo tra due sottotrame in matplotlib
- 28. Trova la distanza tra due CAP utilizzando i servizi Web?
- 29. Calcolo distanza tra due località geografiche
- 30. Distanza diversa tra due punti su iOS e Android
Ecco un [ricetta ActiveState] (http://code.activestate.com/recipes/393241-calculating-the-distance-between-zip-codes/) per questo scopo. Quasi certamente non è costruito in Django. –
Dai un'occhiata anche al [Database Database Project] (http://zips.sourceforge.net/). Forniscono anche il codice Python per il calcolo della distanza sulla pagina collegata. –
@Sven Marnach - invia il progetto di database del codice postale come risposta: è una buona soluzione. (E sì, GeoDjango è probabilmente eccessivo per questo.) – tcarobruce