/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#include "mrilib.h"
#include "thd.h"
/*-----------------------------------------------------------------------
Create FD_bricks for viewing purposes.
FD_bricks are a relic of the very earliest code that evolved into
AFNI. By the time I invented THD_3dim_datasets, I had enough code
in place to keep this data structure alive. Basically, it exists
only to provide a structure that enables fast copying of data out
of a 3D array into 2D arrays.
-------------------------------------------------------------------------*/
FD_brick ** THD_setup_bricks( THD_3dim_dataset * dset )
{
int r2l=0 , a2p=0 , i2s=0 ;
THD_dataxes * daxes ;
FD_brick ** br ;
if( ! ISVALID_3DIM_DATASET(dset) ) return NULL ;
daxes = CURRENT_DAXES(dset) ;
if( ! ISVALID_DATAXES(daxes) ) return NULL ;
/*----- create FD_bricks for viewing purposes -----*/
switch( daxes->xxorient ){
case ORI_R2L_TYPE: r2l = 1 ; break ;
case ORI_L2R_TYPE: r2l = -1 ; break ;
case ORI_P2A_TYPE: a2p = -1 ; break ;
case ORI_A2P_TYPE: a2p = 1 ; break ;
case ORI_I2S_TYPE: i2s = 1 ; break ;
case ORI_S2I_TYPE: i2s = -1 ; break ;
}
switch( daxes->yyorient ){
case ORI_R2L_TYPE: r2l = 2 ; break ;
case ORI_L2R_TYPE: r2l = -2 ; break ;
case ORI_P2A_TYPE: a2p = -2 ; break ;
case ORI_A2P_TYPE: a2p = 2 ; break ;
case ORI_I2S_TYPE: i2s = 2 ; break ;
case ORI_S2I_TYPE: i2s = -2 ; break ;
}
switch( daxes->zzorient ){
case ORI_R2L_TYPE: r2l = 3 ; break ;
case ORI_L2R_TYPE: r2l = -3 ; break ;
case ORI_P2A_TYPE: a2p = -3 ; break ;
case ORI_A2P_TYPE: a2p = 3 ; break ;
case ORI_I2S_TYPE: i2s = 3 ; break ;
case ORI_S2I_TYPE: i2s = -3 ; break ;
}
if( r2l==0 || a2p==0 || i2s==0 ){
char buf[256] ;
sprintf(buf,"Illegal orientation codes: %d %d %d",
daxes->xxorient,daxes->yyorient,daxes->zzorient ) ;
THD_FATAL_ERROR(buf) ;
}
/* now we can set up views: axial, sagittal, coronal;
the top option is the way I think it ought to be, so that
in the axial and coronal views, left is left and right is right;
the bottom options are the radiologists conventions, so sue me! */
br = (FD_brick **) XtMalloc( sizeof(FD_brick *) * 3 ) ;
#undef LEFT_IS_LEFT
#ifdef LEFT_IS_LEFT
br[0] = THD_3dim_dataset_to_brick(dset,-r2l, a2p,-i2s); /* axi */
br[1] = THD_3dim_dataset_to_brick(dset, a2p,-i2s,-r2l); /* sag */
br[2] = THD_3dim_dataset_to_brick(dset,-r2l,-i2s,-a2p); /* cor */
#else
br[0] = THD_3dim_dataset_to_brick(dset, r2l, a2p, i2s); /* axi */
br[1] = THD_3dim_dataset_to_brick(dset, a2p,-i2s,-r2l); /* sag */
br[2] = THD_3dim_dataset_to_brick(dset, r2l,-i2s, a2p); /* cor */
#endif
strcpy( br[0]->namecode , "Axial" ) ;
strcpy( br[1]->namecode , "Sagittal" ) ;
strcpy( br[2]->namecode , "Coronal" ) ;
return br ;
}
/*----------------------------------------------------------------------
07 Dec 2001 - orient an FD brick in any legal way
(e.g., orients = "RAI" for standard axial)
------------------------------------------------------------------------*/
FD_brick * THD_oriented_brick( THD_3dim_dataset *dset , char *orients )
{
int r2l=0 , a2p=0 , i2s=0 , xx,yy,zz , pp=0,qq=0,rr=0 ;
THD_dataxes *daxes ;
FD_brick *br ;
ENTRY("THD_oriented_brick") ;
if( !ISVALID_DSET(dset) ||
orients == NULL ||
strlen(orients) < 3 ) RETURN(NULL) ;
daxes = CURRENT_DAXES(dset) ;
if( !ISVALID_DATAXES(daxes) ) RETURN(NULL) ;
xx = ORCODE( orients[0] ) ;
yy = ORCODE( orients[1] ) ;
zz = ORCODE( orients[2] ) ;
if( !OR3OK(xx,yy,zz) ) RETURN(NULL) ;
/*----- create FD_bricks for viewing purposes -----*/
switch( daxes->xxorient ){
case ORI_R2L_TYPE: r2l = 1 ; break ;
case ORI_L2R_TYPE: r2l = -1 ; break ;
case ORI_P2A_TYPE: a2p = -1 ; break ;
case ORI_A2P_TYPE: a2p = 1 ; break ;
case ORI_I2S_TYPE: i2s = 1 ; break ;
case ORI_S2I_TYPE: i2s = -1 ; break ;
}
switch( daxes->yyorient ){
case ORI_R2L_TYPE: r2l = 2 ; break ;
case ORI_L2R_TYPE: r2l = -2 ; break ;
case ORI_P2A_TYPE: a2p = -2 ; break ;
case ORI_A2P_TYPE: a2p = 2 ; break ;
case ORI_I2S_TYPE: i2s = 2 ; break ;
case ORI_S2I_TYPE: i2s = -2 ; break ;
}
switch( daxes->zzorient ){
case ORI_R2L_TYPE: r2l = 3 ; break ;
case ORI_L2R_TYPE: r2l = -3 ; break ;
case ORI_P2A_TYPE: a2p = -3 ; break ;
case ORI_A2P_TYPE: a2p = 3 ; break ;
case ORI_I2S_TYPE: i2s = 3 ; break ;
case ORI_S2I_TYPE: i2s = -3 ; break ;
}
if( r2l==0 || a2p==0 || i2s==0 ) RETURN(NULL) ;
switch( xx ){
case ORI_R2L_TYPE: pp = r2l ; break ;
case ORI_L2R_TYPE: pp = -r2l ; break ;
case ORI_P2A_TYPE: pp = -a2p ; break ;
case ORI_A2P_TYPE: pp = a2p ; break ;
case ORI_I2S_TYPE: pp = i2s ; break ;
case ORI_S2I_TYPE: pp = -i2s ; break ;
}
switch( yy ){
case ORI_R2L_TYPE: qq = r2l ; break ;
case ORI_L2R_TYPE: qq = -r2l ; break ;
case ORI_P2A_TYPE: qq = -a2p ; break ;
case ORI_A2P_TYPE: qq = a2p ; break ;
case ORI_I2S_TYPE: qq = i2s ; break ;
case ORI_S2I_TYPE: qq = -i2s ; break ;
}
switch( zz ){
case ORI_R2L_TYPE: rr = r2l ; break ;
case ORI_L2R_TYPE: rr = -r2l ; break ;
case ORI_P2A_TYPE: rr = -a2p ; break ;
case ORI_A2P_TYPE: rr = a2p ; break ;
case ORI_I2S_TYPE: rr = i2s ; break ;
case ORI_S2I_TYPE: rr = -i2s ; break ;
}
if( pp==0 || qq==0 || rr==0 ) RETURN(NULL) ;
br = THD_3dim_dataset_to_brick(dset,pp,qq,rr) ;
RETURN(br) ;
}
/*======================================================================
routines adapted from original afni code for display of a 3D dataset
========================================================================*/
/*----------------------------------------------------------------------
prepare a "display brick" for a 3D dataset;
ax_n = 1,2,3 for displaying the x,y,z axis along the n-th display
direction (n=1 --> across, n=2 --> down, n=3 --> slices )
negative value means reverse
a return of NULL means something bad happened
------------------------------------------------------------------------*/
FD_brick * THD_3dim_dataset_to_brick( THD_3dim_dataset * dset ,
int ax_1, int ax_2, int ax_3 )
{
FD_brick * br ; /* will be output */
THD_dataxes * daxes ; /* connection to actual axes */
int xyz_dim[4] , xyz_stp[4] , xyz_dir[4] ;
float xyz_del[4] , xyz_org[4] ;
int x_dir,y_dir,z_dir , sx,sy,sz , aax_1,aax_2,aax_3 , nx,ny,nz ;
/*-- sanity check --*/
if( ! ISVALID_3DIM_DATASET(dset) ) return NULL ;
daxes = CURRENT_DAXES(dset) ;
aax_1 = abs(ax_1) ; /* which axes, regardless of + or - */
aax_2 = abs(ax_2) ;
aax_3 = abs(ax_3) ;
if( aax_1 < 1 || aax_1 > 3 || /* range checks */
aax_2 < 1 || aax_2 > 3 ||
aax_3 < 1 || aax_3 > 3 ) return NULL ;
xyz_dir[1] = xyz_dir[2] = xyz_dir[3] = 0 ;
xyz_dir[aax_1] = ax_1 ; /* assign to original directions */
xyz_dir[aax_2] = ax_2 ;
xyz_dir[aax_3] = ax_3 ;
x_dir = xyz_dir[1] ; /* if any |ax_n| is duplicated */
y_dir = xyz_dir[2] ; /* then one of these will end */
z_dir = xyz_dir[3] ; /* up as zero --> bad inputs! */
if( x_dir == 0 || y_dir == 0 || z_dir == 0 ) return NULL ;
/*-- the inputs are good, so create a brick: --*/
br = myXtNew(FD_brick) ; /* new brick */
br->dset = dset ; /* dataset */
br->resam_code = RESAM_NN_TYPE ; /* crudest type */
br->parent = NULL ;
br->thr_resam_code = RESAM_NN_TYPE ; /* 09 Dec 1997 */
/*-- at this point, x_dir is +1 or -1, y_dir is +2 or -2, etc. --*/
nx = daxes->nxx ; ny = daxes->nyy ; nz = daxes->nzz ;
sx = (x_dir > 0) ? (0) : (nx-1) ; /* starting voxel indices */
sy = (y_dir > 0) ? (0) : (ny-1) ; /* for each original dimension */
sz = (z_dir > 0) ? (0) : (nz-1) ;
br->start = sx + sy*nx + sz*nx*ny ; /* overall starting voxel index */
/*-- assign original dimensions to arrays,
then pick out the permuted dimensions --*/
xyz_dim[1] = nx ; /* dimensions */
xyz_dim[2] = ny ;
xyz_dim[3] = nz ;
LOAD_IVEC3( br->nxyz , nx,ny,nz ) ; /* save stuff in br */
LOAD_IVEC3( br->sxyz , sx,sy,sz ) ;
LOAD_IVEC3( br->a123 , ax_1,ax_2,ax_3 ) ;
xyz_stp[1] = 1 ; /* index step sizes */
xyz_stp[2] = nx ;
xyz_stp[3] = nx * ny ;
xyz_del[1] = daxes->xxdel ; /* voxel physical step sizes (mm) */
xyz_del[2] = daxes->yydel ;
xyz_del[3] = daxes->zzdel ;
xyz_org[1] = daxes->xxorg ; /* voxel origins (mm) */
xyz_org[2] = daxes->yyorg ;
xyz_org[3] = daxes->zzorg ;
br->n1 = xyz_dim[aax_1] ; /* permute dimensions, etc. */
br->n2 = xyz_dim[aax_2] ;
br->n3 = xyz_dim[aax_3] ;
br->d1 = (ax_1 > 0) ? (xyz_stp[aax_1]) : (-xyz_stp[aax_1]) ;
br->d2 = (ax_2 > 0) ? (xyz_stp[aax_2]) : (-xyz_stp[aax_2]) ;
br->d3 = (ax_3 > 0) ? (xyz_stp[aax_3]) : (-xyz_stp[aax_3]) ;
br->e1 = br->n1 * br->d1 ; /* last indices for readout */
br->e2 = br->n2 * br->d2 ;
br->del1 = fabs(xyz_del[aax_1]) ; /* dimensions */
br->del2 = fabs(xyz_del[aax_2]) ;
br->del3 = fabs(xyz_del[aax_3]) ;
br->namecode[0] = '\0' ;
return br ;
}
syntax highlighted by Code2HTML, v. 0.9.1