xyz traslacion transformación rotación rotacion robotica matriz matrices explicacion encontrar ejes demostracion c# math matrix

c# - traslacion - rotacion de ejes



Matriz de rotación dado ángulo y punto en X, Y, Z (3)

Estoy haciendo manipulación de imágenes y quiero rotar todos los píxeles en un espacio xyz basado en un ángulo, el origen y una coordenada x, y, yz.

Solo necesito configurar la matriz adecuada (4x4) y luego estaré bien desde allí. El ángulo está en grados, no en radianes y las x, y, z van a ser de -1 a 1 (flotadores)

EDITAR:

Bien, aquí está el código que elevé para hacer la rotación sobre una línea determinada definida por el origen y un coorinate X, Y, Z.

float ang = angD * (float)(Math.PI / 180); // from degrees to radians, if needed //U = n*n(t) + cos(a)*(I-n*n(t)) + sin(a)*N(x). var u = MatrixDouble.Identity(4); // 4x4 Identity Matrix u = u.Multiply(Math.Cos(ang)); var n = new MatrixDouble(1, 4, new List<double> { x, y, z, 0 }); var nt = n.Transpose(); // This next part is the N(x) matrix. The data is inputted in Column // first order and fills in the 4x4 matrix with the given 16 Doubles var nx = new MatrixDouble(4, 4, new List<double> { 0, z, -y, 0, -z, 0, x, 0, y, -x, 0, 0, 0, 0, 0, 1 }); nx = nx.Multiply(Math.Sin(ang)); var ret = nt.Multiply(n); ret[3, 3] = 1; u = u.Subtract(ret); u = ret.Add(u.Add(nx));

Es un poco complicado y estoy usando una biblioteca de Matrix personalizada, pero nada allí debería ser demasiado difícil de implementar con cualquier lib de Matrix que funcione.

¡Uf, mucha matemática!


La función rotateAroundAxis() gira el punto alrededor de cualquier eje en 3D. Es mi solución a la rotación en 3D usando la geometría analítica y la programación para modelar el proceso. El código está en JavaScript.

function rotateAroundAxis(A, B, C, alpha, precision) { // A is rotated point, BC is axis, alpha is angle // A, B, C are points in format [Ax, Ay, Az], alpha is float, precision is int // A2 is output in format [A2x, A2y, A2z] if((A[0] - B[0])*(A[1] - C[1]) == (A[1] - B[1])*(A[0] - C[0]) && (A[1] - B[1])*(A[2] - C[2]) == (A[1] - C[1])*(A[2] - B[2]) && (A[0] - B[0])*(A[2] - C[2]) == (A[0] - C[0])*(A[2] - B[2])) { return A }// Return the original point if it is on the axis. var D = findClosestPoint(A, B, C, precision); var w = crossProduct(new Array(C[0] - B[0], C[1] - B[1], C[2] - B[2]), new Array(C[0] - A[0], C[1] - A[1], C[2] - A[2])); var W = pointPlusVector(A, w); var sizeAW = vectorSize(A, W); var sizeDA = vectorSize(D, A); var sizeAE = sizeDA*(Math.sin(0.5*alpha))/(Math.cos(0.5*alpha)); var E = new Array(A[0] + (W[0] - A[0])*sizeAE/sizeAW, A[1] + (W[1] - A[1])*sizeAE/sizeAW, A[2] + (W[2] - A[2])*sizeAE/sizeAW); var sizeDE = vectorSize(D, E); var sizeEF = sizeAE*Math.sin(alpha/2); var F = new Array(D[0] + (E[0] - D[0])*(sizeDE - sizeEF)/sizeDE, D[1] + (E[1] - D[1])*(sizeDE - sizeEF)/sizeDE, D[2] + (E[2] - D[2])*(sizeDE - sizeEF)/sizeDE); var A2 = new Array(A[0] + 2*(F[0] - A[0]), A[1] + 2*(F[1] - A[1]), A[2] + 2*(F[2] - A[2])) return A2; } function angleSize(A, S, B) { ux = A[0] - S[0]; uy = A[1] - S[1]; uz = A[2] - S[2]; vx = B[0] - S[0]; vy = B[1] - S[1]; vz = B[2] - S[2]; if((Math.sqrt(ux*ux + uy*uy + uz*uz)*Math.sqrt(vx*vx + vy*vy + vz*vz)) == 0) {return 0} return Math.acos((ux*vx + uy*vy + uz*vz)/(Math.sqrt(ux*ux + uy*uy + uz*uz)*Math.sqrt(vx*vx + vy*vy + vz*vz))); } function findClosestPoint(N, B, C, precision) { // We will devide the segment BC into many tiny segments and we will choose the point F where the |NB F| distance is the shortest. if(B[0] == C[0] && B[1] == C[1] && B[2] == C[2]) {return B} var shortest = 0; for(var i = 0; i <= precision; i++) { var Fx = Math.round(precision*precision*(B[0] + (C[0] - B[0])*i/precision))/(precision*precision); var Fy = Math.round(precision*precision*(B[1] + (C[1] - B[1])*i/precision))/(precision*precision); var Fz = Math.round(precision*precision*(B[2] + (C[2] - B[2])*i/precision))/(precision*precision); var sizeF = vectorSize(new Array(N[0], N[1], N[2]), new Array(Fx, Fy, Fz)); if(i == 0 || sizeF < shortest) { // first run or condition shortest = sizeF; F = new Array(Fx, Fy, Fz); } } // recursion, if it is an outer point return findClosestPoint(we mirror further point in the closer one) if(F[0] == Math.round(precision*precision*(B[0]))/(precision*precision) && F[1] == Math.round(precision*precision*(B[1]))/(precision*precision) && F[2] == Math.round(precision*precision*(B[2]))/(precision*precision)) { // F == B if(Math.round(precision*precision*180*angleSize(C, B, N)/Math.PI)/(precision*precision) <= 90){return F} else {return findClosestPoint(N, new Array(2*B[0] - C[0], 2*B[1] - C[1], 2*B[2] - C[2]), B, precision)} } else if (F[0] == Math.round(precision*precision*(C[0]))/(precision*precision) && F[1] == Math.round(precision*precision*(C[1]))/(precision*precision) && F[2] == Math.round(precision*precision*(C[2]))/(precision*precision)) { // F == C if(Math.round(precision*precision*180*angleSize(B, C, N)/Math.PI)/(precision*precision) <= 90) {return F} else {return findClosestPoint(N, C, new Array(2*C[0] - B[0], 2*C[1] - B[1], 2*C[2] - B[2]), precision)} } else {return F;} } function vectorSize(A, B) { var ux = A[0] - B[0]; var uy = A[1] - B[1]; var uz = A[2] - B[2]; return Math.sqrt(ux*ux + uy*uy + uz*uz); } function crossProduct(u, v) { return (new Array(u[1]*v[2] - u[2]*v[1], u[2]*v[0] - u[0]*v[2], u[0]*v[1] - u[1]*v[0])); } function pointPlusVector (A, v) { return (new Array(A[0] + v[0], A[1] + v[1], A[2] + v[2])); }


Las matrices de rotación completas se derivan y dan en https://sites.google.com/site/glennmurray/Home/rotation-matrices-and-formulas .

Del papel:

5.2 La matriz simplificada para rotaciones sobre el origen

Tenga en cuenta que esto supone que (u, v, w) es un vector de dirección para el eje de rotación y que u ^ 2 + v ^ 2 + w ^ 2 = 1.

Si tiene un punto (x, y, z) que desea rotar, entonces podemos obtener una función de siete variables que produce el punto girado:

f (x, y, z, u, v, w, theta) =

El documento también incluye matrices y fórmulas para rotaciones sobre un eje arbitrario (no necesariamente a través del origen), código de Java disponible bajo la licencia de Apache y un enlace a una aplicación web que ilustra las rotaciones.


Usar la estructura Matrix3D ( MSDN ): representa una matriz 4 x 4 utilizada para transformaciones en el espacio 3-D

Mire aquí un tutorial: Construyendo un motor 3D

Esencialmente, las matrices se construyen para las rotaciones X, Y y Z y luego puedes multiplicar las rotaciones en cualquier orden.

public static Matrix3D NewRotateAroundX(double radians) { var matrix = new Matrix3D(); matrix._matrix[1, 1] = Math.Cos(radians); matrix._matrix[1, 2] = Math.Sin(radians); matrix._matrix[2, 1] = -(Math.Sin(radians)); matrix._matrix[2, 2] = Math.Cos(radians); return matrix; } public static Matrix3D NewRotateAroundY(double radians) { var matrix = new Matrix3D(); matrix._matrix[0, 0] = Math.Cos(radians); matrix._matrix[0, 2] = -(Math.Sin(radians)); matrix._matrix[2, 0] = Math.Sin(radians); matrix._matrix[2, 2] = Math.Cos(radians); return matrix; } public static Matrix3D NewRotateAroundZ(double radians) { var matrix = new Matrix3D(); matrix._matrix[0, 0] = Math.Cos(radians); matrix._matrix[0, 1] = Math.Sin(radians); matrix._matrix[1, 0] = -(Math.Sin(radians)); matrix._matrix[1, 1] = Math.Cos(radians); return matrix; }