Domanda

Ho una serie di punti dati nello spazio 3D che apparentemente cadono tutti su un piano specifico. Uso PCA per calcolare i parametri dell'aereo. Il 3o componente del PCA mi dà il vettore normale dell'aereo (componente più debole).

Quello che voglio fare dopo è trasformare tutti i punti su detto piano e guardarlo in 2D.

La mia idea era di fare quanto segue:

  • Trova un punto centrale (punto medio) sul piano
  • Sottrai da tutti i punti dati per disporli attorno all'origine
  • Ruota il normale in modo che diventi (0,0, -1)
  • Applica questa rotazione a tutti i punti dati
  • Usa la proiezione ortogonale (sostanzialmente, salta l'asse z)

Ora sono bloccato nel trovare la giusta operazione di rotazione. Ho provato a lavorare con acos o atan e impostare due matrici di rotazione. Sembra che entrambi i metodi (usando acos, usando atan) mi danno il risultato sbagliato. Forse mi puoi aiutare qui!

Segue il codice Matlab:

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:

Mi aspetto che n2 abbia un componente y pari a zero. Tuttavia, ciò fallisce già per il vettore (-0.6367, 0.7697, 0.0467).

È stato utile?

Soluzione

Se hai un piano, hai un vettore normale e un'origine. Non farei alcuna "rotazione". affatto. Ti mancano solo alcune operazioni vettoriali dalla tua risposta.

  • Chiamiamo il vettore normale del tuo aereo il nuovo asse z.
  • Puoi generare il nuovo asse y incrociando il vecchio asse x con il nuovo asse z (il tuo piano è normale).
  • Genera il nuovo asse x incrociando la nuova z con la nuova y.
  • Trasforma tutti i tuoi nuovi vettori di assi in vettori di unità (lunghezza 1).
  • Per ogni punto che hai, crea un vettore dalla tua nuova origine al punto (sottrazione vettoriale del punto - piano_origine). Basta unire i nuovi vettori x e la nuova unità y e otterrai una coppia (x, y) che puoi tracciare!

Se hai già funzioni incrociate e punti sul prodotto, queste sono solo alcune righe di codice. So che funziona perché la maggior parte dei videogiochi 3D che ho scritto ha funzionato in questo modo.

Trucchi:

  • Presta attenzione a quali direzioni indicano i tuoi vettori. Se puntano nella direzione sbagliata, annulla il vettore risultante o modifica l'ordine del prodotto incrociato.
  • Hai problemi se il normale del tuo aereo è esattamente uguale all'asse x originale.

Altri suggerimenti

Che ne dici di:

Decompone il vettore normale in un vettore nel piano XY e in un vettore Z. Quindi applicare una rotazione attorno all'asse Z per allineare il vettore XY a uno degli assi. Quindi trova il prodotto punto del normale con l'asse Z e ruota lungo il quale mai di X, Y hai allineato.

L'idea è di allineare il vettore normale con Z, e facendo che il tuo piano sia ora il piano XY.

Anche se c'erano altre risposte interessanti, questa è la soluzione che abbiamo trovato in attesa di risposte:

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;

(Restituisce una matrice di doppia rotazione, si spera, corretta)

Il difetto che avevamo prima risolto qui era l'esp. gestire il segno del componente X, che non era coperto nei calcoli del coseno. Questo ci ha fatto ruotare una volta nella direzione sbagliata (ruotando di 180 & # 176; - angolo).

Spero di trovare anche il tempo per provare la soluzione di Nosredna! È sempre bene evitare la trigonometria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top