@@ -536,6 +536,69 @@ def OA(cls, o, a):
536536 """
537537 return cls (base .oa2r (o , a ), check = False )
538538
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+
539602 @classmethod
540603 def AngleAxis (cls , theta , v , * , unit = 'rad' ):
541604 r"""
0 commit comments