旋转矩阵给定角度和X,Y,Z点

我正在进行图像处理,我想根据角度,原点以及x,y和z坐标旋转xyz空间中的所有像素。

我只需要设置正确的矩阵(4×4)然后我就会很好。 角度是度,而不是弧度,x,y,z都是从-1到1(浮点数)

编辑:

好吧,这是我为了由原点和X,Y,Z坐标定义的给定线进行旋转而编写的代码。

float ang = angD * (float)(Math.PI / 180); // from degrees to radians, if needed //U = n*n(t) + cos(a)*(In*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 { 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 { 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)); 

这有点复杂,我正在使用一个自定义的Matrix库,但没有任何东西应该太难实现任何function的Matrix lib。

P,很多数学!

完整的轮播矩阵派生自https://sites.google.com/site/glennmurray/Home/rotation-matrices-and-formulas 。

从论文:

5.2关于原点旋转的简化矩阵

注意,这假设(u,v,w)是旋转轴的方向向量,并且u ^ 2 + v ^ 2 + w ^ 2 = 1。

用于围绕原点旋转的简化3D矩阵。

如果你有一个你想要旋转的点(x,y,z),那么我们可以得到七个变量的函数,产生旋转点:

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

旋转点的公式。

本文还包括关于任意轴(不一定是通过原点)的旋转的矩阵和公式,Apache许可下可用的Java代码,以及说明旋转的Web应用程序的链接。

使用Matrix3D结构( MSDN ) – 表示用于3-D空间中的变换的4 x 4矩阵

看看这里的教程: 构建3D引擎

基本上,矩阵是为X,Y和Z旋转构建的,然后您可以按任意顺序乘以旋转。

 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; } 

函数rotateAroundAxis()在3D中围绕任何轴旋转点。 这是我使用分析几何和编程来对3D进行旋转的解决方案。 代码是用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])); }