Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Cartesian co-ordinate rotation around an Axis

by fraizerangus (Sexton)
on Aug 08, 2011 at 14:16 UTC ( [id://919225]=perlquestion: print w/replies, xml ) 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) += @_; $angrad = 9.4; $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; $coefl1 = 1-cos($angrad); $coefl2 = sin($angrad); ($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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://919225]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-18 03:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found