Как этот код может получить двумерный вектор из перекрестного произведения двух двумерных векторов?

Я в растерянности. Я пытался реализовать этот код по адресу: http://www.blackpawn.com/texts/pointinpoly/default.html

Однако я не знаю, как это возможно, что перекрестное произведение, присутствующее между двумя 2D-векторами, может также привести к 2D-вектору. Для меня это не имеет смысла. Это также присутствует в некоторых примерах пересечения полигонов и линий в прекрасной книге «Обнаружение столкновений в реальном времени», где даже скалярные тройки между 2D-векторами появляются в кодах (см., Например, стр. 189).

Проблема в том, что, насколько я понимаю, псевдокросс-произведение двух 2D-векторов может привести только к скаляру (v1.x v2.y-v1.y v2.x ) или самое большее в трехмерном векторе, если добавить два нуля, поскольку этот скаляр представляет размерность Z. Но как это может привести к двумерному вектору?

Я не первый, кто спрашивает об этом, и по совпадению, пытаясь использовать тот же пример кода: Перекрестное произведение двух 2D-векторов Однако, как легко увидеть, ответ, исходный вопрос после обновления и комментарии в этой цепочке закончились полным беспорядком, если я осмелюсь так сказать.

Кто-нибудь знает, как мне получить эти 2D-векторы из перекрестного произведения двух 2D-векторов? Если нужно предоставить код, я могу обрабатывать C #, JavaScript и немного C ++.

ИЗМЕНИТЬ - вот фрагмент кода в книге, как я упоминал выше:

int IntersectLineQuad(Point p, Point q, Point a, Point b, Point c, Point d,     Point &r)
{
Vector pq = q - p;
Vector pa = a - p;
Vector pb = b - p;
Vector pc = c - p;
// Determine which triangle to test against by testing against diagonal     first
Vector m = Cross(pc, pq);
float v = Dot(pa, m); // ScalarTriple(pq, pa, pc);
if (v >= 0.0f) {
   // Test intersection against triangle abc
   float u = -Dot(pb, m); // ScalarTriple(pq, pc, pb);
   if (u < 0.0f) return 0;
   float w = ScalarTriple(pq, pb, pa);
....

person MAnd    schedule 30.09.2015    source источник
comment
Вы ведь говорите о технике одной стороны? Перекрестное произведение 2 трехмерных векторов в плоскости XY - это вектор, параллельный оси Z. Cross2d из 2 2d-векторов является Z-компонентой 3d-креста, поэтому скалярное произведение, упомянутое там, может быть получено простым умножением значений двух 2d-векторов (т. Е. Расстановка точек 3d-крестов, которые параллельны оси Z и, следовательно, друг с другом).   -  person dbc    schedule 30.09.2015
comment
Спасибо за ваш комментарий. Так что да, я имел в виду именно эту технику. Вы говорите, что точечное произведение было бы просто умножением двух скаляров, полученных путем перекрестного произведения двух двумерных векторов? Но взгляните на пример из книги, которую я только что включил в исходный вопрос. В этом примере я должен просто умножить весь 2D-вектор pa на скаляр, полученный в результате перекрестного произведения pc и pq?   -  person MAnd    schedule 30.09.2015
comment
@dbc Обратите внимание, что в приведенном примере автор хранит произведение двухмерных векторов pc и pq в векторе с именем m. Если я перейду прямо к вашему предложению и просто сделаю обычный расчет для перекрестного произведения между двумя 2D-векторами, сохраню его в m (объявив его как float), а затем напрямую умножу m и вектор pa, тогда v не может быть float как в примере   -  person MAnd    schedule 30.09.2015
comment
Я написал свой комментарий, используя ваш исходный вопрос, в котором не было образца кода, на основе связанного алгоритма. Образец кода в обновлении, похоже, не соответствует этому алгоритму - это совсем другое. Похоже, он работает с 3D-векторами, а не с 2d.   -  person dbc    schedule 30.09.2015


Ответы (1)


Кажется, что для страницы, на которую вы указали ссылку, речь идет о треугольнике в трехмерном пространстве:

Поскольку треугольник можно как угодно сориентировать в трехмерном пространстве, ...

Следовательно, все векторы, о которых они говорят, являются трехмерными векторами, и весь текст и код имеют смысл. Обратите внимание, что даже для 2-мерных векторов все также имеет смысл, если вы рассматриваете перекрестное произведение как вектор 3d, указывающий за пределы экрана. И они тоже упоминают об этом на странице:

Если вы возьмете перекрестное произведение [B-A] и [p-A], вы получите вектор, указывающий за пределы экрана.

Их код тоже правильный, как для 2-го, так и для 3-го случая:

function SameSide(p1,p2, a,b)
    cp1 = CrossProduct(b-a, p1-a)
    cp2 = CrossProduct(b-a, p2-a)
    if DotProduct(cp1, cp2) >= 0 then return true
    else return false

Для 2d и cp1, и cp2 являются векторами, указывающими за пределы экрана, а скалярное произведение (3d) - это именно то, что вам нужно проверить; проверка только произведения соответствующих Z компонентов такая же. Если все 3д, это тоже правильно. (Хотя я бы написал просто return DotProduct(cp1, cp2) >= 0.)

Что касается int IntersectLineQuad(), я могу предположить, что ситуация такая же: Quad, каким бы он ни был, является трехмерным объектом, а также Vector и Point в коде. Однако, если вы добавите более подробную информацию о том, что эта функция должна делать, это поможет.

Фактически, очевидно, что любая проблема, указанная в 2d, может быть расширена до 3d, и поэтому любой подход, действующий в 3d, также будет действителен и для 2d случая, вам просто нужно представить третью ось, указывающую за пределы экрана. Так что я думаю, что это действенный (хотя и сбивающий с толку) метод для полного описания двумерной проблемы в трехмерных терминах. Возможно, вы сами проделаете некоторую дополнительную работу, потому что при таком подходе некоторые значения всегда будут равны нулю, но, в свою очередь, (почти) тот же код будет работать и в общем случае 3D.

person Petr    schedule 30.09.2015
comment
Спасибо за подробное разъяснение! Это как раз та часть, которая меня смутила: если вы возьмете перекрестное произведение [B-A] и [p-A], вы получите вектор, указывающий за пределы экрана. Это могло иметь смысл только для 2D-среды, но не для 3D. Но в любом случае, я думаю, вы сделали очень хорошее замечание, это очевидно, но я не полностью осознавал это раньше. Независимо от того, относится ли пример кода к пересечению отрезка 3D линии / четырехугольника, я могу просто использовать тот же код в качестве начала, но поставить нули на оси Z, а затем вызвать некоторую оптимизацию (то есть отбросить ненужные вещи для 2D кейс) - person MAnd; 30.09.2015