If you're seeing this message, it means we're having trouble loading external resources on our website.

Ha webszűrőt használsz, győződj meg róla, hogy a *.kastatic.org és a *.kasandbox.org nincsenek blokkolva.

Fő tartalom

Bevezetés a vektorokba

Ezzel a tananyaggal az a célunk, hogy megfigyeljük a körülöttünk levő világot, és ügyes megoldást találjunk a jelenségek számítógépes szimulációjára. Azzal kezdjük, hogy megvizsgáljuk a fizika alaptörvényeit - hogyan esik le az alma a fáról, hogyan mozog az inga a levegőben, hogyan forog a Föld a Nap körül, és így tovább. Minden, amiről beszélni fogunk, a mozgás programozásának alapvető építőkövét használja — a vektort.
A vektor szónak különböző jelentései vannak. Vector volt a neve a kaliforniai Sacramentóban az 1980-as években alakult új hullám zenekarnak. Ez a neve a Kellog's által Kanadában gyártott reggeli gabonapehelynek. A járványügy területén a vektor egy fertőző ágenst hordozó, annak átvitelét megvalósító élőlény, ami átviszi a fertőzést az egyik gazdaélőlényről a másikra. A C++ programnyelvben a vektor (std::vector) dinamikusan átméretezhető adatstruktúra implementációja. Bár az összes fenti definíció érdekes, nem ezeket keressük. Amire szükségünk van, az az euklideszi térben (a görög matematikusról, Euklidészről nevezték el) az irányított szakasz fogalma. Amikor „vektorról” beszélünk, akkor ennek a jelentése egy olyan szakasz, amit a hosszán túl az iránya is jellemez.
A vektort nyíllal szokták ábrázolni; az irányt a nyíl hegye mutatja, míg a hosszt a nyíl hossza jelöli.
Vektor ábrája nagysággal és iránnyal
1,1. ábra Vektor (nyíllal ábrázolva), aminek van nagysága (a nyíl hossza) és iránya (amerre mutat).
A fenti ábrán az A pontból B pontba mutató nyíllal ábrázoltuk a vektort, amivel azt akartuk megmutatni, hogy hogyan lehet eljutni az A pontból B-be.

Miért érdemes vektort használni?

Mielőtt belemerülünk a vektorok rejtelmeibe, nézzünk meg egy alapprogramot, amely megmutatja, miért foglalkozzunk egyáltalán vektorokkal. Ha megcsináltad a Khan Academy bevezető JS kurzusát, akkor már megtanultad, hogyan kell egy egyszerű pattogó labda programot írni. (A programban található megjegyzések: 1. sor: Dan Shiffman, natureofcode.com példája alapján; 11. sor: A sebesség függvényében mozgatjuk a labdát; 15. sor: Ellenőrizzük, hogy visszapattan-e; 25. sor: Megjelenítjük a labdát az (x;y) pontban.)
A fenti példa világa nagyon egyszerű – egy üres háttér előtt egy kör alakú forma (egy „labda”) mozog. A labdának vannak tulajdonságai, amit a programban változók képviselnek.
PozícióSebesség
x és yxspeed és yspeed
Bonyolultabb programban sokkal több változónk lehetne:
GyorsulásCél helyzeteSzélSúrlódás
xacceleration és yaccelerationxtarget és ytargetxwind és ywindxfriction és yfriction
Látjuk, hogy minden fogalomhoz (szél, pozíció, gyorsulás, stb.) két változóra van szükségünk. És ez még csak a kétdimenziós világ. A 3D világában három változó kell: x, y, z, xSpeed, ySpeed, zSpeed és így tovább.
Mennyivel kellemesebb lenne, ha kevesebb változóra lenne szükség, és ezáltal egyszerűsödne a program!
E helyett:
var x = 5;
var y = 10;
var xSpeed;
var ySpeed;
Lehetne csak két változónk, ahol mindkét változó kétdimenziós, vektorszerű objektum lenne:
var position;
var speed;
Ezzel az első lépéssel még semmi újat nem tudunk csinálni. Csupán azzal, hogy vektorszerű objektumokat használunk változónak, még nem varázsoljuk át programunkat a fizikai világ szimulációjává. Viszont egyszerűsíti a kódot, és lehetővé teszi, hogy a mozgás programozása során ismétlődően előforduló egyszerű matematikai műveletekhez függvényeket állíts elő.
A vektorok bevezetésekor két dimenziót fogunk használni. A példák mind elég könnyen kiterjesztetők három dimenzióra (és a használt objektum, — PVector — három dimenziót enged meg.) Azonban könnyebb két dimenzióval kezdeni.

PVector használata a programban

Úgy is gondolhatunk a vektorra, mint két pont közötti különbség. Képzeld el, hogyan magyaráznád el valakinek, hogyan juthat el az egyik pontból a másikba!
Íme néhány vektor, és azok lehetséges fordítása: 
Vektor ábrák
1,2. ábra
| (-15, 3) | Sétálj 15 lépést nyugatra; fordulj el és sétálj három lépést észak felé! | | (3, 4) | Sétálj három lépést nyugatra; fordulj el és sétálj négy lépést észak felé! | | (2, -1) | Sétálj két lépést nyugatra; fordulj el és sétálj egy lépést dél felé! |
Ilyet már valószínűleg csináltál, amikor mozgást programoztál. Az animáció minden képkockájához (azaz a ProcessingJS minden draw() ciklusában) a kép minden objektumát utasítod, hogy elmozduljon adott számú pixellel vízszintes irányba, és valahány pixellel függőleges irányba.
Vektor használata új pozíció meghatározásához
1,3. ábra
Minden képkocka esetében:
új pozíció = sebesség a jelenlegi pozícióból kiindulva
Ha a sebesség egy vektor (két pont közötti különbség), akkor mi a pozíció? Az is egy vektor? Technikai értelemben érvelhetünk azzal, hogy a pozíció nem vektor, mivel az nem azt írja le, hogy hogyan juthatunk el az egyik pontból a másik pontba – egyszerűen a tér egy pontját írja le.
De egy helyzetet úgy is meghatározhatunk, hogy leírjuk azt az utat, ami az origóból a pozícióba vezet. Tehát egy helyzetet meghatározhatunk úgy is, mint egy vektor, ami az origó és a pozíció közötti különbséget írja le.
Pozíció mint vektor
1,4. ábra
Vizsgáljuk meg a háttérben levő pozíció és sebesség adatokat! A pattogó labda példában az alábbi adataink voltak:
PozícióSebesség
x és yxSpeed és ySpeed
Figyeld meg, hogyan tároljuk minkét esetben az adatokat – két lebegőpontos szám, egy x és egy y. Ha nekünk kellene megírni egy vektor osztályt, egy egészen alapvető dolgot csinálnánk:
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};
Alapjaiban a PVector csupán egy kényelmes módja két (vagy, mint a 3D példákban látni fogjuk, három) érték tárolásának.
Úgyhogy ebből …
var x = 100;
var y = 100;
var xSpeed = 1;
var ySpeed = 3.3;
ez lesz …
var position = new PVector(100,100);
var velocity = new PVector(1,3.3);
Most, hogy van két vektor objektumunk (position és velocity), implementálni tudjuk a mozgás algoritmusát—position = position + velocity. Az 1,1. példában, még vektorok nélkül, ezt írtuk:
x = x + xSpeed;
y = y + ySpeed;
Egy ideális világban ezt írhatnánk:
position = position + velocity;
JavaScriptben viszont az összeadás + művelete az elemi adattípusok számára (számok és sztringek) van fenntartva. Vannak olyan programozási nyelvek, ahol megengedett az operátorok esetében a „túlterhelés, vagy kiterjesztés” (overloading: azonos néven, de különböző paraméterlistával több függvény létrehozása), de a JavaScriptben ez nem megengedett. Szerencsére a PVector objektum tartalmaz a szokásos matematikai műveleteket megvalósító metódusokat, mint például az add().

Vektor összeadás

Mielőtt tovább vizsgálnánk a PVector objektumot és annak add() metódusát, vegyük szemügyre a vektorok összeadását és jelölésrendszerét, ahogy azt a matematikai és fizikai tankönyvek tárgyalják.
A vektorokat általában vagy félkövér betűkkel jelölik, vagy egy nyíl van felül. Ebben a tananyagban a vektor és a skalár megkülönböztetésére a nyilas jelölést fogjuk használni (a skalár egy érték, mint például egy egész szám vagy egy lebegőpontos érték):
  • Vektor: u
  • Skalár: x
Tegyük fel, hogy van két vektorunk:
Két vektor ábrája
1,5. ábra
Mindkét vektornak két komponense van, egy x és egy y. A két vektor összeadásakor egyszerűen összeadjuk a két x-et és a két y-t.
1,6. ábra
Azaz:
w=u+v
így is írható:
wx=ux+vxwy=uy+vy
Ezután helyettesítve u-t és v-t a megfelelő értékekkel az 1,6. ábrán, ezt kapjuk:
wx=5+3wy=2+4
ami ezt jelenti:
wx=8wy=6
Végül ezt is írjuk fel vektor formában:
w=(8,6)
Most, hogy megértettük, hogyan kell két vektort összeadni, megnézzük, hogyan valósították meg két vektor összeadását a PVector objektumban. Írjunk egy add() metódust, ami paraméterként átvesz egy másik PVector objektumot, és egyszerűen összeadja az x és y komponenseket!
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};

Vector.prototype.add = function(v) {
  this.y = this.y + v.y;
  this.x = this.x + v.x;
};
Most, hogy már látod, hogyan van megírva a PVector add() metódusa, visszatérhetünk a pattogó labda példánkhoz és az ottani pozíció + sebesség algoritmushoz, és használhatjuk a vektor-összeadást:
position.add(velocity);
Most már készen állunk arra, hogy újraírjuk a pattogó labda példát PVector objektumot használva. Figyeld meg a két kód közötti különbségeket! (A programban található megjegyzések: 1. sor: Dan Shiffman, natureofcode.com példája alapján; 11. sor: Még mindig időnként hivatkozni kell a PVektor egyes komponenseire. Ezt a pont jelölési konvenció használatával tehetjük meg: location.x, velocity.y, stb.)
Figyeljünk meg a fenti átírással kapcsolatban egy fontos tényezőt: bár PVector objektumokat használunk két érték – az x és y pozíció, valamint az x és y sebesség – leírására, gyakran hivatkoznunk kell az egyes PVector objektumok x és y komponenseire külön-külön. Ha egy objektumot rajzolunk a ProcessingJS-ben, nem írhatunk ilyen kódot:
ellipse(position, 16, 16);
Az ellipse() függvény nem fogad el PVector adattípusú paramétert. Elipszist csak két skaláris x és y koordinátával rajzolhatunk. Úgyhogy le kell ásni a PVector objektumba, és elő kell bányászni az x és y tulajdonságokat az objektumorientált programozás pontjelölési konvenciója szerint:
ellipse(position.x, position.y, 16, 16);
Ugyanez a probléma merül fel akkor, amikor azt vizsgáljuk, hogy a kör elérte-e az ablak szélét, és hozzá kell férnünk a position és velocity vektorok tulajdonságaihoz.
if ((position.x > width) || (position.x < 0)) {
  velocity.x = velocity.x * -1;
}
Most kicsit csalódott lehetsz. Végül is a program megváltoztatása első látásra az eredetinél bonyolultabbá tette azt. Ez egy teljesen észszerű és helytálló kritika, de fontos megérteni, hogy egyenlőre még nem mélyültünk el a vektorok használata által kínált lehetőségekben. Az egyszerű pattogó labda példája és a vektorösszeadás használata csak az első lépés.
Ahogy előrehaladunk a többszörös objektumok és többszörös erőhatások összetettebb világa felé (amit nemsokára megismerünk), a PVector előnyei világossá válnak. Csak így tovább!

Ez a „Természetes szimulációk" tananyag a Daniel Shiffman által készített „The Nature of Code” alapján készült, a Creative Commons Attribution-NonCommercial 3.0 Unported License szerint.

Szeretnél részt venni a beszélgetésben?

Még nincs hozzászólás.
Tudsz angolul? Kattints ide, ha meg szeretnéd nézni, milyen beszélgetések folynak a Khan Academy angol nyelvű oldalán.