00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
#include  <volume_io/internal_volume_io.h>
00017 
#include  <bicpl/data_structures.h>
00018 
00019 
#ifndef lint
00020 
static char rcsid[] = 
"$Header: /software/source//libraries/bicpl/Data_structures/bintree.c,v 1.9 2000/02/06 15:30:09 stever Exp $";
00021 
#endif
00022 
00023 
private  Status  
io_range(
00024     FILE             *file,
00025     IO_types         direction,
00026     File_formats     format,
00027     
range_struct     *range );
00028 
private  Status  
output_bintree_node(
00029     FILE                    *file,
00030     File_formats            format,
00031     
bintree_node_struct     *node );
00032 
private  Status  
input_bintree_node(
00033     FILE                    *file,
00034     File_formats            format,
00035     
bintree_node_struct     **node );
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 public  void  initialize_bintree(
00058     Real                 x_min,
00059     Real                 x_max,
00060     Real                 y_min,
00061     Real                 y_max,
00062     Real                 z_min,
00063     Real                 z_max,
00064     
bintree_struct_ptr   bintree )
00065 {
00066     bintree->
range.
limits[X][0] = (
float) x_min;
00067     bintree->
range.
limits[X][1] = (
float) x_max;
00068     bintree->
range.
limits[Y][0] = (
float) y_min;
00069     bintree->
range.
limits[Y][1] = (
float) y_max;
00070     bintree->
range.
limits[Z][0] = (
float) z_min;
00071     bintree->
range.
limits[Z][1] = (
float) z_max;
00072 
00073     bintree->
n_nodes = 0;
00074     bintree->
root = (
bintree_node_struct *) 0;
00075 }
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 public  void  delete_bintree_node(
00091     
bintree_node_struct   *node )
00092 {
00093     FREE( node );
00094 }
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 private  void  recursive_delete_bintree(
00110     
bintree_node_struct   *node )
00111 {
00112     
bintree_node_struct  *left, *right;
00113 
00114     
if( 
get_bintree_left_child( node, &left ) )
00115         
recursive_delete_bintree( left );
00116     
if( 
get_bintree_right_child( node, &right ) )
00117         
recursive_delete_bintree( right );
00118 
00119     
delete_bintree_node( node );
00120 }
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 public  void  delete_bintree(
00136     
bintree_struct_ptr   bintree )
00137 {
00138     
if( bintree->
root != NULL )
00139         
recursive_delete_bintree( bintree->
root );
00140 }
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 public  void  get_bintree_limits(
00156     
bintree_struct_ptr    bintree,
00157     
range_struct          *limits )
00158 {
00159     *limits = bintree->
range;
00160 }
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 private  void  set_bintree_child(
00178     
bintree_node_struct   *node,
00179     
int                   which,
00180     
bintree_node_struct   *child )
00181 {
00182     
int                   ind;
00183 
00184     
if( which == 
LEFT_CHILD )
00185         ind = 0;
00186     
else
00187     {
00188         
if( (node->
node_info & 
LEFT_CHILD_EXISTS) != 0 )
00189             ind = 1;
00190         
else
00191             ind = 0;
00192     }
00193 
00194     node->
data.children[ind] = child;
00195 }
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 public  bintree_node_struct  *
create_bintree_internal_node(
00211     
int                   split_coord,
00212     Real                  split_position,
00213     
bintree_node_struct   *left,
00214     
bintree_node_struct   *right )
00215 {
00216     
bintree_node_struct  *node;
00217     
int                  n_children, children_bits;
00218 
00219     n_children = 0;
00220 
00221     children_bits = 0;
00222 
00223     
if( left != NULL )
00224     {
00225         children_bits |= 
LEFT_CHILD_EXISTS;
00226         ++n_children;
00227     }
00228     
if( right != NULL )
00229     {
00230         children_bits |= 
RIGHT_CHILD_EXISTS;
00231         ++n_children;
00232     }
00233 
00234     
if( n_children == 0 )
00235     {
00236         handle_internal_error( 
"create_bintree_internal_node" );
00237         
return( NULL );
00238     }
00239 
00240     ALLOC_VAR_SIZED_STRUCT( node, 
bintree_node_struct *, n_children );
00241 
00242     node->
node_info = (
unsigned char) (split_coord | children_bits);
00243     node->
split_position = (
float) split_position;
00244 
00245     
00246 
00247     
if( left != NULL )
00248         
set_bintree_child( node, 
LEFT_CHILD, left );
00249 
00250     
if( right != NULL )
00251         
set_bintree_child( node, 
RIGHT_CHILD, right );
00252 
00253     
return( node );
00254 }
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 public  bintree_node_struct  *
create_bintree_leaf(
00272     Real                  split_position,
00273     
int                   n_objects,
00274     
int                   object_list[] )
00275 {
00276     
bintree_node_struct  *node;
00277     
int                  i, n_alloc, *node_list, n_objects_bits;
00278 
00279     
if( n_objects <= 
MAX_NODE_INFO_OBJECTS )
00280     {
00281         n_alloc = n_objects;
00282         n_objects_bits = n_objects;
00283     }
00284     
else
00285     {
00286         n_alloc = n_objects + 1;
00287         n_objects_bits = 0;
00288     }
00289 
00290     ALLOC_VAR_SIZED_STRUCT( node, 
int, n_alloc );
00291 
00292     node->
node_info = (
unsigned char)
00293                 (
LEAF_SIGNAL | (n_objects_bits << 
NODE_INFO_OBJECTS_SHIFT));
00294     node->
split_position = (
float) split_position;
00295 
00296     node_list = node->
data.object_list;
00297 
00298     
if( n_objects > 
MAX_NODE_INFO_OBJECTS )
00299     {
00300         node_list[0] = n_objects;
00301         ++node_list;
00302     }
00303 
00304     for_less( i, 0, n_objects )
00305         node_list[i] = object_list[i];
00306 
00307     
return( node );
00308 }
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 public  BOOLEAN  
bintree_node_is_leaf(
00325     
bintree_node_struct  *node )
00326 {
00327     
return( (node->
node_info & 
SUBDIVISION_AXIS_BITS) == 
LEAF_SIGNAL );
00328 }
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 public  int  get_bintree_leaf_objects(
00345     
bintree_node_struct  *node,
00346     
int                  *object_list[] )
00347 {
00348     
int    *node_list, n_objects;
00349 
00350     node_list = node->
data.object_list;
00351     n_objects = node->
node_info >> 
NODE_INFO_OBJECTS_SHIFT;
00352 
00353     
if( n_objects == 0 )
00354     {
00355         n_objects = node_list[0];
00356         ++node_list;
00357     }
00358 
00359     
if( n_objects > 0 )
00360         *object_list = node_list;
00361 
00362     
return( n_objects );
00363 }
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 public  BOOLEAN  
get_bintree_left_child_ptr(
00381     
bintree_node_struct  *node,
00382     
bintree_node_struct  ***ptr_to_left_child )
00383 {
00384     BOOLEAN               child_exists;
00385 
00386     child_exists = !
bintree_node_is_leaf(node) &&
00387                    (node->
node_info & 
LEFT_CHILD_EXISTS) != 0;
00388 
00389     
if( child_exists )
00390         *ptr_to_left_child = &node->
data.children[0];
00391 
00392     
return( child_exists );
00393 }
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 public  BOOLEAN  
get_bintree_left_child(
00410     
bintree_node_struct  *node,
00411     
bintree_node_struct  **left_child )
00412 {
00413     BOOLEAN              child_exists;
00414     
bintree_node_struct  **ptr;
00415 
00416     child_exists = 
get_bintree_left_child_ptr( node, &ptr );
00417 
00418     
if( child_exists )
00419         *left_child = *ptr;
00420 
00421     
return( child_exists );
00422 }
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 public  BOOLEAN  
get_bintree_right_child_ptr(
00439     
bintree_node_struct  *node,
00440     
bintree_node_struct  ***ptr_to_right_child )
00441 {
00442     BOOLEAN               child_exists;
00443     
int                   ind;
00444 
00445     child_exists = !
bintree_node_is_leaf(node) &&
00446                    (node->
node_info & 
RIGHT_CHILD_EXISTS) != 0;
00447 
00448     
if( child_exists )
00449     {
00450         
if( (node->
node_info & 
LEFT_CHILD_EXISTS) != 0 )
00451             ind = 1;
00452         
else
00453             ind = 0;
00454 
00455         *ptr_to_right_child = &node->
data.children[ind];
00456     }
00457 
00458     
return( child_exists );
00459 }
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 public  BOOLEAN  
get_bintree_right_child(
00476     
bintree_node_struct  *node,
00477     
bintree_node_struct  **right_child )
00478 {
00479     BOOLEAN              child_exists;
00480     
bintree_node_struct  **ptr;
00481 
00482     child_exists = 
get_bintree_right_child_ptr( node, &ptr );
00483 
00484     
if( child_exists )
00485         *right_child = *ptr;
00486 
00487     
return( child_exists );
00488 }
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 public  int  get_node_split_axis(
00505     
bintree_node_struct  *node )
00506 {
00507     
return( node->
node_info & 
SUBDIVISION_AXIS_BITS );
00508 }
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 public  Real  
get_node_split_position(
00524     
bintree_node_struct  *node )
00525 {
00526     
return( (Real) node->
split_position );
00527 }
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 public  BOOLEAN  
point_within_range(
00544     Point         *point,
00545     
range_struct  *range )
00546 {
00547     BOOLEAN   within;
00548 
00549     within = (Point_x(*point) >= range->
limits[X][0] &&
00550               Point_x(*point) <= range->
limits[X][1] &&
00551               Point_y(*point) >= range->
limits[Y][0] &&
00552               Point_y(*point) <= range->
limits[Y][1] &&
00553               Point_z(*point) >= range->
limits[Z][0] &&
00554               Point_z(*point) <= range->
limits[Z][1]);
00555 
00556     
return( within );
00557 }
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 public  Real  
range_volume(
00573     
range_struct  *range )
00574 {
00575     
return( ((Real) range->
limits[X][1] - (Real) range->
limits[X][0]) *
00576             ((Real) range->
limits[Y][1] - (Real) range->
limits[Y][0]) *
00577             ((Real) range->
limits[Z][1] - (Real) range->
limits[Z][0]) );
00578 }
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 public  Real  
range_surface_area(
00594     
range_struct  *range )
00595 {
00596     Real   dx, dy, dz;
00597 
00598     dx = (Real) range->
limits[X][1] - (Real) range->
limits[X][0];
00599     dy = (Real) range->
limits[Y][1] - (Real) range->
limits[Y][0];
00600     dz = (Real) range->
limits[Z][1] - (Real) range->
limits[Z][0];
00601 
00602     
return( 2.0 * (dx * dy + dy * dz + dz * dx) );
00603 }
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 public  Status  
io_bintree(
00623     FILE                 *file,
00624     IO_types             direction,
00625     File_formats         format,
00626     
bintree_struct_ptr   bintree )
00627 {
00628     Status   status;
00629 
00630     status = 
io_range( file, direction, format, &bintree->
range );
00631 
00632     
if( status == OK && direction == WRITE_FILE )
00633         status = 
output_bintree_node( file, format, bintree->
root );
00634     
else if( status == OK && direction == READ_FILE )
00635         status = 
input_bintree_node( file, format, &bintree->
root );
00636 
00637     
return( status );
00638 }
00639 
00640 
00641 
00642 
00643 
00644 
00645 
00646 
00647 
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 private  Status  
io_range(
00657     FILE             *file,
00658     IO_types         direction,
00659     File_formats     format,
00660     
range_struct     *range )
00661 {
00662     Status   status;
00663     
int      c, l;
00664 
00665     status = OK;
00666 
00667     for_less( c, 0, N_DIMENSIONS )
00668     {
00669         for_less( l, 0, 2 )
00670         {
00671             
if( status == OK )
00672             {
00673                 status = io_float( file, direction, format,
00674                                    &range->
limits[c][l] );
00675             }
00676         }
00677     }
00678 
00679     
return( status );
00680 }
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 private  Status  
output_leaf_node(
00698     FILE                    *file,
00699     File_formats            format,
00700     
bintree_node_struct     *node )
00701 {
00702     Status  status;
00703     
int     *object_list, n_objects;
00704 
00705     status = OK ;
00706 
00707     n_objects = 
get_bintree_leaf_objects( node, &object_list );
00708 
00709     
if( n_objects > 
MAX_NODE_INFO_OBJECTS )
00710         status = io_int( file, WRITE_FILE, format, &n_objects );
00711 
00712     
if( status == OK )
00713         status = io_ints( file, WRITE_FILE, format, n_objects, &object_list );
00714 
00715     
return( status );
00716 }
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 private  Status  
output_bintree_node(
00734     FILE                    *file,
00735     File_formats            format,
00736     
bintree_node_struct     *node )
00737 {
00738     Status               status;
00739     
bintree_node_struct  *left, *right;
00740 
00741     status = io_binary_data( file, WRITE_FILE, &node->
node_info,
00742                              
sizeof(node->
node_info), 1 );
00743 
00744     
if( status == OK )
00745         status = io_float( file, WRITE_FILE, format, &node->
split_position );
00746 
00747     
if( status == OK )
00748     {
00749         
if( 
bintree_node_is_leaf( node ) )
00750         {
00751             status = 
output_leaf_node( file, format, node );
00752         }
00753         
else
00754         {
00755             
if( 
get_bintree_left_child( node, &left ) )
00756                 status = 
output_bintree_node( file, format, left );
00757             
if( status == OK && 
get_bintree_right_child( node, &right ) )
00758                 status = 
output_bintree_node( file, format, right );
00759         }
00760     }
00761 
00762     
return( status );
00763 }
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 
00778 
00779 private  Status  
input_bintree_node(
00780     FILE                    *file,
00781     File_formats            format,
00782     
bintree_node_struct     **node )
00783 {
00784     Status               status;
00785     
node_info_type       node_info;
00786     
float                split_position;
00787     
int                  n_objects, *object_list;
00788     
bintree_node_struct  *left, *right;
00789 
00790     *node = NULL;
00791 
00792     status = io_binary_data( file, READ_FILE, &node_info, 
sizeof(node_info), 1);
00793 
00794     
if( status == OK )
00795         status = io_float( file, READ_FILE, format, &split_position );
00796 
00797     
if( (node_info & 
SUBDIVISION_AXIS_BITS) == 
LEAF_SIGNAL )
00798     {
00799         n_objects = node_info >> 
NODE_INFO_OBJECTS_SHIFT;
00800 
00801         
if( n_objects == 0 )
00802             status = io_int( file, READ_FILE, format, &n_objects );
00803 
00804         
if( status == OK && n_objects > 0 )
00805             status = io_ints( file, READ_FILE, format, n_objects, &object_list);
00806 
00807         
if( status == OK )
00808         {
00809             *node = 
create_bintree_leaf( (Real) split_position,
00810                                          n_objects, object_list );
00811             
if( n_objects > 0 )
00812                 FREE( object_list );
00813         }
00814     }
00815     
else
00816     {
00817         status = 
input_bintree_node( file, format, &left );
00818         
if( status == OK )
00819             status = 
input_bintree_node( file, format, &right );
00820 
00821         
if( status == OK )
00822             *node = 
create_bintree_internal_node(
00823                                    node_info & 
SUBDIVISION_AXIS_BITS,
00824                                    (Real) split_position, left, right );
00825     }
00826 
00827     
return( status );
00828 }