为什么转换顺序很重要

单个 Matrix 对象可以存储单个转换或一系列转换。 后者称为复合转换。 复合转换的矩阵是通过乘以单个转换的矩阵获得的。

复合转换示例

在复合转换中,各个转换的顺序非常重要。 例如,如果首先旋转,然后缩放,然后转换,则得到的结果与首次翻译的结果不同,然后旋转,然后缩放。 在 GDI+中,复合转换是从左到右构建的。 如果 S、R 和 T 分别是刻度、旋转和翻译矩阵,则产品 SRT (按顺序)是首先缩放的复合转换的矩阵,然后旋转,然后转换。 由产品 SRT 生成的矩阵不同于产品 TRS 生成的矩阵。

顺序的重要性之一是,诸如旋转和缩放的转换是相对于坐标系的原点进行的。 缩放以原点为中心的对象会生成不同于缩放已移出原点的对象的结果。 同样,旋转原点居中的对象会产生不同于旋转已移出原点的对象的结果。

以下示例组合缩放、旋转和转换(按顺序)形成复合转换。 传递给RotateTransform该方法的参数Append指示旋转将遵循缩放。 同样,参数 Append 传递给方法 TranslateTransform 指示转换将遵循旋转。 AppendPrependMatrixOrder 枚举的成员。

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)

下面的示例进行与前面的示例相同的方法调用,但调用的顺序是相反的。 生成的操作顺序是首先平移,然后旋转,然后缩放,这会产生与先缩放,然后旋转,然后平移截然不同的结果。

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)

在复合转换中反转单个转换顺序的一种方法是反转方法调用序列的顺序。 控制作顺序的第二种方法是更改矩阵顺序参数。 以下示例与前面的示例相同,只不过已 Append 更改为 Prepend。 矩阵乘法按 SRT 的顺序完成,其中 S、R 和 T 是刻度、旋转和转换的矩阵。 复合转换的顺序是先缩放,然后旋转,然后转换。

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)

前面的示例的结果与本主题中第一个示例的结果相同。 这是因为我们反转了方法调用和矩阵乘法的顺序。

另请参阅