Створення полігонів Тіссена (Вороного), використовуючи лінії (а не точки) як вхідні функції?


24

У мене є набір особливостей лінії всередині певної полігональної межі. Для кожного рядка я б хотів генерувати багатокутник, всередині якого кожна можлива точка ближче до заданої лінії, ніж до будь-якої іншої лінії в шарі. Раніше я це робив для функцій введення точок за допомогою триангуляції Делоне, але якщо є подібний процес для цього з функціями лінії, я не зміг його знайти.

ETA: Рішення Geogeek мені трапилося, але на більш прямих ділянках, де вхідні лінії мають меншу кількість вершин, отримані багатокутники занадто близькі (навіть перекриваються) лінії, які вони не повинні. Тут червоні лінії є моїми входами, ви можете бачити вершини та полігони Тіссена, згенеровані з них.

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

Можливо, швидким і (дуже) брудним рішенням може стати перетворення кожного рядка в рясний набір рівномірно розташованих точок (а не лише вершин лінії), генерування полігонів Тіссена з них, а потім їх розчинення на основі вихідного ідентифікатора рядка.


4
Діаграми Вороного, які включають відрізки рядків разом з точками, не складаються з "багатокутників"; скоріше, їх клітини мають межі, які можуть включати частини парабол. З цієї причини одним із найефективніших і точніших способів створення тесселяцій Вороного є використання растрового зображення. ESRI називає цю процедуру виділенням Евкліда .
whuber

Відповіді:


11

Щоб проілюструвати рішення щодо обробки растру / зображення, я почав із розміщеного зображення. Це значно нижчої якості, ніж вихідні дані, завдяки суперпозиції синіх точок, сірих ліній, кольорових областей та тексту; і потовщення початкових червоних ліній. Таким чином, це представляє виклик: проте, ми все ще можемо отримати клітини Вороного з високою точністю.

Я витягнув видимі частини червоної лінійної функції, віднімаючи зелений від червоного каналу, а потім розширюючи та розмиваючи найяскравіші частини на три пікселі. Це було використано як основу для обчислення відстані Евкліда:

i = Import["http://i.stack.imgur.com/y8xlS.png"];
{r, g, b} = ColorSeparate[i];
string = With[{n = 3}, Erosion[Dilation[Binarize[ImageSubtract[r, g]], n], n]];
ReliefPlot[Reverse@ImageData@DistanceTransform[ColorNegate[string]]]

Сюжет допомоги

(Весь код, показаний тут, є Mathematica 8.)

Виявлення очевидних "хребтів" - які повинні включати всі точки, що розділяють дві сусідні комірки Вороного, - і повторне їх поєднання з лінійним шаром забезпечує більшу частину того, що нам потрібно продовжити:

ridges = Binarize[ColorNegate[
   LaplacianGaussianFilter[DistanceTransform[ColorNegate[string]], 2] // ImageAdjust], .65];
ColorCombine[{ridges, string}]

Комбіновані зображення

Червона смуга являє собою те, що я міг би врятувати від лінії, а синя смуга показує пасма в перетворенні відстані. (Ще є багато сміття через перерви в початковій лінії.) Ці хребти потрібно очистити і закрити за допомогою подальшого розширення - два пікселі будуть робити - і тоді ми можемо визначити пов'язані області, визначені оригінальні лінії та гребені між ними (деякі з яких потрібно явно рекомбінувати):

Dilation[MorphologicalComponents[
  ColorNegate[ImageAdd[ridges, Dilation[string, 2]]]] /. {2 -> 5, 8 -> 0, 4 -> 3} // Colorize, 2]

Насправді це досягнуто, це визначити п'ять орієнтованих лінійних ознак. Ми можемо побачити три окремих лінійних ознаки, що випливають з точки злиття. У кожного є дві сторони. Я вважав праву частину двох кращих правих ознак як однакові, але в іншому випадку розрізняв усе інше, надаючи п'ять рис. Кольорові області показують діаграму Вороного з цих п'яти особливостей.

Результат

Команда Евклідового виділення на основі шару, який розрізняє три лінійні ознаки (яких у мене не було в наявності для цієї ілюстрації) не розрізнив різні сторони кожної лінійної ознаки, і тому вона поєднала б зелену та помаранчеву області, що облягають крайню ліву лінію ; вона розділила б крайню праву частину сліз на дві частини; і це поєднало б ці розбиті шматки з відповідними рисами бежевого та пурпурового кольору з інших сторін.

Очевидно, що цей растровий підхід має можливість побудувати Вороного тесселяції довільних ознак - точок, лінійних відрізків і навіть багатокутників, незалежно від їх форм - і він може виділити сторони лінійних ознак.


1
Подібне рішення проілюстровано на сайті mateica.stackexchange.com/questions/20696/… .
whuber

5

Я думаю, що ти можеш:

  • Перетворити вершини ліній у точки (line_points).
  • Складіть вороної багатокутники, використовуючи точки (лінії_точки).
  • Розведіть отримані багатокутники за допомогою атрибута id, який було збережено з рівня рядка, або шляхом просторового з'єднання з лінійним шаром.

Я сподіваюся, що я дійсно зрозумів ваше запитання, якщо ні, не можете ви надати креслення, щоб пояснити свої потреби більше.


2
Я думаю, ти це зрозумів, і мені це було рішення, але ти стикаєшся з проблемами, де рядки мають менше вершин. Я оновлю своє запитання скріншотом.
Dan C

3
Це спрацювало б добре, якби ви зробили точки щільніше по лінії. Хоча підхід, що ґрунтується на растрах (як згадує Уубер у коментарях до питання), я б підозрював, що це буде набагато ефективніше, ніж це.
Andy W
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.