我正在进行图像处理,我想根据角度,原点以及x,y和z坐标旋转xyz空间中的所有像素。
我只需要设置正确的矩阵(4x4)然后我就会很好。角度是度,而不是弧度,x,y,z都是从-1到1(浮点数)
编辑:
好的,这是我为了由原点和X,Y,Z coorinate定义的给定行进行旋转而编写的代码。
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));
这有点复杂,我正在使用一个自定义的Matrix库,但是没有任何东西可以用任何正常运行的Matrix lib来实现。
p,很多数学!答案 0 :(得分:8)
完整的旋转矩阵在https://sites.google.com/site/glennmurray/Home/rotation-matrices-and-formulas得出并给出。
来自论文:
5.2关于原点旋转的简化矩阵
注意这假设(u,v,w)是旋转轴的方向向量,并且u ^ 2 + v ^ 2 + w ^ 2 = 1.
如果你想要旋转一个点(x,y,z),那么我们可以得到七个变量的函数,产生旋转点:
f (x,y,z,u,v,w,theta)=
本文还包括关于任意轴(不一定是通过原点)的旋转的矩阵和公式,Apache许可下可用的Java代码,以及说明旋转的Web应用程序的链接。
答案 1 :(得分:1)
使用Matrix3D结构(MSDN) - 表示用于三维空间转换的4 x 4矩阵
在这里查看教程:Building a 3D Engine
基本上,矩阵是为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;
}
答案 2 :(得分:0)
函数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]));
}