Як можна додати і відняти опуклі багатокутники?


12

У мене два 2D опуклі багатокутники, які перекриваються один з одним . Я шукаю алгоритм віднімання та додавання їх. Результатом повинен бути один увігнутий багатокутник або (ще краще) набір найбільших опуклих, що утворюють увігнутий результат (наприклад, трикутники).

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

( Зліва: Початкові багатокутники, що перекриваються. Середній: Отриманий увігнутий багатокутник після додавання. Праворуч: Набір опуклих багатокутників, що утворюють увігнутий результат. Тут краще було б отримати опуклі багатокутники, більші за трикутник, з причин продуктивності. два полігони, що перекриваються, призвели б до тієї ж картини, що і зліва, але область, що перекривається, не буде частиною багатокутника, що перетворюється.)

Як я можу це зробити?


Ми говоримо про 2D тут? тому що в 3D-об'єднанні багатокутників насправді немає великого сенсу.
concept3d

Так, грі, я кажу про 2D! Хоча я не бачу, чому це не має меншого сенсу в 3D, ніж у 2D.
Себастьян Барт

2
додавання двох багатокутників у 3D, якщо вони плоскі, це не має великого сенсу, якщо вони не знаходяться на одній площині, якщо вони мають об'єм (тверді тіла), то це вже інша історія.
concept3d

Гаразд, я це зрозумів. Я думав не про графіку, а про об’єкти зіткнення. Дякую за роз’яснення.
Себастьян Барт

Крім того, знайдіть усі точки, які вони перетинаються, і додайте вершини до набору. Набір важливий для запобігання перекриття. Потім просто додайте всі інші вершини з двох інших фігур у безліч. Цей набір містить усі вершини добавної форми.
Vaughan Hilts

Відповіді:


9

TL; DR Вам потрібно реалізувати булові операції за допомогою дерев BSP.

Ну, мабуть, тут йдеться про конструктивну геометрію суцільного тіла . Я реалізував CSG на комерційному рівні, тому я знаю щось про нього.

Класичний документ про CSG називається об'єднанням поліедральних наборів BSP Trees Yields , якщо чесно, тут пояснюється занадто багато, але коротко кажучи, алгоритм стосується багатокутників, які лежать на одній площині, як бінарний розділ простору, в основному будуючи дерево BSP з кожної багатокутної сітки. Другий крок - об'єднання цих дерев BSP; ви просто берете одне дерево і вставляєте його в інше. Потім алгоритм пояснює, як поводитися з кожним вузлом аркуша для поділу та підстрахування вузлів, вузли, які не потрібні в остаточній формі, будуть видалені, а іншим буде надано відповідний батьківський елемент.

Але зачекайте! Цей документ в основному говорить про полігональні сітки та тривимірні площини, НЕ?

Алгоритм можна узагальнити в будь-який вимір, тому у вашому двовимірному випадку легко використовувати сегменти рядків замість площини як бінарні розділи. Таким чином, кожен багатокутник буде перетворений у дерево BSP, ніж два будуть об’єднані. Нарешті ви перетинаєте отримане дерево, щоб генерувати остаточний багатокутник,

Зауважте, що цей алгоритм і CSG взагалі не стосується візуалізації та сітчастої грані безпосередньо та не є насправді готовою, тому вам потрібно витягнути обличчя кінцевих дерев BSP. Я також вважаю, що відстеження променів є більш простим підходом для відображення результату CSG. Вам потрібні лише промені, щоб обрізати дерево, а не витягувати та розбивати обличчя (пам'ятайте, що ми маємо справу лише з двійковими розділами).

Щодо чисельної стійкості. Добре зазначити, що існує два типи геометричних обчислень,

  • Ті, що базуються на побудові, ви будуєте форму на основі результату попередньої операції. Наприклад, y = sqrt(x)а потім використовувати yв новій операції. Це називається будівництвом; проблема полягає в тому, що числові помилки накопичуються швидко.
  • Крім того, є операції, які використовують предикати замість цього, по суті, замість того, щоб використовувати конструкцію, ви просто запитуєте, чи умова є істинним / хибним, і ви використовуєте те саме значення в різних операціях. Класичні тести включають incircle та орієнтаційний тест; це також підозрює чисельні помилки, особливо якщо ви використовуєте одинарну або подвійну точність, але зазвичай дають набагато кращі результати. існують інші рішення, що залежать від швидкості та точності. Ось один із останніх робіт, які уникають побудови, використовуючи геометрию на площині, щоб дати точні результати. Я також цитую з статті:

Концепцію представлення багатокутних сіток на площині вперше описали Сугіхара та Ірі [SI89]. Цей вид подання надає одну важливу перевагу, коли мова йде про завдання, що передбачають зміну топології твердих тіл, представлених сітками, як-от оцінка булевих виразів: жодна нова інформація про первинну геометрію не повинна бути побудована для отримання отриманого багатогранника

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

І нарешті, я хотів би додати, якщо ви хочете розпочати реалізацію CSG BSP, я б рекомендував починати з Faqs BSP .


Класно, але протиінтуїтивно, враховуючи, що BSP опуклого багатокутника або багатогранника - це список. Чудовий папір.
3Dave

@DavidLively так, але можна зробити його збалансованим деревом, вибравши кореневу площину, яка не належить до граней. Насправді це частина виклику, про який вони не говорять
concept3d

Ах, це має сенс. Сорт гібридного BSP, значить.
3Dave

@DavidLively також BSP не дуже легко рендерувати, хоча питання ОП - це простий випадок, у складнішому випадку з геометрією мільйонів багатокутників, коли ви закінчили будівництво дерева, яке ви далеко не закінчили.
concept3d

@ concept3d Я сподіваюся, що це не буде занадто дратувати, оскільки це відповідь на 5 років, але я дуже не розумію дві речі: Коли я намагаюся визначити, чи лежить точка зліва чи справа від площини / лінії, чи не було б простіше просто обертати всю річ, щоб площина / лінія відповідала тривіальній площині / прямій, а потім просто розглянути координати обертової точки? Як щодо використання алгоритму Сазерленд - Ходжман замість дерев BSP? Звучить досить схоже на такий підхід.
Джон П

1

Ідучи своїм прикладом:

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

Після того, як ви накопичили всі вершини для нового многокутника, виконайте на ньому алгоритм тріангуляції. Метод відсікання вуха легко здійснити, але там є швидші варіанти.

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

Ітерація над кожним краєм для перевірки перетину була б алгоритмом O (n ^ 2). Ви можете пришвидшити це, спочатку знайти вершини, що знаходяться всередині іншого багатокутника, оскільки краї, пов'язані з цими вершинами, будуть перетинаються.


0

Якщо ви хочете увігнутий багатокутник, просто виберіть найближчий край між двома вхідними багатокутниками та додайте два нові краї:

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

Опуклий стає дещо складнішим:

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

Один підхід є ітераційним, оскільки він додає вершини від другого многокутника до першого, по одному, перетворюючи перший багатокутник у контейнер, який охоплює все.

В основному:

  • Ітерація через вершини другого багатокутника.
  • Для кожної вершини V пройдіть через ребра першого многокутника:
  • Знайдіть "діапазон" ребер, які всі стикаються з вершиною
  • візьміть зовнішню пару вершин, які визначають цей діапазон, і видаліть усі ребра в діапазоні, який їх з'єднує
  • Намалюйте два нові відрізки від цих зовнішніх вершин до нової вершини (з другого многокутника), переконавшись, що нові ребра стикаються у правильному напрямку.
  • Перехід до наступної вершини з другого многокутника

Ось схема, що ілюструє процес для першої вершини:

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

Більш швидкий метод - знайти список ребер на кожному багатокутнику, які не стикаються з іншим багатокутником, видалити все інше та з'єднати кінцеві точки решти смуг рядків між собою.

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


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

Алгоритм неявно ігнорує вершини, які знаходяться «всередині» цільового багатокутника, що також компенсує питання, коли ребро з другого многокутника перетинає перше.
3Dave

Це майже дорівнює фазі злиття (точка 4. алгоритму злиття корпусу . У моєму випадку це неправильне рішення, щоб укласти більше площі після комбінування полігонів. Правильним рішенням було б зберегти обидва полігони такими, якими вони є, оскільки вони є ' t Перекриваючись, не торкаючись
Себастьян Барт

@luftgewehrindianer Ага - так, це має велике значення. Можливо, я неправильно зрозумів питання. Ви хочете скласти багатокутники разом, не переживаючи, чи результат опуклий чи увігнутий? Або генерувати опуклий набір на основі перетину? (Ігнорування віднімання на даний момент.)
3Dave

@DavidLively Уявіть два опуклі багатокутники одного кольору та без стовбура. Коли вони перетинаються, це виглядає як один новий опуклий або увігнутий багатокутник. Він намагається знайти триангуляцію комбінованої форми. Не додайте площі між обома багатокутниками.
danijar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.