создание двух ортогональных векторов, ортогональных определенному направлению

Каковы самые простые и эффективные способы в numpy сгенерировать два ортонормированных вектора a и b, чтобы перекрестное произведение двух векторов равнялось другому единичному вектору k, который уже известен?

Я знаю, что таких пар бесконечно много, и мне все равно, какие пары я получу, пока выполняются условия axb=k и a.b=0.


person Physicist    schedule 11.11.2015    source источник
comment
a и b - это форма (3,) (1d с 3 элементами)? Как бы вы сделали это «вручную»?   -  person hpaulj    schedule 11.11.2015
comment
да. a, b и k имеют форму (3,). Я знаю, как это сделать своими руками. У меня есть 5 уравнений с 6 неизвестными, значит ли это, что нет простых способов (всего несколькими строками), и я должен использовать численные методы в scipy для их решения?   -  person Physicist    schedule 11.11.2015
comment
Я думал об алгебраических версиях перекрестных и точечных произведений в принятом ответе. Для небольших массивов это будет так же быстро.   -  person hpaulj    schedule 11.11.2015


Ответы (3)


Это будет делать:

>>> k  # an arbitrary unit vector k is not array. k is must be numpy class. np.array
np.array([ 0.59500984,  0.09655469, -0.79789754])

Чтобы получить 1-й:

>>> x = np.random.randn(3)  # take a random vector
>>> x -= x.dot(k) * k       # make it orthogonal to k
>>> x /= np.linalg.norm(x)  # normalize it

Чтобы получить 2-й:

>>> y = np.cross(k, x)      # cross product with k

и проверить:

>>> np.linalg.norm(x), np.linalg.norm(y)
(1.0, 1.0)
>>> np.cross(x, y)          # same as k
array([ 0.59500984,  0.09655469, -0.79789754])
>>> np.dot(x, y)            # and they are orthogonal
-1.3877787807814457e-17
>>> np.dot(x, k)
-1.1102230246251565e-16
>>> np.dot(y, k)
0.0
person behzad.nouri    schedule 11.11.2015
comment
Это не работает, если k является другим вектором ``` ››› k = np.array([ 0.0, 0.0215, -1.334]) ››› x = np.random.randn(3) ››› x -= x.dot(k) * k ››› x /= np.linalg.norm(x) ››› np.dot(x, k) 0,38532052441276377 ``` - person Miae Kim; 23.07.2019
comment
Отлично, спасибо, вместе с ответом Рене Вирнаты ниже это работает, даже если первый входной вектор НЕ является единичным вектором. - person Charly Empereur-mot; 04.08.2019

Извините, я не могу оставить это как комментарий из-за отсутствия репутации.

Что касается ответа @behzad.nouri, обратите внимание, что если k не является единичным вектором, код больше не будет давать ортогональный вектор!

Правильный и общий способ сделать это — вычесть продольную часть случайного вектора. Общая формула для этого здесь

Поэтому вам просто нужно заменить это в исходном коде:

>>> x -= x.dot(k) * k / np.linalg.norm(k)**2
person René Wirnata    schedule 02.06.2017
comment
Этот метод называется Процесс Грама-Шмидта. - person Miae Kim; 23.07.2019
comment
Так что это работает в обоих случаях, независимо от того, является ли k единичным вектором или нет, верно? - person Charly Empereur-mot; 04.08.2019
comment
Ну да, это так - person Charly Empereur-mot; 04.08.2019

Предположим, что вектор, поддерживающий ортогональный базис, равен u.

b1 = np.cross(u, [1, 0, 0])   # [1, 0, 0] can be replaced by other vectors, just get a vector orthogonal to u
b2 = np.cross(u, b1)
b1, b2 = b1 / np.linalg.norm(b1), b2 / np.linalg.norm(b2)

Более короткий ответ, если хотите.

Получить матрицу преобразования

B = np.array([b1, b2])
TransB = np.dot(B.T, B)
u2b = TransB.dot(u) # should be like [0, 0, 0]
person william liang    schedule 27.05.2018