Wektor prostopadły do danego

2008-01-29 17:46

Wektor wyznacza pewną linią na płaszczyźnie lub w przestrzeni. A skoro tak jest, to czasami możemy potrzebować wektora, który będzie prostopadły do jakiegoś innego, który jest nam znany. Wyznaczenie go nie jest specjalnie trudne, ale w zależności od tego, czy wszystko dzieje się w 2D czy 3D, trzeba uwzględnić pewne szczegóły.
Takim szczegółem na pewno nie jest jednak długość wynikowego wektora, bo możemy go przecież zawsze przeskalować do żądanego rozmiaru. W tym celu wystarczy go najpierw znormalizować (podzielić przez aktualną długość), a potem pomnożyć przez nową długość.

Wektory prostopadłe na płaszczyźnieNa płaszczyźnie wektor prostopadły jest wyznaczony w miarę jednoznacznie:

  1. const VEC2 Orthogonal(const VEC2& v)
  2. {
  3.    return VEC2(-v.y, v.x);
  4. }

Mówiąc ściślej, znany jest jego kierunek, a przy ustalonej długości może mieć jedynie dwa ustalone, przeciwne zwroty. To w zasadzie dość oczywiste: prostą prostopadłą do wektora wyznaczyć jest… prosto (;D), natomiast kwestia jej skierowania zależy już od nas.
Dla wektora [x, y] prostopadłymi do niego będą więc wektory [-y, x] i [y, –x].

W przestrzeni trójwymiarowej jedno-(a właściwie dwu-)znacznie można wyznaczyć jedynie wektor prostopadły do dwóch innych. Oczywiście w takim przypadku tworzą one płaszczyznę, więc tak naprawdę poszukujemy wektora (prostej), przecinającego pod kątem prostym tę właśnie płaszczyznę. Jak wiadomo, można to uczynić, obliczając iloczyn wektorowy (cross product) tych dwóch wektorów.
W przypadku, gdy mamy tylko jeden wektor, musimy się rzecz jasna liczyć z tym, że kierunków prostopadłych do niego jest nieskończenie wiele. Dlatego możliwe jest co najwyżej wyznaczenie dowolnego z nich, co jednak czasami jest zadowalające. (Możemy mieć np. płaszczyznę wyznaczoną przez punkt i normalną; jeżeli chcemy otrzymać wektor leżący na tej płaszczyźnie, musimy znaleźć wektor prostopadły do normalnej). Aby tego dokonać, trzeba po prostu dobrać drugi wektor do iloczynu. Jedynym wymaganiem dla niego jest to, aby nie był on równoległy z pierwszym:

  1. const VEC3 AnyOrthogonal(const VEC3& v)
  2. {
  3.    if (!Equal(v.x, v.y) || !Equal(v.y, v.z))
  4.       // cross z permutacją składowych
  5.       return Cross(v, VEC3(v.z, v.x, v.y));
  6.    else
  7.       // cross z wersorem osi X
  8.       return Cross(v, VEC3(1.0f, 0.0f, 0.0f));
  9. }

W celu wybrania drugiego argumentu możemy zastosować powyższą sztuczkę. Zamieniamy po prostu składowe pierwotnego wektora tak, aby żadna nie była na swoim miejscu – tutaj dla wektora [x, y, z] taką permutacją jest np. [z, x, y]. Taki wektor prawie na pewno nie będzie równoległy z pierwowzorem.
Wiemy jednak, że prawie robi wielką różnicę :) Problematyczne są te wektory, których wszystkie trzy elementy mają taką samą wartość. Musimy więc sprawdzić ten przypadek. Zamiast permutacji można wtedy zastosować chociażby wektor równoległy do którejś z osi układu współrzędnych.

Tags:
Author: Xion, posted under Uncategorized »


8 comments for post “Wektor prostopadły do danego”.
  1. mtz:
    April 16th, 2008 o 21:13

    Fajne, przydało się :)

  2. optz:
    May 14th, 2008 o 23:59

    wielkie dzięki, bardzo mi się przydało

  3. wjmm:
    December 31st, 2008 o 14:02

    Nie mogłem nigdzie znaleźć takiego wzoru, więc sam sobie wymyśliłem identyczny:)

  4. pytajnik:
    December 30th, 2009 o 8:42

    co to za funkcja equal?? Nie mozna po lucku pisac == ?

  5. Xion:
    December 30th, 2009 o 18:22

    Nie można. Porównywanie “po lucku” liczb zmiennoprzecinkowych poprzez == to zły pomysł, bo ich reprezentacja w komputerze jest niedokładna. Dlatego trzeba uwzględnić pewien margines błędu, a użyta tu funkcja Equal mogłaby wyglądać np. tak:
    const float EPS = 0.0001f;
    bool Equal(float x, float y) { return abs(x – y) < EPS; }[/cpp]

  6. asdafa:
    June 5th, 2012 o 12:31

    “Dla wektora [x, y] prostopadłymi do niego będą więc wektory [-y, x] i [y, -x].” — od kiedy zachodzi taka zależność?…..

  7. asdafa:
    June 5th, 2012 o 12:47

    Co do mojego postu powyżej, to przepraszam i przyznaje rację. :)

  8. dogi:
    July 3rd, 2012 o 9:07

    nice tx :)

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.