Matematika

V této kapitole se budu věnovat matematice. Nedozvíte se tu žádné nové vlastnosti jazyka C. Ale to nevadí, určitě semnou budete souhlasit, že jediná zábavnější věc než programování v C je matematika :-). Zaměřím se zde na tu část matematiky, která je potřebná pro transformace souřadnic ve 2D a 3D prostoru. Tedy na ta témata, které se vám budou hodit (nejen) při programování her.

Těm z vás, kteří dávali ve škole při matematicke pozor, se omlouvám za toto malé opakování :-).

Zatím jsem neprobral žádnou knihovnu, která by vám umožňovala kreslit „obrázky“ (knihovnu pro grafický výstup). Pro jazyk C žádná standardní knihovna neexistuje, ale existuje několik free/open source knihoven (např. OpenGL), na které příjde řada v některé z dalších kapitol. Ať už budete programovat za pomoci jakékoliv knihovny, matika pro výpočet souřadnic na obrazovce bude vždy stejná.

Základní pojmy

Souřadnicový systém

Souřadnicový systém je jakási dohoda o tom, jak se bude určovat poloha bodu v prostoru (ve 2D na ploše, ve 3D v třírozměrném prostoru).

Ve 2D (ve dvou dymenzích) se v matematice obvykle používají souřadnice označované x a y. Ve 3D je ještě navíc souřadnice z, která určuje vzdálenost od plochy, ve které vedou souřadnice x a y (souřadnice x a y vedou v ploše monitoru, z určuje, jak daleko je bod před nebo za monitorem). Protože 3D monitory jsou stále raritou, obvykle se souřadnicová osa z kreslí pomocí perspektivy, viz druhý a třetí obrázek:

Matematický souřadnicový systém 2D

Matematický souřadnicový systém 2D

Matematický souřadnicový systém 3D

Matematický souřadnicový systém 3D (a)

Klikněte na obrázek a použijte + a - pro změnu souřadnice z.
Matematický souřadnicový systém 3D

Matematický souřadnicový systém 3D (b)

Klikněte na obrázek a použijte + a - pro změnu souřadnice x.

Na prvním obrázku je obvyklý souřadnicový systém pro dva rozměry (2 Dimenze). Body se označují souřadnicemi v hranatých závorkách [x,y] (ve 3D [x,y,z]). Počátek je bod se souřadnicí [0,0] ([0,0,0] ve 3D). Je tam, kde se osy protínají. Y-ová souřadnice roste směrem nahoru, X-ová souřadnice směrem doprava.

Jednotky na osách mohou být cokoliv (milimetry, metry, stopy, míle …). Pro tuto kapitolu nejsou podstatné, proto je nebudu uvádět.

Směry os nejsou vytesané do kamene, na druhém a třetím obrázku je tentýž souřadnicový systém, jen je vykreslen z jiného pohledu. (Všiměte si bodu [0,0,6], který má x a y souřadnice 0, z souřadnici 6. Na obou obrázcích je tento bod vykreslen jinak, ale pořád je to tentýž bod.)

Souřadnice na prvním obrázku rozdělují plochu na 4 části, tzv. kvadranty. Na obrázku jsou očíslovány římskými čísly. Kvadranty pomáhají hlavně v komunikaci. Můžu vám třeba říct, že bod [5,5] je v prvním kvadrantu. Nebo že hodnota kosínu je kladná v prvním a čtvrtém kvadrantu a záporná v druhém a třetím. (Matika je cizým jazykům hodně podobná v tom, že se musíte učit spoustu nových slovíček.)

Obrazovkový souřadnicový systém 2D

Obrazovkový souřadnicový systém 2D

OpenGL souřadnicový systém (3D)

OpenGL souřadnicový systém (3D)

Použijte + a - pro změnu souřadnice z.

V počítačové grafice se obvykle používá souřadnicový systém, který má počátek v levém horním rohu obrazovky. X-ová souřadnice jde z leva do prava a y-ová ze zhora dolů. (Takto se obvykle po řádcích překreslují pixely obrazovky – nejdřív první řada pixelů na obrazovce z leva do prava, pak druhá atd. Alespoň u CRT monitorů to tak bývalo.) Rozměry X-ové i Y-ové osy se obvykle uvádějí v pixelech. Grafické knihovny nemusí vykreslovat do celé obrazovky, takže maximální hodnoty na osách x a y záleží na velikosti „plátna“, do kterého grafická knihovna kreslí. Pokud se pokusíte vykreslit něco za hranice plátna, tak se to prostě nezobrazí (nebude mít kde).

Pixel obrazovky je nejmenší bod na monitoru, který může měnit barvu. Čím více má obrazovka pixelů, tím jemněji dokáže vykreslovat obraz. Obrazovku si můžete představit jako čtverečkovaný papír, kde každý čtvereček je jeden pixel.

Pixel se obvykle označuje jednotkou px.

Grafická knihovna OpenGL, která se používá pro vykreslování 3D grafiky, používá souřadný systém zobrazený na posledním obrázku. Počátek je ve středu plátna a osy X,Y a Z mají rozsah od -1 do 1. Body, které mají některou souřadnici větší než 1 nebo menší než -1 se nevykreslí.

Pokud budete mít plátno 300x300px, a vykreslíte kružnici o poloměru 1, pak uvidíte na obrazovce kružnici s průměrem 300px (bude se dotýkat okrajů nahoře i po stranách plátna. Pokud toto plátno natáhnete na velikost 600x300px, vykreslí se elipsa s průměry 600 x 300px (pořád se bude dotýkat všech okrajů). Pokud chcete na takto roztaženém plátně zobrazit kružnici, musíte vykreslit elipsu s poloměry 0.5 a 1. Matika!

Vektor

Vektor je veličina, která udává velikost a směr. Na obrázku níže jsou zobrazené vektory, jejichž směr je zobrazen šipkou, velikost délkou.

Speciálním případem vektoru je jednotkový vektor, který má velikost (délku) 1. Pracovat s jednotkovým vektorem je radost. Když například chcete posunout nějaký bod o 5 pixelů určitým směrem daným jednotkovým vektorem, tak tento vektor jen vynásobíte pěti a posunete bod o výsledný vektor (v jeho směru a o jeho velikost).

Výpočet jednotkového vektoru viz Normalizovaný vektor.

Your Browser doesnt support SVG images.

Červené vektory na obrázku ukazjí směr od počátku sořadného systému k červenému bodu. Plnou čarou je vyznačen jednotkový vektor.

Modré vektory označují směr od červeného bodu k modrému (to se hodí, pokud třeba chcete posunout vojáčka směrem k nepřátelskému vojáčku ...). Plnou čarou vyznačený vektor je jednotkový vektor a jeho počátek je umístěn do počátku souřadného systému. Směr si zachovává stejný, jako je směr od červeného k modrému bodu.

Všiměte si, že vektor a jeho jednotkový vektor jsou vždy rovnoběžné. Když budu chtít posouvat červený puntík k modrému, tak pozici červeného puntíku už znám, takže mi stačí znát jen směr. Nepotřebuji mít tedy u vektoru uložené 2 informace (počátek a směr), ale stačí mi směr.

Většinou nepotřebuji znát ani velikost vektoru (vzdálenost červeného a modrého puntíku), protože se vojáček bude pohybovat nějakou rychlostí. Posun vojáčka bude dán vzorcem jednotkový vektor x rychlost (příklady viz dále).

Vektory se obvykle zapisují do kulatých závorek. Například (0, 1) je (jednotkový) vektor směřující ve směru osy y ve 2D, vektor (1,0,0) je vektor směřující ve směru osy x ve 3D, atd.

Goniometrické funkce

Přesně tak. Je tu oblíbené „sínus, kosínus, deskriptíva…“. Celá tato úhlologie vychází z jednoduchého principu podobnosti trojůhelníků. Na obrázku níže vidíte dva trojůhelníky, přičemž ten červený je 2x větší než ten zelený. Jako zázrakem platí, že nejenže strana a červeného trojůhelníku je 2x větší než strana a zeleného trojůhelníku, ale i b a c u červeného trojůhelníku jsou 2x větší než u zeleného. Zatímco úhly v obou trojůhelnících jsou stejně velké.

Your Browser doesnt support SVG images.

Co z toho plyne? Označme si stranu a zeleného trojúhelníka a z , stranu a červeného trojúhelníka a c atp., pak mimo jiné platí, že:

a z c z = 2 * a z 2 * c z = a c b c

A to je ta podobnost trojúhelníků.

Jednotková kružnice

No a tím jsem vám vysvětlil všechny goniometrické funkce :-). Teď už si je jenom nějak pojmenovat. K názornému příkladu se často používá tzv. jednotková kružnice (kružnice o poloměru r=1). Viz obrázek níže. Vidíte na něm kružnici s poloměrem 1 a takovou světlou, sotva viditelnou, barvou zobrazený trojůhelník. Strany X a Y má zvýrazněné šipkou a je u nich napsaná jejich délka. Jedná se o pravoúhlý trojůhelník.

Strana, která je v pravoúhlém trojůhelníku naproti pravému úhlu, se nazývá přepona. Bez ohledu na to, kam na kružnici posunete vrchol trojůhelníku kolem kterého bliká to kolečko, přepona bude mít vždy délku 1.

Dále nás bude zajímat úhel mezi vodorovnou čárou vedoucí prostředkem kružnice a přeponou. Říkejme mu úhel α (alfa). Na obrázku je úhel α označen oranžovým obloukem na kružnici.

Kliknutím na a táhnutím blikajícího kolečka si můžete vyzkoušet, jak se mění délky stran X a Y a jak se mění úhel α.

Your Browser doesnt support SVG images.

Úhel se uvádí buďto v radiánech, nebo stupních.

Úhel v stupních rozděluje kružnici na 360 dílků. Takže může nabývat hodnot od 0 do 360.

Úhel v radiánech může nabývat hodnot od 0 do 2*π (3.141592). To je docela vychytralá míra, protože, jak jistě víte, obvod kružnice se vypočítá podle vzorečku s = 2*π*r2 . Na jednotkové kružnici je poloměr r=1, takže obvod jednotkové kružnice je roven s = 2*π . Takže úhel α je roven délce oblouku na obvodu kružnice mezi přímkami, které úhel ohraničují (na obrázku je zvýrazněn oranžovou barvou).

Definice goniometrických funkcích

sin(α)
Sínus α je poměr protilehlé strany trojúhelníku ku přeponě.
Na jednotkové kružnici je tedy sinα =yr =y1 =y
cos(α)
Kosínus α je poměr přilehlé strany trojúhelníku ku přeponě.
Na jednotkové kružnici je tedy cosα =xr =x1 =x
tan(α)
Tangens α je poměr protilehlé strany ku přilehlé. tanα =yx

Výsledkem těchto funkcí je bezrozměrné číslo, řekněme číslo x. (Když vydělíte např. metr metrem, žádná jednotka nezbyde.).

Pro zpětný výpočet úhlu z těchto hodnot existují „reverzní“ funkce:

asin(x)
Arkus sínus x vypočítá úhel α z x, kde x je sin(α).
Jinak řečeno: asinsinα =α
acos(x), atan(x)
Arkus kosínus a arkus tangents jsou reverzní funkce pro sínus a tangents.

S funkcí atan(x) je trochu potíž. Když se podíváte na jednotkouvou kružnici pro úhel 45°, tak uvidíte, že x=0.71 a y=0.71, takže tan(45°) = 0.71/0.71 = 1. Jenže pro úhel 225° je x=-0.71 a y=-0.71, takže tan(225°) = -0.71/-0.71 = 1.
Co pak má být výsledkem atan(1)? 45°, nebo 225°?

Kvůli této nejednoznačnosti se v programovacích jazycích zavedla funkce atan2(y,x):

atan2(y,x)
Funkce atan2() vypočítá úhel na základě hodnot y a x. Protože má k dispozici znaménka y a x, ví, do jakého kvadrantu úhel zasahuje.

Goniometrické funkce v jazyce C očekávají argument úhlu v radiánech, připadně (inverzní funkce) vracejí úhel v radiánech. Ikdyž je rozdělení kružnice na 360 stejných dílků pro člověka srozumitelnější, počítači se lépe počítá s radiány.

Funkce atan2() je definována tak, že vrací hodnotu v rozsahu (-π,π>. Takže pro x=0.71 a y=0.71 vrací π/4 (45°) a pro x=-0.71 a y=-0.71 vrací -3/4π (-135°).

To se občas výborně hodí. Třeba když chcete otočit věž tanku k nepříteli, nebudete se otáčet proti směru hodinových ručiček o 225°, ale raději se otočíte po směru hodinových ručiček o 135°. Někdy se to zase tak nehodí, ale díky tomu, že víte, že záporná hodnota výsledku atan2() je ve třetím nebo čtvrtém kvadrantu, stačí vám k zápornému výsledku přičíst 2π a hned máte výsledek v rozsahu <0, 2*π).

Formální definice funkce atan2() viz wikipedie.

K čemu nám ty goniometrický funkce vlastně jsou? Vzpomeňte si na podobnost trojúhelníků, o které jsem psal na začátku. Goniometrické funkce nejsou nic jiného, než podíl stran pravoúhlého trojúhelníka. Díky podobnosti trojúhelníků tak můžete na základě znalosti dvou stran libovolného pravoúhlého trojúhelníka dopočítat úhel. Nebo naopak na základě znalostí úhlu a délky jedné strany dopočítat délku druhé strany.
Praktické příklady budou následovat.

Pythagorova věta

Pythagorovu větu zná ze základní školy jistě každý. Umožňuje dopočítat třetí stranu pravoúhlého trojůhelníka, když znáte zbývající dvě.

c 2 = a2 + b2
c = a2 + b2
a = c2 - b2

Nejčastěji ji při programování grafiky nebo nějakých her využijete na výpočet vzdálenosti bodů. Budete znát souřadnice dvou bodů [x1,y1], [x2,y2], jejich vzdálenost vypočítáte takto:

v = x2-x12 + y2-y12
Your Browser doesnt support SVG images.
v = 3-x12 + 2-y12

Výpočet odmocniny je relativně pomalý. Pokud potřebujete porovnat vzdálenost s nějakou hodnotou x, je efektivnější porovat x2 s x2-x12 + y2-y12 .

Matice

Matice je další matematický konstrukt, který je tu jen pro to, že umožňuje zjednodušit komunikaci, prezentaci a řešení matematických problémů. Na první pohled jde jen o tabulku čísel.

Jako každá tabulka, má i matice řádky a sloupce. Počet řádků se obvykle označuje m, počet sloupců pak n. Matice mxn je tedy matice s m řádky a n sloupci.

Prvky v matici se označují svými „souřadnicemi“. Například můžete napsat, že prvek v matici pojmenované A na druhém řádku ve třetím sloupci je a2,3.

Příklad matice 2x3:

A = 11 12 13 21 22 23

V matici A je prvek a2,3 = 23.

Speciálním případem matice je vektor. Třeba 2D vektor můžete zapsat jako matici 1x2, nebo 2x1, podle toho, jak se vám zrovna hodí.

Motivační příklad

Abyste měli trochu představu o tom, k čemu se v matice matice používají, začnu jednoduchým příkladem - řešení dvou rovnic o dvou neznámých.

Podívejte se na tyto dvě rovnice:

1x + 2y = 5 2x + 1y = 3

Věřím že víte, jak se takové rovnice řeší. Řešení pomocí matice je v podstatě stejné, jen je to trochu jinak zapsané.

Pomocí matic bych předchozí příklad mohl přepsat takto:

1 2 2 1 = 5 3

No ale to vypadá dost divně, protože matice na levé straně se nerovná matici na pravé straně (ani nemají stejné dimenze (mxn), natož že by obsahovaly stejná čísla). Někam nám totiž zmizely proměnné x a y. Lepší zápis bude tento:

1 2 2 1 * x y = 5 3

První matici násobím maticí (x,y)T. Jak je násobení matic definováno?

AT znamená transponovaná matice A. Zápis (x,y)T jsem použil proto, protože v řádce lépe vypadá :-).

Odpověď prozradím o pár řádek níže. Ale z příkladu to jistě trochu tušíte. Vynásobením matic na levé straně rovnice vyjde to, co je na levé straně v původním zadání dvou rovnic o dvou neznámých.

Ještě více zjednodušený zápis příkladu, který se občas používá, vypadá takto:

1 2 5 2 1 3

Případně se může vynechat i ta svislá čára odělující levou a pravou stranu rovnice.

1 2 5 2 1 3

Na tomto zápisu je mimo jiné super to, že se snadno převede do programovacího jazyka. Stačí nám definovat dvourozměrné pole, do kterého se zapíší čísla z matice.

Pokud velikost (dimenze) tohoto pole bude dynamická, můžete si poměrně snadno napsat algoritmus, který vám bude řešit problém x rovnic o x neznámých.

Jednoduchý zápis problému a jeho řešení se ještě více ukáže při transformaci souřadnic, o kterých budu psát v příští kapitole. Teď se ale podívejte na definice některých matematických operací s maticemi.

Sčítání a odčítání matic

Sčítání matic je definované jen pro matice stejných dimezní (mxn) a je velice jednoduché. Každý i,j prvek z první matice se sečte s prvkem i,j druhé matice.

Například:

1 2 3 -1 -2 -3 0 0 0 + 1 1 1 2 2 2 3 3 3 = 2 3 4 1 0 -1 3 3 3

Platí, že A + B = B + A (kde A a B jsou matice stejných dimenzí).

Transpozice matic

Transpozice matice je v podstatě jen přehození řádek a sloupců. Z matice mxn se stane matice nxm.

Transponovaná matice A se značí jako AT.

Takže když napíšu jednořádkovou matici (x,y)T, je to to samé, jako bych napsal jednosloupcovou matici x y . A naopak, transponovaná jednosloupcová matice se stane jednořádkovou maticí.

Další příklad:

123 456 789 T = 147 258 369

Transponované matice mají některé užitečné vlastnosti. Vcelku zjevné je, že platí:

AT T = A

Pořád ještě vcelku zjevné je, že transpozice součtu se rovná součtu transpozice:

A+B T = AT + BT

Už ne tolik zjevné, ale užitečné je, že:

(A*B)T = BT*AT.

Tady je důležité pořadí matic v násobcích, protože u násobení matic neplatí že A*B = B*A.

K čemu je to užitečné ukáži dále.

Násobení matic

Násobení matic je už trochu složitější. Pokud A a B jsou matice, a C je výsledek násobení A*B, pak ci,j je součet násobků i-tého řádku s j-tým sloupcem.

Násobení je definované pouze pro matice, kde když první matice má dimenzi mxn, pak druhá matice musí mít dimenzi nxp. (n, m a p jsou kladná celá nenulová čísla.)

To je vcelku jasné, když násobení matic probíhá jako součet násobení jednotlivých členů řádků z první matice se členy sloupců druhé matice, pak počet členů v řádku první matice (= počet sloupců první matice) musí být stejný jako počet členů v sloupci druhé matice (= počet řádků v druhé matici). Výsledkem je matice o rozměru mxp.

Jsem si vědom toho, že předchozí odstavec je šeredný, ale z příkladu to snad bude jasnější. Vrátím se k předchozímu motivačnímu příkladu. Vezmu si z něho levou stranu maticového zápisu a výsledek označím jako matici C.

1 2 2 1 * x y = c1,1 c2,1 = 1x+2y 2x+1y

Tady se jedná o násobení matice 2x2 maticí 2x1. Počet sloupců v první matici (2) je stejný jako počet řádků v té druhé, takže násobit by šlo. Výsledkem je matice o rozměru 2x1.

Rozepsaný výpočet vypadá takto:

c1,1 = a1,1 * b1,1 + a1,2 * b2,1 = 1 * x + 2 * y c2,1 = a2,1 * b1,1 + a2,2 * b2,1 = 2 * x + 1 * y

Výpočty, které jsou potřeba pro transformaci souřadnic, často obsahují násobení matic 3x3. Proto ukáži ještě jeden příklad právě pro toto násobení:

1 2 3 1 1 1 50 60 70 * 1 1 1 1 0 0 0 0 -1 = 1+2+0 1+0+0 1+0-3 1+1+0 1+0+0 1+0-1 50+60+0 50+0+0 50+0-70 = 3 1 -2 2 1 0 110 50 -20

Pro násobení matic neplatí, že A*B = B*A. Pokud mají matice různé dimenze, tak se dokonce může stát, že je možné spočítat A*B, ale B*A už ne.

Násobení matice skalárem

Matici vynásobíte číslem tak, že vynásobíte každý její člen.

Například násobek vektoru (3,-1) číslem 5 je (15,-5). Jedná se tedy o vektor směřující stejným směrem, jen 5x větší (delší, chcete-li).

Jednotková matice

Jednotková matice je matice, která má na diagonále samé jedničky a všude jinde nuly.

1 0 0 0 1 0 0 0 1

Vlastností jednotkové matice, označme si jí třeba I je, že A*I = A a I*A = A (pokud jsou tato násobení možná).

Když se vrátím k motivačnímu příkladu, tak se vlastně potřebujeme dopočítat z výchozího zadání:

1 2 2 1 * x y = 5 3

k tomuto výsledku:

1 0 0 1 * x y = ? ?

Protože na levé straně se (x,y)T násobí jednotkovou maticí, tak se vlastně dostaneme k tomuto výsledku:

x y = ? ?

Jednodušší zápis pro výsledek je:

1 0 ? 0 1 ?

Algoritmus, jak se dostat ze zadání k tomuto výsledku popisovat nebudu. Je to stejné, jako jste se učili na základaní škole řešit dvě rovnice o dvou neznámých (odečítáte od sebe řádky, násobíte je atp.). V dalším výkladu to stejně nebude potřeba :-).

Jednotková matice se hodí jako startovní čára pro různé transformace. Transformace jednotkovou maticí je vlastně "žádná" transformace. Viz následující kapitola.

Inverzní matice

Inverzní matice k matici A je taková matice, jejímž násobením s A se získá jednotková matice.

Označme si inverzní matici jako A-1 a jednotkovou matici jako I Pak platí:

A*A-1=I A-1*A=I

Z těchto definic je jasné, že inverzní matici lze vytvořit jen pro čtvercovou matici.

Dále platí:

A-1-1=A

Tím, jak se vypočítává inverzni matice už vás nebudu zatěžovat. Je to jednoduché, ale proč se tím zdržovat, bude to za vás stejně počítat nějaká matematická knihovna. Pokud vás to zajímá, postup si snadno vygooglíte.

Co je ale důležité si v souvislosti s inverzními maticemi uvědomit je to, co dělá inverzní matice k transformační matici (=matice, která transformuje pozici bodu – posouvá ho, rotuje s ním atp.).

O transformačních maticích budu hovořit až v následující kapitole, takže teď trochu předbíhám, ale funguje to asi takto: Inverzní matice k posunu bodu posune bod zase zpět, inverzní matice k rotaci o α stupňů je matice rotace o -α stupňů, inverzní matice k zmenšení o x je matice zmenšení o 1/x (= zvětšení o x) …

Závěr

V této kapitole jsem se vám pokusil vysvětlit některé části matematiky, které se používají při transformaci souřadnic ve 2D a 3D prostoru. Pravdou je, že na tyto výpočty už existují pro jazyk C knihovny, takže si ani nemusíte pamatovat jak se co počítá, ale je důležité rozumět tomu, co výpočty znamenají a k čemu jsou dobré.

V této kapitole jsem se zaměřil na to, co výpočty znamenají, v dalších se zaměřím na jejich praktické využití. Nepopsal jsem tu zdaleka všechno, co se o goniometrických funkcích nebo maticích dá napsat. Soustředil jsem se především na to, co budu potřebovat v dalších kaptiolách. A na pochopitelnost výkladu. Snad se mi to i podařilo. Pokud ne, stěžujte si :). Pokud je to naopak poprvé, co vám někdo vysvětlil srozumitelně goniometrické funkce, dejte mi like. Vlastně, tady nejsme na youtube, tak nic :-).

Na internetu najdete nepřeberné množství dalších informací k těmto tématům, pokud vás zaujala.

Komentář Hlášení chyby
Created: 1.3.2016
Last updated: 19.11.2017
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..