Вопрос

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

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

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

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

Теперь я застрял в поиске правильной операции поворота.Я попробовал работать с 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 иметь y-составляющую, равную нулю.Однако это уже не удается для вектора (-0.6367, 0.7697, 0.0467).

Это было полезно?

Решение

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

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

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

Хитрости:

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

Другие советы

Как насчет:

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

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

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

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 °).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top