Алгоритм маркировки края треугольной сетки

Введение

В рамках более крупной программы (связанной с визуализацией объемной графики), У меня есть небольшая, но сложная подзадача, в которой произвольная (но конечная) треугольная 2D-сетка должна быть помечена определенным образом. Уже некоторое время назад я написал решение (см. Ниже), которое было достаточно хорошим для тестовых сеток, которые у меня были в то время, хотя я понимал, что этот подход, вероятно, не будет работать очень хорошо для каждой возможной сетки, о которой можно было подумать. Теперь я наконец столкнулся с сеткой, для которой настоящее решение не работает так хорошо, и похоже, что я должен предложить совершенно другой подход. К сожалению, мне кажется, что я не могу полностью изменить свое мышление, поэтому я подумал, что спрошу здесь.

Проблема

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

Для каждого треугольника (например, оранжевого ABC и зеленого ABD) каждому из трех ребер нужно присвоить одну из двух меток, например «0» или « 1 ". Есть всего два требования:

  1. Не все стороны треугольника могут иметь одинаковую метку. Другими словами, для каждого треугольника должно быть два «0» и одна «1», или , две «1» и один «0».
  2. Если ребро является общим для двух треугольников , он должен иметь одинаковый ярлык для обоих. Другими словами, если ребро AB на картинке помечено «0» для треугольника ABC, оно должно быть помечено «0» и для ABD.

Сетка является настоящей 2D-сеткой, и она конечна: т.е. , он не оборачивается и имеет четко определенную внешнюю границу. Очевидно, на границе удовлетворить требования довольно легко, но внутри становится все труднее.

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

Текущее решение

Мое текущее решение является действительно методом грубой силы (предоставлено здесь только для полноты - не стесняйтесь пропустить этот раздел ):

  • Сохраните четыре набора треугольников - по одному на каждое возможное количество (0..3) ребер, которые нужно пометить. Вначале каждый треугольник входит в набор, в котором еще три ребра нужно пометить.
  • Пока существуют треугольники с немаркированными ребрами:
    Найдите наименьшее ненулевое количество нераспределенных ребер, для которых существует остались еще треугольники. Другими словами: в любой момент времени мы стараемся минимизировать количество треугольников, для которых разметка была частично завершена. Количество оставшихся рёбер будет любым от 1 до 3. Затем просто выберите один такой треугольник с этим определенным количеством рёбер, которые нужно выделить. Для этого треугольника сделайте следующее:
    • Посмотрите, не наложена ли маркировка любого оставшегося края маркировкой другого треугольника. Если да, присвойте метки, как это подразумевается в требовании № 2 выше.
    • Если это приводит к тупику (т. Е. Требование № 1 больше не может быть удовлетворено для текущего треугольника), то запускается на всем процессе с самого начала .
    • Распределите оставшиеся ребра следующим образом:
      • Если до сих пор ни одно ребро не было помечено, назначьте первое из них случайным образом.
      • Когда одно ребро уже выделено, назначьте второе, чтобы оно имело противоположную метку.
      • Когда два ребра назначены: если они иметь такую ​​же метку, присвоить третьей метку противоположную (очевидно); если два имеют разные метки, назначьте третий случайным образом.
    • Обновите наборы треугольников для разного количества нераспределенных ребер.
  • Если мы когда-нибудь доберемся сюда, то у нас есть решение - ура!

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


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

Спасибо, что дочитали до этого места. Мы будем очень благодарны за любую помощь!



Edit: Результаты, основанные на предлагаемых решениях

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

Спасибо, что дочитали до этого места. Мы будем очень благодарны за любую помощь!



Edit: Результаты, основанные на предлагаемых решениях

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

Спасибо, что дочитали до этого места. Мы будем очень благодарны за любую помощь!



Edit: Результаты, основанные на предлагаемых решениях

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

Спасибо, что дочитали до этого места. Мы будем очень благодарны за любую помощь!



Edit: Результаты, основанные на предлагаемых решениях

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

Спасибо, что дочитали до этого места. Мы будем очень благодарны за любую помощь!



Edit: Результаты, основанные на предлагаемых решениях

К сожалению, я не могу заставить подход, предложенный Dialecticus , работать. Возможно, я не понял ... В любом случае, рассмотрим следующую сетку, начальная точка которой обозначена зеленой точкой: Я не могу заставить подход, предложенный Диалектиком , работать. Возможно, я не понял ... В любом случае, рассмотрим следующую сетку, начальная точка которой обозначена зеленой точкой: Я не могу заставить подход, предложенный Диалектиком , работать. Возможно, я не понял ... В любом случае, рассмотрим следующую сетку, начальная точка которой обозначена зеленой точкой: Давайте немного увеличим масштаб ... Теперь приступим к алгоритму. После первого шага маркировка выглядит следующим образом (красный = "пути, отмеченные звездочкой", синий = "пути, отмеченные кольцами"): Все идет нормально. После второго шага: И третий: ... четвертый: Но теперь у нас проблема! Давайте сделаем еще один раунд, но обратите внимание на треугольник, нарисованный пурпурным цветом: Согласно моей текущей реализации, все края пурпурного треугольника находятся на кольцевой траектории, поэтому они должны быть синими, что фактически делает это контрпримером. Возможно, я как-то ошибся ... Но в любом случае два ребра, ближайшие к начальному узлу, очевидно, не могут быть красными; а если третий помечен красным, то кажется, что решение больше не соответствует этой идее.

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

  1. Индекс первого узла
  2. Индекс второго узла
  3. x координата первого узла
  4. y координата первый узел
  5. x координата второго узла
  6. y координата второго узла

Начальным узлом является тот, который имеет индекс 1.


Думаю, что в следующий раз мне следует попробовать метод, предложенный Рафалом Даугирдом ... Но, возможно, мне следует сделать что-то совсем другое на время :)

15
задан TylerH 3 March 2019 в 20:39
поделиться