@@ -701,54 +701,41 @@ def rotation_matrix(angle, axis='z', unit=None):
701
701
rmat: `numpy.matrix`
702
702
A unitary rotation matrix.
703
703
"""
704
- # TODO: This doesn't handle arrays of angles
705
-
706
704
if unit is None :
707
705
unit = u .degree
708
706
709
707
angle = Angle (angle , unit = unit )
710
708
709
+ s = np .sin (angle )
710
+ c = np .cos (angle )
711
+
712
+ # use optimized implementations for x/y/z
711
713
if axis == 'z' :
712
- s = np .sin (angle )
713
- c = np .cos (angle )
714
714
return np .matrix (((c , s , 0 ),
715
715
(- s , c , 0 ),
716
716
(0 , 0 , 1 )))
717
717
elif axis == 'y' :
718
- s = np .sin (angle )
719
- c = np .cos (angle )
720
718
return np .matrix (((c , 0 , - s ),
721
719
(0 , 1 , 0 ),
722
720
(s , 0 , c )))
723
721
elif axis == 'x' :
724
- s = np .sin (angle )
725
- c = np .cos (angle )
726
722
return np .matrix (((1 , 0 , 0 ),
727
723
(0 , c , s ),
728
724
(0 , - s , c )))
729
725
else :
730
- x , y , z = axis
731
- w = np .cos (angle / 2 )
732
-
733
- # normalize
734
- if w == 1 :
735
- x = y = z = 0
736
- else :
737
- l = np .sqrt ((x * x + y * y + z * z ) / (1 - w * w ))
738
- x /= l
739
- y /= l
740
- z /= l
726
+ axis = np .asarray (axis )
727
+ axis = axis / np .sqrt ((axis * axis ).sum ())
741
728
742
- wsq = w * w
743
- xsq = x * x
744
- ysq = y * y
745
- zsq = z * z
746
- return np . matrix ((( wsq + xsq - ysq - zsq , 2 * x * y - 2 * w * z , 2 * x * z + 2 * w * y ) ,
747
- ( 2 * x * y + 2 * w * z , wsq - xsq + ysq - zsq , 2 * y * z - 2 * w * x ),
748
- ( 2 * x * z - 2 * w * y , 2 * y * z + 2 * w * x , wsq - xsq - ysq + zsq )) )
729
+ R = np . diag (( c , c , c ))
730
+ R += np . outer ( axis , axis ) * ( 1. - c )
731
+ axis *= s
732
+ R += np . array ([[ 0. , axis [ 2 ], - axis [ 1 ]],
733
+ [ - axis [ 2 ], 0. , axis [ 0 ]] ,
734
+ [ axis [ 1 ], - axis [ 0 ], 0. ]])
735
+ return R . view ( np . matrix )
749
736
750
737
751
- def angle_axis (matrix , unit = None ):
738
+ def angle_axis (matrix ):
752
739
"""
753
740
Computes the angle of rotation and the rotation axis for a given rotation
754
741
matrix.
@@ -758,29 +745,20 @@ def angle_axis(matrix, unit=None):
758
745
matrix : array-like
759
746
A 3 x 3 unitary rotation matrix.
760
747
761
- unit : UnitBase
762
- The output unit. If `None`, the output unit is degrees.
763
-
764
748
Returns
765
749
-------
766
750
angle : `Angle`
767
751
The angle of rotation for this matrix.
768
752
769
753
axis : array (length 3)
770
- The axis of rotation for this matrix.
754
+ The (normalized) axis of rotation for this matrix.
771
755
"""
772
- # TODO: This doesn't handle arrays of angles
773
-
774
756
m = np .asmatrix (matrix )
775
757
if m .shape != (3 , 3 ):
776
758
raise ValueError ('matrix is not 3x3' )
777
759
778
- angle = np .acos ((m [0 , 0 ] + m [1 , 1 ] + m [2 , 2 ] - 1 ) / 2 )
779
- denom = np .sqrt (2 * ((m [2 , 1 ] - m [1 , 2 ]) + (m [0 , 2 ] - m [2 , 0 ]) + (m [1 , 0 ] - m [0 , 1 ])))
780
- axis = np .array ((m [2 , 1 ] - m [1 , 2 ], m [0 , 2 ] - m [2 , 0 ], m [1 , 0 ] - m [0 , 1 ])) / denom
781
- axis /= np .sqrt (np .sum (axis ** 2 ))
760
+ axis = np .array ((m [2 , 1 ] - m [1 , 2 ], m [0 , 2 ] - m [2 , 0 ], m [1 , 0 ] - m [0 , 1 ]))
761
+ r = np .sqrt ((axis * axis ).sum ())
762
+ angle = np .arctan2 (r , np .trace (m ) - 1 )
782
763
783
- angle = Angle (angle , u .radian )
784
- if unit is None :
785
- unit = u .degree
786
- return angle .to (unit ), axis
764
+ return Angle (angle , u .radian ), - axis / r
0 commit comments