Transformace souřadnic v rovině pomocí transformačních matic

Algoritmy Grafické Transformace souřadnic v rovině pomocí transformačních matic

Klasický problém: jak na obrazovce zobrazit nějaký objekt, který je určen souborem kartézských souřadnic (x, y), otočený o nějaký obecný úhel?


Dejme tomu, že náš objekt vypadá třeba takto:

lokální souřadný systém objektu


Osy xL a yL tvoří lokální souřadný systém - tvar objektu je vyjádřen souřadnicemi měřenými v tomto systému.

Obrazovka tvoří globální souřadný systém. Když něco zobrazujeme, používáme tyto souřadnice. Naší hlavní starostí tedy je vypočítat globální souřadnice každého bodu objektu. V praxi to vypadá tak, že vezmeme lokální souřadnice každého bodu příslušného objektu, uděláme s nimi pár triků zahrnujících souřadnice objektu na obrazovce apod. a vyjdou nám zobrazitelné globální hodnoty.

Zobrazení objektu bez otáčení je jednoduché. Pro každý bod na objektu:

XG = XL + XO
YG = YL + YO



kde hodnoty s indexem G jsou hledané globální souřadnice, index L znamená lokální souřadnice jednotlivých bodů objektu měřené od počátku jeho lokálního souřadného systému a indexem O je označena poloha objektu na obrazovce, čili poloha počátku souřadného systému L pevně spojeného s objektem vůči globálnímu počátku.
Srozumitelnější to je na obrázku:

objekt na obecných souřadnicích



Tohle ale snad zvládne každý. Teď se ale podíváme na to, jak ho zobrazit takhle:

objekt na obecných souřadnicích, obecně natočený



Všimněte si jednoho důležitého detailu: lokální souřadný systém je pořád pevně spojen s objektem a natáčí se spolu s ním.

No, a teď přijdou na řadu slíbené transformační matice. Pro 2D mají rozměry 3x3 (pro 3D by byly 4x4, ale to teď probírat nebudeme).
Jak to celé funguje? Začneme v globálním počátku souřadnic a snažíme se postupně přesunout do lokálního počátku objektu a vhodně se tam natočit. To se provede pomocí transformační matice:

obecný transformační vzorec


kde BG je hledaný rozšířený vektor globálních souřadnic, BL je známý rozšířený vektor lokálních souřadnic příslušného bodu a T je transformační matice. Součin je maticový (předpokládám, že ho znáte; pokud ne, klidně se zeptejte).
Rozšířený vektor se od obyčejného liší jen tím, že kromě složek x a y obsahuje ještě třetí složku, která je konstantně rovna 1. S těmito vektory zacházíme jako s maticemi 3x1 (3 řádky, 1 sloupec), takže jimi můžeme zprava vynásobit matici 3x3. Z výsledného vektoru BG pak samozřejmě zužitkujeme pouze první dvě složky, jednička nás nezajímá.

Obecná transformační matice a rozšířený vektor vypadají takto:

transformační matice a rozšířený vektor


Položky x a y říkají, o kolik se tou maticí posouváme, a čtyři položky s úhlem říkají, o jaký úhel nás ta matice otočí (kolem osy z). Kladný smysl otáčení je pro běžné souřadnice (s osou y mířící kladnou polovinou nahoru) proti směru hodinových ručiček, pro souřadnice počítačové (y roste směrem dolů) po směru hodinových ručiček.

Začínáme tedy v globálním počátku a potřebujeme se posunout o xO, yO a otočit o úhel α. Tyto hodnoty dosadíme do matice a tím jsme se dostali do lokálního počátku spojeného s objektem. Nyní stačí matici zprava vynásobit vektorem lokálních souřadnic příslušného bodu na objektu a vyjdou nám jeho globální souřadnice. Jak prosté. 
Po rozepsání maticového součinu nám vyjde toto:

výsledek


To jsou vzorce, které pak budeme v programech prakticky používat - žádné matice tam doopravdy násobit nebudeme, to by bylo zbytečně moc počítání. Jak vidíte, i kdybychom chtěli počítat jen jednu globální souřadnici (třeba xG), budeme k tomu stejně potřebovat obě lokální (xL i yL).
A ještě jedna věc: pro všechny body našeho objektu si vystačíme s jedněmi hodnotami sinα a cosα, takže stačí spočítat si je jednou (pro aktuální úhel natočení) a pak už jenom dosazovat. Takže žádné otrocké počítání sin a cos pro každý bod zvlášť.

Zajímavou vlastností transformačních matic je jejich skládatelnost. Nemusíme celý posun zvládnout najednou, někdy to ani nejde (třeba když je potřeba se posunout, otočit a potom znovu posunout), ale můžeme ho rozložit do elementárních kroků - posun ve směru x, otočka, teď kousek o y nahoru a jiné x doleva, zase otočka... atd. Složení matic se provede jejich prostým maticovým vynásobením, např.:

skládání transformačních matic


a jednotlivé dílčí matice jsou:

dílčí matice pro x, y a úhel


Tohle je jenom příklad, násobit můžeme libovolné kombinace posunů i natočení (ne jenom takhle x, y, α, ale třeba y, α, x, x, α, y atd.).

Tento rozklad se použije, pokud máme nějaký složitější kinematický řetězec, např. něčí ruku. Počátek globálních souřadnic si dáme dejme tomu do ramene a chceme nakreslit třeba prst. Takže: jsme v rameni. Natočíme se tak, aby osa x mířila ve směru paže a napíšeme si matici pro natočení o tento úhel. Pak se posuneme ve směru x o délku pažní kosti až k lokti (posuny se počítají vždy v tom směru, kam jsme se právě natočili, ne ve směrech globálních os!) a vedle první matice si připíšeme druhou, pro posun ve směru x. Pak se opět natočíme o úhel lokte a připíšeme další matici, pak se posuneme k zápěstí, natočíme, posuneme se přes dlaň a natočíme se tentokrát třeba ypsilonovou osou ve směru prstu. Na konec připíšeme rozšířený vektor, který ukazuje od toho kloubu, kam jsme se dostali s transformační maticí, na konec prstu (v tomto případě (0, něco, 1), protože na prst ukazujeme yovou osou) a všechny ty matice a vektor postupně maticově pronásobíme (je dobré začít zprava, protože je to mnohem méně pracné - vycházejí nám vektory 3x1 a ne matice 3x3). Výsledkem je rozšířený vektor globálních souřadnic špičky prstu.
Jinak kdybychom chtěli, mohli bychom se maticemi přesunout až na špičku prstu a pak to násobit vektorem (0, 0, 1), vyšlo by to samé.

No, a to je celé. Zájemcům o hlubší teorii, 3D, odvození těchto matic a podobné věci doporučuji skripta Mechanika A (nebo Mechanika 1, název se možná změní||změnil) pro FS ČVUT, k dostání ve skriptárně ve Studentském domě v Dejvicích ;-).


P.S.: Tímto systémem se dají pohodlně otáčet i rastrové obrázky. Jenom si dejte pozor na jednu věc: nepočítejte pro každý pixel původního obrázku, kam se otočí a zobrazí do cílové oblasti, ale naopak spočítejte pro každý pixel cílové oblasti, jaký pixel z původního obrázku se do něj zobrazí. To proto, aby pak výsledný obrázek nebyl "děravý".


 

  Aktivity (1)

Článek pro vás napsal Mircosoft
Avatar
Autor je amatérský pascalista, assemblerista a bastlíř. Profesionálně psal nebo píše v HLASM, Rexxu, Cobolu, ST, LAD, FBD, PHP, SQL, JS, Basicu a pár dalších jazycích, které kupodivu stále existují a používají se :-).

Jak se ti líbí článek?
Celkem (1 hlasů) :
4444 4


 


Miniatura
Všechny články v sekci
Grafické algoritmy

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!