Pergunta

Eu tenho um conjunto de pontos de dados no espaço 3D que aparentemente todos caem em um plano específico. Eu uso PCA para calcular os parâmetros de avião. O terceiro componente do PCA me dá o vetor normal do plano (componente mais fraco).

O que eu quero fazer agora é transformar todos os pontos em cima do referido avião e olhar para ele em 2D.

A minha ideia era fazer o seguinte:

  • Encontre um ponto central (ponto médio) no plano
  • subtrair-lo de todos os pontos de dados para organizá-los em torno da origem
  • Girar o modo normal que torna-se (0,0, -1)
  • Aplicar esta rotação para todos os pontos de dados
  • Uso de projecção ortogonal (basicamente, pular eixo z)

Agora eu estou preso em encontrar a operação de rotação direita. Eu tentei trabalhar com acos ou atan e criação de duas matrizes de rotação. Parece ambos os métodos (usando acos, usando atan) me dá o resultado errado. Talvez você possa me ajudar aqui!

código Matlab seguinte:

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:

Espero n2 ter componente y de zero. No entanto, que já não para o vetor (-0,6367, 0,7697, 0,0467).

Foi útil?

Solução

Se você tem um plano, você tem um vetor normal e uma origem. Eu não faria qualquer "rotações" em tudo. Você é apenas um poucas operações vetor de distância de sua resposta.

  • Vamos chamada vetor normal do seu plano do novo eixo z.
  • Você pode gerar o novo eixo y cruzando o eixo x antigo com o novo eixo z (do seu plano normal).
  • Gerar o novo eixo x, atravessando o novo z com o novo y.
  • Faça todos os seus novos vetores de eixo em vetores unitários (comprimento 1).
  • Para cada ponto que você tem, criar um vector que é de sua nova origem ao ponto (vetor subtração de ponto - plane_origin). Apenas dot com os vetores nova nova unidade X e Y e você terá um par (x, y) é possível traçar!

Se você tem cruz e dot funções do produto já, este é apenas algumas linhas de código. Eu sei que ele funciona porque a maioria dos 3D videogames que eu escrevi trabalhou desta forma.

Truques:

  • Preste atenção para que as direções seus vetores estão apontando. Se eles apontam o caminho errado, negar o vetor resultante ou alterar a ordem do produto cruzado.
  • Você tem dificuldade para se do normal, o avião é exatamente o mesmo que o seu eixo x originais.

Outras dicas

Como sobre: ??

decompor o vetor normal num vector no plano XY e Z um vector. Em seguida, aplicam-se uma rotação em torno do eixo Z para alinhar o vector XY com um dos eixos. Em seguida, encontrar o produto escalar do normal com o eixo Z, e girar ao longo do qual nunca de X, Y você alinhados com.

A idéia é alinhar o vetor normal com Z, e fazendo que o avião é agora o plano XY.

Embora houvesse outras respostas interessantes, esta é a solução que descobrimos enquanto espera por respostas:

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;

(ele está retornando uma matriz espero correta rotação dupla)

A falha que tínhamos antes e fixo aqui era esp. lidar com o sinal do componente X, que não foi coberto nos cálculos de cosseno. Isso nos fez girar na direção errada uma vez (rotativo com 180 ° - ângulo).

Espero também vai encontrar tempo para tentar a solução da Nosredna! É sempre bom para evitar trigonometria.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top