# rotation shmotation

October 23, 2006 4:37 PM Subscribe

Vector Geometry Filter: I'm working in matlab and need to transform a surface to match an arbitrary angle. I have the unit vector of the new normal (and the original normal is in the Z axis (0 0 1))...however i'm not sure how to rotate one normal to another (i know, i know, it sounds very simple really...)

So the real problem is that the orders of rotation cannot be mixed around. Matlab allows you to rotate a surface using an angle of rotation and an arbitrary vector...so theoretically i could find a single axis and angle that would allow me to do the rotation in one operation (and thus get rid of the orders), but i'm finding the math is a beyond my head. I've also tried transforming the original data to a new plane but matlab isn't soo happy with that technique (and i've had a hard time tracking down a good equation for that as well). Any suggestions would be much appreciated....help me obi wan kenobe, you're my only hope.

So the real problem is that the orders of rotation cannot be mixed around. Matlab allows you to rotate a surface using an angle of rotation and an arbitrary vector...so theoretically i could find a single axis and angle that would allow me to do the rotation in one operation (and thus get rid of the orders), but i'm finding the math is a beyond my head. I've also tried transforming the original data to a new plane but matlab isn't soo happy with that technique (and i've had a hard time tracking down a good equation for that as well). Any suggestions would be much appreciated....help me obi wan kenobe, you're my only hope.

If A is the old normal and B the new one:

Rotate an angle "acos(dot(A,B)/(norm(A)*norm(B)))" around the vector "cross(A,B)".

posted by springload at 5:01 PM on October 23, 2006

Rotate an angle "acos(dot(A,B)/(norm(A)*norm(B)))" around the vector "cross(A,B)".

posted by springload at 5:01 PM on October 23, 2006

Take the cross product of your new normal with the original (which is just (0,0,1)). This gives you the direction of the axis to rotate around. Assuming the original vectors were normalized, the magnitude of this vector is the sine of the angle of rotation. In your case, things are simple. Let (x,y,z) represent the final normal vector. The axis to rotate around is (x,-y,0), and the angle is ArcSin(Sqrt(x^2+y^2)) (I'll let you work out whether it's + or -).

posted by dsword at 5:02 PM on October 23, 2006

posted by dsword at 5:02 PM on October 23, 2006

What you want to do is read up on a thing called a Quaternion, it is a 4-number representation of orientation, specifically by rotating around a vector. You can represent ANY orientation of a frame of reference by a single rotation if you get to pick the vector to rotate about and the amount of rotation. Your plane is a frame of reference.

If you email me (follow the link from my profile), I can send you a scan of a very decent paper on all the usual ways that are used to represent rotations, e.g. Euler angles, direction-cosine matrices and quaternions (Euler-axis and Euler-Rodrigues). I cannot recommend the paper highly enough.

You might also want to do some reading up on matrices. In particular, a rotation in 3D can be represented as a 3x3 matrix, sometimes referred to as the direction-cosine matrix. If you multiply a vector by this special matrix, the result is the same as rotating it. You can manufacture such matrices directly or from a quaternion; there are formulae on the web for it.

Given that you have two (normalised) vectors V1 and V2 representing the normal before and after the rotation, you just need to figure the amount and axis of rotation. The axis will be the cross product of the two vectors. The angle to rotate will be cos

You could equally validly take the positive or negative cos

Feel free to email if you have more questions, this is what I'm doing at work at the moment (kinematics).

posted by polyglot at 8:11 AM on October 24, 2006

If you email me (follow the link from my profile), I can send you a scan of a very decent paper on all the usual ways that are used to represent rotations, e.g. Euler angles, direction-cosine matrices and quaternions (Euler-axis and Euler-Rodrigues). I cannot recommend the paper highly enough.

You might also want to do some reading up on matrices. In particular, a rotation in 3D can be represented as a 3x3 matrix, sometimes referred to as the direction-cosine matrix. If you multiply a vector by this special matrix, the result is the same as rotating it. You can manufacture such matrices directly or from a quaternion; there are formulae on the web for it.

Given that you have two (normalised) vectors V1 and V2 representing the normal before and after the rotation, you just need to figure the amount and axis of rotation. The axis will be the cross product of the two vectors. The angle to rotate will be cos

^{-1}(V1 dot V2) since cos(θ)=V1 dot V2. Gonna have to disagree with dsword on that one.You could equally validly take the positive or negative cos

^{-1}but the convention is to go with positive; the negative one is a left-hand quaternion and we don't want anything sinister and you'd need to reverse the rotation vector.Feel free to email if you have more questions, this is what I'm doing at work at the moment (kinematics).

posted by polyglot at 8:11 AM on October 24, 2006

What's wrong with my method? You use the dot product, so you get a scalar that's just the cosine. I use the cross product, so I get a vector, the length of which is the sine. Your method gives cos(θ)=z, mine gives sin(θ)=Sqrt(x^2+y^2). You can check that cos^2+sin^2=1. Both work just fine.

posted by dsword at 3:24 PM on October 25, 2006

posted by dsword at 3:24 PM on October 25, 2006

« Older What utilities do I need to call before a move-in? | Help me! Something feels wrong with my brain! Newer »

This thread is closed to new comments.

In MATLAB, try this:

function newr = rotateIt(vectorToBeRotatedAbout, angle, vectorToBeRotated)r = vectorToBeRotated;

n = vectorToBeRotatedAbout;

newr = r*cos(angle) + n*dot(n,r)*(1-cos(angle)) + cross(r,n)*sin(angle);

posted by Upton O'Good at 4:57 PM on October 23, 2006