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

Каква е формулата за получаване на триизмерен вектор B, лежащ в равнината, перпендикулярна на вектор A?

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


person MaiaVictor    schedule 21.06.2012    source източник
comment
Две неща: първо, работим ли в две измерения? Три? n? Второ, в заглавието ви се казва перпендикулярно, но тялото на въпроса казва завъртяно под ъгъл - този ъгъл някога ще бъде ли различен от деветдесет градуса?   -  person AakashM    schedule 21.06.2012
comment
В 3 измерения има безкрайно много различни вектори (двумерно векторно пространство), перпендикулярни на даден вектор. Няма нито един вектор, който формулата да генерира.   -  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
Dokkat, причината да продължаваш да виждаш ДВА вектора в описанието е, че като се има предвид първият вектор V1, има много вектори V2, които са перпендикулярни на V1. В 2D пространството има поне два такива вектора с дължина 1. В 3D пространството има безкрайно много вектори, перпендикулярни на V1! Това, което искате да намерите, е или един произволен V2 (perp към 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