int21h

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 3×3 (pro 3D by byly 4×4, 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 3×1 (3 řádky, 1 sloupec), takže jimi můžeme zprava vynásobit matici 3×3. 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ř. lidskou 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 3×1 a ne matice 3×3). Výsledkem je rozšířený vektor globálních souřadnic špičky prstu. Jinak samozřejmě 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í 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ý".

2006-12-15 | Mircosoft
Reklamy: