### Cartesian co-ordinate rotation around an Axis

by fraizerangus (Sexton)
 on Aug 08, 2011 at 14:16 UTC Need Help??
fraizerangus has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks I'm writing a Perl program to rotate some Cartesian co-ordinates around an axis (acting as a pivot) but the new cartesian co-ordinates are way out, (* is dot product and x cross product). Its broken down into 2 subroutines, can anyone give any pointers or tell me where I'm going wrong please?! many thanks in advance x
```
sub Axis {

#2 sets of cartesian XYZ co-ordinates on the axis
(\$Xl1, \$Yl1, \$Zl1, \$Xl2, \$Yl2, \$Zl2) = @_;

\$Axx = \$Xl1 - \$Xl2;
\$Axy = \$Yl1 - \$Yl2;
\$Axz = \$Zl1 - \$Zl2;

\$Vform = V(\$Axx,\$Axy,\$Axz);

\$eq = sqrt(\$Axx**2 + \$Axy**2 + \$Axz**2);

\$Unitvector = 1/\$eq * \$Vform;

return(\$Vform, \$Unitvector);

}

```
sub rotator {

(*xcord, *ycord, *zcord, *TotalnumberofCoords, \$lineUnitvector, \$Xline
+coord, \$Ylinecoord, \$Zlinecoord) = @_;

\$angle = 9.4;
\$translation = 0.4;

\$coefl1 = 1-cos(\$angle);
\$coefl2 = sin(\$angle);

(\$LUVx, \$LUVy, \$LUVz) = &VectorBreakdown(\$lineUnitvector);

for (my \$i = 0; \$i < @TotalnumberofCoords; \$i++) {

\$Xco[\$i] = \$xcord[\$i] - \$Xlinecoord;
\$Yco[\$i] = \$ycord[\$i] - \$Ylinecoord;
\$Zco[\$i] = \$zcord[\$i] - \$Zlinecoord;

\$Vector[\$i] = V(\$Xco[\$i], \$Yco[\$i], \$Zco[\$i]);

\$scal[\$i] = \$lineUnitvector * \$Vector[\$i];

\$f[\$i] = \$scal[\$i] * (\$lineUnitvector - \$Vector[\$i]);

\$f[\$i] = \$coefl1 * \$f[\$i];

\$s[\$i] = \$lineUnitvector x \$Vector[\$i];

\$s[\$i] = \$coefl2 * \$s[\$i];

(\$fx[\$i], \$fy[\$i], \$fz[\$i]) = &VectorBreakdown(\$f[\$i]);

(\$sx[\$i], \$sy[\$i], \$sz[\$i]) = &VectorBreakdown(\$s[\$i]);

\$xo[\$i] = \$xcord[\$i] + \$fx[\$i] + \$sx[\$i] + (\$transl * \$LUVx);

\$yo[\$i] = \$ycord[\$i] + \$fy[\$i] + \$sy[\$i] + (\$transl * \$LUVy);

\$zo[\$i] = \$zcord[\$i] + \$fz[\$i] + \$sz[\$i] + (\$transl * \$LUVz);

\$xo[\$i] = sprintf("%.3f", \$xo[\$i]);

\$yo[\$i] = sprintf("%.3f", \$yo[\$i]);

\$zo[\$i] = sprintf("%.3f", \$zo[\$i]);

}

return(\@xo, \@yo, \@zo);

}

Replies are listed 'Best First'.
Re: Cartesian co-ordinate rotation around an Axis
by FunkyMonk (Chancellor) on Aug 08, 2011 at 15:00 UTC
```\$angle = 9.4;
\$translation = 0.4;

\$coefl1 = 1-cos(\$angle);
\$coefl2 = sin(\$angle);

\$angle looks to be measured in degrees, whereas, cos, sin etc use radians.

</guess>

Re: Cartesian co-ordinate rotation around an Axis
by zentara (Archbishop) on Aug 08, 2011 at 14:54 UTC
You might find some clues by looking at a pure trig solution to the problem in Rotate a 3D vector. Maybe try to compare outputs for similar inputs, and see where your logic/math error is? One big error to watch out for is degree/rad mixups.

I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku ................... flash japh
Re: Cartesian co-ordinate rotation around an Axis
by moritz (Cardinal) on Aug 08, 2011 at 14:38 UTC

Start by posting a self-contained example that we can actually run, including the output and expected output.

You're using a lot of functions that you never declare, and neither tells us what they do, nor if you're certain that they do what you think they do (are they tested?).

Hi Sorry I was trying to simplify the code, here's the working example:
```#XYZ Coordinates of point 1 on the axis
\$Xl1 =   -3.902;
\$Yl1 =    9.353;
\$Zl1 =   -1.556;

#XYZ Coordinates of point 2 on the axis
\$Xl2 =  -47.470;
\$Yl2 =   -2.908;
\$Zl2 =  -17.596;

#XYZ Coordinates of a midpoint on the axis
\$XlM =  -20.284;
\$YlM =    4.548;
\$ZlM =   -7.261;

#XYZ data for all the cartesian co-ordinates to be rotated
@BMxcord = ( -18.731, -19.287, -20.545, -21.421, -19.594, -18.388, -18
+.784, -17.107, -20.681, -21.870, -23.239, -24.201, -21.604, -20.782,
+-19.827, -29.918, -29.341, -30.384, -31.579, -28.853, -29.953, -27.73
+5, -29.939, -30.878, -31.833, -33.036, -30.088, -29.320, -29.582, -28
+.457, -31.275, -31.996, -31.636, -30.654, -31.599, -30.210, -31.741,
+-32.428, -32.135, -30.851, -30.080, -33.281, -34.391, -35.291, -33.83
+4, -30.598, -29.385, -28.185, -27.196, -29.374, -28.083, -28.213, -26
+.851, -26.976, -28.281, -27.192, -27.020, -25.897, -27.447, -27.316,
+-26.408, -28.108, -28.126, -28.039, -27.400, -26.592, -29.432, -29.51
+5, -28.622, -30.990, -27.788, -27.250, -25.745, -25.000, -27.931, -27
+.790, -27.786, -27.688, -25.280, -23.859, -23.145, -22.033, -23.597,
+-24.127, -23.878, -23.247, -24.368, -23.758, -23.128, -22.938, -21.86
+4, -24.018, -23.448, -22.595, -23.733, -22.035, -23.167, -22.322, -23
+.984, -23.948, -22.987, -22.261, -25.376, -26.289, -25.329, -27.739,
+-22.959, -22.088, -20.683, -19.718, -22.774, -22.821, -24.225, -20.53
+1, -19.203, -18.510, -17.411, -19.234, -19.923, -19.918, -20.834, -18
+.981);
@BMycord = (  -0.135,  -1.473,  -1.396,  -0.553,  -2.172,  -2.409,  -3
+.016,  -3.128,  -2.300,  -2.245,  -2.337,  -1.730,  -3.351,  -4.304,
+ -3.453,  -5.632,  -6.925,  -7.735,  -7.459,  -7.732,  -8.003,  -6.95
+8,  -8.747,  -9.551, -10.352, -10.461, -10.510,  -9.797,  -8.595, -10
+.451, -10.936, -11.805, -11.519, -10.802, -13.294, -13.487, -13.642,
+-12.075, -11.978, -12.716, -12.298, -12.532, -11.563, -12.246, -10.23
+2, -13.835, -14.574, -13.675, -13.667, -15.839, -16.600, -17.957, -18
+.613, -20.031, -12.904, -11.993, -10.918, -10.550, -11.319, -12.286,
+-13.135, -12.169, -10.396,  -9.393,  -9.998,  -9.339,  -8.849,  -7.90
+9,  -6.677,  -7.549, -11.220, -11.886, -12.043, -11.783, -13.252, -13
+.802, -13.011, -15.033, -12.456, -12.616, -11.284, -11.206, -13.346,
+-14.755, -15.578, -15.119, -16.813, -10.226,  -8.913,  -8.514,  -8.03
+0,  -7.892,  -6.509,  -6.140,  -5.581,  -4.860,  -4.280,  -3.934,  -8
+.686,  -8.313,  -9.148,  -8.598,  -8.459,  -7.371,  -8.392,  -7.521,
+-10.461, -11.246, -11.497, -11.631, -12.556, -13.385, -12.310, -11.49
+0, -11.666, -10.387, -10.096, -12.599, -13.930, -14.829, -15.660, -14
+.717);
@BMzcord = ( -11.272, -11.499, -12.335, -12.114, -10.170,  -9.308,  -7
+.671,  -6.966, -13.307, -14.145, -13.447, -13.882, -15.184, -14.461,
+-13.654, -11.352, -11.736, -12.500, -12.407, -10.500,  -9.622,  -9.75
+5, -13.241, -14.011, -13.136, -13.408, -14.903, -15.991, -16.229, -16
+.622, -12.094, -11.190,  -9.746,  -9.448, -11.440, -11.070, -12.949,
+ -8.840,  -7.411,  -7.074,  -6.199,  -6.554,  -6.233,  -5.196,  -5.63
+0,  -7.746,  -7.494,  -7.804,  -7.069,  -8.366,  -8.281,  -8.920,  -9
+.055,  -9.478,  -8.884,  -9.228,  -8.147,  -7.798, -10.586, -11.759,
+-11.716, -12.711,  -7.647,  -6.586,  -5.331,  -4.682,  -6.290,  -5.07
+9,  -5.324,  -4.806,  -4.974,  -3.803,  -3.924,  -2.971,  -3.645,  -2
+.257,  -1.288,  -2.135,  -5.100,  -5.309,  -5.250,  -4.727,  -6.625,
+ -6.529,  -7.770,  -8.724,  -7.760,  -5.757,  -5.673,  -4.211,  -3.82
+8,  -6.380,  -6.415,  -7.449,  -5.409,  -7.485,  -5.431,  -6.480,  -3
+.405,  -2.000,  -1.168,  -0.347,  -1.390,  -1.967,   0.151,  -1.574,
+ -1.364,  -0.490,  -1.042,  -0.257,  -0.095,  -1.247,   0.420,  -2.35
+8,  -2.942,  -3.385,  -2.922,  -4.139,  -3.875,  -5.113,  -5.290,  -5
+.920);

#Array size for for loop
\$BMatoms = 122;

(\$LineVform, \$LineUnitvector) = &Haxell(\$Xl1, \$Yl1, \$Zl1, \$Xl2, \$Yl2,
+\$Zl2);

(*xo, *yo, *zo) = &rotator(\@BMxcord, \@BMycord, \@BMzcord, \$BMatoms,
+\$LineUnitvector, \$XlM, \$YlM, \$ZlM);

######################
#SUBROUTINES
######################

sub Haxell {

(\$Xl1, \$Yl1, \$Zl1, \$Xl2, \$Yl2, \$Zl2) = @_;

\$Axx = \$Xl1 - \$Xl2;
\$Axy = \$Yl1 - \$Yl2;
\$Axz = \$Zl1 - \$Zl2;

\$Vform = V(\$Axx,\$Axy,\$Axz);

\$vector = sqrt(\$Axx**2 + \$Axy**2 + \$Axz**2);

\$Unitvector = 1/\$vector * \$Vform;

return(\$Vform, \$Unitvector);

}

sub rotator {

use Math::Vector::Real;

(*xcord, *ycord, *zcord, \$BMatoms, \$LineUnitvector, \$XlM, \$YlM, \$ZlM)
+= @_;

\$transl = 0.4;

my \$coefl1;
my \$coefl2;
my @Xco;
my @Yco;
my @Zco;
my @Vector;
my @scal;
my @f;
my @s;
my @fx;
my @fy;
my @fz;
my @sx;
my @sy;
my @sz;
my @xo;
my @yo;
my @zo;

(\$LUVx, \$LUVy, \$LUVz) = &VectorBreakdown(\$LineUnitvector);

for (my \$i = 0; \$i < \$BMatoms; \$i++) {

\$Xco[\$i] = \$xcord[\$i] - \$XlM;
\$Yco[\$i] = \$ycord[\$i] - \$YlM;
\$Zco[\$i] = \$zcord[\$i] - \$ZlM;

\$Vector[\$i] = V(\$Xco[\$i], \$Yco[\$i], \$Zco[\$i]);

\$scal[\$i] = \$LineUnitvector * \$Vector[\$i];

\$f[\$i] = \$scal[\$i] * (\$LineUnitvector - \$Vector[\$i]);

\$f[\$i] = \$coefl1 * \$f[\$i];

\$s[\$i] = \$LineUnitvector x \$Vector[\$i];

\$s[\$i] = \$coefl2 * \$s[\$i];

(\$fx[\$i], \$fy[\$i], \$fz[\$i]) = &VectorBreakdown(\$f[\$i]);

(\$sx[\$i], \$sy[\$i], \$sz[\$i]) = &VectorBreakdown(\$s[\$i]);

\$xo[\$i] = \$xcord[\$i] + \$fx[\$i] + \$sx[\$i] + (\$transl * \$LUVx);

\$yo[\$i] = \$ycord[\$i] + \$fy[\$i] + \$sy[\$i] + (\$transl * \$LUVy);

\$zo[\$i] = \$zcord[\$i] + \$fz[\$i] + \$sz[\$i] + (\$transl * \$LUVz);

\$xo[\$i] = sprintf("%.3f", \$xo[\$i]);

\$yo[\$i] = sprintf("%.3f", \$yo[\$i]);

\$zo[\$i] = sprintf("%.3f", \$zo[\$i]);

}

return(\@xo, \@yo, \@zo);

}

sub VectorBreakdown {

(\$complete) = @_;

my @personal = ();

@personal = split(/,/, \$complete);

\$personal[0] = substr(\$personal[0], 1);

\$personal[2] = substr(\$personal[2], 0, -1);

return (\$personal[0], \$personal[1], \$personal[2]);

}

I have difficulty understanding your initial post as well as your clarifying post. If you want to rotate you typically need a Rotation matrix R. You represent the point you want to rotate by a vector v and perform the multiplication R.v. This is fairly straightforward. CPAN is your friend: Math::VectorReal contains an example of rotating a vector with a rotation matrix.

HTH

Harry

Create A New User
Node Status?
node history
Node Type: perlquestion [id://919225]
Approved by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2018-05-24 23:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
World peace can best be achieved by:

Results (181 votes). Check out past polls.

Notices?