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 #ifndef lint
00041 static const char RCSid[] = "";
00042 #endif
00043
00044 #include "common.h"
00045
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <signal.h>
00049 #ifdef HAVE_STRING_H
00050 # include <string.h>
00051 #else
00052 # include <strings.h>
00053 #endif
00054 #include <errno.h>
00055 #include <time.h>
00056
00057 #include "machine.h"
00058 #include "bu.h"
00059 #include "vmath.h"
00060 #include "nmg.h"
00061 #include "rtgeom.h"
00062 #include "raytrace.h"
00063 #include "solid.h"
00064 #include <ctype.h>
00065
00066
00067 struct dg_client_data {
00068 struct dg_obj *dgop;
00069 Tcl_Interp *interp;
00070 int wireframe_color_override;
00071 int wireframe_color[3];
00072 struct application *ap;
00073 struct bu_ptbl leaf_list;
00074 struct rt_i *rtip;
00075 time_t start_time;
00076 time_t etime;
00077 long nvectors;
00078 int do_polysolids;
00079 int num_halfs;
00080 };
00081
00082 union E_tree *build_etree(union tree *tp, struct dg_client_data *dgcdp);
00083
00084
00085 #define ON_SURF (struct soltab *)0x1
00086 #define IN_SOL (struct soltab *)0x2
00087 #define ON_INT (struct soltab *)0x3
00088
00089 #define NOT_SEG_OVERLAP( _a, _b ) ((_a->seg_out.hit_dist <= _b->seg_in.hit_dist) || (_b->seg_out.hit_dist <= _a->seg_in.hit_dist))
00090
00091
00092 #define MY_FREE_SEG_LIST( _segheadp, _res ) { \
00093 register struct seg *_a; \
00094 while( BU_LIST_WHILE( _a, seg, (_segheadp) ) ) { \
00095 BU_LIST_DEQUEUE( &(_a->l) ); \
00096 RT_FREE_SEG( _a, _res ); \
00097 } }
00098
00099
00100 struct half_specific {
00101 plane_t half_eqn;
00102 vect_t half_Xbase;
00103 vect_t half_Ybase;
00104 };
00105 #define HALF_NULL ((struct half_specific *)0)
00106
00107
00108
00109
00110 union E_tree
00111 {
00112 long magic;
00113
00114 struct E_node
00115 {
00116 long magic;
00117 int op;
00118 union E_tree *left;
00119 union E_tree *right;
00120 } n;
00121
00122 struct E_leaf
00123 {
00124 long magic;
00125 int op;
00126 struct model *m;
00127 struct bu_list seghead;
00128 struct bu_ptbl edge_list;
00129 struct soltab *stp;
00130 unsigned char do_not_free_model;
00131
00132 } l;
00133 };
00134
00135 #define E_TREE_MAGIC 0x45545245
00136 #define CK_ETREE(_p) BU_CKMAG( _p, E_TREE_MAGIC, "struct E_tree" )
00137
00138 void
00139 Edrawtree(int dp)
00140 {
00141 return;
00142 }
00143
00144 HIDDEN union E_tree *
00145 #if 1
00146 add_solid(const struct directory *dp,
00147 matp_t mat,
00148 struct dg_client_data *dgcdp)
00149 #else
00150 add_solid(dp, mat, dgcdp)
00151 struct directory *dp;
00152 matp_t mat;
00153 struct dg_client_data *dgcdp;
00154 #endif
00155 {
00156 union E_tree *eptr;
00157 struct nmgregion *r;
00158 struct rt_db_internal intern;
00159 int id;
00160 int solid_is_plate_mode_bot=0;
00161
00162 BU_GETUNION( eptr, E_tree );
00163 eptr->magic = E_TREE_MAGIC;
00164
00165 id = rt_db_get_internal( &intern, dp, dgcdp->dgop->dgo_wdbp->dbip, mat, &rt_uniresource );
00166 if( id < 0 )
00167 {
00168 Tcl_AppendResult(dgcdp->interp, "Failed to get internal form of ",
00169 dp->d_namep, "\n", (char *)NULL );
00170 eptr->l.m = (struct model *)NULL;
00171 return( eptr );
00172 }
00173 if( id == ID_COMBINATION )
00174 {
00175
00176
00177 struct rt_comb_internal *comb;
00178
00179 bu_free( (char *)eptr, "eptr" );
00180
00181 comb = (struct rt_comb_internal *)intern.idb_ptr;
00182 RT_CK_COMB( comb );
00183
00184 eptr = build_etree( comb->tree, dgcdp );
00185 rt_db_free_internal( &intern, &rt_uniresource );
00186 return( eptr );
00187 }
00188 #if 0
00189 if( id == ID_BOT )
00190 {
00191 struct rt_bot_internal *bot = (struct rt_bot_internal *)intern.idb_ptr;
00192
00193
00194
00195
00196
00197 RT_BOT_CK_MAGIC( bot );
00198
00199 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
00200 {
00201 solid_is_plate_mode_bot = 1;
00202 bot->mode = RT_BOT_SOLID;
00203 }
00204 }
00205 #endif
00206 if( id == ID_HALF )
00207 {
00208 eptr->l.m = NULL;
00209 dgcdp->num_halfs++;
00210 }
00211 else if( id == ID_NMG )
00212 {
00213
00214 eptr->l.m = (struct model *)intern.idb_ptr;
00215 eptr->l.do_not_free_model = 1;
00216 }
00217 else
00218 {
00219
00220 eptr->l.m = nmg_mm();
00221 if (rt_functab[id].ft_tessellate( &r, eptr->l.m, &intern,
00222 &dgcdp->dgop->dgo_wdbp->wdb_ttol, &dgcdp->dgop->dgo_wdbp->wdb_tol) < 0)
00223 {
00224 nmg_km( eptr->l.m );
00225 eptr->l.m = NULL;
00226 }
00227 }
00228
00229
00230 BU_GETSTRUCT( eptr->l.stp, soltab );
00231 eptr->l.stp->l.magic = RT_SOLTAB_MAGIC;
00232 eptr->l.stp->l2.magic = RT_SOLTAB2_MAGIC;
00233 eptr->l.stp->st_dp = dp;
00234 eptr->l.stp->st_matp = mat;
00235
00236 {
00237 struct rt_bot_internal *bot;
00238 struct rt_db_internal intern2;
00239
00240 if( dgcdp->do_polysolids )
00241 {
00242 struct shell *s=(struct shell *)NULL;
00243 struct nmgregion *r=(struct nmgregion *)NULL;
00244
00245
00246 if( eptr->l.m ) {
00247 r = BU_LIST_FIRST( nmgregion, &eptr->l.m->r_hd );
00248 s = BU_LIST_FIRST( shell, &r->s_hd );
00249 }
00250
00251 if( solid_is_plate_mode_bot ||
00252 !eptr->l.m ||
00253 (bot=nmg_bot( s, &dgcdp->dgop->dgo_wdbp->wdb_tol ) ) == (struct rt_bot_internal *)NULL )
00254 {
00255 eptr->l.stp->st_id = id;
00256 eptr->l.stp->st_meth = &rt_functab[id];
00257 if( rt_functab[id].ft_prep( eptr->l.stp, &intern, dgcdp->rtip ) < 0 )
00258 Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00259 "'\n", (char *)NULL );
00260 }
00261 else
00262 {
00263 RT_INIT_DB_INTERNAL( &intern2 );
00264 intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00265 intern2.idb_type = ID_BOT;
00266 intern2.idb_meth = &rt_functab[ID_BOT];
00267 intern2.idb_ptr = (genptr_t)bot;
00268 eptr->l.stp->st_id = ID_BOT;
00269 eptr->l.stp->st_meth = &rt_functab[ID_BOT];
00270 if (rt_functab[ID_BOT].ft_prep( eptr->l.stp, &intern2, dgcdp->rtip ) < 0 )
00271 {
00272 Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00273 "'\n", (char *)NULL );
00274 }
00275
00276 rt_db_free_internal( &intern2, &rt_uniresource );
00277 }
00278 }
00279 else
00280 {
00281
00282
00283 eptr->l.stp->st_id = id;
00284 eptr->l.stp->st_meth = &rt_functab[id];
00285 if( rt_functab[id].ft_prep( eptr->l.stp, &intern, dgcdp->rtip ) < 0 )
00286 Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", dp->d_namep,
00287 "'\n", (char *)NULL );
00288 }
00289 }
00290
00291 if( id != ID_NMG )
00292 rt_db_free_internal( &intern, &rt_uniresource );
00293
00294
00295 bu_ptbl_ins( &dgcdp->leaf_list, (long *)eptr );
00296
00297 return( eptr );
00298 }
00299
00300
00301 union E_tree *
00302 build_etree(union tree *tp,
00303 struct dg_client_data *dgcdp)
00304 {
00305 union E_tree *eptr = NULL;
00306 struct soltab *stp;
00307 struct directory *dp;
00308
00309 RT_CK_TREE( tp );
00310
00311 switch( tp->tr_op )
00312 {
00313 case OP_UNION:
00314 case OP_SUBTRACT:
00315 case OP_INTERSECT:
00316 BU_GETUNION( eptr, E_tree );
00317 eptr->magic = E_TREE_MAGIC;
00318 eptr->n.op = tp->tr_op;
00319 eptr->n.left = build_etree( tp->tr_b.tb_left, dgcdp );
00320 eptr->n.right = build_etree( tp->tr_b.tb_right, dgcdp );
00321 break;
00322 case OP_SOLID:
00323 stp = tp->tr_a.tu_stp;
00324 eptr = add_solid( stp->st_dp, stp->st_matp, dgcdp );
00325 eptr->l.op = tp->tr_op;
00326 BU_LIST_INIT( &eptr->l.seghead );
00327 break;
00328 case OP_DB_LEAF:
00329 if( (dp=db_lookup( dgcdp->dgop->dgo_wdbp->dbip, tp->tr_l.tl_name, LOOKUP_NOISY )) == DIR_NULL )
00330 {
00331 eptr->l.m = (struct model *)NULL;
00332 break;
00333 }
00334 eptr = add_solid( dp, tp->tr_l.tl_mat, dgcdp );
00335 eptr->l.op = tp->tr_op;
00336 BU_LIST_INIT( &eptr->l.seghead );
00337 break;
00338 case OP_NOP:
00339
00340 BU_GETUNION( eptr, E_tree );
00341 eptr->magic = E_TREE_MAGIC;
00342 eptr->l.m = (struct model *)NULL;
00343 break;
00344 default:
00345 bu_bomb("build_etree() Unknown tr_op\n");
00346 }
00347 return( eptr );
00348 }
00349
00350
00351 void
00352 show_seg(struct bu_list *seg, int str)
00353 {
00354 struct seg *ptr;
00355
00356 if( !seg )
00357 bu_log( "%s - NULL seg list\n", str );
00358 else
00359 {
00360 if( BU_LIST_IS_EMPTY( seg ) )
00361 bu_log( "%s - empty\n", str );
00362 else
00363 {
00364 bu_log( "%s:\n", str );
00365 for( BU_LIST_FOR( ptr, seg, seg ) )
00366 {
00367 if( ptr->seg_stp == ON_SURF )
00368 bu_log( "\t %g to %g (ON_SURF)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00369 else if( ptr->seg_stp == ON_INT )
00370 bu_log( "\t %g to %g (ON_INT)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00371 else if( ptr->seg_stp == IN_SOL )
00372 bu_log( "\t %g to %g (IN)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00373 else
00374 bu_log( "\t %g to %g (?)\n", ptr->seg_in.hit_dist, ptr->seg_out.hit_dist );
00375 bu_log( "\t\t( %g %g %g) <-> (%g %g %g)\n", V3ARGS( ptr->seg_in.hit_point),
00376 V3ARGS( ptr->seg_out.hit_point ) );
00377 }
00378 }
00379 }
00380 }
00381
00382
00383 HIDDEN void
00384 eliminate_overlaps(struct bu_list *seghead,
00385 struct dg_client_data *dgcdp)
00386 {
00387 struct seg *a, *b, *nextb;
00388
00389 a = BU_LIST_FIRST( seg, seghead );
00390 while( BU_LIST_NOT_HEAD( &a->l, seghead ) )
00391 {
00392 b = BU_LIST_PNEXT( seg, &a->l );
00393 if( BU_LIST_IS_HEAD( &b->l, seghead ) )
00394 break;
00395
00396 while( BU_LIST_NOT_HEAD( &b->l, seghead ) )
00397 {
00398 nextb = BU_LIST_PNEXT( seg, &b->l );
00399 if( NOT_SEG_OVERLAP( a, b ) )
00400 break;
00401
00402 if( b->seg_in.hit_dist < a->seg_out.hit_dist )
00403 {
00404 if( b->seg_out.hit_dist > a->seg_out.hit_dist )
00405 a->seg_out.hit_dist = b->seg_out.hit_dist;
00406
00407 BU_LIST_DEQUEUE( &b->l );
00408 RT_FREE_SEG( b, dgcdp->ap->a_resource );
00409 b = nextb;
00410 continue;
00411 }
00412
00413 b = nextb;
00414 }
00415
00416 a = BU_LIST_PNEXT(seg, &a->l );
00417 }
00418 }
00419
00420
00421
00422
00423 HIDDEN void
00424 do_intersect(struct seg *A,
00425 struct seg *B,
00426 struct bu_list *seghead,
00427 struct soltab *type,
00428 struct dg_client_data *dgcdp)
00429 {
00430 struct seg *tmp=(struct seg *)NULL;
00431
00432 if( NOT_SEG_OVERLAP( A, B ) )
00433 return;
00434
00435 RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00436 if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00437 {
00438 if( B->seg_out.hit_dist <= A->seg_out.hit_dist )
00439 {
00440 *tmp = *B;
00441 tmp->seg_stp = type;
00442 }
00443 else
00444 {
00445 tmp->seg_in.hit_dist = B->seg_in.hit_dist;
00446 tmp->seg_out.hit_dist = A->seg_out.hit_dist;
00447 tmp->seg_stp = type;
00448 }
00449 }
00450 else
00451 {
00452 if( B->seg_out.hit_dist >= A->seg_out.hit_dist )
00453 {
00454 *tmp = *A;
00455 tmp->seg_stp = type;
00456 }
00457 else
00458 {
00459 tmp->seg_in.hit_dist = A->seg_in.hit_dist;
00460 tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00461 tmp->seg_stp = type;
00462 }
00463 }
00464 if( tmp )
00465 BU_LIST_INSERT( seghead, &tmp->l )
00466 return;
00467 }
00468
00469
00470
00471
00472 HIDDEN void
00473 do_subtract(struct seg *A,
00474 struct seg *B,
00475 struct bu_list *seghead,
00476 struct dg_client_data *dgcdp)
00477 {
00478 struct seg *tmp=(struct seg *)NULL;
00479
00480
00481 if( NOT_SEG_OVERLAP( A, B ) )
00482 {
00483 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00484 *tmp = *A;
00485 BU_LIST_INSERT( seghead, &tmp->l )
00486 return;
00487 }
00488
00489 if( B->seg_in.hit_dist<= A->seg_in.hit_dist )
00490 {
00491 if( B->seg_out.hit_dist < A->seg_out.hit_dist )
00492 {
00493 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00494 *tmp = *A;
00495 tmp->seg_in.hit_dist = B->seg_out.hit_dist;
00496 BU_LIST_INSERT( seghead, &tmp->l )
00497 return;
00498 }
00499 else
00500 return;
00501 }
00502 else
00503 {
00504 if( B->seg_out.hit_dist >= A->seg_out.hit_dist )
00505 {
00506 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00507 *tmp = *A;
00508 tmp->seg_out.hit_dist = B->seg_in.hit_dist;
00509 BU_LIST_INSERT( seghead, &tmp->l )
00510 return;
00511 }
00512 else
00513 {
00514 RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00515 tmp->seg_in.hit_dist = A->seg_in.hit_dist;
00516 tmp->seg_out.hit_dist = B->seg_in.hit_dist;
00517 tmp->seg_stp = A->seg_stp;
00518 BU_LIST_INSERT( seghead, &tmp->l )
00519 RT_GET_SEG( tmp, dgcdp->ap->a_resource );
00520 tmp->seg_in.hit_dist = B->seg_out.hit_dist;
00521 tmp->seg_out.hit_dist = A->seg_out.hit_dist;
00522 tmp->seg_stp = A->seg_stp;
00523 BU_LIST_INSERT( seghead, &tmp->l )
00524 return;
00525 }
00526 }
00527 }
00528
00529
00530
00531
00532 HIDDEN void
00533 do_union(struct seg *A,
00534 struct seg *B,
00535 struct bu_list *seghead,
00536 struct dg_client_data *dgcdp)
00537 {
00538 struct seg *tmp;
00539
00540 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00541
00542 if( NOT_SEG_OVERLAP( A, B ) )
00543 {
00544 if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00545 {
00546 *tmp = *A;
00547 BU_LIST_INSERT( seghead, &tmp->l )
00548 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00549 *tmp = *B;
00550 BU_LIST_INSERT( seghead, &tmp->l )
00551 }
00552 else
00553 {
00554 *tmp = *B;
00555 BU_LIST_INSERT( seghead, &tmp->l )
00556 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00557 *tmp = *A;
00558 BU_LIST_INSERT( seghead, &tmp->l )
00559 }
00560 return;
00561 }
00562
00563 if( A->seg_in.hit_dist <= B->seg_in.hit_dist )
00564 {
00565 *tmp = *A;
00566 if( B->seg_out.hit_dist > A->seg_out.hit_dist )
00567 tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00568 }
00569 else
00570 {
00571 *tmp = *B;
00572 if( A->seg_out.hit_dist > B->seg_out.hit_dist )
00573 tmp->seg_out.hit_dist = B->seg_out.hit_dist;
00574 }
00575
00576 BU_LIST_INSERT( seghead, &tmp->l )
00577 }
00578
00579 HIDDEN void
00580 promote_ints(struct bu_list *head,
00581 struct dg_client_data *dgcdp)
00582 {
00583 struct seg *a, *b, *tmp;
00584
00585 #ifdef debug
00586 bu_log( "In promote_ints():\n" );
00587 show_seg( head, "SEGS" );
00588 for( BU_LIST_FOR( a, seg, head ) )
00589 {
00590 b = BU_LIST_PNEXT( seg, &a->l );
00591 if( BU_LIST_IS_HEAD( &b->l, head ) )
00592 break;
00593
00594 if( b->seg_in.hit_dist < a->seg_in.hit_dist )
00595 bu_log( "\tsegments out of order:\n" );
00596 }
00597 #endif
00598
00599 a = BU_LIST_FIRST( seg, head );
00600 while( BU_LIST_NOT_HEAD( &a->l, head ) )
00601 {
00602 b = BU_LIST_PNEXT( seg, &a->l );
00603 while( BU_LIST_NOT_HEAD( &b->l, head ) )
00604 {
00605 if( a->seg_stp == ON_INT && b->seg_stp == ON_SURF )
00606 {
00607 if( NOT_SEG_OVERLAP( a, b ) )
00608 {
00609 b = BU_LIST_PNEXT( seg, &b->l );
00610 continue;
00611 }
00612
00613 if( a->seg_in.hit_dist == b->seg_in.hit_dist &&
00614 a->seg_out.hit_dist == b->seg_out.hit_dist )
00615 {
00616 a->seg_stp = ON_SURF;
00617 tmp = b;
00618 b = BU_LIST_PNEXT( seg, &b->l );
00619 BU_LIST_DEQUEUE( &tmp->l )
00620 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00621 continue;;
00622 }
00623
00624 if( a->seg_out.hit_dist == b->seg_out.hit_dist )
00625 a->seg_out.hit_dist = b->seg_in.hit_dist;
00626 else if( a->seg_out.hit_dist < b->seg_out.hit_dist )
00627 {
00628 if( b->seg_in.hit_dist > a->seg_in.hit_dist )
00629 a->seg_out.hit_dist = b->seg_in.hit_dist;
00630 else
00631 {
00632 tmp = a;
00633 a = BU_LIST_PLAST( seg, &a->l );
00634 BU_LIST_DEQUEUE( &tmp->l )
00635 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00636 break;
00637 }
00638 }
00639 else if( a->seg_in.hit_dist == b->seg_in.hit_dist )
00640 {
00641 fastf_t tmp_dist;
00642
00643 tmp_dist = a->seg_out.hit_dist;
00644 a->seg_out.hit_dist = b->seg_out.hit_dist;
00645 b->seg_in.hit_dist = a->seg_out.hit_dist;
00646 b->seg_out.hit_dist = tmp_dist;
00647 a->seg_stp = ON_SURF;
00648 b->seg_stp = ON_INT;
00649 }
00650 else
00651 {
00652 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00653 *tmp = *a;
00654 tmp->seg_in.hit_dist = b->seg_out.hit_dist;
00655 a->seg_out.hit_dist = b->seg_in.hit_dist;
00656 BU_LIST_APPEND( &b->l, &tmp->l )
00657 }
00658 }
00659 else if( b->seg_stp == ON_INT && a->seg_stp == ON_SURF )
00660 {
00661 if( NOT_SEG_OVERLAP( b, a ) )
00662 {
00663 b = BU_LIST_PNEXT( seg, &b->l );
00664 continue;
00665 }
00666
00667 if( b->seg_in.hit_dist == a->seg_in.hit_dist &&
00668 b->seg_out.hit_dist == a->seg_out.hit_dist )
00669 {
00670 b->seg_stp = ON_SURF;
00671 tmp = a;
00672 a = BU_LIST_PLAST( seg, &a->l );
00673 BU_LIST_DEQUEUE( &tmp->l )
00674 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00675 break;
00676 }
00677
00678 if( b->seg_out.hit_dist == a->seg_out.hit_dist )
00679 {
00680 tmp = b;
00681 b = BU_LIST_PNEXT( seg, &b->l );
00682 BU_LIST_DEQUEUE( &tmp->l )
00683 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00684 }
00685 else if( b->seg_out.hit_dist < a->seg_out.hit_dist )
00686 {
00687 if( a->seg_in.hit_dist > b->seg_in.hit_dist )
00688 b->seg_out.hit_dist = a->seg_in.hit_dist;
00689 else
00690 {
00691 tmp = b;
00692 b = BU_LIST_PNEXT( seg, &b->l );
00693 BU_LIST_DEQUEUE( &tmp->l )
00694 RT_FREE_SEG( tmp, dgcdp->ap->a_resource )
00695 continue;
00696 }
00697 }
00698 else if( b->seg_in.hit_dist == a->seg_in.hit_dist )
00699 b->seg_in.hit_dist = a->seg_out.hit_dist;
00700 else
00701 {
00702 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00703 *tmp = *b;
00704 tmp->seg_in.hit_dist = a->seg_out.hit_dist;
00705 b->seg_out.hit_dist = a->seg_in.hit_dist;
00706 BU_LIST_APPEND( &a->l, &tmp->l )
00707 }
00708 }
00709
00710 if( (a->seg_stp != ON_INT) || (b->seg_stp != ON_INT) )
00711 {
00712 b = BU_LIST_PNEXT( seg, &b->l );
00713 continue;
00714 }
00715
00716 if( NOT_SEG_OVERLAP( a, b ) )
00717 {
00718 b = BU_LIST_PNEXT( seg, &b->l );
00719 continue;
00720 }
00721
00722 #ifdef debug
00723 bu_log( "\tfound overlapping ON_INT segs:\n" );
00724 #endif
00725
00726 if( a->seg_in.hit_dist == b->seg_in.hit_dist &&
00727 a->seg_out.hit_dist == b->seg_out.hit_dist )
00728 {
00729 #ifdef debug
00730 bu_log( "Promoting A, eliminating B\n" );
00731 #endif
00732
00733 a->seg_stp = ON_SURF;
00734 BU_LIST_DEQUEUE( &b->l )
00735 RT_FREE_SEG( b, dgcdp->ap->a_resource )
00736 break;
00737 }
00738
00739 if( a->seg_out.hit_dist == b->seg_out.hit_dist )
00740 {
00741 b->seg_stp = ON_SURF;
00742 a->seg_out.hit_dist = b->seg_in.hit_dist;
00743
00744 #ifdef debug
00745 bu_log( "Promoting B, reducing A:\n" );
00746 #endif
00747 }
00748 else if( a->seg_out.hit_dist < b->seg_out.hit_dist )
00749 {
00750 if( b->seg_in.hit_dist > a->seg_in.hit_dist )
00751 {
00752 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00753 tmp->seg_stp = ON_SURF;
00754 tmp->seg_in.hit_dist = b->seg_in.hit_dist;
00755 tmp->seg_out.hit_dist = a->seg_out.hit_dist;
00756 b->seg_in.hit_dist = a->seg_out.hit_dist;
00757 a->seg_out.hit_dist = tmp->seg_in.hit_dist;
00758 BU_LIST_INSERT( &b->l, &tmp->l )
00759
00760 #ifdef debug
00761 bu_log( "--==__ overlap\n" );
00762 #endif
00763 }
00764 else
00765 {
00766 b->seg_in.hit_dist = a->seg_out.hit_dist;
00767 a->seg_stp = ON_SURF;
00768
00769 #ifdef debug
00770 bu_log( "A within B\n" );
00771 #endif
00772 }
00773 }
00774 else
00775 {
00776 if( a->seg_in.hit_dist == b->seg_in.hit_dist )
00777 {
00778 fastf_t tmp_dist;
00779
00780 tmp_dist = a->seg_out.hit_dist;
00781 a->seg_out.hit_dist = b->seg_out.hit_dist;
00782 a->seg_stp = ON_SURF;
00783 b->seg_in.hit_dist = a->seg_out.hit_dist;
00784 b->seg_out.hit_dist = tmp_dist;
00785 }
00786 else
00787 {
00788 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
00789 *tmp = *a;
00790 tmp->seg_in.hit_dist = b->seg_out.hit_dist;
00791 a->seg_out.hit_dist = b->seg_in.hit_dist;
00792 b->seg_stp = ON_SURF;
00793 BU_LIST_APPEND( &b->l, &tmp->l )
00794
00795 #ifdef debug
00796 bu_log( "B within A:\n" );
00797 #endif
00798 }
00799 }
00800 b = BU_LIST_PNEXT( seg, &b->l );
00801 }
00802 a = BU_LIST_PNEXT( seg, &a->l );
00803 }
00804
00805 #ifdef debug
00806 bu_log( "Results of promote_ints()\n" );
00807 show_seg( head, "SEGS" );
00808 #endif
00809 }
00810
00811
00812 HIDDEN struct bu_list *
00813 eval_op(struct bu_list *A,
00814 int op,
00815 struct bu_list *B,
00816 struct dg_client_data *dgcdp)
00817 {
00818 struct seg *sega, *segb, *tmp, *next;
00819 struct bu_list ret, ons, ins;
00820 int inserted;
00821
00822 BU_LIST_INIT( &ret );
00823
00824 #ifdef debug
00825 bu_log( "In eval_op:\n" );
00826 show_seg( A, "\tA:" );
00827 show_seg( B, "\tB:" );
00828 #endif
00829
00830 switch( op )
00831 {
00832 case OP_SUBTRACT:
00833
00834 #ifdef debug
00835 bu_log( "\t\tSUBTACT\n" );
00836 #endif
00837
00838 if( BU_LIST_IS_EMPTY( A ) )
00839 {
00840 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00841 bu_free( (char *)B, "bu_list" );
00842
00843 #ifdef debug
00844 show_seg( A, "Returning" );
00845 #endif
00846
00847 return( A );
00848 }
00849 else if( BU_LIST_IS_EMPTY( B ) )
00850 {
00851 bu_free( (char *)B, "bu_list" );
00852
00853 #ifdef debug
00854 show_seg( A, "Returning" );
00855 #endif
00856
00857 return( A );
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867 for( BU_LIST_FOR( sega, seg, A ) )
00868 {
00869 for( BU_LIST_FOR( segb, seg, B ) )
00870 {
00871 if( sega->seg_stp == ON_INT && segb->seg_stp == ON_INT )
00872 do_intersect( sega, segb, &ret, ON_SURF, dgcdp );
00873 else if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00874 {
00875 do_subtract( sega, segb, &ret, dgcdp );
00876 }
00877 else if( segb->seg_stp == ON_SURF || segb->seg_stp == ON_INT )
00878 do_intersect( segb, sega, &ret, segb->seg_stp, dgcdp );
00879 }
00880 }
00881 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00882 bu_free( (char *)B, "bu_list" );
00883 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00884 BU_LIST_INSERT_LIST( A, &ret )
00885
00886 #ifdef debug
00887 show_seg( A, "Returning" );
00888 #endif
00889
00890 return( A );
00891 case OP_INTERSECT:
00892
00893 #ifdef debug
00894 bu_log( "\t\tINTERSECT\n" );
00895 #endif
00896
00897 if( BU_LIST_IS_EMPTY( A ) || BU_LIST_IS_EMPTY( B ) )
00898 {
00899 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00900 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00901 bu_free( (char *)B, "bu_list" );
00902
00903 #ifdef debug
00904 show_seg( A, "Returning" );
00905 #endif
00906
00907 return( A );
00908 }
00909
00910
00911
00912
00913 for( BU_LIST_FOR( sega, seg, A ) )
00914 {
00915 for( BU_LIST_FOR( segb, seg, B ) )
00916 {
00917 if( sega->seg_stp == ON_INT && segb->seg_stp == ON_INT )
00918 do_intersect( sega, segb, &ret, ON_SURF, dgcdp );
00919 else if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00920 do_intersect( sega, segb, &ret, sega->seg_stp, dgcdp );
00921 else
00922 do_intersect( segb, sega, &ret, segb->seg_stp, dgcdp );
00923 }
00924 }
00925 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
00926 bu_free( (char *)B, "bu_list" );
00927 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
00928 BU_LIST_INSERT_LIST( A, &ret )
00929
00930 #ifdef debug
00931 show_seg( A, "Returning" );
00932 #endif
00933
00934 return( A );
00935 case OP_UNION:
00936
00937 #ifdef debug
00938 bu_log( "\t\tUNION\n" );
00939 #endif
00940
00941 if( BU_LIST_IS_EMPTY( A ) )
00942 {
00943 bu_free( (char *)A, "bu_list" );
00944
00945 #ifdef debug
00946 show_seg( B, "Returning B (A is empty)" );
00947 #endif
00948
00949 return( B );
00950 }
00951 if( BU_LIST_IS_EMPTY( B ) )
00952 {
00953 bu_free( (char *)B, "bu_list" );
00954
00955 #ifdef debug
00956 show_seg( A, "Returning A (B is empty)" );
00957 #endif
00958
00959 return( A );
00960 }
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 BU_LIST_INIT( &ons )
00974 BU_LIST_INIT( &ins )
00975
00976
00977 while( BU_LIST_WHILE( sega, seg, A ) )
00978 {
00979 BU_LIST_DEQUEUE( &sega->l )
00980
00981 if( sega->seg_stp == ON_SURF || sega->seg_stp == ON_INT )
00982 BU_LIST_INSERT( &ons, &sega->l )
00983 else
00984 BU_LIST_INSERT( &ins, &sega->l )
00985 }
00986
00987
00988
00989
00990 while( BU_LIST_WHILE( segb, seg, B ) )
00991 {
00992 int inserted;
00993 BU_LIST_DEQUEUE( &segb->l )
00994
00995 if( segb->seg_stp == IN_SOL )
00996 {
00997 inserted = 0;
00998 for( BU_LIST_FOR( tmp, seg, &ins ) )
00999 {
01000 if( tmp->seg_in.hit_dist >= segb->seg_in.hit_dist )
01001 {
01002 inserted = 1;
01003 BU_LIST_INSERT( &tmp->l, &segb->l )
01004 break;
01005 }
01006 }
01007 if( !inserted )
01008 BU_LIST_INSERT( &ins, &segb->l )
01009 }
01010 else
01011 {
01012 inserted = 0;
01013 for( BU_LIST_FOR( tmp, seg, &ons ) )
01014 {
01015 if( tmp->seg_in.hit_dist >= segb->seg_in.hit_dist )
01016 {
01017 inserted = 1;
01018 BU_LIST_INSERT( &tmp->l, &segb->l )
01019 break;
01020 }
01021 }
01022 if( !inserted )
01023 BU_LIST_INSERT( &ons, &segb->l )
01024 }
01025 }
01026
01027
01028 promote_ints( &ons, dgcdp );
01029
01030
01031 eliminate_overlaps( &ins, dgcdp );
01032 eliminate_overlaps( &ons, dgcdp );
01033
01034 #ifdef debug
01035 show_seg( &ons, "ONS" );
01036 show_seg( &ins, "INS" );
01037 #endif
01038
01039
01040 #ifdef debug
01041 bu_log( "doing subtraction:\n" );
01042 #endif
01043 sega = BU_LIST_FIRST( seg, &ons );
01044 while( BU_LIST_NOT_HEAD( &sega->l, &ons ) )
01045 {
01046 next = BU_LIST_PNEXT( seg, &sega->l );
01047
01048 #ifdef debug
01049 bu_log( "A is %g to %g:\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist );
01050 #endif
01051
01052 for( BU_LIST_FOR( segb, seg, &ins ) )
01053 {
01054 #ifdef debug
01055 bu_log( "\tcomparing to B %g to %g\n", segb->seg_in.hit_dist, segb->seg_out.hit_dist );
01056 #endif
01057
01058 if( NOT_SEG_OVERLAP( sega, segb ) )
01059 {
01060 #ifdef debug
01061 bu_log( "\t\tNo overlap!!\n" );
01062 #endif
01063
01064 continue;
01065 }
01066
01067 if( segb->seg_in.hit_dist <= sega->seg_in.hit_dist &&
01068 segb->seg_out.hit_dist >= sega->seg_out.hit_dist )
01069 {
01070 #ifdef debug
01071 bu_log( "\t\teliminating A\n" );
01072 #endif
01073
01074
01075 BU_LIST_DEQUEUE( &sega->l )
01076 RT_FREE_SEG( sega, dgcdp->ap->a_resource )
01077 sega = next;
01078 break;
01079 }
01080
01081 if( segb->seg_in.hit_dist > sega->seg_in.hit_dist &&
01082 segb->seg_out.hit_dist < sega->seg_out.hit_dist )
01083 {
01084
01085 RT_GET_SEG( tmp, dgcdp->ap->a_resource )
01086 *tmp = *sega;
01087 tmp->seg_in.hit_dist = segb->seg_out.hit_dist;
01088 sega->seg_out.hit_dist = segb->seg_in.hit_dist;
01089 BU_LIST_APPEND( &sega->l, &tmp->l )
01090 next = tmp;
01091
01092 #ifdef debug
01093 bu_log( "\t\tsplit A into: %g to %g and %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist, tmp->seg_in.hit_dist, tmp->seg_out.hit_dist );
01094 #endif
01095 }
01096 else
01097 {
01098
01099 if( segb->seg_in.hit_dist > sega->seg_in.hit_dist )
01100 sega->seg_out.hit_dist = segb->seg_in.hit_dist;
01101 if( segb->seg_out.hit_dist < sega->seg_out.hit_dist )
01102 sega->seg_in.hit_dist = segb->seg_out.hit_dist;
01103
01104 #ifdef debug
01105 bu_log( "\t\tsubtracted A down to %g to %g\n", sega->seg_in.hit_dist, sega->seg_out.hit_dist );
01106 #endif
01107 }
01108 }
01109 sega = next;
01110 }
01111
01112
01113 BU_LIST_INSERT_LIST( &ret, &ons )
01114
01115
01116 while( BU_LIST_WHILE( sega, seg, &ins ) )
01117 {
01118 BU_LIST_DEQUEUE( &sega->l )
01119
01120 inserted = 0;
01121 for( BU_LIST_FOR( segb, seg, &ret ) )
01122 {
01123 if( sega->seg_in.hit_dist < segb->seg_in.hit_dist )
01124 {
01125 BU_LIST_INSERT( &segb->l, &sega->l )
01126 inserted = 1;
01127 break;
01128 }
01129 }
01130
01131 if( !inserted )
01132 BU_LIST_INSERT( &ret, &sega->l )
01133 }
01134
01135 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
01136 bu_free( (char *)B, "bu_list" );
01137 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
01138 BU_LIST_INSERT_LIST( A, &ret )
01139
01140 #ifdef debug
01141 show_seg( A, "Returning" );
01142 #endif
01143
01144 return( A );
01145 }
01146
01147
01148 MY_FREE_SEG_LIST( A, dgcdp->ap->a_resource );
01149 MY_FREE_SEG_LIST( B, dgcdp->ap->a_resource );
01150 bu_free( (char *)B, "bu_list" );
01151
01152 #ifdef debug
01153 show_seg( A, "Returning (default)" );
01154 #endif
01155
01156 return( A );
01157
01158 }
01159
01160
01161 HIDDEN struct bu_list *
01162 eval_etree(union E_tree *eptr,
01163 struct dg_client_data *dgcdp)
01164
01165 {
01166 struct bu_list *A, *B;
01167
01168 CK_ETREE( eptr );
01169
01170 #ifdef debug
01171 bu_log( "In eval_etree:\n" );
01172 #endif
01173
01174 switch( eptr->l.op )
01175 {
01176 case OP_DB_LEAF:
01177 case OP_SOLID:
01178 A = (struct bu_list *)bu_malloc( sizeof( struct bu_list ), "bu_list" );
01179 BU_LIST_INIT( A );
01180 BU_LIST_INSERT_LIST( A, &eptr->l.seghead )
01181
01182 #ifdef debug
01183 show_seg( A, "LEAF:" );
01184 #endif
01185
01186 return( A );
01187 case OP_SUBTRACT:
01188 case OP_INTERSECT:
01189 case OP_UNION:
01190 #ifdef debug
01191 bu_log( "Evaluating subtrees\n" );
01192 #endif
01193
01194 A = eval_etree( eptr->n.left, dgcdp );
01195 B = eval_etree( eptr->n.right, dgcdp );
01196 return( eval_op( A, eptr->n.op, B, dgcdp ) );
01197 }
01198
01199
01200 return( (struct bu_list *)NULL );
01201 }
01202
01203 HIDDEN void
01204 inverse_dir( vect_t dir, vect_t inv_dir )
01205 {
01206
01207 if( !NEAR_ZERO( dir[X], SQRT_SMALL_FASTF ) ) {
01208 inv_dir[X]=1.0/dir[X];
01209 } else {
01210 inv_dir[X] = INFINITY;
01211 dir[X] = 0.0;
01212 }
01213 if( !NEAR_ZERO( dir[Y], SQRT_SMALL_FASTF ) ) {
01214 inv_dir[Y]=1.0/dir[Y];
01215 } else {
01216 inv_dir[Y] = INFINITY;
01217 dir[Y] = 0.0;
01218 }
01219 if( !NEAR_ZERO( dir[Z], SQRT_SMALL_FASTF ) ) {
01220 inv_dir[Z]=1.0/dir[Z];
01221 } else {
01222 inv_dir[Z] = INFINITY;
01223 dir[Z] = 0.0;
01224 }
01225 }
01226
01227 HIDDEN struct soltab *
01228 classify_seg( struct seg *seg, struct soltab *shoot, struct xray *rp, struct dg_client_data *dgcdp )
01229 {
01230 fastf_t mid_dist;
01231 struct xray new_rp;
01232 struct ray_data rd;
01233 struct soltab *ret = IN_SOL;
01234
01235 bzero( &rd, sizeof( struct ray_data ) );
01236
01237 BU_GETSTRUCT( rd.seghead, seg );
01238 BU_LIST_INIT( &rd.seghead->l );
01239
01240 mid_dist = (seg->seg_in.hit_dist + seg->seg_out.hit_dist) / 2.0;
01241 VJOIN1( new_rp.r_pt, rp->r_pt, mid_dist, rp->r_dir );
01242 #ifdef debug
01243 bu_log( "Classifying segment with mid_pt (%g %g %g) with respct to %s\n", V3ARGS( new_rp.r_pt ), shoot->st_dp->d_namep );
01244 #endif
01245
01246 bn_vec_ortho( new_rp.r_dir, rp->r_dir );
01247 inverse_dir( new_rp.r_dir, rd.rd_invdir );
01248
01249
01250 rd.rp = &new_rp;
01251 rd.tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01252 rd.ap = dgcdp->ap;
01253 rd.magic = NMG_RAY_DATA_MAGIC;
01254 rd.classifying_ray = 0;
01255 rd.hitmiss = (struct hitmiss **)NULL;
01256 rd.stp = shoot;
01257
01258 if( rt_functab[shoot->st_id].ft_shot( shoot, &new_rp, dgcdp->ap, rd.seghead ) ) {
01259 struct seg *seg;
01260
01261 while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) ) {
01262 BU_LIST_DEQUEUE( &seg->l );
01263 #ifdef debug
01264 bu_log( "dist = %g and %g\n", seg->seg_in.hit_dist,
01265 seg->seg_out.hit_dist );
01266 #endif
01267 if( ret != ON_SURF ) {
01268 if( NEAR_ZERO( seg->seg_in.hit_dist, rd.tol->dist ) ) {
01269 ret = ON_SURF;
01270 }
01271 if( NEAR_ZERO( seg->seg_out.hit_dist, rd.tol->dist ) ) {
01272 ret = ON_SURF;
01273 }
01274 }
01275 RT_FREE_SEG( seg, dgcdp->ap->a_resource );
01276 }
01277 }
01278
01279 if( ret != ON_SURF ) {
01280 vect_t new_dir;
01281
01282 VCROSS( new_dir, new_rp.r_dir, rp->r_dir );
01283 VMOVE( new_rp.r_dir, new_dir );
01284 inverse_dir( new_rp.r_dir, rd.rd_invdir );
01285 if( rt_functab[shoot->st_id].ft_shot( shoot, &new_rp, dgcdp->ap, rd.seghead ) ) {
01286 struct seg *seg;
01287
01288 while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) ) {
01289 BU_LIST_DEQUEUE( &seg->l );
01290 #ifdef debug
01291 bu_log( "dist = %g and %g\n", seg->seg_in.hit_dist,
01292 seg->seg_out.hit_dist );
01293 #endif
01294 if( ret != ON_SURF ) {
01295 if( NEAR_ZERO( seg->seg_in.hit_dist, rd.tol->dist ) ) {
01296 ret = ON_SURF;
01297 }
01298 if( NEAR_ZERO( seg->seg_out.hit_dist, rd.tol->dist ) ) {
01299 ret = ON_SURF;
01300 }
01301 }
01302 RT_FREE_SEG( seg, dgcdp->ap->a_resource );
01303 }
01304 }
01305 }
01306 #ifdef debug
01307 bu_log( "\t x%x\n", ret );
01308 #endif
01309 return ret;
01310 }
01311
01312
01313
01314
01315
01316 HIDDEN void
01317 shoot_and_plot(point_t start_pt,
01318 vect_t dir,
01319 struct bu_list *vhead,
01320 fastf_t edge_len,
01321 int skip_leaf1,
01322 int skip_leaf2,
01323 union E_tree *eptr,
01324 struct soltab *type,
01325 struct dg_client_data *dgcdp)
01326 {
01327 struct xray rp;
01328 struct ray_data rd;
01329 int shoot_leaf;
01330 struct bu_list *final_segs;
01331
01332 if( bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck() )
01333 bu_log( "Error at start of shoot_and_plot()\n" );
01334
01335 CK_ETREE( eptr );
01336
01337 bzero( &rd, sizeof( struct ray_data ) );
01338
01339 BU_GETSTRUCT( rd.seghead, seg );
01340 BU_LIST_INIT( &rd.seghead->l );
01341
01342 VMOVE( rp.r_pt, start_pt )
01343 VMOVE( rp.r_dir, dir )
01344
01345 if( !NEAR_ZERO( rp.r_dir[X], SQRT_SMALL_FASTF ) ) {
01346 rd.rd_invdir[X]=1.0/rp.r_dir[X];
01347 } else {
01348 rd.rd_invdir[X] = INFINITY;
01349 rp.r_dir[X] = 0.0;
01350 }
01351 if( !NEAR_ZERO( rp.r_dir[Y], SQRT_SMALL_FASTF ) ) {
01352 rd.rd_invdir[Y]=1.0/rp.r_dir[Y];
01353 } else {
01354 rd.rd_invdir[Y] = INFINITY;
01355 rp.r_dir[Y] = 0.0;
01356 }
01357 if( !NEAR_ZERO( rp.r_dir[Z], SQRT_SMALL_FASTF ) ) {
01358 rd.rd_invdir[Z]=1.0/rp.r_dir[Z];
01359 } else {
01360 rd.rd_invdir[Z] = INFINITY;
01361 rp.r_dir[Z] = 0.0;
01362 }
01363
01364
01365 rd.rp = &rp;
01366 rd.tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01367 rd.ap = dgcdp->ap;
01368 rd.magic = NMG_RAY_DATA_MAGIC;
01369 rd.classifying_ray = 0;
01370 rd.hitmiss = (struct hitmiss **)NULL;
01371
01372
01373
01374
01375 for( shoot_leaf=0 ; shoot_leaf < BU_PTBL_END( &dgcdp->leaf_list ) ; shoot_leaf++ )
01376 {
01377 union E_tree *shoot;
01378 int dont_shoot=0;
01379
01380 shoot = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, shoot_leaf );
01381
01382 if( BU_LIST_NON_EMPTY( &shoot->l.seghead ) )
01383 {
01384 MY_FREE_SEG_LIST( &shoot->l.seghead, dgcdp->ap->a_resource );
01385 }
01386 BU_LIST_INIT( &shoot->l.seghead );
01387
01388
01389 if( shoot_leaf == skip_leaf1 || shoot_leaf == skip_leaf2 )
01390 dont_shoot = 1;
01391 else
01392 {
01393
01394 union E_tree *leaf;
01395
01396 if( skip_leaf1 >= 0 )
01397 {
01398 leaf = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, skip_leaf1 );
01399 if( leaf->l.stp->st_dp == shoot->l.stp->st_dp )
01400 {
01401 if( !leaf->l.stp->st_matp && !shoot->l.stp->st_matp )
01402 dont_shoot = 1;
01403 else if( !leaf->l.stp->st_matp &&
01404 bn_mat_is_equal( shoot->l.stp->st_matp,
01405 bn_mat_identity,
01406 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01407 dont_shoot = 1;
01408 else if( !shoot->l.stp->st_matp &&
01409 bn_mat_is_equal( leaf->l.stp->st_matp,
01410 bn_mat_identity,
01411 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01412 dont_shoot = 1;
01413 else if( leaf->l.stp->st_matp &&
01414 shoot->l.stp->st_matp &&
01415 bn_mat_is_equal( leaf->l.stp->st_matp,
01416 shoot->l.stp->st_matp,
01417 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01418 dont_shoot = 1;
01419 }
01420 }
01421 if( !dont_shoot && skip_leaf2 >= 0 )
01422 {
01423 leaf = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, skip_leaf2 );
01424 if( leaf->l.stp->st_dp == shoot->l.stp->st_dp )
01425 {
01426 if( !leaf->l.stp->st_matp && !shoot->l.stp->st_matp )
01427 dont_shoot = 1;
01428 else if( !leaf->l.stp->st_matp &&
01429 bn_mat_is_equal( shoot->l.stp->st_matp,
01430 bn_mat_identity,
01431 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01432 dont_shoot = 1;
01433 else if( !shoot->l.stp->st_matp &&
01434 bn_mat_is_equal( leaf->l.stp->st_matp,
01435 bn_mat_identity,
01436 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01437 dont_shoot = 1;
01438 else if( leaf->l.stp->st_matp &&
01439 shoot->l.stp->st_matp &&
01440 bn_mat_is_equal( leaf->l.stp->st_matp,
01441 shoot->l.stp->st_matp,
01442 &dgcdp->dgop->dgo_wdbp->wdb_tol ) )
01443 dont_shoot = 1;
01444 }
01445 }
01446 }
01447
01448 if( dont_shoot )
01449 {
01450 struct seg *seg;
01451
01452
01453 RT_GET_SEG( seg, dgcdp->ap->a_resource );
01454 seg->l.magic = RT_SEG_MAGIC;
01455 seg->seg_in.hit_dist = 0.0;
01456 seg->seg_out.hit_dist = edge_len;
01457 seg->seg_stp = type;
01458 BU_LIST_INSERT( &shoot->l.seghead, &seg->l );
01459 continue;
01460 }
01461
01462
01463 rd.rd_m = shoot->l.m;
01464 BU_LIST_INIT(&rd.rd_hit);
01465 BU_LIST_INIT(&rd.rd_miss);
01466
01467 rd.stp = shoot->l.stp;
01468
01469
01470 if( rt_in_rpp( &rp, rd.rd_invdir, shoot->l.stp->st_min, shoot->l.stp->st_max ) )
01471 {
01472 if( rt_functab[shoot->l.stp->st_id].ft_shot( shoot->l.stp, &rp, dgcdp->ap, rd.seghead ) )
01473 {
01474 struct seg *seg;
01475
01476
01477 while( BU_LIST_WHILE( seg, seg, &rd.seghead->l ) )
01478 {
01479 BU_LIST_DEQUEUE( &seg->l )
01480
01481 if( seg->seg_in.hit_dist >= edge_len || seg->seg_out.hit_dist <= 0 )
01482 RT_FREE_SEG( seg, dgcdp->ap->a_resource )
01483 else
01484 {
01485 if( seg->seg_in.hit_dist < 0.0 )
01486 seg->seg_in.hit_dist = 0.0;
01487 if( seg->seg_out.hit_dist > edge_len )
01488 seg->seg_out.hit_dist = edge_len;
01489 seg->seg_stp = classify_seg( seg, shoot->l.stp, &rp, dgcdp );
01490 BU_LIST_INSERT( &shoot->l.seghead, &seg->l )
01491 }
01492 }
01493 }
01494 }
01495 }
01496
01497
01498
01499
01500 #ifdef debug
01501 bu_log( "EVALUATING ETREE:\n" );
01502 bu_log( "ray start (%g %g %g), dir=(%g %g %g)\n", V3ARGS( start_pt ), V3ARGS( dir ) );
01503 #endif
01504
01505 final_segs = eval_etree( eptr, dgcdp );
01506
01507 #ifdef debug
01508 show_seg( final_segs, "DRAWING" );
01509 #endif
01510
01511 if( final_segs )
01512 {
01513 struct seg *seg;
01514
01515
01516 for( BU_LIST_FOR( seg, seg, final_segs ) )
01517 {
01518 point_t pt;
01519
01520
01521 if( seg->seg_stp != ON_SURF )
01522 continue;
01523
01524 dgcdp->nvectors++;
01525 VJOIN1( pt, rp.r_pt, seg->seg_in.hit_dist, rp.r_dir )
01526
01527 #ifdef debug
01528 bu_log( "\t\tDRAW (%g %g %g)", V3ARGS( pt ) );
01529 #endif
01530
01531 RT_ADD_VLIST( vhead, pt, RT_VLIST_LINE_MOVE );
01532 VJOIN1( pt, rp.r_pt, seg->seg_out.hit_dist, rp.r_dir )
01533
01534 #ifdef debug
01535 bu_log( "<->(%g %g %g)\n", V3ARGS( pt ) );
01536 #endif
01537
01538 RT_ADD_VLIST( vhead, pt, RT_VLIST_LINE_DRAW );
01539 }
01540
01541 }
01542
01543 if( final_segs )
01544 MY_FREE_SEG_LIST( final_segs, dgcdp->ap->a_resource );
01545 bu_free( (char *)final_segs, "bu_list" );
01546
01547 if( bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck() )
01548 bu_log( "Error at end of shoot_and_plot()\n" );
01549
01550 }
01551
01552 #define HITS_BLOCK 20
01553
01554 HIDDEN void
01555 Eplot(union E_tree *eptr,
01556 struct bu_list *vhead,
01557 struct dg_client_data *dgcdp)
01558 {
01559 point_t start_pt;
01560 int leaf_no;
01561 union E_tree *leaf_ptr;
01562 int hit_count1=0, hit_count2=0;
01563 point_t *hits1=NULL, *hits2=NULL;
01564 int hits_avail1=0, hits_avail2=0;
01565 int i;
01566 struct bu_list *result;
01567 struct bn_tol *tol;
01568
01569 tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01570
01571 CK_ETREE( eptr );
01572
01573
01574 for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01575 {
01576 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01577 CK_ETREE( leaf_ptr );
01578 if( leaf_ptr->l.op != OP_DB_LEAF && leaf_ptr->l.op != OP_SOLID )
01579 {
01580 Tcl_AppendResult(dgcdp->interp, "Eplot: Bad leaf node!!!\n", (char *)NULL );
01581 return;
01582 }
01583
01584 if( leaf_ptr->l.m )
01585 nmg_edge_tabulate( &leaf_ptr->l.edge_list, &leaf_ptr->l.m->magic );
01586 else
01587 bu_ptbl_init( &leaf_ptr->l.edge_list, 1, "edge_list" );
01588 }
01589
01590
01591
01592
01593 for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01594 {
01595 int edge_no;
01596
01597 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01598
01599 if( !leaf_ptr->l.m )
01600 continue;
01601
01602
01603 for( edge_no=0 ; edge_no < BU_PTBL_END( &leaf_ptr->l.edge_list ) ; edge_no++ )
01604 {
01605 struct edge *e;
01606 struct vertex_g *vg;
01607 struct vertex_g *vg2;
01608 vect_t dir;
01609 fastf_t edge_len;
01610 fastf_t inv_len;
01611
01612 e = (struct edge *)BU_PTBL_GET( &leaf_ptr->l.edge_list, edge_no );
01613 NMG_CK_EDGE( e );
01614 vg = e->eu_p->vu_p->v_p->vg_p;
01615 NMG_CK_VERTEX_G( vg );
01616
01617 vg2 = e->eu_p->eumate_p->vu_p->v_p->vg_p;
01618 NMG_CK_VERTEX_G( vg2 );
01619
01620
01621 VSUB2( dir, vg2->coord, vg->coord );
01622 edge_len = MAGNITUDE( dir );
01623 if( edge_len < tol->dist )
01624 continue;
01625 inv_len = 1.0/edge_len;
01626 VSCALE( dir, dir, inv_len );
01627 shoot_and_plot( vg->coord, dir, vhead, edge_len, leaf_no, -1, eptr, ON_SURF, dgcdp );
01628
01629 }
01630 }
01631
01632 hits1 = (point_t *)bu_calloc( HITS_BLOCK, sizeof( point_t ), "hits" );
01633 hits_avail1 = HITS_BLOCK;
01634 hits2 = (point_t *)bu_calloc( HITS_BLOCK, sizeof( point_t ), "hits" );
01635 hits_avail2 = HITS_BLOCK;
01636
01637
01638 for( leaf_no=0 ; leaf_no < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf_no++ )
01639 {
01640 int leaf2;
01641
01642 leaf_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf_no );
01643 if( !leaf_ptr->l.m )
01644 continue;
01645
01646 for( leaf2=leaf_no+1 ; leaf2 < BU_PTBL_END( &dgcdp->leaf_list ) ; leaf2++ )
01647 {
01648 union E_tree *leaf2_ptr;
01649 struct nmgregion *r1, *r2;
01650 struct shell *s1, *s2;
01651 struct faceuse *fu1, *fu2;
01652 struct face *f1, *f2;
01653 plane_t pl1, pl2;
01654 struct loopuse *lu1, *lu2;
01655 struct edgeuse *eu1, *eu2;
01656 struct vertex_g *vg1a, *vg1b, *vg2a, *vg2b;
01657 struct bu_list *A, *B;
01658
01659 leaf2_ptr = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, leaf2 );
01660 if( !leaf2_ptr->l.m )
01661 continue;
01662
01663
01664
01665 r1 = BU_LIST_FIRST( nmgregion, &leaf_ptr->l.m->r_hd );
01666 s1 = BU_LIST_FIRST( shell, &r1->s_hd );
01667 r2 = BU_LIST_FIRST( nmgregion, &leaf2_ptr->l.m->r_hd );
01668 s2 = BU_LIST_FIRST( shell, &r2->s_hd );
01669
01670 for( BU_LIST_FOR( fu1, faceuse, &s1->fu_hd ) )
01671 {
01672 if( fu1->orientation != OT_SAME )
01673 continue;
01674
01675 f1 = fu1->f_p;
01676 NMG_GET_FU_PLANE( pl1, fu1 );
01677
01678 for( BU_LIST_FOR( fu2, faceuse, &s2->fu_hd ) )
01679 {
01680 fastf_t dist;
01681 vect_t dir;
01682 vect_t diff;
01683 fastf_t *dists1, *dists2;
01684 fastf_t min_dist, max_dist;
01685 int min_hit, max_hit;
01686 int done;
01687 struct seg *aseg;
01688
01689 if( fu2->orientation != OT_SAME )
01690 continue;
01691
01692 f2 = fu2->f_p;
01693
01694 if ( !V3RPP_OVERLAP_TOL(f2->min_pt, f2->max_pt,
01695 f1->min_pt, f1->max_pt,
01696 tol) )
01697 continue;
01698
01699 NMG_GET_FU_PLANE( pl2, fu2 );
01700
01701 if( bn_coplanar( pl1, pl2, tol ) ) {
01702 continue;
01703 }
01704
01705 hit_count1=0;
01706 hit_count2=0;
01707 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) )
01708 {
01709 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_EDGEUSE_MAGIC )
01710 continue;
01711
01712 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) )
01713 {
01714 vg1a = eu1->vu_p->v_p->vg_p;
01715 vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
01716 VSUB2( dir, vg1b->coord, vg1a->coord );
01717
01718
01719
01720 if( bn_isect_line3_plane( &dist, vg1a->coord,
01721 dir, pl2,
01722 tol ) < 1 )
01723 continue;
01724
01725 if( dist < -tol->dist || dist > 1.0 + tol->dist )
01726 continue;
01727
01728 if( hit_count1 >= hits_avail1 ) {
01729 hits_avail1 += HITS_BLOCK;
01730 hits1 = (point_t *)bu_realloc( hits1,
01731 hits_avail1 * sizeof( point_t ), "hits1" );
01732 }
01733 VJOIN1( hits1[hit_count1], vg1a->coord, dist, dir );
01734 hit_count1++;
01735 }
01736 }
01737 for( BU_LIST_FOR( lu2, loopuse, &fu2->lu_hd ) )
01738 {
01739 if( BU_LIST_FIRST_MAGIC( &lu2->down_hd ) != NMG_EDGEUSE_MAGIC )
01740 continue;
01741
01742 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) )
01743 {
01744 vg2a = eu2->vu_p->v_p->vg_p;
01745 vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
01746 VSUB2( dir, vg2b->coord, vg2a->coord );
01747
01748
01749
01750 if( bn_isect_line3_plane( &dist, vg2a->coord,
01751 dir, pl1,
01752 tol ) < 1 )
01753 continue;
01754
01755 if( dist < -tol->dist || dist > 1.0 + tol->dist )
01756 continue;
01757
01758 if( hit_count2 >= hits_avail2 ) {
01759 hits_avail2 += HITS_BLOCK;
01760 hits2 = (point_t *)bu_realloc( hits2,
01761 hits_avail2 * sizeof( point_t ), "hits2" );
01762 }
01763 VJOIN1( hits2[hit_count2], vg2a->coord, dist, dir );
01764 hit_count2++;
01765 }
01766 }
01767
01768 if( hit_count1 < 2 || hit_count2 < 2 ) {
01769
01770 continue;
01771 }
01772
01773
01774 dists1 = (fastf_t *)bu_calloc( hit_count1,
01775 sizeof( fastf_t ), "dists1" );
01776 dists2 = (fastf_t *)bu_calloc( hit_count2,
01777 sizeof( fastf_t ), "dists2" );
01778 VMOVE( start_pt, hits1[0] );
01779 dists1[0] = 0.0;
01780 min_dist = 0.0;
01781 min_hit = 0;
01782 VSUB2( dir, hits1[1], hits1[0] );
01783 dists1[1] = MAGNITUDE( dir );
01784 VUNITIZE( dir );
01785 max_dist = dists1[1];
01786 max_hit = 1;
01787 for( i=2 ; i<hit_count1 ; i++ ) {
01788 VSUB2( diff, hits1[i], start_pt );
01789 dists1[i] = MAGNITUDE( diff );
01790 if( VDOT( dir, diff ) < 0.0 )
01791 dists1[i] = -dists1[i];
01792 if( dists1[i] > max_dist ) {
01793 max_dist = dists1[i];
01794 max_hit = i;
01795 }
01796 if( dists1[i] < min_dist ) {
01797 min_dist = dists1[i];
01798 min_hit = i;
01799 }
01800 }
01801
01802
01803 VSUB2( dir, hits1[max_hit], hits1[min_hit] );
01804 VUNITIZE( dir );
01805
01806 done = 0;
01807 while( !done ) {
01808 done = 1;
01809 for( i=1 ; i<hit_count1 ; i++ ) {
01810 if( dists1[i-1] > dists1[i] ) {
01811 fastf_t tmp;
01812 point_t tmp_pt;
01813
01814 done = 0;
01815 tmp = dists1[i];
01816 VMOVE( tmp_pt, hits1[i] );
01817 dists1[i] = dists1[i-1];
01818 VMOVE( hits1[i], hits1[i-1] );
01819 dists1[i-1] = tmp;
01820 VMOVE( hits1[i-1], tmp_pt );
01821 }
01822 }
01823 }
01824
01825
01826 min_dist = MAX_FASTF;
01827 min_hit = -1;
01828 max_dist = -min_dist;
01829 max_hit = -1;
01830 for( i=0 ; i<hit_count2 ; i++ ) {
01831 VSUB2( diff, hits2[i], start_pt );
01832 dists2[i] = MAGNITUDE( diff );
01833 if( VDOT( dir, diff ) < 0.0 )
01834 dists2[i] = -dists2[i];
01835 if( dists2[i] > max_dist ) {
01836 max_dist = dists2[i];
01837 max_hit = i;
01838 }
01839 if( dists2[i] < min_dist ) {
01840 min_dist = dists2[i];
01841 min_hit = i;
01842 }
01843 }
01844
01845 done = 0;
01846 while( !done ) {
01847 done = 1;
01848 for( i=1 ; i<hit_count2 ; i++ ) {
01849 if( dists2[i-1] > dists2[i] ) {
01850 fastf_t tmp;
01851 point_t tmp_pt;
01852
01853 done = 0;
01854 tmp = dists2[i];
01855 VMOVE( tmp_pt, hits2[i] );
01856 dists2[i] = dists2[i-1];
01857 VMOVE( hits2[i], hits2[i-1] );
01858 dists2[i-1] = tmp;
01859 VMOVE( hits2[i-1], tmp_pt );
01860 }
01861 }
01862 }
01863
01864
01865 A = (struct bu_list *)bu_calloc( 1, sizeof( struct bu_list ), "A" );
01866 B = (struct bu_list *)bu_calloc( 1, sizeof( struct bu_list ), "B" );
01867 BU_LIST_INIT( A );
01868 BU_LIST_INIT( B );
01869
01870 for( i=1 ; i<hit_count1 ; i += 2 ) {
01871 fastf_t diff;
01872
01873 diff = dists1[i] - dists1[i-1];
01874 if( NEAR_ZERO( diff, tol->dist )) {
01875 continue;
01876 }
01877 RT_GET_SEG( aseg, dgcdp->ap->a_resource );
01878 aseg->l.magic = RT_SEG_MAGIC;
01879 aseg->seg_stp = ON_INT;
01880 VMOVE( aseg->seg_in.hit_point, hits1[i-1] );
01881 aseg->seg_in.hit_dist = dists1[i-1];
01882 VMOVE( aseg->seg_out.hit_point, hits1[i] );
01883 aseg->seg_out.hit_dist = dists1[i];
01884
01885 BU_LIST_APPEND( A, &aseg->l );
01886 }
01887
01888 for( i=1 ; i<hit_count2 ; i += 2 ) {
01889 fastf_t diff;
01890
01891 diff = dists2[i] - dists2[i-1];
01892 if( NEAR_ZERO( diff, tol->dist )) {
01893 continue;
01894 }
01895 RT_GET_SEG( aseg, dgcdp->ap->a_resource );
01896 aseg->l.magic = RT_SEG_MAGIC;
01897 aseg->seg_stp = ON_INT;
01898 VMOVE( aseg->seg_in.hit_point, hits2[i-1] );
01899 aseg->seg_in.hit_dist = dists2[i-1];
01900 VMOVE( aseg->seg_out.hit_point, hits2[i] );
01901 aseg->seg_out.hit_dist = dists2[i];
01902
01903 BU_LIST_APPEND( B, &aseg->l );
01904 }
01905
01906 result = eval_op( A, OP_INTERSECT, B, dgcdp );
01907
01908 for( BU_LIST_FOR( aseg, seg, result ) ) {
01909 point_t ray_start;
01910
01911 VJOIN1( ray_start, start_pt, aseg->seg_in.hit_dist, dir );
01912 shoot_and_plot( ray_start, dir, vhead,
01913 aseg->seg_out.hit_dist - aseg->seg_in.hit_dist,
01914 leaf_no, leaf2, eptr, ON_INT, dgcdp );
01915 }
01916 MY_FREE_SEG_LIST( result, dgcdp->ap->a_resource );
01917
01918 bu_free( (char *)dists1, "dists1" );
01919 bu_free( (char *)dists2, "dists2" );
01920 }
01921 }
01922 }
01923 }
01924
01925 bu_free( (char *)hits1, "hits1" );
01926 bu_free( (char *)hits2, "hits2" );
01927 }
01928
01929 HIDDEN void
01930 free_etree(union E_tree *eptr,
01931 struct dg_client_data *dgcdp)
01932 {
01933 CK_ETREE( eptr );
01934
01935 switch( eptr->l.op )
01936 {
01937 case OP_UNION:
01938 case OP_SUBTRACT:
01939 case OP_INTERSECT:
01940 free_etree( eptr->n.left, dgcdp );
01941 free_etree( eptr->n.right, dgcdp );
01942 bu_free( (char *)eptr, "node pointer" );
01943 break;
01944 case OP_DB_LEAF:
01945 case OP_SOLID:
01946 if( eptr->l.m && !eptr->l.do_not_free_model )
01947 {
01948 nmg_km( eptr->l.m );
01949 eptr->l.m = (struct model *)NULL;
01950 }
01951 if( BU_LIST_NON_EMPTY( &eptr->l.seghead ) )
01952 {
01953 MY_FREE_SEG_LIST( &eptr->l.seghead, dgcdp->ap->a_resource );
01954 }
01955 if( BU_LIST_NON_EMPTY( &eptr->l.edge_list.l ) )
01956 {
01957 bu_ptbl_free( &eptr->l.edge_list );
01958 }
01959 if( eptr->l.stp )
01960 {
01961 if( eptr->l.stp->st_specific )
01962 rt_functab[eptr->l.stp->st_id].ft_free( eptr->l.stp );
01963 bu_free( (char *)eptr->l.stp, "struct soltab" );
01964 }
01965
01966 bu_free( (char *)eptr, "leaf pointer" );
01967 break;
01968 }
01969 }
01970
01971
01972 HIDDEN void
01973 fix_halfs(struct dg_client_data *dgcdp)
01974 {
01975 point_t max, min;
01976 int i, count=0;
01977 struct bn_tol *tol;
01978
01979 tol = &dgcdp->dgop->dgo_wdbp->wdb_tol;
01980
01981 VSETALL( max, -MAX_FASTF )
01982 VSETALL( min, MAX_FASTF )
01983
01984 for( i=0 ; i<BU_PTBL_END( &dgcdp->leaf_list ) ; i++ )
01985 {
01986 union E_tree *tp;
01987
01988 tp = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, i );
01989
01990 if( tp->l.stp->st_id == ID_HALF )
01991 continue;
01992
01993 VMINMAX( min, max, tp->l.stp->st_min )
01994 VMINMAX( min, max, tp->l.stp->st_max )
01995 count++;
01996 }
01997
01998 if( !count )
01999 {
02000 Tcl_AppendResult(dgcdp->interp, "A 'half' solid is the only solid in a region (ignored)\n", (char *)NULL );
02001 return;
02002 }
02003
02004 for( i=0 ; i<BU_PTBL_END( &dgcdp->leaf_list ) ; i++ )
02005 {
02006 union E_tree *tp;
02007 struct vertex *v[8];
02008 struct vertex **vp[4];
02009 struct nmgregion *r;
02010 struct shell *s;
02011 struct rt_pg_internal *pg;
02012 struct faceuse *fu;
02013 plane_t haf_pl;
02014 struct half_specific *hp;
02015 int j;
02016
02017 tp = (union E_tree *)BU_PTBL_GET( &dgcdp->leaf_list, i );
02018
02019 if( tp->l.stp->st_id != ID_HALF )
02020 continue;
02021
02022 hp = (struct half_specific *)tp->l.stp->st_specific;
02023
02024 HMOVE( haf_pl, hp->half_eqn )
02025
02026 if( DIST_PT_PLANE( max, haf_pl ) >= -tol->dist &&
02027 DIST_PT_PLANE( min, haf_pl ) >= -tol->dist )
02028 continue;
02029
02030
02031 tp->l.m = nmg_mm();
02032 r = nmg_mrsv( tp->l.m );
02033 s = BU_LIST_FIRST( shell, &r->s_hd );
02034
02035 for( j=0 ; j<8 ; j++ )
02036 v[j] = (struct vertex *)NULL;
02037
02038 vp[0] = &v[0];
02039 vp[1] = &v[1];
02040 vp[2] = &v[2];
02041 vp[3] = &v[3];
02042 fu = nmg_cmface( s, vp, 4 );
02043 nmg_vertex_g( v[0], max[X], min[Y], min[Z] );
02044 nmg_vertex_g( v[1], max[X], max[Y], min[Z] );
02045 nmg_vertex_g( v[2], max[X], max[Y], max[Z] );
02046 nmg_vertex_g( v[3], max[X], min[Y], max[Z] );
02047 nmg_calc_face_g( fu );
02048
02049 vp[0] = &v[4];
02050 vp[1] = &v[5];
02051 vp[2] = &v[6];
02052 vp[3] = &v[7];
02053 fu = nmg_cmface( s, vp, 4 );
02054 nmg_vertex_g( v[4], min[X], min[Y], min[Z] );
02055 nmg_vertex_g( v[5], min[X], min[Y], max[Z] );
02056 nmg_vertex_g( v[6], min[X], max[Y], max[Z] );
02057 nmg_vertex_g( v[7], min[X], max[Y], min[Z] );
02058 nmg_calc_face_g( fu );
02059
02060 vp[0] = &v[0];
02061 vp[1] = &v[3];
02062 vp[2] = &v[5];
02063 vp[3] = &v[4];
02064 fu = nmg_cmface( s, vp, 4 );
02065 nmg_calc_face_g( fu );
02066
02067 vp[0] = &v[1];
02068 vp[1] = &v[7];
02069 vp[2] = &v[6];
02070 vp[3] = &v[2];
02071 fu = nmg_cmface( s, vp, 4 );
02072 nmg_calc_face_g( fu );
02073
02074 vp[0] = &v[3];
02075 vp[1] = &v[2];
02076 vp[2] = &v[6];
02077 vp[3] = &v[5];
02078 fu = nmg_cmface( s, vp, 4 );
02079 nmg_calc_face_g( fu );
02080
02081 vp[0] = &v[1];
02082 vp[1] = &v[0];
02083 vp[2] = &v[4];
02084 vp[3] = &v[7];
02085 fu = nmg_cmface( s, vp, 4 );
02086 nmg_calc_face_g( fu );
02087
02088 nmg_region_a( r, tol );
02089
02090 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
02091 {
02092 struct edgeuse *eu, *new_eu;
02093 struct loopuse *lu, *new_lu;
02094 plane_t pl;
02095 int count;
02096 struct vertexuse *vcut[2];
02097 point_t pt[2];
02098 struct edgeuse *eu_split[2];
02099
02100 if( fu->orientation != OT_SAME )
02101 continue;
02102
02103 NMG_GET_FU_PLANE( pl, fu );
02104
02105 if( bn_coplanar( pl, haf_pl, tol ) > 0 )
02106 continue;
02107
02108 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02109
02110 count = 0;
02111 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02112 {
02113 vect_t dir;
02114 struct vertex_g *v1g, *v2g;
02115 fastf_t dist;
02116
02117 v1g = eu->vu_p->v_p->vg_p;
02118 v2g = eu->eumate_p->vu_p->v_p->vg_p;
02119
02120 VSUB2( dir, v2g->coord, v1g->coord )
02121
02122 if( bn_isect_line3_plane( &dist, v1g->coord, dir, haf_pl, tol ) < 1 )
02123 continue;
02124
02125 if( dist < 0.0 || dist >=1.0 )
02126 continue;
02127
02128 VJOIN1( pt[count], v1g->coord, dist, dir )
02129 eu_split[count] = eu;
02130
02131 count++;
02132 if( count == 2 )
02133 break;
02134 }
02135
02136 if( count != 2 )
02137 continue;
02138
02139 new_eu = nmg_eusplit( (struct vertex *)NULL, eu_split[0], 1 );
02140 vcut[0] = new_eu->vu_p;
02141 nmg_vertex_gv( vcut[0]->v_p, pt[0] );
02142
02143 new_eu = nmg_eusplit( (struct vertex *)NULL, eu_split[1], 1 );
02144 vcut[1] = new_eu->vu_p;
02145 nmg_vertex_gv( vcut[1]->v_p, pt[1] );
02146
02147 new_lu = nmg_cut_loop( vcut[0], vcut[1] );
02148 nmg_lu_reorient( lu );
02149 nmg_lu_reorient( new_lu );
02150
02151 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02152 {
02153 if( eu->vu_p->v_p == vcut[0]->v_p || eu->vu_p->v_p == vcut[1]->v_p )
02154 continue;
02155
02156 if( DIST_PT_PLANE( eu->vu_p->v_p->vg_p->coord, haf_pl ) > tol->dist )
02157 {
02158 nmg_klu( lu );
02159 break;
02160 }
02161 else
02162 {
02163 nmg_klu( new_lu );
02164 break;
02165 }
02166 }
02167 }
02168
02169
02170 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
02171 if( fu->orientation != OT_SAME )
02172 fu = BU_LIST_PNEXT( faceuse, &fu->l );
02173 while( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) )
02174 {
02175 struct faceuse *next_fu;
02176 struct loopuse *lu;
02177 int killfu=0;
02178
02179 next_fu = BU_LIST_PNEXT( faceuse, &fu->l );
02180 if( fu->fumate_p == next_fu )
02181 next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l );
02182
02183 if( fu->orientation != OT_SAME )
02184 {
02185 fu = next_fu;
02186 continue;
02187 }
02188
02189 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02190 while( BU_LIST_NOT_HEAD( &lu->l, &fu->lu_hd ) )
02191 {
02192 struct loopuse *next_lu;
02193 struct edgeuse *eu;
02194 int killit;
02195
02196 next_lu = BU_LIST_PNEXT( loopuse, &lu->l );
02197
02198 killit = 0;
02199 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02200 {
02201 struct vertex_g *vg;
02202
02203 vg = eu->vu_p->v_p->vg_p;
02204
02205 if( DIST_PT_PLANE( vg->coord, haf_pl ) > tol->dist )
02206 {
02207 killit = 1;
02208 break;
02209 }
02210 }
02211
02212 if( killit )
02213 {
02214 if( nmg_klu( lu ) )
02215 {
02216 killfu = 1;
02217 break;
02218 }
02219 }
02220 lu = next_lu;
02221 }
02222
02223 if( killfu )
02224 nmg_kfu( fu );
02225
02226 fu = next_fu;
02227 }
02228
02229 nmg_rebound( tp->l.m, tol );
02230 nmg_model_fuse( tp->l.m, tol );
02231 nmg_close_shell( s, tol );
02232 nmg_rebound( tp->l.m, tol );
02233
02234 BU_GETSTRUCT( pg, rt_pg_internal );
02235
02236 if( !nmg_to_poly( tp->l.m, pg, tol ) )
02237 {
02238 bu_free( (char *)pg, "rt_pg_internal" );
02239 Tcl_AppendResult(dgcdp->interp, "Prep failure for solid '", tp->l.stp->st_dp->d_namep,
02240 "'\n", (char *)NULL );
02241 }
02242 else
02243 {
02244 struct rt_db_internal intern2;
02245
02246 RT_INIT_DB_INTERNAL( &intern2 );
02247 intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
02248 intern2.idb_type = ID_POLY;
02249 intern2.idb_meth = &rt_functab[ID_POLY];
02250 intern2.idb_ptr = (genptr_t)pg;
02251 rt_functab[tp->l.stp->st_id].ft_free( tp->l.stp );
02252 tp->l.stp->st_specific = NULL;
02253 tp->l.stp->st_id = ID_POLY;
02254 VSETALL( tp->l.stp->st_max, -INFINITY );
02255 VSETALL( tp->l.stp->st_min, INFINITY );
02256 if (rt_functab[ID_POLY].ft_prep( tp->l.stp, &intern2, dgcdp->rtip ) < 0 )
02257 {
02258 Tcl_AppendResult(dgcdp->interp, "Prep failure for polysolid version of solid '", tp->l.stp->st_dp->d_namep,
02259 "'\n", (char *)NULL );
02260 }
02261
02262 rt_db_free_internal( &intern2, &rt_uniresource );
02263 }
02264 }
02265 }
02266
02267 int
02268 dgo_E_cmd(struct dg_obj *dgop,
02269 Tcl_Interp *interp,
02270 int argc,
02271 char **argv)
02272 {
02273 register int c;
02274 char perf_message[128];
02275 struct dg_client_data *dgcdp;
02276
02277 if (argc < 2) {
02278 struct bu_vls vls;
02279
02280 bu_vls_init(&vls);
02281 bu_vls_printf(&vls, "help E");
02282 Tcl_Eval(interp, bu_vls_addr(&vls));
02283 bu_vls_free(&vls);
02284 return TCL_ERROR;
02285 }
02286
02287 if (bu_debug&BU_DEBUG_MEM_CHECK && bu_mem_barriercheck())
02288 bu_log("Error at start of 'E'\n");
02289
02290 BU_GETSTRUCT(dgcdp, dg_client_data);
02291 dgcdp->dgop = dgop;
02292 dgcdp->interp = interp;
02293 dgcdp->do_polysolids = 0;
02294 dgcdp->wireframe_color_override = 0;
02295
02296
02297 bu_optind = 1;
02298 while((c=bu_getopt(argc,argv,"sC:")) != EOF) {
02299 switch (c) {
02300 case 'C':
02301 {
02302 int r,g,b;
02303 register char *cp = bu_optarg;
02304
02305 r = atoi(cp);
02306 while((*cp >= '0' && *cp <= '9')) cp++;
02307 while(*cp && (*cp < '0' || *cp > '9')) cp++;
02308 g = atoi(cp);
02309 while((*cp >= '0' && *cp <= '9')) cp++;
02310 while(*cp && (*cp < '0' || *cp > '9')) cp++;
02311 b = atoi(cp);
02312
02313 if (r < 0 || r > 255) r = 255;
02314 if (g < 0 || g > 255) g = 255;
02315 if (b < 0 || b > 255) b = 255;
02316
02317 dgcdp->wireframe_color_override = 1;
02318 dgcdp->wireframe_color[0] = r;
02319 dgcdp->wireframe_color[1] = g;
02320 dgcdp->wireframe_color[2] = b;
02321 }
02322 break;
02323 case 's':
02324 dgcdp->do_polysolids = 1;
02325 break;
02326 default:
02327 {
02328 struct bu_vls vls;
02329
02330 bu_vls_init(&vls);
02331 bu_vls_printf(&vls, "help %s", argv[0]);
02332 Tcl_Eval(interp, bu_vls_addr(&vls));
02333 bu_vls_free(&vls);
02334
02335 return TCL_ERROR;
02336 }
02337 }
02338 }
02339 argc -= bu_optind;
02340 argv += bu_optind;
02341
02342 dgo_eraseobjpath(dgop, interp, argc, argv, LOOKUP_QUIET, 0);
02343
02344 #if 0
02345 dgop->dgo_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC;
02346 dgop->dgo_wdbp->wdb_ttol.rel = 0.01;
02347 #endif
02348
02349 dgcdp->ap = (struct application *)bu_malloc(sizeof(struct application), "Big E app");
02350 RT_APPLICATION_INIT(dgcdp->ap);
02351 dgcdp->ap->a_resource = &rt_uniresource;
02352 rt_uniresource.re_magic = RESOURCE_MAGIC;
02353 if( BU_LIST_UNINITIALIZED( &rt_uniresource.re_nmgfree ) )
02354 BU_LIST_INIT( &rt_uniresource.re_nmgfree );
02355
02356 bu_ptbl_init( &dgcdp->leaf_list, 8, "leaf_list" );
02357
02358 dgcdp->rtip = rt_new_rti( dgop->dgo_wdbp->dbip );
02359 dgcdp->rtip->rti_tol = dgop->dgo_wdbp->wdb_tol;
02360 dgcdp->rtip->useair = 1;
02361 dgcdp->ap->a_rt_i = dgcdp->rtip;
02362
02363 dgcdp->nvectors = 0;
02364 (void)time( &dgcdp->start_time );
02365
02366 if( rt_gettrees( dgcdp->rtip, argc, (const char **)argv, 1 ) )
02367 {
02368 bu_ptbl_free( &dgcdp->leaf_list );
02369
02370
02371 rt_clean( dgcdp->rtip );
02372
02373 bu_free( (char *)dgcdp->rtip, "rt_i structure for 'E'" );
02374 bu_free(dgcdp, "dgcdp");
02375
02376 Tcl_AppendResult(interp, "Failed to get objects\n", (char *)NULL);
02377 return TCL_ERROR;
02378 }
02379 {
02380 struct region *rp;
02381 union E_tree *eptr;
02382 struct bu_list vhead;
02383 struct db_tree_state ts;
02384 struct db_full_path path;
02385
02386 BU_LIST_INIT( &vhead );
02387
02388 for( BU_LIST_FOR( rp, region, &(dgcdp->rtip->HeadRegion) ) ) {
02389 dgcdp->num_halfs = 0;
02390 eptr = build_etree( rp->reg_treetop, dgcdp );
02391
02392 if( dgcdp->num_halfs )
02393 fix_halfs(dgcdp);
02394
02395 Eplot( eptr, &vhead, dgcdp );
02396 free_etree( eptr, dgcdp );
02397 bu_ptbl_reset( &dgcdp->leaf_list );
02398 ts.ts_mater = rp->reg_mater;
02399 db_string_to_path( &path, dgop->dgo_wdbp->dbip, rp->reg_name );
02400 dgo_drawH_part2( 0, &vhead, &path, &ts, SOLID_NULL, dgcdp );
02401 db_free_full_path( &path );
02402 }
02403
02404 rt_clean( dgcdp->rtip );
02405
02406 bu_free( (char *)dgcdp->rtip, "rt_i structure for 'E'" );
02407 }
02408
02409 dgo_color_soltab(&dgop->dgo_headSolid);
02410 (void)time( &dgcdp->etime );
02411
02412
02413 bu_ptbl_free( &dgcdp->leaf_list );
02414
02415 sprintf(perf_message, "E: %ld vectors in %ld sec\n", dgcdp->nvectors, (long)(dgcdp->etime - dgcdp->start_time) );
02416 Tcl_AppendResult(interp, perf_message, (char *)NULL);
02417
02418 return TCL_OK;
02419 }
02420
02421
02422
02423
02424
02425
02426
02427
02428 int
02429 dgo_E_tcl(ClientData clientData,
02430 Tcl_Interp *interp,
02431 int argc,
02432 char **argv)
02433 {
02434 struct dg_obj *dgop = (struct dg_obj *)clientData;
02435
02436 return dgo_E_cmd(dgop, interp, argc-1, argv+1);
02437 }
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447