Як знайти 2D комірки сітки, змітані рухомим колом?


9

Я роблю гру на основі 2D сітки, де деякі клітини прохідні, а деякі ні. Динамічні об'єкти можуть рухатися безперервно, незалежно від сітки, але потрібно стикатися з непрохідними осередками.

Я написав алгоритм простеження променя на сітці, який дає мені всі клітини, що промінь перетинається. Однак фактичний об'єкт не має точкових розмірів; Зараз я представляю їх як кола. Але я не можу розробити ефективний алгоритм для відстеження рухомого кола. Ось малюнок того, що мені потрібно: введіть тут опис зображення

Цифри показують, в якому порядку коло стикається з осередками сітки. Хтось знає алгоритм пошуку цих зіткнень? Переважно в C #.

Оновити коло може бути більшим, ніж одна комірка сітки.


ммх, чому 3 стикаються ДО 4?
FxIII

@FxIII Я насправді перемістив коло на малюнку, і він потрапив 3 до 4. Лише ледь, але все-таки раніше.
Nevermind

Відповіді:


6

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

Нехай C - ваш центр, а r радіус, тому P ' = C + ( r , 0) і P " = C + (0, r).

Якщо D - ваш напрямок вектора (у порівнянні), у вас є дві лінії:

R '= D · t + P' ,

R "= D · t + P"

Вам просто потрібно знайти перетин цих прямих з лініями рівняння:

y = i і y = i - це краї вашої сітки!

Рішення просте, тому що ви повинні просто розглянути x або y компонент R 'і R ". Ви знайдете значення t s для кожного вставки, а точки для tose t s, просто сортуйте ці точки за t і ви зроблені.

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

Це працює, якщо r <1 (ширина та висота комірки).

Він працює і для інших випадків, просто замислюючись про P ' і P " . Ми вибираємо TOP і LEFT через напрямок, BOTTOM і RIGHT слід вважати для протилежного напрямку, ви розумієте, чому.

А тепер подивіться на це зображення: велике коло

Коло більше, ніж одна клітинка, і ми припускаємо, що воно йде в тому ж напрямку, що і ваш малюнок. Р1 - перша точка, яка торкнеться, Р2 - друга, Р3 - марна, оскільки знаходиться в нижній половині. Що вам потрібно зробити, це викинути промені від P1 і P2, як ми бачили раніше, і зробити те ж саме для вертикальних ліній.

Як правило, у вас будуть інші вихідні точки разом з ТОП та ЛІВОМИ, звідки стріляти вашими променями, чим більше коло, тим більше променів.

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


Так, я придумав точки P 'і P ", але не міг зрозуміти, що робити, коли коло більше однієї комірки. Додаткові точки дійсно мають сенс (і я, очевидно, потрібно лише додавати промені між P' і П ")
Nevermind

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

Чи зрозуміло, що вам потрібно перевірити горизонтальні та вертикальні лінії сітки окремо?
FxIII

Я думаю, ви також повинні перевірити, коли коло охоплює вершину сітки, тому що коло буде стикатися з діагонально-сусідньою коміркою на її куті, але це необов'язково буде верхньою / лівою / нижньою / правою точкою на колі, яке спочатку торкається її. (і ви зіткнетесь зіткнення занадто рано.) Приклад: квадрати 3,4,5 на прикладі діаграми у питанні. Вони потрапляють у порядку (3, то 4, то 5), але ваш алгоритм визначатиме 4 та 5 одночасно.
finnw

@finnw вони торкаються одночасно лише в тому випадку, якщо цикл рухається точно в бісектрисі.
FxIII

1

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

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


8 променів, ймовірно, гарантують усі перехрестя, але вони не дадуть їх у правильному порядку. А для зіткнень мені потрібен порядок, а не лише список комірок.
Nevermind

Додайте алгоритм зіткнення променів, щоб зберегти значення t для кожного зіткнення. Коли ви отримуєте об'єднання комірок, ви можете сортувати за t-значення, щоб отримати правильний порядок.
TreDubZedd

Але як я можу порівняти t-значення різних променів?
Nevermind

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

1
Можливо, вам вдасться піти лише з двома променями на сторонах кола, перпендикулярних руху, тоді ви можете побачити, які плитки потрапляють під промені, а ви можете перевірити решту, щоб побачити, чи потрапляють їх центри між двома променями. Єдине, що слід пропустити, - це речі, що стикаються на початку або в кінці кола, але це всього два кола, і з ними можна легко впоратися. Це може бути трохи повільніше, ніж вісім променів, я не впевнений; але вам не потрібно масштабувати число на основі розміру кола.
Лунін

1

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


Я над цим теж думав, але це, на мою думку, це не правильний алгоритм. Брезенхем вибирає лише один піксель, йому потрібні всі. І було б важко пристосувати бресенхам до кола, що мав би лише один піксель.
zacharmarz

Я використовую промінь-відстежувач насправді свого роду на основі алгоритму Брезенхама. У мене виникають труднощі з узагальненням його від тонкої лінії до "жирної", зокрема кругової.
Nevermind
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.