00001
#include <volume_io/internal_volume_io.h>
00002
#include <bicpl/deform.h>
00003
00004 public BOOLEAN
is_point_inside_surface(
00005 Volume volume,
00006 Volume label_volume,
00007
int continuity,
00008 Real voxel[],
00009 Vector *direction,
00010
boundary_definition_struct *boundary_def )
00011 {
00012 BOOLEAN active;
00013 Real value, mag, dx, dy, dz, dot_product;
00014 Real derivs[MAX_DIMENSIONS], *deriv_ptr[1];
00015 Real min_dot, max_dot;
00016
00017 active =
get_volume_voxel_activity( label_volume, voxel,
FALSE );
00018
00019
if( !active )
00020
return(
FALSE );
00021
00022 deriv_ptr[0] = derivs;
00023
00024 evaluate_volume( volume, voxel, NULL, continuity,
FALSE,
00025 get_volume_real_min(volume),
00026 &value, deriv_ptr, NULL );
00027
00028
if( value < boundary_def->
min_isovalue )
00029
return(
FALSE );
00030
else if( value >= boundary_def->
max_isovalue )
00031
return(
TRUE );
00032
00033 convert_voxel_normal_vector_to_world( volume, derivs,
00034 &dx, &dy, &dz );
00035
00036 mag = dx * dx + dy * dy + dz * dz;
00037
00038
if( mag <
00039 boundary_def->
gradient_threshold * boundary_def->
gradient_threshold )
00040
return(
FALSE );
00041
00042
if( mag == 0.0 )
00043 mag = 1.0;
00044
00045 dot_product = dx * (Real) Vector_x(*direction) +
00046 dy * (Real) Vector_y(*direction) +
00047 dz * (Real) Vector_z(*direction);
00048
00049 min_dot = boundary_def->
min_dot_product;
00050 max_dot = boundary_def->
max_dot_product;
00051
00052
if( min_dot <= -1.0 && max_dot == 0.0 )
00053
return( dot_product <= 0.0 );
00054
else if( min_dot == 0.0 && max_dot >= 1.0 )
00055
return( dot_product >= 0.0 );
00056
else if( min_dot <= -1.0 && max_dot >= 1.0 )
00057
return(
TRUE );
00058
else
00059 {
00060 dot_product /= sqrt(mag);
00061
00062
return( dot_product >= min_dot && dot_product <= max_dot );
00063 }
00064 }
00065
00066 public void get_centre_of_cube(
00067 Point *cube,
00068
int sizes[3],
00069 Point *centre )
00070 {
00071
int c;
00072
00073 for_less( c, 0, 3 )
00074 {
00075
if( sizes[c] > 1 )
00076 Point_coord(*centre,c) = (Point_coord_type) (
00077 ((Real) Point_coord(cube[0],c) +
00078 (Real) Point_coord(cube[1],c)) / 2.0);
00079
else
00080 Point_coord(*centre,c) = Point_coord(cube[0],c);
00081 }
00082 }
00083
00084 public BOOLEAN
contains_value(
00085 Real values[2][2][2],
00086
int sizes[3] )
00087 {
00088 BOOLEAN under_found, over_found;
00089
int x,
y, z;
00090
00091 for_less( x, 0, sizes[X] )
00092 {
00093 for_less(
y, 0, sizes[Y] )
00094 {
00095 for_less( z, 0, sizes[Z] )
00096 {
00097
if( values[x][
y][z] == 0.0 )
00098 {
00099
return(
TRUE );
00100 }
00101
else if( x == 0 &&
y == 0 && z == 0 )
00102 {
00103 under_found = (values[x][
y][z] < 0.0);
00104 over_found = (values[x][
y][z] > 0.0);
00105 }
00106
else if( values[x][
y][z] < 0.0 )
00107 {
00108
if( over_found )
00109
return(
TRUE );
00110 under_found =
TRUE;
00111 }
00112
else if( values[x][
y][z] > 0.0 )
00113 {
00114
if( under_found )
00115
return(
TRUE );
00116 over_found =
TRUE;
00117 }
00118 }
00119 }
00120 }
00121
00122
return(
FALSE );
00123 }
00124
00125 public BOOLEAN
cube_is_small_enough(
00126 Point cube[2],
00127
int sizes[3],
00128 Real min_cube_size )
00129 {
00130 BOOLEAN small_enough;
00131 Real size_in_dimension;
00132
int c;
00133
00134 small_enough =
TRUE;
00135
00136 for_less( c, 0, 3 )
00137 {
00138 size_in_dimension = (Real) Point_coord(cube[sizes[c]-1],c ) -
00139 (Real) Point_coord(cube[0],c );
00140
if( size_in_dimension > min_cube_size )
00141 {
00142 small_enough =
FALSE;
00143
break;
00144 }
00145 }
00146
00147
return( small_enough );
00148 }
00149
00150 public void initialize_deform_stats(
00151
deform_stats *stats )
00152 {
00153
int i;
00154
00155 stats->
average = 0.0;
00156 stats->
maximum = 0.0;
00157
00158 for_less( i, 0,
N_DEFORM_HISTOGRAM )
00159 stats->
n_below[i] = 0;
00160 }
00161
00162 public void record_error_in_deform_stats(
00163
deform_stats *stats,
00164 Real error )
00165 {
00166
int i;
00167
00168 stats->
average += error;
00169
if( error > stats->
maximum )
00170 stats->
maximum = error;
00171
00172 i =
N_DEFORM_HISTOGRAM-1;
00173
while( i >= 0 && error <= (Real) (i+1) )
00174 {
00175 ++stats->
n_below[i];
00176 --i;
00177 }
00178 }
00179
00180 public void print_deform_stats(
00181
deform_stats *stats,
00182
int n_points )
00183 {
00184
int i, n_above;
00185
00186 print(
"avg %5.2f max %6.2f hist:",
00187 stats->
average / (Real) n_points, stats->
maximum );
00188
00189 for_less( i, 0,
N_DEFORM_HISTOGRAM )
00190 {
00191
if( i <
N_DEFORM_HISTOGRAM-1 )
00192 n_above = stats->
n_below[i+1] - stats->
n_below[i];
00193
else
00194 n_above = n_points - stats->
n_below[i];
00195
00196
if( stats->
n_below[i] == n_points )
00197
break;
00198
00199
if( n_above == 0 )
00200 print(
" " );
00201
else if( n_above < 100 )
00202 print(
" %4d", n_above );
00203
else
00204 print(
" %3.0f%%", 100.0 * (Real) n_above / (Real) n_points );
00205 }
00206 print(
"\n" );
00207 }
00208
00209 public BOOLEAN
get_max_point_cube_distance(
00210 Point cube[2],
00211
int sizes[3],
00212 Point *point,
00213 Real *distance )
00214 {
00215
int c;
00216 Real dist_to_low, dist_to_high, dist, max_dist;
00217
00218 max_dist = 0.0;
00219
00220 for_less( c, 0, 3 )
00221 {
00222
if( sizes[c] > 1 )
00223 {
00224 dist_to_low = (Real) Point_coord(*point,c) -
00225 (Real) Point_coord(cube[0],c);
00226 dist_to_high = (Real) Point_coord(cube[1],c) -
00227 (Real) Point_coord(*point,c);
00228
00229 dist = MAX( dist_to_low, dist_to_high );
00230 max_dist += dist * dist;
00231 }
00232 }
00233
00234 max_dist = sqrt( (
double) max_dist );
00235
00236
if( max_dist < *distance )
00237 {
00238 *distance = max_dist;
00239
return(
TRUE );
00240 }
00241
else
00242
return(
FALSE );
00243 }
00244
00245 public void initialize_deformation_parameters(
00246
deform_struct *deform )
00247 {
00248 deform->
deform_data.
type =
VOLUME_DATA;
00249
00250
initialize_deformation_model( &deform->
deformation_model );
00251 deform->
deformation_model.
position_constrained =
FALSE;
00252 deform->
fractional_step = 0.3;
00253 deform->
max_step = 0.3;
00254 deform->
stop_threshold = 0.0;
00255 deform->
degrees_continuity = 0;
00256 deform->
boundary_definition.
min_isovalue = 90.0;
00257 deform->
boundary_definition.
max_isovalue = 90.0;
00258 deform->
boundary_definition.
gradient_threshold = 0.0;
00259 deform->
boundary_definition.
min_dot_product = -2.0;
00260 deform->
boundary_definition.
max_dot_product = 0.0;
00261 deform->
boundary_definition.
normal_direction =
TOWARDS_LOWER;
00262 deform->
max_iterations = 1000000;
00263 deform->
stop_threshold = 0.0;
00264
00265 deform->
n_movements_alloced = 0;
00266 deform->
movement_threshold = 0.0;
00267 }
00268
00269 public void delete_deformation_parameters(
00270
deform_struct *deform )
00271 {
00272
delete_deformation_model( &deform->
deformation_model );
00273
00274
if( deform->
n_movements_alloced > 0 )
00275 FREE( deform->
prev_movements );
00276 }
00277
00278 public void set_boundary_definition(
00279
boundary_definition_struct *boundary_def,
00280 Real min_value,
00281 Real max_value,
00282 Real grad_threshold,
00283 Real angle,
00284
char direction,
00285 Real tolerance )
00286 {
00287 Real cosine;
00288
00289 boundary_def->
min_isovalue = MIN( min_value, max_value );
00290 boundary_def->
max_isovalue = MAX( min_value, max_value );
00291 boundary_def->
gradient_threshold = grad_threshold;
00292 boundary_def->
tolerance = tolerance;
00293
00294
if( angle == 90.0 )
00295 cosine = 0.0;
00296
else
00297 cosine = cos( angle * DEG_TO_RAD );
00298
00299
if( direction ==
'-' )
00300 {
00301 boundary_def->
normal_direction =
TOWARDS_LOWER;
00302 boundary_def->
min_dot_product = -2.0;
00303 boundary_def->
max_dot_product = -cosine;
00304 }
00305
else if( direction ==
'+' )
00306 {
00307 boundary_def->
normal_direction =
TOWARDS_HIGHER;
00308 boundary_def->
min_dot_product = cosine;
00309 boundary_def->
max_dot_product = 2.0;
00310 }
00311
else
00312 {
00313 boundary_def->
normal_direction =
ANY_DIRECTION;
00314 boundary_def->
min_dot_product = -2.0;
00315 boundary_def->
max_dot_product = 2.0;
00316 }
00317 }
00318
00319 public void initialize_lookup_volume_coeficients(
00320
voxel_coef_struct *lookup )
00321 {
00322
lookup->n_in_hash = 0;
00323 }
00324
00325 public void lookup_volume_coeficients(
00326
voxel_coef_struct *lookup,
00327 Volume volume,
00328
int degrees_continuity,
00329
int x,
00330
int y,
00331
int z,
00332 Real c[] )
00333 {
00334
int key, i, offset, n, sizes[N_DIMENSIONS];
00335
voxel_lin_coef_struct *data;
00336
00337 offset = -(degrees_continuity + 1) / 2;
00338 n = degrees_continuity + 2;
00339 get_volume_sizes( volume, sizes );
00340
00341
if( x + offset < 0 || x + offset + n >= sizes[X] ||
00342
y + offset < 0 || y + offset + n >= sizes[Y] ||
00343 z + offset < 0 || z + offset + n >= sizes[Z] )
00344 {
00345 for_less( i, 0, n * n * n )
00346 c[i] = 0.0;
00347
return;
00348 }
00349
00350
if(
lookup == NULL || degrees_continuity != 0 )
00351 {
00352 get_volume_value_hyperslab_3d( volume, x+offset,
y+offset, z+offset,
00353 n, n, n, c );
00354
return;
00355 }
00356
00357
if(
lookup->n_in_hash == 0 )
00358 {
00359
initialize_hash_table( &
lookup->hash,
MAX_IN_VOXEL_COEF_LOOKUP * 10,
00360
sizeof(
voxel_lin_coef_struct *),
00361 0.5, 0.25 );
00362
lookup->head = NULL;
00363
lookup->tail = NULL;
00364 }
00365
00366 key = IJK( x,
y, z, sizes[Y], sizes[Z] );
00367
00368 data = NULL;
00369
00370
if( !
lookup_in_hash_table( &
lookup->hash, key, (
void *) &data ) )
00371 {
00372
if(
lookup->n_in_hash >=
MAX_IN_VOXEL_COEF_LOOKUP )
00373 {
00374
if( !
remove_from_hash_table( &
lookup->hash,
lookup->tail->hash_key,
00375 (
void *) &data))
00376 handle_internal_error(
"lookup_volume_coeficients" );
00377
00378
lookup->tail = data->prev;
00379
if(
lookup->tail == NULL )
00380
lookup->head = NULL;
00381
else
00382
lookup->tail->
next = NULL;
00383 }
00384
else
00385 {
00386 ALLOC( data, 1 );
00387 ++
lookup->n_in_hash;
00388 }
00389
00390 data->hash_key = key;
00391 get_volume_value_hyperslab_3d( volume, x,
y, z, 2, 2, 2, data->coefs );
00392
00393 data->next =
lookup->head;
00394 data->prev = NULL;
00395
if(
lookup->head != NULL )
00396
lookup->head->prev = data;
00397
else
00398
lookup->tail = data;
00399
lookup->head = data;
00400
00401
insert_in_hash_table( &
lookup->hash, key, (
void *) &data );
00402 }
00403
00404 for_less( i, 0, 8 )
00405 c[i] = data->coefs[i];
00406 }
00407
00408 public void delete_lookup_volume_coeficients(
00409
voxel_coef_struct *lookup )
00410 {
00411
voxel_lin_coef_struct *ptr, *next;
00412
00413 ptr =
lookup->head;
00414
while( ptr != NULL )
00415 {
00416 next = ptr->
next;
00417 FREE( ptr );
00418 ptr = next;
00419 }
00420
00421
if(
lookup->n_in_hash > 0 )
00422
delete_hash_table( &
lookup->hash );
00423 }