写给前端工程师的向量知识

1,684 阅读4分钟

前言

时光飞逝,不知不觉地已经在前端领域已经练习时长五年半了。工作内容无非就是做做后台管理系统的增删改查居多,也做过一些可视化方面的项目,现在看来也是太普通,太没技术含量的活了。随着 ChatGPT 浪潮的兴起,IT行业也必将迎来新的变革,例如低级重复性的工作内容多半会被机器所取代,你会越来越变得廉价和可替代。唯有保持不断学习,重视基础理论和知识,提升自己才能更快的成长。

思考了很久,我打算从零学习 WEBGL 这门技术。因为这门技术涉及到了很多理论知识,例如向量,矩阵,几何,图形学等,这些知识具有通用性,在人工智能方面也有广泛的应用。而且当你学完之后能做出一些效果出来,那将很有成就感。学习没有捷径,这里我就先不去学封装好了的 three.js 框架了,万丈高楼平地起,学习WEBGL,我们先得复习下我们高中学习的向量知识。

向量

向量通俗来说就是有方向和大小的度量,一些教材也称向量为矢量,这是一回事。向量可以进行一些运算。向量可以进行加减运算,点乘运算和叉乘运算。不同运算具有不同的现实意义。

向量加法

向量加法运算即将两个向量的横坐标相加,纵坐标相加即可得到新的向量。

a=(x1,y1)b=(x2,y2)a+b=(x1+x2,y1+y2)\vec{a} = (x1,y1) \\ \vec{b} = (x2,y2) \\ 则\vec{a}+\vec{b} = (x1+x2,y1+y2)

image.png

根据向量的加法规则(平行四边形法则)可知:
w=v+u=(3,1)+(2,3)=(5,4)\vec{w}=\vec{v}+\vec{u}=(3,1)+(2,3)=(5,4)

向量的减法

向量的减法就是第一个向量加上第二个向量的反方向,也遵循平行四边形法则。

a=(x1,y1)b=(x2,y2)ab=a+(b)=(x1,y1)+(x2,y2)=(x1x2,y1y2)\vec{a} = (x1,y1) \\ \vec{b} = (x2,y2) \\ 则\vec{a}-\vec{b} = \vec{a}+-(\vec{b}) = (x1,y1) + (-x2,-y2) = (x1-x2,y1-y2)

image.png

uv=u+(v)=(2,3)(3,1)=(23,31)=(1,2)\vec{u}-\vec{v}=\vec{u}+-(\vec{v}) = (2,3) - (3,1) =(2-3,3-1) = (-1,2)

向量数乘

数乘很好理解
λu=λ(x,y)=(λx,λy)λ\vec{u}=λ(x,y) = (λx,λy)

向量点乘

两个向量相乘的几何意义可以看成一个向量在另一个向量方向上的投影长度与另一个向量长度相乘。向量相乘具有如下公式:
vw=vwcosθ\vec{v} \cdot \vec{w}=|\vec{v}| \cdot|\vec{w}| \cos \theta

CE垂直于AB,根据余弦定义: cosθ=AEAC\cos \theta=\frac{A E}{A C} ,可知AE=w=ACcosθ\vec{AE} = \vec{w} = |\vec{AC}|\cdot\cos \theta,其中AE即为向量w在v向量上的投影。

image.png

如果你要计算两个向量的点乘值,你不得不计算出各自向量的长度,还需要计算出这两个向量的夹角。长度好说,套用勾股定理即可,夹角就不好求了。其实向量的点乘还可以表示为下面方式:

假如 v=(x1,y1)\vec{v}=(x1,y1) , w=(x2,y2)\vec{w}=(x2,y2), 则有 vw=x1x2+y1y2\vec{v}\cdot\vec{w} = x1*x2+y1*y2

我们可以来证明一下:根据高中学的余弦定理
vw2=v2+w22vwcosθ|\vec{v}-\vec{w}|^{2}=|\vec{v}|^{2}+|\vec{w}|^{2}-2|\vec{v}||\vec{w}| \cos \theta

(x1x2)2+(y1y2)2=x12+y12+x22+y222vw{\left(x_{1}-x_{2}\right)^{2}+\left(y_{1}-y_{2}\right)^{2}}=x_{1}^{2}+y_{1}{ }^{2}+x_{2}^{2}+y_{2}^{2}-2 \vec{v} \cdot \vec{w} 可以推理出
vw=x1x2+y1y2\vec{v}\cdot\vec{w} = x1\cdot x2 + y1\cdot y2

也可以推理出两个向量夹角余弦值公式

cosθ=vwvw=x1x2+y1y2x12+y12x22+y22\cos \theta=\frac{\vec{v} \cdot \vec{w}}{|\vec{v}| \cdot|\vec{w}|}=\frac{x_{1} x_{2}+y_{1} y_{2}}{\sqrt{x_{1}^{2}+y_{1}^{2}} \cdot \sqrt{x_{2}^{2}+y_{2}^{2}}}

那如何求解出向量 w\vec{w} 在向量 v\vec{v} 上的投影向量AE\vec{AE}呢?我们可以先求解出向量AE\vec{AE}的长度:

AE=ωcosθ=ωvwvw=5×3+1×432+42=195|\overrightarrow{A E}|=|\vec{\omega}| \cos \theta = |\vec{\omega}|\frac{\vec{v} \cdot \vec{w}}{|\vec{v}| \cdot|\vec{w}|} =\frac{5×3+1×4}{\sqrt{3^{2}+4^{2}}} =\frac{19}{5}

AE=(X3,Y3)\vec{AE} = (X_{3},Y_{3})

AEAB=1925=1925=X33=Y34\frac{|\vec{AE}|}{|\vec{AB}|} = \frac{19}{25} =\frac{19}{25} = \frac{X_{3}}{3} = \frac{Y_{3}}{4}

求出:X3=5725,Y3=7625X_{3} = \frac{57}{25},Y_{3} = \frac{76}{25}

三维向量点乘

w=(x1,y1,z1),v=(x2,y2,z2)\vec{w} =(x_{1},y_{1},z_{1}),\vec{v} =(x_{2},y_{2},z_{2})

wv=wvcosθ=x1x2+y1y2+z1z2\vec{w}\cdot\vec{v} =|\vec{w}|\cdot|\vec{v}|\cdot\cos \theta =x_{1}x_{2}+y_{1}y_{2}+z_{1}z_{2}

cosθ=vwvw=x1x2+y1y2+z1z2x12+y12+z12x22+y22+z22\cos \theta=\frac{\vec{v} \cdot \vec{w}}{|\vec{v}| \cdot|\vec{w}|}=\frac{x_{1} x_{2}+y_{1} y_{2}+z_{1}z_{2}}{\sqrt{x_{1}^{2}+y_{1}^{2}+z_{1}^{2}} \cdot \sqrt{x_{2}^{2}+y_{2}^{2}+z_{2}^{2}}}

法向量

在二维平面内,假如一个向量v\vec{v}垂直于一个向量w\vec{w},则称v\vec{v}为向量w\vec{w}的一个法向量

image.png

AB=(3,2)\vec{AB} = (3,2),设法向量v=(x1,y1)\vec{v} = (x_{1},y_{1}),根据点乘公式:
ABv=ABvcos900=3x1+2y1=0\vec{AB}\cdot\vec{v} = |\vec{AB}|\cdot|\vec{v}|\cdot\cos90^0 =3x_{1}+2y_{1} = 0
显然只要满足: 3x1+2y1=03x_{1}+2y_{1} = 0 的点都可以是AB\vec{AB}的法向量,一般来说在图形学中我们会求解其中的一个长度为1的法向量

{3x1+2y1=0x12+y12=1\left\{\begin{array}{l} 3 x_{1}+2 y_{1}=0 \\ x_{1}^{2}+y_{1}^{2}=1 \end{array}\right.

叉乘

上述向量与向量相乘,例如vw\vec{v}\cdot\vec{w},中间我们是“.”这个符号来相乘,向量和向量如果用×号来相乘则具有不同的意义,这点要注意区分,一般来说叉乘在三维向量中更加有意义。

a×b=c\vec{a}×\vec{b} = \vec{c}

首先向量a\vec{a}与向量b\vec{b}叉乘结果依然是一个向量c\vec{c},且这个向量会同时垂直于a\vec{a}b\vec{b},c\vec{c}也可以称之为a\vec{a}b\vec{b}构成的平面的法向量。

image.png

a=(x1,y1,z1)\vec{a}=(x_{1},y_{1},z_{1})
b=(x2,y2,z2)\vec{b}=(x_{2},y_{2},z_{2})
a×b\vec{a}×\vec{b} = (y1z2y2z1,x2z1x1z2,x1y2x2y1)(y_{1}z_{2} - y_{2}z_{1},x_{2}z_{1} - x_{1}z_{2},x_{1}y_{2} - x_{2}y_{1})

AB=(8,6,2)\vec{AB} = (8,6,2),
AC=(1,8,4)\vec{AC} = (-1,8,4)

AB×AC\vec{AB}×\vec{AC} = (y1z2y2z1,x1z2x2z1,x1y2x2y1)(y_{1}z_{2} - y_{2}z_{1},x_{1}z_{2} - x_{2}z_{1},x_{1}y_{2} - x_{2}y_{1}) = (2416,232,64+6)=(8,34,70)(24-16,-2-32,64+6) = (8,-34,70)

image.png

我们可以通过前面的点乘公式验证一下,对于垂直向量有: x1x2+y1y2+z1z2=0x1x2+y1y2+z1z2 = 0
8×8+6×34+2×70=08×8+6×-34+2×70 = 0
1×8+8×34+4×70=0-1×8+8×-34+4×70 = 0

向量的叉乘的顺序很重要a×b\vec{a}×\vec{b}b×a\vec{b}×\vec{a}是不相等的,这两个结果恰好是相反方向的法向量,上述的AB×AC\vec{AB}×\vec{AC}为什么是AD\vec{AD}而不是AD\vec{AD}的相反方向呢,我们又应该如何快速地通过两个向量来判断法向量的朝向呢?这里就要讲到一个重要的规则:右手法则

a×b\vec{a}×\vec{b} 伸出你的右手,把食指指向第一个向量a,这个也可以说是x的方向,中指指向第二个向量b,也可以理解为y的方向,则大拇指指向的就是法向量方向

image.png

image.png

注意顺序不能错,如果是AC×AB\vec{AC}×\vec{AB} 则先将食指指向AC\vec{AC},中指指向AB\vec{AB},最后伸出拇指指向法向量

image.png

基向量

i=(1,0)\vec{i}=(1,0)
j=(0,1)\vec{j}=(0,1)

image.png

平面内的任何一个向量,都可以由这两个向量变换而得

image.png

v=2i+3j=2(1,0)+3(0,1)=(2,3)\vec{v}=2\vec{i}+3\vec{j} = 2(1,0)+3(0,1) = (2,3)

x=m×1+n×0y=t×0+q×1\begin{array}{l} x=m \times 1+n\times 0 \\ y=t \times 0+q\times 1 \end{array}

基向量的意义在后续的矩阵教程中会重点讲述。
(完)