Dlaczego kolejność przekształcania jest ważna

Pojedynczy Matrix obiekt może przechowywać pojedynczą transformację lub sekwencję przekształceń. Ten ostatni jest nazywany transformacją złożoną. Macierz przekształcenia złożonego jest uzyskiwana przez pomnożenie macierzy poszczególnych przekształceń.

Przykłady transformacji złożonej

W transformacji złożonej kolejność poszczególnych przekształceń jest ważna. Jeśli na przykład najpierw obrócisz, przeprowadź skalowanie, a następnie przetłumacz, uzyskasz inny wynik niż w przypadku pierwszego tłumaczenia, a następnie obróć, a następnie przeprowadź skalowanie. W przypadku interfejsu GDI+przekształcenia złożone są tworzone od lewej do prawej. Jeśli macierze S, R i T są odpowiednio skalowane, obracane i translacyjne, wówczas produkt SRT (w tej kolejności) jest macierzą transformacji złożonej, która najpierw skaluje, a następnie obraca, a następnie tłumaczy. Macierz wygenerowana przez produkt SRT różni się od macierzy produkowanej przez produkt TRS.

Jedną z przyczyn jest to, że przekształcenia, takie jak rotacja i skalowanie, są wykonywane w odniesieniu do źródła układu współrzędnych. Skalowanie obiektu, który jest wyśrodkowany na początku, powoduje inny wynik niż skalowanie obiektu, który został przeniesiony z punktu początkowego. Podobnie obracanie obiektu, który jest wyśrodkowany na początku, powoduje inny wynik niż obracanie obiektu, który został przeniesiony z punktu początkowego.

Poniższy przykład łączy skalowanie, rotację i tłumaczenie (w tej kolejności) w celu utworzenia złożonej transformacji. Argument Append przekazany do RotateTransform metody wskazuje, że rotacja będzie podążać za skalowaniem. Podobnie argument Append przekazany do TranslateTransform metody wskazuje, że tłumaczenie będzie zgodne z rotacją. Append i Prepend są członkami MatrixOrder wyliczenia.

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)

W poniższym przykładzie wywołania metody są takie same jak w poprzednim przykładzie, ale kolejność wywołań jest odwrócona. Wynikowa kolejność operacji jest najpierw tłumaczona, a następnie obracana, a następnie skalowana, co powoduje bardzo inny wynik niż pierwsza skala, a następnie obracanie, a następnie tłumaczenie.

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)

Jednym ze sposobów odwrócenia kolejności poszczególnych przekształceń w transformacji złożonej jest odwrócenie kolejności wywołań metod. Drugim sposobem kontrolowania kolejności operacji jest zmiana argumentu kolejności macierzy. Poniższy przykład jest taki sam jak w poprzednim przykładzie, z tą różnicą, że Append został zmieniony na Prepend. Mnożenie macierzy odbywa się odpowiednio w kolejności SRT, gdzie S, R i T są macierzami do skalowania, obracania i tłumaczenia. Kolejność transformacji złożonej jest najpierw skalowana, a następnie obracana, a następnie tłumaczona.

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)

Wynik bezpośrednio poprzedniego przykładu jest taki sam jak w wyniku pierwszego przykładu w tym temacie. Dzieje się tak, ponieważ odwracaliśmy zarówno kolejność wywołań metody, jak i kolejność mnożenia macierzy.

Zobacz też