Пересечение многоугольников (PSLG overlaying) — различия между версиями
Darkraven (обсуждение | вклад) |
Darkraven (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
== Постановка задачи == | == Постановка задачи == | ||
Определим пересечение двух [[ППЛГ и РСДС (PSLG и DCEL): определение, построение РСДС множества прямых|ППЛГ]] <tex>S_1</tex> и <tex>S_2</tex> как ППЛГ <tex>O(S_1, S_2)</tex>, такой, что в нем существует грань <tex>f</tex> тогда и только тогда, когда существуют грани <tex>f_1</tex> в <tex>S_1</tex> и <tex>f_2</tex> в <tex>S_2</tex> такие, что <tex>f</tex> является наибольшим связным подмножеством <tex>f_1 \cap f_2</tex>. Иначе говоря, пересечение двух ППЛГ — это разбиение плоскости с помощью ребер из <tex>S_1</tex> и <tex>S_2</tex>. Необходимо построить [[ППЛГ и РСДС (PSLG и DCEL): определение, построение РСДС множества прямых|РСДС]] для <tex>O(S_1, S_2)</tex>, имея РСДС для <tex>S_1</tex> и <tex>S_2</tex>. Кроме того, для каждой грани из <tex>O(S_1, S_2)</tex> будем хранить ссылки на грани из <tex>S_1</tex> и <tex>S_2</tex>, содержащие ее. | Определим пересечение двух [[ППЛГ и РСДС (PSLG и DCEL): определение, построение РСДС множества прямых|ППЛГ]] <tex>S_1</tex> и <tex>S_2</tex> как ППЛГ <tex>O(S_1, S_2)</tex>, такой, что в нем существует грань <tex>f</tex> тогда и только тогда, когда существуют грани <tex>f_1</tex> в <tex>S_1</tex> и <tex>f_2</tex> в <tex>S_2</tex> такие, что <tex>f</tex> является наибольшим связным подмножеством <tex>f_1 \cap f_2</tex>. Иначе говоря, пересечение двух ППЛГ — это разбиение плоскости с помощью ребер из <tex>S_1</tex> и <tex>S_2</tex>. Необходимо построить [[ППЛГ и РСДС (PSLG и DCEL): определение, построение РСДС множества прямых|РСДС]] для <tex>O(S_1, S_2)</tex>, имея РСДС для <tex>S_1</tex> и <tex>S_2</tex>. Кроме того, для каждой грани из <tex>O(S_1, S_2)</tex> будем хранить ссылки на грани из <tex>S_1</tex> и <tex>S_2</tex>, содержащие ее. | ||
+ | |||
+ | <картинка> | ||
+ | |||
+ | == Алгоритм == | ||
+ | Для начала, скопируем ППЛГ <tex>S_1</tex> и <tex>S_2</tex> в новый РСДС. Далее необходимо преобразовать полученный РСДС, чтобы он соответствовал <tex>O(S_1, S_2)</tex>. Отдельно рассмотрим преобразования вершин, полуребер и граней. | ||
+ | |||
+ | === Вершины и полуребра === | ||
+ | Алгоритм базируется на [[Пересечение множества отрезков|заметающей прямой]], определяющей пересечения отрезков. Запускаем алгоритм на множестве отрезков, представляющих собой ребра из <tex>S_1</tex> и <tex>S_2</tex>. Напомним, что алгоритм поддерживает очередь событий <tex>Q</tex> и текущий статус <tex>T</tex> заметающей прямой. Также будем поддерживать ссылки между ребрами статуса и соответствующими полуребрами из РСДС. Поддерживаемый инвариант: над заметающей прямой корректный РСДС. | ||
+ | |||
+ | <картинка> | ||
+ | |||
+ | Обработка точки события происходит следующим образом: сначала обновляем <tex>Q</tex> и <tex>T</tex> (как в алгоритме пересечения отрезков). Если оба ребра события принадлежат одному ППЛГ, переходим к следующему событию. В противном случае, необходимо модифицировать РСДС. Возможны следующие варианты событий (см. рисунок ниже): | ||
+ | |||
+ | <картинка> | ||
+ | |||
+ | Рассмотрим один из случаев, остальные обрабатываются аналогично. Пусть ребро <tex>e</tex> из <tex>S_1</tex> пересекает вершину <tex>v</tex> из <tex>S_2</tex>. Ребро <tex>e</tex> заменяем двумя ребрами <tex>e'</tex> и <tex>e''</tex>. Два полуребра, соответствующих <tex>e</tex>, заменяются четырьмя полуребрами: два существующих полуребра будут исходить из концов <tex>e</tex>, а два новых полуребра — из <tex>v</tex> (см. рисунок). Устанавливаем ссылки на близнецов для ребер <tex>e'</tex> и <tex>e''</tex>. Обновим ссылки на следующие полуребра для <tex>h_1</tex> и <tex>h_4</tex>, пусть это будут <tex>h_5</tex> и <tex>h_6</tex>, соответственно. Не забудем установить полуребра <tex>h_1</tex> и <tex>h_4</tex> в качестве предыдущих полуребер у <tex>h_5</tex> и <tex>h_6</tex>. Теперь обновим ссылки на полуребра, инцидентные вершине <tex>v</tex>. Для этого сначала при помощи порядка обхода определим, между какими полуребрами <tex>S_2</tex> находится <tex>e</tex>. Рассмотрим полуребро <tex>h_3</tex>: свяжем его с первым полуребром, видимым из <tex>h_4</tex> при обходе по часовой стрелке и исходящем из <tex>v</tex>. Полуребро <tex>h_4</tex> должно быть связано с первым полуребром, идущим в <tex>v</tex>, при обходе против часовой стрелки. Аналогично обработаем <tex>e''</tex>. | ||
+ | |||
+ | |||
+ | <tex></tex> |
Версия 14:44, 17 мая 2015
Постановка задачи
Определим пересечение двух ППЛГ и как ППЛГ , такой, что в нем существует грань тогда и только тогда, когда существуют грани в и в такие, что является наибольшим связным подмножеством . Иначе говоря, пересечение двух ППЛГ — это разбиение плоскости с помощью ребер из и . Необходимо построить РСДС для , имея РСДС для и . Кроме того, для каждой грани из будем хранить ссылки на грани из и , содержащие ее.
<картинка>
Алгоритм
Для начала, скопируем ППЛГ
и в новый РСДС. Далее необходимо преобразовать полученный РСДС, чтобы он соответствовал . Отдельно рассмотрим преобразования вершин, полуребер и граней.Вершины и полуребра
Алгоритм базируется на заметающей прямой, определяющей пересечения отрезков. Запускаем алгоритм на множестве отрезков, представляющих собой ребра из и . Напомним, что алгоритм поддерживает очередь событий и текущий статус заметающей прямой. Также будем поддерживать ссылки между ребрами статуса и соответствующими полуребрами из РСДС. Поддерживаемый инвариант: над заметающей прямой корректный РСДС.
<картинка>
Обработка точки события происходит следующим образом: сначала обновляем
и (как в алгоритме пересечения отрезков). Если оба ребра события принадлежат одному ППЛГ, переходим к следующему событию. В противном случае, необходимо модифицировать РСДС. Возможны следующие варианты событий (см. рисунок ниже):<картинка>
Рассмотрим один из случаев, остальные обрабатываются аналогично. Пусть ребро
из пересекает вершину из . Ребро заменяем двумя ребрами и . Два полуребра, соответствующих , заменяются четырьмя полуребрами: два существующих полуребра будут исходить из концов , а два новых полуребра — из (см. рисунок). Устанавливаем ссылки на близнецов для ребер и . Обновим ссылки на следующие полуребра для и , пусть это будут и , соответственно. Не забудем установить полуребра и в качестве предыдущих полуребер у и . Теперь обновим ссылки на полуребра, инцидентные вершине . Для этого сначала при помощи порядка обхода определим, между какими полуребрами находится . Рассмотрим полуребро : свяжем его с первым полуребром, видимым из при обходе по часовой стрелке и исходящем из . Полуребро должно быть связано с первым полуребром, идущим в , при обходе против часовой стрелки. Аналогично обработаем .