Алгоритм однозначного поиска ребер из полигональной сетки

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

У меня есть работающая версия, но производительность падает при достижении более 500 000 полигонов. Моя версия проходит по каждой грани и добавляет отсортированные вершины каждого ребра в stl :: set. Мой набор данных будет в основном состоять из треугольников и четырехугольников, и большинство ребер будут общими.

Есть ли для этого более умный алгоритм?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
4 620
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Чтобы прояснить, вы хотите, чтобы список многоугольников был таким:

A +-----+ B
   \    |\
    \ 1 | \
     \  |  \
      \ | 2 \
       \|    \
      C +-----+ D

Тогда вместо ребер вроде этого:

A - B -+
B - C  +- first polygon
C - A -+

B - D -+
D - C  +- second polygon
C - B -+

тогда вы хотите удалить дублирующуюся кромку B - C и C - B и поделиться ею?

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

Ответ принят как подходящий

Да Используйте двойную хеш-карту. Каждое ребро имеет два индекса A, B. допустим, что A> B.
Первая хэш-карта верхнего уровня сопоставляет A с другой хеш-картой, которая, в свою очередь, сопоставляет B с некоторым значением, которое представляет информацию, которую вы хотите получить о каждом ребре. (или просто bool, если вам не нужно хранить информацию для ребер) .
По сути, это создает двухуровневое дерево, состоящее из хэш-карт.

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

Если я правильно понимаю, вы получите уникальную хэш-карту первого уровня, но с большим количеством хэш-карт уровня 2 (по одной для каждого значения A). Интересно, действительно ли помогают хэш-карты уровня 2 °, достаточно ли значений B на этих вторых хэш-картах?

labotsirc 28.09.2011 17:35

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

Общее количество ребер будет от N / 2 до N. N - количество уникальных вершин в сетке. Все общие ребра будут N / 2, а все уникальные ребра будут N. Оттуда я выделяю буфер из uint64 и упаковываю свои индексы в эти значения. Используя небольшой набор уникальных таблиц, я могу быстро найти уникальные края!

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

typedef std::pair<int, int> Edge;

Edge sampleEdge;

std::map<Edge, bool> uniqueEdges;

Ребро содержит индексы вершин, составляющих ребро в отсортированном порядке. Следовательно, если sampleEdge - это ребро, составленное из вершин с номерами индексов 12 и 5, sampleEdge.first = 5 и sampleEdge.12.

Тогда ты можешь просто сделать

uniqueEdges[sampleEdge] = true;

для всех краев. uniqueEdges будет содержать все уникальные края.

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

http://gitorious.org/blenderprojects/blender/blobs/master/blender/source/blender/blenlib/intern/edgehash.c

http://gitorious.org/blenderprojects/blender/blobs/master/blender/source/blender/blenlib/BLI_edgehash.h

Это использует BLI_mempool, https://gitorious.org/blenderprojects/blender/blobs/master/blender/source/blender/blenlib/intern/BLI_mempool.c

https://gitorious.org/blenderprojects/blender/blobs/master/blender/source/blender/blenlib/BLI_mempool.h

Другие вопросы по теме