计算机原理/仿射变换

来自康健生活
跳转到导航 跳转到搜索

前言

2023年08月05日开始起稿。

在 css 中矩阵的变换与 transform 中的 translate、scale、rotate、skew 属性息息相关,彼此符合计算为 matrix 以此实现位移、缩放、旋转、倾斜等视觉效果。

基础运算

点积

点积 ab=abcosθ

叉积

笛卡尔坐标

Cartesian coordinate,正交坐标系。

欧几里得空间

齐次坐标系

Homogencous coordinate 由德国数学家 August Ferdinand Möbius 提出,采用 N+1 维来表示 N 维坐标。

欧几里得空间/笛卡尔空间与齐次坐标转换

基本变换

通用公式

转换矩阵 * 原齐次坐标 = 转换后齐次坐标。即,[m×n]Amatrix×[1×n]Bmatrix=[1×m]Ymatrix


假设 A*B=Y。其中,A 为 m*n 的 m 行 n 列矩阵,B 为 1*n 列的矩阵。B 拆分为列向量,并且列向量的维数就是矩阵的行数

Warning: 矩阵列数必须等于向量的维数么?eq: [1234abcd]×[1234]

二维转换方法

transform(a, b, c, d, e, f) 与 Matrix 的转换。这里需要注意的是两者的对应关系为纵向。

[x1y11]=[acebdfghi]×[xy1]=[acebdf001]×[xy1]

  • a [线性变换]: 表示为 x 方向的缩放因子,也常用 sx 标识;
  • b [线性变换]: 表示为 y 方向的倾斜因子或旋转角度正弦值,这也说明倾斜与旋转之间会有冲突需要处理;
  • c [线性变换]: 表示为 x 方向的倾斜因子或旋转角度正弦值;
  • d [线性变换]: 表示为 y 方向的缩放因子,也常用 sy 标识;
  • e [平移变换]: 表示为 x 方向平移值, 也用 tx 标识;
  • f [平移变换]: 表示为 y 方向平移值, 也用 ty 标识。
  • g [透视变换]:
  • h [透视变换]:

并以此可推导出来

{x1=a×x+c×y+1×ey1=b×x+d×y+1×f1=0×0+0×0+1×1

简化后

{x1=a×x+c×y+ey1=b×x+d×y+f

matrix3d 三维转换方法

[x1y1z1w1]=[aeimbfjncgkodhlp]×[xyzw]

平移(Translation)

2D-平移
2D-平移

[x1y11]=[10e01f001]×[xy1]


{x1=e+xy1=f+y

简化公式为,P=T(e,f)×P

平移逆矩阵

T1=[10e01f001]

二维平移

在二维空间里面平移需要进行矩阵加法。假设现有点 A(x1,y1) 平移至点 B(x2,y2),平移距离为 X 轴距离偏移 e、Y 轴距离偏移 f,计算如下:

{AB=u=e2+f2x2=x1+ey2=y1+f

推导矩阵

M2=[x2y2]=M1+T=[x1y1]+[ef]=[x1+ey1+f]

旋转(Rotation)

四元数

欧拉角

简述

在语言计算中 ,与数学表示法如 sin300.5 不同的是,需要将弧度和角度进行转换,之后代入数学函数计算出结果值。

定义 ϕ 为弧度,并定义 θ 为角度。则 ϕ 值为 ϕ=π180×θ

如在前端 javascript 中进行计算sin30 则为

// 定义角度为 theta
const theta = 30;
// 定义弧度 phi
const phi = Math.PI / 180 * theta;
// 数学函数计算 sin 值
Math.sin(phi)

[x1y11]=[ac0bd0001]×[xy1]=[cosθsinθ0sinθcosθ0001]×[xy1]

推导出来

{x1=cosθ×xsinθ×yy1=sinθ×x+cosθ×y

简化公式为,P=R(θ)×P

旋转逆矩阵

R1=[cosθsinθ0sinθcosθ0001]

假设

假设存在点 E 移动至点 F。设 E 坐标为(x1, y1),F 坐标为(x2, y2),D 坐标为(a, b)。

简要图示:

Transform-平移
Transform-平移

初中数学:

{cosβ=x1arsinβ=y1brcosγ=x2arsinγ=y2br

演算:

{cosβ=x1arsinβ=y1arx2a=cosγ×r=cos(βα)×r=(cosα×cosβ+sinβ×sinα)×ry2b=sinγ×r=sin(βα)×r=(sinβ×cosαsinα×cosβ)×r

推导:

{a=0b=0x2=cosα×(x1a)+sinα×(y1b)+a=cosα×x1+sinα×y1y2=cosα×(y1b)sinα×(x1a)+b=cosα×y1sinα×x1

点旋转的角度 α 是正旋转还是负旋转,当角度是负旋转时 θ=α

验证:

{cosβ=x1arsinβ=y1arx2=cos(β(θ))×r=(cosβ×cosθsinβ×sinθ)×r=cosθ×x1sinθ×y1y2=sin(β(θ))×r=(sinθ×cosβ+sinβ×cosθ)×r=cosθ×y1+sinθ×x1

转换为矩阵:

[x2y2]=[cosθsinθcosθsinθ]×[x1y1]

rotate

从 css 语法上开始转换

.box {
  transform: rotate(30deg);
}

这个旋转套用公式

[cos30sin300sin30cos300001]×[111]=[0.860.500.50.860001]×[111]

等价于

.box {
  transform: matrix(0.86, 0.5, -0.5, 0.86, 0, 0);
}
matrix-旋转-1
matrix-旋转-1

定点旋转

围绕特定枢轴点 (cx,cy) 旋转角度 θmatrix(cosθ,sinθ,sinθ,cosθ,cx×(1cosθ)+cy×sinθ,cy×(1cosθ)cx×sinθ)

变换矩阵为: [x1y11]=[cosθsinθcxcx×cosθ+cy×sinθsinθcosθcycx×sinθcy×cosθ001]×[xy1]

缩放(Scale)

在叙述之前先复习一下二维空间中的向量相关表达式,比如向量的长度计算(勾股定理),定义 x 轴、y 轴方向相同的两个单位向量 u,v 作为一组基底。

2D-向量长度
2D-向量长度

单位向量 u,v(依据维基阐述:“一个非零向量u的正规化向量u就是平行于u的单位向量[1]”。求一个方向上给定向量的单位向量即为正规化[Normalization]向量。)的表述法为:

{u^=1u×u=uuv^=1v×v=vv

并且标准单位向量 {u^=1u×u=uu=1v^=1v×v=vv=1

勾股定理推导向量 AC 的模 w 的值。

w=wx2+wy2

扩展到三维。

3D-向量长度
3D-向量长度

w=AD2+DE2=AB2+BD2+DE2=wx2+wy2+wz2

扩展到多维。多维向量的表示法为 w=(w1,w2,,wn)T

w=w12+w22++wn2

推导出。

(w)2=w12+w22++wz2=[w1w2wn]×[w1w2wn]

总结。

{w=[w1w2wn]w=w12+w22++wn2

推导出在二维坐标系中 X、Y 两个方向的单位向量,使用 i、j、k 进行表示。

{i^=[10]j^=[01]

三维坐标系中 X、Y、Z 三个方向的单位向量。

{i^=[100]j^=[010]k^=[001]


[x1y11]=[a000d0001]×[xy1]

推导出来

{x1=a×xy1=d×y

简化公式为,P=S(a,b)×P

缩放逆矩阵

S1=[1a0001d0001]

scale

.box {
  transform: scale(0.3, 0.6);
}

通过公式计算

[a000d0001]=[0.30000.60001]×[111]

等价于

.box {
  // transform: matrix(a, b, c, d, e, f);
  transform: matrix(0.3, 0, 0, 0.6, 0, 0);
}
matrix-缩放-1
matrix-缩放-1

定点缩放

通过前文已知缩放由矩阵转为 matrix 后,其格式为 matrix(a,0,0,d,0,0),这是基于原点 (0,0) 的情况,如果是围绕特定枢轴点 (cx,cy) 进行缩放,则是 matrix(sx,0,0,sy,cx×(1sx),cy×(1sy)),也就是 matrix(a,0,0,d,cx×(1a),cy×(1d))

偏斜/错切(Skew)

倾斜矩阵(错切矩阵)指定沿某一轴线发生 θ 度的倾斜变换。即,matrix(1,tanθy,tanθx,1,0,0)

[x1y11]=[1tanθx0tanθy10001]×[xy1]

沿 x 轴倾斜 沿 y 轴倾斜
[1tanθ0010001] [100tanθ10001]
matrix(1,0,tanθ,1,0,0) matrix(1,tanθ,0,1,0,0)

复合

复合也被称之为累积变换。复合需要注意运算顺序,即旋转缩放偏移。所以复合公式的矩阵计算也遵循这个顺序。具体计算仍要根据需求进行组合,不同复合矩阵相乘的结果说不同的。

复 合=Rn×Sn×Tn

这里用 css 中的 transform 举例,当我有一个元素节点需要进行旋转和缩放时,rotatescale 等几个基础的转换函数的顺序最终会转化为如下图示。

{{#mermaid:flowchart LR translate --> scale --> rotate }}

举例。

.box {
  transform: rotate(30deg) scale(0.3, 0.6);
}

组合需要进行矩阵乘法计算

复 合=T1×S1×R1=...=[cos30sin300sin30cos300001]×[0.30000.60001]=[0.2580.300.150.5160001]

等价于

.box {
  transform: matrix(0.258, 0.15, -0.3, 0.516, 0, 0);
}

复合顺序

累积矩阵不满足乘法的交换律(但具有结合律、分配律特质),所以累积顺序差异(列矩阵从右向左运算)会计算出不同的结果。论证顺序不同结果不同如下:

先旋转再平移简化公式为,P=(T×R)×P=复 合×P=R×P+T

复 合×P=[10e01f001]×[ac0bd0001]×P=[acebdf001]×[P001]=[RT01]×[P001]=×[RPT01]=R×P+T


先平移再旋转简化公式为,P=(R×T)×P=复 合×P=R×P+R×T

复 合×P=[ac0bd0001]×[10e01f001]×P=[acc×f+a×ebdd×f+b×e001]×[P001]=[R[c×f+a×ed×f+b×e]01]×[P001]=[R([acbd]×[ef])01]×[P001]=[R([ac0bd0001]×[ef0])01]×[P001]=[RR3×3×T3×101]×[P001]=[RR×T01]×[P001]=×[RPRT01]=R×P+R×T

推导出结果 R×P+R×TR×P+R×T,以此可以看出累积顺序的值的区别。

矩阵结合律: (AB)C=A(BC)

变换矩阵

变换矩阵允许原坐标点通过变换获取新坐标点,新坐标点 P(xm,ym) 与原坐标点 P(xn,yn) 的公式转换如下:

Pm=复 合×Pn

法线变换

CSS

translation, rotation, scaling, skewing

其他

组件库 ml-matrix、gl-matrix

附件

matrix-组合计算-1
matrix-组合计算-1
  1. 单位向量[OL],2010:10-14. https://zh.wikipedia.org/zh-hans/单位向量.