2009-06-21 40 views
7

Tôi có một tập hợp các điểm dữ liệu trong không gian 3D mà dường như tất cả đều rơi vào một mặt phẳng cụ thể. Tôi sử dụng PCA để tính toán các thông số mặt phẳng. Thành phần thứ 3 của PCA mang lại cho tôi vectơ bình thường của mặt phẳng (thành phần yếu nhất).Xoay vectơ bình thường trên mặt phẳng trục

Điều tôi muốn làm tiếp theo là chuyển tất cả các điểm trên mặt phẳng đã nói và xem nó theo dạng 2D.

Ý tưởng của tôi là phải làm như sau:

  • Tìm một điểm trung tâm (điểm trung bình) trên máy bay
  • trừ nó từ tất cả các điểm dữ liệu để sắp xếp chúng xung quanh nguồn gốc
  • Xoay bình thường để nó trở thành (0,0, -1)
  • Áp dụng luân chuyển này cho tất cả các điểm dữ liệu
  • Sử dụng chiếu trực giao (về cơ bản, bỏ qua trục z)

Bây giờ tôi đang gặp khó khăn trong việc tìm kiếm hoạt động xoay đúng. Tôi đã thử làm việc với acos hoặc atan và thiết lập hai ma trận xoay. Có vẻ cả hai phương pháp (sử dụng acos, sử dụng atan) cho tôi kết quả sai. Có lẽ bạn có thể giúp tôi ở đây!

Matlab đang sau:

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: 

Tôi hy vọng n2 có y thành phần của zero. Tuy nhiên điều đó đã thất bại đối với véc tơ (-0.6367, 0.7697, 0.0467).

+0

Tại sao bạn không chỉ đơn giản là chiếu tất cả các điểm trên mặt phẳng và sau đó xoay mọi thứ để bạn có thể vẽ các điểm bằng tọa độ xz (hoặc xy) của chúng? –

+0

Điều đó, hoặc gắn máy ảnh trực tiếp với mặt phẳng sao cho nó nhìn thẳng vào nó. –

+0

Ý tưởng máy ảnh là một ý tưởng hay. Bạn di chuyển máy ảnh ra khỏi máy bay từ nguồn gốc một khoảng cách dọc theo bình thường. Sau đó, bạn chỉ máy ảnh vào nguồn gốc. Tất nhiên, điều này giả định rằng bạn có mã chiếu máy ảnh, có thể được thực hiện với các phép quay hoặc vectơ. – Nosredna

Trả lời

10

Nếu bạn có mặt phẳng, bạn có véc tơ thông thường và nguồn gốc. Tôi sẽ không làm bất kỳ "phép quay" nào cả. Bạn chỉ là một vài hoạt động vector đi từ câu trả lời của bạn.

  • Hãy gọi vectơ bình thường của mặt phẳng của bạn là trục z mới.
  • Bạn có thể tạo trục y mới bằng cách vượt qua trục x cũ với trục z mới (bình thường của máy bay).
  • Tạo trục x mới bằng cách vượt qua z mới với y mới.
  • Làm cho tất cả vectơ trục mới của bạn thành vectơ đơn vị (độ dài 1).
  • Đối với mọi điểm bạn có, tạo một véc tơ từ nguồn gốc mới của bạn đến điểm (trừ vector của điểm - plane_origin). Chỉ cần chấm với v mới và vectơ đơn vị y mới và bạn nhận được một cặp (x, y) bạn có thể âm mưu!

Nếu bạn có chức năng sản phẩm chéo và dấu chấm, đây chỉ là một vài dòng mã. Tôi biết nó hoạt động vì hầu hết các trò chơi điện tử 3D mà tôi viết đều hoạt động theo cách này.

Tricks:

  • Chú ý đến mà hướng vector của bạn đang trỏ. Nếu chúng trỏ sai hướng, hãy phủ nhận vector kết quả hoặc thay đổi thứ tự của sản phẩm chéo.
  • Bạn gặp khó khăn nếu bình thường của máy bay của bạn chính xác giống với trục x ban đầu của bạn.
+0

Điều này thực sự có vẻ rất tốt! – ypnos

+1

Câu trả lời tuyệt vời! Điều này khắc phục rất nhiều vấn đề tôi đã gặp phải (đối phó với các lỗi quay qua trig) toàn bộ thời gian này. Tôi nghĩ rằng tôi cần phải tham gia một khóa học đại số tuyến tính. – Kaiged

1

Làm thế nào về:

Phân chia véc tơ thông thường thành vectơ trong mặt phẳng XY và véc-tơ Z. Sau đó, áp dụng một vòng xoay quanh trục Z để xếp hàng vectơ XY với một trong các trục. Sau đó tìm sản phẩm dấu chấm của bình thường với trục Z và xoay dọc theo X, Y mà bạn xếp hàng.

Ý tưởng là xếp thẳng vectơ bình thường lên bằng Z và bằng cách đó, mặt phẳng của bạn bây giờ là mặt phẳng XY.

0

Mặc dù có phản ứng thú vị khác, đây là giải pháp chúng tôi đã tìm ra trong khi chờ đợi câu trả lời:

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; 

(Nó trả về một ma trận xoay đôi hy vọng đúng)

Lỗ hổng này chúng tôi đã có trước và cố định ở đây là đặc biệt. đối phó với các dấu hiệu của thành phần X, mà không được bao gồm trong tính toán cosin. Điều này làm cho chúng ta xoay theo hướng sai một lần (quay với góc 180 °).

Tôi hy vọng tôi cũng sẽ tìm thấy thời gian để thử giải pháp của Nosredna! Nó luôn luôn tốt để tránh lượng giác.

+0

Tôi muốn đề cập rằng bất cứ khi nào bạn đi tuyến đường trig thay vì tuyến đường vector và bạn thấy mình sử dụng nhãn, hãy xem liệu atan2 có hoạt động cho bạn hay không. Phải mất cả x và y làm đối số thay vì lấy một đối số. Nó đặt câu trả lời ở góc phần tư chính xác để bạn có thể tránh được sự lộn xộn có điều kiện thông thường. http://en.wikipedia.org/wiki/Atan2 – Nosredna

+0

Vâng, atan2 thật tuyệt vời và nó đã tiết kiệm cho tôi rất nhiều thời gian trước đó. Một gợi ý tốt. – ypnos

Các vấn đề liên quan