00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/tree.c,v 14.18 2006/09/16 02:04:26 lbutler Exp $ (ARL)";
00039 #endif
00040
00041 #include "common.h"
00042
00043 #include <stddef.h>
00044 #include <stdio.h>
00045 #include <math.h>
00046 #ifdef HAVE_STRING_H
00047 # include <string.h>
00048 #else
00049 # include <strings.h>
00050 #endif
00051
00052 #include "machine.h"
00053 #include "bu.h"
00054 #include "vmath.h"
00055 #include "bn.h"
00056 #include "db.h"
00057 #include "raytrace.h"
00058
00059 #include "./debug.h"
00060
00061 BU_EXTERN(void rt_tree_kill_dead_solid_refs, (union tree *tp));
00062
00063 HIDDEN struct region *rt_getregion(struct rt_i *rtip, register const char *reg_name);
00064 HIDDEN void rt_tree_region_assign(register union tree *tp, register const struct region *regionp);
00065
00066
00067
00068
00069
00070 const struct db_tree_state rt_initial_tree_state = {
00071 RT_DBTS_MAGIC,
00072 0,
00073 0,
00074 0, 0, 0, 0,
00075 #if __STDC__
00076 {
00077 #endif
00078
00079 #if __STDC__
00080 {
00081 #endif
00082 1.0, 1.0, 1.0
00083 #if __STDC__
00084 }
00085 #endif
00086 ,
00087 -1.0,
00088 0,
00089 DB_INH_LOWER,
00090 DB_INH_LOWER,
00091 NULL
00092 #if __STDC__
00093 }
00094 #endif
00095 ,
00096 #if __STDC__
00097 {
00098 #endif
00099 1.0, 0.0, 0.0, 0.0,
00100 0.0, 1.0, 0.0, 0.0,
00101 0.0, 0.0, 1.0, 0.0,
00102 0.0, 0.0, 0.0, 1.0
00103 #if __STDC__
00104 }
00105 #endif
00106 ,
00107 REGION_NON_FASTGEN,
00108 #if __STDC__
00109 {
00110 #endif
00111
00112 BU_AVS_MAGIC,
00113 0,
00114 0,
00115 NULL,
00116 NULL,
00117 NULL
00118 #if __STDC__
00119 }
00120 #endif
00121 ,
00122 0,
00123 NULL,
00124 NULL,
00125 NULL,
00126 NULL,
00127 NULL,
00128 NULL,
00129 NULL,
00130 NULL
00131 };
00132
00133 #define ACQUIRE_SEMAPHORE_TREE(_hash) switch((_hash)&03) { \
00134 case 0: \
00135 bu_semaphore_acquire( RT_SEM_TREE0 ); \
00136 break; \
00137 case 1: \
00138 bu_semaphore_acquire( RT_SEM_TREE1 ); \
00139 break; \
00140 case 2: \
00141 bu_semaphore_acquire( RT_SEM_TREE2 ); \
00142 break; \
00143 default: \
00144 bu_semaphore_acquire( RT_SEM_TREE3 ); \
00145 break; \
00146 }
00147
00148 #define RELEASE_SEMAPHORE_TREE(_hash) switch((_hash)&03) { \
00149 case 0: \
00150 bu_semaphore_release( RT_SEM_TREE0 ); \
00151 break; \
00152 case 1: \
00153 bu_semaphore_release( RT_SEM_TREE1 ); \
00154 break; \
00155 case 2: \
00156 bu_semaphore_release( RT_SEM_TREE2 ); \
00157 break; \
00158 default: \
00159 bu_semaphore_release( RT_SEM_TREE3 ); \
00160 break; \
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 HIDDEN int rt_gettree_region_start(struct db_tree_state *tsp, struct db_full_path *pathp, const struct rt_comb_internal *combp, genptr_t client_data)
00170
00171
00172
00173
00174 {
00175 RT_CK_RTI(tsp->ts_rtip);
00176 RT_CK_RESOURCE(tsp->ts_resp);
00177
00178
00179 if( tsp->ts_rtip->useair == 0 && tsp->ts_aircode != 0 ) {
00180 tsp->ts_rtip->rti_air_discards++;
00181 return(-1);
00182 }
00183 return(0);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 HIDDEN union tree *rt_gettree_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
00201 {
00202 struct region *rp;
00203 struct directory *dp;
00204 int shader_len=0;
00205 struct rt_i *rtip;
00206 int i;
00207 Tcl_HashTable *tbl = (Tcl_HashTable *)client_data;
00208 Tcl_HashEntry *entry;
00209 matp_t inv_mat;
00210
00211 RT_CK_DBI(tsp->ts_dbip);
00212 RT_CK_FULL_PATH(pathp);
00213 RT_CK_TREE(curtree);
00214 rtip = tsp->ts_rtip;
00215 RT_CK_RTI(rtip);
00216 RT_CK_RESOURCE(tsp->ts_resp);
00217
00218 if( curtree->tr_op == OP_NOP ) {
00219
00220 return curtree;
00221 }
00222
00223 BU_GETSTRUCT( rp, region );
00224 rp->l.magic = RT_REGION_MAGIC;
00225 rp->reg_regionid = tsp->ts_regionid;
00226 rp->reg_is_fastgen = tsp->ts_is_fastgen;
00227 rp->reg_aircode = tsp->ts_aircode;
00228 rp->reg_gmater = tsp->ts_gmater;
00229 rp->reg_los = tsp->ts_los;
00230
00231 if( tsp->ts_attrs.count && tsp->ts_attrs.avp ) {
00232 rp->attr_values = (struct bu_mro **)bu_calloc( tsp->ts_attrs.count+1,
00233 sizeof( struct bu_mro *), "regp->attr_values" );
00234 for( i=0 ; i<tsp->ts_attrs.count ; i++ ) {
00235 rp->attr_values[i] = bu_malloc( sizeof( struct bu_mro ),
00236 "rp->attr_values[i]" );
00237 bu_mro_init_with_string( rp->attr_values[i], tsp->ts_attrs.avp[i].value );
00238 }
00239 } else {
00240 rp->attr_values = (struct bu_mro **)NULL;
00241 }
00242
00243 rp->reg_mater = tsp->ts_mater;
00244 if( tsp->ts_mater.ma_shader )
00245 shader_len = strlen( tsp->ts_mater.ma_shader );
00246 if( shader_len )
00247 {
00248 rp->reg_mater.ma_shader = bu_strdup( tsp->ts_mater.ma_shader );
00249 }
00250 else
00251 rp->reg_mater.ma_shader = (char *)NULL;
00252
00253 rp->reg_name = db_path_to_string( pathp );
00254
00255 dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp);
00256
00257 if(RT_G_DEBUG&DEBUG_TREEWALK) {
00258 bu_log("rt_gettree_region_end() %s\n", rp->reg_name );
00259 rt_pr_tree( curtree, 0 );
00260 }
00261
00262 rp->reg_treetop = curtree;
00263 rp->reg_all_unions = db_is_tree_all_unions( curtree );
00264
00265
00266 rp->reg_mfuncs = (char *)0;
00267 rp->reg_udata = (char *)0;
00268 if( rp->reg_mater.ma_color_valid == 0 )
00269 rt_region_color_map(rp);
00270
00271 bu_semaphore_acquire( RT_SEM_RESULTS );
00272
00273 rp->reg_instnum = dp->d_uses++;
00274
00275
00276
00277
00278
00279 BU_LIST_INSERT( &(rtip->HeadRegion), &rp->l );
00280
00281 rp->reg_bit = rtip->nregions++;
00282 bu_semaphore_release( RT_SEM_RESULTS );
00283
00284 if( tbl && bu_avs_get( &tsp->ts_attrs, "ORCA_Comp" ) ) {
00285 int newentry;
00286 long int reg_bit = rp->reg_bit;
00287
00288 inv_mat = (matp_t)bu_calloc( 16, sizeof( fastf_t ), "inv_mat" );
00289 if( tsp->ts_mat )
00290 bn_mat_inv( inv_mat, tsp->ts_mat );
00291 else
00292 bn_mat_idn( inv_mat );
00293
00294 bu_semaphore_acquire( RT_SEM_RESULTS );
00295
00296 entry = Tcl_CreateHashEntry(tbl, (char *)reg_bit, &newentry);
00297 Tcl_SetHashValue( entry, (ClientData)inv_mat );
00298
00299 bu_semaphore_release( RT_SEM_RESULTS );
00300 }
00301
00302 if( RT_G_DEBUG & DEBUG_REGIONS ) {
00303 bu_log("Add Region %s instnum %d\n",
00304 rp->reg_name, rp->reg_instnum);
00305 }
00306
00307
00308 return(TREE_NULL);
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 HIDDEN struct soltab *rt_find_identical_solid(register const matp_t mat, register struct directory *dp, struct rt_i *rtip)
00365 {
00366 register struct soltab *stp = RT_SOLTAB_NULL;
00367 int hash;
00368
00369 RT_CK_DIR(dp);
00370 RT_CK_RTI(rtip);
00371
00372 hash = db_dirhash( dp->d_namep );
00373
00374
00375 ACQUIRE_SEMAPHORE_TREE(hash);
00376
00377
00378
00379
00380
00381
00382
00383
00384 if( dp->d_uses > 0 && dp->d_uses < 100 &&
00385 rtip->rti_dont_instance == 0
00386 ) {
00387 struct bu_list *mid;
00388
00389
00390 for( BU_LIST_FOR( mid, bu_list, &dp->d_use_hd ) ) {
00391
00392 stp = BU_LIST_MAIN_PTR( soltab, mid, l2 );
00393 RT_CK_SOLTAB(stp);
00394
00395 if( stp->st_matp == (matp_t)0 ) {
00396 if( mat == (matp_t)0 ) {
00397
00398 goto more_checks;
00399 }
00400 continue;
00401 }
00402 if( mat == (matp_t)0 ) continue;
00403
00404 if( !bn_mat_is_equal(mat, stp->st_matp, &rtip->rti_tol))
00405 continue;
00406
00407 more_checks:
00408
00409
00410 if( stp->st_rtip != rtip ) continue;
00411
00412
00413
00414
00415
00416 RT_CK_SOLTAB(stp);
00417
00418
00419 if( !(stp->st_aradius <= -1) )
00420 stp->st_uses++;
00421
00422 if( RT_G_DEBUG & DEBUG_SOLIDS ) {
00423 bu_log( mat ?
00424 "rt_find_identical_solid: %s re-referenced %d\n" :
00425 "rt_find_identical_solid: %s re-referenced %d (identity mat)\n",
00426 dp->d_namep, stp->st_uses );
00427 }
00428
00429
00430 RELEASE_SEMAPHORE_TREE(hash);
00431 return stp;
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442 BU_GETSTRUCT(stp, soltab);
00443 stp->l.magic = RT_SOLTAB_MAGIC;
00444 stp->l2.magic = RT_SOLTAB2_MAGIC;
00445 stp->st_rtip = rtip;
00446 stp->st_dp = dp;
00447 dp->d_uses++;
00448 stp->st_uses = 1;
00449
00450
00451 if( mat ) {
00452 stp->st_matp = (matp_t)bu_malloc( sizeof(mat_t), "st_matp" );
00453 MAT_COPY( stp->st_matp, mat );
00454 } else {
00455 stp->st_matp = (matp_t)0;
00456 }
00457
00458
00459
00460 BU_LIST_INSERT( &(rtip->rti_solidheads[hash]), &(stp->l) );
00461
00462
00463
00464 BU_LIST_INSERT( &dp->d_use_hd, &(stp->l2) );
00465
00466
00467
00468
00469 RELEASE_SEMAPHORE_TREE(hash);
00470
00471
00472
00473 bu_semaphore_acquire(RT_SEM_STATS);
00474 stp->st_bit = rtip->nsolids++;
00475 bu_semaphore_release(RT_SEM_STATS);
00476
00477
00478
00479
00480
00481
00482
00483 bu_ptbl_init( &stp->st_regions, 7, "st_regions ptbl" );
00484
00485 return stp;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 HIDDEN union tree *rt_gettree_leaf(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data)
00495
00496
00497
00498
00499 {
00500 register struct soltab *stp;
00501 union tree *curtree;
00502 struct directory *dp;
00503 register matp_t mat;
00504 int i;
00505 struct rt_i *rtip;
00506
00507 RT_CK_DBTS(tsp);
00508 RT_CK_DBI(tsp->ts_dbip);
00509 RT_CK_FULL_PATH(pathp);
00510 RT_CK_DB_INTERNAL(ip);
00511 rtip = tsp->ts_rtip;
00512 RT_CK_RTI(rtip);
00513 RT_CK_RESOURCE(tsp->ts_resp);
00514 dp = DB_FULL_PATH_CUR_DIR(pathp);
00515
00516
00517
00518 if( !bn_mat_is_equal(tsp->ts_mat, bn_mat_identity, &rtip->rti_tol)) {
00519
00520 mat = (matp_t)tsp->ts_mat;
00521 } else {
00522
00523 mat = (matp_t)0;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 stp = rt_find_identical_solid( mat, dp, rtip );
00537 if( stp->st_id != 0 ) {
00538
00539 if( stp->st_aradius <= -1 ) {
00540
00541 return( TREE_NULL );
00542 }
00543 goto found_it;
00544 }
00545
00546 if( rtip->rti_add_to_new_solids_list ) {
00547 bu_ptbl_ins( &rtip->rti_new_solids, (long *)stp );
00548 }
00549
00550 stp->st_id = ip->idb_type;
00551 stp->st_meth = &rt_functab[ip->idb_type];
00552 if( mat ) {
00553 mat = stp->st_matp;
00554 } else {
00555 mat = (matp_t)bn_mat_identity;
00556 }
00557
00558 RT_CK_DB_INTERNAL( ip );
00559
00560
00561 VSETALL( stp->st_max, -INFINITY );
00562 VSETALL( stp->st_min, INFINITY );
00563
00564
00565
00566
00567
00568
00569 if( stp->st_meth->ft_prep( stp, ip, rtip ) ) {
00570 int hash;
00571
00572 bu_log("rt_gettree_leaf(%s): prep failure\n", dp->d_namep );
00573
00574 hash = db_dirhash( dp->d_namep );
00575 ACQUIRE_SEMAPHORE_TREE(hash);
00576 stp->st_aradius = -1;
00577 stp->st_uses--;
00578 RELEASE_SEMAPHORE_TREE(hash);
00579 return( TREE_NULL );
00580 }
00581
00582 if( rtip->rti_dont_instance ) {
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 db_full_path_init( &stp->st_path );
00595 db_dup_full_path( &stp->st_path, pathp );
00596 } else {
00597
00598
00599
00600
00601
00602
00603
00604 i = pathp->fp_len-1;
00605 if( i > 0 && !(pathp->fp_names[i-1]->d_flags & DIR_REGION) ) {
00606
00607 for( --i; i > 0; i-- ) {
00608 if( pathp->fp_names[i-1]->d_flags & DIR_REGION ) break;
00609 }
00610 if( i < 0 ) i = 0;
00611 db_full_path_init( &stp->st_path );
00612 db_dup_path_tail( &stp->st_path, pathp, i );
00613 }
00614 }
00615 if(RT_G_DEBUG&DEBUG_TREEWALK && stp->st_path.magic == DB_FULL_PATH_MAGIC) {
00616 char *sofar = db_path_to_string(&stp->st_path);
00617 bu_log("rt_gettree_leaf() st_path=%s\n", sofar );
00618 bu_free(sofar, "path string");
00619 }
00620
00621 if(RT_G_DEBUG&DEBUG_SOLIDS) {
00622 struct bu_vls str;
00623 bu_log("\n---Primitive %d: %s\n", stp->st_bit, dp->d_namep);
00624 bu_vls_init( &str );
00625
00626 if( stp->st_meth->ft_describe( &str, ip, 1, 1.0, tsp->ts_resp, tsp->ts_dbip ) < 0 ) {
00627 bu_log("rt_gettree_leaf(%s): solid describe failure\n",
00628 dp->d_namep );
00629 }
00630 bu_log( "%s: %s", dp->d_namep, bu_vls_addr( &str ) );
00631 bu_vls_free( &str );
00632 }
00633
00634 found_it:
00635 RT_GET_TREE( curtree, tsp->ts_resp );
00636 curtree->magic = RT_TREE_MAGIC;
00637 curtree->tr_op = OP_SOLID;
00638 curtree->tr_a.tu_stp = stp;
00639
00640 curtree->tr_a.tu_regionp = (struct region *)0;
00641
00642 if(RT_G_DEBUG&DEBUG_TREEWALK) {
00643 char *sofar = db_path_to_string(pathp);
00644 bu_log("rt_gettree_leaf() %s\n", sofar );
00645 bu_free(sofar, "path string");
00646 }
00647
00648 return(curtree);
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 void
00669 rt_free_soltab(struct soltab *stp)
00670 {
00671 int hash;
00672
00673 RT_CK_SOLTAB(stp);
00674 if( stp->st_id < 0 || stp->st_id >= rt_nfunctab )
00675 rt_bomb("rt_free_soltab: bad st_id");
00676 hash = db_dirhash(stp->st_dp->d_namep);
00677
00678 ACQUIRE_SEMAPHORE_TREE(hash);
00679 if( --(stp->st_uses) > 0 ) {
00680 RELEASE_SEMAPHORE_TREE(hash);
00681 return;
00682 }
00683 BU_LIST_DEQUEUE( &(stp->l2) );
00684 BU_LIST_DEQUEUE( &(stp->l) );
00685
00686 RELEASE_SEMAPHORE_TREE(hash);
00687
00688 if( stp->st_aradius > 0 ) {
00689 stp->st_meth->ft_free( stp );
00690 stp->st_aradius = 0;
00691 }
00692 if( stp->st_matp ) bu_free( (char *)stp->st_matp, "st_matp");
00693 stp->st_matp = (matp_t)0;
00694
00695 bu_ptbl_free(&stp->st_regions);
00696
00697 stp->st_dp = DIR_NULL;
00698
00699 if( stp->st_path.magic ) {
00700 RT_CK_FULL_PATH( &stp->st_path );
00701 db_free_full_path( &stp->st_path );
00702 }
00703
00704 bu_free( (char *)stp, "struct soltab" );
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 int
00737 rt_gettrees_muves(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus)
00738 {
00739 register struct soltab *stp;
00740 register struct region *regp;
00741 Tcl_HashTable *tbl;
00742 int prev_sol_count;
00743 int i;
00744 int num_attrs=0;
00745 point_t region_min, region_max;
00746
00747 RT_CHECK_RTI(rtip);
00748 RT_CK_DBI(rtip->rti_dbip);
00749
00750 if(!rtip->needprep) {
00751 bu_log("ERROR: rt_gettree() called again after rt_prep!\n");
00752 return(-1);
00753 }
00754
00755 if( argc <= 0 ) return(-1);
00756
00757 tbl = (Tcl_HashTable *)bu_malloc( sizeof( Tcl_HashTable ), "rtip->Orca_hash_tbl" );
00758 Tcl_InitHashTable( tbl, TCL_ONE_WORD_KEYS );
00759 rtip->Orca_hash_tbl = (genptr_t)tbl;
00760
00761 prev_sol_count = rtip->nsolids;
00762
00763 {
00764 struct db_tree_state tree_state;
00765
00766 tree_state = rt_initial_tree_state;
00767 tree_state.ts_dbip = rtip->rti_dbip;
00768 tree_state.ts_rtip = rtip;
00769 tree_state.ts_resp = NULL;
00770
00771 if( attrs ) {
00772 if( rtip->rti_dbip->dbi_version < 5 ) {
00773 bu_log( "WARNING: requesting attributes from an old database version (ignored)\n" );
00774 bu_avs_init_empty( &tree_state.ts_attrs );
00775 } else {
00776 while( attrs[num_attrs] ) {
00777 num_attrs++;
00778 }
00779 if( num_attrs ) {
00780 bu_avs_init( &tree_state.ts_attrs,
00781 num_attrs,
00782 "avs in tree_state" );
00783 num_attrs = 0;
00784 while( attrs[num_attrs] ) {
00785 bu_avs_add( &tree_state.ts_attrs,
00786 attrs[num_attrs],
00787 NULL );
00788 num_attrs++;
00789 }
00790 } else {
00791 bu_avs_init_empty( &tree_state.ts_attrs );
00792 }
00793 }
00794 } else {
00795 bu_avs_init_empty( &tree_state.ts_attrs );
00796 }
00797
00798
00799
00800
00801
00802 #if 0
00803 bu_avs_add( &tree_state.ts_attrs, "ORCA_Comp", (char *)NULL );
00804 #endif
00805 i = db_walk_tree( rtip->rti_dbip, argc, argv, ncpus,
00806 &tree_state,
00807 rt_gettree_region_start,
00808 rt_gettree_region_end,
00809 rt_gettree_leaf, (genptr_t)tbl );
00810 bu_avs_free( &tree_state.ts_attrs );
00811 }
00812
00813
00814 for( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) {
00815 RT_CK_REGION(regp);
00816 db_ck_tree(regp->reg_treetop);
00817 }
00818
00819
00820
00821
00822
00823
00824 for( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) {
00825 RT_CK_REGION(regp);
00826 rt_tree_kill_dead_solid_refs( regp->reg_treetop );
00827 (void)rt_tree_elim_nops( regp->reg_treetop, &rt_uniresource );
00828 }
00829 again:
00830 RT_VISIT_ALL_SOLTABS_START( stp, rtip ) {
00831 RT_CK_SOLTAB(stp);
00832 if( stp->st_aradius <= 0 ) {
00833 bu_log("rt_gettrees() cleaning up dead solid '%s'\n",
00834 stp->st_dp->d_namep );
00835 rt_free_soltab(stp);
00836
00837
00838 goto again;
00839 }
00840 } RT_VISIT_ALL_SOLTABS_END
00841
00842
00843
00844
00845
00846
00847 RT_VISIT_ALL_SOLTABS_START( stp, rtip ) {
00848 if( stp->st_npieces > 1 ) {
00849
00850 VMINMAX( rtip->mdl_min, rtip->mdl_max, stp->st_min );
00851 VMINMAX( rtip->mdl_min, rtip->mdl_max, stp->st_max );
00852 stp->st_piecestate_num = rtip->rti_nsolids_with_pieces++;
00853 }
00854 if(RT_G_DEBUG&DEBUG_SOLIDS)
00855 rt_pr_soltab( stp );
00856 } RT_VISIT_ALL_SOLTABS_END
00857
00858
00859
00860
00861 for( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) {
00862 RT_CK_REGION(regp);
00863
00864
00865 rt_tree_region_assign( regp->reg_treetop, regp );
00866
00867
00868
00869
00870
00871
00872
00873 if( rt_bound_tree( regp->reg_treetop, region_min, region_max ) < 0 ) {
00874 bu_log("rt_gettrees() %s\n", regp->reg_name );
00875 rt_bomb("rt_gettrees(): rt_bound_tree() fail\n");
00876 }
00877 if( region_max[X] < INFINITY ) {
00878
00879 VMINMAX( rtip->mdl_min, rtip->mdl_max, region_min );
00880 VMINMAX( rtip->mdl_min, rtip->mdl_max, region_max );
00881 }
00882 }
00883
00884
00885 for( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) {
00886 RT_CK_REGION(regp);
00887 db_ck_tree(regp->reg_treetop);
00888 }
00889
00890 if( i < 0 ) return(i);
00891
00892 if( rtip->nsolids <= prev_sol_count )
00893 bu_log("rt_gettrees(%s) warning: no primitives found\n", argv[0]);
00894 return(0);
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 int
00917 rt_gettrees_and_attrs(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus)
00918 {
00919 return( rt_gettrees_muves( rtip, attrs, argc, argv, ncpus ) );
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 int
00936 rt_gettree(struct rt_i *rtip, const char *node)
00937 {
00938 int rv;
00939 const char *argv[2];
00940
00941 argv[0] = node;
00942 argv[1] = (const char *)NULL;
00943
00944 rv = rt_gettrees_and_attrs( rtip, NULL, 1, argv, 1 );
00945
00946 if (rv == 0 || rv == -2)
00947 {
00948 return 0;
00949 }
00950 else
00951 {
00952 return -1;
00953 }
00954 }
00955
00956 int
00957 rt_gettrees(struct rt_i *rtip, int argc, const char **argv, int ncpus)
00958 {
00959 int rv;
00960 rv = rt_gettrees_and_attrs( rtip, NULL, argc, argv, ncpus );
00961
00962 if (rv == 0 || rv == -2)
00963 {
00964 return 0;
00965 }
00966 else
00967 {
00968 return -1;
00969 }
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 int
00984 rt_bound_tree(register const union tree *tp, fastf_t *tree_min, fastf_t *tree_max)
00985 {
00986 vect_t r_min, r_max;
00987
00988 RT_CK_TREE(tp);
00989
00990 switch( tp->tr_op ) {
00991
00992 case OP_SOLID:
00993 {
00994 register const struct soltab *stp;
00995
00996 stp = tp->tr_a.tu_stp;
00997 RT_CK_SOLTAB(stp);
00998 if( stp->st_aradius <= 0 ) {
00999 bu_log("rt_bound_tree: encountered dead solid '%s'\n",
01000 stp->st_dp->d_namep);
01001 return -1;
01002 }
01003
01004 if( stp->st_aradius >= INFINITY ) {
01005 VSETALL( tree_min, -INFINITY );
01006 VSETALL( tree_max, INFINITY );
01007 return(0);
01008 }
01009 VMOVE( tree_min, stp->st_min );
01010 VMOVE( tree_max, stp->st_max );
01011 return(0);
01012 }
01013
01014 default:
01015 bu_log( "rt_bound_tree(x%x): unknown op=x%x\n",
01016 tp, tp->tr_op );
01017 return(-1);
01018
01019 case OP_XOR:
01020 case OP_UNION:
01021
01022 if( rt_bound_tree( tp->tr_b.tb_left, tree_min, tree_max ) < 0 ||
01023 rt_bound_tree( tp->tr_b.tb_right, r_min, r_max ) < 0 )
01024 return(-1);
01025 VMIN( tree_min, r_min );
01026 VMAX( tree_max, r_max );
01027 break;
01028 case OP_INTERSECT:
01029
01030 if( rt_bound_tree( tp->tr_b.tb_left, tree_min, tree_max ) < 0 ||
01031 rt_bound_tree( tp->tr_b.tb_right, r_min, r_max ) < 0 )
01032 return(-1);
01033
01034 VMAX( tree_min, r_min );
01035 VMIN( tree_max, r_max );
01036 break;
01037 case OP_SUBTRACT:
01038
01039 if( rt_bound_tree( tp->tr_b.tb_left, tree_min, tree_max ) < 0 ||
01040 rt_bound_tree( tp->tr_b.tb_right, r_min, r_max ) < 0 )
01041 return(-1);
01042
01043 break;
01044 case OP_NOP:
01045
01046 break;
01047 }
01048 return(0);
01049 }
01050
01051
01052
01053
01054
01055
01056 void
01057 rt_tree_kill_dead_solid_refs(register union tree *tp)
01058 {
01059
01060 RT_CK_TREE(tp);
01061
01062 switch( tp->tr_op ) {
01063
01064 case OP_SOLID:
01065 {
01066 register struct soltab *stp;
01067
01068 stp = tp->tr_a.tu_stp;
01069 RT_CK_SOLTAB(stp);
01070 if( stp->st_aradius <= 0 ) {
01071 if(RT_G_DEBUG&DEBUG_TREEWALK)bu_log("rt_tree_kill_dead_solid_refs: encountered dead solid '%s' stp=x%x, tp=x%x\n",
01072 stp->st_dp->d_namep, stp, tp);
01073 rt_free_soltab(stp);
01074 tp->tr_a.tu_stp = SOLTAB_NULL;
01075 tp->tr_op = OP_NOP;
01076 }
01077 return;
01078 }
01079
01080 default:
01081 bu_log( "rt_tree_kill_dead_solid_refs(x%x): unknown op=x%x\n",
01082 tp, tp->tr_op );
01083 return;
01084
01085 case OP_XOR:
01086 case OP_UNION:
01087 case OP_INTERSECT:
01088 case OP_SUBTRACT:
01089
01090 rt_tree_kill_dead_solid_refs( tp->tr_b.tb_left );
01091 rt_tree_kill_dead_solid_refs( tp->tr_b.tb_right );
01092 break;
01093 case OP_NOT:
01094 case OP_GUARD:
01095 case OP_XNOP:
01096
01097 rt_tree_kill_dead_solid_refs( tp->tr_b.tb_left );
01098 break;
01099 case OP_NOP:
01100
01101 return;
01102 }
01103 return;
01104 }
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120 int
01121 rt_tree_elim_nops( register union tree *tp, struct resource *resp )
01122 {
01123 union tree *left, *right;
01124
01125 RT_CK_RESOURCE(resp);
01126 top:
01127 RT_CK_TREE(tp);
01128
01129 switch( tp->tr_op ) {
01130
01131 case OP_SOLID:
01132 return(0);
01133
01134 default:
01135 bu_log( "rt_tree_elim_nops(x%x): unknown op=x%x\n",
01136 tp, tp->tr_op );
01137 return(-1);
01138
01139 case OP_XOR:
01140 case OP_UNION:
01141
01142 left = tp->tr_b.tb_left;
01143 right = tp->tr_b.tb_right;
01144 if( rt_tree_elim_nops( left, resp ) < 0 ) {
01145 *tp = *right;
01146 RT_FREE_TREE( left, resp );
01147 RT_FREE_TREE( right, resp );
01148 goto top;
01149 }
01150 if( rt_tree_elim_nops( right, resp ) < 0 ) {
01151 *tp = *left;
01152 RT_FREE_TREE( left, resp );
01153 RT_FREE_TREE( right, resp );
01154 goto top;
01155 }
01156 break;
01157 case OP_INTERSECT:
01158
01159 left = tp->tr_b.tb_left;
01160 right = tp->tr_b.tb_right;
01161 if( rt_tree_elim_nops( left, resp ) < 0 ||
01162 rt_tree_elim_nops( right, resp ) < 0 ) {
01163 db_free_tree( left, resp );
01164 db_free_tree( right, resp );
01165 tp->tr_op = OP_NOP;
01166 return(-1);
01167 }
01168 break;
01169 case OP_SUBTRACT:
01170
01171
01172
01173 left = tp->tr_b.tb_left;
01174 right = tp->tr_b.tb_right;
01175 if( rt_tree_elim_nops( left, resp ) < 0 ) {
01176 db_free_tree( left, resp );
01177 db_free_tree( right, resp );
01178 tp->tr_op = OP_NOP;
01179 return(-1);
01180 }
01181 if( rt_tree_elim_nops( right, resp ) < 0 ) {
01182 *tp = *left;
01183 RT_FREE_TREE( left, resp );
01184 RT_FREE_TREE( right, resp );
01185 goto top;
01186 }
01187 break;
01188 case OP_NOT:
01189 case OP_GUARD:
01190 case OP_XNOP:
01191
01192 left = tp->tr_b.tb_left;
01193 if( rt_tree_elim_nops( left, resp ) < 0 ) {
01194 RT_FREE_TREE( left, resp );
01195 tp->tr_op = OP_NOP;
01196 return(-1);
01197 }
01198 break;
01199 case OP_NOP:
01200
01201 return(-1);
01202 }
01203 return(0);
01204 }
01205
01206
01207
01208
01209
01210
01211
01212 const char *
01213 rt_basename(register const char *str)
01214 {
01215 register const char *p = str;
01216 while( *p != '\0' )
01217 if( *p++ == '/' )
01218 str = p;
01219 return str;
01220 }
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 HIDDEN struct region *
01234 rt_getregion(struct rt_i *rtip, register const char *reg_name)
01235 {
01236 register struct region *regp;
01237 register const char *reg_base = rt_basename(reg_name);
01238
01239 RT_CK_RTI(rtip);
01240 for( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) {
01241 register const char *cp;
01242
01243 if( *reg_base == regp->reg_name[0] &&
01244 strcmp( reg_base, regp->reg_name ) == 0 )
01245 return(regp);
01246
01247 cp = rt_basename( regp->reg_name );
01248 if( *cp == *reg_name && strcmp( cp, reg_name ) == 0 )
01249 return(regp);
01250 }
01251 return(REGION_NULL);
01252 }
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262 int
01263 rt_rpp_region(struct rt_i *rtip, const char *reg_name, fastf_t *min_rpp, fastf_t *max_rpp)
01264 {
01265 register struct region *regp;
01266
01267 RT_CHECK_RTI(rtip);
01268
01269 regp = rt_getregion( rtip, reg_name );
01270 if( regp == REGION_NULL ) return(0);
01271 if( rt_bound_tree( regp->reg_treetop, min_rpp, max_rpp ) < 0)
01272 return(0);
01273 return(1);
01274 }
01275
01276
01277
01278
01279
01280
01281 void
01282 rt_fastf_float(register fastf_t *ff, register const dbfloat_t *fp, register int n)
01283 {
01284 # include "noalias.h"
01285 while( n-- ) {
01286 *ff++ = *fp++;
01287 *ff++ = *fp++;
01288 *ff++ = *fp++;
01289 ff += ELEMENTS_PER_VECT-3;
01290 }
01291 }
01292
01293
01294
01295
01296
01297
01298 void
01299 rt_mat_dbmat(register fastf_t *ff, register const dbfloat_t *dbp)
01300 {
01301
01302 *ff++ = *dbp++;
01303 *ff++ = *dbp++;
01304 *ff++ = *dbp++;
01305 *ff++ = *dbp++;
01306
01307 *ff++ = *dbp++;
01308 *ff++ = *dbp++;
01309 *ff++ = *dbp++;
01310 *ff++ = *dbp++;
01311
01312 *ff++ = *dbp++;
01313 *ff++ = *dbp++;
01314 *ff++ = *dbp++;
01315 *ff++ = *dbp++;
01316
01317 *ff++ = *dbp++;
01318 *ff++ = *dbp++;
01319 *ff++ = *dbp++;
01320 *ff++ = *dbp++;
01321 }
01322
01323
01324
01325
01326
01327
01328 void
01329 rt_dbmat_mat(register dbfloat_t *dbp, register const fastf_t *ff)
01330 {
01331
01332 *dbp++ = (dbfloat_t) *ff++;
01333 *dbp++ = (dbfloat_t) *ff++;
01334 *dbp++ = (dbfloat_t) *ff++;
01335 *dbp++ = (dbfloat_t) *ff++;
01336
01337 *dbp++ = (dbfloat_t) *ff++;
01338 *dbp++ = (dbfloat_t) *ff++;
01339 *dbp++ = (dbfloat_t) *ff++;
01340 *dbp++ = (dbfloat_t) *ff++;
01341
01342 *dbp++ = (dbfloat_t) *ff++;
01343 *dbp++ = (dbfloat_t) *ff++;
01344 *dbp++ = (dbfloat_t) *ff++;
01345 *dbp++ = (dbfloat_t) *ff++;
01346
01347 *dbp++ = (dbfloat_t) *ff++;
01348 *dbp++ = (dbfloat_t) *ff++;
01349 *dbp++ = (dbfloat_t) *ff++;
01350 *dbp++ = (dbfloat_t) *ff++;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360 struct soltab *
01361 rt_find_solid(const struct rt_i *rtip, register const char *name)
01362 {
01363 register struct soltab *stp;
01364 struct directory *dp;
01365
01366 RT_CHECK_RTI(rtip);
01367 if( (dp = db_lookup( (struct db_i *)rtip->rti_dbip, (char *)name,
01368 LOOKUP_QUIET )) == DIR_NULL )
01369 return(RT_SOLTAB_NULL);
01370
01371 RT_VISIT_ALL_SOLTABS_START( stp, (struct rt_i *)rtip ) {
01372 if( stp->st_dp == dp )
01373 return(stp);
01374 } RT_VISIT_ALL_SOLTABS_END
01375 return(RT_SOLTAB_NULL);
01376 }
01377
01378
01379
01380
01381
01382 void
01383 rt_optim_tree(register union tree *tp, struct resource *resp)
01384 {
01385 register union tree **sp;
01386 register union tree *low;
01387 register union tree **stackend;
01388
01389 RT_CK_TREE(tp);
01390 while( (sp = resp->re_boolstack) == (union tree **)0 )
01391 rt_grow_boolstack( resp );
01392 stackend = &(resp->re_boolstack[resp->re_boolslen-1]);
01393 *sp++ = TREE_NULL;
01394 *sp++ = tp;
01395 while( (tp = *--sp) != TREE_NULL ) {
01396 switch( tp->tr_op ) {
01397 case OP_NOP:
01398
01399
01400 break;
01401 case OP_SOLID:
01402 break;
01403 case OP_SUBTRACT:
01404 while( (low=tp->tr_b.tb_left)->tr_op == OP_SUBTRACT ) {
01405
01406 tp->tr_b.tb_left = low->tr_b.tb_left;
01407 low->tr_op = OP_UNION;
01408 low->tr_b.tb_left = low->tr_b.tb_right;
01409 low->tr_b.tb_right = tp->tr_b.tb_right;
01410 tp->tr_b.tb_right = low;
01411 }
01412
01413 *sp++ = tp->tr_b.tb_right;
01414 *sp++ = tp->tr_b.tb_left;
01415 if( sp >= stackend ) {
01416 register int off = sp - resp->re_boolstack;
01417 rt_grow_boolstack( resp );
01418 sp = &(resp->re_boolstack[off]);
01419 stackend = &(resp->re_boolstack[resp->re_boolslen-1]);
01420 }
01421 break;
01422 case OP_UNION:
01423 case OP_INTERSECT:
01424 case OP_XOR:
01425
01426
01427 *sp++ = tp->tr_b.tb_right;
01428 *sp++ = tp->tr_b.tb_left;
01429 if( sp >= stackend ) {
01430 register int off = sp - resp->re_boolstack;
01431 rt_grow_boolstack( resp );
01432 sp = &(resp->re_boolstack[off]);
01433 stackend = &(resp->re_boolstack[resp->re_boolslen-1]);
01434 }
01435 break;
01436 default:
01437 bu_log("rt_optim_tree: bad op x%x\n", tp->tr_op);
01438 break;
01439 }
01440 }
01441 }
01442
01443
01444
01445
01446 HIDDEN void
01447 rt_tree_region_assign(register union tree *tp, register const struct region *regionp)
01448 {
01449 RT_CK_TREE(tp);
01450 RT_CK_REGION(regionp);
01451 switch( tp->tr_op ) {
01452 case OP_NOP:
01453 return;
01454
01455 case OP_SOLID:
01456 tp->tr_a.tu_regionp = (struct region *)regionp;
01457 return;
01458
01459 case OP_NOT:
01460 case OP_GUARD:
01461 case OP_XNOP:
01462 tp->tr_b.tb_regionp = (struct region *)regionp;
01463 rt_tree_region_assign( tp->tr_b.tb_left, regionp );
01464 return;
01465
01466 case OP_UNION:
01467 case OP_INTERSECT:
01468 case OP_SUBTRACT:
01469 case OP_XOR:
01470 tp->tr_b.tb_regionp = (struct region *)regionp;
01471 rt_tree_region_assign( tp->tr_b.tb_left, regionp );
01472 rt_tree_region_assign( tp->tr_b.tb_right, regionp );
01473 return;
01474
01475 default:
01476 rt_bomb("rt_tree_region_assign: bad op\n");
01477 }
01478 }
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488