向量点乘及其几何意义详解
向量点乘及其几何意义详解
向量点乘是计算机图形学和线性代数中的一个核心概念,它不仅能够帮助我们计算两个向量之间的夹角,还能用于判断物体的位置关系。本文将从点乘的基本定义出发,深入探讨其几何意义,并结合Three.js源码进行具体说明。
点乘的含义
点乘(Dot Product)是两个向量之间的运算,其结果是一个标量。点乘的计算公式为:
- 向量a长度 * 向量b长度 * cos(ab夹角)
- 向量a在向量b上的投影 * 向量b
- 点乘 = |a||b|cosθ
两向量归一化后点乘
当两个向量归一化后(即长度为1),它们的点乘结果就等于两向量夹角的余弦值:
// 两向量垂直
const a = new THREE.Vector3(0, 10, 0);
const b = new THREE.Vector3(20, 0, 0);
const dot = a.dot(b); // 向量a与向量b点乘,返回结果是一个数字
console.log('点乘结果', dot); // 0 a b正交
// a、b向量归一化后点乘 就是等于两向量夹角的余弦值
const cos = a.normalize().dot(b.normalize());
console.log('向量夹角余弦值', cos); // 0
const rad = Math.acos(cos); // 反余弦计算向量夹角弧度 余弦转弧度
console.log('向量夹角弧度', rad); // 1.570
// 弧度转角度
const angle = THREE.MathUtils.radToDeg(rad);
console.log('向量夹角角度值', angle); // 90
点乘满足交换律
虽然点乘满足交换律,但向量的方向会对夹角计算产生影响。例如,在计算三角形夹角θ时:
// 三角形的三个点坐标p1,p2,p3
const p1 = new THREE.Vector3(0, 0, 0); // 点1坐标
const p2 = new THREE.Vector3(20, 0, 0); // 点2坐标
const p3 = new THREE.Vector3(10, 10, 0); // 点3坐标
const a = p3.clone().sub(p1); // p1,p3两个点确定一个向量 p3-p1
const b = p2.clone().sub(p1); // p1,p2两个点确定一个向量 p2-p1
// a、b向量归一化后点乘 就是 两向量夹角的cos 点乘 = |a||b|cosθ
const cos = a.normalize().dot(b.normalize());
const rad = Math.acos(cos); // 反余弦计算向量夹角弧度
const angle = THREE.MathUtils.radToDeg(rad); // 弧度转角度
console.log('向量夹角角度值', angle); // 45
当a向量方向由 p1->p3 变为 p3->p1时,将向量方向反过来,得到的是 135度:
const a = p1.clone().sub(p3); // 和p3.clone().sub(p1)向量方向反过来 重新计算角度值 p1-p3
const b = p2.clone().sub(p1); // p1,p2两个点确定一个向量 p2-p1
// a、b向量归一化后点乘 就是 两向量夹角的cos 点乘 = |a||b|cosθ
const cos = a.normalize().dot(b.normalize());
const rad = Math.acos(cos); // 反余弦计算向量夹角弧度
const angle = THREE.MathUtils.radToDeg(rad); // 弧度转角度
console.log('向量夹角角度值', angle); // 135
当b向量方向由 p2->p1 变为 p1->p2时,将b向量方向反过来,夹角又会变为 45度:
const a = p1.clone().sub(p3); // 和p3.clone().sub(p1)向量方向反过来 重新计算角度值
const b = p1.clone().sub(p2); // p1,p2两个点确定一个向量 p2-p1
// a、b向量归一化后点乘 就是 两向量夹角的cos 点乘 = |a||b|cosθ
const cos = a.normalize().dot(b.normalize());
const rad = Math.acos(cos); // 反余弦计算向量夹角弧度
const angle = THREE.MathUtils.radToDeg(rad); // 弧度转角度
console.log('向量夹角角度值', angle); // 45
点乘的几何意义
正交
两向量正交 <=> 两向量夹角为 90度 <=> cosθ为0 <=> 点积为0
平行
两向量平行 <=> 两向量夹角为0度 <=> cosθ为1 <=> 点积为1 (两向量长度是1)
逆向
两向量相反 <=> 两向量夹角为180度 <=> cosθ为-1 <=> 点积为-1 (两向量长度是1)
Three.js源码实现点乘 dot
在Three.js中,点乘操作可以通过Vector3类的dot
方法实现。
点乘判断物体在人前或人后
物体绕着人360度挪动位置,创建的不同位置人指向物体的向量b,会发现向量b与向量a的夹角处于0~180度之间。余弦规律表明,角度θ在0 ~180度范围内,随着θ度数的增加,角度θ余弦值cos(θ)下降。换句话说,向量b与向量a夹角越小,对应的余弦值越大。余弦值满足负相关。
分析:向量a和b夹角,在0~180度的范围内的前提下
当a和b点乘a. dot(b)大于0,意味着cos(θ)大于0,cos(θ)大于0意味着夹角θ是090度,θ是090度说明物体在人的前方。
a和b点乘 a.dot (b)小于0,意味着cos(θ)小于0,0180度的范围内,cos(θ)小于0,意味着夹角θ是90180度,θ是90~180度说明物体在人的后方。

// 已知条件
person.position.set(0, 0, 2); // 人位置
mesh.position.set(2, 0, -3); // 物体位置
// a向量:人的正前方沿着z轴负半轴
const a = new THREE.Vector3(0, 0, -1);
// 物体坐标减去人坐标,创建一个人指向物体的向量
const b = mesh.position.clone().sub(person.position);
const dot = a.dot(b); // 向量a和b点乘
if (dot > 0) { // 物体在人前面,向量a和b夹角0~90度,夹角余弦值大于0,a和b点乘`.dot()`大于0。
console.log('物体在人前面'); // 物体在人前面
} else if (dot < 0) { // 物体在人后面,向量a和b夹角0~180度,夹角余弦值小于0,a和b点乘`.dot()`小于0
console.log('物体在人后面');
}