urotate.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:6k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* 
  2.  * MODULE: urotate.c
  3.  *
  4.  * FUNCTION:
  5.  * This module contains three different routines that compute rotation
  6.  * matricies and return these to user.
  7.  * Detailed description is provided below.
  8.  *
  9.  * HISTORY:
  10.  * Developed & written, Linas Vepstas, Septmeber 1991
  11.  * double precision port, March 1993
  12.  *
  13.  * DETAILED DESCRIPTION:
  14.  * This module contains three routines:
  15.  * --------------------------------------------------------------------
  16.  *
  17.  * void urot_about_axis (float m[4][4],      --- returned
  18.  *                       float angle,        --- input 
  19.  *                       float axis[3])      --- input
  20.  * Computes a rotation matrix.
  21.  * The rotation is around the the direction specified by the argument
  22.  * argument axis[3].  User may specify vector which is not of unit
  23.  * length.  The angle of rotation is specified in degrees, and is in the
  24.  * right-handed direction.
  25.  *
  26.  * void rot_about_axis (float angle,        --- input 
  27.  *                      float axis[3])      --- input
  28.  * Same as above routine, except that the matrix is multiplied into the
  29.  * GL matrix stack.
  30.  *
  31.  * --------------------------------------------------------------------
  32.  *
  33.  * void urot_axis (float m[4][4],      --- returned
  34.  *                 float omega,        --- input
  35.  *                 float axis[3])      --- input
  36.  * Same as urot_about_axis(), but angle specified in radians.
  37.  * It is assumed that the argument axis[3] is a vector of unit length.
  38.  * If it is not of unit length, the returned matrix will not be correct.
  39.  *
  40.  * void rot_axis (float omega,        --- input
  41.  *                float axis[3])      --- input
  42.  * Same as above routine, except that the matrix is multiplied into the
  43.  * GL matrix stack.
  44.  *
  45.  * --------------------------------------------------------------------
  46.  *
  47.  * void urot_omega (float m[4][4],       --- returned
  48.  *                  float omega[3])      --- input
  49.  * same as urot_axis(), but the angle is taken as the length of the
  50.  * vector omega[3]
  51.  *
  52.  * void rot_omega (float omega[3])      --- input
  53.  * Same as above routine, except that the matrix is multiplied into the
  54.  * GL matrix stack.
  55.  *
  56.  * --------------------------------------------------------------------
  57.  */
  58. #include <math.h>
  59. #include "gutil.h"
  60. /* Some <math.h> files do not define M_PI... */
  61. #ifndef M_PI
  62. #define M_PI 3.14159265358979323846
  63. #endif
  64.    
  65. /* ========================================================== */
  66. #ifdef __GUTIL_DOUBLE
  67. void urot_axis_d (double m[4][4],  /* returned */
  68.                   double omega,  /* input */
  69.                   double axis[3]) /* input */
  70. #else
  71. void urot_axis_f (float m[4][4],  /* returned */
  72.                   float omega,  /* input */
  73.                   float axis[3]) /* input */
  74. #endif
  75. {
  76.    double s, c, ssq, csq, cts;
  77.    double tmp;
  78.    /*
  79.     * The formula coded up below can be derived by using the 
  80.     * homomorphism between SU(2) and O(3), namely, that the
  81.     * 3x3 rotation matrix R is given by
  82.     *      t.R.v = S(-1) t.v S
  83.     * where
  84.     * t are the Pauli matrices (similar to Quaternions, easier to use)
  85.     * v is an arbitrary 3-vector
  86.     * and S is a 2x2 hermitian matrix:
  87.     *     S = exp ( i omega t.axis / 2 )
  88.     * 
  89.     * (Also, remember that computer graphics uses the transpose of R).
  90.     * 
  91.     * The Pauli matrices are:
  92.     * 
  93.     *  tx = (0 1)          ty = (0 -i)            tz = (1  0)
  94.     *       (1 0)               (i  0)                 (0 -1)
  95.     *
  96.     * Note that no error checking is done -- if the axis vector is not 
  97.     * of unit length, you'll get strange results.
  98.     */
  99.    tmp = (double) omega / 2.0;
  100.    s = sin (tmp);
  101.    c = cos (tmp);
  102.    ssq = s*s;
  103.    csq = c*c;
  104.    m[0][0] = m[1][1] = m[2][2] = csq - ssq;
  105.    ssq *= 2.0;
  106.    /* on-diagonal entries */
  107.    m[0][0] += ssq * axis[0]*axis[0];
  108.    m[1][1] += ssq * axis[1]*axis[1];
  109.    m[2][2] += ssq * axis[2]*axis[2];
  110.    /* off-diagonal entries */
  111.    m[0][1] = m[1][0] = axis[0] * axis[1] * ssq;
  112.    m[1][2] = m[2][1] = axis[1] * axis[2] * ssq;
  113.    m[2][0] = m[0][2] = axis[2] * axis[0] * ssq;
  114.    cts = 2.0 * c * s;
  115.    tmp = cts * axis[2];
  116.    m[0][1] += tmp;
  117.    m[1][0] -= tmp;
  118.    tmp = cts * axis[0];
  119.    m[1][2] += tmp;
  120.    m[2][1] -= tmp;
  121.    tmp = cts * axis[1];
  122.    m[2][0] += tmp;
  123.    m[0][2] -= tmp;
  124.    /* homogeneous entries */
  125.    m[0][3] = m[1][3] = m[2][3] = m[3][2] = m[3][1] = m[3][0] = 0.0;
  126.    m[3][3] = 1.0;
  127. }
  128. /* ========================================================== */
  129. #ifdef __GUTIL_DOUBLE
  130. void urot_about_axis_d (double m[4][4],  /* returned */
  131.                         double angle,  /* input */
  132.                         double axis[3]) /* input */
  133. #else
  134. void urot_about_axis_f (float m[4][4],  /* returned */
  135.                         float angle,  /* input */
  136.                         float axis[3]) /* input */
  137. #endif
  138. {
  139.    gutDouble len, ax[3];
  140.    angle *= M_PI/180.0; /* convert to radians */
  141.    /* renormalize axis vector, if needed */
  142.    len = axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2];
  143.    /* we can save some machine instructions by normalizing only
  144.     * if needed.  The compiler should be able to schedule in the 
  145.     * if test "for free". */
  146.    if (len != 1.0) {
  147.       len = (gutDouble) (1.0 / sqrt ((double) len));
  148.       ax[0] = axis[0] * len;
  149.       ax[1] = axis[1] * len;
  150.       ax[2] = axis[2] * len;
  151. #ifdef __GUTIL_DOUBLE
  152.       urot_axis_d (m, angle, ax);
  153. #else
  154.       urot_axis_f (m, angle, ax);
  155. #endif
  156.    } else {
  157. #ifdef __GUTIL_DOUBLE
  158.       urot_axis_d (m, angle, axis);
  159. #else
  160.       urot_axis_f (m, angle, axis);
  161. #endif
  162.    }
  163. }
  164. /* ========================================================== */
  165. #ifdef __GUTIL_DOUBLE
  166. void urot_omega_d (double m[4][4],  /* returned */
  167.                    double axis[3]) /* input */
  168. #else
  169. void urot_omega_f (float m[4][4],  /* returned */
  170.                    float axis[3]) /* input */
  171. #endif
  172. {
  173.    gutDouble len, ax[3];
  174.    /* normalize axis vector */
  175.    len = axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2];
  176.    len = (gutDouble) (1.0 / sqrt ((double) len));
  177.    ax[0] = axis[0] * len;
  178.    ax[1] = axis[1] * len;
  179.    ax[2] = axis[2] * len;
  180.    /* the amount of rotation is equal to the length, in radians */
  181. #ifdef __GUTIL_DOUBLE
  182.    urot_axis_d (m, len, ax);
  183. #else
  184.    urot_axis_f (m, len, ax);
  185. #endif
  186. }
  187. /* ======================= END OF FILE ========================== */