SQlite Obtenir le plus proche emplacements (latitude et longitude)
J'ai des données avec la latitude et la longitude stockées dans ma base de données SQLite, et je veux être le plus proche des endroits les paramètres que j'ai mis dans (ex. Ma position actuelle - lat/lng, etc.).
Je sais que c'est possible dans MySQL, et j'ai fait quelques recherches que SQLite a besoin d'un custom fonction externe pour la Haversine formule (calcul de la distance sur une sphère), mais je n'ai pas trouvé tout ce qui est écrit en Java et fonctionne.
Aussi, si je veux ajouter des fonctions personnalisées, j'ai besoin de la org.sqlite
.jar (pour org.sqlite.Function
), et qui alourdit inutilement la taille de l'application.
L'autre côté de cette est, j'ai besoin de la Commande en fonction de SQL, parce que l'affichage de la distance n'est pas un problème - je l'ai déjà fait dans mon custom SimpleCursorAdapter, mais je ne peux pas trier les données, parce que je n'ai pas la distance de la colonne dans ma base de données. Que signifierait la mise à jour de la base de données à chaque fois que les modifications de l'emplacement et c'est un gaspillage de la batterie et de la performance. Donc, si quelqu'un a une idée sur le tri le curseur avec une colonne qui n'est pas dans la base de données, je lui en serais reconnaissant aussi!
Je sais qu'il y a des tonnes de Android applications qui utilisent cette fonction, mais quelqu'un peut-il expliquer la magie.
Par ailleurs, j'ai trouvé cette alternative: Requête pour obtenir les enregistrements en fonction du Rayon de SQLite?
Il suggère de faire 4 nouvelles colonnes pour les cos et sin valeurs de la lat et de gnl, mais est-il des autres, pas tellement redondant façon?
- Avez-vous vérifier si org.sqlite.La fonction fonctionne pour vous (même si la formule n'est pas correcte)?
- Non, j'ai trouvé un (redondant) alternative (édité le post) qui sonne mieux que d'ajouter un 2,6 MB .jar de l'application. Mais je suis toujours à la recherche d'une meilleure solution. Merci!
- Quel est le rendement de l'unité de distance type?
- Voici un la pleine mise en œuvre pour la construction d'une requête SQlite sous Android basé sur la distance entre votre emplacement et l'emplacement de l'objet.
Vous devez vous connecter pour publier un commentaire.
1) Au premier filtrer vos données SQLite avec une bonne approximation et de la diminution de la quantité de données que vous devez évaluer dans votre code java. Utilisez la procédure suivante pour cette fin:
D'avoir un déterministe seuil et plus précis filtre sur les données, Il est préférable de calculer 4 emplacements qui sont dans
radius
mètre du nord, de l'ouest à l'est et au sud de votre point central dans votre code java et puis vérifier facilement en moins et plus que les opérateurs SQL (>, <) pour déterminer si vos points dans la base de données sont dans un rectangle ou non.La méthode
calculateDerivedPosition(...)
calcule ces points (p1, p2, p3, p4 dans l'image).Et maintenant créer votre requête:
COL_X
est le nom de la colonne dans la base de données qui stocke les valeurs de latitude et deCOL_Y
est pour la longitude.Si vous avez des données qui sont à proximité de votre point central avec une bonne approximation.
2) Maintenant, vous pouvez faire une boucle sur ces données filtrées et de déterminer si elles sont vraiment à proximité de votre lieu (dans le cercle) ou non en utilisant les méthodes suivantes:
Profitez-en!
Que j'ai utilisé et personnalisé cette référence et à la fin.
android.location.Location. distanceBetween()
méthode, qui, fondamentalement, ne la même chose que la dernière fonction de cette réponse, donc pas utiliser le réinventer.De Chris réponse est vraiment utile (merci!), mais ne fonctionnera que si vous êtes à l'aide de coordonnées rectilignes (par exemple UTM ou OS de la grille de références). Si à l'aide de degrés de lat/lng (par exemple WGS84) puis le ci-dessus ne fonctionne qu'à l'équateur. À d'autres latitudes, vous avez besoin de diminuer l'impact de longitude sur l'ordre de tri. (Imaginez que vous êtes à proximité du pôle nord... un degré de latitude est toujours la même c'est n'importe où, mais d'un degré de longitude est peut-être seulement un peu les pieds. Cela signifie que l'ordre de tri est incorrect).
Si vous n'êtes pas à l'équateur, pré-calculer le fudge factor, en fonction de votre latitude:
Puis commande par:
((<lat> - LAT_COLUMN) * (<lat> - LAT_COLUMN) +
(<lng> - LNG_COLUMN) * (<lng> - LNG_COLUMN) * <fudge>)
C'est encore qu'une approximation, mais beaucoup mieux que la première, donc de l'ordre de tri des inexactitudes sera beaucoup plus rares.
((<lat> - LAT_COLUMN) * (<lat> - LAT_COLUMN) + (<lng> - LNG_COLUMN) * (<lng> - LNG_COLUMN) * <fudge>)
être moins dedistance
oudistance^2
?Je sais que cela a été répondu et accepté, mais j'ai pensé ajouter mon expérience et de leur solution.
Alors que j'ai été heureux de faire un haversine de la fonction sur l'appareil pour calculer la distance exacte entre l'utilisateur de la position actuelle et les objectifs endroit, il y avait un besoin de trier et de limiter les résultats de la requête dans l'ordre de la distance.
Moins que satisfaisants, la solution est de retour du lot et de tri et de filtre après le fait, mais il en résulterait un deuxième curseur et bien des résultats retournés et jetés.
Mon préféré de la solution a été de passer dans un ordre de tri des carrés des valeurs delta de long et lat:
Il n'y a pas besoin de faire le plein haversine juste pour un ordre de tri et il n'y a pas besoin de racine carrée par conséquent, les résultats SQLite peut gérer le calcul.
EDIT:
Cette réponse est encore recevoir l'amour. Il fonctionne bien dans la plupart des cas, mais si vous avez besoin d'un peu plus de précision, veuillez consulter la réponse par @Teasel ci-dessous qui ajoute un "fudge" facteur qui corrige les inexactitudes qu'augmenter à mesure que la latitude approches 90.
cos(latitude)
avoir la latitude et la longitude à peu près égale. Voir en.wikipedia.org/wiki/...Avez-vous considéré comme un Geohash tag/index pour vos entrées pour réduire la taille de votre résultat de définir et d'appliquer ensuite la fonction appropriée.
Un autre stackoverflow question dans un domaine similaire:
trouver le plus proche-point-pour-un-compte tenu de point
Afin d'accroître les performances, autant que possible, je suggère d'améliorer @Chris Simpson idée avec les éléments suivants
ORDER BY
clause:Dans ce cas, vous devez transmettre les valeurs suivantes de code:
Et vous devriez également stocker
LAT_LON_SQ_SUM = LAT_COL^2 + LON_COL^2
comme colonne supplémentaire dans la base de données. Remplir l'insertion de vos entités dans la base de données. Cela améliore légèrement les performances lors de l'extraction de grandes quantités de données.Avoir un oeil sur ce post:
Fonction de Distance pour sqlite
Il semble pour vous permettre d'ajouter une coutume Distance() la fonction de SQLite qui peut vous permettre d'éviter de sauter à travers tous les cercles dans les autres réponses.
Essayer quelque chose comme cela:
Après cela, l'id contient l'élément que vous voulez à partir de la base de données de sorte que vous pouvez le récupérer:
Espère que ça aide!