Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

build_bintree.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 00013 ---------------------------------------------------------------------------- */ 00014 00015 #include <volume_io/internal_volume_io.h> 00016 #include <bicpl/data_structures.h> 00017 00018 #ifndef lint 00019 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Data_structures/build_bintree.c,v 1.12 2000/02/06 15:30:10 stever Exp $"; 00020 #endif 00021 00022 #define NODE_VISIT_COST 0.02 00023 #define NET_CHANGE_THRESHOLD 0.0 00024 00025 typedef struct 00026 { 00027 bintree_node_struct **ptr_to_node; 00028 range_struct limits; 00029 } leaf_queue_type; 00030 00031 typedef PRIORITY_QUEUE_STRUCT( leaf_queue_type ) leaf_queue_struct; 00032 00033 /*---------------- private functions ------------------------- */ 00034 00035 private void subdivide_bintree( 00036 bintree_struct_ptr bintree, 00037 int max_nodes, 00038 int n_objects, 00039 range_struct bound_vols[] ); 00040 private void split_node( 00041 range_struct bound_vols[], 00042 bintree_node_struct **ptr_to_node, 00043 range_struct *limits, 00044 int *n_nodes, 00045 range_struct *left_limits, 00046 Real *left_cost, 00047 range_struct *right_limits, 00048 Real *right_cost ); 00049 private void create_leaf_queue( 00050 leaf_queue_struct *leaf_queue ); 00051 private void delete_leaf_queue( 00052 leaf_queue_struct *leaf_queue ); 00053 private BOOLEAN leaf_queue_empty( 00054 leaf_queue_struct *leaf_queue ); 00055 private void insert_in_leaf_queue( 00056 leaf_queue_struct *leaf_queue, 00057 bintree_node_struct **ptr_to_node, 00058 Real node_cost, 00059 range_struct *limits ); 00060 private void remove_from_leaf_queue( 00061 leaf_queue_struct *leaf_queue, 00062 bintree_node_struct ***ptr_to_node, 00063 range_struct *limits ); 00064 private BOOLEAN node_tightly_bounds_object( 00065 range_struct *bound_vol, 00066 range_struct *limits ); 00067 private void recursive_efficiency_count( 00068 bintree_node_struct *node, 00069 range_struct *limits, 00070 Real *avg_nodes_visited, 00071 Real *avg_objects_visited ); 00072 private Real node_visit_estimation( 00073 range_struct *limits ); 00074 00075 /* ---------------------------------------------------------- */ 00076 00077 #define FACTOR 1.0e-4 00078 00079 /* ----------------------------- MNI Header ----------------------------------- 00080 @NAME : create_object_bintree 00081 @INPUT : n_objects 00082 bound_vols 00083 max_nodes 00084 @OUTPUT : bintree 00085 @RETURNS : 00086 @DESCRIPTION: Creates a bintree of objects specified by their bounding volumes. 00087 @METHOD : 00088 @GLOBALS : 00089 @CALLS : 00090 @CREATED : 1993 David MacDonald 00091 @MODIFIED : 00092 ---------------------------------------------------------------------------- */ 00093 00094 public void create_object_bintree( 00095 int n_objects, 00096 range_struct bound_vols[], 00097 bintree_struct_ptr bintree, 00098 int max_nodes ) 00099 { 00100 int i, c; 00101 Real avg_nodes, avg_objects, limits[N_DIMENSIONS][2], size; 00102 #ifdef DEBUG 00103 Real best_objects; 00104 #endif 00105 00106 for_less( i, 0, n_objects ) 00107 { 00108 for_less( c, 0, N_DIMENSIONS ) 00109 { 00110 size = (Real) bound_vols[i].limits[c][1] - 00111 (Real) bound_vols[i].limits[c][0]; 00112 bound_vols[i].limits[c][0] -= (float) (size * FACTOR); 00113 bound_vols[i].limits[c][1] += (float) (size * FACTOR); 00114 } 00115 00116 if( i == 0 ) 00117 { 00118 limits[X][0] = (Real) bound_vols[i].limits[X][0]; 00119 limits[Y][0] = (Real) bound_vols[i].limits[Y][0]; 00120 limits[Z][0] = (Real) bound_vols[i].limits[Z][0]; 00121 limits[X][1] = (Real) bound_vols[i].limits[X][1]; 00122 limits[Y][1] = (Real) bound_vols[i].limits[Y][1]; 00123 limits[Z][1] = (Real) bound_vols[i].limits[Z][1]; 00124 } 00125 else 00126 { 00127 for_less( c, 0, N_DIMENSIONS ) 00128 { 00129 if( (Real) bound_vols[i].limits[c][0] < limits[c][0] ) 00130 limits[c][0] = (Real) bound_vols[i].limits[c][0]; 00131 if( (Real) bound_vols[i].limits[c][1] > limits[c][1] ) 00132 limits[c][1] = (Real) bound_vols[i].limits[c][1]; 00133 } 00134 } 00135 } 00136 00137 initialize_bintree( limits[X][0], limits[X][1], 00138 limits[Y][0], limits[Y][1], 00139 limits[Z][0], limits[Z][1], bintree ); 00140 00141 subdivide_bintree( bintree, max_nodes, n_objects, bound_vols ); 00142 00143 evaluate_bintree_efficiency( bintree, &avg_nodes, &avg_objects ); 00144 00145 #ifdef DEBUG 00146 best_objects = 0.0; 00147 for_less( i, 0, n_objects ) 00148 best_objects += node_visit_estimation( &bound_vols[i] ); 00149 best_objects /= node_visit_estimation( &bintree->range ); 00150 00151 print( "Est Nodes Visit: %g Est Objects Visit %g (Best possible: %g\n", 00152 avg_nodes, avg_objects, best_objects ); 00153 00154 if( n_objects > 100 && avg_objects > (Real) n_objects * 0.1 ) 00155 { 00156 print( "Warning, bintree not efficient: n_objects = %d, ", 00157 n_objects ); 00158 print( "avg_nodes %g, avg_objects %g\n", avg_nodes, avg_objects ); 00159 } 00160 #endif 00161 } 00162 00163 /* ----------------------------- MNI Header ----------------------------------- 00164 @NAME : subdivide_bintree 00165 @INPUT : bintree 00166 max_nodes 00167 n_objects 00168 bound_vols 00169 @OUTPUT : 00170 @RETURNS : 00171 @DESCRIPTION: Creates a subtree by prioritized subdivision of leaves until 00172 the max_nodes is reached. 00173 @METHOD : 00174 @GLOBALS : 00175 @CALLS : 00176 @CREATED : 1993 David MacDonald 00177 @MODIFIED : 00178 ---------------------------------------------------------------------------- */ 00179 00180 private void subdivide_bintree( 00181 bintree_struct_ptr bintree, 00182 int max_nodes, 00183 int n_objects, 00184 range_struct bound_vols[] ) 00185 { 00186 bintree_node_struct **ptr_to_node; 00187 bintree_node_struct **ptr_to_left_child, **ptr_to_right_child; 00188 Real left_cost, right_cost; 00189 range_struct left_limits, right_limits; 00190 leaf_queue_struct leaf_queue; 00191 int n_nodes; 00192 int i, *object_list; 00193 range_struct limits; 00194 progress_struct progress; 00195 00196 ALLOC( object_list, n_objects ); 00197 for_less( i, 0, n_objects ) 00198 object_list[i] = i; 00199 00200 bintree->root = create_bintree_leaf( 0.0, n_objects, object_list ); 00201 00202 FREE( object_list ); 00203 00204 create_leaf_queue( &leaf_queue ); 00205 00206 get_bintree_limits( bintree, &limits ); 00207 00208 insert_in_leaf_queue( &leaf_queue, &bintree->root, 1.0, &limits ); 00209 00210 initialize_progress_report( &progress, FALSE, max_nodes+2, 00211 "Creating bintree" ); 00212 00213 n_nodes = 1; 00214 00215 while( n_nodes < max_nodes && !leaf_queue_empty( &leaf_queue ) ) 00216 { 00217 remove_from_leaf_queue( &leaf_queue, &ptr_to_node, &limits ); 00218 00219 split_node( bound_vols, ptr_to_node, &limits, &n_nodes, 00220 &left_limits, &left_cost, &right_limits, &right_cost ); 00221 00222 if( get_bintree_left_child_ptr( *ptr_to_node, &ptr_to_left_child ) ) 00223 { 00224 insert_in_leaf_queue( &leaf_queue, ptr_to_left_child, left_cost, 00225 &left_limits ); 00226 } 00227 00228 if( get_bintree_right_child_ptr( *ptr_to_node, &ptr_to_right_child ) ) 00229 { 00230 insert_in_leaf_queue( &leaf_queue, ptr_to_right_child, right_cost, 00231 &right_limits ); 00232 } 00233 00234 update_progress_report( &progress, n_nodes ); 00235 } 00236 00237 terminate_progress_report( &progress ); 00238 00239 delete_leaf_queue( &leaf_queue ); 00240 } 00241 00242 /* ----------------------------- MNI Header ----------------------------------- 00243 @NAME : get_planes 00244 @INPUT : axis_index 00245 n_objects 00246 list 00247 bound_vols 00248 right_plane 00249 @OUTPUT : left_plane 00250 n_left 00251 n_overlap 00252 n_right 00253 @RETURNS : 00254 @DESCRIPTION: Computes the plane position for a node. 00255 @METHOD : 00256 @GLOBALS : 00257 @CALLS : 00258 @CREATED : 1993 David MacDonald 00259 @MODIFIED : 00260 ---------------------------------------------------------------------------- */ 00261 00262 private void get_planes( 00263 int axis_index, 00264 int n_objects, 00265 int list[], 00266 range_struct bound_vols[], 00267 Real right_plane, 00268 Real *left_plane, 00269 int *n_left, 00270 int *n_overlap, 00271 int *n_right ) 00272 { 00273 int i; 00274 Real left_side, right_side; 00275 BOOLEAN found; 00276 00277 found = FALSE; 00278 *left_plane = (Real) bound_vols[list[0]].limits[axis_index][0]; 00279 00280 for_less( i, 0, n_objects ) 00281 { 00282 left_side = (Real) bound_vols[list[i]].limits[axis_index][0]; 00283 right_side = (Real) bound_vols[list[i]].limits[axis_index][1]; 00284 if( left_side < right_plane && 00285 (!found || right_side > *left_plane ) ) 00286 { 00287 *left_plane = right_side; 00288 found = TRUE; 00289 } 00290 } 00291 00292 *n_left = 0; 00293 *n_overlap = 0; 00294 *n_right = 0; 00295 00296 for_less( i, 0, n_objects ) 00297 { 00298 left_side = (Real) bound_vols[list[i]].limits[axis_index][0]; 00299 right_side = (Real) bound_vols[list[i]].limits[axis_index][1]; 00300 if( left_side < right_plane ) 00301 ++(*n_left); 00302 else if( !found || right_side > *left_plane ) 00303 ++(*n_right); 00304 else 00305 ++(*n_overlap); 00306 } 00307 } 00308 00309 #define THRESHOLD 30 00310 00311 /* ----------------------------- MNI Header ----------------------------------- 00312 @NAME : find_best_split_node_for_axis 00313 @INPUT : axis_index 00314 n_objects 00315 object_list 00316 bound_vols 00317 limits 00318 @OUTPUT : best_left_plane 00319 best_right_plane 00320 @RETURNS : 00321 @DESCRIPTION: Finds a good split plane for the bintree. 00322 @METHOD : 00323 @GLOBALS : 00324 @CALLS : 00325 @CREATED : 1993 David MacDonald 00326 @MODIFIED : 00327 ---------------------------------------------------------------------------- */ 00328 00329 private Real find_best_split_node_for_axis( 00330 int axis_index, 00331 int n_objects, 00332 int object_list[], 00333 range_struct bound_vols[], 00334 range_struct *limits, 00335 Real *best_left_plane, 00336 Real *best_right_plane ) 00337 { 00338 int i, n_left, n_right, n_overlap, step; 00339 Real left_plane, right_plane; 00340 float save_plane; 00341 Real cost, best_cost, size_left, size_right; 00342 00343 best_cost = 0.0; 00344 00345 if( n_objects > THRESHOLD ) 00346 step = n_objects+1; 00347 else 00348 step = 1; 00349 00350 for( i = 0; i <= n_objects; i += step ) 00351 { 00352 if( n_objects > THRESHOLD ) 00353 right_plane = ((Real) limits->limits[axis_index][0] + 00354 (Real) limits->limits[axis_index][1]) / 2.0; 00355 else if( i < n_objects ) 00356 { 00357 right_plane = (Real) bound_vols[object_list[i]]. 00358 limits[axis_index][0]; 00359 } 00360 else 00361 right_plane = (Real) limits->limits[axis_index][1]; 00362 00363 get_planes( axis_index, n_objects, object_list, bound_vols, 00364 right_plane, &left_plane, 00365 &n_left, &n_overlap, &n_right ); 00366 00367 save_plane = limits->limits[axis_index][1]; 00368 limits->limits[axis_index][1] = (float) left_plane; 00369 size_left = node_visit_estimation( limits ); 00370 limits->limits[axis_index][1] = save_plane; 00371 00372 save_plane = limits->limits[axis_index][0]; 00373 limits->limits[axis_index][0] = (float) right_plane; 00374 size_right = node_visit_estimation( limits ); 00375 limits->limits[axis_index][0] = save_plane; 00376 00377 if( size_left < size_right ) 00378 n_left += n_overlap; 00379 else 00380 n_right += n_overlap; 00381 00382 cost = size_left * (Real) n_left + size_right * (Real) n_right; 00383 00384 if( i == 0 || cost < best_cost ) 00385 { 00386 best_cost = cost; 00387 *best_right_plane = right_plane; 00388 *best_left_plane = left_plane; 00389 } 00390 } 00391 00392 return( best_cost ); 00393 } 00394 00395 #define SWAP( a, b, type ) \ 00396 { \ 00397 type _tmp; \ 00398 _tmp = (a); \ 00399 (a) = (b); \ 00400 (b) = _tmp; \ 00401 } 00402 00403 #ifdef DEBUG 00404 private void check_objects( 00405 range_struct *limits, 00406 int n_objects, 00407 int object_list[], 00408 range_struct bound_vols[] ) 00409 { 00410 int i, c; 00411 for_less( i, 0, n_objects ) 00412 for_less( c, 0, N_DIMENSIONS ) 00413 if( bound_vols[object_list[i]].limits[c][0] < limits->limits[c][0]|| 00414 bound_vols[object_list[i]].limits[c][1] > limits->limits[c][1] ) 00415 handle_internal_error( "check_objects" ); 00416 } 00417 #endif 00418 00419 /* ----------------------------- MNI Header ----------------------------------- 00420 @NAME : split_node 00421 @INPUT : 00422 @OUTPUT : 00423 @RETURNS : 00424 @DESCRIPTION: 00425 @METHOD : 00426 @GLOBALS : 00427 @CALLS : 00428 @CREATED : 1993 David MacDonald 00429 @MODIFIED : 00430 ---------------------------------------------------------------------------- */ 00431 00432 private void split_node( 00433 range_struct bound_vols[], 00434 bintree_node_struct **ptr_to_node, 00435 range_struct *limits, 00436 int *n_nodes, 00437 range_struct *left_limits, 00438 Real *left_cost, 00439 range_struct *right_limits, 00440 Real *right_cost ) 00441 { 00442 int i, c, n_objects; 00443 int *object_list; 00444 int axis_index, top, bottom, start_dim, end_dim; 00445 BOOLEAN overlap_in_left, tightly_bounds; 00446 Real left_plane, right_plane, split_position; 00447 Real min_plane, max_plane, best, cost; 00448 Real test_left, test_right; 00449 Real node_cost, previous_cost, net_change; 00450 bintree_node_struct *left_child, *right_child; 00451 00452 n_objects = get_bintree_leaf_objects( *ptr_to_node, &object_list ); 00453 00454 if( n_objects == 0 ) 00455 return; 00456 00457 tightly_bounds = TRUE; 00458 00459 for_less( i, 0, n_objects ) 00460 { 00461 if( !node_tightly_bounds_object( &bound_vols[object_list[i]], limits ) ) 00462 { 00463 tightly_bounds = FALSE; 00464 break; 00465 } 00466 } 00467 00468 if( tightly_bounds ) 00469 return; 00470 00471 best = 0.0; 00472 00473 if( n_objects > THRESHOLD ) 00474 { 00475 start_dim = 0; 00476 for_less( c, 0, N_DIMENSIONS ) 00477 { 00478 if( limits->limits[c][1] - limits->limits[c][0] > 00479 limits->limits[start_dim][1] - limits->limits[start_dim][0] ) 00480 { 00481 start_dim = c; 00482 } 00483 } 00484 end_dim = start_dim + 1; 00485 } 00486 else 00487 { 00488 start_dim = 0; 00489 end_dim = N_DIMENSIONS; 00490 } 00491 00492 for_less( c, start_dim, end_dim ) 00493 { 00494 cost = find_best_split_node_for_axis( c, n_objects, object_list, 00495 bound_vols, limits, 00496 &test_left, &test_right ); 00497 00498 if( c == start_dim || cost < best ) 00499 { 00500 best = cost; 00501 axis_index = c; 00502 left_plane = test_left; 00503 right_plane = test_right; 00504 } 00505 } 00506 00507 previous_cost = (Real) n_objects * node_visit_estimation( limits ); 00508 node_cost = NODE_VISIT_COST * node_visit_estimation( limits ); 00509 00510 net_change = node_cost + cost - previous_cost; 00511 00512 if( net_change >= NET_CHANGE_THRESHOLD ) 00513 return; 00514 00515 min_plane = (Real) limits->limits[axis_index][0]; 00516 max_plane = (Real) limits->limits[axis_index][1]; 00517 00518 if( left_plane - min_plane < max_plane - right_plane ) 00519 overlap_in_left = TRUE; 00520 else 00521 overlap_in_left = FALSE; 00522 00523 bottom = 0; 00524 top = n_objects - 1; 00525 00526 while( bottom <= top ) 00527 { 00528 while( bottom < n_objects && 00529 (Real) bound_vols[object_list[bottom]].limits[axis_index][1] <= 00530 left_plane && 00531 (overlap_in_left || 00532 (Real) bound_vols[object_list[bottom]].limits[axis_index][0] < 00533 right_plane) ) 00534 ++bottom; 00535 while( top >= 0 && 00536 (Real) bound_vols[object_list[top]].limits[axis_index][0] >= 00537 right_plane && 00538 (!overlap_in_left || 00539 (Real) bound_vols[object_list[top]].limits[axis_index][1] > 00540 left_plane) ) 00541 --top; 00542 if( bottom < top ) 00543 { 00544 SWAP( object_list[bottom], object_list[top], int ) 00545 } 00546 } 00547 00548 if( (bottom == 0 && right_plane == (Real) limits->limits[axis_index][0]) || 00549 (bottom == n_objects && 00550 left_plane == (Real) limits->limits[axis_index][1]) ) 00551 { 00552 return; 00553 } 00554 00555 if( bottom > 0 ) 00556 { 00557 *left_limits = *limits; 00558 left_limits->limits[axis_index][1] = (float) left_plane; 00559 00560 *left_cost = (Real) bottom * node_visit_estimation( left_limits ); 00561 00562 left_child = create_bintree_leaf( left_plane, bottom, object_list ); 00563 00564 #ifdef DEBUG 00565 check_objects( left_limits, bottom, object_list, bound_vols ); 00566 #endif 00567 00568 ++(*n_nodes); 00569 } 00570 else 00571 left_child = (bintree_node_struct *) NULL; 00572 00573 if( bottom < n_objects ) 00574 { 00575 *right_limits = *limits; 00576 right_limits->limits[axis_index][0] = (float) right_plane; 00577 00578 *right_cost = (Real) (n_objects - bottom) * 00579 node_visit_estimation( right_limits ); 00580 00581 right_child = create_bintree_leaf( right_plane, n_objects - bottom, 00582 &object_list[bottom] ); 00583 #ifdef DEBUG 00584 check_objects( right_limits, n_objects - bottom, &object_list[bottom], 00585 bound_vols ); 00586 #endif 00587 ++(*n_nodes); 00588 } 00589 else 00590 right_child = (bintree_node_struct *) NULL; 00591 00592 if( left_child == (bintree_node_struct *) NULL && 00593 right_child == (bintree_node_struct *) NULL ) 00594 handle_internal_error( "Split bintree node" ); 00595 00596 /* --- replace the leaf with an internal node */ 00597 00598 split_position = get_node_split_position( *ptr_to_node ); 00599 delete_bintree_node( *ptr_to_node ); 00600 *ptr_to_node = create_bintree_internal_node( axis_index, 00601 split_position, 00602 left_child, 00603 right_child ); 00604 } 00605 00606 private void create_leaf_queue( 00607 leaf_queue_struct *leaf_queue ) 00608 { 00609 INITIALIZE_PRIORITY_QUEUE( *leaf_queue ); 00610 } 00611 00612 private void delete_leaf_queue( 00613 leaf_queue_struct *leaf_queue ) 00614 { 00615 DELETE_PRIORITY_QUEUE( *leaf_queue ); 00616 } 00617 00618 private BOOLEAN leaf_queue_empty( 00619 leaf_queue_struct *leaf_queue ) 00620 { 00621 return( IS_PRIORITY_QUEUE_EMPTY( *leaf_queue ) ); 00622 } 00623 00624 private void insert_in_leaf_queue( 00625 leaf_queue_struct *leaf_queue, 00626 bintree_node_struct **ptr_to_node, 00627 Real node_cost, 00628 range_struct *limits ) 00629 { 00630 leaf_queue_type entry; 00631 00632 entry.ptr_to_node = ptr_to_node; 00633 entry.limits = *limits; 00634 00635 INSERT_IN_PRIORITY_QUEUE( *leaf_queue, entry, node_cost ); 00636 } 00637 00638 private void remove_from_leaf_queue( 00639 leaf_queue_struct *leaf_queue, 00640 bintree_node_struct ***ptr_to_node, 00641 range_struct *limits ) 00642 { 00643 leaf_queue_type entry; 00644 Real node_cost; 00645 00646 REMOVE_FROM_PRIORITY_QUEUE( *leaf_queue, entry, node_cost ); 00647 00648 if( node_cost < 0.0 ) 00649 handle_internal_error( "remove from leaf queue" ); 00650 00651 *ptr_to_node = entry.ptr_to_node; 00652 *limits = entry.limits; 00653 } 00654 00655 private BOOLEAN node_tightly_bounds_object( 00656 range_struct *bound_vol, 00657 range_struct *limits ) 00658 { 00659 int l, c; 00660 00661 for_less( c, 0, N_DIMENSIONS ) 00662 { 00663 for_less( l, 0, 2 ) 00664 { 00665 if( bound_vol->limits[c][l] != limits->limits[c][l] ) 00666 { 00667 return( FALSE ); 00668 } 00669 } 00670 } 00671 00672 return( TRUE ); 00673 } 00674 00675 public void evaluate_bintree_efficiency( 00676 bintree_struct_ptr bintree, 00677 Real *avg_nodes_visited, 00678 Real *avg_objects_visited ) 00679 { 00680 Real n_visits_top_level; 00681 range_struct limits; 00682 00683 *avg_nodes_visited = 0.0; 00684 *avg_objects_visited = 0.0; 00685 00686 limits = bintree->range; 00687 00688 recursive_efficiency_count( bintree->root, &limits, 00689 avg_nodes_visited, avg_objects_visited ); 00690 00691 n_visits_top_level = node_visit_estimation( &bintree->range ); 00692 00693 *avg_nodes_visited /= n_visits_top_level; 00694 *avg_objects_visited /= n_visits_top_level; 00695 } 00696 00697 private void recursive_efficiency_count( 00698 bintree_node_struct *node, 00699 range_struct *limits, 00700 Real *avg_nodes_visited, 00701 Real *avg_objects_visited ) 00702 { 00703 float save_limit; 00704 Real node_visit_estimate; 00705 bintree_node_struct *left_child, *right_child; 00706 Real left_limit, right_limit; 00707 int *object_list, axis_index; 00708 00709 node_visit_estimate = node_visit_estimation( limits ); 00710 00711 *avg_nodes_visited += node_visit_estimate; 00712 00713 if( bintree_node_is_leaf( node ) ) 00714 { 00715 *avg_objects_visited += node_visit_estimate * 00716 (Real) get_bintree_leaf_objects( node, &object_list ); 00717 } 00718 else 00719 { 00720 axis_index = get_node_split_axis( node ); 00721 00722 if( get_bintree_left_child( node, &left_child ) ) 00723 { 00724 left_limit = get_node_split_position( left_child ); 00725 00726 save_limit = limits->limits[axis_index][1]; 00727 limits->limits[axis_index][1] = (float) left_limit; 00728 00729 recursive_efficiency_count( left_child, limits, 00730 avg_nodes_visited, 00731 avg_objects_visited ); 00732 limits->limits[axis_index][1] = save_limit; 00733 } 00734 00735 if( get_bintree_right_child( node, &right_child ) ) 00736 { 00737 right_limit = get_node_split_position( right_child ); 00738 00739 save_limit = limits->limits[axis_index][0]; 00740 limits->limits[axis_index][0] = (float) right_limit; 00741 00742 recursive_efficiency_count( right_child, limits, 00743 avg_nodes_visited, 00744 avg_objects_visited ); 00745 limits->limits[axis_index][0] = save_limit; 00746 } 00747 } 00748 } 00749 00750 private Real node_visit_estimation( 00751 range_struct *limits ) 00752 { 00753 #ifdef VOLUME_EST 00754 return( range_volume(limits) ); 00755 #else 00756 return( range_surface_area(limits) ); 00757 #endif 00758 }

Generated on Wed Jul 28 09:10:56 2004 for BICPL by doxygen 1.3.7