关于Android Matrix pre post 的理解
2017-01-30 00:28
495 查看
前言
最近由于项目需要,接触到矩阵相关的知识较多,在实践后于此做知识记录,方便下次用到的时候可以快速的捡起来。正文
理论上,矩阵是按照长方形阵列排列的复数或实数集合实际上,从源码看Matrix是用于坐标变换的3x3的矩阵【本文讨论的是graphics包下的矩阵,非opengl包下的矩阵】
单个Matrix对象在Java层保留一个Native层对象的指针,在Native堆上进行实际内存分配、使用、回收
Java层内存是个【壳】,Native层内存才是【核】。
关键字段
3x3矩阵中各个字段
以(0,0)点为轴心旋转一定的角度,则实际改变的是左上角的四个数据
平移,右上角2个元素
旋转和缩放,左上角4个元素
数据结构
float数组,长度9单位矩阵
⎡⎣⎢⎢100010001⎤⎦⎥⎥第0、4、8号地址数值为1,其它地址为0的矩阵。单位矩阵乘法满足交换律。
变换过程
假设原坐标点为(x0, y0),作用于矩阵M,则变换后的坐标点为(x1, y1)。(x1, y1, 1) = M * (x0, y0, 1)
这里的难点在于【M = M1 * M2 … * Mn】,即M可以为多个矩阵变换之后的结果。
计算顺序
M = M1 * M2 * ... * Mn 后 <------------------------------------ 先
从右边开始向左边进行矩阵的乘法运算,最后得出结果矩阵M
M(n-1) * Mn 结果为矩阵Nn
M(n-2) * Nn结果为矩阵N(n-1)
M(n-3) * N(n-1)结果为N(n-2)
…
为什么从右向左计算?个人理解是一种栈结构,每次做变换的时候都会在栈顶压入一个变换,最后退栈时依次从栈顶做矩阵乘法,故形成一种从右向左计算
先乘
M’ = M * X
当前矩阵为M
变换矩阵为X
在当前矩阵的【右边】乘以矩阵X,此处X可以为平移矩阵T, 旋转矩阵R, 缩放矩阵S
由于矩阵从右向左运算,故右边称之为【先】乘。
后乘
M’ = X * M
当前矩阵为M
变换矩阵为X
在当前矩阵的【左边】乘以矩阵X
由于矩阵从右边向左边运算,故左边称之为【后】乘。
Canvas中的矩阵变换
Canvas中的矩阵变换都是先乘,也就是在当前矩阵的右边乘以一个矩阵在ViewRootImpl从上向下遍历的过程中,在draw阶段作用在同一个Canvas对象的不同矩阵将不断放在右边
最后从右向左计算出整个变换矩阵M
然后拿着M矩阵对原坐标(x0, y0)进行矩阵变换
利用这个属性可以对某个View进行缩放截图等。
例如,Canvas中相对某点做缩放的代码
/** 572 * Preconcat the current matrix with the specified scale. 573 * 574 * @param sx The amount to scale in X 575 * @param sy The amount to scale in Y 576 * @param px The x-coord for the pivot point (unchanged by the scale) 577 * @param py The y-coord for the pivot point (unchanged by the scale) 578 */ 579 public final void scale(float sx, float sy, float px, float py) { 580 translate(px, py); 581 scale(sx, sy); 582 translate(-px, -py); 583 }
translate
551 /** 552 * Preconcat the current matrix with the specified translation 553 * 554 * @param dx The distance to translate in X 555 * @param dy The distance to translate in Y 556 */ 557 public void translate(float dx, float dy) { 558 native_translate(mNativeCanvasWrapper, dx, dy); 559 }
scale
561 /** 562 * Preconcat the current matrix with the specified scale. 563 * 564 * @param sx The amount to scale in X 565 * @param sy The amount to scale in Y 566 */ 567 public void scale(float sx, float sy) { 568 native_scale(mNativeCanvasWrapper, sx, sy); 569 }
上面以(px, py)为轴心进行缩放(sx, sy)的scale API内部做的事情:
假如当前矩阵为M1,则
translate(px, py)
M1 * T1 先乘平移矩阵T1
scale(sx, sy)
M1 * T1 * S 先乘缩放矩阵S
translate(-px, -py)
M1 * T1 * S * T2 先乘平移矩阵T2
这三步的结果M = M1 * (T1 * (S * T2))
把M作用在原来的坐标点 (x1, y1, 1) = M * (x0, y0, 1)
从感官上理解经过以下步骤
整个图像先做相对于轴点的逆向平移变换
再做缩放变换
最后把图像平移回轴点,这样轴点的坐标不会受到缩放的影响。
pre和post混合使用
在理解了pre和post实际做的事情之后,就可以分析别人代码在干什么以及合理使用矩阵来达到你想要的效果。例如我们要做变换M = T1 * R1 * S1 则写法可以是:
【注】
sin 30° = 0.5
cos 30° = 0.8660254
2 * sin 30° = 1.0
2 * cos 30° = 1.7320508
第一种写法
Matrix matrix = new Matrix(); matrix.preTranslate(1,1); matrix.preRotate(30); matrix.preScale(2, 2);
结果矩阵为:
Matrix{[1.7320508, -1.0, 1.0][1.0, 1.7320508, 1.0][0.0, 0.0, 1.0]}
第二种写法
Matrix matrix = new Matrix(); matrix.postScale(2, 2); matrix.postRotate(30); matrix.postTranslate(1,1);
结果矩阵为:
Matrix{[1.7320508, -1.0, 1.0][1.0, 1.7320508, 1.0][0.0, 0.0, 1.0]}
第三种写法
Matrix matrix = new Matrix(); matrix.preScale(2, 2); matrix.postRotate(30); matrix.postTranslate(1,1);
结果矩阵为:
Matrix{[1.7320508, -1.0, 1.0][1.0, 1.7320508, 1.0][0.0, 0.0, 1.0]}
第四种写法
Matrix matrix = new Matrix(); matrix.preRotate(30); matrix.postTranslate(1,1); matrix.preScale(2, 2);
结果矩阵为:
Matrix{[1.7320508, -1.0, 1.0][1.0, 1.7320508, 1.0][0.0, 0.0, 1.0]}
…
总结
上文通过对Matrix的一些基本概念和pre、post变换的原理进行记录,方便根据需求做相应的变换来处理Bitmap和Canvas。因本人水平有限,难免理解不到位,请大家多多指正。参考
android matrix 最全方法详解与进阶(完整篇)Android UI学习|对Canvas和Matrix的理解
相关文章推荐
- Android Matrix的 pre post set方法的理解(zz)
- Android中Matrix的pre post set方法理解
- Android中Matrix的pre post set方法理解
- Android中Matrix的pre post set方法理解(转载来源:Linux社区 作者:zjmdp)
- Android中Matrix的pre post set方法理解
- Android中Matrix的pre post set方法理解
- Android中Matrix的pre post set方法理解(转载来源:Linux社区 作者:zjmdp)
- Android中Matrix的pre post set方法理解
- Android中Matrix的set、pre、post的区别
- Android 图形处理特效 Matrix 的set 、 pre、post方法的区别和使用
- Android中Matrix的set、pre、post的区别
- 自己关于Android中Matrix的理解
- 【Android】图形处理特效 Matrix 的set 、 pre、post方法的区别和使用
- 详谈Android中Matrix的set、pre、post的区别
- android Matrix的pre、post、set三种变形方式
- Android中的Matrix,以及set,pre和post的区别
- android Matrix.setRotate 和 postRotate的区别
- android中父view与子view关于触摸事件的理解
- 关于android中JNI层的理解
- 关于Android系统常用的五种布局理解