Algoritmo per trovare il punto più vicino


18

Ho un elenco di alcune centinaia di città con la loro latitudine / longitudine. Data un'altra posizione (anche in lat / long) ho bisogno di trovare la città più vicina.

Dato che non uso alcun GIS, ormai l'algoritmo ovvio è fare un giro per tutte le città, calcolando la distanza tra i punti.

Rendere il ciclo è praticabile per me, ma esiste un algoritmo facile da implementare per farlo in modo più efficiente? O qualche libreria Java leggera che può aiutare a risolverlo?

Note : Non ho bisogno / voglio una soluzione GIS completa o libreria pesante / complicata. Preferisco una soluzione meno buona ma più semplice e leggera perché è l'unica cosa che devo risolvere.


Quindi non importa che la distanza non sia corretta? E non vuoi tenere conto delle strade che potrebbero rendere una città più lontana di un'altra (diagonale vs piazza)?
Brad Nesom,

Sì, le strade non sono importanti per me. Ho bisogno della città più vicina a distanza lineare perché è per le previsioni del tempo.
Lujop,

1
Previsioni meteorologiche? Spero che tu abbia un supercomputer e uno staff di meteorologi addestrati a tua disposizione.
Michael Todd,

Le previsioni sono fatte Michael, solo io devo prendere il più vicino :)
lujop,

Risposte:


24

Ho studiato esattamente questa domanda 20 anni fa durante la progettazione di un GIS desktop. Dovevamo trovare le distanze punto-punto in modo interattivo; il nostro obiettivo era eseguire i calcoli in meno di 1/2 secondo per migliaia di punti. I test (su un PC 486 a 25 MHz!) Hanno mostrato che potevamo calcolare tutte le distanze, esattamente come descrivi (con il semplice algoritmo ovvio), così rapidamente che non aveva senso creare una soluzione più sofisticata, come una struttura quadrifoglio .

Per calcolare le distanze su un singolo punto "sonda" le opzioni includono (a) la proiezione di tutti i punti utilizzando una proiezione equidistante centrata nel punto della sonda o (b) l'adozione di un modello di terra sferica e la formula di Haversine . Il primo è appropriato se è necessaria la precisione di un modello ellissoidale. In entrambi i casi i calcoli sono ragionevolmente veloci, probabilmente richiedono meno di 1000 tick: è possibile eseguire una query su circa un milione di punti al secondo con un singolo processore.

Abbastanza veloce per te? Altrimenti, il metodo della forza bruta si parallelizza facilmente e si ridimensiona direttamente con il numero di processori: basta dividere i punti tra i processori e quindi fare un confronto finale di quello più vicino trovato da ciascun processore.

Se devi andare più veloce, puoi usare varie approssimazioni per schermare i punti. Ad esempio, se la latitudine è compresa tra -88 e +88 gradi e il punto più vicino trovato finora è a 200 km di distanza, allora qualsiasi punto la cui latitudine differisce dalla latitudine del punto della sonda di oltre 2 gradi non può essere più vicino (perché ovunque terra, un grado di latitudine supera circa 110 km). In molti casi questo tipo di pre-screening potrebbe consentire di elaborare centinaia di milioni di punti al secondo.


1
Per una discussione sulla formula di haversine, consultare gis.stackexchange.com/q/4906/664
whuber

4

Concordo con gli altri sul fatto che un semplice circuito dovrebbe essere efficace per "alcune centinaia di città".

Data la tua applicazione, gestire le distanze ellissoidali è probabilmente un grosso problema, probabilmente hai a che fare con previsioni meteorologiche la cui località è a malapena ridotta a pochi metri. La geometria sferica è abbastanza semplice da poter essere facilmente eseguita nel ciclo.

Potrebbe essere ancora più semplice (ad esempio, usa delta lat come y e delta lon * cos (lat) come x e trova il minimo x ^ 2 + y ^ 2). Stai utilizzando il coseno della latitudine target, che calcoli solo una volta. Ciò sarà sempre più impreciso per le città lontane, ma saranno comunque respinte, quindi non importa. Supponendo che la tua città più vicina sia generalmente entro un paio di centinaia di chilometri, le possibilità di un risultato diverso (città più vicina) usando questo vs usando una formula più accurata sono piuttosto piccole e si verificherebbero solo quando le differenze sono abbastanza piccole che "quale previsione è maggiore accurate "probabilmente dipenderebbe comunque da altri fattori (es: perdita nel rumore).

A meno che tu non stia usando un sistema incorporato o un interprete lento, probabilmente puoi permetterti di usare solo i formali sferici che altri suggeriscono, comunque.


1

Questo è in aggiunta a quanto è già stato detto, ma ho pensato di notare l'importanza di scegliere una struttura dati adeguata. Ho scritto il mio codice per una funzione K in .NET e ho scoperto che l'uso di raccolte efficienti ha velocizzato notevolmente le cose. Mi dispiace non conosco la notazione O per la velocità esatta. Ho usato due dizionari per le coordinate xey con l'ID punto come chiave. Non conosco Java, quindi non ho potuto suggerire nulla.

Saluti, David

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.