1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "mrilib.h"
8 #include "thd.h"
9 
10 /*----------------------------------------------------------------
11    Edit a THD_dataxes structure to allow for resampling to a new
12    voxel size (resam).
13 -----------------------------------------------------------------*/
14 
THD_edit_dataxes(float resam,THD_dataxes * daxes,THD_dataxes * wod_daxes)15 void THD_edit_dataxes( float resam , THD_dataxes *daxes ,
16                                      THD_dataxes *wod_daxes )
17 {
18    float lxx , lyy , lzz ;
19    float rex , rey , rez ;
20 
21    if( !ISVALID_DATAXES(daxes) || !ISVALID_DATAXES(wod_daxes) ) return ;
22 
23    *wod_daxes = *daxes ;       /* copy insides, then edit them */
24 
25    if( resam <= 0.0 ) return ; /* error */
26 
27    rex = (daxes->xxdel > 0) ? resam : -resam ;  /* signed resampled */
28    rey = (daxes->yydel > 0) ? resam : -resam ;  /* voxel sizes */
29    rez = (daxes->zzdel > 0) ? resam : -resam ;
30 
31    lxx = daxes->nxx * daxes->xxdel ;    /* signed lengths of data box */
32    lyy = daxes->nyy * daxes->yydel ;
33    lzz = daxes->nzz * daxes->zzdel ;
34 
35    wod_daxes->nxx = (int)( lxx/rex + 0.499 ) ;  /* new dimensions */
36    wod_daxes->nyy = (int)( lyy/rey + 0.499 ) ;  /* (will be > 0) */
37    wod_daxes->nzz = (int)( lzz/rez + 0.499 ) ;
38 
39    /* go to old middle, then back out to get new edge */
40 
41    wod_daxes->xxorg = daxes->xxorg + 0.5*(lxx - daxes->xxdel)
42                                    - 0.5*(wod_daxes->nxx - 1)*rex ;
43 
44    wod_daxes->yyorg = daxes->yyorg + 0.5*(lyy - daxes->yydel)
45                                    - 0.5*(wod_daxes->nyy - 1)*rey ;
46 
47    wod_daxes->zzorg = daxes->zzorg + 0.5*(lzz - daxes->zzdel)
48                                    - 0.5*(wod_daxes->nzz - 1)*rez ;
49 
50    /* new dimensions of the voxels */
51 
52    wod_daxes->xxdel = rex ;
53    wod_daxes->yydel = rey ;
54    wod_daxes->zzdel = rez ;
55 
56    /* do the bounding box thing again */
57 
58    THD_set_daxes_bbox( wod_daxes ) ;  /* 20 Dec 2005 */
59 
60    /** 15 Dec 2005: deal with the new matrix coordinate entries **/
61 
62    { mat44 new_mat ; int nxnew , nynew , nznew ;
63      new_mat = THD_resample_mat44( daxes->ijk_to_dicom ,
64                                    daxes->nxx , daxes->nyy , daxes->nzz ,
65                                    resam      , resam      , resam      ,
66                                    &nxnew     , &nynew     , &nznew      ) ;
67      if( ISVALID_MAT44(new_mat) ){
68        wod_daxes->ijk_to_dicom = new_mat ;
69        wod_daxes->dicom_to_ijk = nifti_mat44_inverse( new_mat ) ;
70        THD_set_dicom_box(wod_daxes) ;
71      }
72    }
73 
74    return ;
75 }
76 
77 /*----------------------------------------------------------------*/
78 
THD_set_daxes_bbox(THD_dataxes * daxes)79 void THD_set_daxes_bbox( THD_dataxes *daxes )  /* 20 Dec 2005 */
80 {
81     if( !ISVALID_DATAXES(daxes) ) return ;
82 
83     /*---------------------------------------*/
84     /*-- set bounding box for this dataset --*/
85     /*---------------------------------------*/
86 
87     daxes->xxmin = daxes->xxorg ;
88     daxes->xxmax = daxes->xxorg + (daxes->nxx-1) * daxes->xxdel ;
89     if( daxes->xxmin > daxes->xxmax ){
90       float temp   = daxes->xxmin ;
91       daxes->xxmin = daxes->xxmax ; daxes->xxmax = temp ;
92     }
93 
94     daxes->yymin = daxes->yyorg ;
95     daxes->yymax = daxes->yyorg + (daxes->nyy-1) * daxes->yydel ;
96     if( daxes->yymin > daxes->yymax ){
97       float temp   = daxes->yymin ;
98       daxes->yymin = daxes->yymax ; daxes->yymax = temp ;
99     }
100 
101     daxes->zzmin = daxes->zzorg ;
102     daxes->zzmax = daxes->zzorg + (daxes->nzz-1) * daxes->zzdel ;
103     if( daxes->zzmin > daxes->zzmax ){
104       float temp   = daxes->zzmin ;
105       daxes->zzmin = daxes->zzmax ; daxes->zzmax = temp ;
106     }
107 
108 #ifdef EXTEND_BBOX
109     daxes->xxmin -= 0.5 * daxes->xxdel ;  /* pushes edges back by 1/2  */
110     daxes->xxmax += 0.5 * daxes->xxdel ;  /* voxel dimensions (the box */
111     daxes->yymin -= 0.5 * daxes->yydel ;  /* defined above is based on */
112     daxes->yymax += 0.5 * daxes->yydel ;  /* voxel centers, not edges) */
113     daxes->zzmin -= 0.5 * daxes->zzdel ;
114     daxes->zzmax += 0.5 * daxes->zzdel ;
115 #endif
116 
117    return ;
118 }
119 
120 /*----------------------------------------------------------------*/
121 
THD_set_daxes_to_dicomm(THD_dataxes * daxes)122 void THD_set_daxes_to_dicomm( THD_dataxes *daxes )  /* 20 Dec 2005 */
123 {
124     if( !ISVALID_DATAXES(daxes) ) return ;
125 
126     /*----------------------------------------------------------------*/
127     /*--  matrix that transforms to Dicom (left-posterior-superior) --*/
128     /*----------------------------------------------------------------*/
129 
130     LOAD_ZERO_MAT(daxes->to_dicomm) ;
131 
132     switch( daxes->xxorient ){
133       case ORI_R2L_TYPE:
134       case ORI_L2R_TYPE: daxes->to_dicomm.mat[0][0] = 1.0 ; break ;
135       case ORI_P2A_TYPE:
136       case ORI_A2P_TYPE: daxes->to_dicomm.mat[1][0] = 1.0 ; break ;
137       case ORI_I2S_TYPE:
138       case ORI_S2I_TYPE: daxes->to_dicomm.mat[2][0] = 1.0 ; break ;
139     }
140 
141     switch( daxes->yyorient ){
142       case ORI_R2L_TYPE:
143       case ORI_L2R_TYPE: daxes->to_dicomm.mat[0][1] = 1.0 ; break ;
144       case ORI_P2A_TYPE:
145       case ORI_A2P_TYPE: daxes->to_dicomm.mat[1][1] = 1.0 ; break ;
146       case ORI_I2S_TYPE:
147       case ORI_S2I_TYPE: daxes->to_dicomm.mat[2][1] = 1.0 ; break ;
148     }
149 
150     switch( daxes->zzorient ){
151       case ORI_R2L_TYPE:
152       case ORI_L2R_TYPE: daxes->to_dicomm.mat[0][2] = 1.0 ; break ;
153       case ORI_P2A_TYPE:
154       case ORI_A2P_TYPE: daxes->to_dicomm.mat[1][2] = 1.0 ; break ;
155       case ORI_I2S_TYPE:
156       case ORI_S2I_TYPE: daxes->to_dicomm.mat[2][2] = 1.0 ; break ;
157     }
158 
159     return ;
160 }
161