程序员数学:用Python学透线性代数和微积分
上QQ阅读APP看书,第一时间看更新

2.4 向量集合的变换

无论使用极坐标系还是笛卡儿坐标系,向量集合都会存储一些数据,参见前面画的那只恐龙。事实证明,当处理向量时,某种坐标系可能比另一种坐标系更好。我们已经看到,用笛卡儿坐标移动(或平移)向量集合很容易,而在极坐标中就不那么自然了。不过,由于极坐标包含角度信息,会使得旋转向量更为方便。

在极坐标中,角度的相加会使向量逆时针旋转,角度的相减会使向量顺时针旋转。极坐标(1, 2)的距离是1,角度是2弧度。(注意:如果没有角度符号,单位就是弧度。)从2弧度开始,加减1分别使向量逆时针或顺时针旋转1弧度(见图2-54)。

图2-54 加减弧度使向量绕原点旋转

同时旋转多个向量的效果是使这些向量代表的图形围绕原点旋转。draw函数只接收笛卡儿坐标,所以需要在使用它之前将极坐标转换为笛卡儿坐标。类似地,因为在极坐标中可以旋转向量,所以需要在执行旋转之前将笛卡儿坐标转换为极坐标。可以使用下面这个方法来旋转恐龙。

rotation_angle = pi/4
dino_polar = [to_polar(v) for v in dino_vectors]
dino_rotated_polar = [(l,angle + rotation_angle) for l,angle in dino_polar]
dino_rotated = [to_cartesian(p) for p in dino_rotated_polar]
draw(
    Polygon(*dino_vectors, color=gray),
    Polygon(*dino_rotated, color=red)
)

上面的代码让原来的灰色恐龙逆时针旋转π/4,得到了一只红色(书中为深灰色)的恐龙 (见图2-55)。

图2-55 原始恐龙和旋转后的恐龙

作为本节结尾的练习,你可以写一个通用的rotate函数,将向量列表旋转相同的角度。我将在接下来的几个示例中使用这个函数,既可以参考我在源代码中提供的实现,也可以自己实现一个。

2.4.1 组合向量变换

到目前为止,我们已经学习了如何平移、缩放和旋转向量。将这些变换应用于向量的集合,会对这些向量在平面上定义的形状产生同样的效果。当依次应用这些向量变换时,效果会非常惊人。

例如,我们可以先旋转恐龙,然后平移。使用2.2.4节练习中的translate函数和rotate函数,可以很方便地实现(见图2-56中的结果)。

new_dino = translate((8,8), rotate(5 * pi/3, dino_vectors))

图2-56 恐龙的旋转和平移

首先旋转,将恐龙逆时针旋转5π/3,也就是逆时针旋转大半圈。然后将恐龙向上和向右各平移8个单位。想象一下,适当地结合旋转和平移,可以将恐龙(或任何图形)移动到平面中任意需要的位置和方向。无论是在电影中还是在游戏中制作恐龙的动画,都可以通过向量变换灵活地移动恐龙。如此一来,就以编程的方式赋予了它生命。

我们不会只停留在画恐龙阶段,还有很多其他关于向量的操作等待我们去探索,比如泛化到更高维的操作。现实世界中的数据集通常有几十或几百个维度,所以我们也会对这些数据集应用类似的转换。对数据集进行平移和旋转,使其重要特征更加清晰,是非常有用的。虽然无法想象对100维的数据进行旋转操作,但可以先思考如何旋转二维数据。

2.4.2 练习

练习2.42:实现rotate(angle, vectors)函数,接收笛卡儿坐标向量数组,并将这些向量旋转指定的角度(根据角度的正负来确定是逆时针还是顺时针)。

def rotate(angle, vectors):
    polars = [to_polar(v) for v in vectors]
    return [to_cartesian((l, a+angle)) for l,a in polars]

 

练习2.43:实现函数regular_polygon(n),返回一个规则边形(即所有角和边长都相等)各顶点的笛卡儿坐标。例如,polygon(7)返回如图2-57所定义七边形的顶点向量。

图2-57 一个规则的七边形,其顶点围绕原点均匀分布

提示:在图2-57中,基于原点对向量(1, 0)进行6次均匀的旋转,从而得到了各个顶点。

def regular_polygon(n):
    return [to_cartesian((1, 2*pi*k/n)) for k in range(0,n)]

 

练习2.44:先将恐龙按向量(8, 8)平移,再将其旋转5π/3(见图2-58),结果是什么?和先旋转再平移的结果一样吗?

图2-58 先平移再旋转恐龙

结果并一样。通常,以不同的顺序应用旋转和平移,会产生不同的结果。