Bedeutung der Transformationsreihenfolge
In einem einzelnen Matrix-Objekt kann entweder eine einzelne Transformation oder eine Abfolge von Transformationen gespeichert werden. Der zweite Vorgang wird als zusammengesetzte Transformation bezeichnet. Die Matrix einer zusammengesetzten Transformation ergibt sich aus der Multiplikation der Matrizen der einzelnen Transformationen.
Beispiele für zusammengesetzte Transformationen
In einer zusammengesetzten Transformation ist die Reihenfolge der einzelnen Transformationen von Bedeutung. Wenn Sie beispielsweise zuerst eine Drehung, dann eine Skalierung und zuletzt eine Verschiebung durchführen, erhalten Sie ein anderes Ergebnis, als wenn Sie zuerst eine Verschiebung, dann eine Drehung und zuletzt eine Skalierung durchführen. In GDI+ sind zusammengesetzte Transformationen von links nach rechts aufgebaut. Wenn S, D und Ü der Skalierungs-, Drehungs- und Verschiebungsmatrix entsprechen, dann ist das Produkt SDÜ (in dieser Reihenfolge) die Matrix der zusammengesetzten Transformation, bei der zunächst die Skalierung, dann die Drehung und zuletzt die Verschiebung erfolgt. Die Matrix, die das Ergebnis des Produkts SDÜ ist, unterscheidet sich von der Matrix, die das Ergebnis des Produkts ÜDS ist.
Ein Grund, warum die Reihenfolge von Transformationen, wie Drehungen und Skalierungen, wichtig ist, liegt darin, dass sie mit Bezug auf den Ursprung des Koordinatensystems durchgeführt werden. Die Skalierung eines Objekts, dessen Mittelpunkt im Ursprung liegt, ergibt ein anderes Ergebnis als die Skalierung eines Objekts, das vom Ursprung verschoben wurde. Analog dazu ergibt die Drehung eines Objekts, dessen Mittelpunkt im Ursprung liegt, ein anderes Ergebnis als die Drehung eines Objekts, das vom Ursprung verschoben wurde.
Im folgenden Beispiel bildet die Aneinanderreihung von Skalierung, Drehung und Verschiebung (in dieser Reihenfolge) eine zusammengesetzte Transformation. Das Argument Append, das an die RotateTransform-Methode übergeben wird, zeigt an, dass die Drehung im Anschluss an die Skalierung erfolgt. Dementsprechend zeigt das Argument Append, das an die TranslateTransform-Methode übergeben wird, an, dass die Verschiebung im Anschluss an die Drehung erfolgt. Append und Prepend sind Member der MatrixOrder-Enumeration.
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)
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);
Im folgenden Beispiel werden die gleichen Methoden wie im vorherigen Beispiel aufgerufen, allerdings in umgekehrter Reihenfolge. Daraus ergibt sich die folgende Reihenfolge der Operationen: erst Verschiebung, dann Drehung und dann Skalierung. Das auf diese Weise produzierte Ergebnis unterscheidet sich erheblich von der Reihenfolge Skalierung, dann Drehung, dann Verschiebung.
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)
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);
Eine Möglichkeit, die Reihenfolge der einzelnen Transformationen in einer zusammengesetzten Transformation umzukehren, besteht darin, die Reihenfolge der aufeinander folgenden Methodenaufrufe umzukehren. Eine zweite Möglichkeit, die Operationsreihenfolge zu steuern, besteht darin, das Argument für die Matrixreihenfolge zu ändern. Das folgende Beispiel ist mit dem vorangehenden Beispiel identisch, abgesehen davon, dass Append in Prepend geändert wurde. Die Matrixmultiplikation erfolgt in der Reihenfolge SDV, wobei S, D und V jeweils den Matrizen für Skalierung, Drehung und Verschiebung entsprechen. Die Reihenfolge der zusammengesetzten Transformation lautet: zuerst Skalierung, dann Drehung, dann Verschiebung.
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)
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);
Das Ergebnis des unmittelbar vorangehenden Beispiels ist identisch mit dem Ergebnis des ersten Beispiels in diesem Thema. Das liegt daran, dass sowohl die Reihenfolge der Methodenaufrufe als auch die Reihenfolge der Matrixmultiplikation umgekehrt wurde.