Пересечение треугольника треугольника k-way и триангуляция

Если у нас есть K множеств потенциально перекрывающихся треугольников, то какой вычислительно эффективный способ вычисления нового, непересекающегося множества треугольников?

Например, рассмотрим эту проблему:

Tesselation

Здесь мы имеем три треугольных множества A, B, C с некоторым взаимным перекрытием и хотим получить непересекающиеся множества A ', B', C ', AB, AC, BC, ABC, где, например, треугольники в AC будут содержать поверхности, где есть исключительное перекрытие между A и C; и A 'будут содержать поверхности A, которые не перекрывают никакого другого набора.

Ответ 1

I (также) предлагает двухэтапный подход.

1. Найдите точки пересечения всех сторон треугольника.

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

2. Триангуляция с Ограниченным Делоне.

Я думаю, что триангуляция Polygon, предложенная @Claudiu, не может решить вашу проблему, поскольку она не может гарантировать включение всех исходных ребер. Поэтому я предлагаю вам взглянуть на Ограниченные триангуляции Delaunay. Они позволяют указывать ребра, которые должны быть включены в вашу триангуляцию, даже если они не будут включены в неконденсированную триангуляцию Delaunay или polygon. Кроме того, существуют реализации, которые позволяют вам указать невыпуклую границу триангуляции, вне которой не образуются треугольники. Это также, по-видимому, является требованием в вашем случае.

Реализация Constrained Delaunay является нетривиальной. Тем не менее, существует несколько устаревшая, но очень хорошая реализация C, доступная от исследователя CMU (включая инструмент командной строки). См. здесь для теории этого конкретного алгоритма. Этот алгоритм также поддерживает спецификацию границы. Обратите внимание, что связанный алгоритм может делать больше, чем просто Constrained Delaunay (а именно, создание качественной сетки), но его можно настроить, чтобы не добавлять новые точки, что равно ограничению Delaunay.

Изменить. См. комментарии к другой реализации.

Ответ 2

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

Треугольники просты, потому что расщепление треугольника в данной плоскости всегда приводит к 1 или 2 новым (всего 2 или 3). Если ваш набор данных довольно велик, вы можете ввести четырехъядерную или другую форму пространственной организации, чтобы быстрее находить пересекающиеся треугольники по мере добавления новых.

enter image description here

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

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

В любом случае, удачи!

Ответ 3

Ваш пример - частный случай того, что вычислительные геометры называют "договоренностью". CGAL Library имеет обширные и эффективные процедуры обработки заказов. Если вы проверите эту часть документации, вы увидите, что можете объявить пустую компоновку, а затем вставить треугольники, чтобы разделить плоскость 2d на непересекающуюся лица. Как говорили другие, вам нужно будет триангулировать лица, которые еще не треугольники. К счастью, CGAL также предоставляет процедуры для этого. Этот пример ограниченной триангуляции Delaunay является хорошим местом для начала.

CGAL пытается использовать наиболее эффективные алгоритмы, доступные для реализации. В этом случае, похоже, вы можете достичь O ((n + k) log n) для организации с n ребрами (в 3 раза больше треугольников в вашем случае) с k пересечением. Алгоритм использует общий метод, называемый "линия развертки". Вертикальная линия перемещается слева направо с помощью "событий", вычисленных и обработанных по пути. События - это граничные точки и пересечения. По мере обработки каждого события обновляется ячейка компоновки.

Алгоритмы Delaunay, как правило, O (n log n) для n вершин. Существует несколько распространенных алгоритмов, которые можно легко найти или найти в ссылках CGAL. ​​

Даже если вы не можете использовать CGAL в своей работе (например, по причинам лицензирования), документация полна источников по базовым алгоритмам: соглашения и ограниченные алгоритмы Delaunay.

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

Ответ 4

Я могу представить два подхода.

Более общий подход рассматривает ваш ввод как просто набор строк и разбивает проблему на две части:

  • Обнаружение многоугольника. Возьмите набор строк, которые сделают ваши начальные треугольники, и получите набор неперекрывающихся полигонов. В этой статье предлагается подход O ((N + M) ^ 4), где N - число отрезков линии, а M - число пересечений, который, похоже, немного медленный, к сожалению...
  • Триангуляция многоугольника. Возьмите каждый многоугольник с шага 1 и триангулируйте его. Это принимает O (n log * n), который практически равен O (n).

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

  • Нет точек треугольника в любом другом треугольнике.
    • Нет пересечений
    • Еврейская звезда
    • Два перпендикулярных пика
  • Одна точка одного треугольника содержится в другом
  • Каждый треугольник содержит одну точку другого
  • Две точки одного треугольника находятся в другом
  • Три точки одного находятся в другом - один полностью содержит

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

Ответ 5

Чтобы разбить бит на комментарий от Теда Хоппа, это должно быть возможно, сначала вычислив плоское подразделение, в котором каждая ограниченная грань вывода связана с одним из множеств A ', B', C ', AB, AC, BC, ABC или "none". Вторая фаза затем состоит в триангуляции (возможно, не выпуклых) граней в каждом множестве.

Шаг 1 может быть выполнен в O ((N + K) log N) времени с использованием вариации алгоритма развертки Bentley-Ottmann в котором текущий набор поддерживается как часть состояния алгоритма. Это можно определить из сегментов линии, которые уже были пересечены, и их направления.

После этого непересекающиеся многоугольники для каждого набора затем могут быть разбиты на монотонные части в O (N log N), которые, в свою очередь, могут быть триангулированы в O (N) времени.

Если вы еще этого не сделали, возьмите копию "Вычислительная геометрия: алгоритмы и приложения" от Berg и др.