Android自定义控件高级进阶与精彩实例
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.1 位置矩阵概述

2.1.1 矩阵运算

在开始讲解位置矩阵的具体内容前,我们先温习一下矩阵的加、减、乘、除运算方法。

2.1.1.1 矩阵的加法与减法

1.运算规则

设矩阵A=imgB=img,则

A±B=img。简言之,两个矩阵相加减,即它们相同位置的元素相加减。

注意:对于行数、列数都相等的两个矩阵(同型矩阵),加减法运算才有意义,即加减法运算才是可行的。

2.运算性质

满足交换律和结合律。

交换律:A+B=B+A

结合律:(A+B)+C=A+(B+C

2.1.1.2 矩阵与数的乘法

1.运算规则

λ乘以矩阵A,就是将数λ乘以矩阵A中的每一个元素,记为λAAλ。特别地,称-AA=(aijm×s的负矩阵。

2.运算性质

满足结合律和分配律。

结合律:(λμA=λμA),(λ+μA=λA+μA

分配律:λA+B)=λA+λB

img

2.1.1.3 矩阵与矩阵的乘法

1.运算规则

A=(aijm×sB=(bijs×n,则AB的乘积是这样一个矩阵C(1)行数与(左矩阵)A相同,列数与(右矩阵)B相同;(2)C的第i行第j列元素ijCA的第i行元素与B的第j列元素对应相乘后取乘积之和。

定义:设Am× s的矩阵,Bs× n的矩阵,那么称m× n的矩阵C为矩阵AB的乘积,记作C=AB,其中矩阵C中的第i行第j列元素可以表示为

img

矩阵乘法举例如下所示:

img

矩阵乘法其实并不难,它的意思就是将第1个矩阵A的第1行与第2个矩阵B的第1列的元素分别相乘,得到的结果相加,将最终的值作为结果矩阵(1,1)位置(第1行第1列)的值。同样,A矩阵的第1行与B矩阵的第2列的元素分别相乘,然后相加,将最终的值作为结果矩阵(1,2)位置(第1行第2列)的值。再如,A矩阵的第2行与B矩阵的第1列的元素分别相乘,然后相加,将最终的值作为结果矩阵(2,1)位置(第2行第1列)的值。

这里主要说明了如下两个问题。

A矩阵的列数必须与B矩阵的行数相同,这样才能相乘。因为我们需要把A矩阵一行中的各个元素与B矩阵一列中的各个元素分别相乘,所以A矩阵的列数与B矩阵的行数必须相同。

●矩阵A乘以矩阵B和矩阵B乘以矩阵A的结果必然是不一样的。

img

2.运算性质(假设运算都是可行的)

(1)结合律:(ABC=ABC

(2)分配律:AB± C)=AB± AC(左分配律),(B± CA=BA± CA(右分配律)

(3)(λAB=λAB)=AλB

这里有一点需要特别注意,那就是矩阵与矩阵的乘法是不满足交换率的。在后面的操作中,我们也会看到前乘和后乘的区别,其主要原因就是因为不满足交换率。

2.1.2 位置矩阵简介

2.1.2.1 位置矩阵是几阶矩阵

在第1章中,我们经常通过Matrix matrix=new Matrix()来创建一个位置矩阵,如果我们将这个原始矩阵打印出来,它是这样的:

img

很明显,这是一个三阶单位矩阵。

接下来,我们来大概地看看位置矩阵中具体每个位置(标志位)的值所代表的含义,大家可以先了解一下,后面会搭配代码细讲。

img

下面以元素MSCALE_X为例来讲解一下其名称组成。

●开头的M:表示这是一个矩阵(Matrix)。

●中间的SCALE:表示这个位置数值的作用,SCALE表示缩放,SKEW表示错切,TRANS表示平移(translate),PERSP表示透视(perspective)。

●下画线后的数值_X:主要用于补充中间的字母,以MSCALE_X为例,其表示在X轴方向上的缩放。另外,MSKEW_Y表示在Y轴方向上的错切;而MPERSP_0比较特殊,表示透视时没有XYZ轴的区分,而是以数值标识的。

2.1.2.2 Canvas的Translate与Matrix

下面将回顾一下Canvas的各个函数,看看在各个函数操作之后对应的矩阵是怎样变化的,初步了解一下位置矩阵的作用。

1.沿X轴平移

如下面的代码所示,沿X轴平移45:

img

此时打印出来的矩阵结果如下:

img

可以看到,在MTRANS_X位置上,原来的数字0变为了45。

2.沿Y轴平移

同样的代码,改为沿Y轴平移45:

img

此时打印出来的矩阵结果如下:

img

同样地,在MTRANS_Y位置上,原来的数字0变为了-45,可见沿Y轴平移了45,但是Matrix与Camera操作的数值是相反的。在camera.translate(0,y,0)操作之后,所对应的矩阵在MTRANS_Y位置上的数值是-y。

大家需要注意,这里只是简单地讲解了位置矩阵中各个位置值的含义,在实际的工作中,并不会用数值变换的方法来直接操作矩阵。

3.沿Z轴平移

很明显,在对位置矩阵各个位置的解释中,找不到MTRANS_Z,这说明其不支持直接对Z轴平移,那么怎么通过Matrix操作来实现Camera沿Z轴平移的操作呢?

同样地,我们来做一个实验,沿Z轴平移45,代码如下:

img

输出结果如下:

img

大家可能觉得很奇怪,我们要沿Z轴平移,那么为什么改变的是MSCALE_X、MSCALE_Y的值呢?大家可以回头看看第1章中演示的沿Z轴平移的效果,可扫码查看效果图。

img

扫码查看动态效果图

从效果图也可以看出,随着沿Z轴平移的距离增大,图像是逐渐变小的。所以,沿Z轴平移需要通过改变图像原大小来实现,这样也就可以理解为什么要改变MSCALE_X、MSCALE_Y的值了。此处不必深究值是如何获得的,因为我们不会用到这个公式,这里就不再详细讲解了。

2.1.2.3 Canvas的Rotate与Matrix

我们再来看看位置矩阵中各个位置代表的含义:

img

很明显,以上没有直接用Rotate标识的位置,因此肯定是通过其他方式来实现Rotate操作的。

下面以绕X轴旋转45°为例,看看对应的Matrix操作,代码如下:

img

对应的矩阵如下:

img

可见,其中改变的是MSCALE_Y和MPERSP_1。

同样地,绕Y轴和绕Z轴旋转也是通过改变其他标志位来实现的,这里就不再一一列举了。另外,有关的计算公式平常是用不到的,而且Matrix类中也有对应的函数。

从本节可以初步看出,位置矩阵中的各个标志位没有直接对Z轴操作的,都是直接对XY轴操作的。

这是因为Matrix是使用2D坐标系来操作控件的,而Camera则通过模拟3D坐标系,最终通过Matrix来实现虚拟的三维效果。在后面的章节中,Matrix所使用的坐标系都是2D坐标系。

到这里,大家对位置矩阵就有了一个初步的认识。下面我们将讲解Matrix类中各个函数的用法。