Як визначити, чи ефективна герметизація кімнати на основі 3D-вокселів


10

У мене виникли проблеми з ефективним визначенням того, чи великі приміщення запечатані в 3D-кімнатах на основі вокселів. Я в той момент, коли я намагався найсильніше вирішити проблему, не просячи допомоги, але недостатньо намагався відмовитись, тому я прошу допомоги.

Щоб уточнити, запечатано те, що в кімнаті немає дірок. Є кисневі ущільнювачі, які перевіряють, чи приміщення герметичне, і герметизують залежно від рівня введення кисню.

Зараз я це роблю:

  • Починаючи з блоку над плиткою ущільнювача (вентиляційний отвір знаходиться на верхній стороні ущільнювача), рекурсивно прокручуємо через усі 6 суміжних напрямків
  • Якщо сусідня плитка - це повна, не вакуумна плитка, продовжуйте через петлю
  • Якщо сусідня плитка не є повною чи вакуумною плиткою, перевірте, чи є сусідні блоки, рекурсивно.
  • Кожен раз, коли перевіряється плитка, зменшуйте лічильник
  • Якщо кількість досягне нуля, якщо останній блок примикає до вакуумної плитки, поверніться, що область не запечатана
  • Якщо підрахунок дорівнює нулю, а останній блок не є вакуумною плиткою, або рекурсивний цикл закінчується (не залишається вакуумних плиток) до лічильника дорівнює нулю, область запечатується

Якщо область не запечатана, запустіть цикл знову з деякими змінами:

  • Перевірка сусідніх блоків на плитку "дихаючого повітря" замість вакуумної плитки
  • Замість використання лічильника, що зменшується, продовжуйте, поки не знайдеться сусідня плитка "дихаючого повітря".
  • Після завершення циклу встановіть кожен перевірений блок на вакуумну плитку.

Ось код, який я використовую: http://pastebin.com/NimyKncC

Проблема:

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

Мені було цікаво, чи може хтось із більшим досвідом оптимізації подати мені руку чи принаймні вказати на мене в правильному напрямку. Дякую купу.


Тільки перевірка, коли зміниться, стала би початком. Перевірка кожні три секунди здається непосильною, оскільки ви знаєте, коли змінюються вокселі, які можуть зламати печатку. Якщо змінено воксель, що складається із запечатаної кімнати, ви можете позначити цю кімнату для повторної перевірки, інакше не турбуйтеся.
MichaelHouse

Оскільки в 3-секундному часовому інтервалі може бути змінено сотні вокселів, я вважав, що було б ефективніше просто робити це періодично, а не перевіряти, чи щось змінилося поблизу. Я буду експериментувати з цим, хоча.
NigelMan1010

О, добре, якщо сотні вокселів можуть змінитися за три секунди, у вас, швидше за все, виникне ряд проблем із продуктивністю. Почніть з профілювання свого коду, щоб знайти неефективність. Удачі!
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.