@@ -536,6 +536,69 @@ def OA(cls, o, a):
536
536
"""
537
537
return cls (base .oa2r (o , a ), check = False )
538
538
539
+ @classmethod
540
+ def TwoVectors (cls , x = None , y = None , z = None ):
541
+ """
542
+ Construct a new SO(3) from any two vectors
543
+
544
+ :param x: new x-axis, defaults to None
545
+ :type x: str, array_like(3), optional
546
+ :param y: new y-axis, defaults to None
547
+ :type y: str, array_like(3), optional
548
+ :param z: new z-axis, defaults to None
549
+ :type z: str, array_like(3), optional
550
+
551
+ Create a rotation by defining the direction of two of the new
552
+ axes in terms of the old axes. Axes are denoted by strings ``"x"``,
553
+ ``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
554
+
555
+ The directions can also be specified by 3-element vectors, but these
556
+ must be orthogonal.
557
+
558
+ To create a rotation where the new frame has its x-axis in -z-direction
559
+ of the previous frame, and its z-axis in the x-direction of the previous
560
+ frame is::
561
+
562
+ >>> SO3.TwoVectors(x='-z', z='x')
563
+ """
564
+ def vval (v ):
565
+ if isinstance (v , str ):
566
+ sign = 1
567
+ if v [0 ] == '-' :
568
+ sign = - 1
569
+ v = v [1 :] # skip sign char
570
+ elif v [0 ] == '+' :
571
+ v = v [1 :] # skip sign char
572
+ if v [0 ] == 'x' :
573
+ v = [sign , 0 , 0 ]
574
+ elif v [0 ] == 'y' :
575
+ v = [0 , sign , 0 ]
576
+ elif v [0 ] == 'z' :
577
+ v = [0 , 0 , sign ]
578
+ return np .r_ [v ]
579
+ else :
580
+ return base .unitvec (base .getvector (v , 3 ))
581
+
582
+ if x is not None and y is not None and z is None :
583
+ # z = x x y
584
+ x = vval (x )
585
+ y = vval (y )
586
+ z = np .cross (x , y )
587
+
588
+ elif x is None and y is not None and z is not None :
589
+ # x = y x z
590
+ y = vval (y )
591
+ z = vval (z )
592
+ x = np .cross (y , z )
593
+
594
+ elif x is not None and y is None and z is not None :
595
+ # y = z x x
596
+ z = vval (z )
597
+ x = vval (x )
598
+ y = np .cross (z , x )
599
+
600
+ return cls (np .c_ [x , y , z ], check = False )
601
+
539
602
@classmethod
540
603
def AngleAxis (cls , theta , v , * , unit = 'rad' ):
541
604
r"""
0 commit comments