向量相乘

点乘

两个向量的点乘等于它们的数乘结果乘以两个向量之间夹角的余弦值。公式:


v¯⋅k¯=||v¯||⋅||k¯||⋅cosθ


v¯ 和k¯ 都是单位向量,它们的长度会等于1。这样公式会有效简化成:


v¯⋅k¯=1⋅1⋅cosθ=cosθ




我们使用点乘(dot product)计算方向是否一致。两个单位向量之间的点乘等于这两个向量之间夹角的余弦值。当我们计算出的点乘结果为1,则说明两向量间余弦值为1,即两者夹角为0°,说明两者方向一致,而结果为-1时,说明两者方向相反(180°)。所以我们不必算出最后的角度,仅仅通过点乘结果就可以判断两向量之间方向的关系。

单位向量是指向量长度大小(模)为1的向量,也就是说当向量v满足sqrt(v.x*v.x+v.y*v.y+v.z*v.z)=1时,此向量为单位向量。不要认为单位向量就是(1,1,1)!

如果要使用点乘的结果来表示两向量之间的角度,首先要将两个向量的长度变为单位长度,也就是将两个向量变到单位向量再计算点乘。

点乘的计算是通过将对应分量逐个相乘,然后再把所得积相加来计算的。两个单位向量的(你可以验证它们的长度都为1)点乘会像是这样:


向量相乘Python 向量相乘等于1_transform


cos−1

叉乘

叉乘只在3D空间中有定义,它需要两个不平行向量作为输入,生成一个正交于两个输入向量的第三个向量。如果输入的两个向量也是正交的,那么叉乘之后将会产生3个互相正交的向量。接下来的教程中这会非常有用。下面的图片展示了3D空间中叉乘的样子:


向量相乘Python 向量相乘等于1_变换_02



叉乘得到的结果向量使用右手法则得到。运算公式:


  向量相乘Python 向量相乘等于1_变换_03 


=(

 

向量相乘Python 向量相乘等于1_transform_04

 

),

  向量相乘Python 向量相乘等于1_向量_05 

=(

 

向量相乘Python 向量相乘等于1_transform_06

 

)。i,j,k分别是X,Y,Z轴方向的单位向量,则:


向量相乘Python 向量相乘等于1_变换_03 ✖️向量相乘Python 向量相乘等于1_向量_05 =  

向量相乘Python 向量相乘等于1_向量_09

               = i· 

向量相乘Python 向量相乘等于1_transform_10

 + j ·

向量相乘Python 向量相乘等于1_矩阵_11

 + k·

向量相乘Python 向量相乘等于1_矩阵_12

 - k·

向量相乘Python 向量相乘等于1_transform_13

 - j·

向量相乘Python 向量相乘等于1_向量_14

 - i· 

向量相乘Python 向量相乘等于1_transform_15

=  (

 

向量相乘Python 向量相乘等于1_transform_10

 

-

 

向量相乘Python 向量相乘等于1_transform_15

 

) i +  (

 

向量相乘Python 向量相乘等于1_矩阵_11

 

-

 

向量相乘Python 向量相乘等于1_向量_14

 

) j  + (

 

向量相乘Python 向量相乘等于1_矩阵_12

 

-

 

向量相乘Python 向量相乘等于1_transform_13

 

) k


矩阵与向量相乘

缩放


对一个向量进行缩放(Scaling)就是对向量的长度进行缩放,而保持它的方向不变。由于我们进行的是2维或3维操作,我们可以分别定义一个


有2或3个缩放变量的向量,每个变量缩放一个轴(x、y或z)。


下面会构造一个变换矩阵来为我们提供缩放功能。我们从单位矩阵了解到,每个对角线元素会分别与向量的对应元素相乘。把向量缩放3倍表示为:


向量相乘Python 向量相乘等于1_向量_22

注意,第四个缩放向量仍然是1,因为在3D空间中缩放w分量是无意义的。w分量另有其他用途,在后面我们会看到。

位移

      位移 (Translation)是在原始向量的基础上加上另一个向量从而获得一个在不同位置的新向量的过程,从而在位移向量基础上 移动 了原始向量。在4×4矩阵上有几个特别的位置用来执行特定的操作,对于位移来说它们是第四列最上面的3个值。如果我们把位移向量表示为

(Tx,Ty, Tz)

,我们就能把位移矩阵定义为:


向量相乘Python 向量相乘等于1_transform_23


所有的位移值都要乘以向量的w行,所以位移值会加到向量的原始值上(想想矩阵乘法法则)。而如果你用3x3矩阵我们的位移值就没地方放也没地方乘了,所以是不行的。




齐次坐标(Homogeneous Coordinates)

向量的w分量也叫齐次坐标。想要从齐次向量得到3D向量,我们可以把x、y和z坐标分别除以w坐标。我们通常不会注意这个问题,因为w分量通常是1.0。使用齐次坐标有几点好处:它允许我们在3D向量上进行位移(如果没有w分量我们是不能位移向量的),而且下一章我们会用w值创建3D视觉效果。

如果一个向量的齐次坐标是0,这个坐标就是方向向量(Direction Vector),因为w坐标是0,这个向量就不能位移(译注:这也就是我们说的不能位移一个方向)。




      旋转




下图中展示的2D向量是k向右旋转72°得到的:


向量相乘Python 向量相乘等于1_矩阵_24

旋转矩阵在3D空间中每个单位轴都有不同定义,旋转角度用θ表示:

沿x轴旋转:


向量相乘Python 向量相乘等于1_变换_25


沿y轴旋转:


向量相乘Python 向量相乘等于1_transform_26


沿z轴旋转:


向量相乘Python 向量相乘等于1_向量_27


利用旋转矩阵我们可以把我们的位置向量沿一个单位轴进行旋转。也可以把多个矩阵结合起来,比如先沿着x轴旋转再沿着y轴旋转。但是这会很快导致一个问题——万向节死锁(Gimbal Lock)。我们不会讨论它的细节,但是一个更好的解决方案是沿着任意轴比如(0.662, 0.2, 0.7222)(注意这是个单位向量)旋转,而不是使用一系列旋转矩阵的组合。这样一个旋转矩阵是存在的,(Rx,Ry,Rz)代表任意旋转轴:


向量相乘Python 向量相乘等于1_向量相乘Python_28




避免万向节死锁的真正解决方案是使用四元数(Quaternion),它不仅安全,而且计算更加友好。