Skip to content

Commit 616115e

Browse files
committed
提交Matrix的md文章
1 parent 6842e14 commit 616115e

3 files changed

Lines changed: 66 additions & 52 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
## 归档文章
1717

18-
[你需要知道的Android拍照适配问题](notes/你需要知道的Android拍照适配问题.md)
18+
- [你需要知道的Android拍照适配问题](notes/你需要知道的Android拍照适配问题.md)
19+
- [你深入理解Android中的Matrix](notes/你深入理解Android中的Matrix.md)
1920

2021
## 找我
2122

‎notes/深入理解Android中的Matrix.md‎

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
- [齐次坐标系入门级思考](https://oncemore2020.github.io/blog/homogeneous/)
66
- [仿射变换与齐次坐标](https://guangchun.wordpress.com/2011/10/12/affineandhomogeneous/)
77

8+
读完本文,相信你能够搞明白以下三个问题:
9+
10+
- 为什么 Matrix 是个 3 X 3 的矩阵
11+
- Matrix 这个 3 X 3 的矩阵每个元素的作用
12+
- Matrix 的 setXXX、preXXX、postXXX API 方法的工作原理
13+
814
## Matrix 的结构
915

1016
Matrix 是 Android SDK 提供的一个矩阵类,它代表一个 3 X 3 的矩阵(不懂矩阵为何物的童鞋就要自行 Google 了)。 Matrix 提供了让我们获得 Matrix 值的 API —— **getValues**
@@ -23,83 +29,103 @@ Matrix 是 Android SDK 提供的一个矩阵类,它代表一个 3 X 3 的矩
2329

2430
![](http://d.hiphotos.baidu.com/image/pic/item/2934349b033b5bb5425dd68d3ed3d539b600bc3f.jpg)
2531

26-
没错,我们平常利用 Matrix 来进行 Translate(平移)、Scale(缩放)、Rotate(旋转)的操作,实际上就是在操作着这个矩阵中元素的数值来达到我们想要的效果。但是现在问题来了,上面提到的平移、缩放、旋转操作中,旋转和缩放可以用乘法表示,而平移就只能用加法表示,而且 Matrix 是一个 3 X 3 的矩阵,实际上表示这些操作 2 X 2 的矩阵足矣!
32+
实际上我们平常利用 Matrix 来进行 Translate(平移)、Scale(缩放)、Rotate(旋转)的操作,就是在操作着这个矩阵中元素的数值来达到我们想要的效果。但是现在问题来了,上面提到的平移、缩放、旋转操作中,旋转和缩放可以用乘法表示,而平移就只能用加法表示,而且 Matrix 是一个 3 X 3 的矩阵,实际上表示这些操作 2 X 2 的矩阵足矣!
2733

2834
![](http://e.hiphotos.baidu.com/image/pic/item/7acb0a46f21fbe096feccf6063600c338744ad17.jpg)
2935

3036
![](http://h.hiphotos.baidu.com/image/pic/item/bf096b63f6246b600bbcbe00e3f81a4c510fa217.jpg)
3137

3238
![](http://c.hiphotos.baidu.com/image/pic/item/d058ccbf6c81800a737a857ab93533fa828b4722.jpg)
3339

34-
如上,可以依次看到平移、缩放、旋转的矩阵,其中(x',y')表示执行操作后的点的坐标,(x,y)表示执行操作前的点的坐标。tx、ty 分别表示x轴、y轴上平移的距离,Sx、Sy 分别表示x轴、y轴上的缩放比例,θ 则表示旋转角度。至于上面矩阵的推导过程,Google一下其实很多,这里就不去赘述了。以前到了这里,我就会很纳闷,为什么 2 X 2 矩阵能干的事情,偏偏要用 3 X 3 矩阵去做,直到遇到前面提到的两篇文章才有所领悟。
40+
如上,可以依次看到平移、缩放、旋转的矩阵,其中
3541

36-
其实在计算机图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘。那些数学大神们为了方便计算,所以引入了一样神器叫做**齐次坐标**(不懂得童鞋,老规矩自行搜索),将平移的加法合并用乘法表示。所以,2 X 2 的矩阵经过一番变换后,成了下面这样的。
42+
- (x',y')表示执行操作后的点的坐标,(x,y)表示执行操作前的点的坐标
43+
- tx、ty 分别表示x轴、y轴上平移的距离,Sx、Sy 分别表示x轴、y轴上的缩放比例
44+
- θ 则表示旋转角度
45+
46+
至于上面矩阵的推导过程,网络上很多,这里就不去赘述了。以前到了这里,我就会很纳闷,为什么 2 X 2 矩阵能干的事情,偏偏要用 3 X 3 矩阵去做,直到遇到前面提到的两篇文章才有所领悟。
47+
48+
其实在计算机图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘。那些数学大神们为了方便计算,所以引入了一样神器叫做**齐次坐标**(不懂的童鞋,老规矩自行搜索),将平移的加法合并用乘法表示。所以,2 X 2 的矩阵经过一番变换后,成了下面这样的。
3749

3850
![](http://h.hiphotos.baidu.com/image/pic/item/5d6034a85edf8db184610e100123dd54564e7472.jpg)
3951

4052
![](http://b.hiphotos.baidu.com/image/pic/item/c83d70cf3bc79f3d89569944b2a1cd11728b290a.jpg)
4153

4254
![](http://b.hiphotos.baidu.com/image/pic/item/5fdf8db1cb13495458519a105e4e9258d1094a72.jpg)
4355

44-
## 验证结果
45-
46-
## 总结
47-
56+
至此,我们可以得知**为什么 Matrix 是一个 3 X 3 的矩阵**,其实 2 X 2 的矩阵是足以表示的,不过是为了方便计算而合并写成了 3 X 3 的格式。
4857

58+
## Matrix 元素的作用
4959

50-
## applyTransformation
60+
一个 Matrix 共有 9 个元素,那么它每个元素的值发生改变会起到什么作用呢?按照前面所示的齐次坐标转换得到 3 X 3 的矩阵和 Android 文档提供的官方结构相对应,我们不难看出下面的对应关系(其实从 Matrix 中每个位置的常量命名也可以看出来):
5161

52-
传入两个参数 void applyTransformation (float interpolatedTime, Transformation t)
62+
![](http://f.hiphotos.baidu.com/image/pic/item/aec379310a55b3193603a1034ba98226cefc17c9.jpg)
5363

54-
interpolatedTime:时间比例系数,由0变化到1;
55-
t:包含两个部分,一个Alpha值和一个Matrix矩阵,Matrix默认是一个3X3的单位矩阵
64+
![](http://e.hiphotos.baidu.com/image/pic/item/562c11dfa9ec8a136f837496ff03918fa0ecc02e.jpg)
5665

57-
https://developer.android.com/reference/android/view/animation/Animation.html#applyTransformation(float, android.view.animation.Transformation)
66+
![](http://b.hiphotos.baidu.com/image/pic/item/aa64034f78f0f73676046f770255b319eac413c9.jpg)
5867

59-
## Animation API小结
68+
从这我们可以看出这个 Matrix 结构中的每个参数发挥着如下作用:
6069

61-
可以在xml中做的,也可以在代码里面做到
70+
- MTRANS_X、MTRANS_Y 同时控制着 Translate
71+
- MSCALE_X、MSCALE_Y 同时控制着 Scale
72+
- MSCALE_X、MSKEW_X、MSCALE_Y、MSKEW_Y 同时控制着 Rotate
73+
- 从名称上看,我们可以顺带看出 MSKEW_X、MSKEW_Y 同时控制着 Skew
6274

63-
动画的构造函数参数要么是绝对的像素值,要么是相对某个View的比例值。
75+
如果要进行代码验证的话,也非常简单,例如直接只对 Matrix 做 Translate 的 API 调用操作,再将 Matrix 的信息打印到控制台,你会发现整个 Matrix 确实只有 MTRANS_X、MTRANS_Y 两个位置的数字在发生变化。其他 Scale、Rotate、Skew 操作也是一样,感兴趣的童鞋可以自行代码验证一番。
6476

65-
## Animation 实现原理
77+
至此,我们可以大致弄清矩阵每个元素的作用。至于 MPERSP_0、MPERSP_1、MPERSP_2 这三个参数,目前暂时不得而知,网上有文章说这三个参数控制着透视变换,但是文档和 API 上都没怎么提及,所以还是有待验证研究的,有明白的童鞋不妨留言赐教一下,不胜感激。
6678

67-
研究动画,如何实现,应该对其原理进行分析才对。
79+
## 理解 Matrix API 调用
6880

69-
跟 View 的绘制原理有关,需要了解。
81+
按照第一小节里面通过齐次坐标转换而来的矩阵方程可以知道,假设一根线执行了平移操作,相当于线上每个点的坐标被下方的矩阵左乘。(缩放和旋转操作也是同理)
7082

71-
Android 动画框架详解:https://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt1/
83+
![](http://f.hiphotos.baidu.com/image/pic/item/5882b2b7d0a20cf49c1f77a87e094b36acaf993e.jpg)
7284

73-
## 自定义 Animation
85+
如果要进行同时缩放、平移之类的符合变化操作,也无非就是选取相应的矩阵做左乘操作。为了加深矩阵变换对应 Matrix API 调用的理解,直接通过下面的一个自定义的动画效果和代码来讲解好了。
7486

75-
http://www.cnblogs.com/wondertwo/p/5295976.html
87+
```java
7688

77-
矩阵知识,以及矩阵生成的XY轴的图如何展示(有什么工具可以画出来吗)
89+
public class SimpleCustomAnimation extends Animation {
7890

79-
例子:http://www.apkbus.com/blog-104974-52806.html
91+
private int mWidth, mHeight;
8092

93+
@Override
94+
public void initialize(int width, int height, int parentWidth, int parentHeight) {
95+
super.initialize(width, height, parentWidth, parentHeight);
96+
this.mWidth = width;
97+
this.mHeight = height;
98+
}
8199

82-
## 关于 Matrix
100+
@Override
101+
protected void applyTransformation(float interpolatedTime, Transformation t) {
102+
Matrix matrix = t.getMatrix();
103+
Matrix matrix = t.getMatrix();
104+
matrix.preScale(interpolatedTime, interpolatedTime);//缩放
105+
matrix.preRotate(interpolatedTime * 360);//旋转
106+
//下面的Translate组合是为了将缩放和旋转的基点移动到整个View的中心,不然系统默认是以View的左上角作为基点
107+
matrix.preTranslate(-mWidth / 2, -mHeight / 2);
108+
matrix.postTranslate(mWidth / 2, mHeight / 2);
109+
}
110+
}
83111

84-
Matrix 是一个 3 X 3 的矩阵
112+
```
85113

86-
不懂矩阵的乘法,可以查看阮一峰先生的博文 [理解矩阵乘法](http://www.ruanyifeng.com/blog/2015/09/matrix-multiplication.html),或者去维基百科。
114+
熟悉动画这块的童鞋肯定知道,Animation 就是通过不断改变 applyTransformation 函数传入的 Matrix 来实现各种各样的动画效果的,通过上面 applyTransformation 寥寥的几行 Matrix 的复合变换操作可以得到如下效果
87115

88-
详细介绍 Android Matrix 矩阵的文章:
116+
![](http://f.hiphotos.baidu.com/image/pic/item/9358d109b3de9c82048c06f86481800a18d843d8.jpg)
89117

90-
Android Matrix矩阵详解:http://www.maplejaw.com/2016/06/21/Android-Matrix%E7%9F%A9%E9%98%B5%E8%AF%A6%E8%A7%A3/index.html
118+
实际上这几行代码用矩阵来表示就相当于如下所示:
91119

92-
Android Matrix:http://www.cnblogs.com/qiengo/archive/2012/06/30/2570874.html (透视那块,既然文档没有提,那就稍作解释然后忽略即可)
120+
![](http://d.hiphotos.baidu.com/image/pic/item/c8ea15ce36d3d539cd1eedb43287e950352ab0a2.jpg)
93121

94-
矩阵的左乘右乘法概念:
122+
关于代码的作用上边已经给出了注释,这里就不多写了。主要还是要弄明白 Matrix 复合变换中 pre 、 post 等操作与其对应的矩阵发生的左乘、右乘变化。
95123

96-
http://www.cnblogs.com/ylwn817/archive/2011/12/15/2288921.html
97-
98-
http://blog.csdn.net/linmiansheng/article/details/18820599
124+
## 总结
99125

100-
2D平面中关于矩阵(Matrix)跟图形变换的讲解: http://blog.csdn.net/linmiansheng/article/details/18801947
126+
到此,整篇文章已经完结,相信已经能够让你明白开头提到的三个问题。其实我们也可以发现,Google 封装了 Matrix 已经是很完美了,几乎屏蔽了所有的数学细节,使得我这种数学水平一般的开发者也能够去调用相应的 API 实现一些简单的效果。虽然被封装得很完美,但掌握相应的一些原理,依旧可以帮你更好的理解一些技术实现,此次加深了对 Matrix 一些操作的理解,帮我自己解决了以前不少的困惑,不知道有没有帮你 get 到一些什么呢?
101127

102-
对于其次坐标的理解:https://oncemore2020.github.io/blog/homogeneous/
128+
上面给的示例代码很简单,复制黏贴即可运行玩耍,实在需要直接运行源码的童鞋就到 https://github.com/D-clock/AndroidStudyCode 找吧!
103129

104130

105131

‎src/main/java/com/clock/study/animation/SimpleCustomAnimation.java‎

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,16 @@ public void initialize(int width, int height, int parentWidth, int parentHeight)
2525
super.initialize(width, height, parentWidth, parentHeight);
2626
this.mWidth = width;
2727
this.mHeight = height;
28-
//setFillAfter(true);
29-
//setDuration(15000);
3028
}
3129

3230
@Override
3331
protected void applyTransformation(float interpolatedTime, Transformation t) {
3432
Matrix matrix = t.getMatrix();
35-
//matrix.setTranslate((float) Math.sin(interpolatedTime * 50), interpolatedTime * 350);
36-
//matrix.setRotate(interpolatedTime * 90);
37-
//matrix.setScale(interpolatedTime * 3, interpolatedTime * 3);
38-
//matrix.setSkew(interpolatedTime * 2, 0);
39-
//matrix.setSkew(0, interpolatedTime * 2);
40-
//matrix.setTranslate(0, (float) Math.sin(interpolatedTime * 80) * 10);
41-
//matrix.setScale(interpolatedTime * 1, interpolatedTime * 1, mWidth / 2, mHeight / 2);//线性缩放
42-
/*float[] data = new float[9];
43-
matrix.getValues(data);
44-
data[Matrix.MPERSP_1] = interpolatedTime * 1;
45-
matrix.setValues(data);*/
46-
matrix.preScale(interpolatedTime, interpolatedTime);
47-
matrix.preRotate(interpolatedTime * 360);
33+
matrix.preScale(interpolatedTime, interpolatedTime);//缩放
34+
matrix.preRotate(interpolatedTime * 360);//旋转
35+
//下面的Translate组合是为了将缩放和旋转的基点移动到整个View的中心,不然系统默认是以View的左上角作为基点
4836
matrix.preTranslate(-mWidth / 2, -mHeight / 2);
4937
matrix.postTranslate(mWidth / 2, mHeight / 2);
50-
//t.setAlpha(interpolatedTime);
5138
Log.i(TAG, "-------------applyTransformation-------------");
5239
Log.i(TAG, "interpolatedTime:" + interpolatedTime);//动画持续的时间,时间比例系数(0.0 到 1.0)之间
5340
Log.i(TAG, "transformation:" + t);//控制动画效果,Transformation包含两个信息,一个Alpha值,一个Matrix矩阵,这里的Matrix默认是一个单位矩阵

0 commit comments

Comments
 (0)