Як я можу визначити, чи об’єкт рухається CW або CCW навколо пов'язаного шляху?


19

Скажемо, ми маємо зубчасту форму:

форма0

І дві істоти, що рухаються по його контуру.

Потім повністю розгладжуємо форму, витягуючи куточки.

Ми отримуємо це:

гладкий

Неважко зараз помітити, що Orange рухається CW та зеленим CCW. Як я можу сказати, в якому напрямку вони рухаються, не згладжуючи форму?

Новий образ

введіть тут опис зображення


Ось мої 2 копійки: i.imgur.com/zrBdw.png
Kendall Frey

Відповіді:


27

Намалюйте лінію до нескінченності та порахуйте, скільки разів ви перетнете фігуру (парну чи непарну), не рахуючи відрізка, де лежить істота. Потім перевірте, чи істота йде ліворуч або праворуч від цієї лінії.

приклад

У цьому прикладі ми перетинаємо форму двічі (так рівно) і йдемо ліворуч. Результат одразу з цієї таблиці:

   # Crosses | even  | odd
  Direction  |       |
-------------+-------+------
    left     | CCW   |  CW
    right    |  CW   | CCW

У псевдокоді:

x, y = position of creature
vx, vy = direction of creature movement
crossings = 0
for each x1, y1, x2, y2 in shape segments:
    if (x1 < x and x <= x2) or (x2 < x and x <= x1):
        if y - y1 > (x - x1) * (y2 - y1) / (x2 - x1):
            ++crossings
if (crossings & 1) == (vx < 0):
    return CW
else
    return CCW

ви включаєте створіння лінії, що рухається далі?
Ali1S232

@Gajoo: ні, отже> замість> = у рядку 6. Я додам про це примітку. Але зауважте, що ви можете включити рядок і просто перевернути вміст таблиці.
sam hocevar

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

@TrevorPowell True. Пошук найдальшого краю може бути заплутаним. Я перевірив спочатку на основі найвіддаленішої вершини краю, а потім прокреслив лінію від центру фігури та через два центри ребер (два, які поділяють вершину) і побачив, чи одна з ліній перетинає інший край на шляху до нескінченність після перетину одного з цих країв. Все вийшло добре
вовчий світанок

5

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


Набагато простіше рішення, а також моя перша думка.
Amplify91

як ти знаєш, який напрямок знаходиться всередині форми? Я маю на увазі рух по краю всередині форми або зліва, або справа. як ти знаєш, в який спосіб це?
Ali1S232

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

4
  1. Обчисліть центральну точку своєї форми.
  2. Виберіть найдаліший край своєї форми від центру.
    • (Підбір найвіддаленішого краю гарантує, що ви не починаєте з перевернутої, увігнутої частини форми, що призведе до того, що ви отримаєте визначення за годинниковою стрілкою / проти годинникової стрілки назад на всю форму)
  3. Визначте, який напрямок уздовж цього краю знаходиться за годинниковою стрілкою
    • (Проста реалізація цього передбачає порівняння кутів від центру фігури до кожного кінця вибраного краю. Знак різниці кутів підкаже вашій та проти годинникової стрілки)
  4. Повторіть всі краї фігури, починаючи з краю, який ви вибрали на кроці 2, склавши список країв. Для кожного краю зберігайте дві його вершини в порядку годинникової стрілки.
    • (Якщо ваша форма не змінюється з часом, ви можете зберігати цей крайовий список для подальшого використання, тому вам не доведеться робити перші чотири кроки кожен кадр)
    • (у вас вже може бути список ребер. Якщо так, ви можете зберігати цей порядок вершин за годинниковою стрілкою в тому самому списку.)
  5. Щоб визначити, чи сутність рухається за годинниковою або проти годинникової стрілки:
    • Визначте, по якому краю сутність рухається вздовж.
    • Зробіть крапковий добуток напрямку руху сутності проти вектора від початку цього вершини за годинниковою стрілкою -> кінцеві вершини, які ви визначили ще на кроці 4.
    • Якщо результатом крапкового добутку є значення, що перевищує нуль, сутність рухається за годинниковою стрілкою. Менше нуля означає проти годинникової стрілки.

Дуже розумна відповідь
вовчі світанки

У мене є невелике запитання? якщо припустити, що вершини у його формі нумеруються, починаючи з самої лівої точки CWW, виходячи з вашої відповіді, як я можу сказати, якщо рух від 6-> 7 або 9-> 10 (на нулі) рухається за годинниковою стрілкою?
Ali1S232

Ви починаєте з найвіддаленішого краю і з’ясовуєте, який шлях знаходиться за годинниковою стрілкою на цьому краю. Скажімо, що край A знаходиться за годинниковою стрілкою від вершини 'a' до 'b'. Тоді, якщо ми переходимо до краю B (який має вершини 'b' і 'c'), ми знаємо, що B знаходиться за годинниковою стрілкою від 'b' до 'c'. Аналогічно, край C буде за годинниковою стрілкою від 'c' до 'd'. Як тільки ми знаємо правильний напрямок за годинниковою стрілкою від одного краю (кроки 1-3), продовжуючи його в напрямку за годинниковою стрілкою навколо країв форми, ми можемо вивести правильний напрямок 'за годинниковою стрілкою' для кожного краю, не дивлячись фактично, де розташовані його краї, тому увігнутість нормальна.
Тревор Пауелл

як можна визначити, чи край A знаходиться за годинниковою стрілкою від 'a' до 'b' або якщо він за годинниковою стрілкою від 'b' до 'a'? Я думаю, ти пропустив цю частину.
Ali1S232

@Gajoo Це кругла думка на кроці 3. Напевно, це не повинно бути дужкою, оскільки це дійсно критичний крок усього процесу.
Тревор Пауелл

2

Вам потрібно знати, яким шляхом визначений багатокутник, яким шляхом вершини обходять його.

Якщо ви цього не знаєте, ви можете це обробити, обчисливши площу багатокутника:

float Polygon::area() {
    float result = 0.0f;

    for(int a = 0; a < vertexCount; a ++) {
        int b = (a+1) % vertexCount;
        result += vertices[a].x * vertices[b].y;
        result -= vertices[a].y * vertices[b].x;
    }

    return result * .5f;
}

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

Якщо форма за годинниковою стрілкою:

  • Істота, що йде вперед навколо форми, йде за годинниковою стрілкою , і
  • Істота, що йде назад навколо форми, йде проти годинникової стрілки .

Якщо форма проти годинникової стрілки:

  • Істота, що йде вперед навколо форми, йде проти годинникової стрілки , і
  • Істота, що йде назад навколо форми, йде за годинниковою стрілкою .

0

Здається, Тревор уже висвітлював це питання, але ось моє рішення:

  1. обчислити площу, яку охоплює ваша форма, тобто

    area = 0
    foreach (edge in shape)
        area += edge.begin.x * edge.end.y - edge.begin.y * edge.end.x
  2. Використовуючи обчислену вище область, ви можете легко визначити, сама форма є за годинниковою стрілкою чи ні. це за годинниковою стрілкою, лише якщо площа нижче нуля.

  3. перевірте, чи об’єкт (и) рухаються так само, як вершини в порядку або у зворотному напрямку.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.