Обертання точки щодо іншої точки (2D)


139

Я намагаюсь зробити карткову гру, де картки розбиваються. Прямо зараз, щоб відобразити його Im, використовуючи API Allegro, який має функцію:

al_draw_rotated_bitmap(OBJECT_TO_ROTATE,CENTER_X,CENTER_Y,X
        ,Y,DEGREES_TO_ROTATE_IN_RADIANS);

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

наприклад, 4 пункти картки:

card.x

card.y

card.x + card.width

card.y + card.height

Мені потрібна така функція, як:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
}

Дякую

Відповіді:


331

Спочатку відніміть точку (cx,cy)повороту, потім оберніть її, а потім додайте крапку ще раз.

Не перевірено:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
  float s = sin(angle);
  float c = cos(angle);

  // translate point back to origin:
  p.x -= cx;
  p.y -= cy;

  // rotate point
  float xnew = p.x * c - p.y * s;
  float ynew = p.x * s + p.y * c;

  // translate point back:
  p.x = xnew + cx;
  p.y = ynew + cy;
  return p;
}

45
Відмінна відповідь. Для запису ви встановили правильність обертання з першого разу.
n.collins

@synchronizer точно так само, просто використовуйте підпрограми віднімання / додавання точок та свою матричну функцію вектор * для обертання.
Нілс Піпенбрінк

8
Може бути корисним для необережних згадати, що гріх і cos можуть очікувати вираження кута в радіанах.
15ee8f99-57ff-4f92-890c-b56153

72

Якщо повернути точку (px, py)навколо точки (ox, oy)на кут тета, ви отримаєте:

p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox

p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy

це простий спосіб повернути точку в 2D.


7
Вам потрібно перевести назад після обертання. тож рішенням було б: p'x + = ox
hAlE

57

Система координат на екрані ліворуч, тобто координата x збільшується зліва направо, а y координата збільшується зверху вниз. Походження, O (0, 0) знаходиться у лівому верхньому куті екрана.

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

За годинниковою стрілкою , обертання навколо початку координат точки з координатами (х, у) задається наступними рівняннями:

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

де (x ', y') - координати точки після обертання і кута тета, кут повороту (повинен бути в радіанах, тобто помножений на: PI / 180).

Для здійснення обертання навколо точки, відмінної від початку O (0,0), скажімо, точка A (a, b) (точка зсуву). По-перше, ми переводимо точку, яку слід обертати, тобто (x, y) назад до початку, віднімаючи координати точки повороту, (x - a, y - b). Потім виконуємо обертання і отримуємо нові координати (x ', y') і, нарешті, переводимо крапку назад, додаючи координати точки повороту до нових координат (x '+ a, y' + b).

Дотримуючись вищеописаного опису:

2D тета градусів обертання точки (x, y) навколо точки (a, b) дорівнює:

Використання прототипу вашої функції: (x, y) -> (px, py); (a, b) -> (cx, cy); theta -> кут:

POINT rotate_point(float cx, float cy, float angle, POINT p){

     return POINT(cos(angle) * (p.x - cx) - sin(angle) * (p.y - cy) + cx,
                  sin(angle) * (p.x - cx) + cos(angle) * (p.y - cy) + cy);
}

29
float s = sin(angle); // angle is in radians
float c = cos(angle); // angle is in radians

Для обертання за годинниковою стрілкою:

float xnew = p.x * c + p.y * s;
float ynew = -p.x * s + p.y * c;

Для обертання проти годинникової стрілки:

float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;

Що cі s?
TankorSmash

1
@TankorSmash його визначено вищеc = cos(angle)
nycynik

2

Це відповідь Нілса Піпенбринка, але реалізована в c # скрипці.

https://dotnetfiddle.net/btmjlG

using System;

public class Program
{
    public static void Main()
    {   
        var angle = 180 * Math.PI/180;
        Console.WriteLine(rotate_point(0,0,angle,new Point{X=10, Y=10}).Print());
    }

    static Point rotate_point(double cx, double cy, double angle, Point p)
    {
        double s = Math.Sin(angle);
        double c = Math.Cos(angle);
        // translate point back to origin:
        p.X -= cx;
        p.Y -= cy;
        // rotate point
        double Xnew = p.X * c - p.Y * s;
        double Ynew = p.X * s + p.Y * c;
        // translate point back:
        p.X = Xnew + cx;
        p.Y = Ynew + cy;
        return p;
    }

    class Point
    {
        public double X;
        public double Y;

        public string Print(){
            return $"{X},{Y}";
        }
    }
}

Ps: Мабуть, я не можу коментувати, тому я зобов'язаний розмістити це як відповідь ...

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