Случайные географические координаты (на суше, избегать океана)

Любые умные идеи о том, как создавать случайные координаты (широта/долгота) мест на Земле? Широта Долгота. Точность до 5 баллов и избегать водоемов.

    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));

Может быть, я живу в мире мечты, и тема воды неизбежна... но, надеюсь, там будет более чистый, более чистый и эффективный способ сделать это?

ИЗМЕНИТЬ

Некоторые фантастические ответы/идеи - однако, в масштабе, скажем, мне нужно создать 25 000 координат. Переход к внешнему поставщику услуг может быть не лучшим вариантом из-за латентности, стоимости и нескольких других факторов.

Ответ 1

Для решения проблемы с водой проблема будет в основном проблемой данных, например. вы просто хотите пропустить океаны или вам нужно также пропустить небольшие ручьи. Либо вам нужно использовать службу с качеством данных, которые вам нужны, либо вам нужно получить данные самостоятельно и запустить их локально. Из вашего редактирования это звучит так, как будто вы хотите пройти локальный маршрут данных, поэтому я сосредоточусь на том, как это сделать.

Один из способов - получить шейп файл для земельных участков или акваторий. Затем вы можете создать случайную точку и определить, пересекает ли она участок земли (или, наоборот, не пересекает акваторию).

Чтобы начать работу, вы можете получить данные с низким разрешением здесь, а затем получить данные с более высоким разрешением здесь когда вы хотите получить лучшие ответы на береговых линиях или озерах/реках и т.д. Вы упомянули, что хотите, чтобы точность ваших очков составляла 5 знаков после запятой, что немного больше 1 м. Имейте в виду, что если вы получите данные для соответствия этой точности, у вас будет один гигантский набор данных. И, если вы хотите действительно хорошие данные, будьте готовы заплатить за это.

Когда у вас есть данные формы, вам понадобятся некоторые инструменты, которые помогут вам определить пересечение ваших случайных точек. Geotools - отличное место для начала и, вероятно, будет работать для ваших нужд. Вы также столкнетесь с кодом opengis (docs под сайтом geotools - не уверены, потребляли ли они их или что) и JTS для обработки геометрии. Используя это, вы можете быстро открыть шейп файл и начать выполнять некоторые запросы на пересечение.

    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 );

Краткие пояснения:

  • Предполагается, что полученный шейп файл - это многоугольные данные. Пересечение линий или точек не даст вам то, что вы хотите.
  • Первый раздел открывает шейп файл - ничего интересного
  • вам нужно получить имя свойства геометрии для данного файла
  • система координат - вы указали lat/long в своем сообщении, но GIS может быть немного сложнее. В общем, данные, на которые я указал вам, - это geographic, wgs84, и именно это я и установил здесь. Однако, если это не так для вас, вы должны быть уверены, что имеете дело с вашими данными в правильной системе координат. Если это все звучит как тарабарщина, google вокруг учебника по GIS/системам координат/datum/эллипсоид.
  • генерация геометрий координат и фильтров довольно понятны. Результирующий набор функций будет либо пустым, что означает, что координата находится в воде, если ваши данные являются обложками или не пустыми, что означает противоположность.

Примечание: если вы делаете это с действительно случайным набором точек, вы часто будете ударять по воде, и вам может потребоваться некоторое время, чтобы добраться до 25 тысяч очков. Возможно, вам захочется попытаться охватить ваше поколение точек лучше, чем по-настоящему случайным (например, удалить большие куски Атлантического/Тихого океана/Индийского океанов).

Кроме того, вы можете обнаружить, что ваши запросы на пересечение слишком медленные. Если это так, вы можете захотеть создать индекс quadtree (qix) с помощью инструмента, такого как GDAL. Я не помню, какие типы индексов поддерживаются геотегами.

Ответ 2

  • Загрузите грузовик KML файлов, содержащих только локальные места.
  • Извлеките из них все координаты это может помочь здесь.
  • Выберите их в случайном порядке.

Ответ 3

Есть еще один способ приблизиться к этому с помощью Google Earth Api. Я знаю, что это javascript, но я думал, что это новый способ решить проблему.

Во всяком случае, я собрал здесь полное рабочее решение - обратите внимание, что он работает и для рек: http://www.msa.mmu.ac.uk/~fraser/ge/coord/

Основная идея, которую я использовал, - реализовать метод hiTest Объект GEView в Google Earth Api.

Взгляните на следующий пример Hitest от Google. http://earth-api-samples.googlecode.com/svn/trunk/examples/hittest.html

Метод hitTest снабжается случайной точкой на экране (координаты пикселя), для которой он возвращает объект GEHitTestResult, который содержит информацию о географическом местоположении, соответствующем точке. Если вы используете режим GEPlugin.HIT_TEST_TERRAIN с помощью метода, можно ограничить результаты только приземлением (рельефом), пока мы просматриваем результаты в точках с высотой > 1 м

Это функция, которую я использую для реализации 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 };
};

Очевидно, что вы также хотите иметь случайные результаты из любого места на земном шаре (а не только случайные точки, видимые с одной точки зрения). Для этого я перемещаю вид земли после каждого успешного вызова hitTestTerrain. Это достигается с помощью небольшой вспомогательной функции.

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

Наконец, это урезанная версия основного блока кода, который вызывает эти два метода.

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();
    }
};

Итак, земля перемещается случайным образом к постулированию

В других функциях есть только помощники для генерации случайных x, y и случайных чисел lat, lng для вывода результатов, а также для переключения элементов управления и т.д.

Я немного тестировал код, и результаты не были на 100% идеальными, улучшая altitude до уровня выше, например 50 м, но, очевидно, он уменьшает область возможных выбранных координат.

Очевидно, вы могли бы адаптировать идею в соответствии с вашими потребностями. Возможно, несколько раз запустите код, чтобы заполнить базу данных или что-то еще.

Ответ 4

Чтобы получить хорошее равномерное распределение по широтам и долготам, вы должны сделать что-то подобное, чтобы получить правильные углы:

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

Как для избежания водоемов, у вас есть данные о том, где вода уже есть? Ну, просто переделайте, пока не получите хит! Если у вас нет этих данных, то кажется, что некоторые другие люди имеют несколько лучших предложений, чем я хотел бы для этого...

Надеюсь, это поможет, приветствует.

Ответ 5

Это спрашивается давным-давно, и теперь у меня есть аналогичная потребность. Есть две возможности, которые я изучаю:

1. Определите диапазоны поверхностей для случайного генератора.

Здесь важно определить уровень точности, в котором вы собираетесь двигаться. Самый простой способ - иметь очень расслабленный и приблизительный подход. В этом случае вы можете разделить карту мира на "ящики":

введите описание изображения здесь

Каждый ящик имеет собственный диапазон lat lon. Затем вы сначала производителю, чтобы получить случайную ячейку, затем вы производите случайный лат и случайный длинный в пределах границ этого окна.

Точность, конечно, не самая лучшая здесь... Хотя это зависит: если вы хорошо выполняете домашнее задание и определяете множество ящиков, покрывающих самые сложные формы поверхности, вы можете быть в порядке с точностью.

2. Элемент списка

Некоторые API возвращают имя континента из координат ИЛИ адрес ИЛИ страны ИЛИ района = то, чего нет в ВОДЕ. API Карт Google может помочь здесь. Я не исследовал эту проблему глубже, но я думаю, что это возможно, хотя вам придется запускать проверку каждой сгенерированной пары координат и повторять ее, если это неправильно. Поэтому вы можете немного застрять, если случайный генератор продолжает бросать вас в океан.

Кроме того, некоторые воды принадлежат странам, районам... так что да, не очень точно.

Для моих нужд - я собираюсь с "ящиками", потому что я также хочу контролировать точные области, из которых берутся случайные координаты, и не против, если они приземляются на озеро или реку, просто не открывайте океан:)

Ответ 6

Определенно, вы должны иметь карту в качестве ресурса. Вы можете взять его здесь: http://www.naturalearthdata.com/

Затем я подготовил 1 бит черно-белый растровый ресурс с отметкой 1s и 0x отметкой воды.

Размер растрового изображения зависит от вашей требуемой точности. Если вам нужно 5 градусов, то ваше растровое изображение будет 360/5 x 180/5 = 72x36 пикселей = 2592 бит.

Затем я бы загрузил это растровое изображение в Java, генерировал случайное целое число с диапазоном выше, бит чтения и регенерировал, если он был равен нулю.

P.S. Также вы можете копать здесь http://geotools.org/ для некоторых готовых решений.

Ответ 7

Как план B, возможно, вы можете выбрать случайную страну, а затем выбрать случайную координату внутри этой страны. Чтобы быть справедливым при выборе страны, вы можете использовать ее площадь как вес.

Ответ 9

Я думаю, вы могли бы использовать карту мира, определить несколько точек на ней, чтобы разграничить большинство водных объектов, как вы говорите, и использовать метод polygon.contains для проверки координат.

Более быстрый алгоритм должен был бы использовать эту карту, взять некоторую случайную точку и проверить цвет ниже, если он синий, а затем вода... когда у вас есть координаты, вы конвертируете их в lat/long.

Ответ 10

Вы также можете сделать сине-зеленую вещь, а затем сохранить все зеленые точки для последующего поиска. У этого есть преимущество в том, что он "шаг за шагом" перепланируется. Когда вы выясните лучший способ составить свой список очков, вы можете просто указать своему случайному грабежу в более и более ясную группу очков.

Возможно, у поставщика услуг уже есть ответ на ваш вопрос: например. https://www.google.com/enterprise/marketplace/viewListing?productListingId=3030+17310026046429031496&pli=1

Высота api? http://code.google.com/apis/maps/documentation/elevation/ над уровнем моря или ниже? (нет голландских очков для вас!)

Ответ 11

Существует библиотека здесь, и вы можете использовать ее метод .random() для получения случайной координаты. Затем вы можете использовать GeoNames WebServices, чтобы определить, находится ли он на суше или нет. У них есть список веб-сервисов, и вам просто нужно будет использовать правильный. GeoNames является бесплатным и надежным.

Ответ 12

Создание легко, проблема в том, что они не должны находиться на воде. Я бы импортировал "Open Streetmap", например, здесь http://ftp.ecki-netz.de/osm/ и импортировал его в базу данных (verry easy data Structure). Я бы предложил PostgreSQL, он поставляется с некоторыми гео-функциями http://www.postgresql.org/docs/8.2/static/functions-geometry.html. Для этого вам нужно сохранить точки в "polygon" -column, затем вы можете проверить с помощью "& &" если он находится в полигоне воды. Для атрибутов OpenStreetmap Way-Entry вы должны взглянуть на http://wiki.openstreetmap.org/wiki/Category:En:Keys

Ответ 13

Нужно ли равномерно распределять случайные точки по всему миру? Если вы можете согласиться на кажущееся равномерное распределение, вы можете сделать это:

Откройте свою любимую картографическую службу, нарисуйте прямоугольник внутри США, России, Китая, Западной Европы и, безусловно, северную часть Африки - убедитесь, что в прямоугольниках нет больших озер или каспийских морей. Возьмите угловые координаты каждого прямоугольника, а затем произвольно выберите координаты внутри этих прямоугольников.

Вы гарантированы, что эти очки не будут находиться на любом море или озерах. Вы можете найти редкую реку, но я не уверен, сколько геосервисов будет для этого достаточно точным.

Ответ 14

Это чрезвычайно интересный вопрос, как с теоретической, так и с практической точки зрения. Наиболее подходящее решение во многом будет зависеть от ваших точных требований. Вам нужно учитывать каждый водоем, или только основные моря и океаны? Насколько важны точность и правильность; Будет ли определение моря как земли или наоборот катастрофическим провалом?

Я думаю, что методы машинного обучения будут отличным решением этой проблемы, если вы не возражаете (надеюсь, малая) вероятность того, что точка воды неправильно классифицируется как земля. Если это не проблема, то этот подход должен иметь ряд преимуществ против других методов.

Использование растрового изображения - приятное решение, простое и элегантное. Он может быть произведен с определенной точностью, и классификация гарантирована как правильная (или, по крайней мере, такая же правильная, как вы сделали растровое изображение). Но его практичность зависит от того, насколько точным вам должно быть решение. Вы отмечаете, что вам нужна точность координат до 5 знаков после запятой (что эквивалентно отображению всей поверхности планеты примерно на ближайший метр). Используя 1 бит на элемент, битмап будет весить около ~ 73,6 терабайт!

Нам не нужно хранить все эти данные; Нам нужно только знать, где находятся береговые линии. Просто зная, где точка относится к побережью, мы можем определить, находится ли она на суше или на море. По приблизительным подсчетам, всемирная информационная книга ЦРУ сообщает, что на Земле существует 22498 км береговой линии. Если мы будем хранить координаты для каждого метра береговой линии, используя 32-битное слово для каждой широты и долготы, это займет менее 1,35 ГБ для хранения. Это все еще много, если это для тривиального приложения, но на несколько порядков меньше, чем использование растрового изображения. Если иметь такую ​​высокую степень точности не обязательно, эти цифры значительно уменьшатся. Уменьшение отображения только на ближайший километр сделало бы растровое изображение всего ~ 75 ГБ, а координаты для мировой береговой линии могли поместиться на гибкий диск.

Я предлагаю использовать алгоритм кластеризации, чтобы решить, находится ли точка на суше или нет. Сначала нам понадобилось бы достаточно большое количество координат, которые мы уже знаем, как на суше, так и на море. Для этого пригодны существующие базы данных ГИС. Затем мы можем проанализировать точки для определения кластеров суши и моря. Граница решения между кластерами должна падать на береговые линии, и все точки, не определяющие границу решения, могут быть удалены. Этот процесс можно повторить, чтобы получить более точную границу.

Необходимо сохранить только точки, определяющие границу решения/береговую линию, и, используя простую метрику расстояния, мы можем быстро и легко решить, находится ли набор координат на суше или на море. Для обучения системы потребуется большое количество ресурсов, но после завершения классификатора потребуется очень мало места или времени.

Ответ 15

Предполагая, что Atlantis не находится в базе данных, вы можете случайно выбрать города. Это также обеспечивает более реалистичное распределение баллов, если вы собираетесь имитировать человеческую деятельность: https://simplemaps.com/data/world-cities

В бесплатной версии доступно только 7 300 городов.