Что такое формула для получения вектора, перпендикулярного другому вектору?

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

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

6 ответов


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

так: 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 is 0. Тогда вы в самолете.


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

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

if (A2 != 0 || A3 != 0)
    C = (1, 0, 0);
else
    C = (0, 1, 0);
B = A x C; 

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) не должно быть близко к нулю, поэтому вектор. The c > a случай похож.


одним из способов было бы найти преобразование вращения от положительной оси 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: матрица вращения от оси и угла

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


Я считаю, что это должно произвести произвольный вектор, перпендикулярный данному вектору 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)));
}

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.