Pisząc projekt, o którym niebawem opowiem, napotkałem trudność. Potrzebowałem rysować prymitywy poddane rotacji. Niestety framework w którym pisze nie załatwił tego za mnie, więc problem musiałem rozwiązać sam. Pokażę dziś jak obliczyć pozycję punktu, po rotacji pod kątem alfa, względem danego punktu.
Sytuację przedstawia poniższy rysunek:

Potrzebujemy obliczyć pozycję punktu B, mając dany punkt A, S oraz kąt Alfa. Literkami a oraz b oznaczone są wektory, które wskazują na punkty A i B względem punktu S. Długości wektorów a oraz b są takie same.
Zacząć musimy od obliczenia kąta Beta. Beta jest to kąt pomiędzy wektorem a a półprostą zaczynającą się w punkcie S, o stałej wartości Y i rosnącym Xie. Potrzebujemy Betę aby móc skorzystać w prosty sposób z definicji sinusa oraz cosinusa.
Na początek warto obliczyć współrzędne wektorów, aby potem w prosty sposób z nich korzystać.
Aby obliczyć kąt beta, może,y stworzyć wektor pomocniczy oznaczony literką t, o początku w punkcie S i tmp. Wartość x wektora t może być dowolna dodatnia, ja wybrałem 2, żeby było coś widać na rysunku. Następnie opierając się na moim poprzednim wpisie, obliczmy kąt pomiędzy wektorem pomocniczym a a.
)
Gdy obliczyliśmy już kąt beta nic nie stoi na przeszkodzie, aby obliczyć gamma.

Dobrze, kolejnym krokiem będzie utworzenie kolejnego wektora pomocniczego. Oznaczymy go literką c. Wektor ten będzie mieć taki sam zwrot i kierunek jak poprzedni wektor pomocniczy t, lecz jego długość będzie taka sama jak wektora a oraz b. Czyli:

Mając obliczony wektor c możemy obliczyć x i y, opisujące punkt B. Aby je obliczyć, posłużymy się wzorem na sinus oraz cosinus w układzie współrzędnych.


x, y są to współrzędne punktu. r jest to odległość od środka układu(u nas punkt S) do tego punktu, więc r jest po prostu równe długości wektora. Zamiast kąta alfa posłużymy się kątem gamma. Czyli


Punkt B jest równy (Sx + x, Sy + y).
Zdaje sobie sprawę, że trochę to pogmatwałem, lecz mam nadzieję, że kod źródłowy i przykład do niego dołączony ułatwi zrozumienie tego.
#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
#include <iomanip>
using namespace std;
struct Point
{
double x, y;
};
struct Vector2
{
double x, y;
};
double deg(double rad) // Zamień radiany na stopnie
{
return rad/M_PI*180;
}
double rad(double deg) // Zamień stopnie na radiany
{
return deg*M_PI/180;
}
double angle(Vector2 a, Vector2 b) // oblicz kąt pomiędzy wektorami
{
return acos ( (a.x * b.x + a.y * b.y) / ( sqrt( pow(a.x, 2) + pow(a.y, 2) ) * sqrt( pow(b.x, 2) + pow(b.y, 2) )) );;
}
Point rotate(Point A, Point S, double alpha) // oblicz kąt pomiędzy wektorami
{
Point B;// szukany punkt
if(A.x == S.x && A.y == S.y)
return A;
Vector2 a, b; // wektory a i b
a.x = A.x - S.x;
a.y = A.y - S.y;
double r = sqrt(pow(a.x, 2) + pow(a.y, 2)); // długość wektora a
Point tmp; tmp.x = S.x+1; tmp.y = S.y; // punkt pomocniczy
Vector2 t; // wektor pomocniczy
t.x = 2; // zapis troszkę sktócony
t.y = 0;
double beta = angle(a, t); // kąt pomiędzy wektorami a i t
double gamma = beta + alpha;// kąt pomiędzy wektoami a i b
Vector2 c; // kolejny wektor pomocniczny(dla zobrazowania)
c.x = r;
c.y = 0;
b.x = cos(gamma) * r;// C.x
b.y = sin(gamma) * r;
// oblicz pozycję B mając dany wektor b i punkt S
B.x = S.x + b.x;
B.y =S.y + b.y;
return B;
}
int main()
{
Point a, s;
double alfa;
// Wejście:
// Ax Ay Sx Sy Alfa
// Wyjście:
// Bx By
while(cin>>a.x>>a.y>>s.x>>s.y>>alfa)
{
Point b = rotate(a, s, rad(alfa));// oblicz pozycje punktu B
cout<<fixed <<b.x<<" "<<b.y<<" "<<endl; // Wypisz pozycje punktu B
}
return 0;
}
in:
2 8 1 2 180
2 8 1 2 45
10 10 5 5 180
5 5 -1 -1 360
3 3 1 1 90
5 5 0 0 45
out:
-0.000000 -4.000000
-2.535534 6.949747
-0.000000 0.000000
5.000000 5.000000
-1.000000 3.000000
0.000000 7.071068
Przetestuj online
Rotacja obiektów
Poddawaliśmy rotacji względem punktu pojedyncze punkty. Jak sprawa się ma przy obiektach, takich jak trójkąty/kwadraty? Zadziwiająco prosto. Wystarczy poddać takiej samej rotacji każdy punkt obiektu.