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 #ifndef lint
00040 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_info.c,v 14.14 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00041 #endif
00042
00043 #include "common.h"
00044
00045 #include <stdlib.h>
00046 #include <stddef.h>
00047 #include <stdio.h>
00048 #ifdef HAVE_STRING_H
00049 # include <string.h>
00050 #else
00051 # include <strings.h>
00052 #endif
00053 #include <math.h>
00054
00055 #include "machine.h"
00056 #include "vmath.h"
00057 #include "nmg.h"
00058 #include "raytrace.h"
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 struct model *
00076 nmg_find_model(const long int *magic_p_arg)
00077 {
00078 register const long *magic_p = magic_p_arg;
00079
00080 top:
00081 if( magic_p == (long *)0 ) {
00082 bu_log("nmg_find_model(x%x) enountered null pointer\n",
00083 magic_p_arg );
00084 rt_bomb("nmg_find_model() null pointer\n");
00085
00086 }
00087
00088 switch( *magic_p ) {
00089 case NMG_MODEL_MAGIC:
00090 return( (struct model *)magic_p );
00091 case NMG_REGION_MAGIC:
00092 return( ((struct nmgregion *)magic_p)->m_p );
00093 case NMG_SHELL_MAGIC:
00094 return( ((struct shell *)magic_p)->r_p->m_p );
00095 case NMG_FACEUSE_MAGIC:
00096 magic_p = &((struct faceuse *)magic_p)->s_p->l.magic;
00097 goto top;
00098 case NMG_FACE_MAGIC:
00099 magic_p = &((struct face *)magic_p)->fu_p->l.magic;
00100 goto top;
00101 case NMG_LOOP_MAGIC:
00102 magic_p = ((struct loop *)magic_p)->lu_p->up.magic_p;
00103 goto top;
00104 case NMG_LOOPUSE_MAGIC:
00105 magic_p = ((struct loopuse *)magic_p)->up.magic_p;
00106 goto top;
00107 case NMG_EDGE_MAGIC:
00108 magic_p = ((struct edge *)magic_p)->eu_p->up.magic_p;
00109 goto top;
00110 case NMG_EDGEUSE_MAGIC:
00111 magic_p = ((struct edgeuse *)magic_p)->up.magic_p;
00112 goto top;
00113 case NMG_VERTEX_MAGIC:
00114 magic_p = &(BU_LIST_FIRST(vertexuse,
00115 &((struct vertex *)magic_p)->vu_hd)->l.magic);
00116 goto top;
00117 case NMG_VERTEXUSE_MAGIC:
00118 magic_p = ((struct vertexuse *)magic_p)->up.magic_p;
00119 goto top;
00120
00121 default:
00122 bu_log("nmg_find_model() can't get model for magic=x%x (%s)\n",
00123 *magic_p, bu_identify_magic( *magic_p ) );
00124 rt_bomb("nmg_find_model() failure\n");
00125 }
00126 return( (struct model *)NULL );
00127 }
00128
00129 void
00130 nmg_model_bb(fastf_t *min_pt, fastf_t *max_pt, const struct model *m)
00131 {
00132 struct nmgregion *r;
00133 register int i;
00134
00135 NMG_CK_MODEL(m);
00136
00137 min_pt[0] = min_pt[1] = min_pt[2] = MAX_FASTF;
00138 max_pt[0] = max_pt[1] = max_pt[2] = -MAX_FASTF;
00139
00140 for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
00141 NMG_CK_REGION(r);
00142 NMG_CK_REGION_A(r->ra_p);
00143
00144 for (i=0 ; i < 3 ; i++) {
00145 if (min_pt[i] > r->ra_p->min_pt[i])
00146 min_pt[i] = r->ra_p->min_pt[i];
00147 if (max_pt[i] < r->ra_p->max_pt[i])
00148 max_pt[i] = r->ra_p->max_pt[i];
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int
00171 nmg_shell_is_empty(register const struct shell *s)
00172 {
00173
00174 NMG_CK_SHELL(s);
00175
00176 if( BU_LIST_NON_EMPTY( &s->fu_hd ) ) return 0;
00177 if( BU_LIST_NON_EMPTY( &s->lu_hd ) ) return 0;
00178 if( BU_LIST_NON_EMPTY( &s->eu_hd ) ) return 0;
00179 if( s->vu_p ) return 0;
00180 return 1;
00181 }
00182
00183
00184
00185
00186
00187
00188 struct shell *
00189 nmg_find_s_of_lu(const struct loopuse *lu)
00190 {
00191 if (*lu->up.magic_p == NMG_SHELL_MAGIC) return(lu->up.s_p);
00192 else if (*lu->up.magic_p != NMG_FACEUSE_MAGIC)
00193 rt_bomb("nmg_find_s_of_lu() bad parent for loopuse\n");
00194
00195 return(lu->up.fu_p->s_p);
00196 }
00197
00198
00199
00200
00201
00202
00203 struct shell *
00204 nmg_find_s_of_eu(const struct edgeuse *eu)
00205 {
00206 if (*eu->up.magic_p == NMG_SHELL_MAGIC) return(eu->up.s_p);
00207 else if (*eu->up.magic_p != NMG_LOOPUSE_MAGIC)
00208 rt_bomb("nmg_find_s_of_eu() bad parent for edgeuse\n");
00209
00210 return(nmg_find_s_of_lu(eu->up.lu_p));
00211 }
00212
00213
00214
00215
00216
00217
00218 struct shell *
00219 nmg_find_s_of_vu(const struct vertexuse *vu)
00220 {
00221 NMG_CK_VERTEXUSE(vu);
00222
00223 if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC )
00224 return nmg_find_s_of_lu( vu->up.lu_p );
00225 return nmg_find_s_of_eu( vu->up.eu_p );
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 struct faceuse *
00241 nmg_find_fu_of_eu(const struct edgeuse *eu)
00242 {
00243 NMG_CK_EDGEUSE(eu);
00244
00245 if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
00246 *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC)
00247 return eu->up.lu_p->up.fu_p;
00248
00249 return (struct faceuse *)NULL;
00250 }
00251
00252
00253
00254
00255 struct faceuse *
00256 nmg_find_fu_of_lu(const struct loopuse *lu)
00257 {
00258 switch (*lu->up.magic_p) {
00259 case NMG_FACEUSE_MAGIC:
00260 return lu->up.fu_p;
00261 case NMG_SHELL_MAGIC:
00262 return (struct faceuse *)NULL;
00263 default:
00264 bu_log("Error at %s %d:\nInvalid loopuse parent magic (0x%x %d)\n",
00265 __FILE__, __LINE__, *lu->up.magic_p, *lu->up.magic_p);
00266 rt_bomb("nmg_find_fu_of_lu() giving up on loopuse");
00267 }
00268 return (struct faceuse *)NULL;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 struct faceuse *
00278 nmg_find_fu_of_vu(const struct vertexuse *vu)
00279 {
00280 NMG_CK_VERTEXUSE(vu);
00281
00282 switch (*vu->up.magic_p) {
00283 case NMG_LOOPUSE_MAGIC:
00284 return nmg_find_fu_of_lu( vu->up.lu_p );
00285 case NMG_SHELL_MAGIC:
00286 if (rt_g.NMG_debug & DEBUG_BASIC) bu_log("nmg_find_fu_of_vu(vu=x%x) vertexuse is child of shell, can't find faceuse\n", vu);
00287 return ((struct faceuse *)NULL);
00288 case NMG_EDGEUSE_MAGIC:
00289 switch (*vu->up.eu_p->up.magic_p) {
00290 case NMG_LOOPUSE_MAGIC:
00291 return nmg_find_fu_of_lu( vu->up.eu_p->up.lu_p );
00292 case NMG_SHELL_MAGIC:
00293 if (rt_g.NMG_debug & DEBUG_BASIC) bu_log("nmg_find_fu_of_vu(vu=x%x) vertexuse is child of shell/edgeuse, can't find faceuse\n", vu);
00294 return ((struct faceuse *)NULL);
00295 }
00296 bu_log("Error at %s %d:\nInvalid loopuse parent magic 0x%x\n",
00297 __FILE__, __LINE__, *vu->up.lu_p->up.magic_p);
00298 abort();
00299 break;
00300 default:
00301 bu_log("Error at %s %d:\nInvalid vertexuse parent magic 0x%x\n",
00302 __FILE__, __LINE__,
00303 *vu->up.magic_p);
00304 abort();
00305 break;
00306 }
00307 bu_log("How did I get here %s %d?\n", __FILE__, __LINE__);
00308 rt_bomb("nmg_find_fu_of_vu()\n");
00309 return ((struct faceuse *)NULL);
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 struct faceuse *
00321 nmg_find_fu_with_fg_in_s(const struct shell *s1, const struct faceuse *fu2)
00322 {
00323 struct faceuse *fu1;
00324 struct face *f2;
00325 register struct face_g_plane *fg2;
00326
00327 NMG_CK_SHELL(s1);
00328 NMG_CK_FACEUSE(fu2);
00329
00330 f2 = fu2->f_p;
00331 NMG_CK_FACE(f2);
00332 fg2 = f2->g.plane_p;
00333 NMG_CK_FACE_G_PLANE(fg2);
00334
00335 for( BU_LIST_FOR( fu1, faceuse, &s1->fu_hd ) ) {
00336 register struct face *f1;
00337 register struct face_g_plane *fg1;
00338 int flip1, flip2;
00339
00340 NMG_CK_FACEUSE(fu1);
00341 f1 = fu1->f_p;
00342 NMG_CK_FACE(f1);
00343 fg1 = fu1->f_p->g.plane_p;
00344 NMG_CK_FACE_G_PLANE(fg1);
00345
00346 if( fg1 != fg2 ) continue;
00347
00348 if( fu1 == fu2 || fu1->fumate_p == fu2 ) continue;
00349
00350
00351 flip1 = (fu1->orientation != OT_SAME) != (f1->flip != 0);
00352 flip2 = (fu2->orientation != OT_SAME) != (f2->flip != 0);
00353 if( flip1 == flip2 ) return fu1;
00354 return fu1->fumate_p;
00355 }
00356 return (struct faceuse *)NULL;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 double
00375 nmg_measure_fu_angle(const struct edgeuse *eu, const fastf_t *xvec, const fastf_t *yvec, const fastf_t *zvec)
00376 {
00377 vect_t left;
00378 double ret;
00379
00380 NMG_CK_EDGEUSE(eu);
00381 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC ) return -bn_pi;
00382
00383 if( nmg_find_eu_leftvec( left, eu ) < 0 ) return -bn_pi;
00384
00385 ret = bn_angle_measure( left, xvec, yvec );
00386 return ret;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 struct loopuse *
00399 nmg_find_lu_of_vu(const struct vertexuse *vu)
00400 {
00401 NMG_CK_VERTEXUSE( vu );
00402 if ( *vu->up.magic_p == NMG_LOOPUSE_MAGIC )
00403 return vu->up.lu_p;
00404
00405 if ( *vu->up.magic_p == NMG_SHELL_MAGIC )
00406 return (struct loopuse *)NULL;
00407
00408 NMG_CK_EDGEUSE( vu->up.eu_p );
00409
00410 if ( *vu->up.eu_p->up.magic_p == NMG_SHELL_MAGIC )
00411 return (struct loopuse *)NULL;
00412
00413 NMG_CK_LOOPUSE( vu->up.eu_p->up.lu_p );
00414
00415 return vu->up.eu_p->up.lu_p;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 int
00441 nmg_loop_is_a_crack(const struct loopuse *lu)
00442 {
00443 struct edgeuse *cur_eu;
00444 struct edgeuse *cur_eumate;
00445 struct vertexuse *cur_vu;
00446 struct vertex *cur_v;
00447 struct vertexuse *next_vu;
00448 struct vertex *next_v;
00449 struct faceuse *fu;
00450 struct vertexuse *test_vu;
00451 struct edgeuse *test_eu;
00452 struct loopuse *test_lu;
00453 int ret = 0;
00454
00455 NMG_CK_LOOPUSE(lu);
00456 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC ) {
00457 if (rt_g.NMG_debug & DEBUG_BASIC) bu_log("lu up is not faceuse\n");
00458 ret = 0;
00459 goto out;
00460 }
00461 fu = lu->up.fu_p;
00462 NMG_CK_FACEUSE(fu);
00463
00464 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) {
00465 if (rt_g.NMG_debug & DEBUG_BASIC) bu_log("lu down is not edgeuse\n");
00466 ret = 0;
00467 goto out;
00468 }
00469
00470
00471
00472
00473
00474 for( BU_LIST_FOR( cur_eu, edgeuse, &lu->down_hd ) ) {
00475 NMG_CK_EDGEUSE(cur_eu);
00476 cur_eumate = cur_eu->eumate_p;
00477 NMG_CK_EDGEUSE(cur_eumate);
00478 cur_vu = cur_eu->vu_p;
00479 NMG_CK_VERTEXUSE(cur_vu);
00480 cur_v = cur_vu->v_p;
00481 NMG_CK_VERTEX(cur_v);
00482
00483 next_vu = cur_eumate->vu_p;
00484 NMG_CK_VERTEXUSE(next_vu);
00485 next_v = next_vu->v_p;
00486 NMG_CK_VERTEX(next_v);
00487
00488
00489 for( BU_LIST_FOR( test_vu, vertexuse, &next_v->vu_hd ) ) {
00490 if( *test_vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
00491 test_eu = test_vu->up.eu_p;
00492 NMG_CK_EDGEUSE(test_eu);
00493 if( test_eu == cur_eu ) continue;
00494 if( test_eu == cur_eumate ) continue;
00495 if( *test_eu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
00496 test_lu = test_eu->up.lu_p;
00497 if( test_lu != lu ) continue;
00498
00499 if( test_eu->eumate_p->vu_p->v_p == cur_v ) goto match;
00500 }
00501
00502 ret = 0;
00503 goto out;
00504
00505
00506 match: ;
00507 }
00508 ret = 1;
00509 out:
00510 if (rt_g.NMG_debug & DEBUG_BASIC) {
00511 bu_log("nmg_loop_is_a_crack(lu=x%x) ret=%d\n", lu, ret );
00512 }
00513 return ret;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 int
00530 nmg_loop_is_ccw(const struct loopuse *lu, const fastf_t *norm, const struct bn_tol *tol)
00531 {
00532 fastf_t area;
00533 fastf_t dot;
00534 plane_t pl;
00535 int ret;
00536
00537 area = nmg_loop_plane_area( lu, pl );
00538
00539 if( area <= 0.0 )
00540 {
00541 if( RT_G_DEBUG & DEBUG_MATH )
00542 {
00543 bu_log( "nmg_loop_is_ccw: Loop has no area\n" );
00544 nmg_pr_lu_briefly( lu, " " );
00545 }
00546 ret = 0;
00547 goto out;
00548 }
00549
00550 if( NEAR_ZERO( area, tol->dist_sq ) )
00551 {
00552 if( RT_G_DEBUG & DEBUG_MATH )
00553 {
00554 bu_log( "nmg_loop_is_ccw: Loop area (%g) is less than tol->dist_sq (%g)\n", area, tol->dist_sq );
00555 nmg_pr_lu_briefly( lu, " " );
00556 }
00557 ret = 0;
00558 goto out;
00559 }
00560
00561 dot = VDOT( norm, pl );
00562
00563 if( NEAR_ZERO( dot, tol->perp ) )
00564 {
00565 if( RT_G_DEBUG & DEBUG_MATH )
00566 {
00567 bu_log( "nmg_loop_is_ccw: normal ( %g %g %g ) is in plane of loop ( %g %g %g %g ), dot = %g\n",
00568 V3ARGS( norm ), V4ARGS( pl ), dot );
00569 nmg_pr_lu_briefly( lu, " " );
00570 }
00571 ret = 0;
00572 goto out;
00573 }
00574
00575 if( dot < 0.0 )
00576 ret = (-1 );
00577 else
00578 ret = 1;
00579
00580 out:
00581 if (rt_g.NMG_debug & DEBUG_BASIC)
00582 bu_log( "nmg_loop_is_ccw(lu=x%x) ret=%d\n" , lu, ret );
00583
00584 return( ret );
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 const struct vertexuse *
00602 nmg_loop_touches_self(const struct loopuse *lu)
00603 {
00604 const struct edgeuse *eu;
00605 const struct vertexuse *vu;
00606 const struct vertex *v;
00607
00608 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00609 return (const struct vertexuse *)0;
00610
00611
00612 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
00613 const struct vertexuse *tvu;
00614
00615 vu = eu->vu_p;
00616 NMG_CK_VERTEXUSE(vu);
00617 v = vu->v_p;
00618 NMG_CK_VERTEX(v);
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 for( BU_LIST_FOR( tvu, vertexuse, &v->vu_hd ) ) {
00629 const struct edgeuse *teu;
00630 const struct loopuse *tlu;
00631
00632 if( tvu == vu ) continue;
00633
00634
00635
00636
00637 if( *tvu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
00638 teu = tvu->up.eu_p;
00639 NMG_CK_EDGEUSE(teu);
00640 if( *teu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
00641 tlu = teu->up.lu_p;
00642 NMG_CK_LOOPUSE(tlu);
00643 if( tlu != lu ) continue;
00644
00645
00646
00647 return vu;
00648 }
00649 }
00650 return (const struct vertexuse *)0;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 struct edgeuse *
00668 nmg_find_matching_eu_in_s(const struct edgeuse *eu1, const struct shell *s2)
00669 {
00670 const struct vertexuse *vu1a, *vu1b;
00671 struct edgeuse *eu2;
00672
00673 NMG_CK_EDGEUSE(eu1);
00674 NMG_CK_SHELL(s2);
00675
00676 vu1a = eu1->vu_p;
00677 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
00678 NMG_CK_VERTEXUSE(vu1a);
00679 NMG_CK_VERTEXUSE(vu1b);
00680 if( (nmg_find_v_in_shell( vu1a->v_p, s2, 1 )) == (struct vertexuse *)NULL )
00681 return (struct edgeuse *)NULL;
00682 if( (nmg_find_v_in_shell( vu1b->v_p, s2, 1 )) == (struct vertexuse *)NULL )
00683 return (struct edgeuse *)NULL;
00684
00685
00686
00687 eu2 = nmg_findeu( vu1a->v_p, vu1b->v_p, s2, eu1, 0 );
00688 return eu2;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 struct edgeuse *
00711 nmg_findeu(const struct vertex *v1, const struct vertex *v2, const struct shell *s, const struct edgeuse *eup, int dangling_only)
00712 {
00713 register const struct vertexuse *vu;
00714 register const struct edgeuse *eu;
00715 const struct edgeuse *eup_mate;
00716 int eup_orientation;
00717
00718 NMG_CK_VERTEX(v1);
00719 NMG_CK_VERTEX(v2);
00720 if(s) NMG_CK_SHELL(s);
00721
00722 if(eup) {
00723 struct faceuse *fu;
00724 NMG_CK_EDGEUSE(eup);
00725 eup_mate = eup->eumate_p;
00726 NMG_CK_EDGEUSE(eup_mate);
00727 if( (fu = nmg_find_fu_of_eu(eup)) )
00728 eup_orientation = fu->orientation;
00729 else
00730 eup_orientation = OT_SAME;
00731 } else {
00732 eup_mate = eup;
00733 eup_orientation = OT_SAME;
00734 }
00735
00736 if (rt_g.NMG_debug & DEBUG_FINDEU)
00737 bu_log("nmg_findeu() seeking eu!=%8x/%8x between (%8x, %8x) %s\n",
00738 eup, eup_mate, v1, v2,
00739 dangling_only ? "[dangling]" : "[any]" );
00740
00741 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) ) {
00742 NMG_CK_VERTEXUSE(vu);
00743 if (!vu->up.magic_p)
00744 rt_bomb("nmg_findeu() vertexuse in vu_hd list has null parent\n");
00745
00746
00747 if (*vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
00748 eu = vu->up.eu_p;
00749
00750
00751 if( eu->eumate_p->vu_p->v_p != v2 ) continue;
00752
00753 if (rt_g.NMG_debug & DEBUG_FINDEU ) {
00754 bu_log("nmg_findeu: check eu=%8x vertex=(%8x, %8x)\n",
00755 eu, eu->vu_p->v_p,
00756 eu->eumate_p->vu_p->v_p);
00757 }
00758
00759
00760 if( eu == eup || eu->eumate_p == eup ) {
00761 if (rt_g.NMG_debug & DEBUG_FINDEU )
00762 bu_log("\tIgnoring -- excluded edgeuse\n");
00763 continue;
00764 }
00765
00766
00767 if( s && nmg_find_s_of_eu(eu) != s ) {
00768 if (rt_g.NMG_debug & DEBUG_FINDEU)
00769 bu_log("\tIgnoring x%x -- eu in wrong shell s=%x\n", eu, eu->up.s_p);
00770 continue;
00771 }
00772
00773
00774 if( dangling_only && eu->eumate_p != eu->radial_p) {
00775 if (rt_g.NMG_debug & DEBUG_FINDEU) {
00776 bu_log("\tIgnoring %8x/%8x (radial=x%x)\n",
00777 eu, eu->eumate_p,
00778 eu->radial_p );
00779 }
00780 continue;
00781 }
00782
00783 if (rt_g.NMG_debug & DEBUG_FINDEU)
00784 bu_log("\tFound %8x/%8x\n", eu, eu->eumate_p);
00785
00786 if ( *eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
00787 *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
00788 eup_orientation != eu->up.lu_p->up.fu_p->orientation)
00789 eu = eu->eumate_p;
00790 goto out;
00791 }
00792 eu = (struct edgeuse *)NULL;
00793 out:
00794 if (rt_g.NMG_debug & (DEBUG_BASIC|DEBUG_FINDEU))
00795 bu_log("nmg_findeu() returns x%x\n", eu);
00796
00797 return (struct edgeuse *)eu;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806 struct edgeuse *
00807 nmg_find_eu_in_face(const struct vertex *v1, const struct vertex *v2, const struct faceuse *fu, const struct edgeuse *eup, int dangling_only)
00808 {
00809 register const struct vertexuse *vu;
00810 register const struct edgeuse *eu;
00811 const struct edgeuse *eup_mate;
00812 int eup_orientation;
00813
00814 NMG_CK_VERTEX(v1);
00815 NMG_CK_VERTEX(v2);
00816 if(fu) NMG_CK_FACEUSE(fu);
00817
00818 if(eup) {
00819 struct faceuse *fu;
00820 NMG_CK_EDGEUSE(eup);
00821 eup_mate = eup->eumate_p;
00822 NMG_CK_EDGEUSE(eup_mate);
00823 if( (fu = nmg_find_fu_of_eu(eup)) )
00824 eup_orientation = fu->orientation;
00825 else
00826 eup_orientation = OT_SAME;
00827 } else {
00828 eup_mate = eup;
00829 eup_orientation = OT_SAME;
00830 }
00831
00832 if (rt_g.NMG_debug & DEBUG_FINDEU)
00833 bu_log("nmg_find_eu_in_face() seeking eu!=%8x/%8x between (%8x, %8x) %s\n",
00834 eup, eup_mate, v1, v2,
00835 dangling_only ? "[dangling]" : "[any]" );
00836
00837 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) ) {
00838 NMG_CK_VERTEXUSE(vu);
00839 if (!vu->up.magic_p)
00840 rt_bomb("nmg_find_eu_in_face() vertexuse in vu_hd list has null parent\n");
00841
00842
00843 if (*vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
00844 eu = vu->up.eu_p;
00845
00846
00847 if( eu->eumate_p->vu_p->v_p != v2 ) continue;
00848
00849 if (rt_g.NMG_debug & DEBUG_FINDEU ) {
00850 bu_log("nmg_find_eu_in_face: check eu=%8x vertex=(%8x, %8x)\n",
00851 eu, eu->vu_p->v_p,
00852 eu->eumate_p->vu_p->v_p);
00853 }
00854
00855
00856 if( eu == eup || eu->eumate_p == eup ) {
00857 if (rt_g.NMG_debug & DEBUG_FINDEU )
00858 bu_log("\tIgnoring -- excluded edgeuse\n");
00859 continue;
00860 }
00861
00862
00863 if( fu && nmg_find_fu_of_eu(eu) != fu ) {
00864 if (rt_g.NMG_debug & DEBUG_FINDEU)
00865 bu_log("\tIgnoring x%x -- eu not in faceuse\n", eu);
00866 continue;
00867 }
00868
00869
00870 if( dangling_only && eu->eumate_p != eu->radial_p) {
00871 if (rt_g.NMG_debug & DEBUG_FINDEU) {
00872 bu_log("\tIgnoring %8x/%8x (radial=x%x)\n",
00873 eu, eu->eumate_p,
00874 eu->radial_p );
00875 }
00876 continue;
00877 }
00878
00879 if (rt_g.NMG_debug & DEBUG_FINDEU)
00880 bu_log("\tFound %8x/%8x\n", eu, eu->eumate_p);
00881
00882 if ( *eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
00883 *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
00884 eup_orientation != eu->up.lu_p->up.fu_p->orientation)
00885 eu = eu->eumate_p;
00886 goto out;
00887 }
00888 eu = (struct edgeuse *)NULL;
00889 out:
00890 if (rt_g.NMG_debug & (DEBUG_BASIC|DEBUG_FINDEU))
00891 bu_log("nmg_find_eu_in_face() returns x%x\n", eu);
00892
00893 return (struct edgeuse *)eu;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 struct edgeuse *
00912 nmg_find_e(const struct vertex *v1, const struct vertex *v2, const struct shell *s, const struct edge *ep)
00913 {
00914 register const struct vertexuse *vu;
00915 register const struct edgeuse *eu;
00916
00917 NMG_CK_VERTEX(v1);
00918 NMG_CK_VERTEX(v2);
00919 if(s) NMG_CK_SHELL(s);
00920
00921 if (rt_g.NMG_debug & DEBUG_FINDEU) {
00922 bu_log("nmg_find_e() seeking e!=%8x between (%8x, %8x)\n",
00923 ep, v1, v2 );
00924 }
00925
00926 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) ) {
00927 NMG_CK_VERTEXUSE(vu);
00928 if (!vu->up.magic_p)
00929 rt_bomb("nmg_find_e() vertexuse in vu_hd list has null parent\n");
00930
00931
00932 if (*vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
00933 eu = vu->up.eu_p;
00934
00935
00936
00937 if( eu->eumate_p->vu_p->v_p != v2 ) continue;
00938
00939 if (rt_g.NMG_debug & DEBUG_FINDEU ) {
00940 bu_log("nmg_find_e: check eu=%8x vertex=(%8x, %8x)\n",
00941 eu, eu->vu_p->v_p,
00942 eu->eumate_p->vu_p->v_p);
00943 }
00944
00945
00946 if( eu->e_p == ep ) {
00947 if (rt_g.NMG_debug & DEBUG_FINDEU )
00948 bu_log("\tIgnoring -- excluded edge\n");
00949 continue;
00950 }
00951
00952
00953 if( s && nmg_find_s_of_eu(eu) != s ) {
00954 if (rt_g.NMG_debug & DEBUG_FINDEU)
00955 bu_log("\tIgnoring x%x -- eu in wrong shell s=%x\n", eu, eu->up.s_p);
00956 continue;
00957 }
00958
00959 if (rt_g.NMG_debug & DEBUG_FINDEU)
00960 bu_log("\tFound %8x/%8x\n", eu, eu->eumate_p);
00961
00962 if ( *eu->up.magic_p == NMG_LOOPUSE_MAGIC &&
00963 *eu->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
00964 eu->up.lu_p->up.fu_p->orientation != OT_SAME ) {
00965 eu = eu->eumate_p;
00966 }
00967 goto out;
00968 }
00969 eu = (struct edgeuse *)NULL;
00970 out:
00971 if (rt_g.NMG_debug & (DEBUG_BASIC|DEBUG_FINDEU))
00972 bu_log("nmg_find_e() returns x%x\n", eu);
00973
00974 return (struct edgeuse *)eu;
00975 }
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 struct edgeuse *
00987 nmg_find_eu_of_vu(const struct vertexuse *vu)
00988 {
00989 NMG_CK_VERTEXUSE(vu);
00990 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
00991 return (struct edgeuse *)NULL;
00992 return vu->up.eu_p;
00993 }
00994
00995
00996
00997
00998
00999
01000 struct edgeuse *
01001 nmg_find_eu_with_vu_in_lu(const struct loopuse *lu, const struct vertexuse *vu)
01002 {
01003 register struct edgeuse *eu;
01004
01005 NMG_CK_LOOPUSE(lu);
01006 NMG_CK_VERTEXUSE(vu);
01007 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
01008 rt_bomb("nmg_find_eu_with_vu_in_lu: loop has no edges!\n");
01009 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
01010 NMG_CK_EDGEUSE(eu);
01011 if( eu->vu_p == vu ) return eu;
01012 }
01013 rt_bomb("nmg_find_eu_with_vu_in_lu: Unable to find vu!\n");
01014
01015 return((struct edgeuse *)NULL);
01016 }
01017
01018
01019
01020
01021
01022
01023 const struct edgeuse *
01024 nmg_faceradial(const struct edgeuse *eu)
01025 {
01026 const struct faceuse *fu;
01027 const struct edgeuse *eur;
01028
01029 NMG_CK_EDGEUSE(eu);
01030 NMG_CK_LOOPUSE(eu->up.lu_p);
01031 fu = eu->up.lu_p->up.fu_p;
01032 NMG_CK_FACEUSE(fu);
01033
01034 eur = eu->radial_p;
01035
01036 while (*eur->up.magic_p != NMG_LOOPUSE_MAGIC ||
01037 *eur->up.lu_p->up.magic_p != NMG_FACEUSE_MAGIC ||
01038 eur->up.lu_p->up.fu_p->f_p != fu->f_p)
01039 eur = eur->eumate_p->radial_p;
01040
01041 return(eur);
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051 const struct edgeuse *
01052 nmg_radial_face_edge_in_shell(const struct edgeuse *eu)
01053 {
01054 const struct edgeuse *eur;
01055 const struct shell *s;
01056
01057 NMG_CK_EDGEUSE(eu);
01058 s = nmg_find_s_of_eu(eu);
01059
01060 eur = eu->radial_p;
01061 NMG_CK_EDGEUSE(eur);
01062
01063 while (eur != eu->eumate_p) {
01064 if (*eur->up.magic_p == NMG_LOOPUSE_MAGIC &&
01065 *eur->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
01066 eur->up.lu_p->up.fu_p->s_p == s) {
01067 break;
01068 } else {
01069 eur = eur->eumate_p->radial_p;
01070 NMG_CK_EDGEUSE(eur);
01071 }
01072 }
01073 return(eur);
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 const struct edgeuse *
01094 nmg_find_edge_between_2fu(const struct faceuse *fu1, const struct faceuse *fu2, const struct bn_tol *tol)
01095 {
01096 const struct loopuse *lu1;
01097 const struct edgeuse *ret = (const struct edgeuse *)NULL;
01098 int coincident;
01099
01100 NMG_CK_FACEUSE(fu1);
01101 NMG_CK_FACEUSE(fu2);
01102 BN_CK_TOL(tol);
01103
01104 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) ) {
01105 const struct edgeuse *eu1;
01106 NMG_CK_LOOPUSE(lu1);
01107 if( BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC )
01108 continue;
01109 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) ) {
01110 const struct edgeuse *eur;
01111
01112 NMG_CK_EDGEUSE(eu1);
01113
01114 eur = eu1->radial_p;
01115 NMG_CK_EDGEUSE(eur);
01116
01117 while (eur != eu1->eumate_p) {
01118 if (*eur->up.magic_p == NMG_LOOPUSE_MAGIC &&
01119 *eur->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
01120 eur->up.lu_p->up.fu_p->f_p == fu2->f_p) {
01121
01122 if( !ret ) {
01123
01124 if( eur->up.lu_p->up.fu_p == fu2) {
01125 ret = eur;
01126 } else {
01127 ret = eur->eumate_p;
01128 }
01129 } else {
01130
01131 if( eur->g.lseg_p != ret->g.lseg_p ) {
01132 bu_log("eur=x%x, eg_p=x%x; ret=x%x, eg_p=x%x\n",
01133 eur, eur->g.lseg_p,
01134 ret, ret->g.lseg_p );
01135 nmg_pr_eg( eur->g.magic_p, 0 );
01136 nmg_pr_eg( ret->g.magic_p, 0 );
01137 nmg_pr_eu_endpoints( eur, 0 );
01138 nmg_pr_eu_endpoints( ret, 0 );
01139
01140 coincident = nmg_2edgeuse_g_coincident( eur, ret, tol );
01141 if( coincident ) {
01142
01143 bu_log("nmg_find_edge_between_2fu() belatedly fusing e1=x%x, eg1=x%x, e2=x%x, eg2=x%x\n",
01144 eur->e_p, eur->g.lseg_p,
01145 ret->e_p, ret->g.lseg_p );
01146 nmg_jeg( ret->g.lseg_p, eur->g.lseg_p );
01147
01148 nmg_model_fuse( nmg_find_model(&eur->l.magic), tol );
01149 } else {
01150 rt_bomb("nmg_find_edge_between_2fu() 2 faces intersect with differing edge geometries?\n");
01151 }
01152 }
01153 }
01154 }
01155
01156 eur = eur->eumate_p->radial_p;
01157 NMG_CK_EDGEUSE(eur);
01158 }
01159 }
01160 }
01161 if (rt_g.NMG_debug & DEBUG_BASIC) bu_log("nmg_find_edge_between_2fu(fu1=x%x, fu2=x%x) edgeuse=x%x\n", fu1, fu2, ret);
01162 return ret;
01163
01164 }
01165
01166
01167
01168
01169 struct fen2d_state {
01170 char *visited;
01171 fastf_t mindist;
01172 struct edge *ep;
01173 mat_t mat;
01174 point_t pt2;
01175 const struct bn_tol *tol;
01176 };
01177
01178 static void
01179 nmg_find_e_pt2_handler(long int *lp, genptr_t state, int first)
01180 {
01181 register struct fen2d_state *sp = (struct fen2d_state *)state;
01182 register struct edge *e = (struct edge *)lp;
01183 fastf_t dist_sq;
01184 point_t a2, b2;
01185 struct vertex *va, *vb;
01186 point_t pca;
01187 int code;
01188
01189 BN_CK_TOL(sp->tol);
01190 NMG_CK_EDGE(e);
01191
01192
01193 if( !NMG_INDEX_FIRST_TIME(sp->visited, e) ) return;
01194
01195 va = e->eu_p->vu_p->v_p;
01196 vb = e->eu_p->eumate_p->vu_p->v_p;
01197 NMG_CK_VERTEX(va);
01198 NMG_CK_VERTEX(vb);
01199
01200 MAT4X3PNT( a2, sp->mat, va->vg_p->coord );
01201 MAT4X3PNT( b2, sp->mat, vb->vg_p->coord );
01202
01203 code = bn_dist_pt2_lseg2( &dist_sq, pca, a2, b2, sp->pt2, sp->tol );
01204
01205 if( code == 0 ) dist_sq = 0;
01206
01207 if( dist_sq < sp->mindist ) {
01208 sp->mindist = dist_sq;
01209 sp->ep = e;
01210 }
01211 }
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221 struct edge *
01222 nmg_find_e_nearest_pt2(long int *magic_p, const fastf_t *pt2, const fastf_t *mat, const struct bn_tol *tol)
01223
01224
01225
01226
01227 {
01228 struct model *m;
01229 struct fen2d_state st;
01230 static const struct nmg_visit_handlers htab = {NULL, NULL, NULL, NULL, NULL,
01231 NULL, NULL, NULL, NULL, NULL,
01232 NULL, NULL, NULL, NULL, NULL,
01233 NULL, NULL, NULL, nmg_find_e_pt2_handler, NULL,
01234 NULL, NULL, NULL, NULL, NULL};
01235
01236
01237 BN_CK_TOL(tol);
01238 m = nmg_find_model( magic_p );
01239 NMG_CK_MODEL(m);
01240
01241 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
01242 st.mindist = INFINITY;
01243 VMOVE( st.pt2, pt2 );
01244 MAT_COPY( st.mat, mat );
01245 st.ep = (struct edge *)NULL;
01246 st.tol = tol;
01247
01248 nmg_visit( magic_p, &htab, (genptr_t)&st );
01249
01250 bu_free( (char *)st.visited, "visited[]" );
01251
01252 if( st.ep ) {
01253 NMG_CK_EDGE(st.ep);
01254 return st.ep;
01255 }
01256 return (struct edge *)NULL;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 void
01271 nmg_eu_2vecs_perp(fastf_t *xvec, fastf_t *yvec, fastf_t *zvec, const struct edgeuse *eu, const struct bn_tol *tol)
01272 {
01273 const struct vertex *v1, *v2;
01274 fastf_t len;
01275
01276 NMG_CK_EDGEUSE(eu);
01277 v1 = eu->vu_p->v_p;
01278 NMG_CK_VERTEX(v1);
01279 v2 = eu->eumate_p->vu_p->v_p;
01280 NMG_CK_VERTEX(v2);
01281 if( v1 == v2 ) rt_bomb("nmg_eu_2vecs_perp() start&end vertex of edge are the same!\n");
01282 BN_CK_TOL(tol);
01283
01284 NMG_CK_VERTEX_G(v1->vg_p);
01285 NMG_CK_VERTEX_G(v2->vg_p);
01286 VSUB2( zvec, v2->vg_p->coord, v1->vg_p->coord );
01287 len = MAGNITUDE(zvec);
01288
01289 if( len < tol->dist ) rt_bomb("nmg_eu_2vecs_perp(): 0-length edge (geometry)\n");
01290 len = 1 / len;
01291 VSCALE( zvec, zvec, len );
01292
01293 bn_vec_perp( xvec, zvec );
01294 VCROSS( yvec, zvec, xvec );
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 int
01312 nmg_find_eu_leftvec(fastf_t *left, const struct edgeuse *eu)
01313 {
01314 const struct loopuse *lu;
01315 const struct faceuse *fu;
01316 vect_t Norm;
01317 vect_t edgevect;
01318 fastf_t dot;
01319 struct vertex_g *vg1;
01320 struct vertex_g *vg2;
01321 fastf_t edge_len_sq;
01322 fastf_t sin_sq;
01323
01324 NMG_CK_EDGEUSE(eu);
01325 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC ) return -1;
01326 lu = eu->up.lu_p;
01327 NMG_CK_LOOPUSE(lu);
01328 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC ) return -1;
01329 fu = lu->up.fu_p;
01330 NMG_CK_FACEUSE(fu);
01331 NMG_CK_FACE(fu->f_p);
01332 NMG_CK_FACE_G_PLANE(fu->f_p->g.plane_p);
01333
01334 vg1 = eu->vu_p->v_p->vg_p;
01335 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
01336
01337
01338 NMG_GET_FU_NORMAL( Norm, fu );
01339
01340 VSUB2( edgevect, vg2->coord, vg1->coord );
01341 edge_len_sq = MAGSQ( edgevect );
01342
01343 dot = VDOT( edgevect, Norm );
01344 sin_sq = 1.0 - (dot * dot / edge_len_sq);
01345
01346 if( NEAR_ZERO( sin_sq, 0.000001) )
01347 {
01348 const struct edgeuse *eu_next;
01349 const struct edgeuse *eu_prev;
01350 vect_t next_left;
01351 vect_t prev_left;
01352 vect_t other_edge;
01353 int other_edge_is_parallel=1;
01354
01355 bu_log( "WARNING: eu x%x (%f %f %f) parallel to normal (%f %f %f)\n", eu, V3ARGS( edgevect ), V3ARGS( Norm ) );
01356
01357 eu_next = eu;
01358 while( other_edge_is_parallel )
01359 {
01360 eu_next = BU_LIST_PNEXT_CIRC( edgeuse, &eu_next->l );
01361 if( eu_next == eu )
01362 break;
01363 if( NMG_ARE_EUS_ADJACENT( eu, eu_next ) )
01364 continue;
01365 VSUB2( other_edge, eu_next->eumate_p->vu_p->v_p->vg_p->coord,
01366 eu_next->vu_p->v_p->vg_p->coord );
01367 VUNITIZE( other_edge );
01368 dot = 1.0 - fabs( VDOT( other_edge, Norm ) );
01369 if( dot < .5 )
01370 other_edge_is_parallel = 0;
01371 }
01372 if( other_edge_is_parallel )
01373 {
01374 bu_log( "Cannot find edge (starting eu =x%x) that is not parallel to face normal!!!\n", eu );
01375 nmg_pr_fu_briefly( fu, (char *)NULL );
01376 rt_bomb( "Cannot find edge that is not parallel to face normal!!!\n" );
01377 }
01378
01379 VCROSS( next_left, Norm, other_edge );
01380 VUNITIZE( next_left );
01381
01382 eu_prev = eu;
01383 other_edge_is_parallel = 1;
01384 while( other_edge_is_parallel )
01385 {
01386 eu_prev = BU_LIST_PPREV_CIRC( edgeuse, &eu_prev->l );
01387 if( eu_prev == eu )
01388 break;
01389 if( NMG_ARE_EUS_ADJACENT( eu, eu_prev ) )
01390 continue;
01391 VSUB2( other_edge, eu_prev->eumate_p->vu_p->v_p->vg_p->coord,
01392 eu_prev->vu_p->v_p->vg_p->coord );
01393 VUNITIZE( other_edge );
01394 dot = 1.0 - fabs( VDOT( other_edge, Norm ) );
01395 if( dot < .5 )
01396 other_edge_is_parallel = 0;
01397 }
01398 if( other_edge_is_parallel )
01399 {
01400 bu_log( "Cannot find edge (starting eu =x%x) that is not parallel to face normal!!!\n", eu );
01401 nmg_pr_fu_briefly( fu, (char *)NULL );
01402 rt_bomb( "Cannot find edge that is not parallel to face normal!!!\n" );
01403 }
01404
01405 VCROSS( prev_left, Norm, other_edge );
01406 VUNITIZE( prev_left );
01407
01408 VBLEND2( left, 0.5, next_left, 0.5, prev_left );
01409 VUNITIZE( left );
01410 #if 0
01411 bu_log( "\t eu_prev (%g %g %g)<->(%g %g %g)\n",
01412 V3ARGS( eu_prev->vu_p->v_p->vg_p->coord ),
01413 V3ARGS( eu_prev->eumate_p->vu_p->v_p->vg_p->coord ) );
01414 bu_log( "\t eu_next (%g %g %g)<->(%g %g %g)\n",
01415 V3ARGS( eu_next->vu_p->v_p->vg_p->coord ),
01416 V3ARGS( eu_next->eumate_p->vu_p->v_p->vg_p->coord ) );
01417 bu_log( "\tprev_left=(%g %g %g), next_left=(%g %g %g)\n", V3ARGS( prev_left ), V3ARGS( next_left ) );
01418 bu_log( "\tUnitized left=(%f %f %f)\n", V3ARGS( left ) );
01419
01420 nmg_pr_fu_briefly( fu, "" );
01421 #endif
01422 return 0;
01423 }
01424
01425 VCROSS( left, Norm, edgevect );
01426 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
01427 vect_t edge_unit;
01428 vect_t norm_x_edge;
01429
01430 VMOVE( edge_unit, edgevect );
01431 VUNITIZE( edge_unit );
01432 VCROSS( norm_x_edge, Norm, edge_unit );
01433 bu_log( "for eu x%x from fu x%x v1=x%x, v2=x%x:\n", eu, fu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p );
01434 bu_log( "\t(%.10f %.10f %.10f) <-> (%.10f %.10f %.10f)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ), V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
01435 bu_log( "\tedge dot norm = %.10f\n", VDOT( edge_unit, Norm ) );
01436 bu_log( "\tnorm X edge = (%.10f %.10f %.10f)\n", V3ARGS( norm_x_edge ) );
01437 bu_log( "\tnorm=(%.10f %.10f %.10f), edgevect=(%.10f %.10f %.10f), left=(%.10f %.10f %.10f )\n",
01438 V3ARGS( Norm ), V3ARGS( edgevect ), V3ARGS( left ) );
01439 }
01440 VUNITIZE( left );
01441 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
01442 bu_log( "\tUnitized left=(%f %f %f)\n", V3ARGS( left ) );
01443 }
01444 return 0;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 int
01462 nmg_find_eu_left_non_unit(fastf_t *left, const struct edgeuse *eu)
01463 {
01464 const struct loopuse *lu;
01465 const struct faceuse *fu;
01466 vect_t Norm;
01467 vect_t edgevect;
01468 pointp_t p1,p2;
01469
01470 NMG_CK_EDGEUSE(eu);
01471 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC ) return -1;
01472 lu = eu->up.lu_p;
01473 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC ) return -1;
01474 fu = lu->up.fu_p;
01475
01476
01477 NMG_GET_FU_NORMAL( Norm, fu );
01478
01479
01480 p1 = eu->vu_p->v_p->vg_p->coord;
01481 p2 = eu->eumate_p->vu_p->v_p->vg_p->coord;
01482 VSUB2( edgevect, p2, p1 );
01483
01484
01485 VCROSS( left, Norm, edgevect );
01486 return 0;
01487 }
01488
01489
01490
01491
01492
01493
01494
01495 struct edgeuse *
01496 nmg_find_ot_same_eu_of_e(const struct edge *e)
01497 {
01498 register struct edgeuse *eu1;
01499 register struct edgeuse *eu;
01500 struct faceuse *fu;
01501
01502 NMG_CK_EDGE(e);
01503 eu = eu1 = e->eu_p;
01504 do {
01505 fu = nmg_find_fu_of_eu(eu);
01506 if( fu && fu->orientation == OT_SAME ) return eu;
01507
01508 fu = nmg_find_fu_of_eu(eu->eumate_p);
01509 if( fu && fu->orientation == OT_SAME ) return eu->eumate_p;
01510 eu = eu->radial_p->eumate_p;
01511 } while( eu != eu1 );
01512 return eu1;
01513 }
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531 struct vertexuse *
01532 nmg_find_v_in_face(const struct vertex *v, const struct faceuse *fu)
01533 {
01534 struct vertexuse *vu;
01535 struct edgeuse *eu;
01536 struct loopuse *lu;
01537
01538 NMG_CK_VERTEX(v);
01539
01540 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) ) {
01541 NMG_CK_VERTEXUSE(vu);
01542 if (*vu->up.magic_p == NMG_EDGEUSE_MAGIC) {
01543 eu = vu->up.eu_p;
01544 if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC) {
01545 lu = eu->up.lu_p;
01546 if (*lu->up.magic_p == NMG_FACEUSE_MAGIC && lu->up.fu_p == fu)
01547 return(vu);
01548 }
01549
01550 } else if (*vu->up.magic_p == NMG_LOOPUSE_MAGIC) {
01551 lu = vu->up.lu_p;
01552 if (*lu->up.magic_p == NMG_FACEUSE_MAGIC && lu->up.fu_p == fu)
01553 return(vu);
01554 }
01555 }
01556 return((struct vertexuse *)NULL);
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569 struct vertexuse *
01570 nmg_find_v_in_shell(const struct vertex *v, const struct shell *s, int edges_only)
01571 {
01572 struct vertexuse *vu;
01573
01574 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) ) {
01575 NMG_CK_VERTEXUSE(vu);
01576
01577 if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC ) {
01578 if( edges_only ) continue;
01579 if( nmg_find_s_of_lu( vu->up.lu_p ) == s )
01580 return vu;
01581 continue;
01582 }
01583 if( *vu->up.magic_p == NMG_SHELL_MAGIC ) {
01584 if( edges_only ) continue;
01585 if( vu->up.s_p == s )
01586 return vu;
01587 continue;
01588 }
01589 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
01590 rt_bomb("nmg_find_v_in_shell(): bad vu up ptr\n");
01591
01592
01593 if( nmg_find_s_of_eu( vu->up.eu_p ) == s )
01594 return vu;
01595 }
01596 return (struct vertexuse *)NULL;
01597 }
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 struct vertexuse *
01611 nmg_find_pt_in_lu(const struct loopuse *lu, const fastf_t *pt, const struct bn_tol *tol)
01612 {
01613 struct edgeuse *eu;
01614 vect_t delta;
01615 struct vertex *v;
01616 register struct vertex_g *vg;
01617 int magic1;
01618
01619 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
01620 if (magic1 == NMG_VERTEXUSE_MAGIC) {
01621 struct vertexuse *vu;
01622 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01623 v = vu->v_p;
01624 NMG_CK_VERTEX(v);
01625 if( !(vg = v->vg_p) )
01626 return ((struct vertexuse *)NULL);
01627 NMG_CK_VERTEX_G(vg);
01628 VSUB2(delta, vg->coord, pt);
01629 if ( MAGSQ(delta) <= tol->dist_sq)
01630 return(vu);
01631 return ((struct vertexuse *)NULL);
01632 }
01633 if (magic1 != NMG_EDGEUSE_MAGIC) {
01634 rt_bomb("nmg_find_pt_in_lu() Bogus child of loop\n");
01635 }
01636
01637 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
01638 v = eu->vu_p->v_p;
01639 NMG_CK_VERTEX(v);
01640 if( !(vg = v->vg_p) ) continue;
01641 NMG_CK_VERTEX_G(vg);
01642 VSUB2(delta, vg->coord, pt);
01643 if ( MAGSQ(delta) <= tol->dist_sq)
01644 return(eu->vu_p);
01645 }
01646 return ((struct vertexuse *)NULL);
01647
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 struct vertexuse *
01661 nmg_find_pt_in_face(const struct faceuse *fu, const fastf_t *pt, const struct bn_tol *tol)
01662 {
01663 register struct loopuse *lu;
01664 struct vertexuse *vu;
01665
01666 NMG_CK_FACEUSE(fu);
01667 BN_CK_TOL(tol);
01668
01669 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
01670 NMG_CK_LOOPUSE(lu);
01671 if( (vu = nmg_find_pt_in_lu(lu, pt, tol)) )
01672 return vu;
01673 }
01674 return ((struct vertexuse *)NULL);
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694 struct vertex *
01695 nmg_find_pt_in_shell(const struct shell *s, const fastf_t *pt, const struct bn_tol *tol)
01696 {
01697 const struct faceuse *fu;
01698 const struct loopuse *lu;
01699 const struct edgeuse *eu;
01700 const struct vertexuse *vu;
01701 struct vertex *v;
01702 const struct vertex_g *vg;
01703 vect_t delta;
01704
01705 NMG_CK_SHELL(s);
01706 BN_CK_TOL(tol);
01707
01708 fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
01709 while (BU_LIST_NOT_HEAD(fu, &s->fu_hd) ) {
01710
01711 NMG_CK_FACEUSE(fu);
01712 if( (vu = nmg_find_pt_in_face( fu, pt, tol )) )
01713 return(vu->v_p);
01714
01715 if (BU_LIST_PNEXT(faceuse, fu) == fu->fumate_p)
01716 fu = BU_LIST_PNEXT_PNEXT(faceuse, fu);
01717 else
01718 fu = BU_LIST_PNEXT(faceuse, fu);
01719 }
01720
01721
01722 lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
01723 while (BU_LIST_NOT_HEAD(lu, &s->lu_hd) ) {
01724 NMG_CK_LOOPUSE(lu);
01725 if( (vu = nmg_find_pt_in_lu(lu, pt, tol)) )
01726 return vu->v_p;
01727
01728 if (BU_LIST_PNEXT(loopuse, lu) == lu->lumate_p)
01729 lu = BU_LIST_PNEXT_PNEXT(loopuse, lu);
01730 else
01731 lu = BU_LIST_PNEXT(loopuse, lu);
01732 }
01733
01734
01735 for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
01736 NMG_CK_EDGEUSE(eu);
01737 NMG_CK_VERTEXUSE(eu->vu_p);
01738 v = eu->vu_p->v_p;
01739 NMG_CK_VERTEX(v);
01740 if( (vg = v->vg_p) ) {
01741 NMG_CK_VERTEX_G(vg);
01742 VSUB2( delta, vg->coord, pt );
01743 if( MAGSQ(delta) <= tol->dist_sq )
01744 return(v);
01745 }
01746 }
01747
01748
01749 if (s->vu_p) {
01750 NMG_CK_VERTEXUSE(s->vu_p);
01751 v = s->vu_p->v_p;
01752 NMG_CK_VERTEX(v);
01753 if( (vg = v->vg_p) ) {
01754 NMG_CK_VERTEX_G( vg );
01755 VSUB2( delta, vg->coord, pt );
01756 if( MAGSQ(delta) <= tol->dist_sq )
01757 return(v);
01758 }
01759 }
01760 return( (struct vertex *)0 );
01761 }
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 struct vertex *
01772 nmg_find_pt_in_model(const struct model *m, const fastf_t *pt, const struct bn_tol *tol)
01773 {
01774 struct nmgregion *r;
01775 struct shell *s;
01776 struct vertex *v;
01777
01778 NMG_CK_MODEL(m);
01779 BN_CK_TOL(tol);
01780
01781 for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) ) {
01782 NMG_CK_REGION(r);
01783 for( BU_LIST_FOR( s, shell, &r->s_hd ) ) {
01784 NMG_CK_SHELL(s);
01785 if( (v = nmg_find_pt_in_shell( s, pt, tol )) ) {
01786 NMG_CK_VERTEX(v);
01787 return v;
01788 }
01789 }
01790 }
01791 return (struct vertex *)NULL;
01792 }
01793
01794
01795
01796
01797
01798
01799
01800
01801 int
01802 nmg_is_vertex_in_edgelist(register const struct vertex *v, const struct bu_list *hd)
01803 {
01804 register const struct edgeuse *eu;
01805
01806 NMG_CK_VERTEX(v);
01807 for( BU_LIST_FOR( eu, edgeuse, hd ) ) {
01808 NMG_CK_EDGEUSE(eu);
01809 NMG_CK_VERTEXUSE(eu->vu_p);
01810 NMG_CK_VERTEX(eu->vu_p->v_p);
01811 if( eu->vu_p->v_p == v ) return(1);
01812 }
01813 return(0);
01814 }
01815
01816
01817
01818
01819
01820
01821
01822
01823 int
01824 nmg_is_vertex_in_looplist(register const struct vertex *v, const struct bu_list *hd, int singletons)
01825 {
01826 register const struct loopuse *lu;
01827 long magic1;
01828
01829 NMG_CK_VERTEX(v);
01830 for( BU_LIST_FOR( lu, loopuse, hd ) ) {
01831 NMG_CK_LOOPUSE(lu);
01832 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
01833 if( magic1 == NMG_VERTEXUSE_MAGIC ) {
01834 register const struct vertexuse *vu;
01835 if( !singletons ) continue;
01836 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd );
01837 NMG_CK_VERTEXUSE(vu);
01838 NMG_CK_VERTEX(vu->v_p);
01839 if( vu->v_p == v ) return(1);
01840 } else if( magic1 == NMG_EDGEUSE_MAGIC ) {
01841 if( nmg_is_vertex_in_edgelist( v, &lu->down_hd ) )
01842 return(1);
01843 } else {
01844 rt_bomb("nmg_is_vertex_in_loopuse() bad magic\n");
01845 }
01846 }
01847 return(0);
01848 }
01849
01850
01851
01852
01853
01854
01855
01856
01857 struct vertexuse *
01858 nmg_is_vertex_in_face(const struct vertex *v, const struct face *f)
01859 {
01860 struct vertexuse *vu;
01861
01862 NMG_CK_VERTEX(v);
01863 NMG_CK_FACE(f);
01864
01865 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) ) {
01866 register const struct edgeuse *eu;
01867 register const struct loopuse *lu;
01868 register const struct faceuse *fu;
01869
01870 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
01871 if( *(eu = vu->up.eu_p)->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
01872 lu = eu->up.lu_p;
01873 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC ) continue;
01874 fu = lu->up.fu_p;
01875 if( fu->f_p != f ) continue;
01876 return vu;
01877 }
01878 return (struct vertexuse *)NULL;
01879 }
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 int
01893 nmg_is_vertex_a_selfloop_in_shell(const struct vertex *v, const struct shell *s)
01894 {
01895 const struct vertexuse *vu;
01896
01897 NMG_CK_VERTEX(v);
01898 NMG_CK_SHELL(s);
01899
01900
01901 for (BU_LIST_FOR(vu, vertexuse, &v->vu_hd)) {
01902 register const struct loopuse *lu;
01903 NMG_CK_VERTEXUSE(vu);
01904 if (*vu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
01905 lu = vu->up.lu_p;
01906 NMG_CK_LOOPUSE(lu);
01907 if( *lu->up.magic_p != NMG_SHELL_MAGIC ) continue;
01908 NMG_CK_SHELL(lu->up.s_p);
01909 if( lu->up.s_p == s)
01910 return 1;
01911 }
01912 return 0;
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922 int
01923 nmg_is_vertex_in_facelist(register const struct vertex *v, const struct bu_list *hd)
01924 {
01925 register const struct faceuse *fu;
01926
01927 NMG_CK_VERTEX(v);
01928 for( BU_LIST_FOR( fu, faceuse, hd ) ) {
01929 NMG_CK_FACEUSE(fu);
01930 if( nmg_is_vertex_in_looplist( v, &fu->lu_hd, 1 ) )
01931 return(1);
01932 }
01933 return(0);
01934 }
01935
01936
01937
01938
01939
01940
01941
01942
01943 int
01944 nmg_is_edge_in_edgelist(const struct edge *e, const struct bu_list *hd)
01945 {
01946 register const struct edgeuse *eu;
01947
01948 NMG_CK_EDGE(e);
01949 for( BU_LIST_FOR( eu, edgeuse, hd ) ) {
01950 NMG_CK_EDGEUSE(eu);
01951 NMG_CK_EDGE(eu->e_p);
01952 if( e == eu->e_p ) return(1);
01953 }
01954 return(0);
01955 }
01956
01957
01958
01959
01960
01961
01962
01963
01964 int
01965 nmg_is_edge_in_looplist(const struct edge *e, const struct bu_list *hd)
01966 {
01967 register const struct loopuse *lu;
01968 long magic1;
01969
01970 NMG_CK_EDGE(e);
01971 for( BU_LIST_FOR( lu, loopuse, hd ) ) {
01972 NMG_CK_LOOPUSE(lu);
01973 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
01974 if( magic1 == NMG_VERTEXUSE_MAGIC ) {
01975
01976 continue;
01977 } else if( magic1 == NMG_EDGEUSE_MAGIC ) {
01978 if( nmg_is_edge_in_edgelist( e, &lu->down_hd ) )
01979 return(1);
01980 } else {
01981 rt_bomb("nmg_is_edge_in_loopuse() bad magic\n");
01982 }
01983 }
01984 return(0);
01985 }
01986
01987
01988
01989
01990
01991
01992
01993
01994 int
01995 nmg_is_edge_in_facelist(const struct edge *e, const struct bu_list *hd)
01996 {
01997 register const struct faceuse *fu;
01998
01999 NMG_CK_EDGE(e);
02000 for( BU_LIST_FOR( fu, faceuse, hd ) ) {
02001 NMG_CK_FACEUSE(fu);
02002 if( nmg_is_edge_in_looplist( e, &fu->lu_hd ) )
02003 return(1);
02004 }
02005 return(0);
02006 }
02007
02008
02009
02010
02011
02012
02013
02014
02015 int
02016 nmg_is_loop_in_facelist(const struct loop *l, const struct bu_list *fu_hd)
02017 {
02018 register const struct faceuse *fu;
02019 register const struct loopuse *lu;
02020
02021 NMG_CK_LOOP(l);
02022 for( BU_LIST_FOR( fu, faceuse, fu_hd ) ) {
02023 NMG_CK_FACEUSE(fu);
02024 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
02025 NMG_CK_LOOPUSE(lu);
02026 NMG_CK_LOOP(lu->l_p);
02027 if( l == lu->l_p ) return(1);
02028 }
02029 }
02030 return(0);
02031 }
02032
02033
02034
02035
02036
02037
02038
02039 struct vf_state {
02040 char *visited;
02041 struct bu_ptbl *tabl;
02042 };
02043
02044
02045
02046
02047
02048
02049
02050
02051 static void
02052 nmg_2rvf_handler(long int *vp, genptr_t state, int first)
02053 {
02054 register struct vf_state *sp = (struct vf_state *)state;
02055 register struct vertex *v = (struct vertex *)vp;
02056
02057 NMG_CK_VERTEX(v);
02058
02059 if( !NMG_INDEX_FIRST_TIME(sp->visited, v) ) return;
02060
02061 bu_ptbl_ins( sp->tabl, vp );
02062 }
02063
02064
02065
02066
02067
02068
02069
02070
02071 void
02072 nmg_vertex_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02073 {
02074 struct model *m;
02075 struct vf_state st;
02076 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02077 NULL, NULL, NULL, NULL, NULL,
02078 NULL, NULL, NULL, NULL, NULL,
02079 NULL, NULL, NULL, NULL, NULL,
02080 NULL, NULL, NULL, nmg_2rvf_handler, NULL};
02081
02082
02083 m = nmg_find_model( magic_p );
02084 NMG_CK_MODEL(m);
02085
02086 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02087 st.tabl = tab;
02088
02089 (void)bu_ptbl_init( tab, 64, " tab");
02090
02091 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02092
02093 bu_free( (char *)st.visited, "visited[]");
02094 }
02095
02096
02097
02098
02099
02100
02101
02102
02103 static void
02104 nmg_vert_a_handler(long int *vp, genptr_t state, int first)
02105 {
02106 register struct vf_state *sp = (struct vf_state *)state;
02107 register struct vertexuse_a_plane *va;
02108
02109 if( *vp != NMG_VERTEXUSE_A_PLANE_MAGIC )
02110 return;
02111
02112 va = (struct vertexuse_a_plane *)vp;
02113
02114 if( !NMG_INDEX_FIRST_TIME(sp->visited, va) ) return;
02115
02116 bu_ptbl_ins( sp->tabl, vp );
02117 }
02118
02119
02120
02121
02122
02123
02124
02125
02126 void
02127 nmg_vertexuse_normal_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02128 {
02129 struct model *m;
02130 struct vf_state st;
02131 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02132 NULL, NULL, NULL, NULL, NULL,
02133 NULL, NULL, NULL, NULL, NULL,
02134 NULL, NULL, NULL, NULL, NULL,
02135 NULL, NULL, nmg_vert_a_handler, NULL, NULL};
02136
02137
02138 m = nmg_find_model( magic_p );
02139 NMG_CK_MODEL(m);
02140
02141 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02142 st.tabl = tab;
02143
02144 (void)bu_ptbl_init( tab, 64, " tab");
02145
02146 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02147
02148 bu_free( (char *)st.visited, "visited[]");
02149 }
02150
02151
02152
02153
02154
02155
02156
02157
02158 static void
02159 nmg_2edgeuse_handler(long int *eup, genptr_t state, int first)
02160 {
02161 register struct vf_state *sp = (struct vf_state *)state;
02162 register struct edgeuse *eu = (struct edgeuse *)eup;
02163
02164 NMG_CK_EDGEUSE(eu);
02165
02166 if( !NMG_INDEX_FIRST_TIME(sp->visited, eu) ) return;
02167
02168 bu_ptbl_ins( sp->tabl, eup );
02169 }
02170
02171
02172
02173
02174
02175
02176
02177
02178 void
02179 nmg_edgeuse_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02180 {
02181 struct model *m;
02182 struct vf_state st;
02183 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02184 NULL, NULL, NULL, NULL, NULL,
02185 NULL, NULL, NULL, NULL, NULL,
02186 NULL, nmg_2edgeuse_handler, NULL, NULL, NULL,
02187 NULL, NULL, NULL, NULL, NULL};
02188
02189
02190 m = nmg_find_model( magic_p );
02191 NMG_CK_MODEL(m);
02192
02193 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02194 st.tabl = tab;
02195
02196 (void)bu_ptbl_init( tab, 64, " tab");
02197
02198 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02199
02200 bu_free( (char *)st.visited, "visited[]");
02201 }
02202
02203
02204
02205
02206
02207
02208
02209
02210 static void
02211 nmg_2edge_handler(long int *ep, genptr_t state, int first)
02212 {
02213 register struct vf_state *sp = (struct vf_state *)state;
02214 register struct edge *e = (struct edge *)ep;
02215
02216 NMG_CK_EDGE(e);
02217
02218 if( !NMG_INDEX_FIRST_TIME(sp->visited, e) ) return;
02219
02220 bu_ptbl_ins( sp->tabl, ep );
02221 }
02222
02223
02224
02225
02226
02227
02228
02229
02230 void
02231 nmg_edge_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02232 {
02233 struct model *m;
02234 struct vf_state st;
02235 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02236 NULL, NULL, NULL, NULL, NULL,
02237 NULL, NULL, NULL, NULL, NULL,
02238 NULL, NULL, NULL, nmg_2edge_handler, NULL,
02239 NULL, NULL, NULL, NULL, NULL};
02240
02241
02242 m = nmg_find_model( magic_p );
02243 NMG_CK_MODEL(m);
02244
02245 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02246 st.tabl = tab;
02247
02248 (void)bu_ptbl_init( tab, 64, " tab");
02249
02250 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02251
02252 bu_free( (char *)st.visited, "visited[]");
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262 static void
02263 nmg_edge_g_handler(long int *ep, genptr_t state, int first)
02264 {
02265 register struct vf_state *sp = (struct vf_state *)state;
02266
02267 NMG_CK_EDGE_G_EITHER(ep);
02268
02269
02270 switch( *ep ) {
02271 case NMG_EDGE_G_LSEG_MAGIC:
02272 if( !NMG_INDEX_FIRST_TIME(sp->visited, ((struct edge_g_lseg *)ep)) )
02273 return;
02274 break;
02275 case NMG_EDGE_G_CNURB_MAGIC:
02276 if( !NMG_INDEX_FIRST_TIME(sp->visited, ((struct edge_g_cnurb *)ep)) )
02277 return;
02278 break;
02279 }
02280
02281 bu_ptbl_ins( sp->tabl, ep );
02282 }
02283
02284
02285
02286
02287
02288
02289
02290
02291 void
02292 nmg_edge_g_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02293 {
02294 struct model *m;
02295 struct vf_state st;
02296 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02297 NULL, NULL, NULL, NULL, NULL,
02298 NULL, NULL, NULL, NULL, NULL,
02299 NULL, NULL, NULL, NULL, nmg_edge_g_handler,
02300 NULL, NULL, NULL, NULL, NULL};
02301
02302
02303 m = nmg_find_model( magic_p );
02304 NMG_CK_MODEL(m);
02305
02306 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02307 st.tabl = tab;
02308
02309 (void)bu_ptbl_init( tab, 64, " tab");
02310
02311 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02312
02313 bu_free( (char *)st.visited, "visited[]");
02314 }
02315
02316
02317
02318
02319
02320
02321
02322
02323 static void
02324 nmg_2face_handler(long int *fp, genptr_t state, int first)
02325 {
02326 register struct vf_state *sp = (struct vf_state *)state;
02327 register struct face *f = (struct face *)fp;
02328
02329 NMG_CK_FACE(f);
02330
02331 if( !NMG_INDEX_FIRST_TIME(sp->visited, f) ) return;
02332
02333 bu_ptbl_ins( sp->tabl, fp );
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343 void
02344 nmg_face_tabulate(struct bu_ptbl *tab, const long int *magic_p)
02345 {
02346 struct model *m;
02347 struct vf_state st;
02348 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02349 NULL, NULL, NULL, NULL, NULL,
02350 nmg_2face_handler, NULL, NULL, NULL, NULL,
02351 NULL, NULL, NULL, NULL, NULL,
02352 NULL, NULL, NULL, NULL, NULL};
02353
02354
02355 m = nmg_find_model( magic_p );
02356 NMG_CK_MODEL(m);
02357
02358 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02359 st.tabl = tab;
02360
02361 (void)bu_ptbl_init( tab, 64, " tab");
02362
02363 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02364
02365 bu_free( (char *)st.visited, "visited[]");
02366 }
02367
02368
02369
02370
02371
02372
02373
02374 void
02375 nmg_edgeuse_with_eg_tabulate(struct bu_ptbl *tab, const struct edge_g_lseg *eg)
02376
02377
02378 {
02379 struct bu_list *midway;
02380 struct edgeuse *eu;
02381
02382 NMG_CK_EDGE_G_EITHER(eg);
02383 (void)bu_ptbl_init( tab, 64, " tab");
02384
02385 for( BU_LIST_FOR( midway, bu_list, &eg->eu_hd2 ) ) {
02386 NMG_CKMAG(midway, NMG_EDGEUSE2_MAGIC, "edgeuse2 [l2]");
02387 eu = BU_LIST_MAIN_PTR( edgeuse, midway, l2 );
02388 NMG_CK_EDGEUSE(eu);
02389 if( eu->g.lseg_p != eg ) rt_bomb("nmg_edgeuse_with_eg_tabulate() eu disavows eg\n");
02390 bu_ptbl_ins_unique( tab, (long *)eu );
02391 }
02392 }
02393
02394 struct edge_line_state {
02395 char *visited;
02396 struct bu_ptbl *tabl;
02397 point_t pt;
02398 vect_t dir;
02399 struct bn_tol tol;
02400 };
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410 static void
02411 nmg_line_handler(long int *longp, genptr_t state, int first)
02412 {
02413 register struct edge_line_state *sp = (struct edge_line_state *)state;
02414 register struct edgeuse *eu = (struct edgeuse *)longp;
02415
02416 NMG_CK_EDGEUSE(eu);
02417
02418 if( !NMG_INDEX_FIRST_TIME(sp->visited, eu) ) return;
02419
02420
02421
02422
02423
02424 BN_CK_TOL(&sp->tol);
02425 NMG_CK_EDGE_G_LSEG(eu->g.lseg_p);
02426
02427
02428
02429 if( fabs( VDOT( eu->g.lseg_p->e_dir, sp->dir ) ) <
02430 0.9 * MAGNITUDE(eu->g.lseg_p->e_dir) * MAGNITUDE(sp->dir) )
02431 return;
02432
02433 if( bn_distsq_line3_pt3( sp->pt, sp->dir, eu->vu_p->v_p->vg_p->coord )
02434 > sp->tol.dist_sq )
02435 return;
02436 if( bn_distsq_line3_pt3( sp->pt, sp->dir, eu->eumate_p->vu_p->v_p->vg_p->coord )
02437 > sp->tol.dist_sq )
02438 return;
02439
02440
02441 bu_ptbl_ins( sp->tabl, longp );
02442 }
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460 void
02461 nmg_edgeuse_on_line_tabulate(struct bu_ptbl *tab, const long int *magic_p, const fastf_t *pt, const fastf_t *dir, const struct bn_tol *tol)
02462 {
02463 struct model *m;
02464 struct edge_line_state st;
02465 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02466 NULL, NULL, NULL, NULL, NULL,
02467 NULL, NULL, NULL, NULL, NULL,
02468 NULL, nmg_line_handler, NULL, NULL, NULL,
02469 NULL, NULL, NULL, NULL, NULL};
02470
02471
02472 m = nmg_find_model( magic_p );
02473 NMG_CK_MODEL(m);
02474 BN_CK_TOL(tol);
02475
02476 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02477 st.tabl = tab;
02478 VMOVE( st.pt, pt );
02479 VMOVE( st.dir, dir );
02480
02481 st.tol = *tol;
02482 #if 0
02483
02484 st.tol.dist = 10 * tol->dist;
02485 st.tol.dist_sq = st.tol.dist * st.tol.dist;
02486 #endif
02487
02488 (void)bu_ptbl_init( tab, 64, " tab");
02489
02490 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02491
02492 bu_free( (char *)st.visited, "visited[]");
02493 }
02494
02495 struct e_and_v_state {
02496 char *visited;
02497 struct bu_ptbl *edges;
02498 struct bu_ptbl *verts;
02499 };
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509 static void
02510 nmg_e_handler(long int *longp, genptr_t state, int first)
02511 {
02512 register struct e_and_v_state *sp = (struct e_and_v_state *)state;
02513 register struct edge *e = (struct edge *)longp;
02514
02515 NMG_CK_EDGE(e);
02516
02517 if( !NMG_INDEX_FIRST_TIME(sp->visited, e) ) return;
02518
02519
02520 bu_ptbl_ins( sp->edges, (long *)e->eu_p );
02521 }
02522
02523
02524
02525
02526
02527
02528 static void
02529 nmg_v_handler(long int *longp, genptr_t state, int first)
02530 {
02531 register struct e_and_v_state *sp = (struct e_and_v_state *)state;
02532 register struct vertex *v = (struct vertex *)longp;
02533
02534 NMG_CK_VERTEX(v);
02535
02536 if( !NMG_INDEX_FIRST_TIME(sp->visited, v) ) return;
02537
02538
02539 bu_ptbl_ins( sp->verts, longp );
02540 }
02541
02542
02543
02544
02545
02546
02547
02548
02549 void
02550 nmg_e_and_v_tabulate(struct bu_ptbl *eutab, struct bu_ptbl *vtab, const long int *magic_p)
02551 {
02552 struct model *m;
02553 struct e_and_v_state st;
02554 static const struct nmg_visit_handlers handlers = {NULL, NULL, NULL, NULL, NULL,
02555 NULL, NULL, NULL, NULL, NULL,
02556 NULL, NULL, NULL, NULL, NULL,
02557 NULL, NULL, NULL, nmg_e_handler, NULL,
02558 NULL, NULL, NULL, nmg_v_handler, NULL};
02559
02560
02561
02562 m = nmg_find_model( magic_p );
02563 NMG_CK_MODEL(m);
02564
02565 st.visited = (char *)bu_calloc(m->maxindex+1, sizeof(char), "visited[]");
02566 st.edges = eutab;
02567 st.verts = vtab;
02568
02569 (void)bu_ptbl_init( eutab, 64, " eutab");
02570 (void)bu_ptbl_init( vtab, 64, " vtab");
02571
02572 nmg_visit( magic_p, &handlers, (genptr_t)&st );
02573
02574 bu_free( (char *)st.visited, "visited[]");
02575 }
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588 int
02589 nmg_2edgeuse_g_coincident(const struct edgeuse *eu1, const struct edgeuse *eu2, const struct bn_tol *tol)
02590 {
02591 struct edge_g_lseg *eg1;
02592 struct edge_g_lseg *eg2;
02593
02594 NMG_CK_EDGEUSE(eu1);
02595 NMG_CK_EDGEUSE(eu2);
02596 BN_CK_TOL(tol);
02597
02598 eg1 = eu1->g.lseg_p;
02599 eg2 = eu2->g.lseg_p;
02600 NMG_CK_EDGE_G_LSEG(eg1);
02601 NMG_CK_EDGE_G_LSEG(eg2);
02602
02603 if( eg1 == eg2 ) return 1;
02604
02605
02606
02607
02608 if( fabs(VDOT(eg1->e_dir, eg2->e_dir)) <
02609 0.9 * MAGNITUDE(eg1->e_dir) * MAGNITUDE(eg2->e_dir) ) return 0;
02610
02611
02612 if( bn_distsq_line3_pt3( eg1->e_pt, eg1->e_dir,
02613 eu2->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) goto trouble;
02614 if( bn_distsq_line3_pt3( eg1->e_pt, eg1->e_dir,
02615 eu2->eumate_p->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) goto trouble;
02616
02617
02618 if( bn_distsq_line3_pt3( eg2->e_pt, eg2->e_dir,
02619 eu1->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) goto trouble;
02620 if( bn_distsq_line3_pt3( eg2->e_pt, eg2->e_dir,
02621 eu1->eumate_p->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) goto trouble;
02622
02623
02624
02625
02626
02627 return 1;
02628 trouble:
02629 if( !bn_2line3_colinear( eg1->e_pt, eg1->e_dir, eg2->e_pt, eg2->e_dir,
02630 1e5, tol ) )
02631 return 0;
02632
02633
02634 nmg_pr_eg( &eg1->l.magic, 0 );
02635 nmg_pr_eg( &eg2->l.magic, 0 );
02636 bu_log("nmg_2edgeuse_g_coincident() lines colinear, vertex check fails, calling colinear anyway.\n");
02637 return 1;
02638 }
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648