Обзор алгоритмов построения оверлеев многоугольников

О.В. Ченцов, А.В. Скворцов ОБЗОР АЛГОРИТМОВ ПОСТРОЕНИЯ ОВЕРЛЕЕВ МНОГОУГОЛЬНИКОВ

Проводится обзор алгоритмов пересечения, объединения и разности многоугольников и сравнение их по ряду таких параметров, как вычислительная устойчивость, трудоемкость, скорость работы, простота программной реализации. В работе описаны как широко известные, так и менее распространенные алгоритмы, в том числе и не опубликованные никем ранее, но доступные через интернет.

Во многих приложениях вычислительной геометрии и компьютерной графики, в системах автоматизированного проектирования (САПР), в геоинформационных системах (ГИС), в различных векторных графических редакторах основные объекты описываются с помощью плоских многоугольников.

Одной из основных операций над многоугольниками является операция построения оверлеев (объединения, пересечения или разности).

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

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

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

ПОСТАНОВКА ЗАДАЧИ

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

Определение. Ребром называется направленный отрезок с началом в точке а и концом в точке Ь, не совпадающей с а, который обозначается как Е(а,Ь). При этом будем говорить, что для точки Ь ребро Е является входящим, а для точки а - выходящим.

Определение. Контуром называется множество ребер {Е0,Е1 ,...,Е„_1} такое, что п>2 и Уі є{0,...,п-1}:

Е-і = Е(уі-і,уіX Еі = Е(Уі,уі+і ). Точка уі , для которой ребра Еі-1 и Еі являются соответственно входящим и выходящим, будем называть і-й вершиной контура С, ребра Еі-1 и Еі - соседними или смежными. Порядок обхода ребер контура С = {Е0 ,Е1 ,...,ЕпЛ } с увеличением индекса і ^ і+1 будем называть прямым направлением обхода, а противоположный ему - обратным. Заметим, что одной точке плоскости может соответствовать несколько вершин контура, такие вершины будем называть кратными.

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

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

Рассмотрим границу йА некоторой области А. Если ориентация йА согласована с ориентацией А, мы приходим к соответствию между границей области и набором контуров на плоскости. Для того, чтобы оно было взаимно-однозначным, добавим к традиционному определению два ограничения. Итак, рассмотрим, контур С, содержащий п ребер.

Определение. Контур С называется ограничивающим контуром области А, если выполняются следующие условия:

1) С с йА ;

2) обход С в прямом направлении является положительным обходом, т.е. обходом, при котором область А остается слева;

3) V; е{0,...,п-1} : 3 е>0 :У х ее+ (иг):хеА ;

4) Vi е{0,...,п-1} :3 е> 0 : V х ее- (иг): х г А .

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

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

Определение. Многоугольник называется выпуклым, если определяемое им множество точек является выпуклым.

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

Определение. Многоугольник называется регулярным, если он не имеет пересекающихся или «висящих» ребер и совпадающих точек.

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

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

Указанные классы полигонов формируют следующую иерархию: выпуклые с простые с регулярные с вершинно-полные с ориентированные с общие.

Итак, рассмотрим два двумерных многоугольника A и В. Под выполнением некоторой булевой операции над многоугольниками A и В понимается выполнение операции над описываемыми ими областями и получение множества многоугольников, описывающего полученную область.

Определим следующий набор возможных операций:

1. Объединение (рис. 1,a):

AuB = {(x,y) : (x,y) e A или (x,y)eB}.

2. Пересечение (рис. 1,6):

A n B = {(x, y) : (x, y) e A и (x, y)e B} .

3. Разность (рис. 1,e):

A - B = clos {(x, y) : (x, y) e A и (x, y) g B}.

A

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

1. Обе вершины (Б и Р) ребра отсекаемого многоугольника внутри ребра отсекателя, вершина Р добавляется в выходной список (рис. 3, а).

2. Если вершина Б внутри ребра отсекателя, а вершина Р снаружи его, то в выходной список заносится точка пересечения і (рис. 3, б).

3. Если обе точки (Б и Р) ребра снаружи ребра от-секателя, тогда в выходной список не попадает ничего (рис. 3, в).

4. Если вершина Р внутри ребра отсекателя, а вершина Б снаружи его, то в выходной список заносится точка пересечения і и вершина Р (рис. 3, г).

Рис. 1. Набор операций над многоугольниками A и B

АЛГОРИТМ САЗЕРЛЕНДА - ХОДЖМАНА

Алгоритм Сазерленда - Ходжмана является одним из самых первых и простых алгоритмов отсечения многоугольников [8]. Он был базовым алгоритмом для процессора Кларка [9], который был предтечей алгоритмов, заложенных в классических программах первых компьютеров Silicon Graphics Inc. Этот алгоритм рассекает исходный общий многоугольник любым выпуклым многоугольником. Отсекающий многоугольник обычно называют отсекающим окном. Суть алгоритма заключается в том, что отсекаемый многоугольник последовательно отсекается каждой границей отсекающего окна (рис. 2).

Рис. 2. Отсечение многоугольника выпуклым отсекателем в алгоритме Сазерленда - Ходжмана

Рис. 3. Варианты пересечения ребра исходного многоугольника и ребра отсекателя в алгоритме Сазерленда - Ходжмана

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

а

б

a

в

г

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

АЛГОРИТМ О’РУРКА

Один из наиболее простых и элегантных алгоритмов пересечения выпуклых многоугольников был предложен О’Рурком [11]. Он базируется на более простом и грубом методе, описанном в [1].

Основная идея алгоритма О’ Рурка состоит в следующем. Допустим, даны два выпуклых многоугольника Р с Ь вершинами и Q с М вершинами. Предположим, что (р1,р2,...,рЬ) и (д1,д2,...,дМ) - это списки вершин Р и Q, упорядоченные при обходе их против часовой стрелки. Для каждого многоугольника объявляются текущие вершины р, и д,, кроме этого, текущие ребра оканчиваются вершинами р, и д. Идея заключается в том, чтобы не двигаться по той границе (Р или Q), текущее ребро которой еще может содержать необнаруженную точку пересечения. Существует четыре возможных варианта взаимного расположения вершин р1 и д^ и ребер рг-1 р и (осталь-

ные ситуации сводятся к указанным четырем путем замены ролей Р и Q). В одном из этих вариантов (рис. 4, а) мы продвинемся по Р, так как текущее ребро из Q может содержать необнаруженную

точку пересечения; по тем же причинам в случае (рис.

4, б) мы продвинемся по границе Q.

Если все пересечения на текущем ребре из Р уже обнаружены, в то время как текущее ребро из Q все еще может содержать необнаруженное пересечение, мы продвигаемся вдоль Р (рис. 4, в); кроме этого, здесь мы должны вычислить точку пересечения ребер

рг-1 р и . В последнем случае (рис. 4, г) выбор

произволен и можно выбрать, например, Q.

АЛГОРИТМ ВЕЙЛЕРА - АЗЕРТОНА

Алгоритм Вейлера - Азертона [4, 5] является гораздо более мощным алгоритмом отсечения многоугольников по сравнению с ранее перечисленными. Он пригоден для обработки областей с «дырами» (без самопересечений) и для любых регулярных отсекате-лей, однако, достигается это ценой заметно большей сложности и меньшей скорости работы.

Отсекаемый многоугольник называется объектом (8Р), а отсекающий многоугольник - отсекателем (СР). В процессе пересечения не создаются новые ребра, поэтому число выходных многоугольников минимизировано.

Алгоритм описывает 8Р и СР как циклический список вершин. Внешние границы многоугольников представляются упорядоченными по часовой стрелке, а внутренние границы и «дыры» упорядоченными против часовой стрелки. Отсюда, при перемещении по списку вершин, внутренняя область многоугольника должна всегда находиться справа. Границы 8Р или СР могут пересекаться, а могут не пересекаться. Если они пересекаются, пересечения возникают дважды. Одно из пересечений происходит, когда ребро 8Р входит внутрь СР, а второе, когда выходит. По существу, алгоритм начинается на «входящем» пересечении и следует по часовой стрелке до внешней границы 8Р до тех пор, пока не будет найдено пересечение с СР. На пересечении делается правый поворот и выполняется обход по часовой стрелке внешней области СР, пока не будет найдено пересечение с 8Р. Далее, снова на пересечении делается правый поворот и выполняется обход по 8Р. Процесс продолжается до тех пор, пока не будет достигнута стартовая точка. Внутренние границы 8Р обходятся против часовой стрелки.

Ниже описаны основные шаги алгоритма:

Шаг 1. Нахождение точек пересечения 8Р и СР -каждое пересечение добавляется в список вершин 8Р и СР. При этом касания не считаются пересечением, т.е. когда вершина или ребро отсекаемого многоугольника инцидентна или совпадает со стороной от-секателя (рис. 5 и 6). Каждая пересекающаяся вершина помечается и устанавливается двунаправленная связь между списками 8Р и СР.

Рис. 5. Случаи, не считающиеся пересечением, в алгоритме Вейлера-Азертона

а б в г

Рис. 4. Варианты взаимного расположения текущих вершин и ребер в алгоритме О’Рурка

В целом, можно сказать, что алгоритм О’Рурка эффективен и прост в реализации, кроме этого, он может быть легко модифицирован для построения объединения и разности многоугольников.

Рис. 6. Частный случай пересечения многоугольников в алгоритме Вейлера - Азертона

Шаг 2. Обработка непересекающихся границ многоугольников - вводятся два списка: один для границ, находящихся внутри СР, второй - для находящихся снаружи. Границы СР, находящиеся снаружи 8Р, игнорируются. Границы СР внутри 8Р формируют «дыры» 8Р. Поэтому копия границ СР идет в оба списка -«внутренний» и «наружный». Границы помещаются в соответствующий список.

Шаг 3. Создание двух списков точек пересечений

- первый, «входящий» список, содержит только точки пересечения, когда ребро 8Р входит внутрь СР. Другой, «выходящий» список, содержит точки пересечения, когда ребро 8Р выходит изнутри СР. Тип пересечения будет чередоваться вдоль границы. Таким образом, только одно определение необходимо для каждой пары пересечений.

Шаг 4. Выполнение пересечения. Многоугольники внутри СР находятся, используя следующую процедуру:

Шаг 4.1. Точка пересечения удаляется из «входящего» списка. Если список пуст, тогда процесс завершен.

Шаг 4.2. Выполняется обход списка вершин 8Р, пока не будет найдена точка пересечения. Список 8Р вплоть до найденной точки копируется во «внутренний» список.

Шаг 4.3. Используя ссылку, переходим на список вершин СР.

Шаг 4.4. Выполняется обход списка вершин СР, пока не будет найдена точка пересечения. Список СР вплоть до найденной точки копируется во «внутренний» список.

Шаг 4.5. Возвращается обратно на список вершин 8Р.

Шаг 4.6. Повторяем до тех пор, пока не будет достигнута стартовая точка. На этой точке заканчивается новый внутренний многоугольник. Конец алгоритма.

Многоугольники снаружи СР находятся, используя ту же процедуру, за исключением того, что начальная точка пересечения получается из «выходящего» списка и список вершин СР обрабатывается в обратном направлении. Списки многоугольников копируются в «наружный» список.

Более подробное описание алгоритма может быть найдено в [2, 3].

Трудоемкость вычислений пересечений равна О(п1 ,п2), где п1 и п2 - соответственно количество вершин 8Р и СР. При применении методов пространственного индексирования рёбер исходных многоугольников, например с помощью ^-деревьев, трудоемкость может быть снижена до О(п1 + п2).

Такие минусы, как высокая сложность при отработке большого количества особых случаев [2], возникающих при реализации, и невысокая скорость работы не позволяют рекомендовать данный алгоритм для практического применения.

АЛГОРИТМ ЛЕОНОВА

Практически все алгоритмы вычисления пересечения, объединения или разности многоугольников реализуют набор операций, не являющийся замкнутым, так как в результате их выполнения могут получаться контуры с самокасаниями, что неприемлемо в качест-

ве исходных данных для всех алгоритмов, и с отверстиями, которые, например, не допускаются алгоритмом Шутте [6]. Кроме этого, многие из широко известных алгоритмов не позволяют корректно обрабатывать вершины, в которых сходится более двух ребер многоугольников.

Алгоритм Леонова [7] лишен этих недостатков. В качестве исходных данных здесь могут быть произвольные полигональные многосвязные области с отверстиями и неограниченной кратностью вершин. Результат, полученный с помощью алгоритма, удовлетворяет его же предусловию.

Алгоритм состоит из четырех этапов:

Этап 1. Обработка пересечений ребер.

Этап 2. Маркировка контуров и ребер.

Этап 3. Получение результирующих контуров.

Этап 4. Создание результирующего региона.

На первом этапе находятся все пары несмежных пересекающихся ребер регионов А и В. Если пересечение ребер не точка, а отрезок, то концы этого отрезка считаются двумя точками пересечения. Если точки пересечения не совпадают с концевыми точками ребер, в исходные регионы добавляются новые вершины с координатами соответствующих точек. Следует отметить, что добавление точек пересечения не изменяет области, описываемые регионами А и В. Вершины, соответствующие точкам пересечения ребер, называются вершинами-пересечениями.

После выполнения первого этапа алгоритма выполняются следующие условия:

1. Ребра регионов А и В не имеют никаких общих точек друг с другом, кроме концевых.

2. Произвольное ребро контура С может либо геометрически совпадать с одним из ребер М (такие ребра будем называть сопряженными), либо находиться целиком (за исключением, может быть, концевых точек) внутри или вне области, описываемой М.

3. Если контур С не содержит вершин-пересечений, то он лежит целиком внутри или вне области, описываемой М.

На втором этапе рассматривается некоторый ограничивающий контур С одного из регионов А и В. За М обозначается регион, к которому не принадлежит С. На предыдущем этапе все точки пересечения были добавлены в исходные регионы.

Пометка контура С или ребра, принадлежащего контуру С, делается в зависимости от геометрического положения относительно М.

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

На четвертом этапе происходит формирование результирующего контура Я. Задача правильного формирования Я очень проста, так как полученные на предыдущем этапе внешние и внутренние контуры имеют правильную ориентацию. Для каждого внешнего контура создается отдельный полигон, внешним контуром которого он и будет являться. Внутренние контуры на предыдущем этапе сохраняются во вре-

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

Вычислительная трудоемкость алгоритма различается на разных этапах. В среднем она равна

O((«i + «2)log(«i + «2)+«о + zlog(n + «2)) , где (n1 + n2) - общее число вершин регионов A и В; z

- общее число контуров регионов A и В; «0 - максимальное число новых вершин.

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

АЛГОРИТМ ШУТТЕ

Алгоритм Шутте [6] базируется на алгоритме Вейле-ра - Азертона [4], однако имеет несколько ограничений:

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

2. Многоугольники не должны иметь «дыр».

3. Многоугольники не должны быть самопересе-кающимися.

Алгоритм состоит из следующих шагов:

Шаг 1. Пересечение двух многоугольников. Результатом являются те же самые многоугольники, с одним отличием, что точки пересечения добавляются как вершины многоугольников.

Шаг 2. Все ребра обоих многоугольников помечаются как «внутренние» (ребро находится внутри другого многоугольника), «разделенные» (ребро принадлежит обоим многоугольникам) и «наружные» (ребро находится снаружи другого многоугольника).

Шаг 3. Находятся минимальные многоугольники.

Шаг 4. Все минимальные многоугольники классифицируются по трем выходным наборам AflB, A\B, A/B. Конец алгоритма.

На первом этапе точки пересечения добавляются к спискам вершин многоугольников. Новые вершины одного многоугольника содержат ссылку на соответствующие вершины другого многоугольника. Получившиеся многоугольники называются расширенными.

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

1. Многоугольник А внутри многоугольника В. Здесь любая вершина из А находится внутри В, что легко может быть проверено. Если А внутри В, мы произвольно разбиваем В на два многоугольника - А будет находиться где-то на пересечении. Мы делаем разбиение, так как не хотим появления многоугольников с «дырами».

2. Многоугольник В находится внутри многоугольника А. Аналогично случаю, описанному выше.

3. Многоугольники А и В разделены.

Идея, заложенная на втором этапе алгоритма, заключается в том, что если одна из вершин ребра соединена с другим многоугольником, можно проверить, располагается ли она внутри или снаружи вто-

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

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

Для проведения классификации на четвертом этапе вводится термин «отцовство». «Отцовство» определяется как отношения между ребрами и исходными многоугольниками и между минимальными многоугольниками и исходными многоугольниками. Если «отцовство» доказано, значит объект является частью исходного многоугольника. Если «отцовство» ложно, значит объект не является частью исходного многоугольника. Кроме значений «доказано» и «ложно», «отцовство» может быть «неизвестным» и «смешанным». «Неизвестное» означает, что убедительных подтверждений нет. «Смешанное» означает, что существуют противоречащие факты. Это возможно только для минимальных многоугольников и означает, что минимальный многоугольник - это «дыра» между двумя исходными многоугольниками.

Процесс классификации минимальных многоугольников происходит в два этапа. На первом этапе проверяется «отцовство» каждого минимального многоугольника, после этого решается, к какому классу относится минимальный многоугольник.

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

Трудоемкость алгоритма при операциях нахождения пересечений и маркировки ребер равна O(njn2).

Можно сделать вывод, что, хотя Шутте модифицировал алгоритм Вейлера - Азертона более четким разделением этапов и новым алгоритмом маркировки ребер (edge labeling), его алгоритм обладает более существенными ограничениями на входные данные и не избавился от врожденных недостатков.

АЛГОРИТМ ХОЛВЕРДА

Входными данными скан-линейного алгоритма Холверда [12] являются два набора многоугольников. Один из наборов является первым операндом булевой операции, другой - вторым операндом. Основная идея состоит в том, чтобы разбить плоскость на секции, называемые закрытыми областями. Закрытые области

- это области, которые могут быть описаны простыми многоугольниками (без самопересечений и самопере-крытий).

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

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

Можно выделить следующие основные этапы алгоритма:

Шаг 1. Конвертация всех многоугольников в графы. Один многоугольник становится одним графом.

Шаг 2. Объединение всех графов в один большой граф. Такой граф идеален для скан-линейного алгоритма, так как ссылки графа могут быть отсортированы без потери структуры отображения. Только ссылки получат другой порядок в списке, позиция же узлов не изменится. Следует заметить, что каждая ссылка в графе получает уникальный номер, содержащий информацию принадлежности тому или иному многоугольнику.

Шаг 3. Вычисление точек пересечения между графами, используя скан-луч, и вставка их как дополнительных вершин или сегментов. Метод скан-луча используется несколько раз в этом алгоритме. Идея состоит в сканировании изображения вертикальным скан-лучом. Скан-луч - это пространство между двумя последовательными вертикальными скан-линиями. Скан-линия генерируется каждым узлом в графе. В первую очередь, все начальные узлы ссылок графа сортируются по минимальной X координате (если X одинаково, то по У). Начальный узел одной ссылки является всегда конечным узлом другой ссылки просто потому, что все многоугольники являются замкнутыми петлями. То есть, когда мы генерируем скан-линию для каждого начального узла всех ссылок, можно быть уверенным, что все узлы графа будут пройдены.

Шаг 4. Установка соответствующих флагов сегментов одновременно для всех булевых операций, используя скан-луч.

Шаг 5. Получение для данной булевой операции результирующих многоугольников. В принципе, на данном этапе необходимо найти подходящую ссылку, помеченную для данной операции, и двигаться по связанным с первой ссылкам, которые также помечены для этой операции. Когда мы снова доходим до стартовой ссылки, можно извлекать один многоугольник, и так далее, пока не будут получены все многоугольники.

Данный этап выполняется за пять шагов:

Шаг 5.1. Уничтожение ненужных ссылок - удаление ссылок, для которых не установлен флаг участия в данной булевой операции.

Шаг 5.2. Выделение внутренних и внешних контуров (рис. 7) из общего графа и помещение их в список графов. На внутренние контуры ставится отметка «дыра».

Шаг 5.3. Создание одного графа - слияние всех контурных графов обратно в один граф (необходимо для связывания «дыр» с помощью скан-луча).

Шаг 5.4. Связывание «дыр» - использование скан-луча для связывания внутриконтурных графов с внешнеконтурными.

Шаг 5.5. Выделение всех связанных графов (внешний и внутренний контур как один граф) из общего графа.

Шаг 5.6. Конвертация графов обратно в много -угольники.

внешнии контур

связанный полигон

внутр. контур

П!

I-----------1

І I

I---------------- I

[ внутренний контур (

Рис. 7. Внутренние и внешние контуры многоугольника в алгоритме Холверда

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

АЛГОРИТМ МАРГАЛИТА - КНОТТА

А. Маргалит и Г. Кнотт, авторы одноименного алгоритма, обратили внимание на то, что многие алгоритмы пересечения, объединения и разности многоугольников не очень практичны, не способны обрабатывать сложные случаи, сложны в реализации, и предложили свой алгоритм, ориентируясь, в первую очередь, на эффективность и простоту реализации [10]. Алгоритм делится на две основные стадии. Первая стадия - это классификация линейных сегментов входных многоугольников, а вторая - конструирование результирующих многоугольников.

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

Далее алгоритм классифицирует реберные фрагменты одного многоугольника на нахождение внутри, снаружи или на границе другого многоугольника. Множество реберных фрагментов многоугольника 2 делится на три подмножества, в зависимости от положения относительно многоугольника Р. Эти три множества реберных фрагментов обозначаются как Р” (2), РрП (2) и Р™* (2). Множество граничных

реберных фрагментов ррп(2) в дальнейшем может

быть разбито на две части, в зависимости от того, в ту же или противоположную сторону фрагментам Р направлены фрагменты 2. Эти множества обозначаются

как (2) и (2). Это тонкое деление по-

зволяет нам создавать только регулярные результирующие многоугольники, для которых необходимо не

использовать реберные фрагменты из множества

F°pnU (Q .

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

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

Этот алгоритм относительно прост и практичен. При реализации можно использовать хэш-таблицы и другие простые структуры данных. Элементарные манипуляции с этими структурами данных производительны, следовательно, минимизируется время и требуемый объем памяти. В алгоритме не нужно обрабатывать большое число специальных случаев, и поэтому он может легко работать с любой парой вершинно-полных многоугольников. Трудоемкость алгоритма составляет в худшем случае O(n2), однако на практике она может быть значительно улучшена в среднем до O(nlogn).

ТРИАНГУЛЯЦИОННЫЙ АЛГОРИТМ

Основная идея алгоритма построения оверлеев многоугольников с помощью триангуляции [13] заключается в построении триангуляции с ограничениями, где в качестве структурных линий выступают стороны исходных многоугольников, а затем объединения некоторых треугольников в искомый многоугольник.

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

В общем виде алгоритм можно записать следующим образом (рис. 8):

Рис. 8. Построение оверлеев: а - исходные многоугольники; б - триангуляция с ограничениями; в - объединение; г - пересечение; д и е - разности многоугольников

Шаг 1. Стороны исходных многоугольников А и В (рис. 8,а) передаются в качестве структурных линий в алгоритм построения триангуляции с ограничениями (рис. 8,б).

Шаг 2. Каждый треугольник триангуляции классифицируется по признаку попадания внутрь А и В.

Шаг 3. Каждый треугольник Ті полученной триангуляции классифицируется в зависимости от выполняемой операции.

Вариант 1 (объединение):

если Ті є А или Ті є В, то сі :=1, иначе сі := 0 .

Вариант 2 (пересечение):

если Ті єА и Ті єВ , то сі :=1, иначе сі := 0 .

Вариант 3 (разность):

если Ті є А и Ті єВ , то сі :=1, иначе сі := 0 .

Шаг 4. Все треугольники, имеющие сі :=1, объединяются в один многоугольник, который выбирается в качестве результата (рис. 8,е-е). Конец алгоритма.

Для выполнения первого шага алгоритма можно воспользоваться любым алгоритмом построения триангуляции с ограничениями. Обзор таких алгоритмов приведен, например, в [14].

В целом трудоемкость первого шага составляет в худшем случае О(п ^(п + п2)), а в среднем - О(п). Трудоемкость третьего шага, очевидно, является линейной - О(п). Трудоемкость второго и четвертого шагов составляет также О(п).

Таким образом, в целом алгоритм построения оверлеев на основе триангуляции имеет в худшем случае трудоемкость О(п^(п + п2)), а в среднем - О(п).

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

ЛИНЕЙНО-УЗЛОВОЙ АЛГОРИТМ

Основная идея рассматриваемого алгоритма [15] заключается в предварительном построении линейноузловой модели - геометрического планарного графа специального вида, ребра которого должны соответствовать отрезкам исходных границ полигонов (происхождение вводимого автором термина «линейноузловой» связано с используемыми в геоинформатике похожими топологическими моделями данных - покрытиями, называемыми также линейно-узловыми моделями).

Затем после построения графа производится классификация ребер графа по признаку вхождения в результирующий полигон. Для классификации всех ребер требуется умение выполнять две операции: 1) определять расположение полигона относительно ребра линейно-узловой модели и 2) определять, попадает ли некоторое ребро на границу, внутрь или вне полигона.

На последнем этапе алгоритма выполняется сборка отрезков графа в последовательность отрезков границы требуемого полигона. Для этого достаточно после классификации пометить входящие в результат ребра как непройденные, а остальные - как пройденные и запустить алгоритм выделения контуров.

Обратим внимание, что в результате работы предложенного алгоритма будет построен полигон, в котором контуры не будут взаимно- и самопересекаться,

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

Линейно-узловой алгоритм построения оверлеев позволяет явно учесть многочисленные тонкие эффекты, возникающие на пороге точности вычислений. Данный алгоритм имеет такой же порядок трудоемкости, что и алгоритм Маргалита - Кнотта [10], но в среднем в 1.5 раза медленнее последнего. Тем не менее предлагаемый алгоритм имеет несколько большую область определения и достаточно простую структуру для программной реализации.

ЗАКЛЮЧЕНИЕ

В таблице приведены сравнительные характеристики всех вышеописанных алгоритмов.

К недостаткам большинства из них стоит отнести недостаточно высокую вычислительную устойчивость, нерешенные численные проблемы, связанные с

округлением. Многие алгоритмы реализуют набор операций, не являющийся замкнутым, так как в результате их выполнения могут получаться контуры с самокасаниями, что неприемлемо в качестве исходных данных.

Одним из наиболее простых алгоритмов можно признать алгоритм О’Рурка, однако он обрабатывает только выпуклые многоугольники. Можно выделить также алгоритмы Леонова и Холверда - наряду с устойчивой и быстрой работой, способностью обрабатывать общие многоугольники, в них решены проблемы появления «посторонних пересечений», возникающих при округлении точек пересечения.

Однако из-за высокой скорости работы и лучшей вычислительной устойчивости для практического применения стоит рекомендовать триангуляционный алгоритм в случае относительно большого числа узлов исходных многоугольников и линейно-узловой алгоритм для меньшего числа.

Сравнительные характеристики различных алгоритмов построения оверлеев: п1 - количество вершин первого многоугольника А; п2 - второго (В); п0 - количество новых точек пересечения сторон двух многоугольников; г - общее число контуров многоугольников А и В п = п1+ п2+ п0

Алгоритм Поддерживаемые операции Тип исходных многоугольников Простота программной реализации Устой- чи- вость Ско- рость Трудоемкость Общая оценка

п и /

Сазерленда - Ходжмана + - - Один выпуклый, другой общий 5 3 4 O(n-ln2log n2) 3

О’Рурка + + + Выпуклые 5 4 5 О(п) 5

Вейлера - Азертона + + + Простые с ориентированными контурами 3 3 4 O(n log(nj + n2)) 3

Леонова + + + Общие 4 5 4 О((щ + n2)log(nj + n2) + +n0 + z log(n1 + n2)) 5

Шутте + - + Простые 4 3 4 O(njn2) 3

Холверда + + + Общие 3 5 4 O(n log n) 4

Маргалита - Кнотта + + + Вершинно-полные 4 4 4 O(n) 4

Линейно-узловой + + + Общие 4 5 4 O(n2) 5

Триангуляционный + + + Общие 5 5 5 O(n) 5

ЛИТЕРАТУРА

1. Препарата Ф., ШеймосМ. Вычислительная геометрия: Введение / Пер. с англ. М.: Мир, 1989. 478 с.

2. Foley D.J., van Dam A., Feiner S.K., Hughes J.F. Computer graphics. Principles and practice. N.Y.: Addisson-Westey, 1991.

3. Роджерс Д. Алгоритмические основы машинной графики / Пер. с англ. М.: Мир, 1989. 512 с.

4. Weiler K., Atherton P. Hidden surface removing using polygon area sorting // Computer Graphics. 1977. V.11. P. 214—222.

5. WeilerK. Polygon comparison using graph representation // Computer Graphics. 1980. V. 14. P. 10-18.

6. Schutte K. An edge labeling approach to concave polygon clipping // ACM Transactions on Graphics. 1995. P. 1-10.

7. Леонов М.В., Никитин А.Г. Эффективный алгоритм, реализующий замкнутый набор булевых операций над множествами многоугольников на плоскости / Препринт Института систем информатики СО РАН № 46. 1997. 20 с.

8. Sutherland I.E., Hodgman G.W. Reentrant polygon clipping // CACM. 1983. V.26. P. 868-877.

9. Clark J.H. A VLSI geometry Processor for Graphics // IEEE Computer. 1980. V.12 (7). P 59-68.

10. Margalit A., Knott G.D. An algorithm for computing the union, intersection or difference of two polygons // Computers & Graphics. 1989. V.13. No. 2. P. 167-183.

11. O'Rourke J., Chien C.B., Olson Т., Naddor D. A new linear algorithm for intersecting convex polygons // Computer Graphics and Image Processing. 1982. V.19. P. 384-391.

12. HolwerdaK. Complete Boolean Description (http:// www.xs4all.nl/~kholwerd/bool.html).

13. Скворцов А.В. Построение объединения, пересечения и разности произвольных многоугольников в среднем за линейное время с помощью триангуляции // Вычислительные методы и программирование. 2002. Т. 3. С. 116-123.

14. Скворцов А. В. Алгоритмы построения триангуляции с ограничениями // Вычислительные методы и программирование. 2002. № 3. С. 82-92 (http://num-meth.srcc.msu.su).

15. Скворцов А.В. Линейно-узловой алгоритм построения оверлеев двух полигонов // Вестник ТГУ. 2002. № 275. С. 99-103.

Статья представлена факультетом информатики Томского государственного университета, поступила в научную редакцию 11 мая 2003 г.