Как я могу найти вращение четырехугольника в 3D? - PullRequest
1 голос
/ 09 октября 2010

У меня есть координаты для 4 векторов, определяющих квад и еще один для нормального.Я пытаюсь получить вращение четырехугольника.Я получаю хорошие результаты для поворота по X и Y, просто используя нормаль, но я застрял, получая Z, поскольку я использовал только 1 вектор.

Вот мой основной тест с использованием Обработка и toxiclibs ( Vec3D и методы заголовка ):

import toxi.geom.*;

Vec3D[] face = {new Vec3D(1.1920928955078125e-07, 0.0, 1.4142135381698608),new Vec3D(-1.4142134189605713, 0.0, 5.3644180297851562e-07),new Vec3D(-2.384185791015625e-07, 0.0, -1.4142135381698608),new Vec3D(1.4142136573791504, 0.0, 0.0),};
Vec3D n = new Vec3D(0.0, 1.0, 0.0);

print("xy: " + degrees(n.headingXY())+"\t");
print("xz: " + degrees(n.headingXZ())+"\t");
print("yz: " + degrees(n.headingYZ())+"\n");

println("angleBetween x: " + degrees(n.angleBetween(Vec3D.X_AXIS)));
println("angleBetween y: " + degrees(n.angleBetween(Vec3D.X_AXIS)));
println("angleBetween z: " + degrees(n.angleBetween(Vec3D.X_AXIS)));

println("atan2 x: " + degrees(atan2(n.z,n.y)));
println("atan2 y: " + degrees(atan2(n.z,n.x)));
println("atan2 z: " + degrees(atan2(n.y,n.x)));

А вот вывод:

xy: 90.0    xz: 0.0 yz: 90.0
angleBetween x: 90.0
angleBetween y: 90.0
angleBetween z: 90.0
atan2 x: 0.0
atan2 y: 0.0
atan2 z: 90.0

Как я могу получить вращение (вокруг его центра / нормали) для Z моего четырехугольника?

Ответы [ 2 ]

2 голосов
/ 10 октября 2010

OK.Честно говоря, я до сих пор не совсем понимаю, что именно вы ищете, но позвольте мне попытаться прояснить проблему, а затем высказать свое лучшее предположение относительно того, что вы действительно хотите, и посмотреть, поможет ли это.

Какупомянутое в ветке комментариев, вращение - это преобразование , которое отображает один набор элементов (например, векторы A , B , C ...) к другому набору вещей ( A ', B' , C ' ...).Мы можем полностью определить это преобразование в терминах угла (назовем его θ) и оси вращения, которую мы назовем R .

Обратите внимание, что R не являетсявектор, это линия .Это означает, что у него есть местоположение , а также направление - оно привязано где-то в пространстве - и поэтому вам нужно либо две точки, либо точка и вектор направления для его определения.Для простоты мы могли бы предположить, что точка привязки - это начало координат (0,0,0), так как вопрос говорит о главных осях X, Y и Z. В целом, однако, это не должно иметь место - если вы хотитеДля определения поворота вокруг произвольных линий вам обычно нужно сначала все перевести так, чтобы ось проходила через начало координат.(Если все, что вас волнует, это ориентация ваших объектов, а не их положение, то вы, вероятно, можете замаскировать эту проблему.)

Учитывая начальную позицию A , конечное положение A ' и ось R , концептуально просто определить угол θ (или и угол θ, поскольку вращение является периодическим и существуетбесконечно много θs, которые займут от A до A '), хотя для общего R это может быть немного затруднительно.В простейшем случае, когда R является одной из главных осей, вы можете сделать что-то вроде этого (для R = Z ):

theta0 = atan2(A.x, A.y);
theta1 = atan2(A_prime.x, A_prime.y);
theta = theta1 - theta0;

В любом случае, из вашего кода видно, что у вас уже есть инструменты для этого - я не знаком с toxiclibs , но я бы вообразил Vec3D angleBetweenметод должен занять у вас большинство пути к ответу, который вы хотите.

Однако это предполагает, что вы знаете A , A 'и R , и кажется, что это настоящий камень преткновения в вашем вопросе.Во-первых, вы упоминаете только один набор точек, определяющих произвольный квад.Во втором вы говорите о нормали как об определении центра вращения.Оба из них указывают на то, что вы не указали проблему правильно.

Как я неоднократно повторял утомительно, вращение составляет от одно до другое.Один набор четырех вершин может определять либо первое состояние, либо второе, но не оба одновременно (если θ не равно 0, в этом случае вопрос тривиален).Если вы хотите определить «вращение четырехугольника», вам также нужно сказать «из более ранней позиции P» или «в следующую позицию Q», чего вы еще не сделали.

Учитывая, что конкретный рассматриваемый четырехугольник - это квадрат , вы можете подумать, что здесь задействована другая интуитивная позиция, то есть: со сторонами, выровненными по оси.И мы действительно можем довольно легко определить угол поворота, необходимый для достижения этой ориентации, , если предположить, что четырехугольник - это прямоугольник :

// A and B are adjacent corners of the square
// B - A is the direction of the edge joining them
// theta is the angle between that side and the X axis
// (rotating by -theta around Z should align the square)
theta = atan2(B.x - A.x, B.y - A.y);

Но , вы заявили, что можете искать любой произвольный квад, для которого не было бы «естественной» базовой позиции для сравнения.И даже в квадратном случае откровенно не очень хорошая практика предполагать исходную линию без явного ее объявления.

Что возвращает нас к моему первоначальному вопросу: что вы имеете в виду ?Если вы действительно сможете правильно это определить, я подозреваю, что саму проблему вам будет относительно легко решить.


РЕДАКТИРОВАТЬ: Исходя из ваших комментариев ниже, что вы действительно хотите сделать, это найти вращение, которое выравнивает ваш четырехугольник с одной из основных плоскостей.Это эквивалентно вращению нормали квадрата для выравнивания с осью, перпендикулярной этой плоскости: например, чтобы получить квад, параллельный плоскости XY, выровняйте его нормаль с осью Z.

Это можно сделать условно с помощьюодин поворот вокруг некоторой вычисленной оси, но на практике вы разложите его на два вращения вокруг главных осей.Первый вращается вокруг оси цели, пока вектор не окажется в плоскости, содержащей эту ось и одну из других;затем поверните вокруг третьей оси, чтобы получить нормаль к ее окончательному выравниванию.Словесное описание неизбежно неуклюже, поэтому давайте немного формализуем:

Допустим, у вас есть плоский объект Q с вершинами { v1 , v2 , v3 , ...} (в вашем четырехугольном случае их будет четыре, но это может быть любое число, если все точки копланарны), с единицей нормального n = (xyz) T .Для объяснения, давайте произвольно предположим, что мы хотим выровнять объект с плоскостью XY и, следовательно, повернуть n по оси Z - процесс будет по существу таким же для XZ / Y илиYZ / X.

Поверните вокруг Z, чтобы получить n в плоскости XZ.Мы можем рассчитать требуемый угол следующим образом:

theta1 = -atan2(x,y);

Однако нам нужны только синус и косинус для построения матрицы вращения, и мы можем вычислить их напрямую, не зная угла:

hypoXY = sqrt(x*x + y*y);
c1 = x/hypoXY;
s1 = y/hypoXY;

(Очевидно, что если hypoXY равно 0, это не получится, но в этом случае n уже выровнено по Z).

Наша первая матрица вращения R1 выглядит следующим образом:

[  c1  s1  0 ]
[ -s1  c1  0 ]
[  0   0   1 ]

Затем поверните вокруг Y, чтобы получить n параллельно Z. Обратите внимание, что предыдущий поворот переместил x в новую позицию x '= sqrt (x *)1136 * 2 + y 2 ), поэтому мы должны учитывать это при расчете нашего второго угла:

theta2 = -atan2(z, sqrt(x*x + y*y));

Опять же, нам на самом деле не нужен theta2.И поскольку мы определили n как единичный вектор, наши следующие вычисления просты:

c2 = z;
s2 = hypoXY;

Наша вторая матрица вращения R2 выглядит следующим образом:

[ c2  0  -s2 ]
[ 0   1   0  ]
[ s2  0   c2 ]

Составьте два вместе, чтобы получить R = R2.R1 :

[  c2c1   c2s1  -s2  ]
[ -s1     c1     0   ]
[  s2c1   s2s1  c2   ]

Если вы примените эту матрицу к n , вы должны выровнять нормаль по оси Z.(Если нет, сначала проверьте знаки - все это немного сзади конверта , и я мог бы легко ошибиться в некоторых направлениях. У меня нет времени кодировать и проверять правильностьсейчас, но попробую попробовать позже. Я также постараюсь просмотреть ваш эскизный код.)

Как только это сработает, примените одно и то же преобразование ко всем точкам в вашем объекте Q и он должен стать параллельным (хотя, вероятно, смещенным) плоскости XY.

0 голосов
/ 09 октября 2010

Вот матрица вращения для оси z

соз (тета) грех (тета) 0

-син (тета) cos (тета) 0

0 0 1

  • ваш вектор

результат - повернутый вектор

...