Sdílet prostřednictvím


Proč je pořadí transformace významné

Jeden objekt Matrix může ukládat jednu transformaci nebo posloupnost transformací. Druhá se nazývá složená transformace. Matice složené transformace se získá vynásobením matic jednotlivých transformací.

Příklady složených transformací

Ve složené transformaci je důležité pořadí jednotlivých transformací. Pokud například nejprve otočíte, potom změníte měřítko a nakonec přeložíte, dostanete jiný výsledek než když nejprve přeložíte, potom otočíte a nakonec změníte měřítko. V GDI+ se složené transformace vytvářejí zleva doprava. Pokud jsou S, R a T matice škálování, otočení a překladu, pak matice výsledné transformace je součin SRT (v tomto pořadí), který nejprve škáluje, poté otočí a nakonec přeloží. Matice vytvořená produktem SRT se liší od matice vyrobené produktem TRS.

Důležitost pořadí spočívá v tom, že transformace jako otáčení a škálování se provádějí s ohledem na počátek souřadnicového systému. Změna velikosti objektu, který je uprostřed na počátku, způsobí jiný výsledek než změna velikosti objektu přesunutého od původního zdroje. Podobně otočení objektu, který je uprostřed na počátku, vytvoří jiný výsledek než otočení objektu, který byl přesunut od původu.

Následující příklad kombinuje škálování, otočení a překlad (v tomto pořadí) a tvoří složenou transformaci. Argument Append předán metodě RotateTransform označuje, že rotace bude následovat po škálování. Podobně argument Append, který byl předán metodě TranslateTransform, znamená, že překlad bude následovat rotaci. Append a Prepend jsou členy výčtu MatrixOrder.

Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.RotateTransform(28, MatrixOrder.Append);
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append);
e.Graphics.DrawRectangle(pen, rect);
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.RotateTransform(28, MatrixOrder.Append)
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append)
e.Graphics.DrawRectangle(pen, rect)

Následující příklad provádí stejná volání metody jako předchozí příklad, ale pořadí volání je obrácené. Výsledné pořadí operací je nejprve posunout, potom otočit a nakonec změnit měřítko, což vede k velmi odlišnému výsledku oproti tomu, kdy se nejprve změní měřítko, pak otočí a nakonec posune.

Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append);
e.Graphics.RotateTransform(28, MatrixOrder.Append);
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.DrawRectangle(pen, rect);
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append)
e.Graphics.RotateTransform(28, MatrixOrder.Append)
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.DrawRectangle(pen, rect)

Jedním ze způsobů, jak obrátit pořadí jednotlivých transformací ve složené transformaci, je obrátit pořadí posloupnosti volání metody. Druhým způsobem řízení pořadí operací je změna argumentu pořadí matice. Následující příklad je stejný jako předchozí příklad s tím rozdílem, že Append byl změněn na Prepend. Násobení matice se provádí v pořadí SRT, kde S, R a T jsou matice pro měřítko, otočení a posunutí. Pořadí složené transformace je nejprve škálovat, poté otočit a nakonec posunout.

Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Prepend);
e.Graphics.RotateTransform(28, MatrixOrder.Prepend);
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.DrawRectangle(pen, rect);
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Prepend)
e.Graphics.RotateTransform(28, MatrixOrder.Prepend)
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.DrawRectangle(pen, rect)

Výsledek bezprostředně předcházejícího příkladu je stejný jako výsledek prvního příkladu v tomto tématu. Důvodem je to, že jsme převráceli pořadí volání metody i pořadí násobení matice.

Viz také