/* 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); }
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); }
/* ----------------------------- 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 ); }
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 ); }
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 ); }
/* 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]]; } }