zoukankan      html  css  js  c++  java
  • Android中的Matrix(矩阵)

    写在前面

    看这篇笔记之前先看一下参考文章,这篇笔记没有系统的讲述矩阵和代码的东西,参考文章写的也有错误的地方,要辨证的看。

    1. 如何计算矩阵乘法
    2. android matrix 最全方法详解与进阶(完整篇)
    3. Android Matrix 最全方法详解与进阶
    4. 1-4 Canvas 对绘制的辅助 clipXXX() 和 Matrix

    矩阵的乘法

    比如有矩阵A和矩阵B,他们分别为:
    v4-728px-multiply-matrices-step-2-version-3

    可以看到A为2行3列的矩阵,B为3行2列的矩阵,矩阵乘法符合下面的规则:

    1. 只有A的列数和B的行数相等,A和B才可以做乘法
    2. A*B的结果C是2行2列的矩阵,行数等于A的行数,列数等于B的列数
    3. 结果矩阵C的第一行第一列数值为A的第一行和B的第一列中的数字分别相乘后再相加。其他行列结果依次类推
    4. 矩阵的乘法不满足交换律,即A*B != B*A
    5. 矩阵的乘法满足结合律M‘ = T*(M*R) = T*M*R = (T*M)*R

    c

    详细信息可以看这里:如何计算矩阵乘法

    Android中常用的四种矩阵变换

    Android中使用3x3的矩阵进行图形的变换,它看起来大概是下面这样:
    20160518113919200

    在Android中,使用一个3x1的矩阵来表示一个点:
    xy1

    x,y分别代表x,y轴上的坐标,而1代表屏幕在z轴上的坐标为默认的。如果将1变大,那么屏幕会拉远, 图形会变小。

    平移(Translate)

    20180611214717

    图例:
    005xtdi2jw1f6dqiw20xoj308c0dw0su

    错切(Skew)

    水平错切

    20180611214828

    图例:
    005xtdi2jw1f6cniifb0sj308c0dw3yz

    垂直错切

    chuizhi

    图例:
    005xtdi2jw1f6cnkwyksij308c0dwq3f

    复合错切

    fuhe

    图例:
    005xtdi2jw1f6cqdu6olfj308c0dwdgi

    旋转(Rotate)

    xuanzhuan1

    图例:
    005xtdi2jw1f6cpp174twj308c0dwt8s

    缩放(Scale)

    suofang1

    图例:
    005xtdi2jw1f6cnk02zy9j308c0dwwej

    Matrix的组合

    应用矩阵进行图形变换的主要原因,是因为矩阵是可以通过矩阵的乘法进行组合使用的,如果想对canvas绘制的bitmap时,先平移T(dx, dy),再旋转R(θ),最后缩放S(k1,k2),就可以将三个变换矩阵相乘,M‘ = ABC,再对canvas应用M’矩阵即可。

    Matrix的坐标系

    矩阵的操作可以看作是以坐标原点为原点的坐标系在三维空间中做的变换,不同于canvas的屏幕坐标系坐标系,矩阵Matrix的坐标系为左手坐标系:

    20160518114718678

    这个坐标系对应的每个轴的旋转方向(从原点看出去,每个轴的旋转方向都是逆时针):

    camaer

    Matrix的操作可以看做是对上面左手坐标系的变换

    因为Matrix变换后是对每个canvas的点起作用,其实也可以看做对这个三维坐标系起了作用,canvas绘制的是三维坐标系上的图像对canvas二位坐标系的投影。

    所以,可以用自己的左手模拟进行平移旋转等操作,更加直观的想象变换后的效果。

    Matrix的左乘和右乘

    在Android中,有关矩阵的操作都是成对的,比如preTranslate(float dx, float dy)和postTranslate(float dx, float dy),通过看api的介绍,如果原矩阵为M,那么pre表示的是左乘,post表示右乘:

    preTranslate : M' = M * T(dx, dy) // 左乘
    postTranslate: M' = T(dx, dy) * M // 右乘

    因为矩阵的变换是顺序执行的,所以在平时最常用的应该是pre左乘,所有的变换操作都依次执行,比如canvas常用的translate等变换方法其实就是左乘。右乘其实就是在所有操作之前增加一步操作,合理的运用右乘可以方便代码的编写。

    比如:图形变换是以左边原点为原点的,所以旋转、缩放等功能应用到canvas.drawBitmap()方法时(因为bitmap常从原点往右下方画),图像表现出来的结果就特别奇怪,需要将canvas的坐标系移动到图像的中心点再操作然后再把坐标系移回去,那么如果只用pre左乘的话,代码是这样的:

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

    如果合理使用右乘,那么代码就成了:

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

    减少了postTranslate和preTranslate之间的距离。

    作者:itlgl
    出处:http://www.cnblogs.com/itlgl/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利

  • 相关阅读:
    第八章 采样
    第七章 优化算法
    第六章 概率图模型
    第五章 非监督学习
    第四章 降维
    第三章 经典算法
    第二章 模型评估
    第一章 特征工程-------------《百面机器学习》
    中等-102,107-二叉树的层序遍历
    字符串单模式匹配 暴力+哈希
  • 原文地址:https://www.cnblogs.com/itlgl/p/10419252.html
Copyright © 2011-2022 走看看