Operacje na wektorach

gringoM

Wektory 2D

Wektor dwuwymiarowy to nic innego, jak przyporządkowana para liczb często z wiadomych przyczyn nazywana "x" i "y".

W C++ WinApi dostępna jest struktura, którą można nazwać namiastką wektora, a nazywa się ona POINT, jednak dla umożliwienia pełnego wykorzystania operacji wektorowych lepiej napisać własną klasę, która mogła by wyglądać następująco:

class dPoint{
public:
double x;
double y;
};

Podstawowe operacje wektorowe

dwa wektory V1 i V2 można dodawać do siebie w następujący sposób otrzymując wektor V3:

V3.x = V1.x + V2.x;
V3.y = V1.y + V2.y;

analogicznie odejmowanie

V3.x = V1.x - V2.x;
V3.x = V1.y - V2.y;

mnożenie wektora przez stałą wartość k nazywa się skalowaniem wektora i pozwala na zmianę jego długości danego wektora przy zachowaniu kąta jego położenia.

V1.x *= k;
V1.y *= k;

Długość wektora oblicza się korzystając ze wzoru Pitagorasa:

L1 = sqrt(V1.x * V1.x + V1.y * V1.y);

Znając długość wektora można go przeskalować tak, aby jego nowa długość wynosiła określoną wartość "a" w następujący sposób

V1.x = V1.x / L1 * a;
V1.y = V1.y / L1 * a;

lub bardziej w stylu C++

V1.x *= a / L1;
V1.y *= a / L1;

Nie trudno domyślić się, że gdy a = 1 to długość wektora przeskalowanego przez 1 / L1 daje wektor o długości równej 1.

Dzielenie przez wartość "a" jest niczym innym jak operacją mnożenia przez wartość 1 / a (odwrotność a), więc nie będę się tu o tym rozpisywał.

Mnożenie wektora przez wektor (to zwykłe, nie skalarne)

V3.x = V1.x * V2.x;
V3.y = V1.y * V2.y;

A więc zwykłe mnożenie wektora przez wektor daje wektor, a skalarne (iloczyn skalarny)

IloczynSkalarny = V1.x * V2.x + V1.y * V2.y; Jak widać daje liczbę

można go obliczyć nieco innaczej

IloczynSkalarny = L1 * L2 * cos alfa; I tu też liczbę daje

gdzie:
L1 - długość wektora V1
L2 - długość wektora V2
alfa - kąt pomiędzy wektorem V1 a V2

No dobra, bo zaraz ktoś napisze "a skąd ja mam wziąć kąt pomiędzy dwoma znanym już wektorami", ano zazwyczaj jest tak, że ten kąt jest komuś potrzebny i można go wyliczyć gdy się chce go poznać, w jaki sposób a w taki:

V1.x * V2.x + V1.y * V2.y = L1 * L2 * cos alfa

            V1.x * V2.x + V1.y *V2.y

cos alfa = ------------------------------
L1 * L2

            |V1.x * V2.x + V1.y *V2.y|

alfa = acos|------------------------------| to już wyprowadzony wzór na kąt alfa
| L1 * L2 |

Do czego jeszcze przyda się iloczyn skalarny
Do sprawdzenia, czy dwa wektory są prostopadłe, a robi się to tak

jeżeli V1 x V2 == 0 to
"V1 jest prostopadły do V2"
w przeciwnym razie
"V1 nie jest prostopadły do V2"

x - czytaj tutaj jako iloczyn skalarny

Jest jeszcze coś czego nie pisałem, niektórzy mówią na to wyznacznik dwóch wektorów, a liczy się to tak:

              |V1.x  V1.y|

w(V1,V2) = | | = V1.x * V2.y - V2.x * V1.y
|V2.x V2.y|

w(V1,V2) - należy czytać: wyznacznik wektorów V1 i V2

Zaraz ktoś powie a to na co komu Jeżeli czytaliście uważnie przypowieść o iloczynie skalarnym to wiecie już, że występuje tam wartość cos alfa, no cóż wyznacznik dwóch wektorów jest nieco podobny do iloczynu skalarnego w wersji L1 * L2 * cos alfa, jedyną różnicą jest to, że zamiast cos jest sin a więc

w(V1,V2) = L1 * L2 * sin alfa

gdzie: L1, L2 i alfa już wiecie czym są

Za pomocą wyznacznika można sprawdzić warunek równoległości dwóch wektorów w następujący sposób:

jeżeli w(V1,V2) == 0 to
V1 jest równoległe do V2
w przeciwnym przypadku
V1 nie jest równoległe do V2

No i teraz można powiedzieć, że podstawowe informacje o wektorach nie są nam obce.

A teraz z czym to się je, czyli jak to wykorzystać

Załóżmy, że mam punkt 2D o nazwie p1 i drugi punkt p2. Chcę przesunąć p1 o p2 a więc należy zastosować dodawanie wektorów.
Wygodnie byłoby użyć następującego zapisu w c++: p1 += p2; lub p1 = p1 + p2; ale żeby to zrobić trzeba obsłużyć odpowiednie operatory (w tym przypadku dodawania). Podobnie można, a nawet należy postąpić z odejmowaniem, mnożeniem (ale nie skalarnym) i dzieleniem. Jak się obsługuje operatory w C++ to chyba już temat na inny artykuł, ale znawcą nie jestem więc napiszę przykład dla operatora dodawania:

class dPoint2D{
public:
double x;
double y;
dPoint2D operator +(dPoint2D &dp2d);
};

dPoint2D dPoint2D::operator +(dPoint2D &dp2d){
dPoint2D nowy; Tutaj przydałby się jakiś fajny konstruktor, np. przyjmujący za parametry "x" i "y"
nowy.x = this->x + dp2d.x;
nowy.y = this->y + dp2d.y;
return nowy;
}

z pozostałymi tak samo postępujemy, tylko że inaczej

No dobra a jak zrobić z obliczeniami długości wektora, iloczynu skalarnego i wyznacznika dwóch wektorów Tutaj można zastosować metody, o których istnieniu mam nadzieję wiecie, ale piszę to na wszelki wypadek dla tych co nie wiedzą.

Co jeszcze można zrobić z wektorami A można je obracać (najłatwiej względem środka układu współrzędnych, za który bierzemy x = 0 i y = 0) w następujący sposób:

xt = x;
yt = y;
x = xt * cos(Angle) - yt * sin(Angle);
y = xt * sin(Angle) + yt * cos(Angle);

gdzie: Angle - kąt obrotu w radianach, aby przeliczyć kąt z radianów na stopnie należy: Angle * PI / 180 (PI jest zadeklarowane w pliku math.h trzeba tylko przed jego załączeniem umieścić #define _USE_MATH_DEFINES a nazwa stałej to M_PI.

Obrócenie punktu p1 względem punktu p2 można opisać następująco:

p1 -= p2; Przesunięcie środka układu dla punktu p1 do punktu p2
p1.Rotate(Angle); Tą metodę trzeba napisać w klasie dPoint
p1 += p2; Powrót do "normalnego" układu współrzędnych

I to by było narazie tyle o wektorach.

1 komentarz

A może by tak w bloki [code] ująć kod??