Exemple #1
0
/*
   function getparams will get the trnsform  parameters from a 
   transformation matrix 'tran' (that has already had the translation 
   componants removed).
   in description below, I assume that tran is a forward xform, from 
   native space to talairach space.
   I assume that trans is a 4x4 homogeneous matrix, with the 
   principal axis stored in the upper left 3x3 matrix.  The first col
   of tran represents is the coordinate of (1,0,0)' mapped through the
   transformation.  (this means  vec2 = tran * vec1).
  
   trans = [scale][shear][rot]
         = [scale][shear][rz][ry][rx];

   the shear matrix is constrained to be of the form:
     shear = [1 0 0 0
              f 1 0 0
              g h 1 0
              0 0 0 1];
     where f,g,h can take on any value.

   the scale matrix is constrained to be of the form:
     scale = [sx 0  0  0
              0  sy 0  0
              0  0  sz 0
              0  0  0  1];
     where sx,sy,sz must be positive.
   
  all rotations are assumed to be in the range -pi/2..pi/2

  the rotation angles are returned as radians and are applied 
  counter clockwise, when looking down the axis (from the positive end
  towards the origin).

  trans is assumed to be invertible.

  i assume a coordinate system:
             ^ y
             |
             |
             |
             |_______> x
            /
           /
          /z  (towards the viewer).

  
  
  procedure: 
          start with t = inv(tran) (after removing translation from tran )
  
          t = inv(r)*inv(sh)*inv(sc)
                  t maps the talairach space unit vectors into native
                space, which means that the columns of T are the
                direction cosines of these vectors x,y,z

   (1)  the length of the vectors x,y,z give the inverse scaling
        parameters:
             sx = 1/norm(x); sy = 1/norm(y); sz = 1/norm(z);

   (2)  with the constraints on the form of sh above, inv(sh) has the
        same form.  let inv(sh) be as above in terms of a,b and c.
          inv(sh) = [1 0 0 0; a 1 0 0; b c 1 0; 0 0 0 1];

        for c: project y onto z and normalize:

                  /     |y.z|^2     \(1/2)
             c = <  ---------------  >
                  \ |y|^2 - |y.z|^2 /

        for b: project x onto z and normalize

                  /        |x.z|^2        \(1/2)
             b = <  ---------------------  >
                  \ |x|^2 - |x.z|^2 - a^2 /
     
          where a is the projection of x onto the coordinate sys Y axis.

        for a: project x onto z and normalize
           a is taken from (b) above, and normalized... see below

  (3) rots are returned by getrots by giving the input transformation:
        rot_mat = [inv(sh)][inv(sc)][trans]

  (4) once completed, the parameters of sx,sy,sz and a,b,c are
      adjusted so that they maintain the matrix contraints above.


*/
VIO_BOOL extract2_parameters_from_matrix(VIO_Transform *trans,
                                               double *center,
                                               double *translations,
                                               double *scales,
                                               double *shears,
                                               double *rotations)
{
  int 
    i,j;

  float 
    n1,n2,
    magnitude, magz, magx, magy, ai,bi,ci,scalar,a1,
    **center_of_rotation,
    **result,
    **unit_vec,
    *ang,*tmp,**x,**y,**z, **nz, **y_on_z, **ortho_y,
    **xmat,**T,**Tinv,**C,**Sinv,
    **R,**SR,**SRinv,**Cinv,**TMP1,**TMP2;

  ALLOC2D(xmat  ,5,5); nr_identf(xmat ,1,4,1,4);
  ALLOC2D(TMP1  ,5,5); nr_identf(TMP1 ,1,4,1,4);
  ALLOC2D(TMP2  ,5,5); nr_identf(TMP2 ,1,4,1,4);
  ALLOC2D(Cinv  ,5,5); nr_identf(Cinv ,1,4,1,4);
  ALLOC2D(SR    ,5,5); nr_identf(SR   ,1,4,1,4);
  ALLOC2D(SRinv ,5,5); nr_identf(SRinv,1,4,1,4);
  ALLOC2D(Sinv  ,5,5); nr_identf(Sinv ,1,4,1,4); 
  ALLOC2D(T     ,5,5); nr_identf(T    ,1,4,1,4);
  ALLOC2D(Tinv  ,5,5); nr_identf(Tinv ,1,4,1,4);
  ALLOC2D(C     ,5,5); nr_identf(C    ,1,4,1,4);
  ALLOC2D(R     ,5,5); nr_identf(R    ,1,4,1,4);

  ALLOC2D(center_of_rotation ,5,5);        /* make column vectors */
  ALLOC2D(result             ,5,5);
  ALLOC2D(unit_vec           ,5,5);
  ALLOC2D(x                  ,5,5);
  ALLOC2D(y                  ,5,5);
  ALLOC2D(z                  ,5,5);
  ALLOC2D(nz                 ,5,5);
  ALLOC2D(y_on_z             ,5,5);
  ALLOC2D(ortho_y            ,5,5);

  ALLOC(tmp ,4);
  ALLOC(ang ,4);

  for(i=0; i<=3; i++)        /* copy the input matrix */
    for(j=0; j<=3; j++)
      xmat[i+1][j+1] = (float)Transform_elem(*trans,i,j);

  /* -------------DETERMINE THE TRANSLATION FIRST! ---------  */

                                /* see where the center of rotation is displaced... */

  FILL_NR_COLVEC( center_of_rotation, center[0], center[1], center[2] );


  invertmatrix(4, xmat, TMP1);        /* get inverse of the matrix */

  matrix_multiply( 4, 4, 1, xmat, center_of_rotation, result); /* was TMP! in place of xmat */

  SUB_NR_COLVEC( result, result, center_of_rotation );

  for(i=0; i<=2; i++) 
    translations[i] = result[i+1][1];

  /* -------------NOW GET THE SCALING VALUES! ----------------- */

  for(i=0; i<=2; i++) 
    tmp[i+1] = -translations[i];
  translation_to_homogeneous(3, tmp, Tinv); 

  for(i=0; i<=2; i++) 
    tmp[i+1] = center[i];
  translation_to_homogeneous(3, tmp, C); 
  for(i=0; i<=2; i++) 
    tmp[i+1] = -center[i];
  translation_to_homogeneous(3, tmp, Cinv); 


  matrix_multiply(4,4,4, xmat, C, TMP1);    /* get scaling*shear*rotation matrix */


  matrix_multiply(4,4,4, Tinv, TMP1, TMP1);


  matrix_multiply(4,4,4, Cinv, TMP1,    SR);

  invertmatrix(4, SR, SRinv);        /* get inverse of scaling*shear*rotation */

                                /* find each scale by mapping a unit vector backwards,
                                   and finding the magnitude of the result. */
  FILL_NR_COLVEC( unit_vec, 1.0, 0.0, 0.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[0] = 1/magnitude;
    Sinv[1][1] = magnitude;
  }
  else {
    scales[0] = 1.0;
    Sinv[1][1] = 1.0;
  }

  FILL_NR_COLVEC( unit_vec, 0.0, 1.0, 0.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[1] = 1/magnitude;
    Sinv[2][2] = magnitude;
  }
  else {
    scales[1]  = 1.0;
    Sinv[2][2] = 1.0;
  }

  FILL_NR_COLVEC( unit_vec, 0.0, 0.0, 1.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[2] = 1/magnitude;
    Sinv[3][3] = magnitude;
  }
  else {
    scales[2] = 1.0;
    Sinv[3][3] = 1.0;
  }

  /* ------------NOW GET THE SHEARS, using the info from above ----- */

  /* SR contains the [scale][shear][rot], must multiply [inv(scale)]*SR
     to get shear*rot. */

                                /* make [scale][rot] */
  matrix_multiply(4,4, 4, Sinv, SR,  TMP1);

                                /* get inverse of [scale][rot] */
  invertmatrix(4, TMP1, SRinv);        


  FILL_NR_COLVEC(x, SRinv[1][1], SRinv[2][1], SRinv[3][1]);
  FILL_NR_COLVEC(y, SRinv[1][2], SRinv[2][2], SRinv[3][2]);
  FILL_NR_COLVEC(z, SRinv[1][3], SRinv[2][3], SRinv[3][3]);



                                /* get normalized z direction  */
  magz = MAG_NR_COLVEC(z);
  SCALAR_MULT_NR_COLVEC( nz, z, 1/magz );

                                /* get a direction perpendicular 
                                   to z, in the yz plane.  */
  scalar = DOTSUM_NR_COLVEC(  y, nz );
  SCALAR_MULT_NR_COLVEC( y_on_z, nz, scalar );

  SUB_NR_COLVEC( result, y, y_on_z ); /* result = y - y_on_z */
  scalar = MAG_NR_COLVEC( result);     /* ortho_y = result ./ norm(result)  */
  SCALAR_MULT_NR_COLVEC( ortho_y, result, 1/scalar);


                                /* GET C for the skew matrix */

  scalar = DOTSUM_NR_COLVEC( y, nz ); /* project y onto z */
  magy   = MAG_NR_COLVEC(y);
  ci = scalar / sqrt((double)( magy*magy - scalar*scalar)) ;
                                /* GET B for the skew matrix */

                                /*    first need a1 */

  a1     = DOTSUM_NR_COLVEC( x, ortho_y ); /* project x onto ortho_y */
  magx   = MAG_NR_COLVEC(x);

                                /*    now get B  */

  scalar = DOTSUM_NR_COLVEC( x, nz );
  bi = scalar / sqrt((double)( magx*magx - scalar*scalar - a1*a1)) ;

                                /* GET A for skew matrix  */

  ai = a1 / sqrt((double)( magx*magx - scalar*scalar - a1*a1));

                                /* normalize the inverse shear parameters.
                                   so that there is no scaling in the matrix 
                                   (all scaling is already accounted for 
                                   in sx,sy and sz. */

  n1 = sqrt((double)(1 + ai*ai + bi*bi));
  n2 = sqrt((double)(1 + ci*ci));

  ai = ai / n1;
  bi = bi / n1;
  ci = ci / n2;

                                /* ai,bi,c1 now contain the parameters for 
                                   the inverse NORMALIZED shear matrix 
                                   (i.e., norm(col_i) = 1.0). */

  
  /* ------------NOW GET THE ROTATION ANGLES!----- */

                                  /*  since SR = [scale][shear][rot], then
                                    rot = [inv(shear)][inv(scale)][SR] */

  nr_identf(TMP1 ,1,4,1,4);        /* make inverse scale matrix */
  TMP1[1][1] = 1/scales[0];
  TMP1[2][2] = 1/scales[1];
  TMP1[3][3] = 1/scales[2];

  nr_identf(TMP2 ,1,4,1,4);        /* make_inverse normalized shear matrix */
  TMP2[1][1] = sqrt((double)(1 - ai*ai - bi*bi));
  TMP2[2][2] = sqrt((double)(1 - ci*ci));
  TMP2[2][1] = ai;
  TMP2[3][1] = bi;
  TMP2[3][2] = ci;


                                /* extract rotation matrix */
  matrix_multiply(4,4, 4, TMP2, TMP1, T);
  matrix_multiply(4,4, 4, T,    SR,   R);

                                /* get rotation angles */
  if (!rotmat_to_ang(R, ang)) {
    (void)fprintf(stderr,"Cannot convert R to radians!");
    printmatrix(3,3,R);
    return(FALSE);
  }

  for(i=0; i<=2; i++)
    rotations[i] = ang[i+1];

  /* ------------NOW ADJUST THE SCALE AND SKEW PARAMETERS ------------ */

  invertmatrix(4, T, Tinv);        /* get inverse of the matrix */
  

  scales[0] = Tinv[1][1];
  scales[1] = Tinv[2][2];
  scales[2] = Tinv[3][3];
  shears[0] = Tinv[2][1]/scales[1] ;
  shears[1] = Tinv[3][1]/scales[2] ;
  shears[2] = Tinv[3][2]/scales[2] ;
  

  FREE2D(xmat);
  FREE2D(TMP1);
  FREE2D(TMP2);
  FREE2D(Cinv);
  FREE2D(SR  );
  FREE2D(SRinv);
  FREE2D(Sinv);
  FREE2D(T   );
  FREE2D(Tinv);
  FREE2D(C   );
  FREE2D(R   );
  
  FREE2D(center_of_rotation);
  FREE2D(result            );
  FREE2D(unit_vec          );
  FREE2D(x                 );
  FREE2D(y                 );
  FREE2D(z                 );
  FREE2D(nz                );
  FREE2D(y_on_z            );
  FREE2D(ortho_y           );

  FREE(ang);
  FREE(tmp);

  return(TRUE);
}
Exemple #2
0
VIO_BOOL extract_parameters_from_matrix(VIO_Transform *trans,
                                              double *center,
                                              double *translations,
                                              double *scales,
                                              double *shears,
                                              double *rotations)
{
  int 
    i,j;

  float 
    magnitude,
    **center_of_rotation,
    **result,
    **unit_vec,
    *ang,*tmp,
    **xmat,**T,**Tinv,**C,**Sinv,**R,**SR,**SRinv,**Cinv,**TMP1,**TMP2;

  ALLOC2D(xmat  ,5,5); nr_identf(xmat ,1,4,1,4);
  ALLOC2D(TMP1  ,5,5); nr_identf(TMP1 ,1,4,1,4);
  ALLOC2D(TMP2  ,5,5); nr_identf(TMP2 ,1,4,1,4);
  ALLOC2D(Cinv  ,5,5); nr_identf(Cinv ,1,4,1,4);
  ALLOC2D(SR    ,5,5); nr_identf(SR   ,1,4,1,4);
  ALLOC2D(SRinv ,5,5); nr_identf(SRinv,1,4,1,4);
  ALLOC2D(Sinv  ,5,5); nr_identf(Sinv ,1,4,1,4); 
  ALLOC2D(T     ,5,5); nr_identf(T    ,1,4,1,4);
  ALLOC2D(Tinv  ,5,5); nr_identf(Tinv ,1,4,1,4);
  ALLOC2D(C     ,5,5); nr_identf(C    ,1,4,1,4);
  ALLOC2D(R     ,5,5); nr_identf(R    ,1,4,1,4);

  ALLOC2D(center_of_rotation ,5,5);        /* make column vectors */
  ALLOC2D(result             ,5,5);
  ALLOC2D(unit_vec           ,5,5);

  ALLOC(tmp ,4);
  ALLOC(ang ,4);


  for(i=0; i<=3; i++)        /* copy the input matrix */
    for(j=0; j<=3; j++)
      xmat[i+1][j+1] = (float)Transform_elem(*trans,i,j);

  

  /* -------------DETERMINE THE TRANSLATION FIRST! ---------  */

                                /* see where the center of rotation is displaced... */

  FILL_NR_COLVEC( center_of_rotation, center[0], center[1], center[2] );


  invertmatrix(4, xmat, TMP1);        /* get inverse of the matrix */

  matrix_multiply( 4, 4, 1, xmat, center_of_rotation, result); /* was TMP! in place of xmat */

  SUB_NR_COLVEC( result, result, center_of_rotation );

  for(i=0; i<=2; i++) 
    translations[i] = result[i+1][1];

  /* -------------NOW GET THE SCALING VALUES! ----------------- */

  for(i=0; i<=2; i++) 
    tmp[i+1] = -translations[i];
  translation_to_homogeneous(3, tmp, Tinv); 

  for(i=0; i<=2; i++) 
    tmp[i+1] = center[i];
  translation_to_homogeneous(3, tmp, C); 
  for(i=0; i<=2; i++) 
    tmp[i+1] = -center[i];
  translation_to_homogeneous(3, tmp, Cinv); 


  matrix_multiply(4,4,4, xmat, C, TMP1);    /* get scaling*rotation matrix */


  matrix_multiply(4,4,4, Tinv, TMP1, TMP1);


  matrix_multiply(4,4,4, Cinv, TMP1,    SR);

  invertmatrix(4, SR, SRinv);        /* get inverse of scaling*rotation */

                                /* find each scale by mapping a unit vector backwards,
                                   and finding the magnitude of the result. */
  FILL_NR_COLVEC( unit_vec, 1.0, 0.0, 0.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[0] = 1/magnitude;
    Sinv[1][1] = magnitude;
  }
  else {
    scales[0] = 1.0;
    Sinv[1][1] = 1.0;
  }

  FILL_NR_COLVEC( unit_vec, 0.0, 1.0, 0.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[1] = 1/magnitude;
    Sinv[2][2] = magnitude;
  }
  else {
    scales[1]  = 1.0;
    Sinv[2][2] = 1.0;
  }

  FILL_NR_COLVEC( unit_vec, 0.0, 0.0, 1.0 );
  matrix_multiply( 4, 4, 1, SRinv, unit_vec, result);
  magnitude = MAG_NR_COLVEC( result );
  if (magnitude != 0.0) {
    scales[2] = 1/magnitude;
    Sinv[3][3] = magnitude;
  }
  else {
    scales[2] = 1.0;
    Sinv[3][3] = 1.0;
  }

  /* ------------NOW GET THE ROTATION ANGLES!----- */

                                /* extract rotation matrix */
  matrix_multiply(4,4, 4, Sinv, SR,   R);

                                /* get rotation angles */
  if (!rotmat_to_ang(R, ang)) {
    (void)fprintf(stderr,"Cannot convert R to radians!");
    printmatrix(3,3,R);
    return(FALSE);
  }

  for(i=0; i<=2; i++)
    rotations[i] = ang[i+1];


  FREE2D(xmat);
  FREE2D(TMP1);
  FREE2D(TMP2);
  FREE2D(Cinv);
  FREE2D(SR  );
  FREE2D(SRinv);
  FREE2D(Sinv);
  FREE2D(T   );
  FREE2D(Tinv);
  FREE2D(C   );
  FREE2D(R   );
  
  FREE2D(center_of_rotation);
  FREE2D(result            );
  FREE2D(unit_vec          );

  FREE(ang);
  FREE(tmp);

  return(TRUE);
}
Exemple #3
0
/* ----------------------------- MNI Header -----------------------------------
@NAME       : build_inverse_transformation_matrix_quater
@INPUT      : center, translations, scales, quaternions
@OUTPUT     : the inverse linear transformation matrix of mat:
                since mat = (T)(C)(SH)(S)(R)(-C), then

                invmat = (C)(inv(r))(inv(S))(inv(SH))(-C)(-T)

@RETURNS    : nothing
@DESCRIPTION: 
               the matrix is to be  PREmultiplied with a vector (mat*vec)
               when used in the application
               same as build_inverse_transformation_matrix but with quaternions
@METHOD     : 
@GLOBALS    : 
@CALLS      : 
@CREATED    : Thr Apr 18 10:45:56 EST 2002 pln
@MODIFIED   : 
---------------------------------------------------------------------------- */
void build_inverse_transformation_matrix_quater(VIO_Transform *trans,
                                                       double *center,
                                                       double *translations,
                                                       double *scales,
                                                       double *shears,
                                                       double *quaternions)
{
  float
    **T,
    **SH,
    **S,
    **R,
    **C,
    **T1,
    **T2,
    **T3,
    **T4;

  int
    i,j;
  
  ALLOC2D(T   ,5,5);
  ALLOC2D(SH  ,5,5);
  ALLOC2D(S   ,5,5);
  ALLOC2D(R   ,5,5);
  ALLOC2D(C   ,5,5);
  ALLOC2D(T1  ,5,5);
  ALLOC2D(T2  ,5,5);
  ALLOC2D(T3  ,5,5);
  ALLOC2D(T4  ,5,5);
  
                                /* invmat = (C)(inv(r))(inv(S))(inv(SH))(-C)(-T)
                                   mat = (T)(C)(SH)(S)(R)(-C) */

  nr_identf(T,1,4,1,4);                     /* make (-T)(-C) */
  for(i=0; i<3; i++) {
    T[1+i][4] = -translations[i] - center[i];                
  }

  

  build_rotmatrix(T1,quaternions); /* make rotation matrix from quaternions */
  transpose(4,4,T1,R);
  

  make_shears(T1,shears);        /* make shear rotation matrix */
  invertmatrix(4, T1, SH);        /* get inverse of the matrix */

                                /* make scaling matrix */
  nr_identf(S,1,4,1,4);                   
  for(i=0; i<3; i++) {
    if (scales[i] != 0.0)
      S[1+i][1+i] = 1/scales[i];
    else
      S[1+i][1+i] = 1.0;
  }

  nr_identf(C,1,4,1,4);      /* make center          */
  for(i=0; i<3; i++) {
    C[1+i][4] = center[i];                
  }

  nr_multf(C,1,4,1,4,  R ,1,4,1,4, T1 );  
  nr_multf(T1,1,4,1,4, SH,1,4,1,4, T2 );  
  nr_multf(T2,1,4,1,4, S ,1,4,1,4, T3 );  
  nr_multf(T3,1,4,1,4, T ,1,4,1,4, T4 );  

  for(i=0; i<4; i++)
    for(j=0; j<4; j++)
      Transform_elem(*trans, i, j ) = T4[i+1][j+1];

  FREE2D(T    );
  FREE2D(SH   );
  FREE2D(S    );
  FREE2D(R    );
  FREE2D(C );
  FREE2D(T1   );
  FREE2D(T2   );
  FREE2D(T3   );
  FREE2D(T4   );
}
Exemple #4
0
void build_transformation_matrix_quater(VIO_Transform *trans,
                                               double *center,
                                               double *translations,
                                               double *scales,
                                               double *shears,
                                               double *quaternions)
{
  
  float
    **T,
    **SH,
    **S,
    **R,
    **C,
    **T1,
    **T2,
    **T3,
    **T4;

  double normal;


  int
    i,j;
  
  ALLOC2D(T  ,5,5);
  ALLOC2D(SH ,5,5);
  ALLOC2D(S  ,5,5);
  ALLOC2D(R  ,5,5);
  ALLOC2D(C  ,5,5);
  ALLOC2D(T1 ,5,5);
  ALLOC2D(T2 ,5,5);
  ALLOC2D(T3 ,5,5);
  ALLOC2D(T4 ,5,5);
  
 
  


  
  normal=(quaternions[0]*quaternions[0] + quaternions[1]*quaternions[1] + quaternions[2]*quaternions[2] + quaternions[3]*quaternions[3]);
  if (normal>1){
   for(i = 0; i < 4; i++){
      quaternions[i] /= normal;
   }} 
   
   

                        /* mat = (T)(C)(SH)(S)(R)(-C) */

  nr_identf(T,1,4,1,4);



                                             /* make (T)(C) */
  for(i=0; i<3; i++) {
    T[1+i][4] = translations[i] + center[i];                
  }
   
  

  build_rotmatrix(R,quaternions); /* make rotation matrix from quaternions */
  

                                /* make shear rotation matrix */
  make_shears(SH, shears);

                                /* make scaling matrix */
  nr_identf(S,1,4,1,4);                   
  for(i=0; i<3; i++) {
    S[1+i][1+i] = scales[i];
  }


  nr_identf(C,1,4,1,4);      /* make center          */
  for(i=0; i<3; i++) {
    C[1+i][4] = -center[i];                
  }

  nr_multf(T, 1,4,1,4, S  ,1,4,1,4, T1 );  
  nr_multf(T1,1,4,1,4, SH ,1,4,1,4, T2 );  
  nr_multf(T2,1,4,1,4, R  ,1,4,1,4, T3 );  
  nr_multf(T3,1,4,1,4, C  ,1,4,1,4, T4 );  

  for(i=0; i<4; i++)
    for(j=0; j<4; j++)
      Transform_elem(*trans, i, j ) = T4[i+1][j+1];

  FREE2D(T    );
  FREE2D(SH   );
  FREE2D(S    );
  FREE2D(R    );
  FREE2D(C );
  FREE2D(T1   );
  FREE2D(T2   );
  FREE2D(T3   );
  FREE2D(T4   );
}
Exemple #5
0
void build_transformation_matrix(VIO_Transform *trans,
                                        double *center,
                                        double *translations,
                                        double *scales,
                                        double *shears,
                                        double *rotations)
{
  
  float
    **T,
    **SH,
    **S,
    **R,
    **C,
    **T1,
    **T2,
    **T3,
    **T4;
  int
    i,j;
  
  ALLOC2D(T  ,5,5);
  ALLOC2D(SH ,5,5);
  ALLOC2D(S  ,5,5);
  ALLOC2D(R  ,5,5);
  ALLOC2D(C  ,5,5);
  ALLOC2D(T1 ,5,5);
  ALLOC2D(T2 ,5,5);
  ALLOC2D(T3 ,5,5);
  ALLOC2D(T4 ,5,5);
  
                                             /* mat = (T)(C)(SH)(S)(R)(-C) */

  nr_identf(T,1,4,1,4);                     /* make (T)(C) */
  for(i=0; i<3; i++) {
    T[1+i][4] = translations[i] + center[i];                
  }
                                /* make rotation matix */
  make_rots(R,
            (float)(rotations[0]),
            (float)(rotations[1]),
            (float)(rotations[2])); 

                                /* make shear rotation matrix */
  make_shears(SH, shears);

                                /* make scaling matrix */
  nr_identf(S,1,4,1,4);                   
  for(i=0; i<3; i++) {
    S[1+i][1+i] = scales[i];
  }

  nr_identf(C,1,4,1,4);      /* make center          */
  for(i=0; i<3; i++) {
    C[1+i][4] = -center[i];                
  }

  nr_multf(T, 1,4,1,4, S  ,1,4,1,4, T1 );  
  nr_multf(T1,1,4,1,4, SH ,1,4,1,4, T2 );  
  nr_multf(T2,1,4,1,4, R  ,1,4,1,4, T3 );  
  nr_multf(T3,1,4,1,4, C  ,1,4,1,4, T4 );  

  for(i=0; i<4; i++)
    for(j=0; j<4; j++)
      Transform_elem(*trans, i, j ) = T4[i+1][j+1];

  FREE2D(T    );
  FREE2D(SH   );
  FREE2D(S    );
  FREE2D(R    );
  FREE2D(C );
  FREE2D(T1   );
  FREE2D(T2   );
  FREE2D(T3   );
  FREE2D(T4   );
}
Exemple #6
0
/* regrid a point in a file using the input co-ordinate and data */
void regrid_point(VIO_Volume * totals, VIO_Volume * weights,
                  double x, double y, double z, int v_size, double *data_buf)
{

   int      sizes[MAX_VAR_DIMS];
   VIO_Real     steps[MAX_VAR_DIMS];
   VIO_Real     starts[MAX_VAR_DIMS];
   int      start_idx[3];
   int      stop_idx[3];
   double   value, weight;
   double   euc_dist;
   double   euc[3];
   double   c_pos[3];
   int      i, j, k, v;
   double   coord[3];                  /* target point in mm  coordinates, in X, Y, Z order */

   VIO_Transform dircos, invdircos;
   VIO_Vector   vector;
   VIO_Real     dir[3];

   /* the coord used below has to be in mm coordinates in the dircos space of the 
      target volume.  Hence the manipulations with the vols direction_cosines      */
   make_identity_transform(&dircos);

   get_volume_direction_cosine(*totals, perm[0], dir);
   fill_Vector(vector, dir[0], dir[1], dir[2]);
   set_transform_x_axis(&dircos, &vector);

   get_volume_direction_cosine(*totals, perm[1], dir);
   fill_Vector(vector, dir[0], dir[1], dir[2]);
   set_transform_y_axis(&dircos, &vector);

   get_volume_direction_cosine(*totals, perm[2], dir);
   fill_Vector(vector, dir[0], dir[1], dir[2]);
   set_transform_z_axis(&dircos, &vector);

   for(i = 0; i < 4; i++){
      for(j = 0; j < 4; j++){
         Transform_elem(invdircos, i, j) = Transform_elem(dircos, j, i);
         }
      }

   transform_point(&invdircos, x, y, z, &coord[0], &coord[1], &coord[2]);
   
   get_volume_sizes(*totals, sizes);   /* in volume voxel order, ie z,y,x with x fastest */
   get_volume_separations(*totals, steps);
   get_volume_starts(*totals, starts);

   /* figure out the neighbouring voxels start and stop (in voxel co-ordinates) */
   for(i = 0; i < 3; i++){            /* go through x, y and z */
      start_idx[i] =
         (int)rint((coord[i] - starts[perm[i]] - regrid_radius[i]) / steps[perm[i]]);
      stop_idx[i] = start_idx[i] + rint((regrid_radius[i] * 2) / steps[perm[i]]);

      /* flip if required */
      if(start_idx[i] > stop_idx[i]){
         value = start_idx[i];
         start_idx[i] = stop_idx[i];
         stop_idx[i] = value;
         }

      /* check that we aren't off the edge */
      if(start_idx[i] < 0){
         start_idx[i] = 0;
         }
      if(stop_idx[i] >= sizes[perm[i]]){
         stop_idx[i] = sizes[perm[i]] - 1;
         }
      }

   /* loop over the neighbours, getting euclidian distance */
   c_pos[0] = starts[perm[0]] + (start_idx[0] * steps[perm[0]]);
   for(i = start_idx[0]; i <= stop_idx[0]; i++){
      euc[0] = fabs(c_pos[0] - coord[0]);

      c_pos[1] = starts[perm[1]] + (start_idx[1] * steps[perm[1]]);
      for(j = start_idx[1]; j <= stop_idx[1]; j++){
         euc[1] = fabs(c_pos[1] - coord[1]);

         c_pos[2] = starts[perm[2]] + (start_idx[2] * steps[perm[2]]);
         for(k = start_idx[2]; k <= stop_idx[2]; k++){
            euc[2] = fabs(c_pos[2] - coord[2]);

            euc_dist = sqrt(SQR2(euc[0]) + SQR2(euc[1]) + SQR2(euc[2]));

            if((regrid_radius[0] == 0 || euc[0] <= regrid_radius[0]) &&
               (regrid_radius[1] == 0 || euc[1] <= regrid_radius[1]) &&
               (regrid_radius[2] == 0 || euc[2] <= regrid_radius[2])){

               /* calculate the weighting factor */
               switch (regrid_type){
               default:
                  fprintf(stderr, "Erk! unknown regrid_type. File: %s Line: %d\n",
                          __FILE__, __LINE__);
                  exit(EXIT_FAILURE);
                  break;
                  
               case NEAREST_FUNC:
               case LINEAR_FUNC:
                  weight = euc_dist;
                  break;
                  
               case KAISERBESSEL_FUNC:
                  weight =
                     gsl_sf_bessel_I0(regrid_sigma[0] *
                                      sqrt(1 - SQR2(euc[0] / regrid_radius[0]))) *
                     gsl_sf_bessel_I0(regrid_sigma[1] *
                                      sqrt(1 - SQR2(euc[1] / regrid_radius[1]))) *
                     gsl_sf_bessel_I0(regrid_sigma[2] *
                                      sqrt(1 - SQR2(euc[2] / regrid_radius[2]))) /
                     SQR3((regrid_radius[0] + regrid_radius[1] + regrid_radius[2]) / 3);
                  break;
                  
               case GAUSSIAN_FUNC:
                  weight = exp(-SQR2(euc[0]) / SQR2(regrid_sigma[0])) *
                           exp(-SQR2(euc[1]) / SQR2(regrid_sigma[1])) *
                           exp(-SQR2(euc[2]) / SQR2(regrid_sigma[2]));
                  break;
                  }
               
               /* set data values */
               if(regrid_type == NEAREST_FUNC){
                  value = get_volume_real_value(*weights, k, j, i, 0, 0);
                  if(weight < value){
                     set_volume_real_value(*weights, k, j, i, 0, 0, weight);
                     for(v = 0; v < v_size; v++){
                        set_volume_real_value(*totals, k, j, i, v, 0,
                                               data_buf[0 + v] * weight);
                        }
                     }
                  }
               else{
                  for(v = 0; v < v_size; v++){
                     value = get_volume_real_value(*totals, k, j, i, v, 0);
                     set_volume_real_value(*totals, k, j, i, v, 0,
                                          value + (data_buf[0 + v] * weight));
                     }
   
                  /* increment count value */
                  value = get_volume_real_value(*weights, k, j, i, 0, 0);
                  set_volume_real_value(*weights, k, j, i, 0, 0, value + weight);
                  }
               }

            c_pos[2] += steps[perm[2]];
            }

         c_pos[1] += steps[perm[1]];
         }

      c_pos[0] += steps[perm[0]];
      }

   }