1 三维向量点乘

1.1 三维向量点乘的概念

两个三维向量的点乘又称为点积、数量积或者标量积(Scalar Product)。

假设三维空间中有两个三维向量:\vec{a}=(x_1,y_1,z_1)\vec{b}=(x_2,y_2,z_2)\vec{a}\vec{b}之间的夹角为\theta

数学角度上,两个三维向量的点积是两个向量对应位置的值相乘然后相加,如下

\vec{a}\cdot\vec{b}=x_1x_2+y_1y_2+z_1z_2

几何角度上,两个三维向量的点积是两个向量的长度与它们夹角余弦的积,如下

\vec{a}\cdot\vec{b}=|\vec{a}|\begin{vmatrix}\vec{b}\end{vmatrix}\cos\theta

1.2 三维向量点乘的几何意义

三维向量的点积表示向量\vec{a}在向量\vec{b}方向上的投影与\left|\vec{b}\right|的乘积,反应两个向量在方向上的相似度,结果越大越相似。

通过三维向量点乘结果可以判断两个向量是否同向、垂直,比如

(1)\vec{a}\cdot\vec{b}>0,点乘结果大于0,则表示两个向量方向基本相同,两个向量的夹角在\text{0°}\text{90°}之间

(2)\vec{a}\cdot\vec{b}=0,点乘结果等于0,则表示两个向量正交,相互垂直

(3)\vec{a}\cdot\vec{b}<0,点乘结果小于0,则表示两个向量方向基本相反,两个向量的夹角在\text{90°}\text{180°}之间

1.3 根据三维向量点乘求解两个向量之间的夹角

可以根据以下公式求解两个向量之间的夹角

\theta=\arccos(\frac{\vec{a}\cdot\vec{b}}{|\vec{a}|\left|\vec{b}\right|})

其推导过程如下。

假设\vec{a}的终点为A(x_1,y_1,z_1)\vec{b}的终点为B(x_2,y_2,z_2),原点为O

\overrightarrow{AB}=(x_2-x_1,y_2-y_1,z_2-z_1)

\triangle OAB中,由余弦定理

\left|\overrightarrow{AB}\right|^2=|\vec{a}|^2+\left|\vec{b}\right|^2-2\left|\vec{a}\right|\left|\vec{b}\right|\cos\theta

使用距离公式进行处理,可得:

|\vec{a}|\begin{vmatrix}\vec{b}\end{vmatrix}\cos\theta=\frac{x_1^2+y_1^2+z_1^2+x_2^2+y_2^2+z_2^2-[(x_2-x_1)^2+(y_2-y_1)^2+(z_2-z_1)^2]}{2}

去括号后合并

|\vec{a}|\begin{vmatrix}\vec{b}\end{vmatrix}\cos\theta=x_1x_2+y_1y_2+z_1z_2=\vec{a}\cdot\vec{b}

换位即可得上面求解夹角的公式。

1.4 使用C++计算两个三维向量的点乘

示例代码如下

#include <iostream>

struct Point3f
{
    float x;
    float y;
    float z;

    Point3f()
    {
        x = 0.0;
        y = 0.0;
        z = 0.0;
    }

    Point3f(float x_in, float y_in, float z_in)
    {
        x = x_in;
        y = y_in;
        z = z_in;
    }
};

typedef Point3f Vector3f;

// 计算两个三维向量的点积
float DotProduct(Vector3f u, Vector3f v)
{
    return u.x * v.x + u.y * v.y + u.z * v.z;
}

int main()
{
    Vector3f vector_a(1.0, 2.0, 3.0);
    Vector3f vector_b(4.0, 5.0, 6.0);

    float dot_product_res = DotProduct(vector_a, vector_b);
    std::cout << "向量点乘 = " << dot_product_res << std::endl;

    return 0;
}

2 三维向量叉乘

2.1 三维向量叉乘的概念

两个三维向量的叉乘又称为外积、向量积。

假设三维空间中有两个三维向量:\vec{a}=(x_1,y_1,z_1)\vec{b}=(x_2,y_2,z_2)\vec{a}\vec{b}之间的夹角为\theta

数学角度上,两个三维向量的叉乘计算如下

\vec{a}\times\vec{b}=(y_1z_2-z_1y_2,z_1x_2-x_1z_2,x_1y_2-y_1x_2)

几何角度上,两个三维向量的叉乘计算如下

\vec{a}\times\vec{b}=|\vec{a}|\begin{vmatrix}\vec{b}\end{vmatrix}\sin\theta\vec{n}

其中,\vec{n}为垂直于\vec{a}\vec{b}所在平面的单位向量。

两个三维向量叉乘的结果是一个三维向量,并且该向量垂直于\vec{a}\vec{b}所构成的平面,也就是与\vec{a}\vec{b}都垂直,是\vec{a}\vec{b}所在平面的法线向量,其方向通过右手法则进行判断,如下图所示

计算几何 –  三维向量的点乘、叉乘的概念、几何意义以及如何使用C++计算-StubbornHuang Blog

2.2 三维向量叉乘的几何意义

如果以向量\vec{a}与向量\vec{b}的边构成一个平行四边形,那么这两个向量外积的模长与这个平行四边形的面积相等。

计算几何 –  三维向量的点乘、叉乘的概念、几何意义以及如何使用C++计算-StubbornHuang Blog

2.3 使用C++计算两个三维向量的叉乘

示例代码如下

#include <iostream>

struct Point3f
{
    float x;
    float y;
    float z;

    Point3f()
    {
        x = 0.0;
        y = 0.0;
        z = 0.0;
    }

    Point3f(float x_in, float y_in, float z_in)
    {
        x = x_in;
        y = y_in;
        z = z_in;
    }
};

typedef Point3f Vector3f;

// 计算两个三维向量的叉积
Vector3f CrossProduct(Vector3f u, Vector3f v) {
    Vector3f retult;
    retult.x = u.y * v.z - v.y * u.z;
    retult.y = u.z * v.x - u.x * v.z;
    retult.z = u.x * v.y - u.y * v.x;
    return retult;
}

int main()
{
    Vector3f vector_a(1.0, 2.0, 3.0);
    Vector3f vector_b(4.0, 5.0, 6.0);

    Vector3f cross_product_res = CrossProduct(vector_a, vector_b);
    std::cout << "向量叉乘 = " << cross_product_res.x << "," << cross_product_res.y << "," << cross_product_res.z << std::endl;

    return 0;
}

参考链接