/*

-Procedure frame_c ( Build a right handed coordinate frame )

-Abstract
 
    Given a vector x, this routine builds a right handed 
    orthonormal frame x,y,z where the output x is parallel to 
    the input x. 
 
-Copyright
 
   Copyright (1995), California Institute of Technology. 
   U.S. Government sponsorship acknowledged. 
 
-Required_Reading
 
   None. 
 
-Keywords
 
    AXES,  FRAME 
 
*/
   #include <math.h>
   #include "SpiceUsr.h"


   void frame_c ( SpiceDouble x[3],
                  SpiceDouble y[3],
                  SpiceDouble z[3] ) 

/*

-Brief_I/O
 
    VARIABLE  I/O  DESCRIPTION 
    --------  ---  ------------------------------------------------ 
    x         I/O  Input vector. A parallel unit vector on output. 
    y          O   Unit vector in the plane orthogonal to x. 
    z          O   Unit vector given by x X y. 
 
-Detailed_Input
 
 
    x      This vector is used to form the first vector of a 
           right-handed orthonormal triple. 
 
-Detailed_Output
 
    x, 
    y, 
    z      form a right handed orthonormal frame, where x is 
           now a unit vector parallel to the original input 
           vector x.  There are no special geometric properties 
           connected to y and z (other than that they complete the 
           right handed frame). 
 
-Parameters
 
    None. 
 
-Exceptions
 
   Error Free.
 
   1) If x on input is the zero vector the ``standard'' frame (ijk) 
      is returned. 
 
-Particulars
 
    Given an input vector x, this routine returns unit vectors x, 
    y, and z such that xyz forms a right-handed orthonormal frame 
    where the output x is parallel to the input x. 
 
    This routine is intended primarily to provide a basis for 
    the plane orthogonal to x.  There are no special properties 
    associated with y and z other than that the resulting xyz frame 
    is right handed and orthonormal.  There are an infinite 
    collection of pairs (y,z) that could be used to this end. 
    Even though for a given x, y and z are uniquely determined, users 
    should regard the pair (y,z) as a random selection from this 
    infinite collection. 
 
    For instance, when attempting to determine the locus of points 
    that make up the limb of a triaxial body, it is a straightforward 
    matter to determine the normal to the limb plane.  To find 
    the actual parametric equation of the limb one needs to have 
    a basis of the plane.  This routine can be used to get a basis 
    in which one can describe the curve and from which one can 
    then determine the principal axes of the limb ellipse. 
 
-Examples
 
    In addition to using a vector to construct a right handed frame 
    with the x-axis aligned with the input vector, one can construct 
    right handed frames with any of the axes aligned with the input 
    vector. 
 
    For example suppose we want a right hand frame xyz with the 
    z-axis aligned with some vector v.  Assign v to z 
 
          z[0] = v[0]; 
          z[1] = v[1]; 
          z[2] = v[2]; 
 
    Then call frame_c with the arguments x,y,z cycled so that z 
    appears first. 
 
          frame_c (z, x, y); 
 
    The resulting xyz frame will be orthonormal with z parallel 
    to the vector v. 
 
    To get an xyz frame with y parallel to v perform the following 
 
          y[0] = v[0]; 
          y[1] = v[1]; 
          y[2] = v[2]; 
 
          frame_c (y, z, x); 
 
-Restrictions
 
    None. 
 
-Files
 
    None. 
 
-Author_and_Institution
 
    W.L. Taber      (JPL) 
    I.M. Underwood  (JPL) 
 
-Literature_References
 
    None. 
 
-Version
 
   -CSPICE Version 1.0.0, 26-MAR-1999 (NJB)

-Index_Entries
 
   build a right handed coordinate frame 
 
-&
*/

{ /* Begin frame_c */

 
   SpiceDouble             a;
   SpiceDouble             b;
   SpiceDouble             c;
   SpiceDouble             f;
 
   SpiceInt                s0;
   SpiceInt                s1;
   SpiceInt                s2;

 
   /*
   First make x into a unit vector.
   */
   vhat_c ( x, x );
 
 
   /*
   We'll need the squares of the components of x in a bit.
   */
   a  =  x[0] * x[0];
   b  =  x[1] * x[1];
   c  =  x[2] * x[2];
 
 
   /*
   If X is zero, then just return the ijk frame.
   */
   if ( a+b+c == 0.0  )  
   {
      x[0] = 1.0;
      x[1] = 0.0;
      x[2] = 0.0;

      y[0] = 0.0;
      y[1] = 1.0;
      y[2] = 0.0;

      z[0] = 0.0;
      z[1] = 0.0;
      z[2] = 1.0;

      return;
   }
 
 
   /*
   If we make it this far, determine which component of x has the
   smallest magnitude.  This component will be zero in y. The other
   two components of x will put into y swapped with the sign of
   the first changed.  From there, z can have only one possible
   set of values which it gets from the smallest component
   of x, the non-zero components of y and the length of y.
   */
   
   if (  ( a <= b ) && ( a <= c )  )
   {
      f  = sqrt ( b + c );
      s0 = 0;
      s1 = 1;
      s2 = 2;
   }
   
   else if (  ( b <= a ) && ( b <= c )  )  
   {
      f  = sqrt ( a + c );
      s0 = 1;
      s1 = 2;
      s2 = 0;
   }
   
   else
   {
      f  = sqrt ( a + b );
      s0 = 2;
      s1 = 0;
      s2 = 1;
   }
 
   /*
   Note: by construction, f is the magnitude of the large components
   of x.  With this in mind, one can verify by inspection that x, y
   and z yield an orthonormal frame.  The right handedness follows
   from the assignment of values to s0, s1 and s2 (they are merely
   cycled from one case to the next).
   */
   
   y[s0]  =   0.0; 
   y[s1]  = - x[s2] / f;
   y[s2]  =   x[s1] / f;
   
   z[s0]  =   f;
   z[s1]  = - x[s0] * y[s2];
   z[s2]  =   x[s0] * y[s1];
 

} /* End frame_c */