41 votos

¿Generar ubicaciones aleatorias cercanas?

Estoy tratando de crear lugares aleatorios cerca de mi ubicación. Lo que quiero es crear pares de latitud/longitud aleatorios 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 la gente de StackOverFlow): (Número aleatorio entre -1 y 1)*radio + (longitud antigua) = nueva longitud dentro del radio de la longitud antigua

(Número aleatorio entre -1 y 1)*radio + (antigua latitud) = nueva latitud dentro del radio de la antigua latitud

El caso es que algo raro está pasando con mi implementación porque todas las localizaciones aleatorias están demasiado cerca de mi centro de localizació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?

2voto

Dolanor Puntos 246

Implementación para Swift

Obteniendo la lat y lng del geoencoder y pasándola a esta función

func generateRandomLocation(lat: CLLocationDegrees, lng: CLLocationDegrees){
    let radius : Double = 100000 // this is in meters so 100 KM
    let radiusInDegrees: Double = radius / 111000
    let u : Double = Double(arc4random_uniform(100)) / 100.0
    let v : Double = Double(arc4random_uniform(100)) / 100.0
    let w : Double = radiusInDegrees * u.squareRoot()
    let t : Double = 2 * Double.pi * v
    let x : Double = w * cos(t)
    let y : Double = w * sin(t)

    // Adjust the x-coordinate for the shrinking of the east-west distances
    //in cos converting degree to radian
    let new_x : Double = x / cos(lat * .pi / 180 )

    processedLat = new_x + lat
    processedLng = y + lng

    print("The Lat are :- ")
    print(processedLat)
    print("The Lng are :- ")
    print(processedLng)
}

En mi ejemplo anterior obtengo la latitud y las longitudes a partir de la geo-codificación del nombre del país, ya que cada vez, el nombre del país da la misma latitud y longitud, que también en el centro del país, por lo que necesitaba la aleatoriedad.

0voto

Precipitous Puntos 219

Puede comprobar los resultados de sus cálculos aquí . Desplázate hasta la sección llamada "Punto de destino dada la distancia y el rumbo desde el punto de partida". Incluso hay una sencilla fórmula de JavaScript en la parte inferior para implementar esto. Todavía tendrá que generar un rumbo aleatorio $\theta$ en radianes (medidos en el sentido de las agujas del reloj desde el norte), aunque eso debería ser bastante sencillo. Estas fórmulas suponen una tierra esférica (aunque es elipsoidal), lo cual es bastante bueno ya que produce errores de hasta el 0,3%.

-1voto

Implementación de PHP

function randomNearByCoord(array $coord, int $radiusKm, int $precision = 4): array
{
    $radiusRad = $radiusKm/111.3;
    $y0 = $coord['lat'];
    $x0 = $coord['lon'];
    $u = \lcg_value();
    $v = \lcg_value();
    $w = $radiusRad * \sqrt($u);
    $t = 2 * M_PI * $v;
    $x = $w * \cos($t);
    $y1 = $w * \sin($t);
    $x1 = $x / \cos(\deg2rad($y0));
    $newY = \round($y0 + $y1, $precision);
    $newX = \round($x0 + $x1, $precision);

    return ['lat' => $newY, 'lon' => $newX];
}

$center = ['lat' => 51.5146, 'lon' => -0.1361];
$newCoord = randomNearByCoord($center, 5);
var_dump($newCoord);

-2voto

Alexey Puntos 195

Private void drawPolyline(double lat,double lng) {

         double Pi=Math.PI;

         double lt=lat;
         double ln=lng;

        //Earth’s radius, sphere
         double R=6378137;

         double dn = 50;
         double de = 50;

         //Coordinate offsets in radians
         double dLat = dn/R;
         double dLon = de/(R*Math.cos(Pi*lat/180));

        //OffsetPosition, decimal degrees
        double lat2 = lt + dLat * 180/Pi;
        double lon2 = ln + dLon * 180/Pi ;

            //12.987859, 80.231038
            //12.987954, 80.231252

        double lat3 = lt - dLat * 180/Pi;
        double lon3 = ln - dLon * 180/Pi ;

            LatLng origin=new LatLng(lt, lon3);

            LatLng dest=new LatLng(lt, lon2);

          Polyline line = googleMap.addPolyline(new PolylineOptions()
         .add(origin, dest)
         .width(6)
         .color(Color.RED));

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X