Programowanie w języku C/C++ » Artykuły

Operacje na wektorach

  • 2008-10-19 09:34
  • 1 komentarz
  • 8120 odsłon
  • Oceń ten tekst jako pierwszy
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

winerfresh 2008-10-27 15:15

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