Coordenadas geográficas aleatorias (en tierra, evitar el océano)


¿Alguna idea inteligente sobre cómo generar coordenadas aleatorias (latitud / longitud) de lugares en la Tierra? Latitud / Longitud. Precisión a 5 puntos y evitar cuerpos de agua.

    double minLat = -90.00;
    double maxLat = 90.00;      
    double latitude = minLat + (double)(Math.random() * ((maxLat - minLat) + 1));
    double minLon = 0.00;
    double maxLon = 180.00;     
    double longitude = minLon + (double)(Math.random() * ((maxLon - minLon) + 1));
    DecimalFormat df = new DecimalFormat("#.#####");        
    log.info("latitude:longitude --> " + df.format(latitude) + "," + df.format(longitude));

Tal vez estoy viviendo en un mundo de sueños y el tema del agua es inevitable ... pero esperemos que haya una manera más agradable, más limpia y más eficiente de hacer esto?

EDITAR

Algunas respuestas/ideas fantásticas however sin embargo, a escala, digamos que necesito generar 25,000 coordenadas. Ir a una el proveedor de servicios externo puede no ser la mejor opción debido a la latencia, el costo y algunos otros factores.

Author: Charles, 2012-02-02

16 answers

Lidiar con el problema del cuerpo de agua va a ser en gran medida un problema de datos, por ejemplo, ¿solo quieres perder los océanos o también necesitas perder pequeños arroyos? O bien necesita usar un servicio con la calidad de los datos que necesita, o bien necesita obtener los datos usted mismo y ejecutarlos localmente. Desde su edición, parece que desea ir a la ruta de datos local, así que me centraré en una forma de hacerlo.

Un método es obtener un shapefile para áreas terrestres o áreas acuáticas. Usted luego puede generar un punto aleatorio y determinar si interseca un área de tierra (o alternativamente, no interseca un área de agua).

Para comenzar, puede obtener algunos datos de baja resolución aquí y luego obtener datos de mayor resolución aquí para cuando desee obtener mejores respuestas en líneas costeras o con lagos/ríos/etc. Usted mencionó que desea precisión en sus puntos a 5 decimales, que es un poco más de 1m. Tenga en cuenta que si obtiene datos que coincidan precisión, usted tendrá un conjunto de datos gigante. Y, si desea datos realmente buenos, prepárese para pagar por ellos.

Una vez que tenga sus datos de forma, necesita algunas herramientas para ayudarlo a determinar la intersección de sus puntos aleatorios. Geotools es un gran lugar para comenzar y probablemente funcionará para sus necesidades. También terminará mirando el código opengis (documentos en geotools site - no estoy seguro de si los consumieron o qué) y JTS para el manejo de la geometría. Usando esto usted puede abra rápidamente el shapefile y comience a hacer algunas consultas de intersección.

    File f = new File ( "world.shp" );
    ShapefileDataStore dataStore = new ShapefileDataStore ( f.toURI ().toURL () );
    FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = 
        dataStore.getFeatureSource ();
    String geomAttrName = featureSource.getSchema ()
        .getGeometryDescriptor ().getLocalName ();

    ResourceInfo resourceInfo = featureSource.getInfo ();
    CoordinateReferenceSystem crs = resourceInfo.getCRS ();
    Hints hints = GeoTools.getDefaultHints ();
    hints.put ( Hints.JTS_SRID, 4326 );
    hints.put ( Hints.CRS, crs );

    FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2 ( hints );
    GeometryFactory gf = JTSFactoryFinder.getGeometryFactory ( hints );

    Coordinate land = new Coordinate ( -122.0087, 47.54650 );
    Point pointLand = gf.createPoint ( land );
    Coordinate water = new Coordinate ( 0, 0 );
    Point pointWater = gf.createPoint ( water );

    Intersects filter = ff.intersects ( ff.property ( geomAttrName ), 
        ff.literal ( pointLand ) );
    FeatureCollection<SimpleFeatureType, SimpleFeature> features = featureSource
            .getFeatures ( filter );

    filter = ff.intersects ( ff.property ( geomAttrName ), 
        ff.literal ( pointWater ) );
    features = featureSource.getFeatures ( filter );

Explicaciones rápidas:

  1. Esto asume que el shapefile que tienes son datos de polígonos. La intersección en líneas o puntos no te dará lo que quieres.
  2. La primera sección abre el shapefile-nada interesante
  3. debe obtener el nombre de la propiedad geometry para el archivo dado
  4. cosas del sistema de coordenadas-especificaste lat / long en tu post, pero SIG puede ser bastante complicar. En general, los datos que te señalé son geographic, wgs84 , y eso es lo que configuré aquí. Sin embargo, si este no es el caso para usted, debe asegurarse de que está tratando con sus datos en el sistema de coordenadas correcto. Si todo eso suena como un galimatías, busca en Google un tutorial sobre SIG/sistemas de coordenadas/datum/elipsoide.
  5. generar las geometrías de coordenadas y los filtros son bastante autoexplicativos. El conjunto de características resultante: estar vacío, lo que significa que la coordenada está en el agua si sus datos son cobertura terrestre, o no vacío, lo que significa lo contrario.

Nota: si haces esto con un conjunto realmente aleatorio de puntos, vas a golpear el agua bastante a menudo y podría tomar un tiempo para llegar a 25k puntos. Es posible que desee tratar de medir su generación de puntos mejor que al azar (como eliminar grandes trozos de los océanos Atlántico/Pacífico/Índico).

Además, puede encontrar que sus consultas de intersección son demasiado lentas. Si es así, es posible que desee buscar en la creación de un índice de quadtree (qix) con una herramienta como GDAL. Sin embargo, no recuerdo qué tipos de índice son compatibles con geotools.

 14
Author: philwb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-17 19:58:28
  1. Descargue un camión lleno de archivos KML que contienen ubicaciones solo terrestres.
  2. Extraer todas las coordenadas de ellos esto podría ayudar aquí.
  3. Escógelos al azar.
 4
Author: OldCurmudgeon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-13 15:25:10

Esto se ha pedido hace mucho tiempo y ahora tengo la misma necesidad. Hay dos posibilidades que estoy investigando:

1. Defina los rangos de superficie para el generador aleatorio.

Aquí es importante identificar el nivel de precisión que busca. La forma más fácil sería tener un enfoque muy relajado y aproximado. En este caso se puede dividir el mapa del mundo en"cajas":

introduzca la descripción de la imagen aquí

Cada caja tiene su propio rango de lat lon. Entonces primero aleatorizamos para obtener una caja aleatoria, luego aleatorizamos para obtener una lat aleatoria y una long aleatoria dentro de los límites de esa caja.

Precisions no es, por supuesto, el mejor aquí... Aunque depende:) Si haces bien tu tarea y defines una gran cantidad de cajas que cubren la mayoría de las formas de superficies complejas, podrías estar bastante bien con la precisión.

2. List item

Alguna API para devolver el nombre del continente desde coordenadas O dirección O país O distrito = algo esa AGUA no tiene. Las API de Google Maps pueden ayudar aquí. No investigué esto más a fondo, pero creo que es posible, aunque tendrás que ejecutar la verificación en cada par de coordenadas generadas y volver a ejecutarlas SI está mal. Así que puedes quedarte un poco atascado si random Generator te sigue arrojando al océano.

También-algo de agua pertenece a los países, districts...so sí, no muy preciso.

Para mis necesidades-voy con "cajas" porque también quiero controlar las áreas exactas de que se toman las coordenadas aleatorias y no les importa si aterriza en un lago o río, simplemente no en mar abierto:)

 4
Author: GeekSince1982,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 15:02:09

Definitivamente deberías tener un mapa como recurso. Puedes tomarlo aquí: http://www.naturalearthdata.com /

Entonces prepararía un recurso de mapa de bits en blanco y negro de 1 bit con 1s marcando tierra y 0x marcando agua.

El tamaño del mapa de bits depende de la precisión requerida. Si necesita 5 grados, su mapa de bits será de 360/5 x 180/5 = 72x36 píxeles = 2592 bits.

Luego cargaría este mapa de bits en Java, generaría un entero aleatorio dentro del rango anterior, leería el bit y regenerar si fuera cero.

P.d. También puedes cavar aquí http://geotools.org / para algunas soluciones ya hechas.

 3
Author: Suzan Cioc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-13 17:58:35

Hay otra forma de abordar esto usando la Api de Google Earth. Sé que es javascript, pero pensé que era una forma novedosa de resolver el problema.

De todos modos, he reunido una solución de trabajo completa aquí-observe que funciona para los ríos también: http://www.msa.mmu.ac.uk / ~fraser / ge / coord /

La idea básica que he usado es implementar el método hiTest del objeto GEView en la Api Google Earth.

Eche un vistazo a lo siguiente ejemplo de los más exitosos de Google. http://earth-api-samples.googlecode.com/svn/trunk/examples/hittest.html

El método hitTest se suministra un punto aleatorio en la pantalla en (coordenadas de píxeles) para el que devuelve un objeto GEHitTestResult que contiene información sobre la ubicación geográfica correspondiente al punto. Si se utiliza el GEPlugin.HIT_TEST_TERRAIN mode con el método uno puede limitar los resultados solo a la tierra (terreno), siempre y cuando la pantalla de los resultados a los puntos con una altitud > 1m

Esta es la función que uso que implementa el hitTest:

var hitTestTerrain = function()
{
    var x = getRandomInt(0, 200); // same pixel size as the map3d div height
    var y = getRandomInt(0, 200); // ditto for width
    var result = ge.getView().hitTest(x, ge.UNITS_PIXELS, y, ge.UNITS_PIXELS, ge.HIT_TEST_TERRAIN);
    var success = result && (result.getAltitude() > 1);
    return { success: success, result: result };
};

Obviamente, también desea tener resultados aleatorios de cualquier parte del mundo (no solo puntos aleatorios visibles desde un solo punto de vista). Para hacer esto muevo la vista tierra después de cada llamada hitTestTerrain exitosa. Esto se logra usando una pequeña función auxiliar.

var flyTo = function(lat, lng, rng)
{
    lookAt.setLatitude(lat);
    lookAt.setLongitude(lng);
    lookAt.setRange(rng);
    ge.getView().setAbstractView(lookAt);
};

Finalmente aquí hay una versión simplificada del bloque de código principal que llama a estos dos métodos.

var getRandomLandCoordinates = function()
{
    var test = hitTestTerrain();
    if (test.success)
    {
        coords[coords.length] = { lat: test.result.getLatitude(), lng: test.result.getLongitude() };
    }

    if (coords.length <= number)
    {
       getRandomLandCoordinates();
    }
    else
    {
       displayResults();
    }
};

Entonces, la tierra se mueve al azar a una posición

Las otras funciones allí solo son ayudantes para generar los números aleatorios x,y y lat,lng, para generar los resultados y también para alternar los controles, etc.

He probado el código bastante y los resultados no son 100% perfectos, ajustando el altitude a algo más alto, como 50m resuelve esto, pero obviamente está disminuyendo el área de posibles coordenadas seleccionadas.

Obviamente podrías adaptar la idea a tus necesidades. Tal vez corriendo el código varias veces para llenar una base de datos o algo así.

 3
Author: Fraser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-21 08:05:00

Para obtener una buena distribución uniforme sobre latitudes y longitudes, debe hacer algo como esto para obtener los ángulos rectos:

double longitude = Math.random() * Math.PI * 2;
double latitude = Math.acos(Math.random() * 2 - 1);

En cuanto a evitar cuerpos de agua, ¿tiene los datos de dónde ya está el agua? Bueno, sólo vuelve a muestrear hasta que consigas un éxito! Si usted no tiene estos datos ya entonces parece que algunas otras personas tienen algunas sugerencias mejores que yo para eso...

Espero que esto ayude, saludos.

 2
Author: Elias Vasylenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-13 19:54:34

Como plan B, tal vez puedas elegir un país aleatorio y luego elegir una coordenada aleatoria dentro de este país. Para ser justos al elegir un país, puede usar su área como peso.

 2
Author: cassioso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-06 12:54:32

Hay una biblioteca aquí y puedes usarla .método random () para obtener una coordenada aleatoria. Luego puede usar GeoNames WebServices para determinar si está en tierra o no. Tienen una lista de servicios web y solo tendrás que usar el correcto. GeoNames es gratis y confiable.

 1
Author: bsimic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-14 14:53:22
 1
Author: Kamil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-18 10:03:43

Supongo que podrías usar un mapa del mundo, definir algunos puntos en él para delimitar la mayoría de los cuerpos de agua como dices y usar un polígono.contiene el método para validar las coordenadas.

Un algoritmo más rápido sería usar este mapa, tomar algún punto aleatorio y verificar el color debajo, si es azul, luego agua... cuando tienes las coordenadas, las conviertes a lat / long.

 0
Author: Snicolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-01 23:40:12

También puede hacer lo azul verde , y luego almacenar todos los puntos verdes para buscar más adelante. Esto tiene el benifit de ser" paso sabio " refinable. A medida que encuentre una mejor manera de hacer su lista de puntos, puede apuntar su graber aleatorio a un grupo de puntos cada vez más preciso.

Tal vez un proveedor de servicios ya tiene una respuesta a su pregunta: p. ej. https://www.google.com/enterprise/marketplace/viewListing?productListingId=3030+17310026046429031496&pli=1

¿Api de elevación? http://code.google.com/apis/maps/documentation/elevation / sobre el nivel del mar o por debajo? (¡no hay puntos holandeses para ti!)

 0
Author: David Thornton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-02 02:49:22

Generar es fácil, el problema es que no deben estar en el agua. Importaría el "Open Streetmap" por ejemplo aquí http://ftp.ecki-netz.de/osm / e importarlo a una base de datos (verry easy data Structure). Yo sugeriría PostgreSQL, viene con algunas funciones geo http://www.postgresql.org/docs/8.2/static/functions-geometry.html . Para eso tienes que guardar los puntos en una columna de"polígono", luego puedes comprobar con el operador "& & " si está en un polígono de agua. Para los atributos de una entrada de Vía de OpenStreetMap deberías echar un vistazo a http://wiki.openstreetmap.org/wiki/Category:En:Keys

 0
Author: wutzebaer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-17 18:43:19

Complementario a lo que bsimic dijo acerca de profundizar en los servicios web de GeoNames, aquí hay un atajo:
tienen un servicio web dedicado para solicitar un nombre de océano.

(Soy consciente de la restricción de OP a no utilizando servicios web públicos debido a la cantidad de solicitudes. Sin embargo, me topé con esto con la misma pregunta básica y lo considero útil.)

Vaya a http://www.geonames.org/export/web-services.html#astergdem y echa un vistazo a"Ocean / reverse geocoding". Está disponible como XML y JSON. Cree una cuenta de usuario gratuita para evitar límites diarios en la cuenta demo.

Ejemplo de solicitud sobre la zona oceánica (Mar Báltico, JSON-URL):

http://api.geonames.org/oceanJSON?lat=54.049889&lng=10.851388&username=demo

Resultados en

{
  "ocean": {
    "distance": "0",
    "name": "Baltic Sea"
  }
}

Mientras que algunas coordenadas en tierra resultan en

{
  "status": {
    "message": "we are afraid we could not find an ocean for latitude and longitude :53.0,9.0",
    "value": 15
  }
}
 0
Author: hennzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-07 20:40:37

¿Los puntos aleatorios tienen que ser distribuidos uniformemente por todo el mundo? Si pudieras conformarte con una aparentemente distribución uniforme, puedes hacer esto:

Abra su servicio de mapas favorito, dibuje un rectángulo dentro de los Estados Unidos, Rusia, China, Europa Occidental y definitivamente la parte norte de África, asegurándose de que no haya grandes lagos o mares caspios dentro de los rectángulos. Tome las coordenadas de la esquina de cada rectángulo, y luego seleccione coordenadas al azar dentro de esos rectángulos.

Se le garantiza que ninguno de estos puntos estará en cualquier mar o lago. Usted puede encontrar un río ocasional, pero no estoy seguro de cuántos geoservicios van a ser lo suficientemente precisos para que de todos modos.

 -1
Author: zmbq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-18 07:24:23

Esta es una pregunta extremadamente interesante, tanto desde una perspectiva teórica como práctica. La solución más adecuada dependerá en gran medida de sus requisitos exactos. ¿Necesita tener en cuenta cada cuerpo de agua, o solo los principales mares y océanos? Cuán críticos son la precisión y la corrección; ¿Será una falla catastrófica identificar el mar como tierra o viceversa?

Creo que las técnicas de aprendizaje automático serían una excelente solución a este problema, siempre que no le importe la probabilidad (con suerte pequeña) de que un punto de agua esté clasificado incorrectamente como tierra. Si eso no es un problema, entonces este enfoque debe tener una serie de ventajas frente a otras técnicas.

Usar un mapa de bits es una buena solución, simple y elegante. Se puede producir con una precisión especificada y se garantiza que la clasificación sea correcta (O al menos tan correcta como hizo el mapa de bits). Pero su practicidad depende de cuán precisa sea la solución. Mencionas eso. desea que la precisión de las coordenadas sea de 5 decimales (lo que sería equivalente a mapear toda la superficie del planeta aproximadamente al metro más cercano). Usando 1 bit por elemento, el mapa de bits pesaría en ~73.6 terabytes!

Sin embargo, no necesitamos almacenar todos estos datos; solo necesitamos saber dónde están las costas. Con solo saber dónde está un punto en relación con la costa, podemos determinar si está en tierra o en mar. Como una estimación aproximada, el CIA world factbook informa que hay son 22498km de costa en la Tierra. Si tuviéramos que almacenar coordiates para cada metro de costa, usando una palabra de 32 bits para cada latitud y longitud, esto tomaría menos de 1.35 GB para almacenar. Todavía es mucho si esto es para una aplicación trivial, pero unos pocos órdenes de magnitud menos que el uso de un mapa de bits. Si tener un grado tan alto de precisión no es necesario, sin embargo, estos números caerían considerablemente. Reducir la asignación a solo el kilómetro más cercano haría que el mapa de bits solo ~75 GB y las coordenadas de la costa del mundo podrían caber en un disquete.

Lo que propongo es usar un algoritmo de agrupación para decidir si un punto está en tierra o no. Primero necesitaríamos un número adecuado de coordenadas que ya sabemos que están en tierra o mar. Las bases de datos SIG existentes serían adecuadas para ello. Luego podemos analizar los puntos para determinar los grupos de tierra y mar. El límite de decisión entre los grupos debe caer en las líneas costeras, y todos los puntos no la determinación del límite de decisión se puede eliminar. Este proceso se puede iterar para dar un límite progresivamente más preciso.

Solo los puntos que determinan el límite de decisión/la costa deben almacenarse, y mediante el uso de una métrica de distancia simple podemos decidir rápida y fácilmente si un conjunto de coordenadas está en tierra o mar. Se necesitaría una gran cantidad de recursos para entrenar el sistema, pero una vez completado el clasificador se requeriría muy poco espacio o tiempo.

 -1
Author: GenericJon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-18 14:57:45

Suponiendo que Atlantis no esté en la base de datos, podrías seleccionar ciudades al azar. Esto también proporciona una distribución más realista de puntos si tiene la intención de imitar la actividad humana: https://simplemaps.com/data/world-cities

Solo hay 7.300 ciudades en la versión gratuita.

 -1
Author: steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-12 17:14:51