Как можно определить заливы и проливы на процедурно сгенерированной карте?

40

У меня есть процедурно сгенерированная карта с использованием ячеек Вороного, с определенным уровнем моря и правдоподобной картой высот.

ток

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

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

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

Для определения функций я могу просмотреть любую функцию по типу:

for each (var feature:Object in geography.getFeaturesByType(Geography.LAND))
  // loop through lands
  for each (var cell:Cell in feature.cells)
  // loop through cells
    for each (var neighbor:Cell in cell.neighbors)
    // loop through a cell's neighbors
      trace(neighbor.hasFeatureType(Geography.LAND));
Олин Киркланд
источник
8
Я рекомендую классификатор Байса.
накопление
1
@ Накопление Это каламбур на "заливе" или это серьезное предложение? Если последнее, вы должны написать правильный ответ по этому поводу.
Филипп
Я на 99% уверен, что он шутит.
Олин Киркланд

Ответы:

29

Способ, которым Dragons Abound идентифицирует заливы, состоит в том, чтобы пройти вдоль береговой линии и найти две точки на береговой линии, где прямое расстояние между точками меньше, чем расстояние вдоль береговой линии между точками. Это извилистость береговой линии между двумя точками. Выбрав предел извилистости и пределы для прямой линии между пятнами, вы можете определить узкие глубокие заливы, широкие неглубокие заливы и т. Д.

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

Пример бухты

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

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

Обратите внимание, что это также обнаружит точки. Чтобы найти только бухты, вам нужно проверить, что «внутри» бухты содержится вода, а не земля. Быстрый и простой способ сделать это - проверить среднюю точку линии между двумя точками, чтобы убедиться, что это вода. (Это можно одурачить, но, как правило, достаточно.)

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

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

Доктор Пейн
источник
3
Я должен был знать, что у Dragons Abound будут ответы, которые мне нужны.
Олин Киркланд
48

Вот примерная идея, использующая преобразования обработки изображений для выделения интересующих функций:

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

    Маска океана

  2. Примените локальное сглаживание к краю этой маски, сохраняя неизменность связности / топологии, но сглаживая небольшие шумные элементы береговой линии, которые могут отвлекать. Это позволяет нам сосредоточиться на больших бухтах над крошечными входами. Вы можете использовать ширину ядра фильтра / количество итераций, чтобы точно контролировать масштаб сохраняемых вами функций.

    Здесь я применил медианный фильтр несколько раз. Клеточные автоматы - еще один популярный способ размывать плавные формы из-за шумного ввода.

    Сглаженная береговая линия

  3. Превратите маску в поле расстояния, где каждая ячейка хранит свое расстояние от сглаженной береговой линии.

    Поле расстояния

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

Хребты выделены

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

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

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

Д.М.Григорий
источник
9
Это выглядит действительно круто, и, вероятно, его можно значительно ускорить, напрямую используя структуру ячеек для применения различных шагов, а не графического представления!
Квентин,
7
Второй подход (присвоение каждой отдельной суши идентификатора и различение на основе того, является ли она одинаковой по суше с обеих сторон водоема) кажется наиболее простым делом ..
Монти Хардер
В любом случае, «идентификатор массива земли» - хорошая идея, так как он также понадобится при маркировке карты для создания названий островов.
MSalters
6

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

залив

  • Любая океаническая ячейка, которая соединяется только с одной другой океанической ячейкой
  • ИЛИ: Любая океаническая ячейка, которая соединяется с большим количеством суши, чем океанические, со всеми океанскими ячейками рядом
  • ИЛИ: То же, что и выше, но с критерием, основанным на длине границы (например, в два раза больше земли, чем на границе воды)

Пролив

  • Любая океаническая ячейка, которая соединяется ровно с двумя океанскими ячейками, которые не находятся рядом друг с другом.
  • ИЛИ: Любая океаническая ячейка, которая подключается к двум наземным ячейкам, которые не принадлежат к одной и той же суше (вам необходимо выяснить, какие наземные ячейки подключены первыми, и назначить идентификаторы для каждой суши)
  • ИЛИ: маршируйте вокруг границы и считайте переходы земля / вода и вода / земля. Вам нужно как минимум два из каждого.
  • В зависимости от вашего метода и того, что вы хотите сделать с категориями, вы можете устранить проливы, которые ведут только к заливу, или вместо этого пометить их как залив.
Autolykos
источник
2
Когда пролив ведет к заливу, эти два вместе могут быть помечены как фьорд.
Филипп
1
Если ячейки малы относительно размера бухты / пролива, вам, возможно, придется распространять это, чтобы посмотреть на ячейки за соседними соседями.
DMGregory
Да, масштабирование - это небольшая проблема, и она повлияет на то, как вы определяете вещи и объявляете «ячейки». Рассмотрите карту Канады и сравните следующее: Гудзонов залив, залив Джеймс, залив Святого Лаврентия и залив Фанди. Как вы надежно применяете эти правила, чтобы получить нужные связанные имена? - Есть ли «прямой» между Ньюфаундлендом и Новой Шотландией?
TheLuckless