Partilhar via


Por que a ordem de transformação é significativa

Um único objeto Matrix pode armazenar uma única transformação ou uma sequência de transformações. Esta última é chamada de transformação composta. A matriz de uma transformação composta é obtida multiplicando as matrizes de transformações individuais.

Exemplos de transformação composta

Numa transformação composta, a ordem das transformações individuais é importante. Por exemplo, se você primeiro girar, depois escalar, depois traduzir, obterá um resultado diferente do que se primeiro traduzir, depois girar, depois escalar. No GDI+, as transformações compostas são construídas da esquerda para a direita. Se S, R e T são matrizes de escala, rotação e translação, respectivamente, então o produto SRT (nessa ordem) é a matriz da transformação composta que primeiro escala, depois gira e depois traduz. A matriz produzida pelo produto SRT é diferente da matriz produzida pelo produto TRS.

Uma razão pela qual a ordem é significativa é que transformações como rotação e dimensionamento são feitas em relação à origem do sistema de coordenadas. Dimensionar um objeto que está centrado na origem produz um resultado diferente do dimensionamento de um objeto que foi movido para longe da origem. Da mesma forma, girar um objeto que está centrado na origem produz um resultado diferente de girar um objeto que foi movido para longe da origem.

O exemplo a seguir combina escala, rotação e translação (nessa ordem) para formar uma transformação composta. O argumento Append passado para o método RotateTransform indica que a rotação seguirá o dimensionamento. Da mesma forma, o argumento Append passado para o método TranslateTransform indica que a translação seguirá a rotação. Append e Prepend são membros da MatrixOrder enumeração.

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)

O exemplo a seguir faz as mesmas chamadas de método que o exemplo anterior, mas a ordem das chamadas é invertida. A ordem resultante das operações é primeiro transladar, depois girar, depois escalar, o que produz um resultado muito diferente de primeiro escalar, depois girar, depois transladar.

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)

Uma maneira de inverter a ordem das transformações individuais em uma transformação composta é inverter a ordem de uma sequência de chamadas de método. Uma segunda maneira de controlar a ordem das operações é alterar o argumento de ordem matricial. O exemplo a seguir é o mesmo que o exemplo anterior, exceto que Append foi alterado para Prepend. A multiplicação da matriz é feita na ordem SRT, onde S, R e T são as matrizes para escalar, girar e traduzir, respectivamente. A ordem da transformação composta é primeiro escalar, depois girar e, em seguida, traduzir.

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)

O resultado do exemplo imediatamente anterior é o mesmo do primeiro exemplo neste tópico. Isso ocorre porque invertemos tanto a ordem das chamadas de método quanto a ordem da multiplicação da matriz.

Ver também