Miglior metodo per elaborare posizioni entro un raggio di punto di partenza
-
19-09-2019 - |
Domanda
ho intenzione di creare una feature nel mio ultimo progetto, preferibilmente utilizzando PHP. Quando ogni utente si iscrive hanno intenzione di inserire le loro Cap. Poi spero di essere conversione di questo a latitudine / longitudine utilizzando Open Street Map.
In ogni caso, voglio essere in grado di scoprire altri utenti situati vicino l'utente corrente. Ho visto un sacco di persone che utilizzano la formula Haversine, ma questo significherebbe che l'utente ha interrogato i dettagli di ogni altro utente a lavorare fuori la distanza. Potrei cache di questo, ma la sua ben presto di andare a diventare obsoleti come i nuovi utenti si iscrivono.
Che tipo di effetto potrebbe correre la seguente query sono sul mio sistema?
sql = "SELECT zipcode, ( 3959 * acos( cos( radians( {$coords['latitude']} ) )
* cos( radians( latitude ) ) * cos( radians( longitude )
- radians( {$coords['longitude']} ) )
+ sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) )
AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";
Questo è tirato dal blog di qualcuno.
Non ho alcuna cifra per il tasso di iscrizione o del numero di utenti in quanto è ancora in sviluppo.
Apprezzerei tutte le risposte o di altri metodi che potrei usare per trovare corrispondenza utenti entro un determinato raggio.
Soluzione
Ci sono GIS e spaziale estensioni a MySQL in versione 4.1, vedere qui . Dalla descrizione si trova, che è utilizzato per problemi come avete qui:
Un GIS (sistema informativo geografico) negozi e alza lo sguardo oggetti che hanno uno o più attributi spaziali, quali come dimensione e posizione, ed è utilizzato per elaborare tali oggetti. Un semplice esempio sarebbe un sistema che memorizza gli indirizzi in una città utilizzando geografica coordinate. Se questo piuttosto statica dati sono stati poi combinati con altri informazioni, come ad esempio la posizione di un il taxi-cab, allora questi dati potrebbero essere utilizzati per trovare la cabina più vicina ad un certo posizione.
Si aggiunge diverse cose da MySql come:
-
chiavi Spacial e il tipo di punto:
CREATE TABLE indirizzo ( indirizzo CHAR (80) NOT NULL, address_loc POINT NOT NULL, PRIMARY KEY (indirizzo), SPAZIALE KEY (address_loc) );
-
routine di conversione
INSERT INTO valori di indirizzo ( 'strada Foobar 12', GeomFromText ( 'PUNTO (2671 2500)') );
-
funzioni di calcolo GIS
SELEZIONARE c.cabdriver, ROUND ( GLength (LineStringFromWKB (LineString (AsBinary (c.cab_loc), AsBinary (a.address_loc)))) ) AS distanza Dalla cabina c, affrontare un ORDER BY distanza ASC LIMIT 1;
(esempi tratti dal link qui sotto)
Altri suggerimenti
Il problema può essere notevolmente semplificata se si è disposti ad allentare la definizione di "una determinata distanza" per non essere specificamente un cerchio. Se si semplifica a una "piazza", è possibile trovare tutte posizione all'interno del "raggio" con 2 semplici "tra" le clausole (uno per uno lat per molto). ad esempio:
SELECT * FROM location WHERE
lat BETWEEN (my_lat - radius) AND (my_lat + radius)
AND long BETWEEN (my_long - radius) AND (my_long + radius);
Naturalmente, questo potrebbe essere usato per selezionare un sottoinsieme di posizioni prima di utilizzare un metodo più accurato per calcolare la distanza effettiva a loro.
Certo questo non è Javascript PHP, ma sarebbe banale per convertire Mi piacerebbe immaginare.
Si calcola la distanza tra due punti, che rappresentano la curvatura della Terra. Viene utilizzato in una logistica app un po 'indietro prima di sostituirlo con il codice che lo fa utilizzando un percorso su strada corretta.
potrebbe essere utile a voi ....
<script type="text/javascript">
function getDistance(lat1,lng1,lat2,lng2)
{
p1 = new VELatLong(lat1,lng1);
p2 = new VELatLong(lat2,lng2);
miles = true;
p1.Latitude= latLonToRadians(p1.Latitude);
p1.Longitude= latLonToRadians(p1.Longitude);
p2.Latitude= latLonToRadians(p2.Latitude);
p2.Longitude= latLonToRadians(p2.Longitude);
var R = 6371; // earth's mean radius in km
var dLat = p2.Latitude- p1.Latitude;
var dLong = p2.Longitude- p1.Longitude;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong/2) *
Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var disKm = R * c;
var disMiles = disKm * 0.6214;
alert (miles ? disMiles : disKm);
}
// convert lat/long in degrees to radians
function latLonToRadians( point )
{
return point * Math.PI / 180;
}
</script>
Oh, e gli oggetti VELatLong provengono dalla API di Virtual Earth ( http://msdn.microsoft.com/en-us/library/bb412519.aspx ), ma sono fondamentalmente un glorificato struct, così si dovrebbe essere in grado di trovare un sostituto adeguato