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 RCSnmg_eval[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_eval.c,v 14.12 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00042 #endif
00043
00044 #include "common.h"
00045
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <math.h>
00049
00050 #include "machine.h"
00051 #include "vmath.h"
00052 #include "nmg.h"
00053 #include "raytrace.h"
00054
00055
00056 struct nmg_bool_state {
00057 struct shell *bs_dest;
00058 struct shell *bs_src;
00059 int bs_isA;
00060 long **bs_classtab;
00061 const int *bs_actions;
00062 const struct bn_tol *bs_tol;
00063 };
00064
00065 static void nmg_eval_shell BU_ARGS( (struct shell *s,
00066 struct nmg_bool_state *bs));
00067 static void nmg_eval_plot BU_ARGS( (struct nmg_bool_state *bs,
00068 int num, int delay));
00069
00070
00071 #define BACTION_KILL 1
00072 #define BACTION_RETAIN 2
00073 #define BACTION_RETAIN_AND_FLIP 3
00074
00075 static const char *nmg_baction_names[] = {
00076 "*undefined 0*",
00077 "BACTION_KILL",
00078 "BACTION_RETAIN",
00079 "BACTION_RETAIN_AND_FLIP",
00080 "*undefined 4*"
00081 };
00082
00083 #define NMG_CLASS_BAD 8
00084 static const char *nmg_class_names[] = {
00085 "onAinB",
00086 "onAonBshared",
00087 "onAonBanti",
00088 "onAoutB",
00089 "inAonB",
00090 "onAonBshared",
00091 "onAonBanti",
00092 "outAonB",
00093 "*BAD*CLASS*"
00094 };
00095
00096
00097
00098
00099
00100
00101
00102 void
00103 nmg_ck_lu_orientation(struct loopuse *lu, const struct bn_tol *tolp)
00104 {
00105 struct faceuse *fu;
00106 plane_t fu_peqn;
00107 plane_t lu_peqn;
00108 fastf_t dot;
00109
00110 NMG_CK_LOOPUSE(lu);
00111 fu = lu->up.fu_p;
00112 NMG_CK_FACEUSE(fu);
00113
00114 NMG_GET_FU_PLANE( fu_peqn, fu );
00115 nmg_loop_plane_newell( lu, lu_peqn );
00116
00117 dot = VDOT( fu_peqn, lu_peqn );
00118
00119 if( dot == 0.0 )
00120 return;
00121
00122
00123 if( dot < 0.0 )
00124 {
00125 bu_log("nmg_ck_lu_orientation() lu=x%x, dot=%g, fu_orient=%s, lu_orient=%s\n", lu,
00126 dot,
00127 nmg_orientation(fu->orientation),
00128 nmg_orientation(lu->orientation)
00129 );
00130 rt_bomb("nmg_ck_lu_orientation() loop orientation flags do not match geometry\n");
00131 }
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 const char *
00141 nmg_class_name(int class)
00142 {
00143 if( class == NMG_CLASS_Unknown ) return "Unknown";
00144 if( class < 0 || class > NMG_CLASS_BAD ) class = NMG_CLASS_BAD;
00145 return nmg_class_names[class];
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static const int subtraction_actions[8] = {
00159 BACTION_KILL,
00160 BACTION_KILL,
00161 BACTION_RETAIN,
00162 BACTION_RETAIN,
00163
00164 BACTION_RETAIN,
00165 BACTION_KILL,
00166 BACTION_KILL,
00167 BACTION_KILL
00168 };
00169
00170 static const int union_actions[8] = {
00171 BACTION_KILL,
00172 BACTION_RETAIN,
00173 BACTION_KILL,
00174 BACTION_RETAIN,
00175
00176 BACTION_KILL,
00177 BACTION_KILL,
00178 BACTION_KILL,
00179 BACTION_RETAIN
00180 };
00181
00182 static const int intersect_actions[8] = {
00183 BACTION_RETAIN,
00184 BACTION_RETAIN,
00185 BACTION_KILL,
00186 BACTION_KILL,
00187
00188 BACTION_RETAIN,
00189 BACTION_KILL,
00190 BACTION_KILL,
00191 BACTION_KILL
00192 };
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void
00208 nmg_evaluate_boolean(struct shell *sA, struct shell *sB, int op, long int **classlist, const struct bn_tol *tol)
00209 {
00210 int const *actions;
00211 struct nmg_bool_state bool_state;
00212
00213 NMG_CK_SHELL(sA);
00214 NMG_CK_SHELL(sB);
00215 BN_CK_TOL(tol);
00216
00217 if (rt_g.NMG_debug & DEBUG_BOOLEVAL) {
00218 bu_log("nmg_evaluate_boolean(sA=x%x, sB=x%x, op=%d) START\n",
00219 sA, sB, op );
00220 }
00221
00222 switch( op ) {
00223 case NMG_BOOL_SUB:
00224 actions = subtraction_actions;
00225 nmg_invert_shell(sB, tol);
00226 break;
00227 case NMG_BOOL_ADD:
00228 actions = union_actions;
00229 break;
00230 case NMG_BOOL_ISECT:
00231 actions = intersect_actions;
00232 break;
00233 default:
00234 actions = union_actions;
00235 bu_log("ERROR nmg_evaluate_boolean() op=%d.\n", op);
00236 rt_bomb("bad boolean\n");
00237 }
00238
00239 bool_state.bs_dest = sA;
00240 bool_state.bs_src = sB;
00241 bool_state.bs_classtab = classlist;
00242 bool_state.bs_actions = actions;
00243 bool_state.bs_tol = tol;
00244
00245 bool_state.bs_isA = 1;
00246 nmg_eval_shell( sA, &bool_state );
00247
00248 bool_state.bs_isA = 0;
00249 nmg_eval_shell( sB, &bool_state );
00250
00251 if (rt_g.NMG_debug & DEBUG_BOOLEVAL) {
00252 bu_log("nmg_evaluate_boolean(sA=x%x, sB=x%x, op=%d), evaluations done\n",
00253 sA, sB, op );
00254 }
00255
00256
00257
00258 nmg_js( sA, sB, tol );
00259
00260
00261 if (rt_g.NMG_debug & DEBUG_BOOLEVAL && rt_g.NMG_debug & DEBUG_PLOTEM) {
00262 FILE *fp;
00263
00264 if ((fp=fopen("bool_ans.pl", "w")) == (FILE *)NULL) {
00265 (void)perror("bool_ans.pl");
00266 bu_bomb("unable to open bool_ans.pl for writing");
00267 }
00268 bu_log("plotting bool_ans.pl\n");
00269 nmg_pl_s( fp, sA );
00270 (void)fclose(fp);
00271 }
00272
00273
00274 nmg_rm_redundancies( sA, tol );
00275
00276 if (rt_g.NMG_debug & DEBUG_BOOLEVAL) {
00277 bu_log("nmg_evaluate_boolean(sA=x%x, sB=x%x, op=%d) END\n",
00278 sA, sB, op );
00279 }
00280 }
00281
00282 static int nmg_eval_count = 0;
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 int
00293 nmg_eval_action(long int *ptr, register struct nmg_bool_state *bs)
00294 {
00295 register int ret;
00296 register int class;
00297 int index;
00298
00299 BN_CK_TOL(bs->bs_tol);
00300
00301 index = nmg_index_of_struct(ptr);
00302 if( bs->bs_isA ) {
00303 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_AinB], index) ) {
00304 class = NMG_CLASS_AinB;
00305 ret = bs->bs_actions[NMG_CLASS_AinB];
00306 goto out;
00307 }
00308 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_AonBshared], index) ) {
00309 class = NMG_CLASS_AonBshared;
00310 ret = bs->bs_actions[NMG_CLASS_AonBshared];
00311 goto out;
00312 }
00313 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_AonBanti], index) ) {
00314 class = NMG_CLASS_AonBanti;
00315 ret = bs->bs_actions[NMG_CLASS_AonBanti];
00316 goto out;
00317 }
00318 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_AoutB], index) ) {
00319 class = NMG_CLASS_AoutB;
00320 ret = bs->bs_actions[NMG_CLASS_AoutB];
00321 goto out;
00322 }
00323 bu_log("nmg_eval_action(ptr=x%x) %s has no A classification, retaining\n",
00324 ptr, bu_identify_magic( *((long *)ptr) ) );
00325 class = NMG_CLASS_BAD;
00326 ret = BACTION_RETAIN;
00327 goto out;
00328 }
00329
00330
00331 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_BinA], index) ) {
00332 class = NMG_CLASS_BinA;
00333 ret = bs->bs_actions[NMG_CLASS_BinA];
00334 goto out;
00335 }
00336 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_BonAshared], index) ) {
00337 class = NMG_CLASS_BonAshared;
00338 ret = bs->bs_actions[NMG_CLASS_BonAshared];
00339 goto out;
00340 }
00341 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_BonAanti], index) ) {
00342 class = NMG_CLASS_BonAanti;
00343 ret = bs->bs_actions[NMG_CLASS_BonAanti];
00344 goto out;
00345 }
00346 if( NMG_INDEX_VALUE(bs->bs_classtab[NMG_CLASS_BoutA], index) ) {
00347 class = NMG_CLASS_BoutA;
00348 ret = bs->bs_actions[NMG_CLASS_BoutA];
00349 goto out;
00350 }
00351 bu_log("nmg_eval_action(ptr=x%x) %s has no B classification, retaining\n",
00352 ptr, bu_identify_magic( *((long *)ptr) ) );
00353 class = NMG_CLASS_BAD;
00354 ret = BACTION_RETAIN;
00355 out:
00356 if (rt_g.NMG_debug & DEBUG_BOOLEVAL) {
00357 bu_log("nmg_eval_action(ptr=x%x) index=%d %s %s %s %s\n",
00358 ptr, index,
00359 bs->bs_isA ? "A" : "B",
00360 bu_identify_magic( *((long *)ptr) ),
00361 nmg_class_name(class),
00362 nmg_baction_names[ret] );
00363 }
00364 return(ret);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static void
00377 nmg_eval_shell(register struct shell *s, struct nmg_bool_state *bs)
00378 {
00379 struct faceuse *fu;
00380 struct faceuse *nextfu;
00381 struct loopuse *lu;
00382 struct loopuse *nextlu;
00383 struct edgeuse *eu;
00384 struct edgeuse *nexteu;
00385 struct vertexuse *vu;
00386 int loops_retained;
00387
00388 NMG_CK_SHELL(s);
00389 BN_CK_TOL(bs->bs_tol);
00390
00391 if( rt_g.NMG_debug & DEBUG_VERIFY )
00392 nmg_vshell( &s->r_p->s_hd, s->r_p );
00393
00394
00395
00396
00397
00398 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00399 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
00400 while( BU_LIST_NOT_HEAD( fu, &s->fu_hd ) ) {
00401 NMG_CK_FACEUSE(fu);
00402 nextfu = BU_LIST_PNEXT( faceuse, fu );
00403
00404
00405 if( fu->orientation != OT_SAME ) {
00406 fu = nextfu;
00407 continue;
00408 }
00409 if( fu->fumate_p == nextfu )
00410 nextfu = BU_LIST_PNEXT( faceuse, nextfu );
00411
00412
00413 NMG_CK_FACE(fu->f_p);
00414
00415 loops_retained = 0;
00416 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
00417 while( BU_LIST_NOT_HEAD( lu, &fu->lu_hd ) ) {
00418 NMG_CK_LOOPUSE(lu);
00419 nextlu = BU_LIST_PNEXT( loopuse, lu );
00420 if( lu->lumate_p == nextlu )
00421 nextlu = BU_LIST_PNEXT( loopuse, nextlu );
00422
00423 NMG_CK_LOOP( lu->l_p );
00424 #if 0
00425 if (rt_g.NMG_debug & DEBUG_BOOLEVAL)
00426 #endif
00427 {
00428 nmg_ck_lu_orientation( lu, bs->bs_tol );
00429 }
00430 switch( nmg_eval_action( &lu->l_p->magic, bs ) ) {
00431 case BACTION_KILL:
00432
00433 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC ) {
00434
00435 (void)nmg_klu( lu );
00436 } else if( nmg_demote_lu( lu ) == 0 ) {
00437 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00438 }
00439 lu = nextlu;
00440 continue;
00441 case BACTION_RETAIN:
00442 loops_retained++;
00443 break;
00444 default:
00445 rt_bomb("nmg_eval_shell() bad BACTION\n");
00446 }
00447 lu = nextlu;
00448 }
00449
00450 if (rt_g.NMG_debug & DEBUG_BOOLEVAL)
00451 bu_log("faceuse x%x loops retained=%d\n",
00452 fu, loops_retained);
00453 if( rt_g.NMG_debug & DEBUG_VERIFY )
00454 nmg_vshell( &s->r_p->s_hd, s->r_p );
00455
00456
00457
00458
00459
00460
00461 if( BU_LIST_IS_EMPTY( &fu->lu_hd ) ) {
00462 if( loops_retained ) rt_bomb("nmg_eval_shell() empty faceuse with retained loops?\n");
00463
00464 if (rt_g.NMG_debug & DEBUG_BOOLEVAL)
00465 bu_log("faceuse x%x empty, kill\n", fu);
00466 nmg_kfu( fu );
00467 if( rt_g.NMG_debug & DEBUG_VERIFY )
00468 nmg_vshell( &s->r_p->s_hd, s->r_p );
00469 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00470 fu = nextfu;
00471 continue;
00472 }
00473
00474 if( loops_retained <= 0 ) {
00475 nmg_pr_fu(fu, (char *)NULL);
00476 rt_bomb("nmg_eval_shell() non-empty faceuse, no loops retained?\n");
00477 }
00478 fu = nextfu;
00479 }
00480 if( rt_g.NMG_debug & DEBUG_VERIFY )
00481 nmg_vshell( &s->r_p->s_hd, s->r_p );
00482
00483
00484
00485
00486
00487
00488 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00489 lu = BU_LIST_FIRST( loopuse, &s->lu_hd );
00490 while( BU_LIST_NOT_HEAD( lu, &s->lu_hd ) ) {
00491 NMG_CK_LOOPUSE(lu);
00492 nextlu = BU_LIST_PNEXT( loopuse, lu );
00493 if( lu->lumate_p == nextlu )
00494 nextlu = BU_LIST_PNEXT( loopuse, nextlu );
00495
00496 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC ) {
00497
00498 lu = nextlu;
00499 continue;
00500 }
00501 NMG_CK_LOOP( lu->l_p );
00502 switch( nmg_eval_action( &lu->l_p->magic, bs ) ) {
00503 case BACTION_KILL:
00504
00505
00506 if( nmg_demote_lu( lu ) == 0 )
00507 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00508 lu = nextlu;
00509 continue;
00510 case BACTION_RETAIN:
00511 break;
00512 default:
00513 rt_bomb("nmg_eval_shell() bad BACTION\n");
00514 }
00515 lu = nextlu;
00516 }
00517 if( rt_g.NMG_debug & DEBUG_VERIFY )
00518 nmg_vshell( &s->r_p->s_hd, s->r_p );
00519
00520
00521
00522
00523 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00524 eu = BU_LIST_FIRST( edgeuse, &s->eu_hd );
00525 while( BU_LIST_NOT_HEAD( eu, &s->eu_hd ) ) {
00526 NMG_CK_EDGEUSE(eu);
00527 nexteu = BU_LIST_PNEXT( edgeuse, eu );
00528 if( eu->eumate_p == nexteu )
00529 nexteu = BU_LIST_PNEXT( edgeuse, nexteu );
00530
00531
00532 NMG_CK_EDGE( eu->e_p );
00533 switch( nmg_eval_action( &eu->e_p->magic, bs ) ) {
00534 case BACTION_KILL:
00535
00536 if( nmg_demote_eu( eu ) == 0 )
00537 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00538 eu = nexteu;
00539 continue;
00540 case BACTION_RETAIN:
00541 break;
00542 default:
00543 rt_bomb("nmg_eval_shell() bad BACTION\n");
00544 }
00545 eu = nexteu;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00561 lu = BU_LIST_FIRST( loopuse, &s->lu_hd );
00562 while( BU_LIST_NOT_HEAD( lu, &s->lu_hd ) ) {
00563 NMG_CK_LOOPUSE(lu);
00564 nextlu = BU_LIST_PNEXT( loopuse, lu );
00565
00566 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_VERTEXUSE_MAGIC ) {
00567
00568 lu = nextlu;
00569 continue;
00570 }
00571 if( nextlu == lu->lumate_p )
00572 nextlu = BU_LIST_PNEXT(loopuse, nextlu);
00573 vu = BU_LIST_PNEXT( vertexuse, &lu->down_hd );
00574 NMG_CK_VERTEXUSE( vu );
00575 NMG_CK_VERTEX( vu->v_p );
00576 switch( nmg_eval_action( &vu->v_p->magic, bs ) ) {
00577 case BACTION_KILL:
00578
00579 nmg_klu( lu );
00580 lu = nextlu;
00581 continue;
00582 case BACTION_RETAIN:
00583 break;
00584 default:
00585 rt_bomb("nmg_eval_shell() bad BACTION\n");
00586 }
00587 lu = nextlu;
00588 }
00589 if( rt_g.NMG_debug & DEBUG_VERIFY )
00590 nmg_vshell( &s->r_p->s_hd, s->r_p );
00591
00592
00593
00594
00595 if( (vu = s->vu_p) ) {
00596 NMG_CK_VERTEXUSE( vu );
00597 NMG_CK_VERTEX( vu->v_p );
00598 switch( nmg_eval_action( &vu->v_p->magic, bs ) ) {
00599 case BACTION_KILL:
00600 nmg_kvu( vu );
00601 nmg_eval_plot( bs, nmg_eval_count++, 0 );
00602 s->vu_p = (struct vertexuse *)0;
00603 break;
00604 case BACTION_RETAIN:
00605 break;
00606 default:
00607 rt_bomb("nmg_eval_shell() bad BACTION\n");
00608 }
00609 }
00610 if( rt_g.NMG_debug & DEBUG_VERIFY )
00611 nmg_vshell( &s->r_p->s_hd, s->r_p );
00612 nmg_eval_plot( bs, nmg_eval_count++, 1 );
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 static void
00624 nmg_eval_plot(struct nmg_bool_state *bs, int num, int delay)
00625 {
00626 FILE *fp;
00627 char fname[128];
00628 int do_plot = 0;
00629 int do_anim = 0;
00630
00631 if (rt_g.NMG_debug & DEBUG_BOOLEVAL && rt_g.NMG_debug & DEBUG_PLOTEM)
00632 do_plot = 1;
00633 if( rt_g.NMG_debug & DEBUG_PL_ANIM ) do_anim = 1;
00634
00635 if( !do_plot && !do_anim ) return;
00636
00637 BN_CK_TOL(bs->bs_tol);
00638
00639 if( do_plot ) {
00640 sprintf(fname, "nmg_eval%d.pl", num);
00641 if( (fp = fopen(fname,"w")) == NULL ) {
00642 perror(fname);
00643 return;
00644 }
00645 bu_log("Plotting %s\n", fname);
00646
00647 nmg_pl_s( fp, bs->bs_dest );
00648 nmg_pl_s( fp, bs->bs_src );
00649
00650 fclose(fp);
00651 }
00652
00653 if( do_anim ) {
00654 extern void (*nmg_vlblock_anim_upcall)();
00655 struct bn_vlblock *vbp;
00656
00657 vbp = rt_vlblock_init();
00658
00659 nmg_vlblock_s( vbp, bs->bs_dest, 0 );
00660 nmg_vlblock_s( vbp, bs->bs_src, 0 );
00661
00662
00663 if( nmg_vlblock_anim_upcall ) {
00664
00665 (*nmg_vlblock_anim_upcall)( vbp,
00666 (rt_g.NMG_debug&DEBUG_PL_SLOW) ? 250000 : 0,
00667 0 );
00668 } else {
00669 bu_log("null nmg_vlblock_anim_upcall, no animation\n");
00670 }
00671 rt_vlblock_free(vbp);
00672 }
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683