it-swarm.com.ru

Существует ли эффективный алгоритм для создания 2D вогнутой оболочки?

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

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

59
Fabio Ceconello

This статья обсуждает Эффективную генерацию простых многоугольников для характеристики формы набора точек на плоскости и предоставляет алгоритм. Также есть Java-апплет, использующий тот же алгоритм здесь .

2
Amirali

Один из бывших студентов нашей лаборатории использовал некоторые подходящие методы для своей докторской диссертации. Я полагаю, что один из них называется «альфа-формы» и упоминается в следующей статье:

http://www.cis.rit.edu/people/faculty/kerekes/pdfs/AIPR_2007_Gurram.pdf

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

10
nsanders

Ответ может все еще быть интересным для кого-то еще: можно применить вариацию алгоритма марширующего квадрата, применить (1) в пределах вогнутой оболочки и (2) затем на (например, 3) различных масштабах что моё зависит от средней плотности очков. Шкалы должны быть кратными друг другу, поэтому вы строите сетку, которую вы можете использовать для эффективной выборки. Это позволяет быстро найти пустые выборки = квадраты, выборки, которые полностью находятся в «кластере/облаке» точек, и те, которые находятся между ними. Последняя категория затем может быть легко использована для определения ломаной линии, представляющей часть вогнутой оболочки.

В этом подходе все линейно, триангуляция не требуется, в ней не используются альфа-формы, и она отличается от коммерческого/запатентованного предложения, описанного здесь ( http://www.concavehull.com/ )

2
monnoo

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

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

2
Vinko Vrsalovic

Интерактивный SDK Bing Maps V8 имеет вогнутую опцию корпуса в рамках расширенных операций с фигурами.

https://www.bing.com/mapspreview/sdkrelease/mapcontrol/isdk/advancedshapeoperations?toWww=1&redig=D53FACBB1A00423195C53D841EA0D14E#JS

В ArcGIS 10.5.1 расширение 3D Analyst имеет инструмент Minimum Bounding Volume с геометрическими типами вогнутой оболочки, сферы, огибающей или выпуклой оболочки. Может использоваться на любом уровне лицензии.

Здесь есть вогнутый алгоритм корпуса: https://github.com/mapbox/concaveman

1
Jaybird64

Простое решение - пройтись по краю многоугольника. При заданном текущем ребре на границе, соединяющей точки P0 и P1, следующей точкой на границе P2 будет точка с наименьшим возможным A, где

H01 = bearing from P0 to P1
H12 = bearing from P1 to P2
A = fmod( H12-H01+360, 360 )
|P2-P1| <= MaxEdgeLength

Затем вы установите

P0 <- P1
P1 <- P2

и повторяйте, пока не вернетесь туда, откуда начали.

Это по-прежнему O (N ^ 2), так что вам нужно немного отсортировать список точек. Вы можете ограничить набор точек, которые необходимо учитывать на каждой итерации, если вы сортируете точки, скажем, по их отношению к центроиду города.

1
Mike F

Вы можете сделать это в QGIS с помощью этого плагина; https://github.com/detlevn/QGIS-ConcaveHull-Plugin

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

1
Cameron

Хороший вопрос! Я не пробовал это вообще, но мой первый выстрел был бы таким итеративным методом:

  1. Создайте набор N («не содержится») и добавьте все точки в вашем наборе к N.
  2. Выберите 3 точки из N случайно, чтобы сформировать начальный многоугольник P. Удалите их из N.
  3. Используйте некоторый алгоритм точка-полигон и посмотрите на точки в N. Для каждой точки в N, если она теперь содержится в P, удалите ее из N. Как только вы найдете точку в N, которая все еще не содержится в P, перейдите к шагу 4. Если N становится пустым, все готово.
  4. Назовите точку, которую вы нашли A. Найдите линию в P, ближайшую к A, и добавьте A в середине.
  5. Вернитесь к шагу 3

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

Удачи!

1
Rob Dickerson

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

https://github.com/postgis/postgis/blob/380583da73227ca1a52da0e0b3413b92ae69af9d/postgis/postgis.sql.in#L5819

0
Evan Carroll

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

Основываясь на том, сколько деталей вы хотите, создайте массив фиксированных размеров верхних/нижних границ . Для каждой точки вычислите, в каком столбце E-W он находится, а затем обновите верхние/нижние границы для этого столбца. После обработки всех точек вы можете интерполировать верхние/нижние точки для тех столбцов, которые пропустили.

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

0
Martin Beckett