2012-04-13 12 views
11

(W trzech wymiarach) Poszukuję sposobu obliczenia zarejestrowanego kąta między dwoma wektorami, bez podania informacji innych niż te wektory. Jak podano w this question, jest to dość proste, aby obliczyć kąt znaku ze względu na normalną płaszczyznę, do której wektory są prostopadłe. Ale nie mogę znaleźć sposobu, aby to zrobić bez tej wartości. To oczywiste, że iloczyn dwóch wektorów produkuje takie normalne, ale ja napotkasz następującej sprzeczności pomocą odpowiedź powyżej:Podpisany kąt między dwoma wektorami bez płaszczyzny odniesienia

signed_angle(x_dir, y_dir) == 90 
signed_angle(y_dir, x_dir) == 90 

gdzie spodziewałbym drugi wynik będzie ujemny. Wynika to z faktu, że iloczyn cross(x_dir, y_dir) jest w przeciwnym kierunku cross(y_dir, x_dir), biorąc pod uwagę następujące psuedocode ze znormalizowanym wejściowych:

signed_angle(Va, Vb) 
    magnitude = acos(dot(Va, Vb)) 
    axis = cross(Va, Vb) 
    dir = dot(Vb, cross(axis, Va)) 
    if dir < 0 then 
     magnitude = -magnitude 
    endif 
    return magnitude 

nie uważać DIR zawsze ujemny powyżej.

Widziałem ten sam problem z sugerowanym rozwiązaniem atan2.

szukam sposób, aby:

signed_angle(a, b) == -signed_angle(b, a) 
+1

to nie to: http://www.jtaylor1142001.net/calcjat/Solutions/VDotProduct/VDPTheta3D.htm czego szukasz? – Jack

+0

Link w powyższym komentarzu nie działa – ephere

Odpowiedz

1

Dzięki wszystkim.Po przejrzeniu komentarzy i spojrzeniu wstecz na to, co próbowałem zrobić, zdałem sobie sprawę, że mogę osiągnąć to, co muszę zrobić z podaną, standardową formułą dla podpisanego kąta. Właśnie odłożyłem słuchawkę w teście jednostkowym dla funkcji mojego podpisu kątowego.

Dla odniesienia, podaję wynikowy kąt z powrotem do funkcji obrotu. Nie udało mi się wyjaśnić faktu, że w naturalny sposób użyje on tej samej osi, co w sign_angle (iloczynu krzyżowego wektorów wejściowych), a właściwy kierunek obrotu będzie wynikał z kierunku, w którym ta oś jest zwrócona.

Więcej po prostu mówiąc, obie te powinny po prostu „zrobić dobry uczynek” i obracają się w różnych kierunkach:

rotate(cross(Va, Vb), signed_angle(Va, Vb), point) 
rotate(cross(Vb, Va), signed_angle(Vb, Va), point) 

Gdzie pierwszy argument jest oś obrotu, a drugi to kwota obrócić.

3

Signed kąt między dwoma wektorami bez płaszczyzny odniesienia

angle = acos(dotproduct(normalized(a), normalized(b))); 

signed_angle (a, b) == -signed_angle (b, a)

Myślę, że to niemożliwe bez jakiegoś wektora odniesienia.

+0

Myślałem o tym więcej i tak jest. Znak kąta zależy od osi obrotu, której używasz jako punktu odniesienia. Oczywiście istnieją dwie różne osie, jedna w kierunku poprzecznym i jedna w przeciwnym kierunku. –

+0

@JeffE: Tak, i podczas gdy można znaleźć oś "rotacyjną" za pomocą produktu krzyżowego, nie można określić, w którym kierunku był początkowo zwrócony - w krzyżówkach b' lub w 'b cross a' - swapach, a ty będziesz miał oś zwróconą w przeciwnym kierunku. W rezultacie nie można określić, czy kąt obrotu mieści się w zakresie 0..pi, czy jest w zakresie pi..pi * 2. – SigTerm

-2

Jeśli chcesz to spójny wynik, wtedy każdy dowolny sposób wybierać między x b i b × się za normalne zrobi. Może wybrać ten, który jest mniejszy leksykograficznie?

(Ale warto wyjaśnić, na czym polega problem w rzeczywistości stara się rozwiązać. Może jest to rozwiązanie, które nie wymaga obliczania spójnego podpisaną kąt między dowolnymi 3-wektorów)

18

The odpowiednich formuł matematycznych:

dot_product(a,b) == length(a) * length(b) * cos(angle) 
    length(cross_product(a,b)) == length(a) * length(b) * sin(angle) 

solidnego kąta między wektorami 3-D, rzeczywisty obliczenia powinny być:

s = length(cross_product(a,b)) 
    c = dot_product(a,b) 
    angle = atan2(s, c) 

Jeśli używasz acos(c) sam, otrzymasz poważne problemy precyzji w przypadkach, gdy kąt jest mały. Przetwarzanie s i użycie atan2() zapewnia solidny wynik we wszystkich możliwych przypadkach.

Ponieważ s jest zawsze nieujemny, wynikowy kąt będzie wynosił od 0 do pi. Zawsze będzie odpowiednik ujemnego kąta (angle - 2*pi), ale nie ma powodu geometrycznego, aby go preferować.

+0

Dzięki, zachowam to o acos. Sądzę, że jest to oczywiste, gdy wizualizujesz funkcję. – metatheorem

+0

Ostrzeżenie: ta funkcja jest przemienna i nie powinna być: kąt od kierunku + x (1 0 0) do kierunku + y (0 1 0) powinien wynosić + 90 °. Odwrotnie, od + y do + x, powinno wynosić -90 °. Ale z tą funkcją, 'f (x, y) == f (y, x)'. Nie można stwierdzić różnicy, ponieważ 's' jest nieujemne i że produkt krzyżowy jest jedyną rzeczą, która mogłaby ci powiedzieć o kierunku między tymi dwoma. –

+0

Jeśli byłby w 2 wymiarach, byłby anty-komutacyjny. Jednak w 3 wymiarach jest (i powinno być) przemienne - ponieważ w 3 wymiarach potrzebny jest trzeci wektor do określenia chiralności. Bez trzeciego wektora, który rozróżnia kąty dodatnie i ujemne od pierwszych dwóch, nie masz żadnego powodu, by preferować jeden kierunek nad drugim. – comingstorm

Powiązane problemy