向量的点乘(内积)
定义
概括地说,向量的点乘(内积/数量积)。对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,如下所示,对于向量a和向量b:
a和b的点乘公式为:
这里要求一维向量a和向量b的行列数相同。注意:点乘的结果是一个标量(数量而不是向量)
定义:两个向量a与b的点乘为 a·b = |a||b|cos∠(a, b),特别地,0·a =a·0 = 0;若a,b是非零向量,则a与b****正交的充要条件是a·b = 0。
向量点乘的性质
- a^2 ≥ 0;当a^2 = 0时,必有a = 0. (正定性)
- a·b = b·a. (对称性)
- (λa + μb)·c = λa·c + μb·c,对任意实数λ, μ成立. (线性)
- cos∠(a,b) =a·b/(|a||b|).
- |a·b| ≤ |a||b|,等号只在a与b共线时成立.
向量点乘的几何意义
- 表征或计算两个向量之间的夹角;
- b向量在a向量方向上的投影;
有公式:
推导过程如下,首先看一下向量组成:
定义向量c:
根据三角形余弦定理(这里a、b、c均为向量,下同)有:
根据关系c=a-b有:
即:
a?b=|a||b|cos?(θ)
向量a,b的长度都是可以计算的已知量,从而有a和b间的夹角θ:
θ=arccos?(a?b|a||b|)
进而可以进一步判断两个向量是否同一方向或正交(即垂直)等方向关系,具体对应关系为:
a?b>0→方向基本相同,夹角在0°到90°之间 a?b=0→ 正交,相互垂直 a?b<0→ 方向基本相反,夹角在90°到180°之间
向量的叉乘(外积)
定义
概括地说,两个向量的叉乘,又叫外积、叉积向量积,其运算结果是一个向量而不是一个标量。并且两个向量的叉乘与这两个向量组成的坐标平面垂直。
定义:向量a与b的外积a×b是一个向量,其长度等于|a×b| = |a||b|sin∠(a,b),其方向正交于a与b。并且,(a,b,a×b)构成右手系。 特别地,0×a = a×0 = 0.此外,对任意向量a,a×a=0。
对于向量a和向量b:
a和b的叉乘公式为:
其中:
根据i、j、k间关系,有:
向量叉乘的性质
- a × b = -b × a. (反称性)
- (λa + μb) × c = λ(a ×c) + μ(b ×c). (线性)
向量叉乘的几何意义
在三维几何中,向量a和向量b的外积结果是一个向量,有个更通俗易懂的叫法是法向量,该向量垂直于a和b向量构成的平面。
在3D图像学中,外积的概念非常有用,可以通过两个向量的叉乘,生成第三个垂直于a,b的法向量,从而构建X、Y、Z坐标系。如下图所示:
在二维空间中,叉乘还有另外一个几何意义就是:|a×b|在数值上等于由向量a和向量b构成的平行四边形的面积。
总结
点乘作用:
- 表征或计算两个向量之间的夹角;
- b向量在a向量方向上的投影;
叉乘作用:
- 二维空间中,|a×b|在数值上等于由向量a和向量b构成的平行四边形的面积;
- 三维空间中,可以通过两个向量的叉乘,生成第三个垂直于a,b的法向量,从而构建X、Y、Z坐标系;
重点 - 上代码
import { Vec3 } from 'cc';
export class Vector3 {
public static add(pos1: Vec3, pos2: Vec3): Vec3 {
var outPos: Vec3 = new Vec3();
Vec3.add(outPos, pos1, pos2);
return outPos;
}
public static sub(pos1: Vec3, pos2: Vec3): Vec3 {
var outPos: Vec3 = new Vec3();
Vec3.subtract(outPos, pos1, pos2);
return outPos;
}
public static mul(pos: Vec3, scalar: number): Vec3 {
var outPos: Vec3 = new Vec3();
Vec3.multiplyScalar(outPos, pos, scalar);
return outPos;
}
public static div(pos: Vec3, scalar: number): Vec3 {
var outPos: Vec3 = new Vec3();
outPos.x = pos.x / scalar;
outPos.y = pos.y / scalar;
outPos.z = pos.z / scalar;
return outPos;
}
public static equals(pos1: Vec3, pos2: Vec3): boolean {
if (pos1.x == pos2.x && pos1.y == pos2.y && pos1.z == pos2.z) {
return true;
}
return false;
}
public static magnitude(pos: Vec3): number {
return pos.length();
}
public static normalize(pos: Vec3): Vec3 {
var outPos: Vec3 = new Vec3(pos.x, pos.y, pos.z);
return outPos.normalize();
}
public static direction(pos1: Vec3, pos2: Vec3): Vec3 {
var outPos: Vec3 = new Vec3();
Vec3.subtract(outPos, pos2, pos1);
return outPos.normalize();
}
public static distance(pos1: Vec3, pos2: Vec3): number {
return Vec3.distance(pos1, pos2);
}
public static dot(dir1: Vec3, dir2: Vec3): number {
var tempDir1: Vec3 = dir1;
var tempDir2: Vec3 = dir2;
return tempDir1.x * tempDir2.x + tempDir1.y * tempDir2.y + tempDir1.z * tempDir2.z;
}
public static cross(dir1: Vec3, dir2: Vec3): Vec3 {
var i: Vec3 = new Vec3(1, 0, 0);
var j: Vec3 = new Vec3(0, 1, 0);
var k: Vec3 = new Vec3(0, 0, 1);
var tempDir1: Vec3 = new Vec3(dir1.x, dir1.y, dir1.z);
var tempDir2: Vec3 = new Vec3(dir2.x, dir2.y, dir2.z);
var iv: Vec3 = i.multiplyScalar(tempDir1.y * tempDir2.z - tempDir2.y * tempDir1.z);
var jv: Vec3 = j.multiplyScalar(tempDir2.x * tempDir1.z - tempDir1.x * tempDir2.z);
var kv: Vec3 = k.multiplyScalar(tempDir1.x * tempDir2.y - tempDir2.x * tempDir1.y);
return iv.add(jv).add(kv);
}
public static angle(dir1: Vec3, dir2: Vec3): number {
var dotValue = this.dot(dir1.clone().normalize(), dir2.clone().normalize());
return (Math.acos(dotValue) / Math.PI) * 180 * Math.sign(dotValue);
}
public static dirAngle(a: Vec3, b: Vec3): number {
var c: Vec3 = Vector3.cross(a, b);
var angle: number = Vector3.angle(a, b);
var sign = Math.sign(Vector3.dot(c.normalize(), Vector3.cross(b.normalize(), a.normalize())));
return angle * sign;
}
}
Reference
- http://blog.csdn.net/dcrmg/article/details/52416832
- http://blog.csdn.net/baimafujinji/article/details/50237081
- http://blog.csdn.net/hunter_wwq/article/details/41248537
|