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

3.1 在三维空间中绘制向量

在二维平面上,向量拥有三种可互换的心智模型:坐标对、有固定长度和方向的箭头以及相对于原点的点。由于本书篇幅有限,我们只专注于平面的一小部分——如图3-3所示的长宽固定的矩形。

图3-3 二维平面的一小部分

也能以类似的方式解释三维向量。我们从三维空间中的一个小方框开始,而不是观察平面中的矩形。这样的三维框(如图3-4所示)具有有限的长度、宽度和高度。三维空间中仍然保留了方向和方向的概念,并增加了方向来测量高度。

图3-4 三维空间中的小框具有长度()、宽度()和高度(

可以说,所有二维向量也都存在于三维空间中,它们的大小和方向不变,但被固定在一个高度为零的平面上。图3-5显示了被嵌入三维空间的向量(4, 3)的二维图形,它的特征与之前相同。右图对所有仍然保持不变的特征添加了注释。

图3-5 三维世界包含的二维世界和其中的向量(4, 3)

虚线在没有深度的二维平面中形成了一个矩形。画出垂直相交的虚线有助于定位三维空间中的点。否则,我们可能会受到视觉的误导,点其实不在我们认为的位置上。

可见,向量不仅存在于平面中,也存在于更大的三维空间中。我们可以画出另一个三维向量(新的箭头和新的点),它位于原来的平面之外,向更大的高度值延伸(见图3-6)。

图3-6 与图3-5中的二维世界和其中的向量(4, 3)相比,延伸到三维的向量

通过绘制虚线框而不是图3-5中的虚线矩形,可以明确第二个向量的位置。在图3-6中,这个虚线框显示了向量在三维空间中覆盖的长度、宽度和高度。就像在二维平面上一样,箭头和点在三维空间中充当向量的心智模型,同样可以用坐标来测量。

3.1.1 用坐标表示三维向量

在二维平面上,(4, 3)这个数对足以指定一个点或箭头,但在三维空间中,存在许多坐标为4、坐标为3的点。事实上,在三维空间中,有一整条线上的点都有这个坐标(如图3-7所示),每个点在(高度)方向上都有不同的位置。

图3-7 坐标和坐标相同但坐标不同的几个向量

要在三维空间中指定唯一的点,总共需要三个数。像(4, 3, 5)这样的三元数对在三维空间中称为向量的坐标、坐标和坐标。和以前一样,可以将这些数理解为找到所需点的指令。如图3-8所示,要找到(4, 3, 5)这个点,首先在方向上移动+4个单位,然后在方向上移动+3个单位,最后在方向上移动+5个单位。

图3-8 坐标(4, 3, 5)指定三维空间中该点的方向

3.1.2 用Python进行三维绘图

和第2章中一样,我们使用Python的Matplotlib库的包装器来绘制三维空间中的向量。你可以在本书的源代码中找到实现方法,但我将坚持使用一些包装器来专注于绘图的概念性过程,而不是Matplotlib的细节。

我的包装器使用了诸如Points3DArrow3D这些新的类来将三维对象和二维对象区分开来。新函数draw3d负责解释和渲染三维对象,让它们看起来是三维的。draw3d()会默认显示轴、原点以及三维空间中的小框(见图3-9),即使没有指定要绘制的对象时也是如此。

图3-9 用Matplotlib的draw3d()绘制一个空的三维区域

尽管看上去有所偏斜,但绘制出的轴、轴和轴在空间中是垂直的。为清晰起见,Matplotlib会在框外显示单位,但将原点和轴本身显示在框内。原点的坐标是(0, 0, 0),坐标轴从它出发并分别在正负方向上延伸。

Points3D类存储了我们希望以点来呈现的向量集合,因此会在三维空间中将其绘制为点。例如,下面的代码可以绘制出向量(2, 2, 2)和(1, -2, -2),生成图3-10。

draw3d(
    Points3D((2,2,2),(1,-2,-2))
)

图3-10 画出点(2, 2, 2)和(1, -2, -2)

为了将这些向量可视化为箭头,可以将向量表示为Arrow3D对象。此外,也可以用Segment3D对象连接箭头的头部,如图3-11所示。

draw3d(
    Points3D((2,2,2),(1,-2,-2)),
    Arrow3D((2,2,2)),
    Arrow3D((1,-2,-2)),
    Segment3D((2,2,2), (1,-2,-2))
)

要看出图3-11中箭头的指向有点儿困难。为了让方向更清晰,可以在箭头周围画上虚线框,使其看起来更立体。由于会频繁绘制框,因此我创建了Box3D类来表示一个角位于原点、其对角位于给定点的框。图3-12展示了这个三维框,代码如下所示。

draw3d(
    Points3D((2,2,2),(1,-2,-2)),
    Arrow3D((2,2,2)),
    Arrow3D((1,-2,-2)),
    Segment3D((2,2,2), (1,-2,-2)),
    Box3D(2,2,2),
    Box3D(1,-2,-2)
)

图3-11 绘制三维箭头

图3-12 绘制虚线框,使箭头看起来是三维的

本章用了许多关键字参数,但没有明确地加以介绍(希望它们的含义不言自明)。例如,color关键字参数可以被传递给大多数构造函数,来控制所绘对象的颜色。

3.1.3 练习

练习3.1:绘制表示坐标(-1, -2, 2)的点和三维箭头,以及使箭头更立体的虚线框。可以手动绘制来进行练习,不过从现在开始,我们将使用Python来绘图。

:答案如图3-13所示。

图3-13 向量(-1, -2, 2)和使箭头更立体的虚线框

 

练习3.2(小项目):有8个三维向量的坐标都是+1或-1。例如,(1, -1, 1)就是其中之一。将这8个向量绘制成点。然后想办法通过Segment3D对象用线段将它们连接到一起,以形成立方体的轮廓。

提示:总共需要12条线段。

:因为只有8个顶点和12条边,所以要把它们全部列出来并不太烦琐,不过这里使用列表推导式来枚举它们。对于顶点,让分布在两个可能值组成的列表[1,-1]上,并收集8个结果。对于边,把它们分成3组、每组4条,分别指向每个坐标方向。例如,有4条边从指向,它们的坐标和坐标在两个端点处都是相同的。结果如图3-14所示。

pm1 = [1,-1]
vertices = [(x,y,z) for x in pm1 for y in pm1 for z in pm1]
edges = [((-1,y,z),(1,y,z)) for y in pm1 for z in pm1] +\
            [((x,-1,z),(x,1,z)) for x in pm1 for z in pm1] +\
            [((x,y,-1),(x,y,1)) for x in pm1 for y in pm1]
draw3d(
    Points3D(*vertices,color=blue),
    *[Segment3D(*edge) for edge in edges]
)

图3-14 所有顶点坐标等于+1或-1的立方体