J'essaie de créer des emplacements aléatoires à proximité de mon emplacement. Ce que je veux, c'est créer des paires de latitude / longitude aléatoires à l'intérieur d'un cercle de 200 mètres entourant mon emplacement.
Voici la formule que j'ai trouvée (avec l'aide des gens de StackOverFlow): (nombre aléatoire entre -1 et 1) * rayon + (ancienne longitude) = nouvelle longitude dans le rayon de l'ancienne longitude
(Nombre aléatoire entre -1 et 1) * rayon + (ancienne latitude) = nouvelle latitude dans le rayon de l'ancienne latitude
Le truc, c'est que quelque chose d'étrange se passe avec mon implémentation car tous les emplacements aléatoires sont trop proches de mon centre de localisation, il semble que la formule ne couvre pas tout le rayon.
Une idée de ce qui pourrait mal avec ma formule?
Modifié pour montrer l'implémentation Java actuelle:
public static Location getLocation(Location location, int radius) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / METERS_IN_DEGREES;
double x0 = location.getLongitude() * 1E6;
double y0 = location.getLatitude() * 1E6;
double u = random.nextInt(1001) / 1000;
double v = random.nextInt(1001) / 1000;
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
// Set the adjusted location
Location newLocation = new Location("Loc in radius");
newLocation.setLongitude(new_x + x0);
newLocation.setLatitude(y + y0);
return newLocation;
}
Je ne suis pas sûr de ce que je fais mal, car les nouveaux emplacements sont créés au milieu de la mer.
Une idée?
la source
random.nextInt(1001)/1000
renverra une valeur supérieure à 1 environ 0,1% du temps. Pourquoi n'utilisez-vous pasrandom.nextDouble
ourandom.nextFloat
? (ii) La multiplicationx0
ety0
par1E6
est plutôt mystérieuse; il ne semble pas que cela produira des résultats corrects.Réponses:
Ceci est délicat pour deux raisons: premièrement, limiter les points à un cercle au lieu d'un carré; deuxièmement, la prise en compte des distorsions dans les calculs de distance.
De nombreux SIG incluent des capacités qui gèrent automatiquement et de manière transparente les deux complications. Cependant, les balises suggèrent ici qu'une description indépendante d'un SIG d'un algorithme peut être souhaitable.
Pour générer des points de manière uniforme, aléatoire et indépendante dans un cercle de rayon r autour d'un emplacement (x0, y0), commencez par générer deux valeurs aléatoires uniformes indépendantes u et v dans l'intervalle [0, 1). (C'est ce que presque tous les générateurs de nombres aléatoires vous fournissent.) Calcul
Le point aléatoire souhaité est à l'emplacement (x + x0, y + y0).
Lorsque vous utilisez des coordonnées géographiques (lat, lon), alors x0 (longitude) et y0 (latitude) seront en degrés mais r sera très probablement en mètres (ou pieds ou miles ou toute autre mesure linéaire). Tout d'abord, convertissez le rayon r en degrés comme si vous étiez situé près de l'équateur. Ici, il y a environ 111 300 mètres dans un degré.
Deuxièmement, après avoir généré x et y comme à l'étape (1), ajustez la coordonnée x pour le rétrécissement des distances est-ouest:
Le point aléatoire souhaité est à l'emplacement (x '+ x0, y + y0). Il s'agit d'une procédure approximative. Pour les petits rayons (moins de quelques centaines de kilomètres) qui ne s'étendent sur aucun des pôles de la terre, il sera généralement si précis que vous ne pourrez détecter aucune erreur même en générant des dizaines de milliers de points aléatoires autour de chaque centre (x0, y0) .
la source
Implémenté pour Javascript:
la source
L'implémentation correcte est:
J'ai supprimé la dépendance aux bibliothèques externes pour la rendre plus accessible.
la source
La réponse acceptée et les dérivés n'ont pas fonctionné pour moi. Les résultats étaient très inexacts.
Implémentation correcte en javascript:
L'essentiel ici
Dans la réponse acceptée - j'ai trouvé que les points sont répartis dans une ellipse avec sa largeur 1,5 fois sa hauteur (au Panama) et 8 fois sa hauteur (dans le nord de la Suède). Si j'ai supprimé l'ajustement de coordonnée x de la réponse de @ whuber, l'ellipse est déformée dans l'autre sens, 8 fois plus élevée que sa largeur.
Le code dans ma réponse était basé sur des algorithmes d' ici
Ci-dessous, vous pouvez voir deux jsfiddles qui montrent le problème avec l'ellipse d'étirement
Algorithme correct
Algorithme déformé
la source
whuberPointAtDistance()
:x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.En Python
Sortie
La distance entre les points est de 0,288044147914 La distance entre les points est de 0,409557451806 La distance entre les points est de 0,3668260305716 La distance entre les points est de 0,340720560546 La distance entre les points est de 0,453773334731 La distance entre les points est de 0,460608754561 La distance entre les points est de 0,497188825576 La distance entre les points est de 0,603178188859 La distance entre les points est 0,416629 La distance entre les points est de 0,503691568896 La distance entre les points est de 0,175153349209 La distance entre les points est de 0,195149463735 La distance entre les points est de 0,424094009858 La distance entre les points est de 0,286807741494 La distance entre les points est de 0,558049206307 La distance entre les points est de 0,498612171417 La distance entre les points est de 0,047344718215 La distance entre les points est de 0,484
la source
Vous pouvez vérifier les résultats de vos calculs ici . Faites défiler vers le bas jusqu'à la section intitulée «Point de destination en fonction de la distance et du relèvement par rapport au point de départ». Il y a même une simple formule JavaScript en bas pour implémenter cela. Vous devrez toujours générer un palier aléatoire $ \ theta $ en radians (mesuré dans le sens des aiguilles d'une montre à partir du nord), mais cela devrait être assez simple. Ces formules supposent une terre sphérique (bien qu'elle soit ellipsoïdale), ce qui est assez bon car elle produit des erreurs allant jusqu'à 0,3%.
la source
Implémentation pour Swift
Obtenir le lat et le lng du géoencodeur et le passer à cette fonction
Dans mon exemple ci-dessus, j'obtiens la latitude et les longitudes en géoencodant le nom du pays, car chaque fois, le nom du pays donne la même latitude et les mêmes longitudes, que trop au milieu du pays, donc j'avais besoin d'aléatoire.
la source
tirage privé nulPolyline (double lat, double lng) {
la source