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 }