自定义View

自定义View(十)Matrix 基础理论与使用

2018-11-20  本文已影响0人  光羽隼

Matrix就是矩阵的意思,所有的控件中都有Matrix的身影。

Matrix是一个三阶矩阵,主要功能是坐标映射,数值变换,见下图

Matrix

再讲下边的内容之间,先提前介绍一下下边用到的名词:

名词 解释
单位矩阵 单位矩阵
M 原始矩阵,没有变换之前的矩阵
A 变换
M` 结果矩阵
T 平移变换
-T 反向平移变换
R 旋转变换

Matrix基本原理

Matrix的根本作用就是坐标的变化;基本变换有平移(translate),缩放(scale),旋转(skew),错切四种。


矩阵中各数据组合所指
矩阵中各数据组合所指

最后一行的数据透视使用在3D变换中

缩放(scale)

在进行缩放的时候需要变换(MSCALE_X,MSCALE_Y)这两个值,分别作用于x和y。


缩放
X=K1*X0
Y=K2*Y0

错切(skew)

错切需要变换(MSKEW_X,MSKEW_Y),分别作用于水平错切和垂直错切;


错切
X=X0+K1*Y0
Y=K2*X0+Y0

旋转(rotate)

当要旋转 θ角度的时候,博客中计算了一遍,讲了下边矩阵变换数据的来历,我看了一遍也记不住,还是及这个图来的快。。。。


旋转

平移(translate)

平移需要修改的是最后一列的前两个数据(MTRANS_X,MTRANS_Y),分别作用在x和y 上。


平移

总结

看了上边的几种变换,其实就是对应修改单位矩阵中的特定数值。比如说,要旋转,就要修改左上角四个数值,得到变换矩阵,拿变换矩阵跟原始矩阵相乘。平移,就是修改单位矩阵中最后一列的上边两个数值,如果你只想在x轴平移,那么只需要修改最后一列的第一个数据。看了上边的东西,大概知道矩阵作用了,可是矩阵该怎么在实际代码中使用呢?一步一步来

Matrix 矩阵复合原理

矩阵复合有三种,前乘(pre),后乘(post),设置(set)
为什么会有前乘和后乘的区别呢?
因为

矩阵乘法不满足交换律,即 AB ≠ BA
矩阵乘法满足结合律,即 (AB)C = A(BC)
矩阵与单位矩阵相乘结果不变,即 A * I = A

前乘(pre)

前乘就是原始矩阵在前边,变换矩阵在后边

M`=M*A

后乘(post)

后乘就是原始矩阵在后边,变换矩阵在前边

M`=S*A

设置(set)

设置不是矩阵的乘法,而是覆盖原来的矩阵,使用设置之后会对之前的操作有影响。

几个常见的错误结论:

1.pre 是顺序执行,post 是逆序执行
2.pre 是先执行,而 post 是后执行

其实前乘后乘执行的顺序,跟这句代码所在的位置没有关系。

下边将一个远博客中的例子。
我们想讲一个控件先平移到屏幕的中间,然后对控件做一系列缩放,错切,平移等等操作,最后我们再将控件平移回远位置。
上面的操作我们可以使用三种方法实现:

第一种前后两个平移全部使用前乘(pre)

Matrix matrix=new Matrix();
matrix.preTranslate(200,200);
matrix.preRotate(angle);
matrix.preTranslate(-200,-200);

M`=M*T*R-T
新实例化的矩阵就是单位矩阵,所以这里M为原始矩阵,所以上边的式子可以简化为
M`=*T*R
-T

第二种前后两个平移全部使用后乘

Matrix matrix=new Matrix();
matrix.postTranslate(-200,-200);
matrix.postRotate(angle);
matrix.postTranslate(-200,-200);

化简公式为M`=T*R*-T*

混合使用前乘和后乘

Matrix matrix = new Matrix();
// 各种操作,旋转,缩放,错切等,可以执行多次。
matrix.postTranslate(pivotX,pivotY);
matrix.preTranslate(-pivotX, -pivotY);

M' = TM ... -T = T ... *-T
这种方法是为了避免两次平移被拉得太开,代码量多的话,会容易漏写。

pre 和 post 就是用来调整乘法顺序的,由于矩阵乘法不满足交换律,所以前乘后乘的结果是不一样的。

上面都是矩阵的基础知识的理解,到底该怎么用。下边开始总结:

Matrix的基本使用

先看一下Matrix的基础方法

方法 解释
Matrix (); 构造方法,创建一个新的矩阵,为单位矩阵
Matrix (Matrix src); 构造方法,对src矩阵进行深拷贝,也就是创建一个跟src矩阵一毛一样的矩阵。
equals 比较两个Matrix的数值是否相同。
hashCode 获取Matrix的哈希值。
toString 将Matrix转换为字符串: Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
toShortString 将Matrix转换为短字符串: [1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]
void set (Matrix src) 没有返回值,有一个参数,作用是将参数Matrix的数值复制到当前Matrix中。如果参数为空,则重置当前Matrix,相当于reset()。
void reset () 重置当前Matrix(将当前Matrix重置为单位矩阵)。
void setValues (float[] values) setValues的参数是浮点型的一维数组,长度需要大于9,拷贝数组中的前9位数值赋值给当前Matrix。
void getValues (float[] values) 很显然,getValues和setValues是一对方法,参数也是浮点型的一维数组,长度需要大于9,将Matrix中的数值拷贝进参数的前9位中。

数值计算方法

方法 解释
void mapPoints (float[] pts) 计算一组点基于当前Matrix变换后的位置,讲计算后的矩阵数值存放到pts数组中
void mapPoints (float[] dst, float[] src) 与上个方法作用一样,只不过是讲计算后的结果存放到dst数组中,src不变
void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) 作用和上边两个方法一致,只不过可以指定存储的数组长度。dstIndex表示目标数据存储位置起始下标,srcIndex表示原数据存储起始下标,pointCount表示计算的点个数
float mapRadius (float radius) 测量半径,由于圆可能会因为画布变换变成椭圆,所以此处测量的是平均半径。radius表示原半径,返回的是经过变换之后的半径。
boolean mapRect (RectF rect) 测量rect并将测量结果放入rect中,返回值是判断矩形经过变换后是否仍为矩形
boolean mapRect (RectF dst, RectF src) 测量src并将测量结果放入dst中,返回值是判断矩形经过变换后是否仍为矩形
mapVectors 和上边mapPoints方法类似,不过这里测量的是向量,也就是说平移操作不会影响结果

set/pre/post控制平移(translate)、缩放(scale)、旋转(rotate)、 错切(skew) 的变换

上边在讲Matrix原理的时候就已经对这些方法进行过讲解。

特殊方法

setPoluToPoly()

boolean setPolyToPoly (
        float[] src,    // 原始数组 src [x,y],存储内容为一组点
        int srcIndex,   // 原始数组开始位置
        float[] dst,    // 目标数组 dst [x,y],存储内容为一组点
        int dstIndex,   // 目标数组开始位置
        int pointCount) // 测控点的数量 取值范围是: 0到4

这个方法是控制两部分进行变换的。一是进行变换的点的数据,而是变化的点数。
srcIndex定义要变换哪些点,中心点可以,四边形四边中点可以,四边形四个角可以,这里去的是容易获取的点;dstIndex表示根据srcIndex变换后的点;pointCount是变换点的数量;比如说你上边定义了四个点的变化,但是pointCount是1,那么结果可能就不是你想要得到的。

pointCount 摘要
0 相当于reset
1 相当于translate
2 可以进行 缩放、旋转、平移 变换
3 可以进行 缩放、旋转、平移、错切 变换
4 可以进行 缩放、旋转、平移、错切以及任何形变

这个方法还是很有必要仔细研究的,具体代码我就不贴了,原博客中有详细讲解

setRectToRect

这个方法的作用主要就是填充的模式,比如一张图片要放到父空间中,图片尺寸比较小,那这张图片是要放在左上角,还是右下角,还是中间,还是铺满呢?setRectToRect方法就是控制这些操作的。

boolean setRectToRect (RectF src,           // 源区域
                RectF dst,                  // 目标区域
                Matrix.ScaleToFit stf)      // 缩放适配模式
模式 摘要
CENTER 居中,对src等比例缩放,将其居中放置在dst中。
START 顶部,对src等比例缩放,将其放置在dst的左上角。
END 底部,对src等比例缩放,将其放置在dst的右下角。
FILL 充满,拉伸src的宽和高,使其完全填充满dst。

rectStaysRect

判断举行变换之后是否还是矩形。

invert

获取矩阵的逆矩阵
boolean invert (Matrix inverse)

上一篇下一篇

猜你喜欢

热点阅读