附录:矩阵转换

本主题提供二维图形矩阵转换的数学概述。 但是,无需知道矩阵数学即可在 Direct2D 中使用转换。 如果你对数学感兴趣,请阅读本主题;否则,请随意跳过本主题。

矩阵简介

矩阵是实数的矩形数组。 矩阵 的顺序 是行数和列数。 例如,如果矩阵有 3 行和 2 列,则顺序为 3 × 2。 矩阵通常以方括号括起来的矩阵元素一起显示:

3 x 2 矩阵。

表示法:矩阵由大写字母指定。 元素由小写字母指定。 下标指示元素的行号和列号。 例如,ij 是矩阵 A 的第 i 行和第 j 列的元素。

下图显示了一个 i × j 矩阵,其中包含矩阵的每个单元格中的单个元素。

包含 i 行和 j 列的矩阵。

矩阵运算

本部分介绍在矩阵上定义的基本运算。

加法。 两个矩阵的 A + B 总和是通过添加 A 和 B 的相应元素获得的:

A + B = \[ a*ij* \] + \[ b*ij* \] = \[ a*ij* + b*ij* \]

标量乘法。 此操作将矩阵乘以实数。 假设有一个实数 k,则通过将 A 的每个元素乘以 k 来获得标量积 kA

kA = k\[ a*ij* \] = \[ k × a*ij* \]

矩阵乘法。 假设两个矩阵 A 和 B 的顺序 (m × n) 和 (n × p) ,则积 C = A × B 是一个矩阵,顺序为 (m × p) ,定义如下:

显示矩阵乘法公式。

或者,等效地:

c*ij* = a*i*1 x b1*j* + a*i*2 x b2*j* + ... + a*in* + b*nj*

也就是说,若要计算每个元素 cij,请执行以下操作:

  1. 取 A 的第 i 行和 B 的第 j 列。
  2. 将行和列中的每对元素相乘:第一行条目乘以第一列条目,第二行项乘以第二列条目,依此类推。
  3. 对结果求和。

下面是将 (2 × 2) 矩阵乘以 (2 × 3) 矩阵的示例。

矩阵乘法。

矩阵乘法不是可交换的。 即 A × B ≠ B × A。此外,从它遵循的定义看,并非每对矩阵都可以相乘。 左侧矩阵中的列数必须等于右侧矩阵中的行数。 否则,不会定义 × 运算符。

标识矩阵。 标识矩阵(指定为 I)是一个平方矩阵,定义如下:

如果 *i* = *j*,则 I*ij* = 1;否则为 0。

换句话说,对于行号等于列号的每个元素,标识矩阵包含 1,对于所有其他元素,则为 0。 例如,下面是 3 × 3 标识矩阵。

标识矩阵。

对于任何矩阵 M,以下相等性都保留。

M x I = M I x M = M

仿射转换

仿射变换是将一个坐标空间映射到另一个坐标空间的数学运算。 换句话说,它将一组点映射到另一组点。 仿射转换具有一些功能,使它们在计算机图形中很有用。

  • 仿射转换保留 共线性。 如果三个或更多点落在一条线上,它们仍然在转换后形成一条线。 直线保持直线。
  • 两个仿射变换的组合是仿射变换。

二维空间的仿射转换具有以下形式。

显示二维空间的仿射转换。

如果应用前面给出的矩阵乘法的定义,则可以显示两个仿射变换的乘积是另一个仿射变换。 若要使用仿射变换来转换 2D 点,该点表示为 1 × 3 矩阵。

P = \|x y 1 \|

前两个元素包含点的 x 和 y 坐标。 将 1 放置在第三个元素中,以便正确计算数学。 若要应用转换,请将两个矩阵相乘,如下所示。

P' = P × M

这将扩展为以下内容。

仿射转换。

其中

x' = ax + cy + e y' = bx + dy + f

若要获取转换的点,请获取矩阵 P' 的前两个元素。

p = (x', y') = (ax + cy + e, bx + dy + f)

注意

1 × n 矩阵称为 行向量。 Direct2D 和 Direct3D 都使用行向量来表示 2D 或 3D 空间中的点。 通过使用列向量 (n × 1) 并转换转换矩阵,可以获得等效的结果。 大多数图形文本使用列向量形式。 本主题介绍行向量形式,以便与 Direct2D 和 Direct3D 保持一致。

 

接下来的几个部分派生基本转换。

翻译转换

转换矩阵采用以下形式。

转换转换。

将点 P 插入此公式会产生:

P' = (*x* + *dx*, *y* + *dy*)

对应于 x (点,y) X 轴中 由 dx 转换,在 Y 轴中 由 dy 转换。

显示两个点的翻译的关系图。

缩放转换

缩放转换矩阵具有以下形式。

缩放转换。

将点 P 插入此公式会产生:

P' = (*x* ≤ *dx*, *y* • *dy*)

对应于 (x,y) 按 dxdy 缩放的点。

显示两个点缩放的关系图。

围绕原点旋转

围绕原点旋转的矩阵具有以下形式。

显示旋转转换的公式。

转换的点为:

P' = (*x*cosΟ – ysinΟ,*x*sinΟ + *y*cosΟ)

证明。 若要显示 P' 表示旋转,请考虑下图。

显示围绕原点旋转的关系图。

给:

P = (x,y)

要转换的原始点。

Φ

线条形成的角度 (0,0) 到 P。

Θ

围绕原点 (x,y) 旋转的角度。

P' = (x',y')

已转换的点。

R

行的长度 (0,0) 到 P。也是旋转圆的半径。

注意

此图使用几何图形中使用的标准坐标系,其中正 y 轴指向上。 Direct2D 使用 Windows 坐标系,其中正 y 轴指向下。

 

x 轴与 (0,0) 到 P' 的直线之间的角度为 ー + 日下午。 以下标识保留:

x = R cosЛ y = R sinЛ x' = R cos (Л + ー) y' = R sin (Л+ ー)

现在,以 日起求解 x'和 y'。 按三角加法公式:

x' = R (cosΟcosΟ – sinΟsinΟ) = RcosΟcosο – RsinΟsinΟ y' = R (sinΟcosΟ + cosΟsinΟ) = RsinΟcosΟ + RcosΟsinΟ

替换后,我们得到:

x' = xcosΘ – ysinΘ y' = xsinΘ + ycosΘ

对应于前面显示的转换点 P。

围绕任意点旋转

若要绕原点 (x,y) 点旋转,请使用以下矩阵。

旋转转换。

可以通过将 x,y) 的点 (为原点来派生此矩阵。

显示围绕点旋转的关系图。

让 (x1、y1) 是围绕 x,y) (点旋转点 (x0,y0) 产生的点。 我们可以派生 x1,如下所示。

x1 = (x0 – x) cosー– (y0 – y) sinЛ + x x1 = x0cosー – y0sinЛ + \[ (1 – cosЛ) + ysinЛ \]

现在,请使用前面的公式 x1 = ax0 + cy0 + e 公式,将此公式插入转换矩阵。 使用相同的过程派生 y1。

倾斜转换

倾斜转换由四个参数定义:

  • 日下午:沿 x 轴倾斜的量,以从 y 轴的角度度量。
  • Ø:沿 y 轴倾斜的量,以从 x 轴的角度度量。
  • (pxpy) :执行倾斜的点的 x 坐标和 y 坐标。

倾斜转换使用以下矩阵。

倾斜转换。

转换的点为:

P' = (*x* + *y*tanЛ – *py*tanЛ, *y* + *x*tanЛ) – *py*tanЛ

或等效的:

P' = (*x* + (*y* – *py*) tanΟ, *y* + (*x* – *px*) tanЛ)

若要查看此转换的工作原理,请单独考虑每个组件。 Θ 参数将 x 方向上的每一个点移动等于 tan口的量。 下图显示了 Θ 与 x 轴倾斜之间的关系。

显示沿 x 轴倾斜的关系图。

下面是应用于矩形的相同倾斜:

显示应用于矩形时沿 x 轴倾斜的关系图。

Ф 参数具有相同的效果,但沿 y 轴:

显示沿 y 轴倾斜的关系图。

下图显示了应用于矩形的 y 轴倾斜。

显示应用于矩形时沿 y 轴倾斜的关系图。

最后,参数 pxpy 沿 x 轴和 y 轴移动偏斜的中心点。

在 Direct2D 中表示转换

所有 Direct2D 转换都是仿射转换。 Direct2D 不支持非仿射转换。 转换由 D2D1_MATRIX_3X2_F 结构表示。 此结构定义 3 × 2 矩阵。 由于仿射转换的第三列始终与 ([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 ,并提供用于创建任何基本仿射转换的帮助程序方法。 类还定义 运算符* () 用于组合两个或多个转换,如 在 Direct2D 中应用转换中所述。

下一步

模块 4. 用户输入