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
00038
00039
00040
00041
00042 #ifndef lint
00043 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_tree.c,v 14.14 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00044 #endif
00045
00046 #include "common.h"
00047
00048 #include <stdio.h>
00049 #include <math.h>
00050 #ifdef HAVE_STRING_H
00051 # include <string.h>
00052 #else
00053 # include <strings.h>
00054 #endif
00055
00056 #include "machine.h"
00057 #include "bu.h"
00058 #include "vmath.h"
00059 #include "bn.h"
00060 #include "nmg.h"
00061 #include "raytrace.h"
00062
00063 #include "./debug.h"
00064
00065
00066 BU_EXTERN(void db_ck_tree, (const union tree *tp));
00067
00068
00069
00070
00071
00072
00073
00074 void
00075 db_dup_db_tree_state(struct db_tree_state *otsp, const struct db_tree_state *itsp)
00076 {
00077 int shader_len=0;
00078 int i;
00079
00080 RT_CK_DBTS(itsp);
00081 RT_CK_DBI(itsp->ts_dbip);
00082
00083 *otsp = *itsp;
00084
00085 if( itsp->ts_mater.ma_shader )
00086 shader_len = strlen( itsp->ts_mater.ma_shader );
00087 if( shader_len )
00088 {
00089 otsp->ts_mater.ma_shader = (char *)bu_malloc( shader_len+1, "db_new_combined_tree_state: ma_shader" );
00090 strcpy( otsp->ts_mater.ma_shader, itsp->ts_mater.ma_shader );
00091 }
00092 else
00093 otsp->ts_mater.ma_shader = (char *)NULL;
00094
00095 if( itsp->ts_attrs.count > 0 ) {
00096 bu_avs_init( &otsp->ts_attrs, itsp->ts_attrs.count, "otsp->ts_attrs" );
00097 for( i=0 ; i<itsp->ts_attrs.count ; i++ )
00098 bu_avs_add( &otsp->ts_attrs, itsp->ts_attrs.avp[i].name,
00099 itsp->ts_attrs.avp[i].value );
00100 } else {
00101 bu_avs_init_empty( &otsp->ts_attrs );
00102 }
00103 }
00104
00105
00106
00107
00108
00109
00110 void
00111 db_free_db_tree_state( struct db_tree_state *tsp )
00112 {
00113 RT_CK_DBTS(tsp);
00114 RT_CK_DBI(tsp->ts_dbip);
00115 if( tsp->ts_mater.ma_shader ) {
00116 bu_free( tsp->ts_mater.ma_shader, "db_free_combined_tree_state: ma_shader" );
00117 tsp->ts_mater.ma_shader = (char *)NULL;
00118 }
00119 if( tsp->ts_attrs.max > 0 ) {
00120 bu_avs_free( &tsp->ts_attrs );
00121 tsp->ts_attrs.avp = (struct bu_attribute_value_pair *)NULL;
00122 }
00123 tsp->ts_dbip = (struct db_i *)NULL;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 void
00134 db_init_db_tree_state( struct db_tree_state *tsp, struct db_i *dbip, struct resource *resp )
00135 {
00136 RT_CK_DBI(dbip);
00137 RT_CK_RESOURCE(resp);
00138
00139 bzero( (char *)tsp, sizeof(*tsp) );
00140 tsp->magic = RT_DBTS_MAGIC;
00141 tsp->ts_dbip = dbip;
00142 tsp->ts_resp = resp;
00143 bu_avs_init_empty( &tsp->ts_attrs );
00144 MAT_IDN( tsp->ts_mat );
00145 }
00146
00147
00148
00149
00150 struct combined_tree_state *
00151 db_new_combined_tree_state(register const struct db_tree_state *tsp, register const struct db_full_path *pathp)
00152 {
00153 struct combined_tree_state *new;
00154
00155 RT_CK_DBTS(tsp);
00156 RT_CK_FULL_PATH(pathp);
00157 RT_CK_DBI(tsp->ts_dbip);
00158
00159 BU_GETSTRUCT( new, combined_tree_state );
00160 new->magic = RT_CTS_MAGIC;
00161 db_dup_db_tree_state( &(new->cts_s), tsp );
00162 db_full_path_init( &(new->cts_p) );
00163 db_dup_full_path( &(new->cts_p), pathp );
00164 return new;
00165 }
00166
00167
00168
00169
00170 struct combined_tree_state *
00171 db_dup_combined_tree_state(const struct combined_tree_state *old)
00172 {
00173 struct combined_tree_state *new;
00174
00175 RT_CK_CTS(old);
00176 BU_GETSTRUCT( new, combined_tree_state );
00177 new->magic = RT_CTS_MAGIC;
00178 db_dup_db_tree_state( &(new->cts_s), &(old->cts_s) );
00179 db_full_path_init( &(new->cts_p) );
00180 db_dup_full_path( &(new->cts_p), &(old->cts_p) );
00181 return new;
00182 }
00183
00184
00185
00186
00187 void
00188 db_free_combined_tree_state(register struct combined_tree_state *ctsp)
00189 {
00190 RT_CK_CTS(ctsp);
00191 db_free_full_path( &(ctsp->cts_p) );
00192 db_free_db_tree_state( &(ctsp->cts_s) );
00193 bzero( (char *)ctsp, sizeof(*ctsp) );
00194 bu_free( (char *)ctsp, "combined_tree_state");
00195 }
00196
00197
00198
00199
00200 void
00201 db_pr_tree_state(register const struct db_tree_state *tsp)
00202 {
00203 int i;
00204
00205 RT_CK_DBTS(tsp);
00206
00207 bu_log("db_pr_tree_state(x%x):\n", tsp);
00208 bu_log(" ts_dbip=x%x\n", tsp->ts_dbip);
00209 bu_printb(" ts_sofar", tsp->ts_sofar, "\020\3REGION\2INTER\1MINUS" );
00210 bu_log("\n");
00211 bu_log(" ts_regionid=%d\n", tsp->ts_regionid);
00212 bu_log(" ts_aircode=%d\n", tsp->ts_aircode);
00213 bu_log(" ts_gmater=%d\n", tsp->ts_gmater);
00214 bu_log(" ts_los=%d\n", tsp->ts_los);
00215 bu_log(" ts_mater.ma_color=%g,%g,%g\n",
00216 tsp->ts_mater.ma_color[0],
00217 tsp->ts_mater.ma_color[1],
00218 tsp->ts_mater.ma_color[2] );
00219 bu_log(" ts_mater.ma_temperature=%g K\n", tsp->ts_mater.ma_temperature);
00220 bu_log(" ts_mater.ma_shader=%s\n", tsp->ts_mater.ma_shader ? tsp->ts_mater.ma_shader : "" );
00221 for( i=0 ; i<tsp->ts_attrs.count ; i++ ) {
00222 bu_log( "\t%s = %s\n", tsp->ts_attrs.avp[i].name, tsp->ts_attrs.avp[i].value );
00223 }
00224 bn_mat_print("ts_mat", tsp->ts_mat );
00225 bu_log(" ts_resp=x%x\n", tsp->ts_resp );
00226 }
00227
00228
00229
00230
00231 void
00232 db_pr_combined_tree_state(register const struct combined_tree_state *ctsp)
00233 {
00234 char *str;
00235
00236 RT_CK_CTS(ctsp);
00237 bu_log("db_pr_combined_tree_state(x%x):\n", ctsp);
00238 db_pr_tree_state( &(ctsp->cts_s) );
00239 str = db_path_to_string( &(ctsp->cts_p) );
00240 bu_log(" path='%s'\n", str);
00241 bu_free( str, "path string" );
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 int
00256 db_apply_state_from_comb(struct db_tree_state *tsp, const struct db_full_path *pathp, register const struct rt_comb_internal *comb)
00257 {
00258 RT_CK_DBTS(tsp);
00259 RT_CK_COMB(comb);
00260
00261 if( comb->rgb_valid == 1 ) {
00262 if( tsp->ts_sofar & TS_SOFAR_REGION ) {
00263 if( (tsp->ts_sofar&(TS_SOFAR_MINUS|TS_SOFAR_INTER)) == 0 ) {
00264
00265 char *sofar = db_path_to_string(pathp);
00266
00267 bu_log("db_apply_state_from_comb(): WARNING: color override in combination within region '%s', ignored\n",
00268 sofar );
00269 bu_free(sofar, "path string");
00270 }
00271
00272 } else if( tsp->ts_mater.ma_cinherit == 0 ) {
00273
00274 tsp->ts_mater.ma_color_valid = 1;
00275 tsp->ts_mater.ma_color[0] =
00276 (((float)(comb->rgb[0]))*bn_inv255);
00277 tsp->ts_mater.ma_color[1] =
00278 (((float)(comb->rgb[1]))*bn_inv255);
00279 tsp->ts_mater.ma_color[2] =
00280 (((float)(comb->rgb[2]))*bn_inv255);
00281
00282 tsp->ts_mater.ma_cinherit = comb->inherit;
00283 }
00284 }
00285 if( comb->temperature > 0 ) {
00286 if( tsp->ts_sofar & TS_SOFAR_REGION ) {
00287 if( (tsp->ts_sofar&(TS_SOFAR_MINUS|TS_SOFAR_INTER)) == 0 ) {
00288
00289 char *sofar = db_path_to_string(pathp);
00290
00291 bu_log("db_apply_state_from_comb(): WARNING: temperature in combination below region '%s', ignored\n",
00292 sofar );
00293 bu_free(sofar, "path string");
00294 }
00295
00296 } else if( tsp->ts_mater.ma_minherit == 0 ) {
00297
00298 tsp->ts_mater.ma_temperature = comb->temperature;
00299 }
00300 }
00301 if( bu_vls_strlen( &comb->shader ) > 0 ) {
00302 if( tsp->ts_sofar & TS_SOFAR_REGION ) {
00303 if( (tsp->ts_sofar&(TS_SOFAR_MINUS|TS_SOFAR_INTER)) == 0 ) {
00304
00305 char *sofar = db_path_to_string(pathp);
00306
00307 bu_log("db_apply_state_from_comb(): WARNING: material property spec in combination below region '%s', ignored\n",
00308 sofar );
00309 bu_free(sofar, "path string");
00310 }
00311
00312 } else if( tsp->ts_mater.ma_minherit == 0 ) {
00313 struct bu_vls tmp_vls;
00314
00315
00316 if( tsp->ts_mater.ma_shader )
00317 bu_free( (genptr_t)tsp->ts_mater.ma_shader, "ma_shader" );
00318
00319 bu_vls_init( &tmp_vls );
00320 if( bu_shader_to_key_eq( bu_vls_addr( &comb->shader ), &tmp_vls ) )
00321 {
00322 char *sofar = db_path_to_string(pathp);
00323
00324 bu_log( "db_apply_state_from_comb: Warning: bad shader in %s (ignored):\n", sofar );
00325 bu_vls_free( &tmp_vls );
00326 bu_free(sofar, "path string");
00327 tsp->ts_mater.ma_shader = (char *)NULL;
00328 }
00329 else
00330 {
00331 tsp->ts_mater.ma_shader = bu_vls_strdup( &tmp_vls );
00332 bu_vls_free( &tmp_vls );
00333 }
00334 tsp->ts_mater.ma_minherit = comb->inherit;
00335 }
00336 }
00337
00338
00339 if( comb->region_flag ) {
00340 if( tsp->ts_sofar & TS_SOFAR_REGION ) {
00341 if( (tsp->ts_sofar&(TS_SOFAR_MINUS|TS_SOFAR_INTER)) == 0 ) {
00342 char *sofar = db_path_to_string(pathp);
00343 bu_log("Warning: region unioned into region at '%s', lower region info ignored\n",
00344 sofar);
00345 bu_free(sofar, "path string");
00346 }
00347
00348 } else {
00349
00350 tsp->ts_sofar |= TS_SOFAR_REGION;
00351 tsp->ts_regionid = comb->region_id;
00352 tsp->ts_is_fastgen = comb->is_fastgen;
00353 tsp->ts_aircode = comb->aircode;
00354 tsp->ts_gmater = comb->GIFTmater;
00355 tsp->ts_los = comb->los;
00356 return(1);
00357 }
00358 }
00359 return(0);
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 int
00373 db_apply_state_from_memb(struct db_tree_state *tsp, struct db_full_path *pathp, const union tree *tp)
00374 {
00375 register struct directory *mdp;
00376 mat_t xmat;
00377 mat_t old_xlate;
00378
00379 RT_CK_DBTS(tsp);
00380 RT_CK_FULL_PATH(pathp);
00381 RT_CK_TREE(tp);
00382
00383 if( (mdp = db_lookup( tsp->ts_dbip, tp->tr_l.tl_name, LOOKUP_QUIET )) == DIR_NULL ) {
00384 char *sofar = db_path_to_string(pathp);
00385 bu_log("db_lookup(%s) failed in %s\n", tp->tr_l.tl_name, sofar);
00386 bu_free(sofar, "path string");
00387 return -1;
00388 }
00389
00390 db_add_node_to_full_path( pathp, mdp );
00391
00392 MAT_COPY( old_xlate, tsp->ts_mat );
00393 if( tp->tr_l.tl_mat ) {
00394 MAT_COPY( xmat, tp->tr_l.tl_mat );
00395 }
00396 else {
00397 MAT_IDN( xmat );
00398 }
00399
00400
00401
00402
00403
00404 db_apply_anims( pathp, mdp, old_xlate, xmat,
00405 (tsp->ts_sofar & TS_SOFAR_REGION) ?
00406 (struct mater_info *)NULL :
00407 &tsp->ts_mater );
00408
00409 bn_mat_mul(tsp->ts_mat, old_xlate, xmat);
00410
00411 return(0);
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 int
00423 db_apply_state_from_one_member(
00424 struct db_tree_state *tsp,
00425 struct db_full_path *pathp,
00426 const char *cp,
00427 int sofar,
00428 const union tree *tp )
00429 {
00430 int ret;
00431
00432 RT_CK_DBTS(tsp);
00433 RT_CHECK_DBI( tsp->ts_dbip );
00434 RT_CK_FULL_PATH( pathp );
00435 RT_CK_TREE(tp);
00436
00437 switch( tp->tr_op ) {
00438
00439 case OP_DB_LEAF:
00440 if( strcmp( cp, tp->tr_l.tl_name ) != 0 )
00441 return 0;
00442 tsp->ts_sofar |= sofar;
00443 if( db_apply_state_from_memb( tsp, pathp, tp ) < 0 )
00444 return -1;
00445 return 1;
00446
00447 case OP_UNION:
00448 case OP_INTERSECT:
00449 case OP_SUBTRACT:
00450 case OP_XOR:
00451 ret = db_apply_state_from_one_member( tsp, pathp, cp, sofar,
00452 tp->tr_b.tb_left );
00453 if( ret != 0 ) return ret;
00454 if( tp->tr_op == OP_SUBTRACT )
00455 sofar |= TS_SOFAR_MINUS;
00456 else if( tp->tr_op == OP_INTERSECT )
00457 sofar |= TS_SOFAR_INTER;
00458 return db_apply_state_from_one_member( tsp, pathp, cp, sofar,
00459 tp->tr_b.tb_right );
00460
00461 default:
00462 bu_log("db_apply_state_from_one_member: bad op %d\n", tp->tr_op);
00463 bu_bomb("db_apply_state_from_one_member\n");
00464 }
00465 return -1;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 union tree *
00478 db_find_named_leaf( union tree *tp, const char *cp )
00479 {
00480 union tree *ret;
00481
00482 RT_CK_TREE(tp);
00483
00484 switch( tp->tr_op ) {
00485
00486 case OP_DB_LEAF:
00487 if( strcmp( cp, tp->tr_l.tl_name ) )
00488 return TREE_NULL;
00489 return tp;
00490
00491 case OP_UNION:
00492 case OP_INTERSECT:
00493 case OP_SUBTRACT:
00494 case OP_XOR:
00495 ret = db_find_named_leaf( tp->tr_b.tb_left, cp );
00496 if( ret != TREE_NULL ) return ret;
00497 return db_find_named_leaf( tp->tr_b.tb_right, cp );
00498
00499 default:
00500 bu_log("db_find_named_leaf: bad op %d\n", tp->tr_op);
00501 bu_bomb("db_find_named_leaf\n");
00502 }
00503 return TREE_NULL;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 union tree *
00519 db_find_named_leafs_parent( int *side, union tree *tp, const char *cp )
00520 {
00521 union tree *ret;
00522
00523 RT_CK_TREE(tp);
00524
00525 switch( tp->tr_op ) {
00526
00527 case OP_DB_LEAF:
00528
00529 return TREE_NULL;
00530
00531 case OP_UNION:
00532 case OP_INTERSECT:
00533 case OP_SUBTRACT:
00534 case OP_XOR:
00535 if( tp->tr_b.tb_left->tr_op == OP_DB_LEAF ) {
00536 if( strcmp( cp, tp->tr_b.tb_left->tr_l.tl_name ) == 0 ) {
00537 *side = 1;
00538 return tp;
00539 }
00540 }
00541 if( tp->tr_b.tb_right->tr_op == OP_DB_LEAF ) {
00542 if( strcmp( cp, tp->tr_b.tb_right->tr_l.tl_name ) == 0 ) {
00543 *side = 2;
00544 return tp;
00545 }
00546 }
00547
00548
00549 ret = db_find_named_leafs_parent( side, tp->tr_b.tb_left, cp );
00550 if( ret != TREE_NULL ) return ret;
00551 return db_find_named_leafs_parent( side, tp->tr_b.tb_right, cp );
00552
00553 default:
00554 bu_log("db_find_named_leafs_parent: bad op %d\n", tp->tr_op);
00555 bu_bomb("db_find_named_leafs_parent\n");
00556 }
00557 return TREE_NULL;
00558 }
00559
00560
00561
00562
00563 void
00564 db_tree_del_lhs( union tree *tp, struct resource *resp )
00565 {
00566 union tree *subtree;
00567
00568 RT_CK_TREE(tp);
00569
00570 switch( tp->tr_op ) {
00571
00572 default:
00573 bu_bomb("db_tree_del_lhs() called with leaf node as parameter\n");
00574
00575 case OP_UNION:
00576 case OP_INTERSECT:
00577 case OP_SUBTRACT:
00578 case OP_XOR:
00579 switch( tp->tr_b.tb_left->tr_op ) {
00580 case OP_NOP:
00581 case OP_SOLID:
00582 case OP_REGION:
00583 case OP_NMG_TESS:
00584 case OP_DB_LEAF:
00585
00586 db_free_tree( tp->tr_b.tb_left, resp );
00587 tp->tr_b.tb_left = TREE_NULL;
00588 subtree = tp->tr_b.tb_right;
00589
00590
00591
00592
00593
00594
00595 *tp = *subtree;
00596 RT_FREE_TREE( subtree, resp );
00597 return;
00598 default:
00599 bu_bomb("db_tree_del_lhs() lhs is not a leaf node\n");
00600 }
00601 }
00602 }
00603
00604
00605
00606
00607 void
00608 db_tree_del_rhs( union tree *tp, struct resource *resp )
00609 {
00610 union tree *subtree;
00611
00612 RT_CK_TREE(tp);
00613
00614 switch( tp->tr_op ) {
00615
00616 default:
00617 bu_bomb("db_tree_del_rhs() called with leaf node as parameter\n");
00618
00619 case OP_UNION:
00620 case OP_INTERSECT:
00621 case OP_SUBTRACT:
00622 case OP_XOR:
00623 switch( tp->tr_b.tb_right->tr_op ) {
00624 case OP_NOP:
00625 case OP_SOLID:
00626 case OP_REGION:
00627 case OP_NMG_TESS:
00628 case OP_DB_LEAF:
00629
00630 db_free_tree( tp->tr_b.tb_right, resp );
00631 tp->tr_b.tb_right = TREE_NULL;
00632 subtree = tp->tr_b.tb_left;
00633
00634
00635
00636
00637
00638
00639 *tp = *subtree;
00640 RT_FREE_TREE( subtree, resp );
00641 return;
00642 default:
00643 bu_bomb("db_tree_del_rhs() rhs is not a leaf node\n");
00644 }
00645 }
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 int
00672 db_tree_del_dbleaf(union tree **tp, const char *cp, struct resource *resp)
00673 {
00674 union tree *parent;
00675 int side = 0;
00676
00677 if( *tp == TREE_NULL ) return -1;
00678
00679 RT_CK_TREE(*tp);
00680 RT_CK_RESOURCE(resp);
00681
00682 if( (parent = db_find_named_leafs_parent( &side, *tp, cp )) == TREE_NULL ) {
00683
00684 if( (*tp)->tr_op == OP_DB_LEAF &&
00685 strcmp( cp, (*tp)->tr_l.tl_name ) == 0 ) {
00686 db_free_tree( *tp, resp );
00687 *tp = TREE_NULL;
00688 return 0;
00689 }
00690 return -2;
00691 }
00692
00693 switch( side ) {
00694 case 1:
00695 db_tree_del_lhs( parent, resp );
00696 (void)db_tree_del_dbleaf( tp, cp, resp );
00697 return 0;
00698 case 2:
00699 db_tree_del_rhs( parent, resp );
00700 (void)db_tree_del_dbleaf( tp, cp, resp );
00701 return 0;
00702 }
00703 bu_log("db_tree_del_dbleaf() unknown side=%d?\n", side);
00704 return -3;
00705 }
00706
00707
00708
00709
00710
00711
00712 void
00713 db_tree_mul_dbleaf( union tree *tp, const mat_t mat )
00714 {
00715 mat_t temp;
00716
00717 RT_CK_TREE(tp);
00718
00719 switch( tp->tr_op ) {
00720
00721 case OP_DB_LEAF:
00722 if( tp->tr_l.tl_mat == NULL ) {
00723 tp->tr_l.tl_mat = bn_mat_dup(mat);
00724 return;
00725 }
00726 bn_mat_mul( temp, mat, tp->tr_l.tl_mat );
00727 MAT_COPY( tp->tr_l.tl_mat, temp );
00728 break;
00729
00730 case OP_UNION:
00731 case OP_INTERSECT:
00732 case OP_SUBTRACT:
00733 case OP_XOR:
00734 db_tree_mul_dbleaf( tp->tr_b.tb_left, mat );
00735 db_tree_mul_dbleaf( tp->tr_b.tb_right, mat );
00736 break;
00737
00738 default:
00739 bu_log("db_tree_mul_dbleaf: bad op %d\n", tp->tr_op);
00740 bu_bomb("db_tree_mul_dbleaf\n");
00741 }
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 void
00754 db_tree_funcleaf(
00755 struct db_i *dbip,
00756 struct rt_comb_internal *comb,
00757 union tree *comb_tree,
00758 void (*leaf_func)(),
00759 genptr_t user_ptr1,
00760 genptr_t user_ptr2,
00761 genptr_t user_ptr3 )
00762 {
00763 RT_CK_DBI( dbip );
00764
00765 if( !comb_tree )
00766 return;
00767
00768 RT_CK_TREE( comb_tree );
00769
00770 switch( comb_tree->tr_op )
00771 {
00772 case OP_DB_LEAF:
00773 (*leaf_func)( dbip, comb, comb_tree, user_ptr1, user_ptr2, user_ptr3 );
00774 break;
00775 case OP_UNION:
00776 case OP_INTERSECT:
00777 case OP_SUBTRACT:
00778 case OP_XOR:
00779 db_tree_funcleaf( dbip, comb, comb_tree->tr_b.tb_left, leaf_func, user_ptr1, user_ptr2, user_ptr3 );
00780 db_tree_funcleaf( dbip, comb, comb_tree->tr_b.tb_right, leaf_func, user_ptr1, user_ptr2, user_ptr3 );
00781 break;
00782 default:
00783 bu_log( "db_tree_funcleaf: bad op %d\n", comb_tree->tr_op );
00784 bu_bomb( "db_tree_funcleaf: bad op\n" );
00785 break;
00786 }
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 int
00810 db_follow_path(
00811 struct db_tree_state *tsp,
00812 struct db_full_path *total_path,
00813 const struct db_full_path *new_path,
00814 int noisy,
00815 int depth )
00816 {
00817 struct rt_db_internal intern;
00818 struct rt_comb_internal *comb;
00819 struct directory *comb_dp;
00820 struct directory *dp;
00821 int j;
00822
00823 RT_CK_DBTS(tsp);
00824 RT_CHECK_DBI( tsp->ts_dbip );
00825 RT_CK_FULL_PATH( total_path );
00826 RT_CK_FULL_PATH( new_path );
00827 RT_CK_RESOURCE( tsp->ts_resp );
00828
00829 if(RT_G_DEBUG&DEBUG_TREEWALK) {
00830 char *sofar = db_path_to_string(total_path);
00831 char *toofar = db_path_to_string(new_path);
00832 bu_log("db_follow_path() total_path='%s', tsp=x%x, new_path='%s', noisy=%d, depth=%d\n",
00833 sofar, tsp, toofar, noisy, depth );
00834 bu_free(sofar, "path string");
00835 bu_free(toofar, "path string");
00836 }
00837
00838 if( depth < 0 ) {
00839 depth = new_path->fp_len-1 + depth;
00840 if( depth < 0 ) rt_bomb("db_follow_path() depth exceeded provided path\n");
00841 } else if( depth >= new_path->fp_len ) {
00842 depth = new_path->fp_len-1;
00843 } else if( depth == 0 ) {
00844
00845 depth = new_path->fp_len-1;
00846 }
00847
00848 j = 0;
00849
00850
00851 if( total_path->fp_len > 0 ) {
00852
00853 comb_dp = DB_FULL_PATH_CUR_DIR(total_path);
00854 } else {
00855
00856 comb_dp = DIR_NULL;
00857 dp = new_path->fp_names[0];
00858 RT_CK_DIR(dp);
00859
00860 if( tsp->ts_dbip->dbi_anroot ) {
00861 register struct animate *anp;
00862 mat_t old_xlate, xmat;
00863
00864 for( anp=tsp->ts_dbip->dbi_anroot; anp != ANIM_NULL; anp = anp->an_forw ) {
00865 RT_CK_ANIMATE(anp);
00866 if( dp != anp->an_path.fp_names[0] )
00867 continue;
00868 MAT_COPY( old_xlate, tsp->ts_mat );
00869 MAT_IDN( xmat );
00870 db_do_anim( anp, old_xlate, xmat, &(tsp->ts_mater) );
00871 bn_mat_mul( tsp->ts_mat, old_xlate, xmat );
00872 }
00873 }
00874
00875
00876 db_add_node_to_full_path( total_path, dp );
00877
00878 if( (dp->d_flags & DIR_COMB) == 0 ) goto is_leaf;
00879
00880
00881 j = 1;
00882 comb_dp = dp;
00883 }
00884
00885
00886
00887
00888 do {
00889
00890 if( j > depth ) break;
00891 dp = new_path->fp_names[j];
00892 RT_CK_DIR(dp);
00893
00894 if( (comb_dp->d_flags & DIR_COMB) == 0 ) {
00895 bu_log("db_follow_path() %s isn't combination\n", comb_dp->d_namep);
00896 goto fail;
00897 }
00898
00899
00900 if(RT_G_DEBUG&DEBUG_TREEWALK) {
00901 bu_log("db_follow_path() at %s/%s\n", comb_dp->d_namep, dp->d_namep );
00902 }
00903
00904
00905 if( rt_db_get_internal( &intern, comb_dp, tsp->ts_dbip, NULL, tsp->ts_resp ) < 0 )
00906 goto fail;
00907 comb = (struct rt_comb_internal *)intern.idb_ptr;
00908 RT_CK_COMB(comb);
00909 if( db_apply_state_from_comb( tsp, total_path, comb ) < 0 )
00910 goto fail;
00911
00912
00913 if( db_apply_state_from_one_member( tsp, total_path, dp->d_namep, 0, comb->tree ) <= 0 ) {
00914 bu_log("db_follow_path() ERROR: unable to apply member %s state\n", dp->d_namep);
00915 goto fail;
00916 }
00917
00918
00919
00920 rt_db_free_internal( &intern, tsp->ts_resp );
00921
00922
00923 if( (dp->d_flags & DIR_COMB) == 0 ) {
00924 is_leaf:
00925
00926 if( j == new_path->fp_len-1 ) {
00927
00928 goto out;
00929 }
00930
00931 if( noisy ) {
00932 char *sofar = db_path_to_string(total_path);
00933 char *toofar = db_path_to_string(new_path);
00934 bu_log("db_follow_path() ERROR: path ended in leaf at '%s', additional path specified '%s'\n",
00935 sofar, toofar );
00936 bu_free(sofar, "path string");
00937 bu_free(toofar, "path string");
00938 }
00939 goto fail;
00940 }
00941
00942
00943 j++;
00944 comb_dp = dp;
00945 } while( j <= depth );
00946
00947 out:
00948 if(RT_G_DEBUG&DEBUG_TREEWALK) {
00949 char *sofar = db_path_to_string(total_path);
00950 bu_log("db_follow_path() returns total_path='%s'\n",
00951 sofar);
00952 bu_free(sofar, "path string");
00953 }
00954 return 0;
00955 fail:
00956 return -1;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 int
00972 db_follow_path_for_state(struct db_tree_state *tsp, struct db_full_path *total_path, const char *orig_str, int noisy)
00973 {
00974 struct db_full_path new_path;
00975 int ret;
00976
00977 RT_CK_DBTS(tsp);
00978
00979 if( *orig_str == '\0' ) return 0;
00980
00981 if( db_string_to_path( &new_path, tsp->ts_dbip, orig_str ) < 0 )
00982 return -1;
00983
00984 if( new_path.fp_len <= 0 ) return 0;
00985
00986 ret = db_follow_path( tsp, total_path, &new_path, noisy, 0 );
00987 db_free_full_path( &new_path );
00988
00989 return ret;
00990 }
00991
00992
00993
00994
00995
00996
00997 HIDDEN int
00998 db_detect_cycle( struct db_full_path *pathp, union tree *tp )
00999 {
01000
01001 long int depth = pathp->fp_len - 1;
01002
01003
01004 while (--depth >= 0) {
01005 if (strcmp(tp->tr_l.tl_name, pathp->fp_names[depth]->d_namep) == 0) {
01006 return 1;
01007 }
01008 }
01009
01010
01011 return 0;
01012 }
01013
01014
01015
01016
01017
01018
01019 HIDDEN void
01020 db_recurse_subtree(union tree *tp, struct db_tree_state *msp, struct db_full_path *pathp, struct combined_tree_state **region_start_statepp, genptr_t client_data)
01021 {
01022 struct db_tree_state memb_state;
01023 union tree *subtree;
01024
01025 RT_CK_TREE(tp);
01026 RT_CK_DBTS(msp);
01027 RT_CK_RESOURCE(msp->ts_resp);
01028 db_dup_db_tree_state( &memb_state, msp );
01029
01030 switch( tp->tr_op ) {
01031
01032 case OP_DB_LEAF:
01033 if( db_apply_state_from_memb( &memb_state, pathp, tp ) < 0 ) {
01034
01035 if( tp->tr_l.tl_mat ) {
01036 bu_free( (char *)tp->tr_l.tl_mat, "tl_mat" );
01037 tp->tr_l.tl_mat = NULL;
01038 }
01039 bu_free( tp->tr_l.tl_name, "tl_name" );
01040 tp->tr_l.tl_name = NULL;
01041 tp->tr_op = OP_NOP;
01042 goto out;
01043 }
01044
01045
01046 if ( db_detect_cycle( pathp, tp ) ) {
01047 int depth = pathp->fp_len;
01048
01049 bu_log("Detected cyclic reference of %s\nPath stack is:\n", tp->tr_l.tl_name);
01050 while (--depth >=0) {
01051 bu_log("\tPath depth %d is %s\n", depth, pathp->fp_names[depth]->d_namep);
01052 }
01053 bu_log("WARNING: skipping the cyclic reference lookup\n");
01054
01055
01056 if( tp->tr_l.tl_mat ) {
01057 bu_free( (char *)tp->tr_l.tl_mat, "tl_mat" );
01058 tp->tr_l.tl_mat = NULL;
01059 }
01060 bu_free( tp->tr_l.tl_name, "tl_name" );
01061 tp->tr_l.tl_name = NULL;
01062 tp->tr_op = OP_NOP;
01063 goto out;
01064 }
01065
01066
01067 if( (subtree = db_recurse( &memb_state, pathp, region_start_statepp, client_data )) != TREE_NULL ) {
01068 union tree *tmp;
01069
01070
01071
01072 RT_GET_TREE( tmp, msp->ts_resp );
01073 RT_CK_TREE(subtree);
01074 *tmp = *tp;
01075 *tp = *subtree;
01076 RT_FREE_TREE( subtree, msp->ts_resp );
01077
01078 db_free_tree( tmp, msp->ts_resp );
01079 RT_CK_TREE(tp);
01080 } else {
01081
01082 if( tp->tr_l.tl_mat ) {
01083 bu_free( (char *)tp->tr_l.tl_mat, "tl_mat" );
01084 tp->tr_l.tl_mat = NULL;
01085 }
01086 bu_free( tp->tr_l.tl_name, "tl_name" );
01087 tp->tr_l.tl_name = NULL;
01088 tp->tr_op = OP_NOP;
01089 }
01090 DB_FULL_PATH_POP(pathp);
01091 break;
01092
01093 case OP_UNION:
01094 case OP_INTERSECT:
01095 case OP_SUBTRACT:
01096 case OP_XOR:
01097 db_recurse_subtree( tp->tr_b.tb_left, &memb_state, pathp, region_start_statepp, client_data );
01098 if( tp->tr_op == OP_SUBTRACT )
01099 memb_state.ts_sofar |= TS_SOFAR_MINUS;
01100 else if( tp->tr_op == OP_INTERSECT )
01101 memb_state.ts_sofar |= TS_SOFAR_INTER;
01102 db_recurse_subtree( tp->tr_b.tb_right, &memb_state, pathp, region_start_statepp, client_data );
01103 break;
01104
01105 default:
01106 bu_log("db_recurse_subtree: bad op %d\n", tp->tr_op);
01107 rt_bomb("db_recurse_subtree\n");
01108 }
01109 out:
01110 db_free_db_tree_state( &memb_state );
01111 RT_CK_TREE(tp);
01112 return;
01113 }
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 union tree *
01125 db_recurse(struct db_tree_state *tsp, struct db_full_path *pathp, struct combined_tree_state **region_start_statepp, genptr_t client_data)
01126 {
01127 struct directory *dp;
01128 struct rt_db_internal intern;
01129 union tree *curtree = TREE_NULL;
01130 static long int depth = 0;
01131
01132 RT_CK_DBTS(tsp);
01133 RT_CHECK_DBI( tsp->ts_dbip );
01134 RT_CK_RESOURCE(tsp->ts_resp);
01135 RT_CK_FULL_PATH(pathp);
01136 RT_INIT_DB_INTERNAL(&intern);
01137
01138 if( pathp->fp_len <= 0 ) {
01139 bu_log("db_recurse() null path?\n");
01140 return(TREE_NULL);
01141 }
01142 dp = DB_FULL_PATH_CUR_DIR(pathp);
01143
01144 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01145 char *sofar = db_path_to_string(pathp);
01146 bu_log("db_recurse() pathp='%s', tsp=x%x, *statepp=x%x, tsp->ts_sofar=%d\n",
01147 sofar, tsp,
01148 *region_start_statepp, tsp->ts_sofar );
01149 bu_free(sofar, "path string");
01150 bn_mat_ck("db_recurse() tsp->ts_mat at start", tsp->ts_mat);
01151 }
01152
01153
01154
01155
01156
01157 if( dp->d_addr == RT_DIR_PHONY_ADDR ) return TREE_NULL;
01158
01159 if( dp->d_flags & DIR_COMB ) {
01160 struct rt_comb_internal *comb;
01161 struct db_tree_state nts;
01162 int is_region;
01163
01164 if( rt_db_get_internal( &intern, dp, tsp->ts_dbip, NULL, tsp->ts_resp ) < 0 ) {
01165 bu_log("db_recurse() rt_db_get_internal(%s) FAIL\n", dp->d_namep);
01166 curtree = TREE_NULL;
01167 goto out;
01168 }
01169
01170
01171 db_dup_db_tree_state( &nts, tsp );
01172
01173 comb = (struct rt_comb_internal *)intern.idb_ptr;
01174 RT_CK_COMB(comb);
01175 if( (is_region = db_apply_state_from_comb( &nts, pathp, comb )) < 0 ) {
01176 db_free_db_tree_state( &nts );
01177 curtree = TREE_NULL;
01178 goto out;
01179 }
01180
01181 if( is_region > 0 ) {
01182 struct combined_tree_state *ctsp;
01183
01184
01185 bu_avs_merge( &nts.ts_attrs, &intern.idb_avs );
01186
01187
01188
01189
01190
01191
01192 if( tsp->ts_region_start_func &&
01193 tsp->ts_region_start_func( &nts, pathp, comb, client_data ) < 0 ) {
01194 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01195 char *sofar = db_path_to_string(pathp);
01196 bu_log("db_recurse() ts_region_start_func deletes %s\n",
01197 sofar);
01198 bu_free(sofar, "path string");
01199 }
01200 db_free_db_tree_state( &nts );
01201 curtree = TREE_NULL;
01202 goto out;
01203 }
01204
01205 if( tsp->ts_stop_at_regions ) {
01206 goto region_end;
01207 }
01208
01209
01210 if( *region_start_statepp != (struct combined_tree_state *)0 ) {
01211 bu_log("db_recurse() ERROR at start of a region, *region_start_statepp = x%x\n",
01212 *region_start_statepp );
01213 db_free_db_tree_state( &nts );
01214 curtree = TREE_NULL;
01215 goto out;
01216 }
01217 ctsp = db_new_combined_tree_state( &nts, pathp );
01218 *region_start_statepp = ctsp;
01219 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01220 bu_log("setting *region_start_statepp to x%x\n", ctsp );
01221 db_pr_combined_tree_state(ctsp);
01222 }
01223 }
01224
01225 if( comb->tree ) {
01226
01227 curtree = comb->tree;
01228 comb->tree = TREE_NULL;
01229 if(curtree) RT_CK_TREE(curtree);
01230
01231
01232 rt_db_free_internal( &intern, tsp->ts_resp );
01233 comb = NULL;
01234
01235 db_recurse_subtree( curtree, &nts, pathp, region_start_statepp, client_data );
01236 if(curtree) RT_CK_TREE(curtree);
01237 } else {
01238
01239 RT_GET_TREE( curtree, tsp->ts_resp );
01240 curtree->magic = RT_TREE_MAGIC;
01241 curtree->tr_op = OP_NOP;
01242 if(curtree) RT_CK_TREE(curtree);
01243 }
01244
01245 region_end:
01246 if( is_region > 0 ) {
01247
01248
01249
01250 if( tsp->ts_region_end_func ) {
01251 curtree = tsp->ts_region_end_func(
01252 &nts, pathp, curtree, client_data );
01253 if(curtree) RT_CK_TREE(curtree);
01254 }
01255 }
01256 db_free_db_tree_state( &nts );
01257 if(curtree) RT_CK_TREE(curtree);
01258 } else if( dp->d_flags & DIR_SOLID ) {
01259
01260 if( bn_mat_ck( dp->d_namep, tsp->ts_mat ) < 0 ) {
01261 bu_log("db_recurse(%s): matrix does not preserve axis perpendicularity.\n",
01262 dp->d_namep );
01263 bn_mat_print("bad matrix", tsp->ts_mat);
01264 curtree = TREE_NULL;
01265 goto out;
01266 }
01267
01268 if(RT_G_DEBUG&DEBUG_TREEWALK)
01269 bu_log("db_recurse() rt_db_get_internal(%s) solid\n", dp->d_namep);
01270
01271 RT_INIT_DB_INTERNAL(&intern);
01272 if( rt_db_get_internal( &intern, dp, tsp->ts_dbip, tsp->ts_mat, tsp->ts_resp ) < 0 ) {
01273 bu_log("db_recurse() rt_db_get_internal(%s) FAIL\n", dp->d_namep);
01274 curtree = TREE_NULL;
01275 goto out;
01276 }
01277
01278 if( (tsp->ts_sofar & TS_SOFAR_REGION) == 0 &&
01279 tsp->ts_stop_at_regions == 0 ) {
01280 struct combined_tree_state *ctsp;
01281 char *sofar = db_path_to_string(pathp);
01282
01283
01284
01285
01286
01287 if( *region_start_statepp != (struct combined_tree_state *)0 ) {
01288 bu_log("db_recurse(%s) ERROR at start of a region (bare solid), *region_start_statepp = x%x\n",
01289 sofar, *region_start_statepp );
01290 curtree = TREE_NULL;
01291 goto out;
01292 }
01293 if( RT_G_DEBUG & DEBUG_REGIONS ) {
01294 bu_log("NOTICE: db_recurse(): solid '%s' not contained in a region, creating a region for it of the same name.\n",
01295 sofar );
01296 }
01297
01298 ctsp = db_new_combined_tree_state( tsp, pathp );
01299 ctsp->cts_s.ts_sofar |= TS_SOFAR_REGION;
01300 *region_start_statepp = ctsp;
01301 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01302 bu_log("db_recurse(%s): setting *region_start_statepp to x%x (bare solid)\n",
01303 sofar, ctsp );
01304 db_pr_combined_tree_state(ctsp);
01305 }
01306 bu_free( sofar, "path string" );
01307 }
01308
01309
01310 if( !tsp->ts_leaf_func ) {
01311 curtree = TREE_NULL;
01312 goto out;
01313 }
01314 curtree = tsp->ts_leaf_func( tsp, pathp, &intern, client_data );
01315 if(curtree) RT_CK_TREE(curtree);
01316 } else {
01317 bu_log("%s is not a drawable database object\n",
01318 dp->d_namep );
01319 curtree = TREE_NULL;
01320 return(curtree);
01321 }
01322 out:
01323
01324
01325
01326 if( intern.idb_ptr != NULL ) {
01327 rt_db_free_internal( &intern, tsp->ts_resp );
01328 }
01329 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01330 char *sofar = db_path_to_string(pathp);
01331 bu_log("db_recurse() return curtree=x%x, pathp='%s', *statepp=x%x\n",
01332 curtree, sofar,
01333 *region_start_statepp );
01334 bu_free(sofar, "path string");
01335 }
01336 if(curtree) RT_CK_TREE(curtree);
01337 return(curtree);
01338 }
01339
01340
01341
01342
01343 union tree *
01344 db_dup_subtree( const union tree *tp, struct resource *resp )
01345 {
01346 union tree *new;
01347
01348 RT_CK_TREE(tp);
01349 RT_CK_RESOURCE(resp);
01350
01351 RT_GET_TREE( new, resp );
01352 *new = *tp;
01353
01354 switch( tp->tr_op ) {
01355 case OP_NOP:
01356 case OP_SOLID:
01357
01358 return(new);
01359
01360 case OP_DB_LEAF:
01361 if( tp->tr_l.tl_mat )
01362 new->tr_l.tl_mat = bn_mat_dup( tp->tr_l.tl_mat );
01363 new->tr_l.tl_name = bu_strdup( tp->tr_l.tl_name );
01364 return new;
01365
01366 case OP_REGION:
01367
01368 new->tr_c.tc_ctsp = db_dup_combined_tree_state(
01369 tp->tr_c.tc_ctsp );
01370 return(new);
01371
01372 case OP_NOT:
01373 case OP_GUARD:
01374 case OP_XNOP:
01375 new->tr_b.tb_left = db_dup_subtree( tp->tr_b.tb_left, resp );
01376 return(new);
01377
01378 case OP_UNION:
01379 case OP_INTERSECT:
01380 case OP_SUBTRACT:
01381 case OP_XOR:
01382
01383 new->tr_b.tb_left = db_dup_subtree( tp->tr_b.tb_left, resp );
01384 new->tr_b.tb_right = db_dup_subtree( tp->tr_b.tb_right, resp );
01385 return(new);
01386
01387 default:
01388 bu_log("db_dup_subtree: bad op %d\n", tp->tr_op);
01389 rt_bomb("db_dup_subtree\n");
01390 }
01391 return( TREE_NULL );
01392 }
01393
01394
01395
01396
01397 void
01398 db_ck_tree( const union tree *tp )
01399 {
01400
01401 RT_CK_TREE(tp);
01402
01403 switch( tp->tr_op ) {
01404 case OP_NOP:
01405 break;
01406 case OP_DB_LEAF:
01407 BU_ASSERT_PTR( tp->tr_l.tl_name, !=, NULL );
01408 break;
01409 case OP_SOLID:
01410 if( tp->tr_a.tu_stp )
01411 RT_CK_SOLTAB( tp->tr_a.tu_stp );
01412 break;
01413 case OP_REGION:
01414 RT_CK_CTS( tp->tr_c.tc_ctsp );
01415 break;
01416
01417 case OP_NOT:
01418 case OP_GUARD:
01419 case OP_XNOP:
01420 db_ck_tree( tp->tr_b.tb_left );
01421 break;
01422
01423 case OP_UNION:
01424 case OP_INTERSECT:
01425 case OP_SUBTRACT:
01426 case OP_XOR:
01427
01428 db_ck_tree( tp->tr_b.tb_left );
01429 db_ck_tree( tp->tr_b.tb_right );
01430 break;
01431
01432 default:
01433 bu_log("db_ck_tree: bad op %d\n", tp->tr_op);
01434 rt_bomb("db_ck_tree\n");
01435 }
01436 }
01437
01438
01439
01440
01441
01442
01443
01444 void
01445 db_free_tree( register union tree *tp, struct resource *resp )
01446 {
01447 RT_CK_TREE(tp);
01448 RT_CK_RESOURCE(resp);
01449
01450
01451
01452
01453
01454 tp->magic = -3;
01455
01456 switch( tp->tr_op ) {
01457 case OP_FREE :
01458 tp->tr_op = 0;
01459 return;
01460 case OP_NOP:
01461 break;
01462
01463 case OP_SOLID:
01464 if( tp->tr_a.tu_stp ) {
01465 register struct soltab *stp = tp->tr_a.tu_stp;
01466 RT_CK_SOLTAB(stp);
01467 tp->tr_a.tu_stp = RT_SOLTAB_NULL;
01468 rt_free_soltab(stp);
01469 }
01470 break;
01471 case OP_REGION:
01472
01473 db_free_combined_tree_state( tp->tr_c.tc_ctsp );
01474 tp->tr_c.tc_ctsp = (struct combined_tree_state *)0;
01475 break;
01476
01477 case OP_NMG_TESS:
01478 {
01479 struct nmgregion *r = tp->tr_d.td_r;
01480 if( tp->tr_d.td_name ) {
01481 bu_free( (char *)tp->tr_d.td_name, "region name" );
01482 tp->tr_d.td_name = (const char *)NULL;
01483 }
01484 if( r == (struct nmgregion *)NULL ) {
01485 break;
01486 }
01487
01488
01489
01490
01491 #if 0
01492 if( r->l.magic == (-1L) ) {
01493 bu_log("db_free_tree: OP_NMG_TESS, r = -1, skipping\n");
01494 } else if( r->l.magic != NMG_REGION_MAGIC ) {
01495
01496 bu_log("db_free_tree: OP_NMG_TESS, bad magic x%x (s/b x%x), skipping\n",
01497 r->l.magic, NMG_REGION_MAGIC );
01498 } else {
01499 #endif
01500 if( r->l.magic == NMG_REGION_MAGIC )
01501 {
01502 NMG_CK_REGION(r);
01503 nmg_kr(r);
01504 }
01505 tp->tr_d.td_r = (struct nmgregion *)NULL;
01506 }
01507 break;
01508
01509 case OP_DB_LEAF:
01510 if( tp->tr_l.tl_mat ) {
01511 bu_free( (char *)tp->tr_l.tl_mat, "tl_mat" );
01512 tp->tr_l.tl_mat = NULL;
01513 }
01514 bu_free( tp->tr_l.tl_name, "tl_name" );
01515 tp->tr_l.tl_name = NULL;
01516 break;
01517
01518 case OP_NOT:
01519 case OP_GUARD:
01520 case OP_XNOP:
01521 if( tp->tr_b.tb_left->magic == RT_TREE_MAGIC )
01522 db_free_tree( tp->tr_b.tb_left, resp );
01523 tp->tr_b.tb_left = TREE_NULL;
01524 break;
01525
01526 case OP_UNION:
01527 case OP_INTERSECT:
01528 case OP_SUBTRACT:
01529 case OP_XOR:
01530 {
01531 register union tree *fp;
01532
01533
01534 fp = tp->tr_b.tb_left;
01535 tp->tr_b.tb_left = TREE_NULL;
01536 RT_CK_TREE(fp);
01537 db_free_tree( fp, resp );
01538
01539 fp = tp->tr_b.tb_right;
01540 tp->tr_b.tb_right = TREE_NULL;
01541 RT_CK_TREE(fp);
01542 db_free_tree( fp, resp );
01543 }
01544 break;
01545
01546 default:
01547 bu_log("db_free_tree: bad op %d\n", tp->tr_op);
01548 rt_bomb("db_free_tree\n");
01549 }
01550 tp->tr_op = 0;
01551 RT_FREE_TREE( tp, resp );
01552 }
01553
01554
01555
01556
01557
01558
01559
01560
01561 void
01562 db_left_hvy_node( union tree *tp )
01563 {
01564 union tree *lhs, *rhs;
01565
01566 RT_CK_TREE(tp);
01567
01568 if( tp->tr_op != OP_UNION )
01569 return;
01570
01571 while( tp->tr_b.tb_right->tr_op == OP_UNION )
01572 {
01573 lhs = tp->tr_b.tb_left;
01574 rhs = tp->tr_b.tb_right;
01575
01576 tp->tr_b.tb_left = rhs;
01577 tp->tr_b.tb_right = rhs->tr_b.tb_right;
01578 rhs->tr_b.tb_right = rhs->tr_b.tb_left;
01579 rhs->tr_b.tb_left = lhs;
01580 }
01581 }
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591 void
01592 db_non_union_push( register union tree *tp, struct resource *resp )
01593 {
01594 union tree *A, *B, *C;
01595 union tree *tmp;
01596 int repush_child=0;
01597
01598 RT_CK_TREE(tp);
01599 RT_CK_RESOURCE(resp);
01600
01601 switch( tp->tr_op ) {
01602 case OP_REGION:
01603 case OP_SOLID:
01604 case OP_DB_LEAF:
01605
01606 return;
01607
01608 case OP_NOP:
01609
01610 return;
01611
01612 default:
01613 db_non_union_push( tp->tr_b.tb_left, resp );
01614 db_non_union_push( tp->tr_b.tb_right, resp );
01615 break;
01616 }
01617 if( (tp->tr_op == OP_INTERSECT || tp->tr_op == OP_SUBTRACT) &&
01618 tp->tr_b.tb_left->tr_op == OP_UNION ) {
01619 union tree *lhs = tp->tr_b.tb_left;
01620 union tree *rhs;
01621
01622 A = lhs->tr_b.tb_left;
01623 B = lhs->tr_b.tb_right;
01624
01625 if( A->tr_op == OP_NOP && B->tr_op == OP_NOP ) {
01626
01627 db_free_tree( tp->tr_b.tb_left, resp );
01628 db_free_tree( tp->tr_b.tb_right, resp );
01629 tp->tr_op = OP_NOP;
01630 tp->tr_b.tb_left = NULL;
01631 tp->tr_b.tb_right = NULL;
01632
01633 } else if( A->tr_op == OP_NOP ) {
01634 db_tree_del_lhs( lhs, resp );
01635
01636
01637 db_non_union_push( tp, resp );
01638 } else if( B->tr_op == OP_NOP ) {
01639 db_tree_del_rhs( lhs, resp );
01640
01641
01642 db_non_union_push( tp, resp );
01643 } else {
01644
01645 repush_child = 1;
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656 RT_GET_TREE( rhs, resp );
01657
01658
01659 *rhs = *tp;
01660 tp->tr_b.tb_right = rhs;
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 rhs->tr_b.tb_left = lhs->tr_b.tb_right;
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 tp->tr_op = lhs->tr_op;
01681 lhs->tr_op = rhs->tr_op;
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 lhs->tr_b.tb_right = db_dup_subtree( rhs->tr_b.tb_right, resp );
01692
01693
01694
01695
01696
01697
01698
01699 }
01700
01701 }
01702
01703 else if( tp->tr_op == OP_INTERSECT &&
01704 tp->tr_b.tb_right->tr_op == OP_UNION )
01705 {
01706
01707 union tree *rhs = tp->tr_b.tb_right;
01708
01709 C = tp->tr_b.tb_left;
01710 A = tp->tr_b.tb_right->tr_b.tb_left;
01711 B = tp->tr_b.tb_right->tr_b.tb_right;
01712
01713 if( A->tr_op == OP_NOP && B->tr_op == OP_NOP ) {
01714
01715 tp->tr_op = OP_NOP;
01716 db_free_tree( tp->tr_b.tb_left, resp );
01717 db_free_tree( tp->tr_b.tb_right, resp );
01718 tp->tr_b.tb_left = NULL;
01719 tp->tr_b.tb_right = NULL;
01720 } else if( A->tr_op == OP_NOP ) {
01721 db_tree_del_lhs( rhs, resp );
01722
01723
01724 db_non_union_push( tp, resp );
01725 } else if( B->tr_op == OP_NOP ) {
01726 db_tree_del_rhs( rhs, resp );
01727
01728
01729 db_non_union_push( tp, resp );
01730 } else {
01731 repush_child = 1;
01732
01733 tp->tr_op = OP_UNION;
01734 RT_GET_TREE( tmp, resp );
01735 tmp->tr_regionp = tp->tr_regionp;
01736 tmp->magic = RT_TREE_MAGIC;
01737 tmp->tr_op = OP_INTERSECT;
01738 tmp->tr_b.tb_left = C;
01739 tmp->tr_b.tb_right = A;
01740 tp->tr_b.tb_left = tmp;
01741 tp->tr_b.tb_right->tr_op = OP_INTERSECT;
01742 tp->tr_b.tb_right->tr_b.tb_left = db_dup_subtree( C, resp );
01743 }
01744 }
01745 else if( tp->tr_op == OP_SUBTRACT &&
01746 tp->tr_b.tb_right->tr_op == OP_UNION )
01747 {
01748
01749 union tree *rhs = tp->tr_b.tb_right;
01750
01751
01752 C = tp->tr_b.tb_left;
01753 A = tp->tr_b.tb_right->tr_b.tb_left;
01754 B = tp->tr_b.tb_right->tr_b.tb_right;
01755
01756 if( C->tr_op == OP_NOP ) {
01757
01758 tp->tr_op = OP_NOP;
01759 db_free_tree( tp->tr_b.tb_left, resp );
01760 db_free_tree( tp->tr_b.tb_right, resp );
01761 tp->tr_b.tb_left = NULL;
01762 tp->tr_b.tb_right = NULL;
01763 } else if( A->tr_op == OP_NOP && B->tr_op == OP_NOP ) {
01764 db_tree_del_rhs( tp, resp );
01765
01766
01767 db_non_union_push( tp, resp );
01768 } else if( A->tr_op == OP_NOP ) {
01769 db_tree_del_lhs( rhs, resp );
01770
01771
01772 db_non_union_push( tp, resp );
01773 } else if( B->tr_op == OP_NOP ) {
01774 db_tree_del_rhs( rhs, resp );
01775
01776
01777 db_non_union_push( tp, resp );
01778 } else {
01779 repush_child = 1;
01780
01781 tp->tr_b.tb_left = tp->tr_b.tb_right;
01782 tp->tr_b.tb_left->tr_op = OP_SUBTRACT;
01783 tp->tr_b.tb_right = B;
01784 tmp = tp->tr_b.tb_left;
01785 tmp->tr_b.tb_left = C;
01786 tmp->tr_b.tb_right = A;
01787 }
01788 }
01789
01790
01791
01792
01793 if( repush_child )
01794 {
01795 db_non_union_push( tp->tr_b.tb_left, resp );
01796 db_non_union_push( tp->tr_b.tb_right, resp );
01797 }
01798
01799
01800 db_left_hvy_node( tp );
01801 }
01802
01803
01804
01805
01806
01807
01808
01809 int
01810 db_count_tree_nodes( const union tree *tp, int count )
01811 {
01812 RT_CK_TREE(tp);
01813 switch( tp->tr_op ) {
01814 case OP_NOP:
01815 case OP_SOLID:
01816 case OP_REGION:
01817 case OP_DB_LEAF:
01818
01819 return(count+1);
01820
01821 case OP_UNION:
01822 case OP_INTERSECT:
01823 case OP_SUBTRACT:
01824
01825 count = db_count_tree_nodes( tp->tr_b.tb_left, count );
01826 count = db_count_tree_nodes( tp->tr_b.tb_right, count );
01827 return(count);
01828
01829 case OP_XOR:
01830 case OP_NOT:
01831 case OP_GUARD:
01832 case OP_XNOP:
01833
01834 count = db_count_tree_nodes( tp->tr_b.tb_left, count );
01835 return(count);
01836
01837 default:
01838 bu_log("db_count_tree_nodes: bad op %d\n", tp->tr_op);
01839 rt_bomb("db_count_tree_nodes\n");
01840 }
01841 return( 0 );
01842 }
01843
01844
01845
01846
01847
01848
01849
01850
01851 int
01852 db_is_tree_all_unions( const union tree *tp )
01853 {
01854 RT_CK_TREE(tp);
01855 switch( tp->tr_op ) {
01856 case OP_NOP:
01857 case OP_SOLID:
01858 case OP_REGION:
01859 case OP_DB_LEAF:
01860
01861 return 1;
01862
01863 case OP_UNION:
01864 if( db_is_tree_all_unions( tp->tr_b.tb_left ) == 0 )
01865 return 0;
01866 return db_is_tree_all_unions( tp->tr_b.tb_right );
01867
01868 case OP_INTERSECT:
01869 case OP_SUBTRACT:
01870 return 0;
01871
01872 case OP_XOR:
01873 case OP_NOT:
01874 case OP_GUARD:
01875 case OP_XNOP:
01876 return 0;
01877
01878 default:
01879 bu_log("db_is_tree_all_unions: bad op %d\n", tp->tr_op);
01880 rt_bomb("db_is_tree_all_unions\n");
01881 }
01882 return 0;
01883 }
01884
01885
01886
01887
01888 int
01889 db_count_subtree_regions( const union tree *tp )
01890 {
01891 int cnt;
01892
01893 RT_CK_TREE(tp);
01894 switch( tp->tr_op ) {
01895 case OP_SOLID:
01896 case OP_REGION:
01897 case OP_DB_LEAF:
01898 return(1);
01899
01900 case OP_UNION:
01901
01902 cnt = db_count_subtree_regions( tp->tr_b.tb_left );
01903 cnt += db_count_subtree_regions( tp->tr_b.tb_right );
01904 return(cnt);
01905
01906 case OP_INTERSECT:
01907 case OP_SUBTRACT:
01908 case OP_XOR:
01909 case OP_NOT:
01910 case OP_GUARD:
01911 case OP_XNOP:
01912 case OP_NOP:
01913
01914 return(1);
01915
01916 default:
01917 bu_log("db_count_subtree_regions: bad op %d\n", tp->tr_op);
01918 rt_bomb("db_count_subtree_regions\n");
01919 }
01920 return( 0 );
01921 }
01922
01923
01924
01925
01926 int
01927 db_tally_subtree_regions(
01928 union tree *tp,
01929 union tree **reg_trees,
01930 int cur,
01931 int lim,
01932 struct resource *resp)
01933 {
01934 union tree *new;
01935
01936 RT_CK_TREE(tp);
01937 RT_CK_RESOURCE(resp);
01938 if( cur >= lim ) rt_bomb("db_tally_subtree_regions: array overflow\n");
01939
01940 switch( tp->tr_op ) {
01941 case OP_NOP:
01942 return(cur);
01943
01944 case OP_SOLID:
01945 case OP_REGION:
01946 case OP_DB_LEAF:
01947 RT_GET_TREE( new, resp );
01948 *new = *tp;
01949 tp->tr_op = OP_NOP;
01950 reg_trees[cur++] = new;
01951 return(cur);
01952
01953 case OP_UNION:
01954
01955 cur = db_tally_subtree_regions( tp->tr_b.tb_left, reg_trees, cur, lim, resp );
01956 cur = db_tally_subtree_regions( tp->tr_b.tb_right, reg_trees, cur, lim, resp );
01957 return(cur);
01958
01959 case OP_INTERSECT:
01960 case OP_SUBTRACT:
01961 case OP_XOR:
01962 case OP_NOT:
01963 case OP_GUARD:
01964 case OP_XNOP:
01965
01966 RT_GET_TREE( new, resp );
01967 *new = *tp;
01968 tp->tr_op = OP_NOP;
01969 reg_trees[cur++] = new;
01970 return(cur);
01971
01972 default:
01973 bu_log("db_tally_subtree_regions: bad op %d\n", tp->tr_op);
01974 rt_bomb("db_tally_subtree_regions\n");
01975 }
01976 return( cur );
01977 }
01978
01979
01980
01981 HIDDEN union tree *db_gettree_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
01982 {
01983
01984 RT_CK_DBTS(tsp);
01985 RT_CK_DBI(tsp->ts_dbip);
01986 RT_CK_FULL_PATH(pathp);
01987 RT_CK_RESOURCE(tsp->ts_resp);
01988
01989 RT_GET_TREE( curtree, tsp->ts_resp );
01990 curtree->magic = RT_TREE_MAGIC;
01991 curtree->tr_op = OP_REGION;
01992 curtree->tr_c.tc_ctsp = db_new_combined_tree_state( tsp, pathp );
01993
01994 return(curtree);
01995 }
01996
01997 HIDDEN union tree *db_gettree_leaf(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data)
01998 {
01999 register union tree *curtree;
02000
02001 RT_CK_DBTS(tsp);
02002 RT_CK_DBI(tsp->ts_dbip);
02003 RT_CK_FULL_PATH(pathp);
02004 RT_CK_DB_INTERNAL(ip);
02005 RT_CK_RESOURCE(tsp->ts_resp);
02006
02007 RT_GET_TREE( curtree, tsp->ts_resp );
02008 curtree->magic = RT_TREE_MAGIC;
02009 curtree->tr_op = OP_REGION;
02010 curtree->tr_c.tc_ctsp = db_new_combined_tree_state( tsp, pathp );
02011
02012 return(curtree);
02013 }
02014
02015 struct db_walk_parallel_state {
02016 long magic;
02017 union tree **reg_trees;
02018 int reg_count;
02019 int reg_current;
02020 union tree * (*reg_end_func)();
02021 union tree * (*reg_leaf_func)();
02022 struct rt_i *rtip;
02023 genptr_t client_data;
02024 };
02025 #define DB_WALK_PARALLEL_STATE_MAGIC 0x64777073
02026 #define DB_CK_WPS(_p) BU_CKMAG(_p, DB_WALK_PARALLEL_STATE_MAGIC, "db_walk_parallel_state")
02027
02028
02029
02030
02031 HIDDEN void
02032 db_walk_subtree(
02033 register union tree *tp,
02034 struct combined_tree_state **region_start_statepp,
02035 union tree *(*leaf_func) BU_ARGS((struct db_tree_state *, struct db_full_path *, struct rt_db_internal *, void *)),
02036 genptr_t client_data,
02037 struct resource *resp )
02038 {
02039 struct combined_tree_state *ctsp;
02040 union tree *curtree;
02041
02042 RT_CK_TREE(tp);
02043 RT_CK_RESOURCE(resp);
02044
02045 switch( tp->tr_op ) {
02046 case OP_NOP:
02047 return;
02048
02049
02050 case OP_REGION:
02051
02052 ctsp = tp->tr_c.tc_ctsp;
02053 RT_CK_CTS(ctsp);
02054 if( ctsp->cts_p.fp_len <= 0 ) {
02055 bu_log("db_walk_subtree() REGION with null path?\n");
02056 db_free_combined_tree_state( ctsp );
02057
02058 tp->tr_op = OP_NOP;
02059 tp->tr_a.tu_stp = 0;
02060 return;
02061 }
02062 RT_CK_DBI(ctsp->cts_s.ts_dbip);
02063 ctsp->cts_s.ts_stop_at_regions = 0;
02064
02065 ctsp->cts_s.ts_region_start_func = 0;
02066
02067 ctsp->cts_s.ts_region_end_func = 0;
02068
02069 ctsp->cts_s.ts_leaf_func = leaf_func;
02070 ctsp->cts_s.ts_resp = resp;
02071
02072
02073 if( *region_start_statepp )
02074 ctsp->cts_s.ts_sofar |= TS_SOFAR_REGION;
02075 else
02076 ctsp->cts_s.ts_sofar &= ~TS_SOFAR_REGION;
02077
02078 curtree = db_recurse( &ctsp->cts_s, &ctsp->cts_p, region_start_statepp, client_data );
02079 if( curtree == TREE_NULL ) {
02080 char *str;
02081 str = db_path_to_string( &(ctsp->cts_p) );
02082 bu_log("db_walk_subtree() FAIL on '%s'\n", str);
02083 bu_free( str, "path string" );
02084
02085 db_free_combined_tree_state( ctsp );
02086
02087 tp->tr_op = OP_NOP;
02088 tp->tr_a.tu_stp = 0;
02089 return;
02090 }
02091
02092 *tp = *curtree;
02093 db_free_combined_tree_state( ctsp );
02094 RT_FREE_TREE( curtree, resp );
02095 return;
02096
02097 case OP_NOT:
02098 case OP_GUARD:
02099 case OP_XNOP:
02100 db_walk_subtree( tp->tr_b.tb_left, region_start_statepp,
02101 leaf_func, client_data, resp );
02102 return;
02103
02104 case OP_UNION:
02105 case OP_INTERSECT:
02106 case OP_SUBTRACT:
02107 case OP_XOR:
02108
02109 db_walk_subtree( tp->tr_b.tb_left, region_start_statepp,
02110 leaf_func, client_data, resp );
02111 db_walk_subtree( tp->tr_b.tb_right, region_start_statepp,
02112 leaf_func, client_data, resp );
02113 return;
02114
02115 case OP_DB_LEAF:
02116 rt_pr_tree( tp, 1 );
02117 bu_bomb("db_walk_subtree() unexpected DB_LEAF\n");
02118
02119 default:
02120 bu_log("db_walk_subtree: bad op %d\n", tp->tr_op);
02121 bu_bomb("db_walk_subtree() bad op\n");
02122 }
02123 }
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135 HIDDEN void
02136 db_walk_dispatcher(int cpu, genptr_t arg)
02137 {
02138 struct combined_tree_state *region_start_statep;
02139 int mine;
02140 union tree *curtree;
02141 struct db_walk_parallel_state *wps = (struct db_walk_parallel_state *)arg;
02142 struct resource *resp;
02143
02144 DB_CK_WPS(wps);
02145
02146 if( wps->rtip == NULL && cpu == 0 ) {
02147 resp = &rt_uniresource;
02148 } else {
02149 RT_CK_RTI(wps->rtip);
02150
02151 resp = (struct resource *)BU_PTBL_GET( &wps->rtip->rti_resources, cpu );
02152 if( resp == NULL && cpu == 0 ) resp = &rt_uniresource;
02153 }
02154 RT_CK_RESOURCE(resp);
02155
02156 while(1) {
02157 bu_semaphore_acquire( RT_SEM_WORKER );
02158 mine = wps->reg_current++;
02159 bu_semaphore_release( RT_SEM_WORKER );
02160
02161 if( mine >= wps->reg_count )
02162 break;
02163
02164 if( RT_G_DEBUG&DEBUG_TREEWALK )
02165 bu_log("\n\n***** db_walk_dispatcher() on item %d\n\n", mine );
02166
02167 if( (curtree = wps->reg_trees[mine]) == TREE_NULL )
02168 continue;
02169 RT_CK_TREE(curtree);
02170
02171
02172 region_start_statep = (struct combined_tree_state *)0;
02173 db_walk_subtree( curtree, ®ion_start_statep,
02174 wps->reg_leaf_func, wps->client_data, resp );
02175
02176
02177
02178
02179
02180 RT_CK_TREE(curtree);
02181 if( !region_start_statep ) {
02182 bu_log("ERROR: db_walk_dispatcher() region %d started with no state\n", mine);
02183 if( RT_G_DEBUG&DEBUG_TREEWALK )
02184 rt_pr_tree( curtree, 0 );
02185 continue;
02186 }
02187 RT_CK_CTS( region_start_statep );
02188
02189
02190 if( RT_G_DEBUG&DEBUG_TREEWALK )
02191 db_pr_combined_tree_state(region_start_statep);
02192
02193
02194
02195
02196
02197 if( wps->reg_end_func ) {
02198 wps->reg_trees[mine] = (*(wps->reg_end_func))(
02199 &(region_start_statep->cts_s),
02200 &(region_start_statep->cts_p),
02201 curtree, wps->client_data );
02202 }
02203
02204 db_free_combined_tree_state( region_start_statep );
02205 }
02206 }
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261 int
02262 db_walk_tree(struct db_i *dbip,
02263 int argc,
02264 const char **argv,
02265 int ncpu,
02266 const struct db_tree_state *init_state,
02267 int (*reg_start_func) (struct db_tree_state *, struct db_full_path *, const struct rt_comb_internal *, genptr_t),
02268 union tree *(*reg_end_func) (struct db_tree_state *, struct db_full_path *, union tree *, genptr_t),
02269 union tree *(*leaf_func) (struct db_tree_state *, struct db_full_path *, struct rt_db_internal *, genptr_t),
02270 genptr_t client_data)
02271 {
02272 union tree *whole_tree = TREE_NULL;
02273 int new_reg_count;
02274 int i;
02275 int something_not_found = 0;
02276 union tree **reg_trees;
02277 struct db_walk_parallel_state wps;
02278 struct resource *resp;
02279
02280 RT_CK_DBTS(init_state);
02281 RT_CHECK_DBI(dbip);
02282
02283 if( init_state->ts_rtip == NULL && ncpu == 1 ) {
02284 resp = &rt_uniresource;
02285 } else {
02286 RT_CK_RTI(init_state->ts_rtip);
02287 resp = (struct resource *)BU_PTBL_GET(&init_state->ts_rtip->rti_resources, 0);
02288 if( resp == NULL && ncpu == 1 ) {
02289 resp = &rt_uniresource;
02290 }
02291 }
02292 RT_CK_RESOURCE(resp);
02293
02294
02295 for( i=0; i < argc; i++ ) {
02296 register union tree *curtree;
02297 struct db_tree_state ts;
02298 struct db_full_path path;
02299 struct combined_tree_state *region_start_statep;
02300
02301 ts = *init_state;
02302 ts.ts_dbip = dbip;
02303 ts.ts_resp = resp;
02304 db_full_path_init( &path );
02305
02306
02307 if( db_follow_path_for_state( &ts, &path, argv[i],
02308 LOOKUP_NOISY ) < 0 )
02309 {
02310 bu_log ("db_walk_tree: warning - %s not found.\n",
02311 argv[i]);
02312 ++ something_not_found;
02313 continue;
02314 }
02315 if( path.fp_len <= 0 ) {
02316 continue;
02317 }
02318
02319
02320
02321
02322
02323
02324
02325 ts.ts_stop_at_regions = 1;
02326 ts.ts_region_start_func = reg_start_func;
02327 ts.ts_region_end_func = db_gettree_region_end;
02328 ts.ts_leaf_func = db_gettree_leaf;
02329
02330 region_start_statep = (struct combined_tree_state *)0;
02331 curtree = db_recurse( &ts, &path, ®ion_start_statep, client_data );
02332 if( region_start_statep )
02333 db_free_combined_tree_state( region_start_statep );
02334 db_free_full_path( &path );
02335 if( curtree == TREE_NULL )
02336 continue;
02337
02338 RT_CK_TREE(curtree);
02339 if( RT_G_DEBUG&DEBUG_TREEWALK ) {
02340 bu_log("tree after db_recurse():\n");
02341 rt_pr_tree( curtree, 0 );
02342 }
02343
02344 if( whole_tree == TREE_NULL ) {
02345 whole_tree = curtree;
02346 } else {
02347 union tree *new;
02348
02349 RT_GET_TREE( new, ts.ts_resp );
02350 new->magic = RT_TREE_MAGIC;
02351 new->tr_op = OP_UNION;
02352 new->tr_b.tb_left = whole_tree;
02353 new->tr_b.tb_right = curtree;
02354 whole_tree = new;
02355 }
02356 }
02357
02358 if( whole_tree == TREE_NULL )
02359 return(-1);
02360
02361
02362
02363
02364
02365 db_non_union_push( whole_tree, resp );
02366 if( RT_G_DEBUG&DEBUG_TREEWALK ) {
02367 char *str;
02368
02369 bu_log("tree after db_non_union_push():\n");
02370 rt_pr_tree( whole_tree, 0 );
02371 bu_log( "Same tree in another form:\n" );
02372 str = (char *)rt_pr_tree_str( whole_tree );
02373 bu_log( "%s\n", str );
02374 bu_free( str, "rturn from rt_pr_tree_str" );
02375 }
02376
02377
02378
02379
02380
02381 new_reg_count = db_count_subtree_regions( whole_tree );
02382 reg_trees = (union tree **)bu_calloc( sizeof(union tree *),
02383 (new_reg_count+1), "*reg_trees[]" );
02384 new_reg_count = db_tally_subtree_regions( whole_tree, reg_trees, 0,
02385 new_reg_count, resp );
02386
02387
02388
02389
02390
02391
02392 db_free_tree( whole_tree, resp );
02393
02394
02395 if( RT_G_DEBUG&DEBUG_TREEWALK ) {
02396 bu_log("%d waiting regions:\n", new_reg_count);
02397 for( i=0; i < new_reg_count; i++ ) {
02398 union tree *treep;
02399 struct combined_tree_state *ctsp;
02400 char *str;
02401
02402 if( (treep = reg_trees[i]) == TREE_NULL ) {
02403 bu_log("%d: NULL\n", i);
02404 continue;
02405 }
02406 RT_CK_TREE(treep);
02407 if( treep->tr_op != OP_REGION ) {
02408 bu_log("%d: op=%d\n", i, treep->tr_op);
02409 rt_pr_tree( treep, 2 );
02410 continue;
02411 }
02412 ctsp = treep->tr_c.tc_ctsp;
02413 RT_CK_CTS(ctsp);
02414 str = db_path_to_string( &(ctsp->cts_p) );
02415 bu_log("%d '%s'\n", i, str);
02416 bu_free( str, "path string" );
02417 }
02418 bu_log("end of waiting regions\n");
02419 }
02420
02421
02422
02423
02424 if( bu_is_parallel() && ncpu != 1 ) {
02425 bu_log("db_walk_tree() recursively invoked while inside parallel section with additional parallelism of ncpu=%d requested. Running only in one thread.\n",
02426 ncpu );
02427 ncpu = 1;
02428 }
02429
02430
02431 wps.magic = DB_WALK_PARALLEL_STATE_MAGIC;
02432 wps.reg_trees = reg_trees;
02433 wps.reg_count = new_reg_count;
02434 wps.reg_current = 0;
02435 wps.reg_end_func = reg_end_func;
02436 wps.reg_leaf_func = leaf_func;
02437 wps.client_data = client_data;
02438 wps.rtip = init_state->ts_rtip;
02439
02440 if( ncpu <= 1 ) {
02441 db_walk_dispatcher( 0, (genptr_t)&wps );
02442 } else {
02443 bu_parallel( db_walk_dispatcher, ncpu, (genptr_t)&wps );
02444 }
02445
02446
02447 for( i=0; i < new_reg_count; i++ ) {
02448 if( reg_trees[i] != TREE_NULL ) {
02449 db_free_tree( reg_trees[i], resp );
02450 }
02451 }
02452 bu_free( (char *)reg_trees, "*reg_trees[]" );
02453
02454 if (something_not_found)
02455 {
02456 bu_log ("db_walk_tree: %d %s not found.\n",
02457 something_not_found,
02458 (something_not_found > 1) ? "items" : "item" ) ;
02459 return -2;
02460 }
02461 else
02462 {
02463 return 0;
02464 }
02465 }
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 int
02477 db_path_to_mat(
02478 struct db_i *dbip,
02479 struct db_full_path *pathp,
02480 mat_t mat,
02481 int depth,
02482 struct resource *resp)
02483 {
02484 struct db_tree_state ts;
02485 struct db_full_path null_path;
02486 int ret;
02487
02488 RT_CHECK_DBI(dbip);
02489 RT_CK_FULL_PATH(pathp);
02490 if( !mat ) rt_bomb("db_path_to_mat() NULL matrix pointer\n");
02491
02492 db_full_path_init( &null_path );
02493 db_init_db_tree_state( &ts, dbip, resp );
02494
02495 ret = db_follow_path( &ts, &null_path, pathp, LOOKUP_NOISY, depth );
02496 db_free_full_path( &null_path );
02497 MAT_COPY( mat, ts.ts_mat );
02498 db_free_db_tree_state( &ts );
02499
02500 if( ret < 0 ) {
02501 return 0;
02502 }
02503 return 1;
02504 }
02505
02506
02507
02508
02509
02510
02511
02512
02513 void
02514 db_apply_anims(struct db_full_path *pathp, struct directory *dp, mat_t stack, mat_t arc, struct mater_info *materp)
02515 {
02516 register struct animate *anp;
02517 register int i,j;
02518
02519
02520
02521 if ((dp->d_animate != ANIM_NULL) && (RT_G_DEBUG & DEBUG_ANIM)) {
02522 char *sofar = db_path_to_string(pathp);
02523 bu_log("Animate %s with...\n", sofar);
02524 bu_free(sofar, "path string");
02525 }
02526
02527
02528
02529
02530
02531
02532
02533
02534 for( anp = dp->d_animate; anp != ANIM_NULL; anp = anp->an_forw ) {
02535 register int anim_flag;
02536
02537 j = pathp->fp_len-1;
02538
02539 RT_CK_ANIMATE(anp);
02540 i = anp->an_path.fp_len-1;
02541 anim_flag = 1;
02542
02543 if (RT_G_DEBUG & DEBUG_ANIM) {
02544 char *str;
02545
02546 str = db_path_to_string( &(anp->an_path) );
02547 bu_log( "\t%s\t", str );
02548 bu_free( str, "path string" );
02549 bu_log("an_path.fp_len-1:%d pathp->fp_len-1:%d\n",
02550 i, j);
02551 }
02552
02553 for( ; i>=0 && j>=0; i--, j-- ) {
02554 if( anp->an_path.fp_names[i] != pathp->fp_names[j] ) {
02555 if (RT_G_DEBUG & DEBUG_ANIM) {
02556 bu_log("%s != %s\n",
02557 anp->an_path.fp_names[i]->d_namep,
02558 pathp->fp_names[j]->d_namep);
02559 }
02560 anim_flag = 0;
02561 break;
02562 }
02563 }
02564
02565
02566 if (anim_flag)
02567 db_do_anim( anp, stack, arc, materp);
02568 }
02569 return;
02570 }
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582 int
02583 db_region_mat(
02584 mat_t m,
02585 struct db_i *dbip,
02586 const char *name,
02587 struct resource *resp)
02588 {
02589 struct db_full_path full_path;
02590 mat_t region_to_model;
02591
02592
02593 if (db_string_to_path( &full_path, dbip, name) ) {
02594
02595 bu_log("db_region_mat: db_string_to_path(%s) error\n", name);
02596 return -1;
02597 }
02598 if(! db_path_to_mat(dbip, &full_path, region_to_model, 0, resp)) {
02599
02600 bu_log("db_region_mat: db_path_to_mat(%s) error", name);
02601 return -2;
02602 }
02603
02604
02605
02606
02607 bn_mat_inv(m, region_to_model);
02608 db_free_full_path( &full_path );
02609 return 0;
02610 }
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630 int
02631 db_shader_mat(
02632 mat_t model_to_shader,
02633 const struct rt_i *rtip,
02634 const struct region *rp,
02635 point_t p_min,
02636 point_t p_max,
02637 struct resource *resp)
02638 {
02639 mat_t model_to_region;
02640 mat_t m_xlate;
02641 mat_t m_scale;
02642 mat_t m_tmp;
02643 vect_t v_tmp;
02644 struct rt_i *my_rtip;
02645 const char *reg_name;
02646
02647 RT_CK_RTI(rtip);
02648 RT_CK_RESOURCE(resp);
02649
02650 reg_name = rt_basename(rp->reg_name);
02651 #ifdef DEBUG_SHADER_MAT
02652 bu_log("db_shader_mat(%s)\n", rp->reg_name);
02653 #endif
02654
02655 if( db_region_mat(model_to_region, rtip->rti_dbip, rp->reg_name, resp) < 0 )
02656 return -1;
02657
02658 #ifdef DEBUG_SHADER_MAT
02659 bn_mat_print("model_to_region", model_to_region);
02660 #endif
02661 if (VEQUAL(p_min, p_max)) {
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671 my_rtip = rt_new_rti(rtip->rti_dbip);
02672 my_rtip->useair = rtip->useair;
02673
02674
02675 bu_semaphore_acquire( RT_SEM_MODEL );
02676 if (rt_gettree(my_rtip, reg_name)) bu_bomb(rp->reg_name);
02677 bu_semaphore_release( RT_SEM_MODEL );
02678 rt_rpp_region(my_rtip, reg_name, p_min, p_max);
02679 rt_clean(my_rtip);
02680 }
02681 #ifdef DEBUG_SHADER_MAT
02682 bu_log("db_shader_mat(%s) min(%g %g %g) max(%g %g %g)\n", reg_name,
02683 V3ARGS(p_min), V3ARGS(p_max));
02684 #endif
02685
02686
02687
02688 MAT_IDN(m_xlate);
02689 VSCALE(v_tmp, p_min, -1);
02690 MAT_DELTAS_VEC(m_xlate, v_tmp);
02691 bn_mat_mul(m_tmp, m_xlate, model_to_region);
02692
02693
02694
02695
02696
02697 VSUB2(v_tmp, p_max, p_min);
02698 VINVDIR(v_tmp, v_tmp);
02699 MAT_IDN(m_scale);
02700 MAT_SCALE_VEC(m_scale, v_tmp);
02701 bn_mat_mul(model_to_shader, m_scale, m_tmp);
02702 return 0;
02703 }
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714