I have been following this tutorial for collision-detection in which it uses a 2d triple product to construct a perpendicular line. Using vector A that goes from c0 to c1 and vector B that goes from c0 to the origin. The claim is that the triple product of A,B,A is perpendicular to A and in the direction of the origin. I do not understand why this works or how the cross product is being used in 2D.
I had a look at the implementation and I'd definitely not call that a triple product. The usual triple product uses a cross product and then a dot product, whereas this here is two cross products in a row, with 3d vectors constructed by appending a zero to the 2d vectors. So what happens?
A × B = (Ax,Ay,0) × (Bx,By,0) = (0,0,Ax∙By−Ay∙Bx)
… × A = (Ax∙By−Ay∙Bx)∙(Ay,−Ax,0)
So the result is some multiple of (Ay,−Ax). Which ensures that this is indeed perpendicular to A. And that multiple changes sign exactly if A and B are parallel. So for A and B not parallel, one orientation will give one direction and the other orientation will give the other sign. Use an experiment to decide which is which if you don't want to think more deeply.
As a side note, I wouldn't have done things this way. I would instead have relied on a classical orientation predicate. But I haven't read all that article, so perhaps there is a reason not to do this. In case you want to know more, observe that the determinant
|Ax Bx Cx|
|Ay By Cy|
| 1 1 1|
(which by the way is equal to the triple product (A×B)∙C if you augment with 1 instead of 0) equals twice the oriented area of the triangle formed by A, B, C. So the sign tells you about the orientation of said triangle. You can use this e.g. to compute the signs OAB,OBC,OCA. If they all agree the origin is contained. Note that things like the determinant |OAB| = Ax∙By−Ay∙Bx are very easy to compute.
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";
}