Как надежно построить гексагональную сетку на карте мира

Цель

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

Первая попытка

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

// Attempting to cover the whole map in small hexagons
turf.hexGrid([-179.99, -89.99, 179.99, 89.99], 0.2);

Первая попытка, но с изюминкой

Моя вторая идея состояла в том, чтобы использовать параметр mask для hexGrid(), чтобы я по-прежнему генерировал шестигранную сетку с неизменными координатами шестиугольника, но пытался бы визуализировать шестиугольники только в пределах небольшой области карты (например, области, видимой на карте). Это тоже не представляется возможным, поскольку даже создание такой сетки (без отрисовки ее на карте) оказывается слишком большим потреблением ресурсов.

// Attempting to cover the whole map in small hexagons only within a given area (mask)
turf.hexGrid([-179.99, -89.90, 178.99, 88.90], 30, {
  mask: polygon([[[20, 60], [21, 60], [22, 62], [22, 63], [20, 60]]]),
});

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

перекошенные шестиугольники при распределении по большой площади

Оптимистические расчеты

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

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

Пример из реальной жизни. Самый близкий пример того, чего я хочу достичь, - это запущенная игра под названием «Run an Empire». Кажется, что шестигранная сетка загружается по запросу и только вокруг области, в которой он находится. Судя по всему, эта сетка не имеет зазоров, которые мешали бы шестиугольникам идеально соединяться.

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

Главный вопрос

Учитывая географические координаты, такие как местоположение GPS, как можно надежно создать гексагональную сетку, чтобы при создании другой гексагональной сетки на основе другого набора координат эти две сетки идеально перекрывались? Я открыт для решения этой проблемы любыми инструментами, не обязательно Turf или Mapbox.


Сделать скриншот игры


person Maciej Gurban    schedule 22.04.2019    source источник
comment
Какую систему координат вы используете? Может ли гексагональный слой быть векторным слоем, динамически загружаемым по мере необходимости (например, с использованием GeoJSON)? Раньше я использовал GeoServer, OpenLayer и другие инструменты, включая автономные настольные приложения, такие как ESRI и QMAP. Для ваших целей вы можете попробовать геосервер, сохранить свои векторные данные в геоде или файле, а затем связать фоновую карту с вектором по запросу на основе выбранной вами точки.   -  person Norcino    schedule 02.05.2019
comment
Другой вариант - получить выбранные вами координаты, отправить запрос ajax в базу геоданных, выполнить пространственный запрос и вернуть экзагональ, пересекающий вашу точку (или область), и, используя буфер, вы даже можете, например, добавить 100-метровый диапазон и получить все эксагоны в этой области. Для наилучшей точности система координат должна быть одинаковой для фоновой карты, обычно WGS84 (EPSG: 4326), и предварительно созданной сетки. Это связано с тем, что объединение двух слоев с двумя разными системами координат всегда приводит к погрешности, и, учитывая ваш размер 5 м, несоответствие будет легко заметить.   -  person Norcino    schedule 02.05.2019
comment
@Norcino AFAIK и Mapbox (рисование карты), и Turf (рисование гексов) используют WGS84. Гексы являются векторами и будут отображаться только в пределах видимой области карты. Их можно загружать асинхронно. Я обязательно проверю GeoServer, хотя очень надеялся, что этого можно будет добиться, вычислив координаты. Вы бы порекомендовали какие-либо ресурсы для чтения для настройки геосервера, как вы описали?   -  person Maciej Gurban    schedule 02.05.2019
comment
Документация GeoServer очень хороша (docs.geoserver .org / latest / en / user / gettingstarted /), я собирался указать вам на OpenGeo Suite, но он был переименован и, возможно, изменен, жаль, что все ссылки не работают, проверьте это: github.com/boundlessgeo/suite и это opengeo-suite.software.informer.com/download. Используйте установщик в виртуальной машине или в песочнице, я не знаю этот сайт.   -  person Norcino    schedule 02.05.2019
comment
Если вы решили создать векторный слой, взгляните на qgis.org/en/site. , Quantum GIS - невероятное программное обеспечение, и сообщество, стоящее за ним, очень активное.   -  person Norcino    schedule 02.05.2019
comment
Спасибо! Вы хотите отправить ответ, чтобы я мог его принять? В противном случае награда закончится через 15 минут и пропадет даром.   -  person Maciej Gurban    schedule 02.05.2019


Ответы (1)


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

Границы для WGS84: -180.0000, -90.0000, 180.0000, 90.0000 (я знаю, что это очевидно) источник: https://spatialreference.org/ref/epsg/wgs-84/ Это означает, что вам нужно начать оттуда, сделать оценку количества шестиугольников, которые вам нужны / вы хотите создать. Согласно https://planetcalc.com/7721/, радиус очага в метрах составляет 6378137. Предполагая, что вы Если вы хотите, чтобы шестиугольник состоял из 6 равносторонних треугольников, это означает, что для того, чтобы получить шестиугольник со стороной около 50 метров, он должен иметь ширину 100 метров (при условии, что плоские стороны ориентированы горизонтально).

Теперь мы можем сказать, что нам нужно около 63781 шестиугольника на экваторе, давайте упростим до 63800, 360/63800 = 0,00564 ... поэтому я предлагаю начать со смещения точек на экваторе 0,0055 градуса.

Следует подчеркнуть, что WGS84 - геоид, а не сферический (как наша планета), поэтому окончательное представление можно немного растянуть.

ОБНОВЛЕНИЕ: для автоматического создания сетки, похоже, вы также можете использовать Quantum GIS благодаря Grass

https://github.com/rldhont/Quantum-GIS/blob/master/python/plugins/processing/algs/grass7/description/v.mkgrid.txt https://grass.osgeo.org/grass76/manuals/v.mkgrid.html

person Norcino    schedule 02.05.2019