ППЛГ и РСДС (PSLG и DCEL): определение, построение РСДС множества прямых — различия между версиями
Tiss93 (обсуждение | вклад) (Новая страница: « 400px|thumb|incident_face|Представление плоского графа с помощью РСДС [[Файл:DCEL2.png|200px|thum...») |
Tiss93 (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | [[Файл:DCEL.png|400px|thumb| | + | [[Файл:DCEL.png|400px|thumb|left|Представление плоского графа с помощью РСДС]] |
[[Файл:DCEL2.png|200px|thumb|right|Плоский граф, ребрам которого придана произвольная ориентация для представления его с помощью РСДС. Стрелки вокруг вершин соответствуют указателям (P1, P2)]] | [[Файл:DCEL2.png|200px|thumb|right|Плоский граф, ребрам которого придана произвольная ориентация для представления его с помощью РСДС. Стрелки вокруг вершин соответствуют указателям (P1, P2)]] | ||
[[Файл:DCEL3.png|200px|thumb|right|(а) РСДС, (б) входы по вершинам head_V [1..n] и (в) входы по граням head_F[1..l]]] | [[Файл:DCEL3.png|200px|thumb|right|(а) РСДС, (б) входы по вершинам head_V [1..n] и (в) входы по граням head_F[1..l]]] |
Версия 22:46, 5 января 2014
ППЛГ --- Плоский прямолинейный планарный граф.
РСДС --- Реберный список с двойными связями.
ППЛГ
Планарный граф, уложенный на плоскости, принято называть плоским. Плоская укладка планарного графа --- это отображение каждой вершины из в точку на плоскости, а каждого ребра из в простую линию, соединяющую пару образов концевых вершин этого ребра так, чтобы образы ребер пересекались только в своих концевых точках. Хорошо известно, что любой планарный граф можно уложить на плоскости так, чтобы все ребра отобразились в прямолинейные отрезки.
РСДС
Первое описание
Реберный список с двойными связями особенно удобен для представления ППЛГ. Пусть задан граф
, , а . Главная компонента РСДС для планарного графа это реберный узел. Между ребрами графа и реберными узлами РСДС существует взаимно однозначное соответствие, т.е. каждое ребро представлено в РСДС ровно один раз. Реберный узел РСДС, соответствующий ребру графа, например, имеет 4 поля ( ) и 2 указателя ( ). Поле содержит начало ребра, а поле содержит его конец (так изначально неориентированное ребро получает условную ориентацию). Поля и содержат имена граней, лежащих слева и справа от ориентированного ребра ( ). Указатель (соответственно ) задает реберный узел, содержащий первое ребро, встречаемое вслед за ребром ( ), при повороте от него против часовой стрелки вокруг (соответственно ).Второе описание
РСДС состоит из 3 компонент. Vertex, half-edge, face Vertex - это точка сочленения. Содержит координаты точки. А так же указатель на инцидентное ребро. Face - содержит указатель на наружную компоненту (некоторое ребро на его границе). Для неограниченных поверхностей это nil. Так же содержит внутреннюю компоненту, которая есть указатель на некое ребро, с которого можно начать описывать внутреннюю область (опять же, может быть nil). Half-edge - это ребро. Содержит указатели на точку, откуда исходит (origin), указатель на ребро близнец (twin)(направленное в другую сторону), инцидентную поверхность (incident_face), и указатели на следующее и предыдущие ребра.
struct vertex { x, y; half_edge *rep; /* rep->origin == this */ };
struct face { outer_component *out; inner_component *in; };
struct half_edge { half_edge *prev; /* prev->next == this */ half_edge *next; /* next->prev == this */ half_edge *twin; /* twin->twin == this */ vertex *origin; /* twin->next->origin == origin && prev->twin->origin == origin */ face *incident_face; /* prev->incident_face == incident_face && next->incident_face == incident_face */ };
Построение РСДС множетсва прямых
Алгоритм: Для каждой конечной точки создаем vertex. Для каждого входного сегмента создаем 2 half-edge и присваиваем vertex в origin и создаем поля twin. Для каждой конечной точки сортируем (по часовой стрелке) half-edge, у которых origin vertex и есть эта точка. Для каждой пары half-edge e1, e2, по часовой стрелке присваиваем e1->twin->next = e2 и e2->prev = e1->twin. Выбираем один из этих half-edge и делаем его представителем точки. (Вырожденный случай: если есть только 1 half-edge в отсортированном списке, то присваиваем e->twin->next = e и e->prev = e->twin. Если сделать четко, то это не понадобится). Следующие указатели это перестановки half-edge. В каждом цикле находим и создаем face.