《Practical WPF Charts and Graphics 》翻译——之十一
矩阵操作
WPF里的Matrix结构提供了进行旋转,拉伸和平移的方法。它也实现了一些进行矩阵操作的方法。例如,你也可以使用Invert方法来得到一个可逆矩阵的逆。这个方法没有参数。Multiply方法将两个矩阵相乘并返回一个新矩阵作为结果。下面是一些矩阵操作常用的方法:
Scale—添加一个指定的拉伸向量到Matrix结构 ScaleAt—将矩阵关于指定点拉伸到指定大小 Translate—添加一个指定偏移量的平移到到Matrix结构 Rotate—应用一个关于原点的指定角度的旋转到Matrix结构 RotateAt—关于指定的点旋转矩阵 Skew—在X和Y方向增加一个制定的倾斜角度给Matrix结构 Invert—求Matrix结构的逆矩阵 Multiply—用另一个Matrix结构乘以一个Matrix结构 Transform—通过矩阵变换特定的点,点数组,向量,或者向量数组另外还有和Scale,Translation,Rotation和Skew相关的Prepend方法。缺省的方法是Append。Append和Prepend都决定了矩阵顺序。Append指定新的操作在前一个操作的后面应用;Prepend指定新操作在前一个操作的前面。
让我们考虑一个展示WPF里矩阵操作的例子。创建一个新的WPF windows应用程序项目,命名为Transformation2D。添加一个叫MatrixOperations的WPF window到项目中。这里是例子的XAML文件:
图2-5.WPF矩阵操作的结果
首先,我们检查一下矩阵求逆方法,它求的是矩阵(1, 2, 3, 4, 0, 0)的逆。Matrix.Invert方法得到结果(-2, 1, 1.5, -0.5, 0, 0).这个可以轻易通过矩阵(1, 2, 3, 4, 0, 0) 乘以(-2, 1, 1.5, -0.5, 0, 0)来证明,结果应该等于单位矩阵(1, 0, 0, 1, 0, 0).。事实上:
这确实是单位矩阵,和期望的一样.。
接下来,我们考虑矩阵相乘。在代码里,你创建了两个矩阵m1 = (1, 2, 3, 4, 0, 1)和m2 = (0, 1, 2, 1, 0, 1)。首先用m1乘以m2返回结果到m12;然后用m2乘以m1将结果存入m21。注意如果用矩阵M1乘以m2,结果是存在m12(原文为m1,是不是错了)里。你可以从图2-5看出M12=(4, 3, 8, 7, 2, 2)。事实上:
对于M21=m2×m1,你将期望得到下面的结果:
这和图中显示的(3, 4, 5, 8, 3, 5) 是一致的。
矩阵变换
在前面部分提到,WPF里的矩阵结构也提供了选择,拉伸,和平移矩阵的方法。
你可以使用Rotate和RotateAt方法去选择矩阵。Rotate方法以一个指定的角度选择矩阵。这个方法只有一个参数:一个双精度值用来指定角度。RotateAt方法在你需要改变旋转中心的时候会有用处。它的第一个参数是角度,第二个和第三个参数(都是双精度类型)指定旋转中心。
我们用一个例子来说明WPF里的基本矩阵变换(平移,拉伸,旋转和倾斜)。添加一个新的WPF Window到Transformation2D项目中,命名为MatrixTransforms.下面是例子的XAML文件:
原始的矩阵,m= (1, 2, 3, 4, 0, 1),被进行了各种变换。首先,我们检查拉伸变换,它设定X方向的拉伸系数为1,Y方向为0.5。对于Append拉伸(默认设置),我们得到
这和图2-6显示的结果(1, 1, 3, 2, 0, 0.5)是一样的。另一方面,对于Prepend拉伸,我们得到
这证实了图2-6显示的结果(1, 1, 3, 2, 0, 0.5)。
我们接下来在X方向平移矩阵m一个单位,在Y方向平移一半的单位。对于Append(默认设置)平移,我们得到:
这和图2-6显示的结果(1, 2, 3, 4, 1, 1.5) 一致。
对于Prepend平移,我们进行下面的变换:
它证实了图2-6显示的结果(1, 2, 3, 4, 2.5, 5)。
对于旋转变换,原始矩阵被m旋转45度。在Append选择的情况下,我们得到
注意在前面的计算中,我们使用了 cos(π/4) = sin(π/4) = 0.707。这和图2-6给出的结果一样( -0.707, 2.121, -0.707, 4.95, -0.707, 0.707) 。
对于Prepend旋转,我们得到
这个结果和图2-6中显示的(2.828, 4.243, 1.414, 1.414, 0, 1)一致。
RotateAT方法被设计用在你需要改变旋转中心的情况。事实上,Rotate方法是RotateAt方法的一个特例,它的选转中心是(0,0)。在这个例子里,矩阵m响度点(1,2)旋转了45度。正如本章前面讨论到的,一个对象关于一个任意点P1旋转必须根据下面的步骤进行操作:
平移P1到原点 将它旋转一个想要的角度 将P1平移回原来的点考虑WPF里的矩阵旋转,关于点(1,2)旋转应该表示成下面的形式:
因此,矩阵m的关于点(1,2)Append旋转45度变成
这给出了和图2-6一样的结果(-0.707, 2.121, -0.707, 4.949, 1, 0.586)。存在微小的差异是因为小数舍入。
相似地,关于点(1,2)Prepend旋转45度应该是
同样,结果和图2-6显示的一样。
最后,我们检查Skew方法,它创建了一个剪切变换。这个方法有两个参数,AngleX和AngleY,分别表示,水平和垂直倾斜因子。倾斜变换在齐次坐标系里可以表示成下面的形式
这里,tan(AngleX)和tan(AngleY)分别是X和Y方向的倾斜变换因子。看一下这个例子中的Skew变换。倾斜角度是AngleX=45度,AngleY=30度。这种情况下,Skew矩阵是
因此,对于Append变换,我们得到
这证实了图2-6中显示的结果。
对于Prepend Skew变换,我们得到
结果和图2-6给出的一样。
这里,我对WPF中的矩阵变换进行了详细的解释。这些信息对于理解定义和WPF中的内部表示矩阵,和在WPF应用程序中正确使用矩阵很有用。