http://www.perlmonks.org?node_id=399996

true has asked for the wisdom of the Perl Monks concerning the following question:

Howdy, CPAN has some great modules out on Math, Trig and 3D. Or at least they look great! I've been searching for some examples in use so i can join in. The documentation covers the names of functions but a concrete example slips my grasp so i can use it myself. I've looked at Math::Trig and Math::Project3D.

I want to rotate a 3d vector by a certain amount and return the new vector points so my app can do stuff with it. The 3d vector i have is a point on the edge of a sphere in 3d space. I want to rotate this point by foo and get the 3 vector points back in a subroutine.

I would include some code but its basically the example from Math:Project3D. Which i hope i do not need. Any advice, or known examples are greatly appreciated. Zaxo had a nice snippet but i got lost in the fact that there were only 2 vector points. Seems like the answer is in there somewhere though.

jtrue

Replies are listed 'Best First'.
Re: Rotate a 3D vector
by FoxtrotUniform (Prior) on Oct 17, 2004 at 23:58 UTC

Here's the short version: multiply your source vector by a 3d rotation matrix. Zaxo's snippet is nifty, but not quite sufficient as it doesn't do matrix math.

The extra complexity that comes with moving from 2d rotations to 3d rotations is the fact that, in 3d, you don't really have a canonical axis to rotate around. In the x-y plane, when you do a rotation by r radians, you pretty much have to rotate around the z axis. In 3d space, you can rotate around the x, y, or z axis, or around an arbitrary vector (if that gives you problems, think of it as rotating around several canonical axes at once). So you can't easily describe a 3d rotation with a single parameter; you basically need a matrix (or a quaternion, but let's not go there).

--
Yours in pedantry,
F o x t r o t U n i f o r m

"Lines of code don't matter as long as I'm not writing them." -- merlyn

Re: Rotate a 3D vector
by Anonymous Monk on Oct 18, 2004 at 08:55 UTC
 RX= 1 0 0 0 cos φ - sin φ 0 sin φ cos φ

 RY= cos θ 0 sin θ 0 1 0 0 -sin θ cos θ

 RZ= cos ψ -sin ψ 0 sin ψ cos ψ 0 0 0 1
Then your rotation matrix is RX * RY * RZ, with θ the amount of rotation around the X axis, φ the amount of rotation around the Y axis, and ψ the amount of rotation around the Z axis.
Sorry for bumping an old thread.. i hope this saves a bit of someones time: Ry is wrong, it should be:
cos(th) 0 sin(th) 0 1 0 -sin(th) 0 cos(th)
rgds, Mitja
how do you find the angles è, ö, and ø between two vectors?
To find the angle between the two vectors, you need to normalize them (so they have length of 1 unit) by doing this (v is the vector you want to normalize):
float distance = sqrt(v.x*v.x + v.y*v.y + v.z*v.z); v.x = v.x/distance; v.y = v.y/distance; v.z = v.z/distance;
Then find the dot product of the two normalized vectors (Va and Vb):
float dotProduct = Va.x*Vb.x + Va.y*Vb.y + Va.z*Vb.z;
This gives you the cosine of the angle, so simple do:
acos(dotProduct);
This will give you the angle. I think this post was a bit late :S
Re: Rotate a 3D vector
by itub (Priest) on Oct 18, 2004 at 13:14 UTC
Re: Rotate a 3D vector
by true (Pilgrim) on Oct 18, 2004 at 00:02 UTC
Clarification then. i only need to rotate the vector on the z axis. So the 3dvector point 3 1 3 is rotated 23 degrees on the z axis only. Any help?
jtrue

If you only need to rotate around the Z axis then it is a simple 2D trig problem. The z co-ordinate is invariant as this is our rotational plane.

sub rotate { my ( \$x,\$y,\$z,\$angle ) = @_; \$angle = deg2rad(\$angle); my \$x_new = cos(\$angle)*\$x - sin(\$angle)*\$y; my \$y_new = sin(\$angle)*\$x + cos(\$angle)*\$y; return \$x_new, \$y_new, \$z; } sub deg2rad { return 3.14159265358979*\$_[0]/180 };

Here is a nice article with a pretty applet Update Corrected error noted by johnnywang

cheers

tachyon

The beauty of concrete! Thanks so much for a perfect example tachyon. Also, a good page about the topic: 2D Math
jtrue
just want to point out it's not quite right. You need to first find the polar angle for the original point (x,y), then add the \$angle to that for the new polar angle.

Updated. I'm only refering to the geometric meaning. There is a formula: multiplying by the rotation matrix given by ((cos, -sin),(sin, cos)) (not perl notation!)

Well, the quick-and-dirty way to do it is to scale your x component by cos(t) and your y component by sin(t). You might be happier with a matrix-based solution in the long run, though.

Edit: The math above is, of course, totally bogus. I plead momentary imbecility. johnnywang has the correct solution. D'oh!

What kind of program are you writing, btw?

--
Yours in pedantry,
F o x t r o t U n i f o r m

"Lines of code don't matter as long as I'm not writing them." -- merlyn

Re: Rotate a 3D vector
by true (Pilgrim) on Oct 18, 2004 at 00:44 UTC
The program i am writing is generating sine-wave based seaweed and kelp plants for povray. I wanted to rotate my vector points around a simple y axis, but can't get a concrete example to get started. The sine wav part is done though:) I do not want to use povray to rotate because i want to output to obj file which means i need real coordinates not translated. Any chance you can show me in perl code how to rotate a vector around a single axis? thanks for help.
jtrue
Re: Rotate a 3D vector
by true (Pilgrim) on Oct 18, 2004 at 02:59 UTC
Back to the trenches with me. I'm starting with a 2d space till i can wrap my head around it. The code and examples i am finding are not matching up in 3d space. Here's my closest attempt which still is wrong. Can anyone help?
# 2 points on a plane my \$x = 2; my \$y = 1; #yang is the y-angle 0-360 i want to rotate by my \$yang = 45; #convert yang to radians \$yang = 3.14159265358979*\$yang/180; #rad is the radius of my sphere my \$rad = sqrt(\$x**2 + \$y**2); my \$x = cos(\$yang)*\$rad; my \$y = sin(\$yang)*\$rad; print "x=\$x\ny=\$y\n";