二维三重积构造垂直线
Triple product in 2d to construct perpendicular line
我一直在关注这个 tutorial 的碰撞检测,它使用二维三重乘积来构造垂直线。使用从 c0 到 c 的向量 A 1 和向量 B 从 c0 到起源。声称 A,B,A 的三重乘积垂直于 A 并且在原点方向。我不明白为什么会这样,或者叉积如何在 2D 中使用。
我看过 the implementation and I'd definitely not call that a triple product。通常的三重乘积使用叉积,然后是点积,而这里是连续的两个叉积,通过在二维向量上附加一个零来构建三维向量。那么会发生什么?
A × B = (Ax,Ay,0) × (Bx,By,0) = (0,0,Ax∙By−Ay∙Bx)
… × A = (Ax∙By−Ay∙Bx)∙(Ay,−Ax,0)
所以结果是 (Ay,−Ax) 的某个倍数。这确保这确实垂直于 A。如果 A 和 B 平行,则多个变化的符号完全相同。因此,对于不平行的 A 和 B,一个方向将给出一个方向,而另一个方向将给出另一个符号。如果你不想更深入地思考,用一个实验来决定哪个是哪个。
附带说明一下,我不会这样做的。相反,我会依赖于经典的方向谓词。但我还没有读完那篇文章,所以也许有理由不这样做。如果您想了解更多信息,请观察行列式
|Ax Bx Cx|
|Ay By Cy|
| 1 1 1|
(顺便说一下,如果用 1 而不是 0 增加,则等于三重乘积 (A×B)∙C)等于三角形 oriented 面积的两倍由 A、B、C 组成。因此该符号告诉您该三角形的方向。你可以使用这个,例如计算符号 OAB、OBC、OCA。如果他们都同意原点被包含。请注意行列式|OAB|之类的东西= Ax∙By−Ay∙Bx 非常 容易计算。
var oab = Math.sign(a.x*b.y - a.y*b.x);
var obc = Math.sign(b.x*c.y - b.y*c.x);
var oca = Math.sign(c.x*a.y - c.y*a.x);
if (Math.abs(oab + obc + oca) == 3) {
return "contains origin";
}
if (oab * obc * oca == 0) {
return "origin is on the boundary";
}
var abc = Math.sign(a.x*b.y + b.x*c.y + c.x*a.y -
a.x*c.y - b.x*a.y - c.x*b.y);
if (oab != abc) {
return "outside line ab";
} else if (obc != abc) {
return "outside line bc";
} else {
return "outside line ac";
}
我一直在关注这个 tutorial 的碰撞检测,它使用二维三重乘积来构造垂直线。使用从 c0 到 c 的向量 A 1 和向量 B 从 c0 到起源。声称 A,B,A 的三重乘积垂直于 A 并且在原点方向。我不明白为什么会这样,或者叉积如何在 2D 中使用。
我看过 the implementation and I'd definitely not call that a triple product。通常的三重乘积使用叉积,然后是点积,而这里是连续的两个叉积,通过在二维向量上附加一个零来构建三维向量。那么会发生什么?
A × B = (Ax,Ay,0) × (Bx,By,0) = (0,0,Ax∙By−Ay∙Bx)
… × A = (Ax∙By−Ay∙Bx)∙(Ay,−Ax,0)
所以结果是 (Ay,−Ax) 的某个倍数。这确保这确实垂直于 A。如果 A 和 B 平行,则多个变化的符号完全相同。因此,对于不平行的 A 和 B,一个方向将给出一个方向,而另一个方向将给出另一个符号。如果你不想更深入地思考,用一个实验来决定哪个是哪个。
附带说明一下,我不会这样做的。相反,我会依赖于经典的方向谓词。但我还没有读完那篇文章,所以也许有理由不这样做。如果您想了解更多信息,请观察行列式
|Ax Bx Cx|
|Ay By Cy|
| 1 1 1|
(顺便说一下,如果用 1 而不是 0 增加,则等于三重乘积 (A×B)∙C)等于三角形 oriented 面积的两倍由 A、B、C 组成。因此该符号告诉您该三角形的方向。你可以使用这个,例如计算符号 OAB、OBC、OCA。如果他们都同意原点被包含。请注意行列式|OAB|之类的东西= Ax∙By−Ay∙Bx 非常 容易计算。
var oab = Math.sign(a.x*b.y - a.y*b.x);
var obc = Math.sign(b.x*c.y - b.y*c.x);
var oca = Math.sign(c.x*a.y - c.y*a.x);
if (Math.abs(oab + obc + oca) == 3) {
return "contains origin";
}
if (oab * obc * oca == 0) {
return "origin is on the boundary";
}
var abc = Math.sign(a.x*b.y + b.x*c.y + c.x*a.y -
a.x*c.y - b.x*a.y - c.x*b.y);
if (oab != abc) {
return "outside line ab";
} else if (obc != abc) {
return "outside line bc";
} else {
return "outside line ac";
}