По какой формуле можно получить трехмерный вектор B, лежащий в плоскости, перпендикулярной вектору A?
То есть для вектора A какова формула f (угол, модуль), которая дает вектор, перпендикулярный A, с указанным модулем и повернутый на угол?
По какой формуле можно получить трехмерный вектор B, лежащий в плоскости, перпендикулярной вектору A?
То есть для вектора A какова формула f (угол, модуль), которая дает вектор, перпендикулярный A, с указанным модулем и повернутый на угол?
Если два вектора перпендикулярны, то их скалярное произведение равно нулю.
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
. Тогда вы в самолете.
v1(x1, y1, z1)
.
- person Petar Minchev; 21.06.2012
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
аналогичен.
dot(vec, above_func(vec)) == 0
для всех векторов (мне было лень пытаться проверить стабильность аналитически, так что это был мой следующий лучший вариант). Это сработало отлично.
- person Steve; 28.11.2016
Вычислите перекрестное произведение AxC
с другим вектором C
, не коллинеарным вектору A
.
Есть много возможных направлений в плоскости, перпендикулярной A
. Если вам все равно, какой из них выбрать, просто создайте произвольный вектор C
, не коллинеарный с A
:
if (A2 != 0 || A3 != 0)
C = (1, 0, 0);
else
C = (0, 1, 0);
B = A x C;
Я считаю, что это должно создавать произвольный вектор, который перпендикулярен заданному вектору 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
имеет все равные. Таким образом, мы избегаем нестабильного случая перекрестного произведения двух почти выровненных векторов.
Одним из способов было бы найти преобразование вращения от положительной оси 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: Матрица вращения из ось и угол
Другим методом может быть использование вращение кватернионов. Это немного больше, чтобы обернуть голову, но меньше цифр, чтобы отслеживать.
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.
n
? Во-вторых, в вашем заголовке написано перпендикулярно, но в тексте вопроса сказано, что он повернут на угол - будет ли этот угол когда-либо отличаться от девяноста градусов? - person AakashM   schedule 21.06.2012