Какая формула позволяет получить вектор, перпендикулярный другому вектору?

По какой формуле можно получить трехмерный вектор B, лежащий в плоскости, перпендикулярной вектору A?

То есть для вектора A какова формула f (угол, модуль), которая дает вектор, перпендикулярный A, с указанным модулем и повернутый на угол?


person MaiaVictor    schedule 21.06.2012    source источник
comment
Две вещи: во-первых, работаем ли мы в двух измерениях? Три? n? Во-вторых, в вашем заголовке написано перпендикулярно, но в тексте вопроса сказано, что он повернут на угол - будет ли этот угол когда-либо отличаться от девяноста градусов?   -  person AakashM    schedule 21.06.2012
comment
В трех измерениях существует бесконечно много различных векторов (двухмерное векторное пространство), перпендикулярных данному вектору. Не существует единого вектора, который могла бы сгенерировать формула.   -  person    schedule 21.06.2012


Ответы (6)


Если два вектора перпендикулярны, то их скалярное произведение равно нулю.

So: v1(x1, y1, z1), v2(x2, y2, z2).

=> x1 * x2 + y1 * y2 + z1 * z2 = 0

Вы знаете (x1, y1, z1). Поставьте произвольные x2 и y2 и вы получите соответствующие z2:

z1 * z2 = -x1 * x2 - y1 * y2
=> z2 = (-x1 * x2 - y1 * y2) / z1

Имейте в виду, если z1 является 0. Тогда вы в самолете.

person Petar Minchev    schedule 21.06.2012
comment
Да. У вас есть один вектор, заданный v1(x1, y1, z1). - person Petar Minchev; 21.06.2012
comment
Как вы упомянули, это не удается, если z1 равно 0, однако в таком случае вопрос остается совершенно математически обоснованным. Найдите вектор, перпендикулярный, например, [1,0,0]. z1 равно 0, но [0,1,0] определенно является вектором, который, тем не менее, перпендикулярен [1,0,0]. Смотрите мой ответ для альтернативного метода. - person sircolinton; 17.04.2017

function (a,b,c)
{
    return (-b,a,0)
}

Но этот ответ не является численно стабильным, когда a, b близки к 0.

Чтобы избежать этого случая, используйте:

function (a,b,c) 
{
    return  c<a  ? (b,-a,0) : (0,-c,b) 
}

Приведенный выше ответ численно устойчив, потому что в случае c < a затем max(a,b) = max(a,b,c), затем vector(b,-a,0).length() > max(a,b) = max(a,b,c) , а поскольку max(a,b,c) не должно быть близко к нулю, то и вектор. Случай c > a аналогичен.

person golopot    schedule 16.07.2016
comment
Просто для справки, я перебрал 10 000 случайных единичных векторов и убедился, что dot(vec, above_func(vec)) == 0 для всех векторов (мне было лень пытаться проверить стабильность аналитически, так что это был мой следующий лучший вариант). Это сработало отлично. - person Steve; 28.11.2016
comment
Если вектор, например, (a=0, b=0, c=-1), c‹a таким образом, результатом будет 0, 0, 0, который не является единичным вектором. Это не выглядит правильным для меня - person Giovanni Funchal; 15.12.2016
comment
@GiovanniFunchal Действительно, утверждение max (a, b, c) не должно быть близко к нулю, может быть ложным даже для хороших векторов, как тот, который вы упомянули. Объяснение следует исправить, используя норму L-бесконечности вместо max, а c‹a следует заменить на |c|‹|a| - person Fabio; 29.03.2017

Вычислите перекрестное произведение AxC с другим вектором C, не коллинеарным вектору A.

Есть много возможных направлений в плоскости, перпендикулярной A. Если вам все равно, какой из них выбрать, просто создайте произвольный вектор C, не коллинеарный с A:

if (A2 != 0 || A3 != 0)
    C = (1, 0, 0);
else
    C = (0, 1, 0);
B = A x C; 
person Henrik    schedule 21.06.2012
comment
Есть только один вектор, мне нужна формула, которая дает вектор, перпендикулярный ему, в зависимости от его угла и длины. - person MaiaVictor; 21.06.2012
comment
Доккат, причина, по которой вы продолжаете видеть ДВА вектора в описании, заключается в том, что, учитывая первый вектор V1, есть много векторов V2, которые перпендикулярны V1. В 2D-пространстве есть как минимум два таких вектора длины 1. В 3D-пространстве существует бесконечно много векторов, перпендикулярных V1! То, что вы хотите найти, - это либо один произвольный V2 (отклонение от V1), либо вы хотите определить, перпендикулярны ли (V1, V2). - person Anders Forsgren; 21.06.2012

Я считаю, что это должно создавать произвольный вектор, который перпендикулярен заданному вектору vec, оставаясь численно стабильным независимо от угла vec (при условии, что величина vec не близка к нулю). Предположим, что Vec3D — трехмерный вектор произвольного числового типа.

Vec3D arbitrary_orthogonal(Vec3D vec)
{
  bool b0 = (vec[0] <  vec[1]) && (vec[0] <  vec[2]);
  bool b1 = (vec[1] <= vec[0]) && (vec[1] <  vec[2]);
  bool b2 = (vec[2] <= vec[0]) && (vec[2] <= vec[1]);

  return cross(vec, Vec3D(int(b0), int(b1), int(b2)));
}

Неофициальное объяснение

Устанавливается ровно 1 и только 1 из логических значений; bN устанавливается, если размерность N имеет величину строго меньше всех последующих измерений и не больше всех предыдущих измерений. Затем у нас есть единичный вектор с одним ненулевым измерением, которое соответствует размерности минимальной величины в vec. Перекрестное произведение этого с vec ортогонально vec по определению перекрестного произведения. Учтите теперь, что векторное произведение численно нестабильно только тогда, когда два вектора очень близко выровнены. Учтите, что наш единичный вектор велик только в одном измерении, и это измерение соответствует измерению, где vec было маленьким. Таким образом, гарантируется ортогональность к vec перед перекрестным произведением, с наименьшей ортогональностью в случае, когда все измерения vec равны. В этом наименее ортогональном случае мы по-прежнему вполне ортогональны, учитывая, что наш единичный вектор имеет все измерения, кроме одного, равные 0, тогда как vec имеет все равные. Таким образом, мы избегаем нестабильного случая перекрестного произведения двух почти выровненных векторов.

person sircolinton    schedule 17.04.2017
comment
Добавлено объяснение, надеюсь, оно поможет. - person sircolinton; 29.11.2019

Одним из способов было бы найти преобразование вращения от положительной оси z (или любой другой оси) к заданному вектору. Затем преобразуйте <modulus * cos(angle), modulus * sin(angle), 0>, используя это преобразование.

def getPerpendicular(v1,modulus,angle):
    v2 = vector(0,0,1)
    v1_len = v2.length()

    axis = v1.cross_product(v2)
    sinAngle = axis.length() / v1_len       # |u x v| = |u| * |v| * sin(angle)
    cosAngle = v1.dot_product(v2) / v1_len  # u . v = |u| * |v| * cos(angle)
    axis = axis.normalize()
    # atan2(sin(a), cos(a)) = a, -pi < a < pi
    angle = math.atan2(sinAngle, cosAngle)

    rotationMatrix = fromAxisAngle(axis, angle)

    # perpendicular to v2
    v3 = vector(modulus*cos(angle),modulus*sin(angle),0)

    return rotationMatrix.multiply(v3);

Чтобы рассчитать матрицу вращения, см. эту статью: WP: Матрица вращения из ось и угол

Другим методом может быть использование вращение кватернионов. Это немного больше, чтобы обернуть голову, но меньше цифр, чтобы отслеживать.

person Markus Jarderot    schedule 21.06.2012

q4w56 почти готов для надежного решения. Проблемы: 1) Не учитывает масштабирование. 2) Не сравнивает величину между двумя переменными, когда это необходимо.

scale = |x| + |y| + |z|

if scale == 0:
  return (0,0,0)

x = x/scale
y = y/scale
z = z/scale

if |x| > |y|:
  return (z, 0,-x)
else:
  return (0, z,-y)

Масштабирование важно при работе с очень большими или очень маленькими числами. Плюс в целом вам лучше выполнять операции с плавающей запятой со значениями от 0 до 1.

person lessthanoptimal    schedule 22.08.2017