Matrix学习笔记(一):原理

基本概念

错切:实际上是平面景物在投影平面上的非垂直投影。错切使图像中的图形产生扭变。
仿射变换:仿射变换是 线性变换(缩放,旋转,错切) 和 平移变换(平移) 的复合。
Matrix :是一个3维矩阵,最根本的作用就是坐标转换(属于仿射变换)。
基本变换有4种: 平移(translate)、缩放(scale)、旋转(rotate) 和 错切(skew)。
这里写图片描述

这里写图片描述

缩放

这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述

你可能注意到了,我们坐标多了一个1,这是使用了齐次坐标系的缘故,在数学中我们的点和向量都是这样表示的(x, y),两者看起来一样,计算机无法区分,为此让计算机也可以区分它们,增加了一个标志位,增加之后看起来是这样:
(x, y, 1) - 点
(x, y, 0) - 向量
另外,齐次坐标具有等比的性质,(2,3,1)、(4,6,2)…(2N,3N,N)表示的均是(2,3)这一个点。(将MPERSP_2解释为scale这一误解就源于此)。

图例:
这里写图片描述

错切(Skew)

错切存在两种特殊错切,水平错切(平行X轴)和垂直错切(平行Y轴)。

水平错切
这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述
图例:
这里写图片描述
垂直错切
这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述
图例:
这里写图片描述
复合错切
水平错切和垂直错切的复合。
这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述
图例:
这里写图片描述

旋转(Rotate)

假定一个点 A(x0, y0) ,距离原点距离为 r, 与水平轴夹角为 α 度, 绕原点旋转 θ 度, 旋转后为点 B(x, y) 如下:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述
图例:
这里写图片描述

平移(Translate)

此处也是使用齐次坐标的优点体现之一,实际上前面的三个操作使用 2x2 的矩阵也能满足需求,但是使用 2x2 的矩阵,无法将平移操作加入其中,而将坐标扩展为齐次坐标后,将矩阵扩展为 3x3 就可以将算法统一,四种算法均可以使用矩阵乘法完成。

这里写图片描述
这里写图片描述
用矩阵表示:
这里写图片描述
图例:
这里写图片描述

Matrix复合原理

Matrix的多种复合操作都是使用矩阵乘法实现的,从原理上理解很简单,但是,使用矩阵乘法也有其弱点,后面的操作可能会影响到前面到操作,所以在构造Matrix时顺序很重要。

我们常用的四大变换操作,每一种操作在Matrix均有三类,前乘(pre),后乘(post)和设置(set)。

前乘(pre)

前乘相当于矩阵的右乘:

这表示一个矩阵与一个特殊矩阵前乘后构造出结果矩阵。

后乘(post)

后乘相当于矩阵的左乘:

这表示一个矩阵与一个特殊矩阵后乘后构造出结果矩阵。

设置(set)

设置使用的不是矩阵乘法,而是直接覆盖掉原来的数值,所以,使用设置可能会导致之前的操作失效。

组合

组合操作构造Matrix时,个人建议尽量全部使用后乘或者全部使用前乘,这样操作顺序容易确定,出现问题也比较容易排查。
当然,由于矩阵乘法不满足交换律,前乘和后乘的结果是不同的,使用时应结合具体情景分析使用。

Pre与Post的区别

主要区别其实就是矩阵的乘法顺序不同,pre相当于矩阵的右乘,而post相当于矩阵的左乘。

在实际操作中,我们每一步操作都会得出准确的计算结果,但是为什么还会用存在先后的说法? 难道真的能够用pre和post影响计算顺序? 实则不然,下面我们用一个例子说明:

Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.8f);
matrix.preTranslate(1000, 1000);
Log.e(TAG, "MatrixTest:3" + matrix.toShortString());

在上面的操作中,如果按照正常的思路,先缩放,后平移,缩放操作执行在前,不会影响到后续的平移操作,但是执行结果却发现平移距离变成了(500, 800)。

在上面例子中,计算顺序是没有问题的,先计算的缩放,然后计算的平移,而缩放影响到平移则是因为前一步缩放后的结果矩阵右乘了平移矩阵,这是符合矩阵乘法的运算规律的,也就是说缩放操作虽然在前却影响到了平移操作,相当于先执行了平移操作,然后执行的缩放操作,因此才有pre操作会先执行,而post操作会后执行这一说法。

下面我们用不同对方式来构造一个矩阵:

假设我们需要先缩放再平移。
注意:

1.由于矩阵乘法不满足交换律,请保证使用初始矩阵(Initial Matrix),否则可能导致运算结果不同。
2.注意构造顺序,顺序是会影响结果的。
3.Initial Matrix是指new出来的新矩阵,或者reset后的矩阵,是一个单位矩阵。

1.仅用pre:

Matrix m = new Matrix();
m.reset();
m.preTranslate(tx, ty); //使用pre,越靠后越先执行。
m.preScale(sx, sy);

用矩阵表示:

这里写图片描述

2.仅用post:
Matrix m = new Matrix();
m.reset();
m.postScale(sx, sy);  //使用post,越靠前越先执行。
m.postTranslate(tx, ty);

用矩阵表示:
这里写图片描述

3.混合:

Matrix m = new Matrix();
m.reset();
m.preScale(sx, sy);  
m.postTranslate(tx, ty);

Matrix m = new Matrix();
m.reset();
m.postTranslate(tx, ty);
m.preScale(sx, sy);  

由于此处只有两步操作,且指定了先后,所以代码上交换并不会影响结果。

用矩阵表示:
这里写图片描述

注意: 由于矩阵乘法不满足交换律,请保证初始矩阵为空,如果初始矩阵不为空,则导致运算结果不同。

Matrix方法表

方法类相关API摘要
基本方法equals hashCode toString toShortString比较、 获取哈希值、 转换为字符串
数值操作set reset setValues getValues设置、 重置、 设置数值、 获取数值
数值计算mapPoints mapRadius mapRect mapVectors计算变换后的数值
设置(set)setConcat setRotate setScale setSkew setTranslate设置变换、
前乘(pre)preConcat preRotate preScale preSkew preTranslate前乘变换
后乘(post)postConcat postRotate postScale postSkew postTranslate后乘变换
特殊方法setPolyToPoly setRectToRect rectStaysRect setSinCos一些特殊操作
矩阵相关invert isAffine isIdentity求逆矩阵、 是否为仿射矩阵、 是否为单位矩阵 …

参考
[1]Matrix原理
[2] Android 手势检测实战 打造支持缩放平移的图片预览效果(上)

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值