Mercurial > hg > minc-tools
changeset 772:32437b7bfce4
*** empty log message ***
author | david <david> |
---|---|
date | Wed, 22 Feb 1995 14:42:48 +0000 |
parents | 61cf793fe122 |
children | e1e0f33f27d3 |
files | volume_io/Volumes/evaluate.c |
diffstat | 1 files changed, 378 insertions(+), 811 deletions(-) [+] |
line wrap: on
line diff
--- a/volume_io/Volumes/evaluate.c +++ b/volume_io/Volumes/evaluate.c @@ -1,22 +1,282 @@ #include <internal_volume_io.h> -#include <vols.h> -#include <numerical.h> + +private void interpolate_volume( + int n_dims, + Real parameters[], + int n_values, + int degree, + Real coefs[], + Real values[], + Real **first_deriv, + Real ***second_deriv ) +{ + int v, d, d2, n_derivs, derivs_per_value, mult, mult2; + Real *derivs; + + if( second_deriv != NULL ) + n_derivs = 2; + else if( first_deriv != NULL ) + n_derivs = 1; + else + n_derivs = 0; + + derivs_per_value = 1; + for_less( d, 0, n_dims ) + derivs_per_value *= 1 + n_derivs; + + ALLOC( derivs, n_values * derivs_per_value ); + + evaluate_interpolating_spline( n_dims, parameters, degree, n_values, coefs, + n_derivs, derivs ); + + /* --- derivs is now a one dimensional array representing + derivs[n_values][1+n_derivs][1+n_derivs]... */ + + if( values != NULL ) + { + for_less( v, 0, n_values ) + values[v] = derivs[v*derivs_per_value]; + } -private void trilinear_interpolate_volume( - Volume volume, - Real x, - Real y, - Real z, - BOOLEAN x_use_higher, - BOOLEAN y_use_higher, - BOOLEAN z_use_higher, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z ); + if( first_deriv != NULL ) + { + mult = 1; + for_down( d, n_dims-1, 0 ) + { + for_less( v, 0, n_values ) + first_deriv[v][d] = derivs[mult + v*derivs_per_value]; + + mult *= 1 + n_derivs; + } + } + + if( second_deriv != NULL ) + { + mult = 1; + for_down( d, n_dims-1, 0 ) + { + for_less( v, 0, n_values ) + second_deriv[v][d][d] = derivs[2*mult + v*derivs_per_value]; + + mult *= 1 + n_derivs; + } + + mult = 1; + for_down( d, n_dims-1, 0 ) + { + mult2 = 1; + + for_down( d2, n_dims-1, d+1 ) + { + for_less( v, 0, n_values ) + { + second_deriv[v][d][d2] = + derivs[mult+mult2+v*derivs_per_value]; + second_deriv[v][d2][d] = + derivs[mult+mult2+v*derivs_per_value]; + } + + mult2 *= 1 + n_derivs; + } + + mult *= 1 + n_derivs; + } + } + + FREE( derivs ); +} /* ----------------------------- MNI Header ----------------------------------- -@NAME : evaluate_3D_volume_in_world +@NAME : evaluate_volume +@INPUT : volume + x + y + z +@OUTPUT : value + deriv_x + deriv_y + deriv_z +@RETURNS : +@DESCRIPTION: Takes a voxel space position and evaluates the value within + the volume by nearest_neighbour, linear, quadratic, or + cubic interpolation. + If first_deriv is not a null pointer, then the first derivatives + are passed back. Similarly for the second_deriv. +@CREATED : Mar 1993 David MacDonald +@MODIFIED : +---------------------------------------------------------------------------- */ + +public int evaluate_volume( + Volume volume, + Real voxel[], + BOOLEAN interpolating_dimensions[], + int degrees_continuity, + Real values[], + Real **first_deriv, + Real ***second_deriv, + BOOLEAN *inside ) +{ + int n, v, d, dim, n_values, sizes[MAX_DIMENSIONS], n_dims, ind; + int start[MAX_DIMENSIONS], n_interp_dims; + int end[MAX_DIMENSIONS]; + int interp_dims[MAX_DIMENSIONS]; + int n_coefs; + int vi[MAX_DIMENSIONS]; + Real value, fraction[MAX_DIMENSIONS], bound, *coefs; + + if( degrees_continuity > 2 ) + { + print( "Warning: evaluate_volume(), degrees too large: %d\n", + degrees_continuity ); + degrees_continuity = 2; + } + + n_dims = get_volume_n_dimensions(volume); + get_volume_sizes( volume, sizes ); + n_values = 1; + n_interp_dims = 0; + + for_less( d, 0, n_dims ) + { + if( interpolating_dimensions == NULL || interpolating_dimensions[d] ) + { + if( degrees_continuity > -2 && + (voxel[d] < (Real) degrees_continuity * 0.5 || + voxel[d] > (Real)(sizes[d]-1) - (Real)degrees_continuity*0.5) ) + { + --degrees_continuity; + for( ; degrees_continuity > -2; --degrees_continuity ) + { + if( voxel[d] >= (Real) degrees_continuity * 0.5 && + voxel[d] <= (Real)(sizes[d]-1) - + (Real)degrees_continuity * 0.5 ) + { + break; + } + } + } + ++n_interp_dims; + } + else + { + n_values *= sizes[d]; + } + } + + if( inside != NULL ) + *inside = degrees_continuity >= -1; + + if( degrees_continuity < -1 ) + { + value = get_volume_real_min( volume ); + + for_less( v, 0, n_values ) + values[v] = value; + } + + if( degrees_continuity < 0 && first_deriv != NULL ) + { + for_less( v, 0, n_values ) + for_less( d, 0, n_interp_dims ) + first_deriv[v][d] = 0.0; + } + + if( degrees_continuity < 1 && second_deriv != NULL ) + { + for_less( v, 0, n_values ) + for_less( d, 0, n_interp_dims ) + for_less( dim, 0, n_interp_dims ) + second_deriv[v][d][dim] = 0.0; + } + + if( degrees_continuity > -2 ) + { + bound = degrees_continuity / 2.0; + n_interp_dims = 0; + n_coefs = 1; + + for_less( d, 0, n_dims ) + { + if( interpolating_dimensions == NULL || interpolating_dimensions[d]) + { + interp_dims[n_interp_dims] = d; + n_coefs *= 2 + degrees_continuity; + if( voxel[d] >= (Real) sizes[d] - 1.0 - bound ) + { + start[n_interp_dims] = sizes[d] - degrees_continuity - 2; + fraction[n_interp_dims] = 1.0; + } + else + { + if( voxel[d] < bound ) + voxel[d] = bound; + + start[n_interp_dims] = (int) ( voxel[d] - bound ); + fraction[n_interp_dims] = FRACTION( voxel[d] - bound ); + } + + end[n_interp_dims] = start[d] + degrees_continuity + 2; + ++n_interp_dims; + } + } + + n = 0; + for_less( d, 0, n_dims ) + { + if( interpolating_dimensions != NULL && + !interpolating_dimensions[d] ) + { + interp_dims[n_interp_dims+n] = d; + start[n_interp_dims+n] = 0; + end[n_interp_dims+n] = sizes[d]; + ++n; + } + } + + for_less( d, n_dims, MAX_DIMENSIONS ) + { + start[d] = 0; + end[d] = 1; + interp_dims[d] = d; + } + + ALLOC( coefs, n_values * n_coefs ); + + ind = 0; + for_less( vi[interp_dims[0]], start[0], end[0] ) + for_less( vi[interp_dims[1]], start[1], end[1] ) + for_less( vi[interp_dims[2]], start[2], end[2] ) + for_less( vi[interp_dims[3]], start[3], end[3] ) + for_less( vi[interp_dims[4]], start[4], end[4] ) + { + GET_VALUE( coefs[ind], volume, vi[0], vi[1], vi[2], vi[3], vi[4] ); + ++ind; + } + + switch( degrees_continuity ) + { + case -1: + for_less( v, 0, n_values ) + values[v] = coefs[v]; + break; + + case 0: + case 1: + case 2: + interpolate_volume( n_interp_dims, fraction, n_values, + degrees_continuity + 2, coefs, + values, first_deriv, second_deriv ); + break; + } + + FREE( coefs ); + } + + return( n_values ); +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : evaluate_volume_in_world @INPUT : volume x y @@ -35,833 +295,140 @@ @MODIFIED : ---------------------------------------------------------------------------- */ -public void evaluate_3D_volume_in_world( +public BOOLEAN evaluate_volume_in_world( Volume volume, Real x, Real y, Real z, int degrees_continuity, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_xz, - Real *deriv_yy, - Real *deriv_yz, - Real *deriv_zz ) + Real values[], + Real deriv_x[], + Real deriv_y[], + Real deriv_z[], + Real deriv_xx[], + Real deriv_xy[], + Real deriv_xz[], + Real deriv_yy[], + Real deriv_yz[], + Real deriv_zz[] ) { - Real ignore, dxx, dxy, dxz, dyy, dyz, dzz; + Real ignore; Real voxel[MAX_DIMENSIONS]; - Real txx, txy, txz; - Real tyx, tyy, tyz; - Real tzx, tzy, tzz; - - if( get_volume_n_dimensions(volume) != 3 ) - { - handle_internal_error( - "evaluate_3D_volume_in_world: volume must be 3D.\n" ); - } - - convert_world_to_voxel( volume, x, y, z, voxel ); - - evaluate_3D_volume( volume, voxel[X], voxel[Y], voxel[Z], - degrees_continuity, value, deriv_x, deriv_y, deriv_z, - deriv_xx, deriv_xy, deriv_xz, - deriv_yy, deriv_yz, deriv_zz ); - - if( deriv_x != (Real *) 0 ) - { - convert_voxel_normal_vector_to_world( volume, - *deriv_x, *deriv_y, *deriv_z, - deriv_x, deriv_y, deriv_z ); - } - - if( deriv_xx != (Real *) 0 ) - { - dxx = *deriv_xx; - dxy = *deriv_xy; - dxz = *deriv_xz; - dyy = *deriv_yy; - dyz = *deriv_yz; - dzz = *deriv_zz; - convert_voxel_normal_vector_to_world( volume, - dxx, dxy, dxz, - &txx, &txy, &txz ); - convert_voxel_normal_vector_to_world( volume, - dxy, dyy, dyz, - &tyx, &tyy, &tyz ); - convert_voxel_normal_vector_to_world( volume, - dxz, dyz, dzz, - &tzx, &tzy, &tzz ); - - convert_voxel_normal_vector_to_world( volume, - txx, tyx, tzx, - deriv_xx, &ignore, &ignore ); - convert_voxel_normal_vector_to_world( volume, - txy, tyy, tzy, - deriv_xy, deriv_yy, &ignore ); - convert_voxel_normal_vector_to_world( volume, - txz, tyz, tzz, - deriv_xz, deriv_yz, deriv_zz ); - } -} - -public void special_evaluate_3D_volume_in_world( - Volume volume, - Real x, - Real y, - Real z, - BOOLEAN x_use_higher, - BOOLEAN y_use_higher, - BOOLEAN z_use_higher, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z ) -{ - Real voxel[MAX_DIMENSIONS]; + Real **first_deriv, ***second_deriv; + Real t[MAX_DIMENSIONS][MAX_DIMENSIONS]; + int c, d, dim, v, n_values, n_interp_dims, n_dims, axis; int sizes[MAX_DIMENSIONS]; + BOOLEAN interpolating_dimensions[MAX_DIMENSIONS], inside; convert_world_to_voxel( volume, x, y, z, voxel ); + get_volume_sizes( volume, sizes ); - get_volume_sizes( volume, sizes ); - if( x < -0.5 || x > (Real) sizes[X] - 0.5 || - y < -0.5 || y > (Real) sizes[Y] - 0.5 || - z < -0.5 || z > (Real) sizes[Z] - 0.5 ) + n_dims = get_volume_n_dimensions( volume ); + for_less( d, 0, n_dims ) + interpolating_dimensions[d] = FALSE; + + for_less( d, 0, N_DIMENSIONS ) { - *value = get_volume_voxel_min( volume ); - if( deriv_x != (Real *) NULL ) + axis = volume->spatial_axes[d]; + if( axis < 0 ) { - *deriv_x = 0.0; - *deriv_y = 0.0; - *deriv_z = 0.0; + print("evaluate_volume_in_world(): must have 3 spatial axes.\n"); + return( FALSE ); } - return; + + interpolating_dimensions[axis] = TRUE; + } + + + n_values = 1; + for_less( d, 0, n_dims ) + { + if( !interpolating_dimensions[d] ) + n_values *= sizes[d]; } - trilinear_interpolate_volume( volume, voxel[X], voxel[Y], voxel[Z], - x_use_higher, y_use_higher, z_use_higher, - value, deriv_x, deriv_y, deriv_z ); - - if( deriv_x != (Real *) 0 ) + if( deriv_x != NULL ) { - convert_voxel_normal_vector_to_world( volume, - *deriv_x, *deriv_y, *deriv_z, - deriv_x, deriv_y, deriv_z ); + ALLOC2D( first_deriv, n_values, N_DIMENSIONS ); } -} + else + first_deriv = NULL; -/* ----------------------------- MNI Header ----------------------------------- -@NAME : evaluate_3D_slice_in_world -@INPUT : volume - x - y - z -@OUTPUT : value - deriv_x - deriv_y - deriv_xx - deriv_xy - deriv_yy -@RETURNS : -@DESCRIPTION: Takes a world space position and evaluates the value within - the volume by bilinear interpolation within the slice. - If deriv_x is not a null pointer, then the derivatives are passed - back. -@CREATED : Mar 1993 David MacDonald -@MODIFIED : ----------------------------------------------------------------------------- */ + if( deriv_xx != NULL ) + { + ALLOC3D( second_deriv, n_values, N_DIMENSIONS, N_DIMENSIONS ); + } + else + second_deriv = NULL; + + n_values = evaluate_volume( volume, voxel, interpolating_dimensions, + degrees_continuity, values, first_deriv, second_deriv, + &inside ); -public void evaluate_3D_slice_in_world( - Volume volume, - Real x, - Real y, - Real z, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_yy ) -{ - Real ignore, dxx, dxy, dyy; - Real voxel[MAX_DIMENSIONS]; - Real txx, txy, txz; - Real tyx, tyy, tyz; - Real tzx, tzy, tzz; + if( deriv_x != NULL ) + { + for_less( v, 0, n_values ) + { + n_interp_dims = 0; + for_less( c, 0, n_dims ) + { + if( interpolating_dimensions[c] ) + { + voxel[c] = first_deriv[v][n_interp_dims]; + ++n_interp_dims; + } + else + voxel[c] = 0.0; + } - if( get_volume_n_dimensions(volume) != 3 ) - { - handle_internal_error( - "evaluate_3D_slice_in_world: volume must be 3D.\n" ); - } - - convert_world_to_voxel( volume, x, y, z, voxel ); - - evaluate_3D_slice( volume, voxel[X], voxel[Y], voxel[Z], - value, deriv_x, deriv_y, - deriv_xx, deriv_xy, deriv_yy ); - - if( deriv_x != (Real *) 0 ) - { - convert_voxel_normal_vector_to_world( volume, - *deriv_x, *deriv_y, 0.0, - deriv_x, deriv_y, &ignore ); + convert_voxel_normal_vector_to_world( volume, voxel, + &deriv_x[v], &deriv_y[v], &deriv_z[v] ); + } } if( deriv_xx != (Real *) 0 ) { - dxx = *deriv_xx; - dxy = *deriv_xy; - dyy = *deriv_yy; - convert_voxel_normal_vector_to_world( volume, - dxx, dxy, 0.0, - &txx, &txy, &txz ); - convert_voxel_normal_vector_to_world( volume, - dxy, dyy, 0.0, - &tyx, &tyy, &tyz ); - convert_voxel_normal_vector_to_world( volume, - 0.0, 0.0, 0.0, - &tzx, &tzy, &tzz ); - - convert_voxel_normal_vector_to_world( volume, - txx, tyx, tzx, - deriv_xx, &ignore, &ignore ); - convert_voxel_normal_vector_to_world( volume, - txy, tyy, tzy, - deriv_xy, deriv_yy, &ignore ); - } -} - -/* ----------------------------- MNI Header ----------------------------------- -@NAME : triconstant_interpolate_volume -@INPUT : volume - x - y - z -@OUTPUT : value - deriv_x - deriv_y - deriv_z -@RETURNS : -@DESCRIPTION: Returns the value within the volume, assuming constant voxels, - (step function). Derivative is approximated by neighbours. -@METHOD : -@GLOBALS : -@CALLS : -@CREATED : 1993 David MacDonald -@MODIFIED : ----------------------------------------------------------------------------- */ - -private void triconstant_interpolate_volume( - Volume volume, - Real x, - Real y, - Real z, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z ) -{ - int i, j, k, sizes[MAX_DIMENSIONS]; - Real prev, next, dx, dy, dz, voxel_value; - - get_volume_sizes( volume, sizes ); - - i = ROUND( x ); - if( i == sizes[X] ) - i = sizes[X]-1; - j = ROUND( y ); - if( j == sizes[Y] ) - j = sizes[Y]-1; - k = ROUND( z ); - if( k == sizes[Z] ) - k = sizes[Z]-1; - - GET_VALUE_3D( voxel_value, volume, i, j, k ); - - if( value != (Real *) 0 ) - *value = voxel_value; - - if( deriv_x != (Real *) NULL ) - { - /* --- get derivative wrt x */ - - dx = 0; - if( i == 0 ) - prev = voxel_value; - else + for_less( v, 0, n_values ) { - GET_VALUE_3D( prev, volume, i-1, j, k ); - ++dx; - } - - if( i == sizes[X]-1 ) - next = voxel_value; - else - { - GET_VALUE_3D( next, volume, i+1, j, k ); - ++dx; - } - - if( dx == 0 ) - *deriv_x = 0.0; - else - *deriv_x = (next - prev) / (Real) dx; - - /* --- get derivative wrt y */ - - dy = 0; - if( j == 0 ) - prev = voxel_value; - else - { - GET_VALUE_3D( prev, volume, i, j-1, k ); - ++dy; - } - - if( j == sizes[Y]-1 ) - next = voxel_value; - else - { - GET_VALUE_3D( next, volume, i, j+1, k ); - ++dy; - } + for_less( dim, 0, N_DIMENSIONS ) + { + n_interp_dims = 0; + for_less( c, 0, n_dims ) + { + if( interpolating_dimensions[c] ) + { + voxel[c] = second_deriv[v][dim][n_interp_dims]; + ++n_interp_dims; + } + else + voxel[c] = 0.0; + } - if( dy == 0 ) - *deriv_y = 0.0; - else - *deriv_y = (next - prev) / (Real) dy; - - /* --- get derivative wrt z */ - - dz = 0; - if( k == 0 ) - prev = voxel_value; - else - { - GET_VALUE_3D( prev, volume, i, j, k-1 ); - ++dz; - } - - if( k == sizes[Z]-1 ) - next = voxel_value; - else - { - GET_VALUE_3D( next, volume, i, j, k+1 ); - ++dz; - } - - if( dz == 0 ) - *deriv_z = 0.0; - else - *deriv_z = (next - prev) / (Real) dz; - } -} - -/* ----------------------------- MNI Header ----------------------------------- -@NAME : trilinear_interpolate_volume -@INPUT : volume - x - y - z -@OUTPUT : value - deriv_x - deriv_y - deriv_z -@RETURNS : -@DESCRIPTION: Returns the value within the volume, assuming trilinear - interpolation. -@METHOD : -@GLOBALS : -@CALLS : -@CREATED : 1993 David MacDonald -@MODIFIED : ----------------------------------------------------------------------------- */ + convert_voxel_normal_vector_to_world( volume, voxel, + &t[dim][volume->spatial_axes[X]], + &t[dim][volume->spatial_axes[Y]], + &t[dim][volume->spatial_axes[Z]] ); + } + + for_less( c, 0, n_dims ) + voxel[c] = t[c][volume->spatial_axes[X]]; -private void trilinear_interpolate_volume( - Volume volume, - Real x, - Real y, - Real z, - BOOLEAN x_use_higher, - BOOLEAN y_use_higher, - BOOLEAN z_use_higher, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z ) -{ - int i, j, k, sizes[MAX_DIMENSIONS]; - Real u, v, w; - Real c000, c001, c010, c011, c100, c101, c110, c111; - Real c00, c01, c10, c11; - Real c0, c1; - Real du00, du01, du10, du11, du0, du1; - Real dv0, dv1; - - get_volume_sizes( volume, sizes ); + convert_voxel_normal_vector_to_world( volume, voxel, + &deriv_xx[v], &ignore, &ignore ); + + for_less( c, 0, n_dims ) + voxel[c] = t[c][volume->spatial_axes[Y]]; - if( x == (Real) (sizes[X]-1) ) - { - i = sizes[X]-2; - u = 1.0; - } - else - { - i = (int) x; - u = FRACTION( x ); - if( !x_use_higher && u == 0.0 && i > 0 ) - { - --i; - u = 1.0; - } - } + convert_voxel_normal_vector_to_world( volume, voxel, + &deriv_xy[v], &deriv_yy[v], &ignore ); + + for_less( c, 0, n_dims ) + voxel[c] = t[c][volume->spatial_axes[Z]]; - if( y == (Real) (sizes[Y]-1) ) - { - j = sizes[Y]-2; - v = 1.0; - } - else - { - j = (int) y; - v = FRACTION( y ); - if( !y_use_higher && v == 0.0 && j > 0 ) - { - --j; - v = 1.0; - } - } - - if( z == (Real) (sizes[Z]-1) ) - { - k = sizes[Z]-2; - w = 1.0; - } - else - { - k = (int) z; - w = FRACTION( z ); - if( !z_use_higher && w == 0.0 && k > 0 ) - { - --k; - w = 1.0; + convert_voxel_normal_vector_to_world( volume, voxel, + &deriv_xz[v], &deriv_yz[v], &deriv_zz[v] ); } } - GET_VALUE_3D( c000, volume, i, j, k ); - GET_VALUE_3D( c001, volume, i, j, k+1 ); - GET_VALUE_3D( c010, volume, i, j+1, k ); - GET_VALUE_3D( c011, volume, i, j+1, k+1 ); - GET_VALUE_3D( c100, volume, i+1, j, k ); - GET_VALUE_3D( c101, volume, i+1, j, k+1 ); - GET_VALUE_3D( c110, volume, i+1, j+1, k ); - GET_VALUE_3D( c111, volume, i+1, j+1, k+1 ); - - du00 = c100 - c000; - du01 = c101 - c001; - du10 = c110 - c010; - du11 = c111 - c011; - - c00 = c000 + u * du00; - c01 = c001 + u * du01; - c10 = c010 + u * du10; - c11 = c011 + u * du11; - - dv0 = c10 - c00; - dv1 = c11 - c01; - - c0 = c00 + v * dv0; - c1 = c01 + v * dv1; - - if( value != (Real *) 0 ) - *value = INTERPOLATE( w, c0, c1 ); - - if( deriv_x != (Real *) 0 ) - { - du0 = INTERPOLATE( v, du00, du10 ); - du1 = INTERPOLATE( v, du01, du11 ); - - *deriv_x = INTERPOLATE( w, du0, du1 ); - *deriv_y = INTERPOLATE( w, dv0, dv1 ); - *deriv_z = (c1 - c0); - } -} - -private void trivar_interpolate_volume( - Volume volume, - Real x, - Real y, - Real z, - int degree, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_xz, - Real *deriv_yy, - Real *deriv_yz, - Real *deriv_zz ) -{ - int i, j, k, tu, tv, tw, ind, n_derivs; - Real u, v, w, bound; - Real coefs[4*4*4]; - Real derivs[3*3*3]; - int sizes[MAX_DIMENSIONS]; - - get_volume_sizes( volume, sizes ); - - bound = (degree - 2) / 2.0; - - if( x >= (Real) sizes[X] - 1.0 - bound ) - { - i = sizes[X] - degree; - u = 1.0; - } - else - { - if( x < bound ) - x = bound; - - i = (int) ( x - bound ); - u = FRACTION( x - bound ); - } - - if( y >= (Real) sizes[Y] - 1.0 - bound ) - { - j = sizes[Y] - degree; - v = 1.0; - } - else - { - if( y < bound ) - y = bound; - - j = (int) ( y - bound ); - v = FRACTION( y - bound ); - } - - if( z >= (Real) sizes[Z] - 1.0 - bound ) - { - k = sizes[Z] - degree; - w = 1.0; - } - else - { - if( z < bound ) - z = bound; - - k = (int) ( z - bound ); - w = FRACTION( z - bound ); - } - - ind = 0; - for_less( tu, 0, degree ) - for_less( tv, 0, degree ) - for_less( tw, 0, degree ) - { - GET_VALUE_3D( coefs[ind], volume, i+tu, j+tv, k+tw ); - ++ind; - } - - if( deriv_xx != NULL ) - n_derivs = 2; - else if( deriv_x != NULL ) - n_derivs = 1; - else - n_derivs = 0; - - evaluate_trivariate_catmull_spline( u, v, w, degree, coefs, n_derivs, - derivs ); - - if( deriv_xx != NULL ) - { - *deriv_xx = derivs[IJK(2,0,0,n_derivs+1,n_derivs+1)]; - *deriv_xy = derivs[IJK(1,1,0,n_derivs+1,n_derivs+1)]; - *deriv_xz = derivs[IJK(1,0,1,n_derivs+1,n_derivs+1)]; - *deriv_yy = derivs[IJK(0,2,0,n_derivs+1,n_derivs+1)]; - *deriv_yz = derivs[IJK(0,1,1,n_derivs+1,n_derivs+1)]; - *deriv_zz = derivs[IJK(0,0,2,n_derivs+1,n_derivs+1)]; - } - - if( deriv_x != NULL ) - { - *deriv_x = derivs[IJK(1,0,0,n_derivs+1,n_derivs+1)]; - *deriv_y = derivs[IJK(0,1,0,n_derivs+1,n_derivs+1)]; - *deriv_z = derivs[IJK(0,0,1,n_derivs+1,n_derivs+1)]; - } - - if( value != NULL ) - *value = derivs[IJK(0,0,0,n_derivs+1,n_derivs+1)]; + return( inside ); } - -private void bicubic_interpolate_volume( - Volume volume, - Real x, - Real y, - Real z, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_yy ) -{ - int i, j, k, tu, tv, ind, n_derivs; - Real u, v; - Real coefs[4*4]; - Real derivs[3*3]; - int sizes[MAX_DIMENSIONS]; - - get_volume_sizes( volume, sizes ); - - if( x >= (Real) sizes[X] - 1.5 ) - { - i = sizes[X]-2; - u = 1.0; - } - else - { - i = (int) x; - u = FRACTION( x ); - } - - if( y >= (Real) sizes[Y] - 1.5 ) - { - j = sizes[Y]-2; - v = 1.0; - } - else - { - j = (int) y; - v = FRACTION( y ); - } - - if( z == (Real) sizes[Z] - 1.5 ) - { - k = sizes[Z]-2; - } - else - { - k = (int) z; - } - - ind = 0; - for_less( tu, 0, 4 ) - for_less( tv, 0, 4 ) - { - GET_VALUE_3D( coefs[ind], volume, i-1+tu, j-1+tv, k ); - ++ind; - } - - if( deriv_xx != NULL ) - n_derivs = 2; - else if( deriv_x != NULL ) - n_derivs = 1; - else - n_derivs = 0; - - evaluate_bivariate_catmull_spline( u, v, 4, coefs, n_derivs, derivs ); - - if( deriv_xx != NULL ) - { - *deriv_xx = derivs[IJ(2,0,n_derivs+1)]; - *deriv_xy = derivs[IJ(1,1,n_derivs+1)]; - *deriv_yy = derivs[IJ(0,2,n_derivs+1)]; - } - - if( deriv_x != NULL ) - { - *deriv_x = derivs[IJ(1,0,n_derivs+1)]; - *deriv_y = derivs[IJ(0,1,n_derivs+1)]; - } - - if( value != NULL ) - *value = derivs[IJ(0,0,n_derivs+1)]; -} - -/* ----------------------------- MNI Header ----------------------------------- -@NAME : evaluate_3D_volume -@INPUT : volume - x - y - z -@OUTPUT : value - deriv_x - deriv_y - deriv_z -@RETURNS : -@DESCRIPTION: Takes a voxel space position and evaluates the value within - the volume by trilinear interpolation. - If deriv_x is not a null pointer, then the 3 derivatives are passed - back. -@CREATED : Mar 1993 David MacDonald -@MODIFIED : ----------------------------------------------------------------------------- */ - -public void evaluate_3D_volume( - Volume volume, - Real x, - Real y, - Real z, - int degrees_continuity, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_z, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_xz, - Real *deriv_yy, - Real *deriv_yz, - Real *deriv_zz ) -{ - int sizes[MAX_DIMENSIONS]; - - if( get_volume_n_dimensions(volume) != 3 ) - { - handle_internal_error( "evaluate_3D_volume: volume must be 3D.\n" ); - } - - get_volume_sizes( volume, sizes ); - - if( x < -0.5 || x > (Real) sizes[X] - 0.5 || - y < -0.5 || y > (Real) sizes[Y] - 0.5 || - z < -0.5 || z > (Real) sizes[Z] - 0.5 ) - { - *value = get_volume_voxel_min( volume ); - if( deriv_x != (Real *) NULL ) - { - *deriv_x = 0.0; - *deriv_y = 0.0; - *deriv_z = 0.0; - } - if( deriv_xx != (Real *) NULL ) - { - *deriv_xx = 0.0; - *deriv_xy = 0.0; - *deriv_xz = 0.0; - *deriv_yy = 0.0; - *deriv_yz = 0.0; - *deriv_zz = 0.0; - } - return; - } - - if( x < (Real) degrees_continuity * 0.5 || - x > (Real) (sizes[X]-1) - (Real) degrees_continuity * 0.5 || - y < (Real) degrees_continuity * 0.5 || - y > (Real) (sizes[Y]-1) - (Real) degrees_continuity * 0.5 || - z < (Real) degrees_continuity * 0.5 || - z > (Real) (sizes[Z]-1) - (Real) degrees_continuity * 0.5 ) - { - degrees_continuity = -1; - } - - if( degrees_continuity < 1 && deriv_xx != (Real *) NULL ) - { - *deriv_xx = 0.0; - *deriv_xy = 0.0; - *deriv_xz = 0.0; - *deriv_yy = 0.0; - *deriv_yz = 0.0; - *deriv_zz = 0.0; - } - - switch( degrees_continuity ) - { - case -1: - triconstant_interpolate_volume( volume, x, y, z, value, - deriv_x, deriv_y, deriv_z ); - break; - - case 0: - trilinear_interpolate_volume( volume, x, y, z, - TRUE, TRUE, TRUE, value, - deriv_x, deriv_y, deriv_z ); - break; - - case 1: - case 2: - trivar_interpolate_volume( volume, x, y, z, degrees_continuity+2, - value, - deriv_x, deriv_y, deriv_z, - deriv_xx, deriv_xy, deriv_xz, - deriv_yy, deriv_yz, deriv_zz ); - break; - - default: - handle_internal_error( "evaluate_3D_volume: invalid continuity" ); - } -} - -/* ----------------------------- MNI Header ----------------------------------- -@NAME : evaluate_3D_slice -@INPUT : volume - x - y - z -@OUTPUT : value - deriv_x - deriv_y - deriv_xx - deriv_xy - deriv_yy -@RETURNS : -@DESCRIPTION: Takes a voxel position and evaluates the value within - the volume by bilinear interpolation within the slice. - If deriv_x is not a null pointer, then the - derivatives are passed back. -@CREATED : Mar 1993 David MacDonald -@MODIFIED : ----------------------------------------------------------------------------- */ - -public void evaluate_3D_slice( - Volume volume, - Real x, - Real y, - Real z, - Real *value, - Real *deriv_x, - Real *deriv_y, - Real *deriv_xx, - Real *deriv_xy, - Real *deriv_yy ) -{ - int sizes[MAX_DIMENSIONS]; - - if( get_volume_n_dimensions(volume) != 3 ) - { - handle_internal_error( "evaluate_3D_slice: volume must be 3D.\n" ); - } - - get_volume_sizes( volume, sizes ); - - if( x < 1.0 || x > (Real) sizes[X] - 2.0 || - y < 1.0 || y > (Real) sizes[Y] - 2.0 || - z < 1.0 || z > (Real) sizes[Z] - 2.0 ) - { - *value = get_volume_voxel_min( volume ); - if( deriv_x != (Real *) NULL ) - { - *deriv_x = 0.0; - *deriv_y = 0.0; - } - if( deriv_xx != (Real *) NULL ) - { - *deriv_xx = 0.0; - *deriv_xy = 0.0; - *deriv_yy = 0.0; - } - return; - } - - bicubic_interpolate_volume( volume, x, y, z, value, - deriv_x, deriv_y, - deriv_xx, deriv_xy, deriv_yy ); -}