Skip to content

Latest commit

 

History

History
171 lines (101 loc) · 5.89 KB

vector_3d.md

File metadata and controls

171 lines (101 loc) · 5.89 KB

为了学好Rust也是拼了系列-数学库-三维维向量

三维向量是指具有三个有序数值组成的向量,通常表示为$$ \mathbf{v} = \begin{bmatrix} x \ y \ z \end{bmatrix} $$。其中,$$x$$、$$y$$和$$z$$分别表示该向量在三个坐标轴上的分量。

在数学中,我们可以使用线性代数的概念来定义三维向量。一个三维向量可以被看作是三个标量的有序组合,这些标量分别表示在三个坐标轴上的投影。具体地,给定一个三维向量 $$\mathbf{v} = \begin{bmatrix} x \ y \ z \end{bmatrix}$$,我们可以定义它为:

$$\mathbf{v} = x\mathbf{i} + y\mathbf{j} + z\mathbf{k}$$

其中,$$\mathbf{i}$$、$$\mathbf{j}$$和$$\mathbf{k}$$分别是三维空间中的标准基向量。它们的定义如下:

$$\mathbf{i} = \begin{bmatrix} 1 \ 0 \ 0 \end{bmatrix}, \quad \mathbf{j} = \begin{bmatrix} 0 \ 1 \ 0 \end{bmatrix}, \quad \mathbf{k} = \begin{bmatrix} 0 \ 0 \ 1 \end{bmatrix}$$

这样,三维向量 $$\mathbf{v}$$ 就可以通过在每个基向量上的投影(乘以相应的标量)来表示。这种表示方式有助于理解向量在三维空间中的方向和长度。

程序定义如下

#[derive(Debug)]
pub struct Vector3D {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

加减法

三维向量的加法和减法遵循分量相加和相减的原则。考虑两个三维向量:

$$\mathbf{v}_1 = \begin{bmatrix} x_1 \ y_1 \ z_1 \end{bmatrix}$$ 和 $$\mathbf{v}_2 = \begin{bmatrix} x_2 \ y_2 \ z_2 \end{bmatrix}$$

它们的加法定义为:

$$\mathbf{v}_1 + \mathbf{v}_2 = \begin{bmatrix} x_1 + x_2 \ y_1 + y_2 \ z_1 + z_2 \end{bmatrix}$$

这就是将两个向量的相应分量相加得到的新向量。同样,两个向量的减法定义为:

$$\mathbf{v}_1 - \mathbf{v}_2 = \begin{bmatrix} x_1 - x_2 \ y_1 - y_2 \ z_1 - z_2 \end{bmatrix}$$

这就是将两个向量的相应分量相减得到的新向量。

程序解如下

// 向量加法
pub fn add(&self, other: &Vector3D) -> Vector3D {
    Vector3D {
        x: self.x + other.x,
        y: self.y + other.y,
        z: self.z + other.z,
    }
}

// 向量减法
pub fn subtract(&self, other: &Vector3D) -> Vector3D {
    Vector3D {
        x: self.x - other.x,
        y: self.y - other.y,
        z: self.z - other.z,
    }
}

数乘

数量乘法是指将一个标量与一个向量的每个分量相乘的操作。给定一个标量 $$c$$ 和三维向量 $$\mathbf{v} = \begin{bmatrix} x \ y \ z \end{bmatrix}$$,数量乘法的定义如下:

$$ c \cdot \mathbf{v} = \begin{bmatrix} c \cdot x \ c \cdot y \ c \cdot z \end{bmatrix} $$

在这个操作中,标量 $$c$$ 与向量 $$\mathbf{v}$$ 的每个分量相乘,产生一个新的向量。这个新向量的每个分量都是原向量相应分量与标量的乘积。

数量乘法的几何解释是对向量进行缩放或拉伸。如果 $$c > 1$$,那么结果向量的长度会增加;如果 $$0 < c < 1$$,那么结果向量的长度会减小;如果 $$c < 0$$,那么结果向量方向会反转,并且长度的绝对值会增加。当 $$c = 1$$ 时,向量保持不变;当 $$c = 0$$ 时,结果向量的所有分量都为零向量。

例如,如果有向量 $$\mathbf{v} = \begin{bmatrix} 2 \ 3 \ -1 \end{bmatrix}$$ 和标量 $$c = 3$$,则数量乘法的结果为:

$$ 3 \cdot \mathbf{v} = \begin{bmatrix} 3 \cdot 2 \ 3 \cdot 3 \ 3 \cdot (-1) \end{bmatrix} = \begin{bmatrix} 6 \ 9 \ -3 \end{bmatrix} $$

这表示将向量 $$\mathbf{v}$$ 中的每个分量都乘以标量 $$3$$,得到一个新的向量。

程序解如下

// 数量乘法
pub fn scalar_multiply(&self, scalar: f64) -> Vector3D {
    Vector3D {
        x: self.x * scalar,
        y: self.y * scalar,
        z: self.z * scalar,
    }
}

叉积

向量乘法中的叉积(cross product)是两个向量之间的一种特殊的乘法运算。给定两个三维向量 $$\mathbf{v}_1 = \begin{bmatrix} x_1 \ y_1 \ z_1 \end{bmatrix}$$ 和 $$\mathbf{v}_2 = \begin{bmatrix} x_2 \ y_2 \ z_2 \end{bmatrix}$$,它们的叉积 $$\mathbf{v}_1 \times \mathbf{v}_2$$ 定义如下:

$$\mathbf{v}_1 \times \mathbf{v}_2 = \begin{bmatrix} y_1z_2 - z_1y_2 \ z_1x_2 - x_1z_2 \ x_1y_2 - y_1x_2 \end{bmatrix}$$

程序解如下

// 计算叉积
pub fn cross_product(&self, other: &Vector3D) -> Vector3D {
    Vector3D {
        x: self.y * other.z - self.z * other.y,
        y: self.z * other.x - self.x * other.z,
        z: self.x * other.y - self.y * other.x,
    }
}

模长(长度)

模长,也称为长度、幅值或矢量的大小,是指一个向量在空间中的长度。对于三维向量 $$\mathbf{v} = \begin{bmatrix} x \ y \ z \end{bmatrix}$$,它的模长计算公式为:

$$ |\mathbf{v}| = \sqrt{x^2 + y^2 + z^2} $$

这个公式来源于三维空间中的勾股定理。模长表示从原点到向量终点的距离,或者说向量的大小。

程序解如下

// 计算模长
pub fn magnitude(&self) -> f64 {
    (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
}

夹角

计算两个三维向量之间的夹角通常可以使用向量的点积(内积)和反余弦函数。假设有两个向量 $$\mathbf{v}_1$$$$\mathbf{v}_2$$,它们的夹角为 $$\theta$$,则夹角的计算公式为:

$$ \cos(\theta) = \frac{\mathbf{v}_1 \cdot \mathbf{v}_2}{|\mathbf{v}_1| \cdot |\mathbf{v}_2|} $$

其中,$$\cdot$$ 表示点积,$$ |\mathbf{v}| $$ 表示向量的模长。夹角 $$\theta$$ 可以通过反余弦函数求得:

$$ \theta = \cos^{-1}\left(\frac{\mathbf{v}_1 \cdot \mathbf{v}_2}{|\mathbf{v}_1| \cdot |\mathbf{v}_2|}\right) $$

程序解如下

// 计算两个向量之间的夹角(弧度)
pub fn angle_between(&self, other: &Vector3D) -> f64 {
    let dot_product = self.dot_product(other);
    let magnitude_product = self.magnitude() * other.magnitude();

    dot_product.acos() / magnitude_product
}