2009-06-21 10 views
7

У меня есть набор точек данных в трехмерном пространстве, которые, по-видимому, все падают на конкретную плоскость. Я использую PCA для вычисления параметров плоскости. Третий компонент PCA дает мне нормальный вектор плоскости (самый слабый компонент).Поверните нормальный вектор на плоскость оси

Что я хочу сделать дальше, это преобразовать все точки в указанную плоскость и посмотреть на нее в 2D.

Моя идея состояла в том, чтобы сделать следующее:

  • Найти центральную точку (средняя точка) на плоскости
  • вычитаем это из всех точек данных, чтобы расположить их вокруг начала координат
  • Поворот нормальный так что она становится (0,0, -1)
  • Применить это вращение для всех точек данных
  • Использовать ортогональную проекцию (в основном, пропустить ось г)

Теперь я застреваю в поиске правильной операции вращения. Я пробовал работать с acos или atan и создавал две матрицы вращения. Кажется, что оба метода (используя acos, используя atan) дают мне неправильный результат. Возможно, вы можете помочь мне здесь!

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: 

Я ожидаю n2 иметь у компонента нуля. Однако это уже не выполняется для вектора (-0,6367, 0,7697, 0,0467).

+0

Почему бы вам просто не проецировать все точки на плоскости, а затем вращать все, чтобы вы могли просто нарисовать точки, используя их координаты xz (или xy)? –

+0

Это или прикрепите камеру непосредственно к плоскости, чтобы она смотрела прямо на нее. –

+0

Идея камеры хорошая. Вы перемещаете камеру из плоскости из источника на некоторое расстояние вдоль нормали. Затем вы указываете камеру в начале координат. Конечно, это предполагает, что у вас есть код проецирования камеры, который можно выполнить с помощью поворотов или векторов. – Nosredna

ответ

10

Если у вас есть самолет, у вас есть нормальный вектор и источник. Я бы вообще не делал никаких «поворотов». Вы всего лишь несколько векторных операций от вашего ответа.

  • Назовем нормальный вектор плоскости новой осью z.
  • Вы можете создать новую ось y, пересекая старую ось x с новой осью z (нормальная плоскость вашего самолета).
  • Создайте новую ось x, пересекая новый z с новым y.
  • Сделайте все свои новые векторы оси в единичные векторы (длина 1).
  • Для каждой точки, которую вы создали, создайте вектор, который от вашего нового начала до точки (векторное вычитание точки - plane_origin). Просто долейте новые векторы x и new y, и вы получите пару (x, y), которую вы можете построить!

Если у вас уже есть функции перекрестного и точечного произведения, это всего лишь несколько строк кода. Я знаю, что это работает, потому что большинство 3D-видеоигр, которые я написал, работали именно так.

хитрости:

  • Обратите внимание на то, какие направления ваши векторы, указывающие. Если они указывают неверный путь, отрицайте результирующий вектор или изменяйте порядок перекрестного произведения.
  • У вас возникли проблемы, если нормальная плоскость вашего самолета точно такая же, как и исходная ось x.
+0

Это на самом деле звучит очень хорошо! – ypnos

+1

Фантастический ответ! Это фиксирует много проблем, с которыми я столкнулся (имея дело с вращательными ошибками через тригг) все это время. Я думаю, мне нужно пройти курс линейной алгебры. – Kaiged

1

Как насчет:

Разложить вектор нормали в вектор в XY-плоскости и Z вектора. Затем примените поворот вокруг оси Z, чтобы выровнять вектор XY с одной из осей. Затем найдите точечный продукт нормали с осью Z и повернитесь по тому, что всегда из X, Y вы выстроились.

Идея состоит в том, чтобы выровнять нормальный вектор с помощью Z, и тем самым ваша плоскость теперь является плоскостью XY.

0

Хотя были и другие интересные ответы, это решение, которое мы выяснили во время ожидания ответа:

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; 

(Это возвращает надеюсь, правильную матрицу двойного вращения)

изъян у нас было раньше и фиксированный здесь был esp. со знаком знака X-компонента, который не был рассмотрен в вычислениях косинусов. Это заставило нас вращаться в неправильном направлении один раз (вращающийся с углом 180 °).

Надеюсь, я также найду время, чтобы попробовать решение Ноздренны! Всегда полезно избегать тригонометрии.

+0

Я хотел бы упомянуть, что в любое время, когда вы отправляетесь на трассу, а не на векторный маршрут, и обнаруживаете, что используете atan, посмотрите, будет ли atan2 работать для вас. В качестве аргументов вместо x и y используются аргументы вместо одного аргумента. Он ставит ответ в правильном квадранте, поэтому вы можете избежать обычного условного беспорядка. http://en.wikipedia.org/wiki/Atan2 – Nosredna

+0

Да, atan2 потрясающе, и он спас меня много времени. Хороший намек. – ypnos

 Смежные вопросы

  • Нет связанных вопросов^_^