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


10

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

Чтобы выяснить, запечатано, что в комнате нет дыр. Есть кислородные упаковщики, которые проверяют, запечатана ли комната, и запечатывают в зависимости от уровня входного кислорода.

Прямо сейчас, вот как я это делаю:

  • Начиная с блока над плиткой герметика (вентиляционное отверстие находится на верхней поверхности герметика), рекурсивно проходите по всем 6 смежным направлениям
  • Если соседняя плитка является полной, не вакуумной плиткой, продолжайте цикл
  • Если соседняя плитка не заполнена или является вакуумной плиткой, проверьте, рекурсивно ли соседние блоки.
  • Каждый раз, когда проверяется тайл, уменьшайте счетчик
  • Если число достигает нуля, если последний блок находится рядом с вакуумной плиткой, верните, что область незапечатана
  • Если счетчик достигает нуля, а последний блок не является вакуумным тайлом или рекурсивный цикл завершается (вакуумных тайлов не осталось) до того, как счетчик станет нулевым, область будет запечатана

Если область не запечатана, запустите цикл снова с некоторыми изменениями:

  • Проверка соседних блоков на «воздухопроницаемую» плитку вместо вакуумной плитки
  • Вместо использования уменьшающегося счетчика продолжайте, пока не будут найдены соседние плитки «дышащий воздух».
  • После завершения цикла установите каждый отмеченный блок на вакуумную плитку.

Вот код, который я использую: http://pastebin.com/NimyKncC

Проблема:

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

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


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

Поскольку в течение этого 3-секундного периода времени могут быть изменены сотни вокселей, я подумал, что будет эффективнее просто делать это периодически, а не проверять, не изменилось ли что-то поблизости. Я буду экспериментировать с этим, хотя.
NigelMan1010

О, хорошо, если сотни вокселей могут измениться за 3 секунды, у вас, вероятно, будет ряд проблем с производительностью. Начните профилировать ваш код, чтобы найти недостатки. Удачи!
MichaelHouse

Ответы:


3

Лучшее решение будет зависеть от нескольких факторов, таких как ожидаемый размер комнаты.

  1. Делайте эту проверку только тогда, когда что-то действительно меняется.

Подход 1:

Вы можете использовать A *, чтобы найти путь от вентиляционного отверстия к плитке над вентиляционным отверстием / самим вентиляционным отверстием или к плитке, известной как вакуум. Если путь найден, комната не запечатана. Это не так сильно отличается от вашего текущего подхода, но должно быть быстрее. Найдя, сделайте «заливку», чтобы установить плитки как вакуум.

Подход 2:

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


0

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

И, как сказал Byte56, вы должны также проверять утечки только тогда, когда все меняется. Это может значительно минимизировать объем работы, которую вы выполняете, в зависимости от того, как часто происходят изменения. Вы даже можете кэшировать информацию между последовательными вызовами алгоритма, что может упростить вычисление, которое вы выполняете после первого вызова.

Редактировать:

Я посмотрел на некоторые из вашего кода. Похоже, вы используете LinkedList, чтобы указать, проверен ли уже воксель, как в моем первом абзаце. У вас могут быть лучшие результаты, если вы используете для этого что-то отличное от LinkedList. Возможно, попробуйте HashSet или что-то? Это должно уменьшить сложность вашего метода проверки с O (n) до O (1).


Да, я добавляю его в LinkedList с именем «флажок», а затем проверяю, содержит ли этот список позицию, перед проверкой. Я подумал, что проверка того, что что-то изменилось, также будет чрезвычайно ресурсоемкой, поскольку сотни вокселей могли измениться за этот 3-секундный период времени. Я посмотрю, как хешсет сравнивается со списком ссылок в этой ситуации, спасибо.
NigelMan1010
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.