2009-06-21 11 views
7

Mam zestaw punktów danych w przestrzeni 3D, które najwyraźniej wszystkie mieszczą się na konkretnej płaszczyźnie. Używam PCA do obliczania parametrów płaszczyzny. Trzeci składnik PCA daje mi normalny wektor płaszczyzny (najsłabszy komponent).Obrót wektora normalnego na płaszczyznę osi

Co chcę zrobić, to przekształcić wszystkie punkty na płaszczyznę i spojrzeć na nią w 2D.

Mój pomysł był aby wykonać następujące czynności:

  • Znajdź punkt środkowy (średni punkt) na płaszczyźnie
  • odjąć go od wszystkich punktów danych w celu ustalenia ich wokół pochodzenia
  • Obrót normalny tak, że staje się (0,0, 1)
  • Zastosować ten obrót wszystkich punktów danych
  • Używaj rzut prostopadły (zasadniczo pominąć oś z)

Teraz utknąłem w znalezieniu właściwej operacji obrotu. Próbowałem pracować z acos lub atanem i konfigurowałem dwie macierze rotacyjne. Wydaje się, że obie metody (używając acos, używając atan) dają mi zły wynik. Być może możesz mi pomóc tutaj!

kod MATLAB następująco:

b = atan(n(1)/n(2)); 
rotb = [cos(b) -sin(b) 0; sin(b) cos(b) 0; 0 0 1]; 
n2 = n * rotb; 
a = atan(n(1)/n(3)); 
rota = [cos(a) 0 sin(a); 0 1 0; -sin(a) 0 cos(a)]; 
n3 = n2 * rotaows: 

się spodziewać n2 mieć y składnik zero. Jednak to się nie udaje dla wektora (-0,6367, 0,7697, 0,0467).

+0

Dlaczego po prostu nie rzutujesz wszystkich punktów na płaszczyźnie, a następnie obracasz wszystko, aby można było po prostu narysować punkty za pomocą współrzędnych xz (lub xy)? –

+0

To lub przymocuj kamerę bezpośrednio do samolotu tak, aby patrzyła bezpośrednio na niego. –

+0

Idea aparatu jest dobra. Przesuwasz kamerę z samolotu z miejsca początkowego w pewnej odległości wzdłuż normalnej. Następnie wskaż aparat w punkcie początkowym. Oczywiście zakłada to, że masz kod projekcji kamery, który można wykonać za pomocą obrotów lub wektorów. – Nosredna

Odpowiedz

10

Jeśli masz samolot, masz normalny wektor i pochodzenie. W ogóle nie zrobiłbym żadnej "rotacji". Jesteś tylko kilkoma operacjami wektorowymi z dala od swojej odpowiedzi.

  • Nazwijmy normalny wektor twojego samolotu nową osią z.
  • Możesz wygenerować nową oś y, przecinając starą oś X z nową osią z (normalna płaszczyzna twojego samolotu).
  • Wygeneruj nową oś X, przecinając nowe z z nowym y.
  • Wszystkie nowe wektory osi wektorów jednostkowych (długość 1).
  • Dla każdego punktu, który posiadasz, utwórz wektor pochodzący od twojego nowego początku do punktu (odjęcie wektorów od punktu - plane_origin). Wystarczy kropka z nowymi wektorami y x i new y, a otrzymasz parę (x, y), którą możesz narysować!

Jeśli masz już funkcje produktu krzyżowego i punktowego, to tylko kilka linii kodu. Wiem, że to działa, ponieważ większość gier wideo 3D, które napisałem, działało w ten sposób.

sztuczki:

  • zwrócić uwagę na kierunki, które twoi wektory kierujące. Jeśli wskazują niewłaściwie, zaneguj wypadkowy wektor lub zmień kolejność krzyżowego produktu.
  • Masz problemy, jeśli normalna płaszczyzna jest dokładnie taka sama jak oryginalna oś x.
+0

To naprawdę brzmi bardzo dobrze! – ypnos

+1

Fantastyczna odpowiedź! Naprawia to wiele problemów, które miałem (cały czas zajmowałem się błędami rotacyjnymi za pośrednictwem trig). Myślę, że muszę wziąć kurs algebry liniowej. – Kaiged

1

Jak o:

Decompose normalnego wektora do wektora w płaszczyźnie XY i Z wektora. Następnie obróć wokół osi Z, aby wyrównać wektor XY z jedną z osi. Następnie znajdź iloczyn iloczynu normalnego z osią Z, a następnie obróć wzdłuż której z X, Y ustawiłeś w linii.

Chodzi o to, aby wyrównać wektor normalny z Z, i tym samym twój samolot jest teraz płaszczyzną XY.

0

Chociaż było innych ciekawych odpowiedzi, jest to rozwiązanie zorientowaliśmy się, czekając na odpowiedzi:

function roti = magic_cosini(n) 
    b = acos(n(2)/sqrt(n(1)*n(1) + n(2)*n(2))); 
    bwinkel = b * 360/2/pi; 
    if (n(1) >= 0) 
     rotb = [cos(-b) -sin(-b) 0; sin(-b) cos(-b) 0; 0 0 1]; 
    else 
     rotb = [cos(-b) sin(-b) 0; -sin(-b) cos(-b) 0; 0 0 1]; 
    end 
    n2 = n * rotb; 
    a = acos(n2(3)/sqrt(n2(2)*n2(2) + n2(3)*n2(3))); 
    awinkel = a * 360/2/pi; 
    rota = [1 0 0; 0 cos(-a) -sin(-a); 0 sin(-a) cos(-a)]; 
    roti = rotb * rota; 

(To przekazujących nadzieją prawidłowego podwójne macierz obrotu)

wada mieliśmy przed i ustalone tutaj było esp. radzić sobie ze znakiem komponentu X, którego nie uwzględniono w obliczeniach kosinusów. To spowodowało, że raz obróciliśmy się w niewłaściwym kierunku (obracając się o 180 ° - kąt).

Mam nadzieję, że również znajdę czas na wypróbowanie rozwiązania Nosredny! Zawsze dobrze jest unikać trygonometrii.

+0

Chciałem wspomnieć, że za każdym razem, gdy wybierasz trasa, zamiast trasy wektorowej i używasz atana, sprawdź czy atan2 będzie działał dla ciebie. Przyjmuje zarówno x, jak i y jako argumenty zamiast przyjmowania pojedynczego argumentu. Umieszcza odpowiedź we właściwym kwadrancie, dzięki czemu można uniknąć zwykłego bałaganu warunkowego. http://pl.wikipedia.org/wiki/Atan2 – Nosredna

+0

Tak, atan2 jest niesamowity i zaoszczędziło mi wiele czasu wcześniej. Dobra wskazówka. – ypnos

Powiązane problemy