【数学】向量点乘、叉乘的理论、应用及代码实现(C++)

您所在的位置:网站首页 叉乘的ijk 【数学】向量点乘、叉乘的理论、应用及代码实现(C++)

【数学】向量点乘、叉乘的理论、应用及代码实现(C++)

2024-06-27 23:54| 来源: 网络整理| 查看: 265

前言

我总结了一下向量点乘,叉乘的概念,以及他们的应用及相关C++代码的实现。blog 这类问题也是技术面试经常碰到的,一次研究透了会有收获。

1 向量

向量具有大小和方向。 共线向量:两个平行的向量为共线向量。

1.1 叉积 Cross Product

\[\vec{a}\times\vec{b}=|\vec{a}||\vec{b}|\sin{\theta}\vec{n} \]

\(\theta\)是两个向量之间的角度,\(\vec{n}\)是与两个向量都垂直的单位向量,方向遵循右手定则(右手食指从\(\vec{a}\)划到\(\vec{b}\),大拇指的方向)。

两个向量的叉积结果是一个与两者都垂直的向量。叉积的幅度值大小等于由这两个向量为边组成的平行四边形的面积。当两个向量垂直时,大小也达到最大,及矩形的面积。(这个特性决定了他可以用来计算空间中一个点到一个直线的距离,利用几何中平行四边形的面积同时等于底乘高,后面会介绍。)

三维空间中,叉积的结果也可以用3x3矩阵的行列式表示。

\[\vec{a}\times \vec{b}=\det(\vec{i},\vec{j},\vec{k};a_1,a_2,a_3;b_1,b_2,b_3)\\ =(a_2b_3 - a_3,b_2)\vec{i}+(a_3b_1 - a_1,b_3)\vec{j}+(a_1b_2 - a_2,b_1)\vec{k}\]

1.2 点积 Dot Product

叉积给出一个向量结果,但点积给出一个标量结果。 它将向量的相同方向投影的的长度相乘,因此使用\(\cos{\theta}\)将其中一个向量投影到另一个上。所以如果两个向量成直角,那么结果为零。点积更容易理解一些。

\[\vec{a}\cdot \vec{b} = |\vec{a}||\vec{b}|\cos{\theta} \]

2 实际应用

判断两个向量是否:

共线:\(\vec{A}\)=k*\(\vec{B}\),其中k是一个标量;叉积是零向量(仅适用于三维空间);对应坐标的比率相等。 垂直:点积为零。

计算点P在线段AB上的投影点C坐标。

向量\(\vec{AB}\),\(\vec{AP}\),点积结果为D。\(\vec{AB} \cdot \vec{AP}=D\) 推导一下:\(\vec{AB} \cdot \vec{AP}=|\vec{AB}| |\vec{AP}| \cos{\theta}=|\vec{AC}| |\vec{AB}| = D\) -> \(D/|\vec{AB}| = |\vec{AC}|\) 求比率:\(k = |\vec{AC}|/|\vec{AB}| = D/{|\vec{AB}|^2}\) 最终坐标根据\(A\)和\(k\)可以求得:\(C = A + k\vec{AB}\)

如何验证C是投影点:

验证其共线性:\(\vec{AC} = k \vec{AB}\)或\(\vec{AC} \times \vec{AB}=\vec{0}\) 验证垂直:\(\vec{PC}\cdot \vec{AB} = 0\)

如何计算点P到线AB的距离d

叉积的范数是由两个向量张成的平行四边形的面积\((\vec{AB} \times \vec{AP})\) 基于几何原理,这个面积也等于距离(高)乘以边长 \(d * |\vec{AB}|\) 所以\(d = |\vec{AB} \times \vec{AP}|/|\vec{AB}|\) 3 代码实现

第一个版本代码,不用额外的库,手搓一些Utility函数,透彻了解原理:

#include #include using namespace std; struct Point { double x, y, z; // Overloading the multiplication operator Point operator*(double k) const { return {k*x, k*y, k*z}; } Point operator+(Point A) const { return {A.x + x, A.y + y, A.z + z}; } bool operator==(Point A) const { if (A.x == x and A.y == y and A.z == z) { return true; } else { return false; } } }; double dotProduct(Point A, Point B) { return A.x * B.x + A.y * B.y + A.z * B.z; } Point crossProduct(Point A, Point B) { return {A.y * B.z - A.z * B.y, A.x * B.z - A.z * B.x, A.x * B.y - A.y * B.x}; } float calcNorm(Point A) { return sqrt(A.x * A.x + A.y * A.y + A.z * A.z); } Point calcProjection(Point A, Point B, Point P) { Point AB = {B.x - A.x, B.y - A.y, B.z - A.z}; Point AP = {P.x - A.x, P.y - A.y, P.z - A.z}; double dot_product = dotProduct(AB, AP); double k = dot_product / dotProduct(AB, AB); Point C = A + (AB * k); return C; } bool verifyProjection(Point A, Point B, Point P, Point C) { Point AC = {C.x - A.x, C.y - A.y, C.z - A.z}; Point AB = {B.x - A.x, B.y - A.y, B.z - A.z}; Point PC = {C.x - P.x, C.y - P.y, C.z - P.z}; double dot_product = dotProduct(PC, AB); Point cross_product = crossProduct(AC, AB); Point zero_vec = {0, 0, 0}; if (dot_product == 0 and cross_product == zero_vec) { return true; } else { return false; } } float calcDistance(Point A, Point B, Point P) { Point AB = {B.x - A.x, B.y - A.y, B.z - A.z}; Point AP = {P.x - A.x, P.y - A.y, P.z - A.z}; Point cross_product = crossProduct(AB, AP); float area_parallelogram = calcNorm(cross_product); return (area_parallelogram / calcNorm(AB)); } int main() { // Line segment AB Point A = {0, 0, 0}; Point B = {4, 0, 0}; // Point P Point P = {5, 8, 0}; // Project P to AB and get point C Point C = calcProjection(A, B, P); cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3