Préface
Avec le développement généralisé d'Internet mobile aujourd'hui, le développement d'applications est devenu le premier choix pour de nombreuses entreprises à entrer sur Internet mobile. L'auteur a développé de nombreuses applications et a constaté que de nombreuses applications ont une telle fonction, c'est-à-dire pour obtenir des personnes à proximité. Comment obtenir des personnes à proximité? En fait, c'est très simple. Il s'agit toujours d'enregistrer les informations des coordonnées de l'utilisateur (latitude et de longitude) dans la base de données, puis rechercher tous les utilisateurs de la base de données et la position de coordonnées actuelle dans une certaine plage en fonction des coordonnées de l'utilisateur actuels.
En fait, pour la distance entre deux sujets dont l'emplacement géographique ne change pas, il est préférable de statique directement le résultat. Autrement dit, écrivez-le directement dans la configuration.
Par exemple, trouvez une station de métro près de chez vous.
Dans ce cas, d'une manière générale, le sujet de la "maison" ne "courira pas" facilement. Il n'a pas de sens de calculer la distance une fois à chaque requête. Il est préférable de persister la distance et de l'interroger directement.
Un autre cas:
Obtenez la station de métro près de l'emplacement de l'utilisateur de l'application
Dans ce cas, l'emplacement géographique de l'utilisateur change. La distance réelle doit donc être calculée en temps réel à chaque fois.
Idées de mise en œuvre
Traitez la Terre comme une sphère standard et utilisez la formule de distance sphérique pour calculer la longueur d'arc du grand cercle entre deux points sur la surface sphérique.
Distance sphérique
public static double getDistance2 (double long1, double lat1, double long2, double lat2) {lat1 = rad (lat1); lat2 = rad (lat2); double a = lat1 - lat2; double b = rad (long1 - long2); double sa2 = math.sin (a / 2.0); double sb2 = math.sin (b / 2.0); Retour 2 * Earth_mean_Radius_Km * Math.asin (Math.Sqrt (SA2 * SA2 + MATH.COS (LAT1) * MATH.COS (LAT2) * SB2 * SB2));}Connaissez simplement la latitude et la longitude entre deux points.
Bien sûr, ce calcul doit être placé dans la base de données, puis trié selon la distance. Apportez simplement la formule ci-dessus dans SQL.
Exemples de stations de métro à proximité
Exemple de table pour construire une station de métro
Créer une station de table (id int Auto_inCrement Clé primaire, nom varchar (20) commentaire nul «Nom de la station MRT», commentaire nul Double «Longitude» Lat Double Null Commentaire «Dimension»);
Exemple SQL
Set @targetlat = 31.175702; set @targetlng = 121.519095; Select S.Id, S.Name, S.Lng, S.Lat, Round (6378.138 * 2 * Asin (Sqrt (Pow (Sin (@targetlat * pi () / 180 - S.Lat * Pi () / 180) / 2), 2) + COS (S.LAT * PI () / 180) / 2), 2) / 180 - S.LAT * PI () / 180) @targetlat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2))) * 1000) As Distancefrom Station Station Sorder par distance ASC, S.IDLIMIT 20;
Parmi eux, TargetLat et Targetlng se trouvent les emplacements géographiques des utilisateurs.
Cela peut en effet atteindre l'objectif. Cependant, il s'agit de calculer la distance entre toutes les données et l'utilisateur d'abord, puis de les trier.
Lorsque le nombre de stations de métro est trop grand, cette opération sera moins élégante. Non seulement ce n'est pas assez élégant, mais il est également très efficace.
optimisation
En fait, de nombreuses données peuvent être filtrées avant de calculer la distance.
Il n'est pas nécessaire de calculer la distance entre la station de métro américaine lors du calcul de la distance entre les stations de métro de Shanghai.
Cela peut d'abord être filtré de certaines données indésirables dans la plupart des applications.
Par exemple, lorsque les données distinguent les villes, vous pouvez changer SQL à ce qui suit:
Set @targetlat = 31.175702; set @targetlng = 121.519095; set @ CityId = 605; Select S.Id, S.Name, S.Lng, S.Lat, Round (6378.138 * 2 * Asin (Sqrt (Pow (Sin ((@targetlat * pi () / 180 - S.Lat * Pi () / 180), / 2) 2) + Cos (@targetlat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2))) * 1000) As Distancefrom Station SATHE City_id = @ CityId # First Filmter partie de la partie de l'ordre de la distance pour la distance de la distance de la distance à distance. 20;
L'amélioration ci-dessus consiste à supprimer la plupart des données à calculer avant le calcul. Lorsque vous cherchez une station de métro Changsha, il n'est pas nécessaire de rechercher d'abord à Shanghai.
Bien sûr, cette situation est un peu spéciale car vous pouvez connaître la ville où l'utilisateur est situé à l'avance.
Une autre amélioration est:
Avec l'emplacement de l'utilisateur comme centre, dessinez un cercle avec un rayon R, puis éjectez réversement la plage de latitude et de longitude du quadrilatère extérieur du cercle. Avant de calculer la distance, filtrez les données en dehors de la longitude et de la longitude du quadrilatère externe.
Spécifiez un rayon idéal R et filtrez les données qui ne peuvent pas répondre aux critères en premier.
Push-out inversé Range quadrilatérale externe
/** * Get the latitude and longitude of the four vertices of the point at the specified latitude and longitude{@code radius} KM's external quadrilateral (strictly speaking, it should be an external cube)* * @param lng longitude* @param lat latitude* @param radius, unit: KM * @return <lng1,lng2,lat1,lat2> */public Statique Tuple4 <Double> CalcboxByDistFromppt (Double LNG, Double Lat, Double Radius) {SpatialContext Context = SpatialContext.Geo; Rectangle rectangle = context.getDistCalc () // .CalcBoxByDistFromppt (// context.makepoint (lng, lat), // radius * com.spatial4j.core.Distance.DistanceUtils.km_to_deg, context, null //); return new Tuple4 <> (rectangle.getMinx (), rectangle.getMaxx (), rectangle.getminy (), rectangle.getMaxy ());}Les coordonnées Maven utilisées ici sont les suivantes:
<dependency> <proupId> com.spatial4j </proupId> <ErtifactId> Spatial4j </ artifactId> <DERSE> 0.5 </DERNIFRATION> </DENDENCENCE>
À l'heure actuelle, SQL peut être changé pour cela:
Set @targetlat = 31.175702; set @targetlng = 121.519095; Select S.Id, S.Name, S.Lng, S.Lat, Round (6378.138 * 2 * Asin (Sqrt (Pow (Sin (@targetlat * pi () / 180 - S.Lat * Pi () / 180) / 2), 2) + COS (S.LAT * PI () / 180) / 2), 2) / 180 - S.LAT * PI () / 180) @targetlat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2))) * 1000) comme stade de distance swhere (s.lng entre $ {lng1} et $ {lng2}) et s.lat et s.lat et lng1} et $ {lng2}) et S.Lnat et S.Lng $ {lat1} et $ {lat2}) Ordre par distance asc, s.idlimit 20;Le LNG1, LNG2, LAT1, LAT2 ci-dessus est la plage du quadrilatère externe.
Informations citées: http://blog.csdn.net/A364572/article/details/50483568
Exemple de code source
Service: https: //github.com/hylexus/bl ...
Initialiser les données: https: //github.com/hylexus/bl ...
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.