计算二维向量叉积
Posted
技术标签:
【中文标题】计算二维向量叉积【英文标题】:Calculating a 2D Vector's Cross Product 【发布时间】:2010-09-19 15:02:07 【问题描述】:来自***:
叉积是三维欧几里得空间中两个向量的二元运算,产生另一个向量,该向量垂直于包含两个输入向量的平面。
鉴于定义仅定义在三个 (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类,不知道用什么方法。
【问题讨论】:
实施 2 是错误的。您需要两个向量来形成叉积。 实现 2 将给定的向量 v 旋转 -90 度。在x' = x cos θ - y sin θ
和y' = x sin θ + y cos θ
中替换-90。此实现的另一种变体是 return Vector2D(-v.Y, v.X);
,它会将 v 旋转 +90 度。
@legends2k:值得注意的是,实现 2 是 using the determinant to evaluate the cross product 的扩展:只需删除最后一行和最后一列。这样的扩展总是有N-1
操作数N
维度。
实现 1 计算叉积的幅度。
@MateenUlhaq 之类的,它是“signed 幅度”
【参考方案1】:
实现 1 返回将由输入向量的常规 3D 叉积产生的向量的大小,将其 Z 值隐式设为 0(即将 2D 空间视为 3D 空间中的平面)。 3D 叉积将垂直于该平面,因此具有 0 个 X 和 Y 分量(因此返回的标量是 3D 叉积向量的 Z 值)。
请注意,由 3D 叉积产生的向量的大小也等于两个向量之间的平行四边形的面积,这为实现 1 提供了另一个目的。另外,这个区域是有符号的,可以用来判断从V1旋转到V2是逆时针方向还是顺时针方向。还应注意,实现 1 是由这两个向量构建的 2x2 矩阵的行列式。
实现 2 返回一个垂直于输入向量的向量,仍然在同一个 2D 平面中。不是经典意义上的叉积,而是“给我一个垂直向量”意义上的一致。
请注意,3D 欧几里得空间在叉积运算下是封闭的——也就是说,两个 3D 向量的叉积返回另一个 3D 向量。上述两种 2D 实现方式都与此不一致。
希望这会有所帮助...
【讨论】:
其实实现2是v和指向z方向的单位向量的叉积。 @mattiast:是的。这正是在 3D 中描述 2D 'perp' 操作的方式。 @mattiast:实现 2 可以被认为是使用 determinant to compute the cross product 的扩展 --- 只需删除最后一行和列。应该注意的是,实现 1 等同于:DotProduct(a, CrossProduct(b))
,它(非常优雅!)与“垂直点积”的概念一致(这也是实现 1 也 [也许更准确地] 称为!)。
在第一段中,幅度是返回值的绝对值。它与 Z 组件不太一样。正如您在第 2 段中指出的那样,您可以使用十字符号来击退吸血鬼……呃,我的意思是检测向量何时离开与进入多边形的轮廓。【参考方案2】:
简而言之:这是数学技巧的简写。
详细解释:
您不能在 2D 空间中对向量进行叉积。那里没有定义操作。
但是,假设 2D 向量通过将其 z 坐标设置为零来扩展为 3D,则评估两个向量的叉积通常很有趣。这与在 xy 平面上使用 3D 矢量相同。
如果您以这种方式扩展向量并计算这种扩展向量对的叉积,您会注意到只有 z 分量具有有意义的值:x 和 y 将始终为零。
这就是为什么结果的 z 分量通常简单地返回为标量的原因。例如,此标量可用于查找 2D 空间中三个点的缠绕。
从纯数学的角度来看,2D 空间中的叉积不存在,标量版本是 hack,返回 2D 向量的 2D 叉积根本没有意义。
【讨论】:
“例如用于在 2D 空间中查找三个点的缠绕”@Nils Pipenbrinck,在这种情况下缠绕是什么意思? @NaderBelal 我想这里的缠绕意味着 - 如果我们从点 a 到 b 再到 c,就我们刚刚跨越的角度而言,我们是顺时针还是逆时针。【参考方案3】:叉积的另一个有用属性是它的大小与两个向量之间夹角的正弦有关:
|一个 x b | = |一个| . |b| .正弦(θ)
或
正弦(θ) = |一个 x b | / (|a| . |b|)
因此,在上面的实现 1 中,如果预先知道 a
和 b
是单位向量,那么该函数的结果就是那个 sine() 值。
【讨论】:
...也是向量 a 和向量 b 之间三角形面积的两倍。【参考方案4】:实现 1 是两个向量的 perp 点积。我所知道的关于 2D 图形的最佳参考是出色的 Graphics Gems 系列。如果您正在从事 2D 临时工作,那么拥有这些书籍真的很重要。第 IV 卷有一篇名为“Perp Dot 产品的乐趣”的文章,其中介绍了它的很多用途。
perp 点积的一个主要用途是得到两个向量之间角度的缩放sin
,就像点积返回缩放的@987654325 @ 的角度。当然,您可以同时使用 点积 和 perp 点积 来确定两个向量之间的角度。
Here 是上面的帖子,here 是 Wolfram Math World 的文章。
【讨论】:
【参考方案5】:一个有用的二维向量运算是返回一个标量的叉积。我用它来查看多边形中的两个连续边是向左还是向右弯曲。
来自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;
【讨论】:
【参考方案6】:我在计算中使用 2d 叉积来为一个物体找到新的正确旋转,该物体在相对于其质心的任意点处受到力矢量的作用。 (标量 Z 一。)
【讨论】:
以上是关于计算二维向量叉积的主要内容,如果未能解决你的问题,请参考以下文章