Я следовал этому учебнику для обнаружения столкновений, в котором он использует двумерное тройное произведение для построения перпендикулярной линии. Используя вектор A, который идет от c0 до c1, и вектор >B, который идет от c0 до начала координат. Утверждение состоит в том, что тройное произведение A,B,A перпендикулярно A и в направлении начала координат. Я не понимаю, почему это работает или как перекрестное произведение используется в 2D.
Тройной продукт в 2D для построения перпендикулярной линии
Ответы (1)
Я просмотрел реализацию и я бы определенно не назвал это тройным продуктом. Обычное тройное произведение использует перекрестное произведение, а затем скалярное произведение, тогда как здесь два перекрестных произведения подряд с трехмерными векторами, построенными путем добавления нуля к двумерным векторам. Так что же происходит?
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|
(которое, кстати, равно тройному произведению (A×B)∙C, если добавить 1 вместо 0) равно удвоенной ориентированной площади треугольника, образованного 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";
}