алгоритм поиска ребер с использованием вершин (2D и 3D) в сетке - PullRequest
5 голосов
/ 19 февраля 2010

У меня есть сетка с определенными типами элементов (например, треугольная, тетра). Для каждого элемента, который я знаю, все его вершины, то есть треугольный 2D-элемент будет иметь 3 вершины v1, v2 и v3, координаты x, y, z которых известны.

Вопрос 1

Я ищу алгоритм, который вернет все ребра ... в этом случае:

ребро (v1, v2), ребро (v1, v3), ребро (v2, v3). Исходя из того, сколько вершин имеет каждый элемент, алгоритм должен эффективно определять ребра.

Вопрос 2

Я использую C ++, так что будет наиболее эффективным способом хранения информации о ребрах, возвращаемых вышеупомянутым алгоритмом? Например, все, что меня интересует, это кортеж (v1, v2), который я хочу использовать для некоторых вычислений, а затем забыть об этом.

Спасибо

Ответы [ 3 ]

7 голосов
/ 19 февраля 2010

Вы можете использовать половинную структуру данных.

image
По сути, ваша сетка также имеет список ребер, и для каждой пары вершин в каждом направлении существует одна структура ребер. Это означает, что если у вас есть вершины A и B, то где-то хранятся две структуры ребер: одна для A-> B и одна для B-> A. Каждое ребро имеет 3 указателя, один из которых называется предыдущим, один называется следующим и один называется двойником. Следуя за указателями следующего и предыдущего, вы проведете вас по краям треугольника или многоугольника в сетке. Вызов близнеца приведет вас к соседнему краю в соседнем многоугольнике или треугольнике. (Посмотрите на стрелки на рисунке). Это самая полезная и многословная структура данных из всех известных мне. Я использовал его для сглаживания сетки, создавая новые ребра и обновляя указатели. Кстати, каждое ребро также должно указывать на вершину, чтобы она знала, где она находится в пространстве.

5 голосов
/ 19 февраля 2010

На самом деле ваш вопрос состоит из трех частей, а не двух:

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

Вы должны задать дополнительные вопросы, чтобы найти соответствующие ответы.

Какие структуры данных следует использовать для представления сетки?

Какие типы элементов вам нужно обрабатывать?

Если вам нужно обрабатывать только многоугольники (замкнутые циклы) и симплициалы (каждый узел связан с каждым другим узлом в элементе, таким как тетраэдр), тогда упорядоченный список узлов достаточен, поскольку из списка могут быть выведены ребра узлов. Если, с другой стороны, вам нужно обрабатывать типы элементов, такие как шестигранники, призмы или общие многогранники, вам потребуется дополнительная информация о топологии элементов. Простого массива отображений ребер часто бывает достаточно. Это просто массив [] [2] индексов в списке узлов элемента, который говорит вам, как соединить точки для данного типа элемента.

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

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

Какой алгоритм использовать для извлечения ребер из элементов?

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

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

Как мне представить результаты?

Какое значение имеет то, как я буду использовать результат?

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

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

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

1 голос
/ 19 февраля 2010

У меня нет алгоритмов для вас, но я могу сказать вам, где искать.

"Триангуляция точечного набора" - это то, что вы ищете.

Вот несколько библиотек с открытым исходным кодом, которые сделают это за вас (используйте код для алгоритмов):

...