理解变换矩阵

导语:在 CSS transform-function 中我们经常使用 translate(), rotate(), scale() 等对图形进行变换操作,这些简便的变换函数背后是通过控制矩阵 matrix(a, b, c, d, tx, ty) 中特定参数值实现的。本文尝试理解矩阵变换的工作原理,更深入地了解为什么矩阵可以以及如何表示线性变换,如何应用仿射变换实现平移。

文章概览

本文共有3449字,大概需要10分钟阅读。

在 CoDesign 的标注功能中,我们需要在上传过程中将设计软件中常见的渐变、投影、字体等属性解析成 CSS 样式。在解析 Adobe XD 的径向变换过程中,接触到 matrix 变换矩阵,XD 径向渐变提供的源数据如图所示,而 XD 开发文档对渐变相关的 API 说明不是很详细,只能通过参数变化猜测是如何确定径向变换的。

理解变换矩阵图1

通过对不同情况下参数的变化,发现有效字段只有 startX, startY, endR, colorStops 以及 gradientTransform,通过 startX, startY, endR 可以确定出以图形左上角为原点的坐标下的正圆,当图形为正圆时,不管大小变换矩阵都为matrix(1,0,0,1,0,0),为椭圆时才需要用到 gradientTransform,应用 gradientTransform 变换计算即可得到三个关键点的位置,从而得到椭圆位置及大小比例,最终解析对应到 CSS 中的 radial-gradient(),如图:

理解变换矩阵

图2:XD RadialGradient

腾讯CoDesign设计协作

这个过程中对于矩阵的转换还是十分生疏,尽管在 CSS transform 中已经有所接触,因此重新梳理了一下矩阵变换相关的知识。矩阵只是工具,描述了向量的“运动”,可以用于表示线性变换的映射关系。本文主要是关于矩阵如何表示线性变换实现旋转、缩放等操作,以及如何应用仿射变换实现平移,尝试理解变换过程以更好地掌握和应用矩阵。

线性变换

矩阵与向量

线性变换中重要的两个概念是矩阵与向量。

矩阵是数学工具,用一个矩形的数字阵列表示,一个 m 行和 n 列的矩阵为 m x n 矩阵,m 与 n 相同时为方矩阵。矩阵可以进行转置操作,一个 m x n 矩阵 A 的转置为n x m 矩阵,即把 A 的行元素分别写为转置矩阵的列,把 A 的列元素分别写为转置矩阵的行。比如:

理解变换矩阵图3

矩阵可以进行加法与乘法运算:

理解变换矩阵图4

向量是具有大小和方向的量,向量可以表示物理意义,可以表示数字列表,我们常见的是在坐标空间中以原点出发的箭头。空间中的向量可以用行向量表示为 (x,y),列向量表示可以用矩阵表示。向量的加法为分量分别相加,数乘为分量分别乘以标量。

理解变换矩阵图5

线性变换表示向量空间的映射关系

以二维平面直角坐标系为例,i、j 分别是沿 x、y 坐标轴方向上的单位向量 (1, 0)、(0,1),平面中的其他向量可以理解为是对单位向量进行缩放后相加得到的,如向量 v(x, y) 就是对单位向量 i 进行 x 倍缩放,对 j 进行 y 倍缩放,最后相加,即 v=x(i)+y(j)。用矩阵表示:

理解变换矩阵图6 

此时 i(1, 0) 和j(0,1) 是当前空间的一组基向量且为标准正交基,向量 v 就是i(1, 0)、j(0,1) 的一个线性组合,基向量的线性组合的集合就是张成空间。除这两个单位向量,任意两个不共线的向量都可以作为基向量,经过缩放相加表示其他向量,比如当以 (1,0)、(0, -1) 作为空间的基向量时,相同的组合方式下,向量 v 就变为 (x,-y)。

理解变换矩阵图7

理解变换矩阵图8 


在坐标中表示,发现他们之间是有映射关系的。当基向量变化时,相同组合下的向量随之改变,也就是沿 x 轴翻转了。可以想象为基向量的变换带动整个向量空间变换,空间中的点、线、面都随之改变了,前后两个空间存在一种映射关系。这个映射就是线性变换,线性变换可以理解为函数:输入第一个向量,输出映射后的向量;输入一个形状,输出映射后的形状。那么这个线性变换如何用数(矩阵)表示?

矩阵表示线性变换 

线性变换的定义为:

理解变换矩阵图9 

若变换前的空间 R1 中基向量为 i、j,那么向量 v(x,y) 变换后的向量为:

理解变换矩阵图10

因此通过矩阵 M 就可以表示向量空间由 R1 到 R2 的线性变换,[T(i)  T(j)] 就是变换后的基向量。

回到上面翻转变换的例子,翻转的变换就可以用新的基向量组成的矩阵:

理解变换矩阵11

表示,这就是熟悉的垂直翻转矩阵 matrix(1, 0, 0, -1, 0, 0) 了。

用 i’(a, b)、j’(c,d) 表示新的基向量,那么变换后的向量 v’ = x(i’) + y(j’),如下:

理解变换矩阵图12

用矩阵

理解变换矩阵图13

表示这个线性变换, v’=M(v) 结果是一致的 :

理解变换矩阵图14

简单来说,由标准正交基经过变换后的基向量矩阵可以表示这个线性变换。面对一个矩阵时,可以聚焦于基向量的变换,应用到整个空间,旋转、缩放、错切矩阵中的关键作用值也可以从基向量的角度去理解。比如

理解变换矩阵图15

时,不难想像是基向量 i 从 (1, 0) 变换到 (2, 0)、j 从 (0, 1) 变换到 (0, 2),那么横纵向空间都放大为原来的 2 倍。

理解变换矩阵图16

CSS transform-function提供了 rotate()、skew()、scale()、translate() 等方法,对矩阵中的关键值进行控制。但这些便捷方法都是单一变换,复杂变换的场景还是需要使用 matrix() 一步到位。 

复合矩阵 

两个矩阵相乘时,可以理解为两个线性变换相继应用: v’= M2(M1(v))。

比如将空间放大两倍后再沿 x 轴垂直翻转,按步骤进行,分别对基向量 (1, 0)、(0, 1) 应用缩放矩阵,得到 (2, 0)、(0, 2),再应用翻转矩阵得到 (2, 0)、(0, -2)。

理解变换矩阵图17

理解变换矩阵图18 

对两次变换进行合并,就得到缩放矩阵与翻转矩阵的复合矩阵也就是:

理解变换矩阵图19

若前后两个变换矩阵分别是 

理解变换矩阵图20

对基向量 (1, 0)、(0,1) 进行两次变换,第一次应用变换后,得到的基向量组合是 (e,f)、(g,h),再应用第二次变换,计算如下:

理解变换矩阵图21 

合并表示其实就是矩阵乘法:

理解变换矩阵图22

因此两次变换可以合并为一次计算,即复合矩阵。

理解变换矩阵图23

 这里需要注意变换 M2(M1(v)) 是从右往左去应用的,类似 f(g(x)),且矩阵乘法符合结合律但不满足交换律,即 (AB)C 等于 A(BC) 而 AB 不等于 BA。交换会打乱变换顺序,旋转后非等比缩放和非等比缩放后旋转,结果很可能是不一致的。 

线性变换可以对空间进行旋转、缩放、错切、镜像等操作,但无法实现平移操作,因为线性变换为乘法运算 v’= M(v):

理解变换矩阵图24

而平移需要加上一个常量,即 v’= M(v) + t:

理解变换矩阵图25

仿射变换就是线性变换加上平移变换。

仿射变换

二维线性变换的 2×2 矩阵只能做旋转、缩放、错切等变换,但无法实现平移。为了方便实现平移,需要引入齐次坐标,构造一个 3×3矩阵,在二维的基础上增加一个维度用于表示平移,增加的维度只用于平移计算,因此需要忽略掉其他平移之外的变换。当我们增加一个维度把二维平面移到 z=1 的平面,我们就可以借助三维空间的线性变换实现二维平面的平移变换。参考维基百科的动画,可以更好的解释这个过程:

理解变换矩阵图26

我们只需要平移相关的变换,其他涉及第三维的旋转、缩放变换忽略不计。因此把 i 和 j 基向量的第三个坐标限制在 0,而第三个基向量的第三坐标限制在 1,这样就能保证变换仍然只发生在一个二维平面上但又能实现平移。也就是我们限制基变换为 (a,b,0)(c,d,0)(tx,ty,1),应用后忽略第三维的数值即可。这也是为什么 matrix() 只需要 6 个数值,因为第三坐标的值是固定的,不会影响计算结果,而且也可以节省一定的空间。

理解变换矩阵图27

当然,也可以仍然只使用二维线性变换,再单独使用加法实现平移。但是一旦涉及前文提到的复合矩阵,也就是当应用多个变换时,2×2 矩阵的乘法与加法交叉计算量会大大增加,而且无法合并。但借助 3×3 矩阵,利用乘法结合律可以将多个矩阵变换合并成一个复合矩阵。

以上都是基于二维平面的线性变换与放射变换,三维空间的线性变换及仿射变换同理。3×3的矩阵可以实现三维空间下的线性变换,依旧可以理解为基向量的变换,应用到整个空间后产生的旋转、缩放等映射关系。而 3×3的矩阵同样也无法实现三维空间下的平移变换,需要引入第四维辅助计算。

在 MDN 文档中,matrix(a,b,c,d,tx,ty) 是  matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1) 的简写,也就是对于低维矩阵,我们可以根据需要扩展更高的维度,方便进行仿射变换。

理解变换矩阵图28

总结

理解变换矩阵

图29

线性变换是操作空间的手段,矩阵是计算的数学工具,线性变换可以通过矩阵运算对空间进行旋转、缩放、错切、镜像等操作,仿射变换实现平移操作。将向量空间中的线性变换聚焦于基向量的变换,可以更直观地理解映射关系,从而理解 matrix() 中各个参数所代表的几何变换意义。

线性代数基于向量、矩阵还有更多其他的应用场景,齐次坐标也在透视投影上有更深的应用,以上只是粗浅的理解与总结,还有很多知识点值得深入学习。

参考:

1. transform-function – MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function

2.  Affine transformation – Wikipedia: https://zh.wikipedia.org/wiki/%E4%BB%BF%E5%B0%84%E5%8F%98%E6%8D%A2

3. RadialGradient – Adobe XD Develop: https://www.adobe.io/xd/uxp/develop/reference/RadialGradient/

4. 线性代数的本质: https://www.bilibili.com/video/BV1Ys411k7yQ

5. 理解CSS3 transform中的Matrix(矩阵): https://www.zhangxinxu.com/wordpress/2012/06/css3-transform-matrix-%E7%9F%A9%E9%98%B5/

6. Understanding-the-css-transforms-matrix: https://dev.opera.com/articles/understanding-the-css-transforms-matrix/





 

理解变换矩阵


快乐工作,快乐生活

Happy work , Happy life

/

Join us


本篇文章来源于微信公众号: 腾讯CDC体验设计

UI/UX

浅谈动作捕捉技术:从电影游戏特效到元宇宙交互变革

2022-4-19 17:00:00

UI/UX

谷雨初晴时 | 金山办公「谷雨」节气壁纸焕雅上线

2022-4-20 8:00:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索