УДК 681.3
ОВЕРЛЕЙ МНОГОГРАННИКОВ
Н.А. Тюкачев
Предлагается индексный алгоритм для булевых операций над трехмерными телами, ограниченными многогранниками. Такие многогранники используются, например, для описания гомогенных слоев породы в геоинформа-ционных системах. Алгоритм основан на локальном анализе семейств инцидентных вершин, граней и ребер и не требует глобальной упорядоченности ребер
Ключевые слова: геометрические алгоритмы, булевы операции
1 В геоинформационных системах (ГИС) для описания слоев породы или рудного тела необходимо использовать трехмерные объекты. Эти объекты могут быть гомогенными, например, слой породы с одинаковой литологи-ей|стратиграфией, или гетерогенными, например, рудное тело с плотностью руды, зависящей от координат.
Для описания гомогенных объектов можно использовать граничную модель, определяяя границу как множество многоугольников. Частным случаем граничной модели является модель трехмерного тела, у которого граница представляет собой замкнутое множество нерегулярных треугольников. Замкнутую ориентированную поверхность Р разобьем на треугольники со следующими условиями: а) каждая точка поверхности Р принадлежит хотя бы одному треугольнику; б) два треугольника могут пересекаться только в одной вершине или по целому ребру. Такую модель будем называть CTIN-представлением или CTIN-поверхностью (CTIN
- closed triangular irregular network). На рис. 1 изображены верхняя и боковая триангулированные поверхности слоя.
Рис. 1. Пример трехмерной CTIN-модели для слоя
Тюкачев Николай Аркадиевич - ВГУ, канд. физ.-мат. наук, доцент, тел. (4732) 208-470, Е-mail: [email protected]
Первичные данные о таких поверхностях получают, как правило, бурением сотен скважин с взятием проб породы. За год компания АЛРОСА, например, может пробурить 3-4 сотни километров скважин.
Перечислим некоторые из задач, возникающих при работе с CTIN-поверхностями:
1. построение 2Б-триангуляции верхней и нижней поверхности слоя;
2. построение 2D-триангуляции с ограничениями в виде произвольного многоугольника или ломаной линии, моделирующей разлом земной коры;
3. построение триангуляции всех слоев;
4. сглаживание триангуляции;
5. задача построения триангуляции боковой поверхности слоя, которая сводится к созданию упорядоченного по обходу массива номеров граничных точек;
6. построение триангуляции невыпуклого многоугольника вертикального разреза слоя;
7. построение изолиний;
8. булевы операции над 3D-телами, которые сводятся к задачам:
■ определение точек пересечения двух тел. Эта задача сводится к определению точек пересечения ребер одного тела с гранями второго тела;
■ разбиение ребер и треугольных граней на новые грани и ребра;
■ расстановка индексов для вершин, ребер и граней;
9. изображение тела.
В этой работе предлагается алгоритм для решения наиболее сложной восьмой задачи булевых операций с трехмерными телами. Необходимо отметить, что во многих графических библиотеках, например OpenGL или DirectX, эта задача не решается и обходится z-буферизацией. На рис. 2 приведено широко известное изображение чайника.
Рис. 2. Объект, состоящий из четырех частей
Этот трехмерный объект состоит из четырех несвязанных между собой частей: сети че-тырехгольников, из которых составлена поверхность каждой части. Эти части не взаимодействуют между собой. Однако, 2-буферизация позволяет изображать эти части как единое целое.
Задача состоит в том, чтобы в результате любой булевой операции над двумя СТШ-поверхностями получить новую СТШ-поверхность. Рассмотрим в качестве примера два параллелепипеда А и В (рис. 3).
Рис. 3. Два несвязаных параллелепипеда
Поверхность первого параллелепипеда А разбита на 16 треугольных граней (рис. 4).
Поверхность второго параллелепипеда В также разбита на 16 треугольных граней (рис. 5).
Рис. 5. Второй параллелепипед
При пересечении этих двух многогранников добавляются новые вершины, ребра и грани (рис. 6).
Рис. 6. Пересечение двух параллелепипедов
На рис. 7 показано первое тело А с добавленными вершинами, ребрами и гранями.
Рис. 7. Первый параллелепипед с добавленными вершинами ребрами и гранями
На рис. 8 показано второе тело В с добавленными вершинами, ребрами и гранями.
Рис. 4. Первый параллелепипед
Рис. 8. Второй параллелепипед с добавленными вершинами ребрами и гранями
Новое тело С получается в результате одной из булевых операций, например С=А\В (рис. 9 и 10).
Рис. 10. Результирующее тело А\В (грани)
Обсудим более подробно понятие булевых операций. Из элементов двух множеств А и В пространства М, используя булевы операции объединения «и», пересечения «п» и разности «\» и т.д., можно составить новое множество С (рис. 11).
Аг,В A^jB AYB В\А
Рис. 11. Операции над множествами
Без ограничения общности можно считать, что AnB Ф 0, то есть существуют x такие, что (хеА)л(хеВ). Каждому элементу xeM поставим в соответствие число (рис. 12). Пронумеруем непересекающиеся части пространства M, в котором определены множества А и В: АпВ - 0; А\В - 1; В\А - 2; М\(АиВ) - 3.
Определение. Числа 0, 1, 2, 3 будем называть индексами (Index) внутренних элементов множеств АпВ, А\В, В\А и М\(АиВ):
Index=0: AnB = {x: xeA и xeB};
Index=1: A\B = {x: xeA и xgB};
Index=2: B\A = {x: xeB и xgA};
Index=3: -An-B = {x: x^A и xgB}.
3
3+0=1+2
Рис. 12. Индексы подмножеств и границ при разбиении
Далее вместо термина индекс внутреннего элемента множества будем употреблять термин индекс множества. Индексы множества А равны номерам ненулевых битов в двоичном числе 00112, а индексы множества В равны номерам ненулевых битов в числе 01012.
Определение. Каждому граничному элементу множеств А и В поставим в соответствие число, которое будем называть индексом границы. Индекс границы равен сумме индексов множеств, которые она разделяет (рис. 12): 1+0=1 - индекс граничных точек между множествами с индексами 0 и 1; 2+0=2 - индекс граничных точек между множествами с индексами 0 и 2; 3+0= 1+2=3 - индекс узловых точек;
3+1=4 - индекс точек между множествами с индексами 1 и 3; 3+2=5 - индекс граничных точек между множествами с индексами 3 и 2.
В любой узловой точке - точке пересечения границ - сходятся две или четыре (например,
для операции «исключающее или» с номером б!0=01102) границы нового множества С.
Операции объединения, вычитания, пересечения 2Б и 3Б тел являются достаточно сложными. Однако, бинарная нумерация операций над множествами позволяет сформулировать общий алгоритм сбора ребер и граней в результирующее тело, опирающийся на теорему об индексах [4,5].
В общем случае над двумя множествами А и В можно рассматривать шестнадцать различных операций, каждая из которых имеет номер от 0 до 15. Для дальнейших рассуждений будем использовать двоичную нумерацию этих операций. Двоичный номер операции полностью определяет ее результат. Так, например, операция с номером 710=01112 - это операция объединения «или».
Теорема об индексах [4,5]. Между номерами операций и индексами граничных элементов результирующего тела существует связь: сумма номеров пар различных битов в двоичном представлении номера операции совпадает с индексами граничных элементов.
Доказательство сводится к проверке утверждения для всех 16-ти бинарных операций. Так, например, для операции С=(А\В)и(В\А) с номером б]0=01102 граница состоит из элементов с номерами: 0+1, 2+3, 1+3, 2+3, 3+0=1+2. В двоичном числе 01102 различны следующие пары битов: (0,1), (0,2), (2,3), (1,3). Элементы пересечения границ (0+3=1+2) входят в границы любого нового множества. Для операции пересечения АпВ с номером 110=00012 граница множества С состоит из элементов с индексами 0+1, 0+2, 0+3=1+2. Эти же пары различных битов есть в числе 00012: (0,1), (0,2), (0,3).
Замечание. Порядок нумерации множеств АпВ, А\В, В\А и М\(АиВ) влияет на порядок нумерации булевых операций.
Под выполнением булевой операции над многоугольниками А и В понимается выполнение операции над описываемыми ими областями и получение множества многоугольников, описывающего полученную область.
Таким образом построение результирующего тела для любой булевой операции сводится к задаче определения принадлежности точки V телу. Анализ известных алгоритмов для многоугольников показал, что даже в двумерном случае эта задача далеко не тривиальна, если луч, выходящий из точки, проходит через вершину многоугольника. Поэтому автором был разработан новый алгоритм определения принадлежности точки телу, основанный на понятии инцидентных вершин, ребер и граней [3]. Этот алго-
ритм позволяет решить задачу и в трехмерном случае. Приведем краткое описание этого алгоритма.
Инцидентный лучевой алгоритм определения принадлежности точки трехмерному телу состоит из трех шагов:
1. Находим вершины, попадающие на луч.
1.1. Для каждой такой вершины строим се-
мейства инцидентных вершин.
1.2. Для каждого семейства определяем,
принадлежит ли проекция точки v на плоскость YZ проекции многоугольника инцидентных вершин семейства на ту же плоскость, если принадлежит, то меняется бит принадлежности. Задача сводится к плоской.
2. Находим ребра, попадающие на луч.
2.1. Для каждого такого ребра строим се-
мейства инцидентных вершин.
2.2. Для каждого семейства определяем,
принадлежит ли проекция вершины v на плоскость YZ проекции многоугольника инцидентных вершин семейства на ту же плоскость, если принадлежит, то меняется бит принадлежности.
3. Для всех открытых граней без вершин и ребер, пересекающихся с лучом, меняется бит принадлежности.
Для описания триангулированной поверхности будем использовать модель «сущность-связь» (Entity-Relationship model или ER-модель). Основной концепцией ER-модели является [1]:
• тип сущности (entity type), который представляет группу объектов реального мира, обладающих одинаковыми свойствами;
• и тип связи (relationship type) является набором ассоциаций между одним (или несколькими) типами сущностей, участвующими в этой связи. Каждому типу связи присваивается имя, которое должно описывать его назначение.
Рассмотрим мгогогранники общего вида, которые могут быть определены четырьмя сущностями: тела (Body), грани (Face), ребра (Edge) и вершины (Vertex). В общем случае эти сущности связаны между собой шестью отношениями «многие ко многим» *:* (тела-грани, тела-ребра, тела-вершины, грани-ребра, грани-вершины, ребра-вершины) и четырьмя отношениями «один ко многим» (тело - инцидентные тела, грань - инцидентные грани, ребро - инцидентные ребра, вершина - инцидентные вершины).
Но для алгоритма достаточно оставить 11 связей «один ко многим» (рис. 13).
а
Инцидентные вершины
Рис. 13. ER-модель для многогранников
Обращаем внимание на то, что при реализации алгоритма для каждой вершины потребуется знать семейства ее соседних вершин, то есть необходимо оставить связь «вершина - инцидентные вершины».
Структура сущности Vertex помимо координат x,y,z, массивов номеров граней IdFace и тел IdBody, содержит поле Family
- двумерный массив семейств номеров инцидентных вершин и поле Visit - признак посещения вершины, используемый при реализации алгоритма принадлежности. Этот признак позволяет запрещать обрабатывать вершину дважды.
Структура ребер Edge содержит номера вершин Vertex1 и Vertex2, на которые ребро опирается, массив IdBody номеров тел, которому ребро принадлежит, временный массив точек Points, которые добавляются при пересечении тел, и массив соседних граней IncidentalFace.
Структура треугольных граней Face содержит массивы IdVertex - номеров вершин, на который она опирается, массив IdEdge номеров ребер, составляющих контур грани и массив IdBody номеров тел, которому ребро принадлежит. Кроме этого у грани есть временный массив TempEdge, в который добавляются ребра пересечения с гранями другого тела, и временный массив Tr треугольников триангуляции.
Наконец, структура Body содержит массив номеров граней IdFace и вершин IdVertex.
Алгоритм построения результирующего тела для булевой операции состоит из следующих
семи шагов:
1. Определить индексы вершин 1-го и 2-го многогранников;
2. Найти пересечение всех граней 1-го многогранника со всеми гранями 2-го многогранника;
2.1. Найти пересечение грани 1-го многогранника с ребрами грани 2-го многогранника;
2.1.1. Если точка пересечения ребра принадлежит грани, то ищем ее в массиве вершин Vertex, если она не найдена, то добавляем ее с номером n и добавляем в массив t[] ^n;
2.1.2. Добавляем номер точки n в массив Points ребра;
2.1.3. Добавляем номер точки n в массив Face1.IdVertex;
2.1.4. Добавляем номер точки n в массив Face2.IdVertex;
2.2. Найти пересечение грани 2-го многогранника с ребрами грани 1-го многогранника;
2.2.1. Если точка пересечения ребра принадлежит грани, то ищем ее в массиве вершин Vertex, если не найдена, то добавляем ее с номером n и добавляем в массив t[] ^n;
2.2.2. Добавляем номер точки n в массив Points ребра;
2.2.3. Добавляем номер точки n в массив Face1.IdVertex;
2.2.4. Добавляем номер точки n в массив Face2.IdVertex;
2.3. Если пересечение грани с гранью добавляет 2 точки (длина массива t[ ] равна 2), то в массив грани TempEdge добавляем номера этих точек;
3. Триангуляция всех граней 1-го многогранника по добавленным вершинам с ограничением не пересекать ребра TempEdge. Для каждой грани создается массив треугольников Triangle;
4. Триангуляция всех граней 2-го многогранника по добавленным вершинам с ограничением не пересекать ребра TempEdge. Для каждой грани создается массив треугольников Triangle;
5. Добавление ребер;
5.1. Создать копию массива ребер CopyEdge;
5.2. Для всех ребер, если на них есть новые точки в массиве Points, то отсортировать их;
5.3. Разбить ребро точками Points и добавить их в массив CopyEdge;
5.4. Добавить ребра из треугольников триангуляции Triangle;
5.5. Временный массив CopyEdge переместить в массив ребер;
6. Добавление граней;
6.1. Создать копию массива граней CopyFace;
6.2. Добавить в массив CopyFace треугольники триангуляции Triangle;
6.3. Временный массив CopyFace переместить в массив граней;
7. Добавление нового многогранника;
7.1. Если вершина подходит по индексу, то добавить его в новый многогранник;
7.2. Расставить индексы ребер;
7.3. Если ребро подходит по индексу, то добавить его в новый многогранник;
7.4. Расставить индексы граней;
7.5. Если грань подходит по индексу, то добавить ее в новый многогранник.
Задачу определение индекса точки, сводящуюся к определению принадлежности точки телу необходимо выполнять на первом шаге и на шагах 7.3 и 7.5.
Опишем более подробно второй шаг: пересечение грани с гранью. На шаге 2.1 определяется точка пересечения ребра и грани и добавляется в массив Points ребра. На шаге 5.2 и 5.3 эти точки будут использованы для разбиения ребра на новые ребра. Если в результате пересечения грани с гранью добавилось 2 таких точки
(а их всегда 0 или 2), то в массиве TempEdge граней необходимо зафиксировать ребро пересечения граней. Эти ребра не имеет права пересекать триангуляция граней, выполняемая на шагах 3 и 4. Номера точек пересечения добавляются также в массивы граней Face1.IdVertex и Face2.IdVertex. Эти точки используются при построении триангуляции граней.
На 3 и 4 шагах выполняется триангуляция граней с ограничениями. На рис. 14 показана пирамида с вершинами 0-1-2-3, ребра которой пересеклись с гранями другой пирамиды по точкам 8, 9 и 10. В результате некоторые боковые грани приходится разбивать на три новых грани.
Рис. 14. Пирамида с добавленными точками и ребрами
Задача разбиения граней на треугольники и добавления новых ребер в общем случае не тривиальна. На рис. 15 показан случай, когда в грань 5-6-7 пирамиды 4-5-6-7 по треугольнику 8-9-10 «врезалось» второе тело. Грань 5-6-7 приходится разбивать на семь треугольников.
Эта задача сводится к построению триангуляции по заданным точкам, но при этом недопустима «правильная» в смысле Делоне триангуляция, если хотя бы одна из сторон треугольника пересекает полигон 3-4-5 пересечения грани со вторым телом, как это показано на рис. 16.
Рис. 16. Недопустимая триангуляция грани
В общем случае область песечения грани с телом может быть и невыпуклая неодносвязная (рис. 17).
Рис. 17. Невыпуклая неодносвязная область пересечения грани с телом
Более подробное обсуждение триангуляции с ограничениями можно найти в [2].
Выполнение 5 и 6 шагов особых проблем не вызывает. Обсудим более подробно выполнение последнего, седьмого, шага алгоритма: добавление нового многогранника.
На шаге 7.1 необходимо принять решение, если вершина подходит по индексу операции с номером k, то добавить его в новый многогранник. Для решения этой задачи по номеру опер-ции соберем множество V сумм номеров различных битов номера операции k:
V:=[3];
for i:=0 to 2 do for j:=i+1 to 3 do if ((k and (1 shl i))<>0) xor ((k and (1 shl j))<>0) then V:=V+[i+j];
Воронежский государственный университет
Если Index вершины входит в это множество V (Index in V), то вершина принадлежит результирующему телу.
Для принятия решения на шаге 7.3 о входе ребра в результирующее тело смотрим индексы его обеих вершин. Если (Index1<>3) or (Index2<>3), то условие принадлежности сводится к проверке условия (Index1 in V) and (Index2 in V) . Иначе необходимо вычислить индекс какой-нибудь точки ребра, например середины, и по ее индексу принять решение о принадлежности.
Аналогично принимается решение о принадлежности грани результирующему телу.
Литература
1. Конолли Т. Базы данных. Проектирование, реализация и сопровождение. Теория и практика. 3-е издание.: Пер. с англ. / Томас Конолли, Карелии Бегг. - М.: Издательский дом "Вильямс", 2003. - 1440 с.
2. Скворцов А.В. Алгоритмы построения триангуляции с ограничениями // Вычислительные методы и программирование. 2002. т.3, с. 82-92.
3. Тюкачев Н.А. Определение принадлежности точки многоугольнику общего вида методом трассировки луча // Вестник ВГТУ. 2009. № 4. С. 338-345.
4. Тюкачев Н.А. Программирование графики в Delphi. / Н.А.Тюкачев, И.В. Илларионов, В.Г. Хлебостроев - СПб., БХВ-Петербург. 2008. - 766 с.
5. Тюкачев Н. А. Создание мультимедийных приложений в Delphi. / Тюкачев Н.А., Свиридов Ю.Т. - СПб., Питер. 2001. - 400 с.
OVERLAY POLYHEDRONS N.A. Tjukachev
The index algorithm for boolean operations above the three-dimensional bodies limited by polyhedrons is offered. Such polyhedrons are used, for example, for the description of homogeneous layers of breed in geoinformation systems. The algorithm is based on the local analysis of families of incidental vertex, sides and edges and does not demand global orderliness of edges.
Keywords: geometrical algorithms, boolean operations