计算2D向量的叉积


85

从维基百科:

叉积是在三维欧几里得空间中对两个向量的二进制运算,其结果是另一个向量垂直于包含两个输入向量的平面。

假设定义仅以三个(或七个,一和零)维定义,那么一个如何计算两个2d向量的叉积?

我已经看到了两种实现。一个返回一个新向量(但仅接受单个向量),另一个返回标量(但是两个向量之间的计算)。

实现1(返回一个标量):

float CrossProduct(const Vector2D & v1, const Vector2D & v2) const
{
    return (v1.X*v2.Y) - (v1.Y*v2.X);
}

实现2(返回向量):

Vector2D CrossProduct(const Vector2D & v) const
{
    return Vector2D(v.Y, -v.X);
}

为什么要采用不同的实现方式?我将把标量实现用于什么?矢量实现将用于什么?

我问的原因是因为我自己在编写Vector2D类,却不知道使用哪种方法。


10
实现2是错误的。您需要两个向量才能形成叉积。
bobobobo

7
实现2将给定向量v旋转-90度。将-90替换为x' = x cos θ - y sin θy' = x sin θ + y cos θ。此实现的另一个变体return Vector2D(-v.Y, v.X);是将v旋转+90度。
legends2k

3
@ legends2k:值得注意的是,实现2是使用行列式评估叉积的扩展:只需删除最后一行和最后一列即可。这样的扩展名总是具有尺寸的N-1操作N数。
TimČas2015年

4
实施方案1计算叉积的大小
Mateen Ulhaq '16

@MateenUlhaq之类的,这是“签名幅度”
Moritz Mahringer

Answers:


100

实现1返回由输入向量的规则3D叉积产生的向量的大小,将其Z值隐式设为0(即,将2D空间视为3D空间中的平面)。3D叉积将垂直于该平面,因此具有0个X&Y分量(因此返回的标量是3D叉积矢量的Z值)。

请注意,由3D叉积产生的矢量的大小也等于两个矢量之间的平行四边形的面积,这为实现1提供了另一个目的。此外,该区域是带符号的,可用于确定从V1到V2的旋转是沿逆时针方向还是顺时针方向移动。还应注意,实现1是从这两个向量构建的2x2矩阵的行列式。

实现2返回一个垂直于输入矢量的矢量,该矢量仍在同一2D平面中。不是经典意义上的叉积,而是“给我一个垂直向量”意义上的叉积。

请注意,在叉积运算下3D欧式空间是封闭的-也就是说,两个3D向量的叉积将返回另一个3D向量。以上两种2D实施都以一种或另一种方式与之不一致。

希望这可以帮助...


6
实际上,实现2是v与指向z方向的单位矢量的叉积。
最晚

@mattiast:是的。这就是3D中2D“ perp”操作的描述方式。
德鲁厅

@mattiast:实施2可以看作是使用行列式计算叉积的扩展-只需删除最后一行。应该注意的是,实现1等效于:DotProduct(a, CrossProduct(b)),(非常优雅!)与“垂直点积”的概念一致(实现1也(可能更准确地)被称为!)。
TimČas15年

在您的第一段中,幅度是返回值的绝对值。它与Z组件不太一样。正如您在第二段中指出的那样,您可以使用十字符号来击退吸血鬼...嗯,例如,我的意思是检测矢量何时离开与进入多边形的轮廓。
彼得·科德斯

68

简而言之:这是数学技巧的简写。

详细说明:

您无法在2D空间中对向量进行叉积运算。该操作未在此处定义。

但是,假设将2D向量的z坐标设置为0来将2D向量扩展到3D,则评估两个向量的叉积通常很有趣。这与在xy平面上处理3D向量相同。

如果以这种方式扩展向量并计算此类扩展向量对的叉积,您会注意到只有z分量具有有意义的值:x和y始终为零。

这就是为什么结果的z分量经常简单地以标量形式返回的原因。例如,此标量可用于查找2D空间中三个点的绕组。

从纯粹的数学观点来看,二维空间中的叉积不存在,标量版本是hack,返回二维矢量的2D叉积根本没有意义。


“例如,用于查找2D空间中三个点的绕线” @Nils Pipenbrinck,在这种情况下绕线是什么意思?
Nader Belal

1
@NaderBelal我想在这里绕线意味着-如果我们从点a到b到c,就我们刚刚跨越的角度而言,我们将是顺时针还是逆时针旋转。
阿米特·托玛

12

叉积的另一个有用特性是,其乘积与两个向量之间的角度的正弦有关:

| axb | = | a | 。| b | 。正弦(θ)

要么

正弦(theta)= | axb | /(|||。| b |)

因此,在上面的实现1中,如果ab预先已知是单位矢量,则该函数的结果恰好是sine()值。


1
...也是向量a和向量b之间的三角形面积的两倍。
蒂姆·洛弗尔·史密斯

5

实现1是两个向量的perp点积。我所知道的有关2D图形的最佳参考是出色的Graphics Gems系列。如果您要进行草稿的2D工作,那么拥有这些书非常重要。第IV卷上有一篇名为“ Perp Dot产品的乐趣”的文章,涉及了很多用途。

perp点积的主要用途是获取sin两个向量之间的角度比例,就像点积返回cos角度的比例一样。当然,您可以同时使用点积perp点积来确定两个向量之间的角度。

这里是上一个帖子,并在这里是钨数学世界的文章。


3

我在计算中使用了2D叉积,以找到相对于其质心在任意点处受力矢量作用的对象的新正确旋转。(标量Z一个。)


3

有用的2D矢量运算是返回标量的叉积。我用它来查看多边形中两个连续的边是否向左或向右弯曲。

Chipmunk2D来源:

/// 2D vector cross product analog.
/// The cross product of 2D vectors results in a 3D vector with only a z component.
/// This function returns the magnitude of the z value.
static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
{
        return v1.x*v2.y - v1.y*v2.x;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.