本主题提供了二维图形矩阵变换的数学概述。但是,您不需要知道矩阵数学就可以使用Direct2D中的变换。如果你对数学感兴趣,请阅读这个主题;否则,可以跳过这个话题。
矩阵导论
矩阵是实数的矩形阵列。矩阵的顺序是行数和列数。例如,如果矩阵有3行2列,则其顺序为3×2。矩阵通常以方括号中的矩阵元素显示:
3×2矩阵。
符号:矩阵由大写字母指定。元素由小写字母指定。下标表示一个元素的行号和列号。例如
aij
a
i
j
是矩阵A的第i行和第j列的元素。
下图显示了一个i×j矩阵,矩阵的每个单元中的单个元素。
具有i行和j列的矩阵。
矩阵操作
本节介绍在矩阵上定义的基本操作。
加成。两个矩阵的和A+B是通过相加A和B的相应元素得到的:
A+B=[aij]+[bij]=[aij+bij]
A
+
B
=
[
a
i
j
]
+
[
b
i
j
]
=
[
a
i
j
+
b
i
j
]
标量乘法,该操作将矩阵乘以实数。给定一个实数k,标量积kA是通过将A的每个元素乘以k得到的。
kA=k[aij]=[k×aij]
k
A
=
k
[
a
i
j
]
=
[
k
×
a
i
j
]
矩阵乘法。给定有序(m×n)和(n×p)的两个矩阵A和B,乘积C=A×B是阶数为(m×p)的矩阵,定义如下:
矩阵乘法。
或者等价地:
cij=ai1×b1j+ai2×b2j+...+ain+bnj
c
i
j
=
a
i
1
×
b
1
j
+
a
i
2
×
b
2
j
+
.
.
.
+
a
i
n
+
b
n
j
也就是说,要计算每个元素
cij
c
i
j
,请执行以下操作:
- 以A的第i行和B的第j列
- 将行和列中的每一对元素相乘:第一列条目的第一行条目,第二列条目的第二行条目等等。
- 总结结果。
这是将(2×2)矩阵乘以(2×3)矩阵的示例。
矩阵乘法。
矩阵乘法不可交换。也就是说,A×B≠B×A。另外,根据定义,不是每对矩阵都可以相乘。左侧矩阵中的列数必须等于右侧矩阵中的行数。否则,×运算符没有被定义。
确定矩阵。标识为I的单位矩阵是如下定义的方矩阵:
如果i=j,则Iij=1,否则为0。
如
果
i
=
j
,
则
I
i
j
=
1
,
否
则
为
0
。
换句话说,对于其中行号等于列号的每个元素,单位矩阵包含1,对于所有其他元素为零。例如,这里是3×3的单位矩阵。
标识矩阵。
任何矩阵M都有以下等式
M×I=M
M
×
I
=
M
I×M=M
I
×
M
=
M
仿射变换
仿射变换是将一个坐标空间映射到另一个的数学运算。换句话说,它将一组点指向另一组点。仿射变换具有一些使其在计算机图形学中有用的特征。
- 仿射变换保留共线性。如果三个或更多的点落在一条线上,那么在转换之后它们仍然形成一条线。直线保持直线。
- 两个仿射变换的组合是仿射变换。
二维空间的仿射变换具有以下形式。
仿射变换。
如果应用前面给出的矩阵乘法的定义,则可以显示两个仿射变换的乘积是另一个仿射变换。为了使用仿射变换来变换2D点,该点被表示为1×3矩阵。
P=[xy1]
P
=
[
x
y
1
]
前两个元素包含该点的x和y坐标。1被放置在第三个元素,使数学正确的工作。要应用变换,请按如下方式乘以两个矩阵。
P′=P×M
P
′
=
P
×
M
这扩展到以下。
仿射变换。
哪里
x′=ax+cy+e
x
′
=
a
x
+
c
y
+
e
y′=bx+dy+f
y
′
=
b
x
+
d
y
+
f
为了得到变换点,取矩阵P’的前两个元素。
p=(x′,y′)=(ax+cy+e,bx+dy+f)
p
=
(
x
′
,
y
′
)
=
(
a
x
+
c
y
+
e
,
b
x
+
d
y
+
f
)
注 1×n矩阵被称为行向量。Direct2D和Direct3D都使用行向量来表示2D或3D空间中的点。您可以通过使用列向量(n×1)和转置矩阵来获得等效的结果。大多数图形文本使用列向量形式。本主题介绍了与Direct2D和Direct3D一致的行向量表单。
接下来的几个部分推导出基本的变换。
翻译转换
翻译变换矩阵具有以下形式。
翻译转换。
在这个等式中插入一个点P得出:
P′=(x+dx,y+dy)
P
′
=
(
x
+
d
x
,
y
+
d
y
)
这对应于在X轴上由dx平移的点(x,y)和在Y轴上的dy。
显示两点的翻译的图表。
缩放变换
缩放变换矩阵具有以下形式。
缩放变换。
在这个等式中插入一个点P得出:
P′=(x⋅dx,y⋅dy)
P
′
=
(
x
·
d
x
,
y
·
d
y
)
这对应于由dx和dy缩放的点(x,y)。
显示两点的缩放比例的图表。
围绕原点旋转
围绕原点旋转点的矩阵具有以下形式。
旋转变换。
转换点是:
P′=(xcosθ−ysinθ,xsinθ+ycosθ)
P
′
=
(
x
c
o
s
θ
−
y
s
i
n
θ
,
x
s
i
n
θ
+
y
c
o
s
θ
)
证明。为了显示P’表示旋转,请考虑下图。
显示围绕原点的旋转的图表。
鉴于:
P=(x,y)
P
=
(
x
,
y
)
原始点要转化。
Φ
线(0,0)与P形成的角度
θ
围绕原点旋转(x,y)的角度。
P′=(x′,y′)
P
′
=
(
x
′
,
y
′
)
转化点。
R
线(0,0)到P的长度也是旋转圆的半径。
注意 此图使用几何中使用的标准坐标系,其中正y轴指向。Direct2D使用Windows坐标系统,其中正y轴指向下方。
x轴和线(0,0)到P’之间的角度是Φ+θ。以下身份认定:
x=R⋅cosΦ
x
=
R
·
c
o
s
Φ
y=R⋅sinΦ
y
=
R
·
s
i
n
Φ
x′=R⋅cos(Φ+θ)
x
′
=
R
·
c
o
s
(
Φ
+
θ
)
y′=R⋅sin(Φ+θ)
y
′
=
R
·
s
i
n
(
Φ
+
θ
)
现在用θ来求解x’和y’。通过三角加法公式:
x′=R(cosΦcosθ−sinΦsinθ)=R⋅cosΦcosθ−R⋅sinΦsinθ
x
′
=
R
(
c
o
s
Φ
c
o
s
θ
−
s
i
n
Φ
s
i
n
θ
)
=
R
·
c
o
s
Φ
c
o
s
θ
−
R
·
s
i
n
Φ
s
i
n
θ
y′=R(sinΦcosθ+cosΦsinθ)=R⋅sinΦcosθ+R⋅cosΦsinθ
y
′
=
R
(
s
i
n
Φ
c
o
s
θ
+
c
o
s
Φ
s
i
n
θ
)
=
R
·
s
i
n
Φ
c
o
s
θ
+
R
·
c
o
s
Φ
s
i
n
θ
代替,我们得到:
x′=x⋅cosθ−y⋅sinθ
x
′
=
x
·
c
o
s
θ
−
y
·
s
i
n
θ
y′=x⋅sinθ+y⋅cosθ
y
′
=
x
·
s
i
n
θ
+
y
·
c
o
s
θ
这对应于前面所示的变换点P’。
围绕任意点旋转
要围绕原点以外的点(x,y)旋转,使用以下矩阵。
旋转变换。
你可以通过把点(x,y)作为原点来导出这个矩阵。
显示围绕某个点的旋转的图表。
假设
(x1,y1)
(
x
1
,
y
1
)
是点(x,y)周围点
(x0,y0)
(
x
0
,
y
0
)
的旋转点。我们可以推导出如下的
x1
x
1
。
x1=(x0−x)cosθ−(y0−y)sinθ+x
x
1
=
(
x
0
−
x
)
c
o
s
θ
−
(
y
0
−
y
)
s
i
n
θ
+
x
x1=x0⋅cosθ−y0⋅sinθ+[(1−cosθ)+y⋅sinθ]
x
1
=
x
0
·
c
o
s
θ
−
y
0
·
s
i
n
θ
+
[
(
1
−
c
o
s
θ
)
+
y
·
s
i
n
θ
]
现在使用前面的公式
x1=ax0+cy0+e
x
1
=
a
x
0
+
c
y
0
+
e
将这个方程重新插入到变换矩阵中。使用相同的程序来派生
y1
y
1
。
偏斜变换
偏斜变换由四个参数定义:
- θ:沿着x轴倾斜的量,从y轴测量为一个角度。
- Φ:沿y轴倾斜的量,从x轴测量角度。
-
(px,py)
(
p
x
,
p
y
)
:执行偏斜的点的x坐标和y坐标。
偏斜变换使用以下矩阵。
倾斜变形。
转换点是:
P′=(x+y⋅tanθ−py⋅tanθ,y+x⋅tanΦ)−py⋅tanΦ
P
′
=
(
x
+
y
·
t
a
n
θ
−
p
y
·
t
a
n
θ
,
y
+
x
·
t
a
n
Φ
)
−
p
y
·
t
a
n
Φ
或等同地:
P′=(x+(y−py)tanθ,y+(x−px)tanΦ)
P
′
=
(
x
+
(
y
−
p
y
)
t
a
n
θ
,
y
+
(
x
−
p
x
)
t
a
n
Φ
)
要了解这个转换如何工作,请分别考虑每个组件。θ参数将x方向上的每个点移动一个等于tanθ的量。下图显示了θ和x轴偏斜之间的关系。
显示沿x轴倾斜的图表。
这是应用于矩形的相同的偏斜:
显示沿x轴倾斜的图表。
Φ参数具有相同的效果,但是沿着y轴:
沿y轴显示偏斜的图表。
下图显示了应用于矩形的y轴偏斜。
沿y轴显示偏斜的图表。
最后,参数
px
p
x
和
py
p
y
将偏移中心点沿着x轴和y轴移动。
在Direct2D中表示变换
所有Direct2D变换都是仿射变换。Direct2D不支持非仿射变换。变换由D2D1_MATRIX_3X2_F结构表示。这个结构定义了一个3×2的矩阵。由于仿射变换的第三列总是相同的(
P=⎡⎣⎢001⎤⎦⎥
P
=
[
0
0
1
]
),并且因为Direct2D不支持非仿射变换,所以不需要指定整个3×3矩阵。在内部,Direct2D使用3×3矩阵来计算变换。
D2D1_MATRIX_3X2_F的成员根据它们的索引位置命名:_11成员是元素(1,1),_12成员是元素(1,2)等等。尽管可以直接初始化结构成员,但建议使用D2D1::Matrix3x2F类。该类继承了D2D1_MATRIX_3X2_F,并提供了用于创建任何基本仿射变换的辅助方法。该类还定义了operator*(),用于组成两个或更多变换,如在Direct2D中应用变换中所述。
下一个
模块4.用户输入
原文链接:Appendix: Matrix Transforms
返回目录