Estoy tratando de crear ubicaciones aleatorias cerca de mi ubicación. Lo que quiero es crear pares aleatorios de latitud / longitud dentro de un círculo de 200 metros que rodea mi ubicación.
Esta es la fórmula que se me ocurrió (con la ayuda de personas en StackOverFlow): (Número aleatorio entre -1 y 1) * radio + (longitud anterior) = longitud nueva dentro del radio de longitud anterior
(Número aleatorio entre -1 y 1) * radio + (latitud anterior) = nueva latitud dentro del radio de la latitud anterior
Lo que pasa es que algo extraño está sucediendo con mi implementación porque todas las ubicaciones aleatorias están demasiado cerca de mi centro de ubicación, parece que la fórmula no cubre todo el radio.
¿Alguna idea de lo que podría estar mal con mi fórmula?
Editado para mostrar la implementación actual de Java:
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;
}
No estoy seguro de lo que estoy haciendo mal, porque las nuevas ubicaciones se crean en medio del mar.
¿Alguna idea?
fuente
random.nextInt(1001)/1000
devolverá un valor mayor que 1 aproximadamente 0.1% del tiempo. ¿Por qué no estás usandorandom.nextDouble
orandom.nextFloat
? (ii) Multiplicarx0
yy0
por1E6
es bastante misterioso; no parece que produzca resultados correctos.Respuestas:
Esto es complicado por dos razones: primero, limitar los puntos a un círculo en lugar de un cuadrado; segundo, teniendo en cuenta las distorsiones en los cálculos de distancia.
Muchos SIG incluyen capacidades que manejan de manera automática y transparente ambas complicaciones. Sin embargo, las etiquetas aquí sugieren que una descripción independiente de SIG de un algoritmo puede ser deseable.
Para generar puntos de manera uniforme, aleatoria e independiente dentro de un círculo de radio r alrededor de una ubicación (x0, y0), comience generando dos valores aleatorios uniformes independientes u y v en el intervalo [0, 1). (Esto es lo que casi todos los generadores de números aleatorios le proporcionan).
El punto aleatorio deseado está en la ubicación (x + x0, y + y0).
Cuando se utilizan coordenadas geográficas (lat, lon), entonces x0 (longitud) e y0 (latitud) estarán en grados, pero lo más probable es que r esté en metros (o pies o millas o alguna otra medida lineal). Primero, convierta el radio r en grados como si estuviera ubicado cerca del ecuador. Aquí, hay unos 111.300 metros en un grado.
En segundo lugar, después de generar x e y como en el paso (1), ajuste la coordenada x para reducir las distancias este-oeste:
El punto aleatorio deseado está en la ubicación (x '+ x0, y + y0). Este es un procedimiento aproximado. Para radios pequeños (menos de unos pocos cientos de kilómetros) que no se extienden sobre ninguno de los polos de la tierra, por lo general será tan preciso que no podrá detectar ningún error incluso cuando genere decenas de miles de puntos aleatorios alrededor de cada centro (x0, y0) .
fuente
Implementado para Javascript:
fuente
La implementación correcta es:
Eliminé la dependencia de bibliotecas externas para hacerlo más accesible.
fuente
La respuesta aceptada y los derivados no funcionaron para mí. Los resultados fueron muy inexactos.
Implementación correcta en javascript:
La esencia completa aquí
En la respuesta aceptada, descubrí que los puntos se distribuyen en una elipse con un ancho de 1.5 veces su altura (en Panamá) y 8 veces su altura (en el norte de Suecia). Si eliminé el ajuste x coord de la respuesta de @ whuber, la elipse se distorsiona de la otra manera, 8 veces más que su ancho.
El código en mi respuesta se basó en algoritmos de aquí
A continuación puede ver dos jsfiddles que muestran el problema con la elipse de estiramiento
Algoritmo correcto
Algoritmo distorsionado
fuente
whuberPointAtDistance()
:x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.En python
Salida
La distancia entre puntos es 0.288044147914 La distancia entre puntos es 0.409557451806 La distancia entre puntos es 0.368260305716 La distancia entre puntos es 0.340720560546 La distancia entre puntos es 0.453773334731 La distancia entre puntos es 0.460608754561 La distancia entre puntos es 0.497188825577 La distancia entre puntos es 0.6031781888598 La distancia entre puntos es 0.6031781888598 La distancia entre puntos Distancia entre puntos es 0.503691568896 Distancia entre puntos es 0.175153349209 Distancia entre puntos es 0.195149463735 Distancia entre puntos es 0.424094009858 Distancia entre puntos es 0.286807741494 Distancia entre puntos es 0.558049206307 Distancia entre puntos es 0.498612171417 Distancia entre puntos es 0.047344718215 Distancia entre puntos es 0.047344718242 Distancia entre puntos
fuente
Puede consultar los resultados de sus cálculos aquí . Desplácese hacia abajo hasta la sección llamada "Distancia dada del punto de destino y demora desde el punto de inicio". Incluso hay una fórmula simple de JavaScript en la parte inferior para implementar esto. Aún necesitará generar un rumbo aleatorio $ \ theta $ en radianes (medido en sentido horario desde el norte), aunque eso debería ser bastante sencillo. Estas fórmulas suponen una tierra esférica (aunque es elipsoidal), que es lo suficientemente buena, ya que produce errores de hasta 0.3%.
fuente
Implementación para Swift
Obtener el lat y lng del geoencoder y pasarlo a esta función
En mi ejemplo anterior, obtengo la latitud y las longitudes al geocodificar el nombre del país, ya que cada vez el nombre del país proporciona la misma latitud y longitud, que también en el medio del país, por lo que necesitaba aleatoriedad.
fuente
privado vacío drawPolyline (doble lat, doble lng) {
fuente