计算2D矢量叉积

时间:2008-10-28 16:22:28

标签: language-agnostic math vector 2d

来自维基百科:

  

十字积是对三维欧氏空间中两个向量的二元运算,导致另一个向量垂直于包含两个输入向量的平面。

鉴于该定义仅在三个(or seven, one and zero)维度中定义,如何计算两个二维向量的叉积?

我见过两个实现。一个返回一个新的向量(但只接受一个向量),另一个返回一个标量(但是是两个向量之间的计算)。

实现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类,并且不知道使用哪种方法。

6 个答案:

答案 0 :(得分:95)

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

请注意,3D交叉积导致的矢量幅度也等于两个矢量之间的平行四边形的面积,这为实现1提供了另一个目的。此外,该区域已签名,可用于确定从V1到V2的旋转是以逆时针还是顺时针方向移动。还应注意,实现1是从这两个向量构建的2x2矩阵的决定因素。

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

请注意,3D十字形空间在十字产品操作下关闭 - 也就是说,两个3D矢量的叉积返回另一个3D矢量。上述两种2D实现都与这种或那种方式不一致。

希望这会有所帮助......

答案 1 :(得分:52)

简而言之:这是数学黑客的简写符号。

长解释:

您无法在2D空间中使用矢量进行交叉积分。那里没有定义操作。

然而,通常有意义的是评估两个矢量的叉积,假设通过将它们的z坐标设置为零来将2D矢量扩展到3D。这与在xy平面上使用3D矢量相同。

如果你以这种方式扩展向量并计算这种扩展向量对的叉积,你会注意到只有z分量有一个有意义的值:x和y总是为零。

这就是为什么结果的z分量通常只是作为标量返回的原因。例如,该标量可用于在2D空间中找到三个点的绕组。

从纯粹的数学观点来看,2D空间中的交叉产品不存在,标量版本是黑客,而返回2D矢量的2D交叉产品完全没有任何意义。

答案 2 :(得分:12)

交叉积的另一个有用特性是它的大小与两个向量之间角度的正弦值有关:

  

| a x b | = | a | 。 | B | 。正弦(THETA)

  

正弦(theta)= | a x b | /(| a |。| b |)

因此,在上面的实现1中,如果事先知道ab是单位向量,那么该函数的结果就是sine()值。

答案 3 :(得分:4)

实现1是两个向量的 perp点积。我所知道的2D图形的最佳参考是优秀的Graphics Gems系列。如果您正在进行2D临时工作,那么拥有这些书籍非常重要非常。第四卷有一篇名为" Perp Dot Products的乐趣"这经历了很多用途。

perp点积的一个主要用途是获得两个向量之间角度的缩放sin,就像点积返回缩放的那样cos的角度。当然,你可以一起使用点积 perp点积来确定两个向量之间的角度。

Here上有帖子,here是Wolfram Math World的文章。

答案 4 :(得分:3)

我在计算中使用二维交叉积来找到一个物体的新的正确旋转,该物体在相对于质心的任意点处被一个力矢量作用。 (标量Z一。)

答案 5 :(得分:1)

有用的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;
}