Перекрестное произведение двумерных векторов

У меня есть два координатных вектора:

coor1 = [4 2];
coor2 = [4.3589 1];

и я хочу найти угол поворота, где математически он определяется уравнением:

введите здесь описание изображения

где числитель — это перекрестное произведение двух пар координат, а знаменатель — скалярное произведение.

Проблема в том, что в MATLAB перекрестное произведение невозможно с двухэлементными векторами. Выполнение следующего кода:

ang = atan2(norm(cross(coor1,coor2)),dot(coor1,coor2));

выдает эту ошибку:

Error using cross
A and B must be of length 3 in the dimension in which the cross product is taken. 

Есть ли способ заставить cross работать? Проработав это вручную, угол поворота обеих координат должен быть 13.6441.


person Maxxx    schedule 11.09.2019    source источник
comment
А как насчет rad2deg(atan2(coor2(2)*coor1(1)-coor2(1)*coor1(2), dot(coor1,coor2)))?   -  person avermaet    schedule 11.09.2019
comment
@avermaet rad2deg(atan2(...)) не нужен, вместо этого можно просто использовать atan2d.   -  person Dev-iL    schedule 11.09.2019
comment
Любая причина, по которой вы не принимаете ответ?   -  person Dev-iL    schedule 11.09.2019
comment
@Dev-iL, мой плохой, совсем забыл об этом. Хотел бы я принять все ответы, поскольку все они действительны.   -  person Maxxx    schedule 12.09.2019


Ответы (5)


Почему бы вместо этого не использовать арккосинус (arccos)?

coor1 = [4 2];
coor2 = [4.3589 1];

% normalize the vectors:
d1 = coor1 ./ norm(coor1);
d2 = coor2 ./ norm(coor2);

ang = acosd(dot(d1,d2));
person Dev-iL    schedule 11.09.2019
comment
atan2 — четырехквадрантный угол, acos — двухквадрантный угол. Если знак угла не нужен, этот ответ проще. - person Cris Luengo; 11.09.2019

Преобразуйте векторы в комплексные числа и используйте угол:

x=coor1 * [1; 1i];
y=coor2 * [1; 1i];
ang = angle(x*y')

Другое векторизованное решение, которое может конвертировать несколько векторов:

atan2(coor1 * (coor2(:,[2,1]).*[1 -1]).',coor1 * coor2.')

*Благодаря @Dev-iL я изменил i на 1i.

person rahnema1    schedule 11.09.2019
comment
Хороший! Сложная арифметика упрощает многие вещи с 2D-векторами. - person Cris Luengo; 11.09.2019
comment
Лучше использовать 1i, чтобы избежать возможных проблем, связанных с переопределением i, обычно используемого в качестве индекса цикла. - person Dev-iL; 11.09.2019

Вы можете добавить ноль к векторам, чтобы сделать их трехмерными, а затем получить третий элемент из вектора нормали:

n = cross([coor1 0], [coor2 0]);
theta = atan2(n(3),dot(coor1,coor2));
person rinkert    schedule 11.09.2019
comment
Спасибо! Есть ли причина, по которой Matlab разрешает только 3D-вектор? - person Maxxx; 11.09.2019
comment
@Maxxx, почему бы не определить свою собственную функцию, которая вычисляет пересечение для 2d-векторов? Вы можете назвать это cross2d. - person Dev-iL; 11.09.2019
comment
@Maxxx: перекрестный продукт имеет уникальное определение только в 3D. Расширения на другие измерения неоднозначны. - person Cris Luengo; 11.09.2019
comment
Этот ответ хорош, если вычислительные затраты не имеют значения. Но это решение выполняет в 3 раза больше операций умножения и сложения, чем прямая реализация формулы для двумерного перекрестного произведения (stackoverflow.com/questions/57890014/). - person Cris Luengo; 11.09.2019
comment
@Dev-iL Я бы сказал, что слишком привык использовать встроенную функцию Matlab, что забыл об определении функций для таких задач. - person Maxxx; 11.09.2019
comment
@ Крис Луенго Понятно. Таким образом, имея только координаты [x, y], кросс-функция на самом деле предназначена не только для [x, y], а скорее для [x, y, z]. - person Maxxx; 11.09.2019
comment
@Maxxx: Один из способов расширения перекрестного произведения до 2D (что вам нужно для вычисления угла между векторами) — предположить, что z = 0, как это делает Ринкерт в этом ответе. В этом случае результирующий 3D-вектор равен [0,0,a] с тем значением, которое вас интересует. Но есть и другие способы распространить векторное произведение на 2D. В принципе, кросс-произведение — это трехмерная концепция. - person Cris Luengo; 11.09.2019

С участием:

x = [4 2];
y = [4.3589 1];

Вы можете использовать определитель

ang = atan2d(det([x;y]),dot(x,y))

Обратите внимание, что поскольку единичный круг определяется против часовой стрелки, в этом примере угол будет отрицательным. Также использование определителя математически/теоретически неверно, но с матрицей 2x2 результат тот же.

person obchardon    schedule 11.09.2019
comment
поэтому, если я хочу, чтобы он был положительным, я просто умножаю на -1? Потому что я помню, где-то читал, что преобразование вращения происходит против часовой стрелки, поэтому было бы лучше иметь положительный угол. - person Maxxx; 11.09.2019
comment
возьмите абсолютное значение: ang = abs(atan2d(det([x;y]),dot(x,y)) (но вы потеряете важную информацию). - person obchardon; 11.09.2019
comment
@Maxxx Можно также предоставить входные данные в обратном порядке, чтобы получить представление об угле от x до y и угле от y до x. - person Dev-iL; 11.09.2019

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

cross2 = @(coor1,coor2)(coor2(2)*coor1(1)-coor2(1)*coor1(2))

Теперь вы можете использовать его как обычную функцию. Я думаю, что это должно быть идеальным решением с точки зрения количества операций, а также с точки зрения повторного использования.

atan2d(cross2(coor1,coor2),dot(coor1,coor2)) % Thanks @Dev-iL
person avermaet    schedule 11.09.2019
comment
Я не уверен в этом на 100%, но для производительности может быть лучше, если cross2 будет определена как правильная функция, поскольку JIT-компилятор MATLAB может затем оптимизировать ее, что может быть не так для анонимных функций. А еще лучше, сделать все вычисление угла функцией и покончить с этим. - person Dev-iL; 11.09.2019