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[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_mod.c,v 14.11 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 <string.h>
00049
00050 #include "machine.h"
00051 #include "vmath.h"
00052 #include "nmg.h"
00053 #include "raytrace.h"
00054 #include "nurb.h"
00055
00056
00057
00058
00059
00060 void
00061 nmg_merge_regions(struct nmgregion *r1, struct nmgregion *r2, const struct bn_tol *tol)
00062 {
00063 struct model *m;
00064
00065 NMG_CK_REGION( r1 );
00066 NMG_CK_REGION( r2 );
00067 BN_CK_TOL( tol );
00068
00069 m = r1->m_p;
00070 NMG_CK_MODEL( m );
00071
00072 if( r2->m_p != m )
00073 rt_bomb( "nmg_merge_regions: Tried to merge regions from different models!!" );
00074
00075
00076 while( BU_LIST_NON_EMPTY( &r2->s_hd ) )
00077 {
00078 struct shell *s;
00079
00080 s = BU_LIST_FIRST( shell, &r2->s_hd );
00081 BU_LIST_DEQUEUE( &s->l );
00082 s->r_p = r1;
00083 BU_LIST_APPEND( &r1->s_hd, &s->l );
00084 }
00085
00086 (void)nmg_kr( r2 );
00087 nmg_rebound( m, tol );
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 void
00113 nmg_shell_coplanar_face_merge(struct shell *s, const struct bn_tol *tol, const int simplify)
00114 {
00115 struct model *m;
00116 int len;
00117 char *flags1;
00118 char *flags2;
00119 struct faceuse *fu1;
00120 struct faceuse *fu2;
00121 struct face *f1;
00122 struct face *f2;
00123 struct face_g_plane *fg1;
00124 struct face_g_plane *fg2;
00125
00126 NMG_CK_SHELL(s);
00127 m = nmg_find_model( &s->l.magic );
00128 len = sizeof(char) * m->maxindex * 2;
00129 flags1 = (char *)bu_calloc( sizeof(char), m->maxindex * 2,
00130 "nmg_shell_coplanar_face_merge flags1[]" );
00131 flags2 = (char *)bu_calloc( sizeof(char), m->maxindex * 2,
00132 "nmg_shell_coplanar_face_merge flags2[]" );
00133
00134
00135 for( BU_LIST_FOR( fu1, faceuse, &s->fu_hd ) ) {
00136 plane_t n1;
00137
00138 if( BU_LIST_NEXT_IS_HEAD(fu1, &s->fu_hd) ) break;
00139 f1 = fu1->f_p;
00140 NMG_CK_FACE(f1);
00141 if( NMG_INDEX_TEST(flags1, f1) ) continue;
00142 NMG_INDEX_SET(flags1, f1);
00143
00144 fg1 = f1->g.plane_p;
00145 NMG_CK_FACE_G_PLANE(fg1);
00146 NMG_GET_FU_PLANE( n1, fu1 );
00147
00148
00149
00150 bcopy( flags1, flags2, len );
00151 for( fu2 = BU_LIST_NEXT(faceuse, &fu1->l);
00152 BU_LIST_NOT_HEAD(fu2, &s->fu_hd);
00153 fu2 = BU_LIST_NEXT(faceuse,&fu2->l)
00154 ) {
00155 register fastf_t dist;
00156 plane_t n2;
00157
00158 f2 = fu2->f_p;
00159 NMG_CK_FACE(f2);
00160 if( NMG_INDEX_TEST(flags2, f2) ) continue;
00161 NMG_INDEX_SET(flags2, f2);
00162
00163 fg2 = f2->g.plane_p;
00164 NMG_CK_FACE_G_PLANE(fg2);
00165
00166 if( fu2->fumate_p == fu1 || fu1->fumate_p == fu2 )
00167 rt_bomb("nmg_shell_coplanar_face_merge() mate confusion\n");
00168
00169
00170 if( fg1 != fg2 || f1->flip != f2->flip ) {
00171
00172 NMG_GET_FU_PLANE( n2, fu2 );
00173
00174
00175 dist = n1[3] - n2[3];
00176 if( !NEAR_ZERO(dist, tol->dist) ) continue;
00177
00178
00179
00180
00181
00182
00183 dist = VDOT( n1, n2 );
00184 if( !(dist >= tol->para) ) continue;
00185
00186 if( nmg_ck_fu_verts( fu2, f1, tol ) )
00187 continue;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 {
00197 struct faceuse *prev_fu;
00198 prev_fu = BU_LIST_PREV(faceuse, &fu2->l);
00199
00200 if( BU_LIST_IS_HEAD(prev_fu, &s->fu_hd) )
00201 rt_bomb("prev is head?\n");
00202
00203 nmg_jf( fu1, fu2 );
00204
00205 fu2 = prev_fu;
00206 }
00207
00208
00209
00210
00211 if( simplify ) {
00212 struct loopuse *lu;
00213
00214 for (BU_LIST_FOR(lu, loopuse, &fu1->lu_hd))
00215 nmg_simplify_loop(lu);
00216 }
00217 }
00218 }
00219 bu_free( (char *)flags1, "nmg_shell_coplanar_face_merge flags1[]" );
00220 bu_free( (char *)flags2, "nmg_shell_coplanar_face_merge flags2[]" );
00221
00222 nmg_shell_a( s, tol );
00223
00224 if (rt_g.NMG_debug & DEBUG_BASIC) {
00225 bu_log("nmg_shell_coplanar_face_merge(s=x%x, tol=x%x, simplify=%d)\n",
00226 s, tol, simplify);
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 int
00241 nmg_simplify_shell(struct shell *s)
00242 {
00243 struct faceuse *fu;
00244 int ret_val;
00245
00246 NMG_CK_SHELL(s);
00247
00248 for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
00249 if( nmg_simplify_face(fu) ) {
00250 struct faceuse *kfu = fu;
00251 fu = BU_LIST_PREV( faceuse, &fu->l );
00252 nmg_kfu( kfu );
00253 }
00254 }
00255
00256 ret_val = nmg_shell_is_empty(s);
00257
00258 if (rt_g.NMG_debug & DEBUG_BASIC) {
00259 bu_log("nmg_simplify_shell(s=x%x) returns %d\n", s , ret_val);
00260 }
00261
00262 return( ret_val );
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 void
00275 nmg_rm_redundancies(struct shell *s, const struct bn_tol *tol)
00276 {
00277 struct faceuse *fu;
00278 struct loopuse *lu;
00279 struct edgeuse *eu;
00280 struct vertexuse *vu;
00281 long magic1;
00282
00283 NMG_CK_SHELL(s);
00284 BN_CK_TOL( tol );
00285
00286 if( BU_LIST_NON_EMPTY( &s->fu_hd ) ) {
00287
00288 lu = BU_LIST_FIRST( loopuse, &s->lu_hd );
00289 while( BU_LIST_NOT_HEAD( lu, &s->lu_hd ) ) {
00290 register struct loopuse *nextlu;
00291 NMG_CK_LOOPUSE(lu);
00292 NMG_CK_LOOP(lu->l_p);
00293 nextlu = BU_LIST_PNEXT( loopuse, lu );
00294 if( nmg_is_loop_in_facelist( lu->l_p, &s->fu_hd ) ) {
00295
00296
00297 if( nextlu == lu->lumate_p )
00298 nextlu = BU_LIST_PNEXT(loopuse, nextlu);
00299 nmg_klu( lu );
00300 }
00301 lu = nextlu;
00302 }
00303
00304
00305 eu = BU_LIST_FIRST( edgeuse, &s->eu_hd );
00306 while( BU_LIST_NOT_HEAD( eu, &s->eu_hd ) ) {
00307 register struct edgeuse *nexteu;
00308 NMG_CK_EDGEUSE(eu);
00309 NMG_CK_EDGE(eu->e_p);
00310 nexteu = BU_LIST_PNEXT( edgeuse, eu );
00311 if( nmg_is_edge_in_facelist( eu->e_p, &s->fu_hd ) ) {
00312
00313 if( nexteu == eu->eumate_p )
00314 nexteu = BU_LIST_PNEXT(edgeuse, nexteu);
00315 (void)nmg_keu(eu);
00316 }
00317 eu = nexteu;
00318 }
00319 }
00320
00321
00322 eu = BU_LIST_FIRST( edgeuse, &s->eu_hd );
00323 while( BU_LIST_NOT_HEAD( eu, &s->eu_hd ) ) {
00324 register struct edgeuse *nexteu;
00325 NMG_CK_EDGEUSE(eu);
00326 NMG_CK_EDGE(eu->e_p);
00327 nexteu = BU_LIST_PNEXT( edgeuse, eu );
00328 if( nmg_is_edge_in_looplist( eu->e_p, &s->lu_hd ) ) {
00329
00330 if( nexteu == eu->eumate_p )
00331 nexteu = BU_LIST_PNEXT(edgeuse, nexteu);
00332 (void)nmg_keu(eu);
00333 }
00334 eu = nexteu;
00335 }
00336
00337
00338
00339 lu = BU_LIST_FIRST( loopuse, &s->lu_hd );
00340 while( BU_LIST_NOT_HEAD( lu, &s->lu_hd ) ) {
00341 register struct loopuse *nextlu;
00342 NMG_CK_LOOPUSE(lu);
00343 nextlu = BU_LIST_PNEXT( loopuse, lu );
00344 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
00345 if( magic1 != NMG_VERTEXUSE_MAGIC ) {
00346 lu = nextlu;
00347 continue;
00348 }
00349 vu = BU_LIST_PNEXT( vertexuse, &lu->down_hd );
00350 NMG_CK_VERTEXUSE(vu);
00351 NMG_CK_VERTEX(vu->v_p);
00352 if( nmg_is_vertex_in_facelist( vu->v_p, &s->fu_hd ) ||
00353 nmg_is_vertex_in_looplist( vu->v_p, &s->lu_hd,0 ) ||
00354 nmg_is_vertex_in_edgelist( vu->v_p, &s->eu_hd ) ) {
00355
00356 if( nextlu == lu->lumate_p )
00357 nextlu = BU_LIST_PNEXT(loopuse, nextlu);
00358 nmg_klu( lu );
00359 lu = nextlu;
00360 continue;
00361 }
00362 lu = nextlu;
00363 }
00364
00365
00366 if( s->vu_p ) bu_log("nmg_rm_redundancies() lone vertex?\n");
00367
00368
00369 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
00370 while( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) )
00371 {
00372 struct faceuse *next_fu;
00373 int lu1_count;
00374 int lu_count;
00375
00376 NMG_CK_FACEUSE( fu );
00377
00378 if( fu->orientation != OT_SAME )
00379 {
00380 fu = BU_LIST_NEXT( faceuse, &fu->l );
00381 continue;
00382 }
00383
00384 next_fu = BU_LIST_NEXT( faceuse, &fu->l );
00385 if( next_fu == fu->fumate_p )
00386 next_fu = BU_LIST_NEXT( faceuse, &next_fu->l );
00387
00388 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
00389 while( BU_LIST_NOT_HEAD( &lu->l, &fu->lu_hd ) )
00390 {
00391 struct loopuse *next_lu;
00392 struct loopuse *lu1;
00393 struct edgeuse *eu;
00394
00395 NMG_CK_LOOPUSE( lu );
00396
00397 next_lu = BU_LIST_NEXT( loopuse, &lu->l );
00398
00399 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00400 {
00401 lu = next_lu;
00402 continue;
00403 }
00404
00405
00406 lu_count = 0;
00407 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
00408 lu_count++;
00409
00410
00411 lu1 = BU_LIST_FIRST( loopuse, &fu->lu_hd );
00412 while( BU_LIST_NOT_HEAD( &lu1->l, &fu->lu_hd ) )
00413 {
00414 struct loopuse *next_lu1;
00415
00416 NMG_CK_LOOPUSE( lu1 );
00417
00418 next_lu1 = BU_LIST_PNEXT( loopuse, &lu1->l );
00419
00420 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_EDGEUSE_MAGIC )
00421 {
00422 lu1 = next_lu1;
00423 continue;
00424 }
00425
00426 if( lu1 == lu )
00427 {
00428 lu1 = next_lu1;
00429 continue;
00430 }
00431
00432 if( lu1->orientation == lu->orientation )
00433 {
00434 lu1 = next_lu1;
00435 continue;
00436 }
00437
00438
00439 lu1_count = 0;
00440 for( BU_LIST_FOR( eu, edgeuse, &lu1->down_hd ) )
00441 lu1_count++;
00442
00443 if( lu_count != lu1_count )
00444 {
00445 lu1 = next_lu1;
00446 continue;
00447 }
00448
00449 if( nmg_classify_lu_lu( lu, lu1, tol ) != NMG_CLASS_AonBshared )
00450 {
00451 lu1 = next_lu1;
00452 continue;
00453 }
00454
00455
00456
00457
00458
00459 if( next_lu1 == lu )
00460 next_lu1 = BU_LIST_NEXT( loopuse, &next_lu1->l );
00461
00462 if( next_lu == lu1 )
00463 next_lu = BU_LIST_NEXT( loopuse, &next_lu->l );
00464
00465 (void)nmg_klu( lu );
00466 if( nmg_klu( lu1 ) )
00467 {
00468
00469 if( nmg_kfu( fu ) )
00470 {
00471
00472 next_fu = (struct faceuse *)(&s->fu_hd);
00473 next_lu = (struct loopuse *)NULL;
00474 }
00475 else
00476 {
00477
00478 next_lu = (struct loopuse *)NULL;
00479 }
00480 }
00481 break;
00482 }
00483
00484 if( !next_lu )
00485 break;
00486
00487 lu = next_lu;
00488 }
00489 fu = next_fu;
00490 }
00491
00492
00493 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
00494 {
00495 NMG_CK_FACEUSE( fu );
00496
00497 if( fu->orientation != OT_SAME )
00498 continue;
00499
00500 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
00501 {
00502 struct loopuse *lu1;
00503
00504 NMG_CK_LOOPUSE( lu );
00505
00506
00507 lu1 = BU_LIST_FIRST( loopuse, &fu->lu_hd );
00508 while( BU_LIST_NOT_HEAD( &lu1->l, &fu->lu_hd ) )
00509 {
00510 struct loopuse *next_lu;
00511 struct loopuse *lu2;
00512 int found;
00513
00514 NMG_CK_LOOPUSE( lu1 );
00515
00516 next_lu = BU_LIST_PNEXT( loopuse, &lu1->l );
00517
00518 if( lu1 == lu )
00519 {
00520 lu1 = next_lu;
00521 continue;
00522 }
00523
00524 if( lu1->orientation != lu->orientation )
00525 {
00526 lu1 = next_lu;
00527 continue;
00528 }
00529
00530 if( nmg_classify_lu_lu( lu1, lu, tol ) != NMG_CLASS_AinB )
00531 {
00532 lu1 = next_lu;
00533 continue;
00534 }
00535
00536
00537
00538
00539
00540 found = 0;
00541 for( BU_LIST_FOR( lu2, loopuse, &fu->lu_hd ) )
00542 {
00543 int class1,class2;
00544
00545 NMG_CK_LOOPUSE( lu2 );
00546
00547 if( lu2 == lu || lu2 == lu1 )
00548 continue;
00549
00550 if( lu2->orientation == lu->orientation )
00551 continue;
00552
00553 class1 = nmg_classify_lu_lu( lu2, lu, tol );
00554 class2 = nmg_classify_lu_lu( lu1, lu2, tol );
00555
00556 if( class1 == NMG_CLASS_AinB &&
00557 class2 == NMG_CLASS_AinB )
00558 {
00559 found = 1;
00560 break;
00561 }
00562 }
00563 if( !found )
00564 {
00565
00566 (void) nmg_klu( lu1 );
00567 }
00568 lu1 = next_lu;
00569 }
00570 }
00571 }
00572
00573
00574
00575
00576 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
00577 {
00578 if( fu->orientation != OT_SAME )
00579 continue;
00580
00581 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
00582 {
00583 struct loopuse *lu1;
00584
00585 if( lu->orientation != OT_SAME )
00586 continue;
00587
00588 lu1 = BU_LIST_FIRST( loopuse, &fu->lu_hd );
00589 while( BU_LIST_NOT_HEAD( &lu1->l, &fu->lu_hd ) )
00590 {
00591 int class;
00592 struct loopuse *next_lu;
00593
00594 next_lu = BU_LIST_PNEXT( loopuse, &lu1->l );
00595
00596 if( lu1 == lu || lu1->orientation != OT_OPPOSITE )
00597 {
00598 lu1 = next_lu;
00599 continue;
00600 }
00601
00602 class = nmg_classify_lu_lu( lu, lu1, tol );
00603
00604 if( class == NMG_CLASS_AonBshared )
00605 {
00606 nmg_klu( lu1 );
00607 }
00608
00609 lu1 = next_lu;
00610 }
00611 }
00612 }
00613
00614 if (rt_g.NMG_debug & DEBUG_BASIC) {
00615 bu_log("nmg_rm_redundancies(s=x%x)\n", s);
00616 }
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626 void
00627 nmg_sanitize_s_lv(struct shell *s, int orient)
00628 {
00629 struct faceuse *fu;
00630 struct loopuse *lu;
00631 pointp_t pt;
00632
00633 NMG_CK_SHELL(s);
00634
00635
00636 fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
00637 while (BU_LIST_NOT_HEAD(fu, &s->fu_hd) ) {
00638
00639
00640
00641 lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
00642 while (BU_LIST_NOT_HEAD(lu, &fu->lu_hd)) {
00643 if (lu->orientation == orient) {
00644 lu = BU_LIST_PNEXT(loopuse,lu);
00645 nmg_klu(BU_LIST_PLAST(loopuse, lu));
00646 } else if (lu->orientation == OT_UNSPEC &&
00647 BU_LIST_FIRST_MAGIC(&lu->down_hd) ==
00648 NMG_VERTEXUSE_MAGIC) {
00649 register struct vertexuse *vu;
00650 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00651 pt = vu->v_p->vg_p->coord;
00652 VPRINT("nmg_sanitize_s_lv() OT_UNSPEC at", pt);
00653 lu = BU_LIST_PNEXT(loopuse,lu);
00654 } else {
00655 lu = BU_LIST_PNEXT(loopuse,lu);
00656 }
00657 }
00658
00659
00660
00661
00662 if (BU_LIST_PNEXT(faceuse, fu) == fu->fumate_p)
00663 fu = BU_LIST_PNEXT_PNEXT(faceuse, fu);
00664 else
00665 fu = BU_LIST_PNEXT(faceuse, fu);
00666
00667
00668 if (BU_LIST_IS_EMPTY( &(BU_LIST_PLAST(faceuse, fu))->lu_hd )) {
00669
00670
00671
00672 nmg_kfu(BU_LIST_PLAST(faceuse, fu));
00673 }
00674 }
00675
00676
00677 lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
00678 while (BU_LIST_NOT_HEAD(lu, &s->lu_hd) ) {
00679 if (lu->orientation == orient) {
00680 lu = BU_LIST_PNEXT(loopuse,lu);
00681 nmg_klu(BU_LIST_PLAST(loopuse, lu));
00682 } else if (lu->orientation == OT_UNSPEC &&
00683 BU_LIST_FIRST_MAGIC(&lu->down_hd) ==
00684 NMG_VERTEXUSE_MAGIC) {
00685 register struct vertexuse *vu;
00686 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00687 pt = vu->v_p->vg_p->coord;
00688 VPRINT("nmg_sanitize_s_lv() OT_UNSPEC at", pt);
00689 lu = BU_LIST_PNEXT(loopuse,lu);
00690 } else {
00691 lu = BU_LIST_PNEXT(loopuse,lu);
00692 }
00693 }
00694
00695 if (rt_g.NMG_debug & DEBUG_BASIC) {
00696 bu_log("nmg_sanitize_s_lv(s=x%x, orient=%d)\n", s, orient);
00697 }
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 void
00710 nmg_s_split_touchingloops(struct shell *s, const struct bn_tol *tol)
00711 {
00712 struct faceuse *fu;
00713 struct loopuse *lu;
00714
00715 NMG_CK_SHELL(s);
00716 BN_CK_TOL(tol);
00717
00718 if (rt_g.NMG_debug & DEBUG_BASIC) {
00719 bu_log("nmg_s_split_touching_loops(s=x%x, tol=x%x) START\n", s, tol);
00720 }
00721
00722
00723 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
00724 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
00725 (void)nmg_loop_split_at_touching_jaunt( lu, tol );
00726 nmg_split_touchingloops( lu, tol );
00727 }
00728 }
00729 for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) ) {
00730 (void)nmg_loop_split_at_touching_jaunt( lu, tol );
00731 nmg_split_touchingloops( lu, tol );
00732 }
00733
00734
00735 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
00736 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
00737 if( lu->orientation != OT_UNSPEC ) continue;
00738 nmg_lu_reorient( lu );
00739 }
00740 }
00741
00742 if (rt_g.NMG_debug & DEBUG_BASIC) {
00743 bu_log("nmg_s_split_touching_loops(s=x%x, tol=x%x) END\n", s, tol);
00744 }
00745 }
00746
00747
00748
00749
00750
00751
00752 void
00753 nmg_s_join_touchingloops(struct shell *s, const struct bn_tol *tol)
00754 {
00755 struct faceuse *fu;
00756 struct loopuse *lu;
00757
00758 NMG_CK_SHELL(s);
00759 BN_CK_TOL(tol);
00760
00761 if (rt_g.NMG_debug & DEBUG_BASIC) {
00762 bu_log("nmg_s_join_touching_loops(s=x%x, tol=x%x) START\n", s, tol);
00763 }
00764
00765
00766 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
00767 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
00768 nmg_join_touchingloops( lu );
00769 }
00770 }
00771 for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) ) {
00772 nmg_join_touchingloops( lu );
00773 }
00774
00775
00776 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
00777 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
00778 if( lu->orientation != OT_UNSPEC ) continue;
00779 nmg_lu_reorient( lu );
00780 }
00781 }
00782
00783 if (rt_g.NMG_debug & DEBUG_BASIC) {
00784 bu_log("nmg_s_join_touching_loops(s=x%x, tol=x%x) END\n", s, tol);
00785 }
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 void
00800 nmg_js(register struct shell *s1, register struct shell *s2, const struct bn_tol *tol)
00801
00802
00803
00804 {
00805 struct faceuse *fu2;
00806 struct faceuse *nextfu;
00807 struct loopuse *lu;
00808 struct loopuse *nextlu;
00809 struct edgeuse *eu;
00810 struct edgeuse *nexteu;
00811 struct vertexuse *vu;
00812
00813 NMG_CK_SHELL(s1);
00814 NMG_CK_SHELL(s2);
00815 BN_CK_TOL(tol);
00816
00817 if (rt_g.NMG_debug & DEBUG_BASIC) {
00818 bu_log("nmg_js(s1=x%x, s2=x%x) START\n", s1, s2);
00819 }
00820
00821 if( rt_g.NMG_debug & DEBUG_VERIFY )
00822 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
00823
00824
00825
00826
00827
00828 fu2 = BU_LIST_FIRST( faceuse, &s2->fu_hd );
00829 while( BU_LIST_NOT_HEAD( fu2, &s2->fu_hd ) ) {
00830 struct faceuse *fu1;
00831
00832 nextfu = BU_LIST_PNEXT( faceuse, fu2 );
00833
00834
00835 if( fu2->orientation != OT_SAME ) {
00836 fu2 = nextfu;
00837 continue;
00838 }
00839
00840
00841 NMG_CK_FACEUSE(fu2);
00842 NMG_CK_FACE(fu2->f_p);
00843
00844 if( nextfu == fu2->fumate_p )
00845 nextfu = BU_LIST_PNEXT(faceuse, nextfu);
00846
00847
00848
00849
00850
00851
00852 fu1 = nmg_find_fu_with_fg_in_s( s1, fu2 );
00853 if( fu1 && fu1->orientation == OT_SAME ) {
00854 if (rt_g.NMG_debug & DEBUG_BASIC)
00855 bu_log("nmg_js(): shared face_g_plane, doing nmg_jf()\n");
00856 nmg_jf( fu1, fu2 );
00857
00858 fu2 = fu1;
00859 } else {
00860 nmg_mv_fu_between_shells( s1, s2, fu2 );
00861 }
00862
00863 fu2 = nextfu;
00864 }
00865 #if 0
00866 if( rt_g.NMG_debug & DEBUG_VERIFY )
00867 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
00868 #endif
00869
00870
00871
00872
00873
00874
00875 lu = BU_LIST_FIRST( loopuse, &s2->lu_hd );
00876 while( BU_LIST_NOT_HEAD( lu, &s2->lu_hd ) ) {
00877 nextlu = BU_LIST_PNEXT( loopuse, lu );
00878
00879 NMG_CK_LOOPUSE(lu);
00880 NMG_CK_LOOP( lu->l_p );
00881 if( nextlu == lu->lumate_p )
00882 nextlu = BU_LIST_PNEXT(loopuse, nextlu);
00883
00884 nmg_mv_lu_between_shells( s1, s2, lu );
00885 lu = nextlu;
00886 }
00887 #if 0
00888 if( rt_g.NMG_debug & DEBUG_VERIFY )
00889 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
00890 #endif
00891
00892
00893
00894
00895 eu = BU_LIST_FIRST( edgeuse, &s2->eu_hd );
00896 while( BU_LIST_NOT_HEAD( eu, &s2->eu_hd ) ) {
00897 nexteu = BU_LIST_PNEXT( edgeuse, eu );
00898
00899
00900 NMG_CK_EDGEUSE(eu);
00901 NMG_CK_EDGE( eu->e_p );
00902 if( nexteu == eu->eumate_p )
00903 nexteu = BU_LIST_PNEXT(edgeuse, nexteu);
00904 nmg_mv_eu_between_shells( s1, s2, eu );
00905 eu = nexteu;
00906 }
00907 #if 0
00908 if( rt_g.NMG_debug & DEBUG_VERIFY )
00909 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
00910 #endif
00911
00912
00913
00914
00915 if( (vu = s2->vu_p) ) {
00916 NMG_CK_VERTEXUSE( vu );
00917 NMG_CK_VERTEX( vu->v_p );
00918 nmg_mv_vu_between_shells( s1, s2, vu );
00919 s2->vu_p = (struct vertexuse *)0;
00920 }
00921
00922 if( BU_LIST_NON_EMPTY( &s2->fu_hd ) ) {
00923 rt_bomb("nmg_js(): s2 still has faces!\n");
00924 }
00925 if( BU_LIST_NON_EMPTY( &s2->lu_hd ) ) {
00926 rt_bomb("nmg_js(): s2 still has wire loops!\n");
00927 }
00928 if( BU_LIST_NON_EMPTY( &s2->eu_hd ) ) {
00929 rt_bomb("nmg_js(): s2 still has wire edges!\n");
00930 }
00931 if(s2->vu_p) {
00932 rt_bomb("nmg_js(): s2 still has verts!\n");
00933 }
00934
00935
00936 nmg_ks( s2 );
00937
00938
00939 nmg_s_radial_harmonize( s1, tol );
00940
00941 if( rt_g.NMG_debug & DEBUG_VERIFY )
00942 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
00943
00944 if (rt_g.NMG_debug & DEBUG_BASIC) {
00945 bu_log("nmg_js(s1=x%x, s2=x%x) END\n", s1, s2);
00946 }
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 void
00965 nmg_invert_shell(struct shell *s, const struct bn_tol *tol)
00966 {
00967 struct model *m;
00968 struct faceuse *fu;
00969 char *tags;
00970
00971 NMG_CK_SHELL(s);
00972 m = s->r_p->m_p;
00973 NMG_CK_MODEL(m);
00974 BN_CK_TOL(tol);
00975
00976 if (rt_g.NMG_debug & DEBUG_BASIC) {
00977 bu_log("nmg_invert_shell(x%x)\n", s);
00978 }
00979
00980
00981 tags = bu_calloc( m->maxindex+1, 1, "nmg_invert_shell() tags[]" );
00982
00983 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
00984 NMG_CK_FACEUSE(fu);
00985
00986 if( NMG_INDEX_TEST( tags, fu->f_p ) ) continue;
00987 NMG_INDEX_SET( tags, fu->f_p );
00988
00989 nmg_reverse_face(fu);
00990 }
00991 bu_free( tags, "nmg_invert_shell() tags[]" );
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 struct faceuse *
01056 nmg_cmface(struct shell *s, struct vertex ***verts, int n)
01057 {
01058 struct faceuse *fu;
01059 struct edgeuse *eu, *eur, *euold = NULL;
01060 struct loopuse *lu;
01061 struct vertexuse *vu;
01062 int i;
01063
01064 NMG_CK_SHELL(s);
01065
01066 if (n < 1) {
01067 bu_log("nmg_cmface(s=x%x, verts=x%x, n=%d.)\n",
01068 s, verts, n );
01069 rt_bomb("nmg_cmface() trying to make bogus face\n");
01070 }
01071
01072
01073 if (!verts) {
01074 bu_log("nmg_cmface(s=x%x, verts=x%x, n=%d.) null pointer to array start\n",
01075 s, verts, n );
01076 rt_bomb("nmg_cmface\n");
01077 }
01078
01079
01080 for (i=0 ; i < n ; ++i) {
01081 if (verts[i]) {
01082 if (*verts[i]) {
01083
01084 NMG_CK_VERTEX(*verts[i]);
01085 }
01086 } else {
01087 bu_log("nmg_cmface(s=x%x, verts=x%x, n=%d.) verts[%d]=NULL\n",
01088 s, verts, n, i );
01089 rt_bomb("nmg_cmface\n");
01090 }
01091 }
01092
01093 lu = nmg_mlv(&s->l.magic, *verts[0], OT_SAME);
01094 fu = nmg_mf(lu);
01095 fu->orientation = OT_SAME;
01096 fu->fumate_p->orientation = OT_OPPOSITE;
01097 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd);
01098 NMG_CK_VERTEXUSE(vu);
01099 eu = nmg_meonvu(vu);
01100 NMG_CK_EDGEUSE(eu);
01101
01102 if (!(*verts[0])) {
01103 NMG_CK_VERTEXUSE(eu->vu_p);
01104 NMG_CK_VERTEX(eu->vu_p->v_p);
01105 *verts[0] = eu->vu_p->v_p;
01106 }
01107
01108 for (i = n-1 ; i > 0 ; i--) {
01109
01110 euold = BU_LIST_FIRST( edgeuse, &lu->down_hd );
01111 NMG_CK_EDGEUSE(euold);
01112
01113 if (rt_g.NMG_debug & DEBUG_CMFACE)
01114 bu_log("nmg_cmface() euold: %8x\n", euold);
01115
01116
01117
01118
01119 if (*verts[i]) {
01120
01121 eur = nmg_findeu(*verts[(i+1)%n], *verts[i], s, euold, 1);
01122 eu = nmg_eusplit(*verts[i], euold, 0);
01123 if (eur) {
01124 nmg_je(eur, eu);
01125
01126 if (rt_g.NMG_debug & DEBUG_CMFACE)
01127 bu_log("nmg_cmface() found another edgeuse (%8x) between %8x and %8x\n",
01128 eur, *verts[(i+1)%n], *verts[i]);
01129 } else {
01130 if (rt_g.NMG_debug & DEBUG_CMFACE)
01131 bu_log("nmg_cmface() didn't find edge from verts[%d]%8x to verts[%d]%8x\n",
01132 i+1, *verts[(i+1)%n], i, *verts[i]);
01133 }
01134 } else {
01135 eu = nmg_eusplit(*verts[i], euold, 0);
01136 *verts[i] = eu->vu_p->v_p;
01137
01138 if (rt_g.NMG_debug & DEBUG_CMFACE) {
01139 bu_log("nmg_cmface() *verts[%d] was null, is now %8x\n",
01140 i, *verts[i]);
01141 }
01142 }
01143 }
01144
01145 if( n > 1 ) {
01146 if ((eur = nmg_findeu(*verts[0], *verts[1], s, euold, 1))) {
01147 nmg_je(eur, euold);
01148 } else {
01149 if (rt_g.NMG_debug & DEBUG_CMFACE)
01150 bu_log("nmg_cmface() didn't find edge from verts[%d]%8x to verts[%d]%8x\n",
01151 0, *verts[0], 1, *verts[1]);
01152 }
01153 }
01154
01155 if(rt_g.NMG_debug & DEBUG_BASIC) {
01156
01157 euold = BU_LIST_FIRST( edgeuse, &lu->down_hd );
01158 NMG_CK_EDGEUSE(euold);
01159 if( euold->vu_p->v_p != *verts[0] ) {
01160 bu_log("ERROR nmg_cmface() lu first vert s/b x%x, was x%x\n",
01161 *verts[0], euold->vu_p->v_p );
01162 for( i=0; i < n; i++ ) {
01163 bu_log(" *verts[%2d]=x%x, eu->vu_p->v_p=x%x\n",
01164 i, *verts[i], euold->vu_p->v_p);
01165 euold = BU_LIST_PNEXT_CIRC( edgeuse, &euold->l );
01166 }
01167 rt_bomb("nmg_cmface() bogus eu ordering\n");
01168 }
01169 }
01170
01171 if (rt_g.NMG_debug & DEBUG_BASIC) {
01172 bu_log("nmg_cmface(s=x%x, verts[]=x%x, n=%d) fu=x%x\n",
01173 s, verts, n, fu);
01174 }
01175 return (fu);
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 struct faceuse *
01206 nmg_cface(struct shell *s, struct vertex **verts, int n)
01207 {
01208 struct faceuse *fu;
01209 struct edgeuse *eu;
01210 struct loopuse *lu;
01211 struct vertexuse *vu;
01212 int i;
01213
01214 NMG_CK_SHELL(s);
01215 if (n < 1) {
01216 bu_log("nmg_cface(s=x%x, verts=x%x, n=%d.)\n",
01217 s, verts, n );
01218 rt_bomb("nmg_cface() trying to make bogus face\n");
01219 }
01220
01221 if (verts) {
01222 for (i=0 ; i < n ; ++i) {
01223 if (verts[i]) {
01224 NMG_CK_VERTEX(verts[i]);
01225 }
01226 }
01227 lu = nmg_mlv(&s->l.magic, verts[n-1], OT_SAME);
01228 fu = nmg_mf(lu);
01229 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01230 eu = nmg_meonvu(vu);
01231
01232 if (!verts[n-1])
01233 verts[n-1] = eu->vu_p->v_p;
01234
01235 for (i = n-2 ; i >= 0 ; i--) {
01236 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01237 eu = nmg_eusplit(verts[i], eu, 0);
01238 if (!verts[i])
01239 verts[i] = eu->vu_p->v_p;
01240 }
01241
01242 } else {
01243 lu = nmg_mlv(&s->l.magic, (struct vertex *)NULL, OT_SAME);
01244 fu = nmg_mf(lu);
01245 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01246 eu = nmg_meonvu(vu);
01247 while (--n) {
01248 (void)nmg_eusplit((struct vertex *)NULL, eu, 0);
01249 }
01250 }
01251 if (rt_g.NMG_debug & DEBUG_BASIC) {
01252 bu_log("nmg_cface(s=x%x, verts[]=x%x, n=%d) fu=x%x\n",
01253 s, verts, n, fu);
01254 }
01255 return (fu);
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 struct faceuse *
01286 nmg_add_loop_to_face(struct shell *s, struct faceuse *fu, struct vertex **verts, int n, int dir)
01287 {
01288 int i;
01289 struct edgeuse *eu;
01290 struct loopuse *lu;
01291 struct vertexuse *vu;
01292
01293 NMG_CK_SHELL(s);
01294 if (n < 1) {
01295 bu_log("nmg_add_loop_to_face(s=x%x, verts=x%x, n=%d.)\n",
01296 s, verts, n );
01297 rt_bomb("nmg_add_loop_to_face: request to make 0 faces\n");
01298 }
01299
01300 if (verts) {
01301 if (!fu) {
01302 lu = nmg_mlv(&s->l.magic, verts[n-1], dir);
01303 fu = nmg_mf(lu);
01304 } else {
01305 lu = nmg_mlv(&fu->l.magic, verts[n-1], dir);
01306 }
01307 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01308 eu = nmg_meonvu(vu);
01309 if (!verts[n-1])
01310 verts[n-1] = eu->vu_p->v_p;
01311
01312 for (i = n-2 ; i >= 0 ; i--) {
01313 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01314 eu = nmg_eusplit(verts[i], eu, 0);
01315 if (!verts[i])
01316 verts[i] = eu->vu_p->v_p;
01317 }
01318 } else {
01319 if (!fu) {
01320 lu = nmg_mlv(&s->l.magic, (struct vertex *)NULL, dir);
01321 fu = nmg_mf(lu);
01322 } else {
01323 lu = nmg_mlv(&fu->l.magic, (struct vertex *)NULL, dir);
01324 }
01325 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01326 eu = nmg_meonvu(vu);
01327 while (--n) {
01328 (void)nmg_eusplit((struct vertex *)NULL, eu, 0);
01329 }
01330 }
01331 if (rt_g.NMG_debug & DEBUG_BASIC) {
01332 bu_log("nmg_add_loop_to_face(s=x%x, fu=x%x, verts[]=x%x, n=%d, %s) fu=x%x\n",
01333 s, fu, verts, n,
01334 nmg_orientation(dir) );
01335 }
01336 return (fu);
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 int
01387 nmg_fu_planeeqn(struct faceuse *fu, const struct bn_tol *tol)
01388 {
01389 struct edgeuse *eu, *eu_final, *eu_next;
01390 struct loopuse *lu;
01391 plane_t plane;
01392 struct vertex *a, *b, *c;
01393 register int both_equal;
01394
01395 BN_CK_TOL(tol);
01396
01397 NMG_CK_FACEUSE(fu);
01398 lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
01399 NMG_CK_LOOPUSE(lu);
01400
01401 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
01402 {
01403 bu_log( "nmg_fu_planeeqn(): First loopuse does not contain edges\n" );
01404 return(-1);
01405 }
01406 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01407 NMG_CK_EDGEUSE(eu);
01408 NMG_CK_VERTEXUSE(eu->vu_p);
01409 a = eu->vu_p->v_p;
01410 NMG_CK_VERTEX(a);
01411 NMG_CK_VERTEX_G(a->vg_p);
01412
01413 eu_next = eu;
01414 do {
01415 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, eu_next);
01416 NMG_CK_EDGEUSE(eu_next);
01417 if( eu_next == eu )
01418 {
01419 bu_log( "nmg_fu_planeeqn(): First loopuse contains only one edgeuse\n" );
01420 return -1;
01421 }
01422 NMG_CK_VERTEXUSE(eu_next->vu_p);
01423 b = eu_next->vu_p->v_p;
01424 NMG_CK_VERTEX(b);
01425 NMG_CK_VERTEX_G(b->vg_p);
01426 } while( (b == a
01427 || bn_pt3_pt3_equal(a->vg_p->coord, b->vg_p->coord, tol))
01428 && eu_next->vu_p != eu->vu_p );
01429
01430 eu_final = eu_next;
01431 do {
01432 eu_final = BU_LIST_PNEXT_CIRC(edgeuse, eu_final);
01433 NMG_CK_EDGEUSE(eu_final);
01434 if( eu_final == eu )
01435 {
01436 bu_log( "nmg_fu_planeeqn(): Cannot find three distinct vertices\n" );
01437 return -1;
01438 }
01439 NMG_CK_VERTEXUSE(eu_final->vu_p);
01440 c = eu_final->vu_p->v_p;
01441 NMG_CK_VERTEX(c);
01442 NMG_CK_VERTEX_G(c->vg_p);
01443 both_equal = (c == b) ||
01444 bn_pt3_pt3_equal(a->vg_p->coord, c->vg_p->coord, tol) ||
01445 bn_pt3_pt3_equal(b->vg_p->coord, c->vg_p->coord, tol);
01446 } while( (both_equal
01447 || bn_3pts_collinear(a->vg_p->coord, b->vg_p->coord,
01448 c->vg_p->coord, tol))
01449 && eu_next->vu_p != eu->vu_p );
01450
01451 if (bn_mk_plane_3pts(plane,
01452 a->vg_p->coord, b->vg_p->coord, c->vg_p->coord, tol) < 0 ) {
01453 bu_log("nmg_fu_planeeqn(): bn_mk_plane_3pts failed on (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n",
01454 V3ARGS( a->vg_p->coord ),
01455 V3ARGS( b->vg_p->coord ),
01456 V3ARGS( c->vg_p->coord ) );
01457 HPRINT("plane", plane);
01458 return(-1);
01459 }
01460 if (plane[0] == 0.0 && plane[1] == 0.0 && plane[2] == 0.0) {
01461 bu_log("nmg_fu_planeeqn(): Bad plane equation from bn_mk_plane_3pts\n" );
01462 HPRINT("plane", plane);
01463 return(-1);
01464 }
01465 nmg_face_g( fu, plane);
01466
01467
01468 if( nmg_ck_fu_verts( fu, fu->f_p, tol ) != 0 ) {
01469 bu_log("nmg_fu_planeeqn(fu=x%x) ERROR, verts are not within tol of face\n" , fu );
01470 return -1;
01471 }
01472
01473 if (rt_g.NMG_debug & DEBUG_BASIC) {
01474 bu_log("nmg_fu_planeeqn(fu=x%x, tol=x%x)\n", fu, tol);
01475 }
01476 return(0);
01477 }
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 void
01489 nmg_gluefaces(struct faceuse **fulist, int n, const struct bn_tol *tol)
01490 {
01491 struct shell *s;
01492 struct loopuse *lu;
01493 struct edgeuse *eu;
01494 int i;
01495 int f_no;
01496
01497 NMG_CK_FACEUSE(fulist[0]);
01498 s = fulist[0]->s_p;
01499 NMG_CK_SHELL(s);
01500
01501
01502 for (i = 0 ; i < n ; ++i) {
01503 register struct faceuse *fu;
01504
01505 fu = fulist[i];
01506 NMG_CK_FACEUSE(fu);
01507 if (fu->s_p != s) {
01508 bu_log("nmg_gluefaces() in %s at %d. faceuses don't share parent\n",
01509 __FILE__, __LINE__);
01510 rt_bomb("nmg_gluefaces\n");
01511 }
01512 }
01513
01514 for (i=0 ; i < n ; ++i) {
01515 for( BU_LIST_FOR( lu , loopuse , &fulist[i]->lu_hd ) ) {
01516 NMG_CK_LOOPUSE( lu );
01517
01518 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
01519 continue;
01520
01521 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
01522 for( f_no = i+1; f_no < n; f_no++ ) {
01523 struct loopuse *lu2;
01524 register struct edgeuse *eu2;
01525
01526 for( BU_LIST_FOR( lu2 , loopuse , &fulist[f_no]->lu_hd ) ) {
01527 NMG_CK_LOOPUSE( lu2 );
01528 if( BU_LIST_FIRST_MAGIC(&lu2->down_hd) != NMG_EDGEUSE_MAGIC )
01529 continue;
01530 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) ) {
01531 if (EDGESADJ(eu, eu2))
01532 nmg_radial_join_eu(eu, eu2, tol);
01533 }
01534 }
01535 }
01536 }
01537 }
01538 }
01539
01540 if (rt_g.NMG_debug & DEBUG_BASIC) {
01541 bu_log("nmg_gluefaces(fulist=x%x, n=%d)\n", fulist, n);
01542 }
01543 }
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 int
01557 nmg_simplify_face(struct faceuse *fu)
01558 {
01559 struct loopuse *lu;
01560 int ret_val;
01561
01562 NMG_CK_FACEUSE(fu);
01563
01564 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
01565 nmg_simplify_loop(lu);
01566 }
01567
01568 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
01569 if( nmg_kill_snakes(lu) ) {
01570 struct loopuse *klu = lu;
01571 lu = BU_LIST_PREV( loopuse, &lu->l );
01572 nmg_klu(klu);
01573 }
01574 }
01575
01576 ret_val = BU_LIST_IS_EMPTY(&fu->lu_hd);
01577
01578 if (rt_g.NMG_debug & DEBUG_BASIC) {
01579 bu_log("nmg_simplify_face(fut=x%x) return=%d\n", fu, ret_val);
01580 }
01581
01582 return( ret_val );
01583 }
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 void
01624 nmg_reverse_face(register struct faceuse *fu)
01625 {
01626 register struct faceuse *fumate;
01627
01628 NMG_CK_FACEUSE(fu);
01629 fumate = fu->fumate_p;
01630 NMG_CK_FACEUSE(fumate);
01631 NMG_CK_FACE(fu->f_p);
01632 NMG_CK_FACE_G_EITHER(fu->f_p->g.magic_p);
01633
01634
01635 fu->f_p->flip = !fu->f_p->flip;
01636
01637
01638 if (fu->orientation == OT_SAME) {
01639 if (fumate->orientation != OT_OPPOSITE) {
01640 bu_log("nmg_reverse_face(fu=x%x) fu:SAME, fumate:%d\n",
01641 fu, fumate->orientation);
01642 rt_bomb("nmg_reverse_face() orientation clash\n");
01643 } else {
01644 fu->orientation = OT_OPPOSITE;
01645 fumate->orientation = OT_SAME;
01646 }
01647 } else if (fu->orientation == OT_OPPOSITE) {
01648 if (fumate->orientation != OT_SAME) {
01649 bu_log("nmg_reverse_face(fu=x%x) fu:OPPOSITE, fumate:%d\n",
01650 fu, fumate->orientation);
01651 rt_bomb("nmg_reverse_face() orientation clash\n");
01652 } else {
01653 fu->orientation = OT_SAME;
01654 fumate->orientation = OT_OPPOSITE;
01655 }
01656 } else {
01657
01658 bu_log("ERROR nmg_reverse_face(fu=x%x), orientation=%d.\n",
01659 fu, fu->orientation );
01660 }
01661
01662 if (rt_g.NMG_debug & DEBUG_BASIC) {
01663 bu_log("nmg_reverse_face(fu=x%x) fumate=x%x\n", fu, fumate);
01664 }
01665 }
01666
01667 #if 0
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705 int
01706 nmg_face_fix_radial_parity( fu, tol )
01707 struct faceuse *fu;
01708 const struct bn_tol *tol;
01709 {
01710 struct loopuse *lu;
01711 struct edgeuse *eu;
01712 struct faceuse *fu2;
01713 struct shell *s;
01714 long count = 0;
01715
01716 NMG_CK_FACEUSE( fu );
01717 s = fu->s_p;
01718 NMG_CK_SHELL(s);
01719 BN_CK_TOL(tol);
01720
01721
01722 if( fu->orientation == OT_SAME )
01723 fu2 = fu;
01724 else
01725 fu2 = fu->fumate_p;
01726
01727 for( BU_LIST_FOR( lu , loopuse , &fu2->lu_hd ) ) {
01728 NMG_CK_LOOPUSE( lu );
01729
01730
01731 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01732 continue;
01733
01734
01735
01736
01737
01738
01739 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) ) {
01740 struct edgeuse *eumate;
01741 struct edgeuse *before;
01742 struct edgeuse *sbefore;
01743 struct edgeuse *after;
01744
01745 eumate = eu->eumate_p;
01746 before = eu->radial_p;
01747 after = eumate->radial_p;
01748 NMG_CK_EDGEUSE(eumate);
01749 NMG_CK_EDGEUSE(before);
01750 NMG_CK_EDGEUSE(after);
01751
01752
01753 if( before == eumate )
01754 continue;
01755
01756
01757
01758
01759
01760
01761 for( sbefore = before;
01762 sbefore != eu && sbefore != eumate;
01763 sbefore = sbefore->eumate_p->radial_p
01764 ) {
01765 struct faceuse *bfu;
01766 if( nmg_find_s_of_eu(sbefore) != s ) continue;
01767
01768 bfu = nmg_find_fu_of_eu(sbefore);
01769
01770 if( !bfu ) continue;
01771 if( bfu->f_p == fu->f_p ) continue;
01772
01773 break;
01774 }
01775
01776
01777 if( sbefore == eu || sbefore == eumate )
01778 continue;
01779
01780
01781
01782
01783
01784
01785 if( sbefore->up.lu_p->up.fu_p->orientation == OT_SAME )
01786 continue;
01787
01788 #if 0
01789 bu_log("sbefore eu=x%x, before=x%x, eu=x%x, eumate=x%x, after=x%x\n",
01790 sbefore, before, eu, eumate, after );
01791 nmg_pr_fu_around_eu(eu, tol );
01792 #endif
01793
01794
01795
01796
01797 before->radial_p = eumate;
01798 eumate->radial_p = before;
01799
01800 after->radial_p = eu;
01801 eu->radial_p = after;
01802 count++;
01803 if( rt_g.NMG_debug & DEBUG_BASIC ) {
01804 bu_log("nmg_face_fix_radial_parity() exchanging eu=x%x & eumate=x%x on edge x%x\n",
01805 eu, eumate, eu->e_p);
01806 }
01807 #if 0
01808
01809 if( rt_g.NMG_debug ) {
01810 nmg_pr_fu_around_eu(eu, tol );
01811 if( nmg_check_radial( eu, tol ) )
01812 rt_bomb("nmg_face_fix_radial_parity(): nmg_check_radial failed\n");
01813 }
01814 #endif
01815 }
01816 }
01817
01818 if (rt_g.NMG_debug & DEBUG_BASIC) {
01819 bu_log("nmg_face_fix_radial_parity(fu=x%x) returns %d\n", fu, count);
01820 }
01821
01822 return count;
01823 }
01824 #endif
01825
01826
01827
01828
01829
01830
01831 void
01832 nmg_mv_fu_between_shells(struct shell *dest, register struct shell *src, register struct faceuse *fu)
01833 {
01834 register struct faceuse *fumate;
01835
01836 NMG_CK_FACEUSE(fu);
01837 fumate = fu->fumate_p;
01838 NMG_CK_FACEUSE(fumate);
01839
01840 if (fu->s_p != src) {
01841 bu_log("nmg_mv_fu_between_shells(dest=x%x, src=x%x, fu=x%x), fu->s_p=x%x isnt src shell\n",
01842 dest, src, fu, fu->s_p );
01843 rt_bomb("fu->s_p isnt source shell\n");
01844 }
01845 if (fumate->s_p != src) {
01846 bu_log("nmg_mv_fu_between_shells(dest=x%x, src=x%x, fu=x%x), fumate->s_p=x%x isn't src shell\n",
01847 dest, src, fu, fumate->s_p );
01848 rt_bomb("fumate->s_p isnt source shell\n");
01849 }
01850
01851
01852 BU_LIST_DEQUEUE( &fu->l );
01853 if( BU_LIST_IS_EMPTY( &src->fu_hd ) ) {
01854
01855 bu_log("nmg_mv_fu_between_shells(dest=x%x, src=x%x, fu=x%x), fumate=x%x not in src shell\n",
01856 dest, src, fu, fumate );
01857 rt_bomb("src shell emptied before finding fumate\n");
01858 }
01859
01860
01861 BU_LIST_DEQUEUE( &fumate->l );
01862
01863
01864
01865
01866
01867 if( fu->orientation == OT_SAME ) {
01868 BU_LIST_APPEND( &dest->fu_hd, &fu->l );
01869 BU_LIST_APPEND( &fu->l, &fumate->l );
01870 } else {
01871 BU_LIST_APPEND( &dest->fu_hd, &fumate->l );
01872 BU_LIST_APPEND( &fumate->l, &fu->l );
01873 }
01874
01875 fu->s_p = dest;
01876 fumate->s_p = dest;
01877
01878 if (rt_g.NMG_debug & DEBUG_BASIC) {
01879 bu_log("nmg_mv_fu_between_shells(dest=x%x, src=x%x, fu=x%x)\n", dest , src , fu);
01880 }
01881 }
01882
01883
01884
01885
01886
01887
01888
01889 static void
01890 nmg_move_fu_fu(register struct faceuse *dest_fu, register struct faceuse *src_fu)
01891 {
01892 register struct loopuse *lu;
01893
01894 NMG_CK_FACEUSE(dest_fu);
01895 NMG_CK_FACEUSE(src_fu);
01896
01897 if( dest_fu->orientation != src_fu->orientation )
01898 rt_bomb("nmg_move_fu_fu: differing orientations\n");
01899
01900
01901 while( BU_LIST_WHILE( lu, loopuse, &src_fu->lu_hd ) ) {
01902 BU_LIST_DEQUEUE( &(lu->l) );
01903 BU_LIST_INSERT( &(dest_fu->lu_hd), &(lu->l) );
01904 lu->up.fu_p = dest_fu;
01905 }
01906
01907
01908 if (rt_g.NMG_debug & DEBUG_BASIC) {
01909 bu_log("nmg_move_fu_fu(dest_fu=x%x, src_fu=x%x)\n", dest_fu , src_fu);
01910 }
01911 }
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921 void
01922 nmg_jf(register struct faceuse *dest_fu, register struct faceuse *src_fu)
01923 {
01924 NMG_CK_FACEUSE(dest_fu);
01925 NMG_CK_FACEUSE(src_fu);
01926
01927 if (rt_g.NMG_debug & DEBUG_BASIC) {
01928 bu_log("nmg_jf(dest_fu=x%x, src_fu=x%x)\n", dest_fu, src_fu);
01929 }
01930
01931 if( src_fu->f_p == dest_fu->f_p )
01932 rt_bomb("nmg_jf() src and dest faces are the same\n");
01933
01934 if( dest_fu->orientation == src_fu->orientation ) {
01935 nmg_move_fu_fu(dest_fu, src_fu);
01936 nmg_move_fu_fu(dest_fu->fumate_p, src_fu->fumate_p);
01937 } else {
01938 nmg_move_fu_fu(dest_fu, src_fu->fumate_p);
01939 nmg_move_fu_fu(dest_fu->fumate_p, src_fu);
01940 }
01941
01942 nmg_kfu(src_fu);
01943
01944 }
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 struct faceuse *
01959 nmg_dup_face(struct faceuse *fu, struct shell *s)
01960 {
01961 struct loopuse *new_lu, *lu;
01962 struct faceuse *new_fu = (struct faceuse *)NULL;
01963 struct model *m;
01964 struct model *m_f;
01965 plane_t pl;
01966 long **trans_tbl;
01967 long tbl_size;
01968
01969 NMG_CK_FACEUSE(fu);
01970 NMG_CK_FACE(fu->f_p);
01971 NMG_CK_SHELL(s);
01972
01973
01974
01975
01976 m = nmg_find_model( (long *)s );
01977 tbl_size = m->maxindex;
01978
01979 m_f = nmg_find_model( (long *)fu );
01980 if (m != m_f)
01981 tbl_size += m_f->maxindex;
01982
01983
01984 trans_tbl = (long **)bu_calloc(tbl_size*2, sizeof(long *),
01985 "nmg_dup_face trans_tbl");
01986
01987 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
01988 if (rt_g.NMG_debug & DEBUG_BASIC)
01989 bu_log("nmg_dup_face() duping %s loop...",
01990 nmg_orientation(lu->orientation));
01991 if (new_fu) {
01992 new_lu = nmg_dup_loop(lu, &new_fu->l.magic, trans_tbl);
01993 } else {
01994 new_lu = nmg_dup_loop(lu, &s->l.magic, trans_tbl);
01995 new_fu = nmg_mf(new_lu);
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005 if (lu->orientation != OT_SAME) {
02006 new_lu->orientation = lu->orientation;
02007 new_lu->lumate_p->orientation =
02008 lu->lumate_p->orientation;
02009 }
02010 }
02011 if (rt_g.NMG_debug & DEBUG_BASIC)
02012 bu_log(". Duped %s loop\n",
02013 nmg_orientation(new_lu->orientation));
02014 }
02015
02016
02017 switch (*fu->f_p->g.magic_p) {
02018 case NMG_FACE_G_PLANE_MAGIC:
02019 NMG_GET_FU_PLANE( pl, fu );
02020 nmg_face_g(new_fu, pl);
02021 break;
02022 case NMG_FACE_G_SNURB_MAGIC:
02023 {
02024 struct face_g_snurb *old = fu->f_p->g.snurb_p;
02025 struct face_g_snurb *new;
02026
02027 nmg_face_g_snurb(new_fu,
02028 old->order[0], old->order[1],
02029 old->u.k_size, old->v.k_size,
02030 NULL, NULL,
02031 old->s_size[0], old->s_size[1],
02032 old->pt_type,
02033 NULL );
02034 new = new_fu->f_p->g.snurb_p;
02035
02036 bcopy( old->u.knots, new->u.knots, old->u.k_size*sizeof(fastf_t) );
02037 bcopy( old->v.knots, new->v.knots, old->v.k_size*sizeof(fastf_t) );
02038
02039 bcopy( old->ctl_points, new->ctl_points,
02040 old->s_size[0] * old->s_size[1] *
02041 RT_NURB_EXTRACT_COORDS(old->pt_type) *
02042 sizeof(fastf_t) );
02043 }
02044 }
02045 new_fu->orientation = fu->orientation;
02046 new_fu->fumate_p->orientation = fu->fumate_p->orientation;
02047
02048 bu_free((char *)trans_tbl, "nmg_dup_face trans_tbl");
02049
02050 if (rt_g.NMG_debug & DEBUG_BASIC) {
02051 bu_log("nmg_dup_face(fu=x%x, s=x%x) new_fu=x%x\n",
02052 fu, s, new_fu);
02053 }
02054
02055 return(new_fu);
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 void
02079 nmg_jl(struct loopuse *lu, struct edgeuse *eu)
02080 {
02081 struct loopuse *lu2;
02082 struct edgeuse *eu_r;
02083 struct edgeuse *nexteu;
02084
02085 NMG_CK_LOOPUSE(lu);
02086
02087 NMG_CK_EDGEUSE(eu);
02088 NMG_CK_EDGEUSE(eu->eumate_p);
02089 eu_r = eu->radial_p;
02090 NMG_CK_EDGEUSE(eu_r);
02091 NMG_CK_EDGEUSE(eu_r->eumate_p);
02092
02093 lu2 = eu_r->up.lu_p;
02094 NMG_CK_LOOPUSE(lu2);
02095
02096 if (rt_g.NMG_debug & DEBUG_BASIC) {
02097 bu_log("nmg_jl(lu=x%x, eu=x%x) lu2=x%x\n", lu, eu, lu2);
02098 }
02099
02100 if (eu->up.lu_p != lu)
02101 rt_bomb("nmg_jl: edgeuse is not child of loopuse?\n");
02102
02103 if (lu2->l.magic != NMG_LOOPUSE_MAGIC)
02104 rt_bomb("nmg_jl: radial edgeuse not part of loopuse\n");
02105
02106 if (lu2 == lu)
02107 rt_bomb("nmg_jl: trying to join a loop to itself\n");
02108
02109 if (lu->up.magic_p != lu2->up.magic_p)
02110 rt_bomb("nmg_jl: loopuses do not share parent\n");
02111
02112 if (lu2->orientation != lu->orientation) {
02113 if( lu->orientation != OT_SAME || lu2->orientation != OT_OPPOSITE ) {
02114 bu_log("nmg_jl: lu2 = %s, lu = %s\n",
02115 nmg_orientation(lu2->orientation),
02116 nmg_orientation(lu->orientation) );
02117 rt_bomb("nmg_jl: can't join loops of different orientation!\n");
02118 } else {
02119
02120 }
02121 }
02122
02123 if (eu->radial_p->eumate_p->radial_p->eumate_p != eu ||
02124 eu->eumate_p->radial_p->eumate_p->radial_p != eu)
02125 rt_bomb("nmg_jl: edgeuses must be sole uses of edge to join loops\n");
02126
02127
02128
02129
02130
02131
02132 nexteu = BU_LIST_PNEXT_CIRC(edgeuse, eu_r);
02133 while (nexteu != eu_r) {
02134 BU_LIST_DEQUEUE(&nexteu->l);
02135 BU_LIST_INSERT(&eu->l, &nexteu->l);
02136 nexteu->up.lu_p = eu->up.lu_p;
02137
02138 BU_LIST_DEQUEUE(&nexteu->eumate_p->l);
02139 BU_LIST_APPEND(&eu->eumate_p->l, &nexteu->eumate_p->l);
02140 nexteu->eumate_p->up.lu_p = eu->eumate_p->up.lu_p;
02141
02142 nexteu = BU_LIST_PNEXT_CIRC(edgeuse, eu_r);
02143 }
02144
02145
02146
02147
02148
02149 nmg_klu(lu2);
02150
02151
02152
02153
02154
02155 if( nmg_keu(eu) ) rt_bomb("nmg_jl() loop vanished?\n");
02156
02157 nmg_lu_reorient( lu );
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177 struct vertexuse *
02178 nmg_join_2loops(struct vertexuse *vu1, struct vertexuse *vu2)
02179 {
02180 struct edgeuse *eu1, *eu2;
02181 struct edgeuse *first_new_eu;
02182 struct edgeuse *second_new_eu;
02183 struct edgeuse *final_eu2;
02184 struct loopuse *lu1, *lu2;
02185
02186 NMG_CK_VERTEXUSE(vu1);
02187 NMG_CK_VERTEXUSE(vu2);
02188 eu1 = vu1->up.eu_p;
02189 eu2 = vu2->up.eu_p;
02190 NMG_CK_EDGEUSE(eu1);
02191 NMG_CK_EDGEUSE(eu2);
02192 lu1 = eu1->up.lu_p;
02193 lu2 = eu2->up.lu_p;
02194 NMG_CK_LOOPUSE(lu1);
02195 NMG_CK_LOOPUSE(lu2);
02196
02197 if (rt_g.NMG_debug & DEBUG_BASIC) {
02198 bu_log("nmg_join_2loops(vu1=x%x, vu2=x%x) lu1=x%x, lu2=x%x\n",
02199 vu1, vu2, lu1, lu2 );
02200 }
02201
02202 if( lu1 == lu2 || lu1->l_p == lu2->l_p )
02203 rt_bomb("nmg_join_2loops: can't join loop to itself\n");
02204
02205 if( lu1->up.fu_p != lu2->up.fu_p )
02206 rt_bomb("nmg_join_2loops: can't join loops in different faces\n");
02207
02208 if( vu1->v_p != vu2->v_p ) {
02209
02210
02211
02212
02213
02214 first_new_eu = nmg_eins(eu1);
02215
02216
02217 second_new_eu = nmg_eusplit( vu2->v_p, first_new_eu, 0 );
02218 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, second_new_eu);
02219
02220
02221 nmg_je( second_new_eu, first_new_eu );
02222
02223
02224 vu1 = second_new_eu->vu_p;
02225 } else {
02226 second_new_eu = eu1;
02227 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, second_new_eu);
02228 NMG_CK_EDGEUSE(second_new_eu);
02229 }
02230
02231 vu2 = second_new_eu->vu_p;
02232 if( vu1->v_p != vu2->v_p ) rt_bomb("nmg_join_2loops: jaunt failed\n");
02233
02234
02235
02236
02237
02238
02239
02240
02241 final_eu2 = BU_LIST_PPREV_CIRC(edgeuse, eu2 );
02242 while( BU_LIST_NON_EMPTY( &lu2->down_hd ) ) {
02243 eu2 = BU_LIST_PNEXT_CIRC(edgeuse, final_eu2);
02244
02245 BU_LIST_DEQUEUE(&eu2->l);
02246 BU_LIST_INSERT(&second_new_eu->l, &eu2->l);
02247 eu2->up.lu_p = lu1;
02248
02249 BU_LIST_DEQUEUE(&eu2->eumate_p->l);
02250 BU_LIST_APPEND(&second_new_eu->eumate_p->l, &eu2->eumate_p->l);
02251 eu2->eumate_p->up.lu_p = lu1->lumate_p;
02252 }
02253
02254 nmg_lu_reorient( lu1 );
02255
02256
02257 nmg_klu(lu2);
02258
02259 return vu2;
02260 }
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271 struct vertexuse *
02272 nmg_join_singvu_loop(struct vertexuse *vu1, struct vertexuse *vu2)
02273 {
02274 struct edgeuse *eu1;
02275 struct edgeuse *first_new_eu, *second_new_eu;
02276 struct loopuse *lu2;
02277
02278 NMG_CK_VERTEXUSE( vu1 );
02279 NMG_CK_VERTEXUSE( vu2 );
02280
02281 if (rt_g.NMG_debug & DEBUG_BASIC) {
02282 bu_log("nmg_join_singvu_loop(vu1=x%x, vu2=x%x) lu1=x%x, lu2=x%x\n",
02283 vu1, vu2, vu1->up.lu_p, vu2->up.lu_p );
02284 }
02285
02286 if( *vu2->up.magic_p != NMG_LOOPUSE_MAGIC ||
02287 *vu1->up.magic_p != NMG_EDGEUSE_MAGIC ) rt_bomb("nmg_join_singvu_loop bad args\n");
02288
02289 if( vu1->v_p == vu2->v_p ) rt_bomb("nmg_join_singvu_loop same vertex\n");
02290
02291
02292 eu1 = vu1->up.eu_p;
02293 NMG_CK_EDGEUSE(eu1);
02294
02295
02296 first_new_eu = nmg_eins(eu1);
02297
02298 second_new_eu = nmg_eusplit( vu2->v_p, first_new_eu, 0 );
02299 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, second_new_eu);
02300
02301 nmg_je( second_new_eu, first_new_eu );
02302
02303
02304 lu2 = vu2->up.lu_p;
02305 NMG_CK_LOOPUSE(lu2);
02306 nmg_klu(lu2);
02307
02308 return second_new_eu->vu_p;
02309 }
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321 struct vertexuse *
02322 nmg_join_2singvu_loops(struct vertexuse *vu1, struct vertexuse *vu2)
02323 {
02324 struct edgeuse *first_new_eu, *second_new_eu;
02325 struct loopuse *lu1, *lu2;
02326
02327 if (rt_g.NMG_debug & DEBUG_BASIC) {
02328 bu_log("nmg_join_2singvu_loops(vu1=x%x, vu2=x%x) lu1=x%x, lu2=x%x\n",
02329 vu1, vu2, vu1->up.lu_p, vu2->up.lu_p );
02330 }
02331
02332 NMG_CK_VERTEXUSE( vu1 );
02333 NMG_CK_VERTEXUSE( vu2 );
02334
02335 if( *vu2->up.magic_p != NMG_LOOPUSE_MAGIC ||
02336 *vu1->up.magic_p != NMG_LOOPUSE_MAGIC ) rt_bomb("nmg_join_2singvu_loops bad args\n");
02337
02338 if( vu1->v_p == vu2->v_p ) rt_bomb("nmg_join_2singvu_loops same vertex\n");
02339
02340
02341
02342 first_new_eu = nmg_meonvu(vu1);
02343
02344 second_new_eu = nmg_eusplit( vu2->v_p, first_new_eu, 0 );
02345 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, second_new_eu);
02346
02347 nmg_je( second_new_eu, first_new_eu );
02348
02349
02350 lu2 = vu2->up.lu_p;
02351 NMG_CK_LOOPUSE(lu2);
02352 nmg_klu(lu2);
02353
02354 lu1 = vu1->up.eu_p->up.lu_p;
02355 NMG_CK_LOOPUSE(lu1);
02356
02357 return second_new_eu->vu_p;
02358 }
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420 struct loopuse *
02421 nmg_cut_loop(struct vertexuse *vu1, struct vertexuse *vu2)
02422 {
02423 struct loopuse *lu, *oldlu;
02424 struct edgeuse *eu1, *eu2, *eunext, *neweu, *eu;
02425 struct model *m;
02426 FILE *fd;
02427 char name[32];
02428 static int i=0;
02429
02430 NMG_CK_VERTEXUSE(vu1);
02431 NMG_CK_VERTEXUSE(vu2);
02432
02433 eu1 = vu1->up.eu_p;
02434 eu2 = vu2->up.eu_p;
02435 NMG_CK_EDGEUSE(eu1);
02436 NMG_CK_EDGEUSE(eu2);
02437 oldlu = eu1->up.lu_p;
02438 NMG_CK_LOOPUSE(oldlu);
02439
02440 if (eu2->up.lu_p != oldlu) {
02441 rt_bomb("nmg_cut_loop() vertices not decendants of same loop\n");
02442 }
02443
02444 if( vu1->v_p == vu2->v_p ) {
02445
02446 lu = nmg_split_lu_at_vu( oldlu, vu1 );
02447 goto out;
02448 }
02449
02450 NMG_CK_FACEUSE(oldlu->up.fu_p);
02451 m = oldlu->up.fu_p->s_p->r_p->m_p;
02452 NMG_CK_MODEL(m);
02453
02454 if (rt_g.NMG_debug & DEBUG_CUTLOOP) {
02455 bu_log("\tnmg_cut_loop\n");
02456 if (rt_g.NMG_debug & DEBUG_PLOTEM) {
02457 long *tab;
02458 tab = (long *)bu_calloc( m->maxindex, sizeof(long),
02459 "nmg_cut_loop flag[] 1" );
02460
02461 (void)sprintf(name, "Before_cutloop%d.pl", ++i);
02462 bu_log("nmg_cut_loop() plotting %s\n", name);
02463 if ((fd = fopen(name, "w")) == (FILE *)NULL) {
02464 (void)perror(name);
02465 bu_bomb("unable to open file for writing");
02466 }
02467
02468 nmg_pl_fu(fd, oldlu->up.fu_p, tab, 100, 100, 100);
02469 nmg_pl_fu(fd, oldlu->up.fu_p->fumate_p, tab, 100, 100, 100);
02470 (void)fclose(fd);
02471 bu_free( (char *)tab, "nmg_cut_loop flag[] 1" );
02472 }
02473 }
02474
02475
02476
02477
02478 lu = nmg_mlv(oldlu->up.magic_p, (struct vertex *)NULL, OT_UNSPEC );
02479 oldlu->orientation = oldlu->lumate_p->orientation = OT_UNSPEC;
02480
02481 nmg_kvu(BU_LIST_FIRST(vertexuse, &lu->down_hd));
02482 nmg_kvu(BU_LIST_FIRST(vertexuse, &lu->lumate_p->down_hd));
02483
02484
02485
02486
02487 for (eu = eu2 ; eu != eu1 ; eu = eunext) {
02488 eunext = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
02489
02490 BU_LIST_DEQUEUE(&eu->l);
02491 BU_LIST_INSERT(&lu->down_hd, &eu->l);
02492 BU_LIST_DEQUEUE(&eu->eumate_p->l);
02493 BU_LIST_APPEND(&lu->lumate_p->down_hd, &eu->eumate_p->l);
02494 eu->up.lu_p = lu;
02495 eu->eumate_p->up.lu_p = lu->lumate_p;
02496 }
02497
02498
02499 neweu = nmg_me(eu1->vu_p->v_p, eu2->vu_p->v_p, nmg_find_s_of_eu(eu1));
02500
02501
02502 BU_LIST_DEQUEUE(&neweu->l);
02503 BU_LIST_INSERT(&lu->down_hd, &neweu->l);
02504 neweu->up.lu_p = lu;
02505
02506
02507 BU_LIST_DEQUEUE(&neweu->eumate_p->l);
02508 BU_LIST_APPEND(&lu->lumate_p->down_hd, &neweu->eumate_p->l);
02509 neweu->eumate_p->up.lu_p = lu->lumate_p;
02510
02511
02512 eunext = nmg_me(eu2->vu_p->v_p, eu1->vu_p->v_p, nmg_find_s_of_eu(eu1));
02513
02514 BU_LIST_DEQUEUE(&eunext->l);
02515 BU_LIST_INSERT(&eu1->l, &eunext->l);
02516 BU_LIST_DEQUEUE(&eunext->eumate_p->l);
02517 BU_LIST_APPEND(&eu1->eumate_p->l, &eunext->eumate_p->l);
02518 eunext->up.lu_p = eu1->up.lu_p;
02519 eunext->eumate_p->up.lu_p = eu1->eumate_p->up.lu_p;
02520
02521
02522 nmg_je(neweu, eunext);
02523
02524 nmg_ck_lueu(oldlu, "oldlu");
02525 nmg_ck_lueu(lu, "lu");
02526
02527
02528 if (rt_g.NMG_debug & DEBUG_CUTLOOP && rt_g.NMG_debug & DEBUG_PLOTEM) {
02529 long *tab;
02530 tab = (long *)bu_calloc( m->maxindex, sizeof(long),
02531 "nmg_cut_loop flag[] 2" );
02532
02533 (void)sprintf(name, "After_cutloop%d.pl", i);
02534 bu_log("nmg_cut_loop() plotting %s\n", name);
02535 if ((fd = fopen(name, "w")) == (FILE *)NULL) {
02536 (void)perror(name);
02537 bu_bomb("unable to open file for writing");
02538 }
02539
02540 nmg_pl_fu(fd, oldlu->up.fu_p, tab, 100, 100, 100);
02541 nmg_pl_fu(fd, oldlu->up.fu_p->fumate_p, tab, 100, 100, 100);
02542 (void)fclose(fd);
02543 bu_free( (char *)tab, "nmg_cut_loop flag[] 2" );
02544 }
02545 out:
02546 if (rt_g.NMG_debug & DEBUG_BASIC) {
02547 bu_log("nmg_cut_loop(vu1=x%x, vu2=x%x) old_lu=x%x, new_lu=x%x\n",
02548 vu1, vu2, oldlu, lu );
02549 }
02550
02551 return lu;
02552 }
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588 struct loopuse *
02589 nmg_split_lu_at_vu(struct loopuse *lu, struct vertexuse *split_vu)
02590 {
02591 struct edgeuse *eu;
02592 struct vertexuse *vu;
02593 struct loopuse *newlu;
02594 struct loopuse *newlumate;
02595 struct vertex *split_v;
02596 int iteration;
02597
02598 split_v = split_vu->v_p;
02599 NMG_CK_VERTEX(split_v);
02600
02601 eu = split_vu->up.eu_p;
02602 NMG_CK_EDGEUSE(eu);
02603
02604 if( eu->up.lu_p != lu ) {
02605
02606 newlu = (struct loopuse *)0;
02607 goto out;
02608 }
02609
02610
02611 lu->orientation = lu->lumate_p->orientation = OT_UNSPEC;
02612 newlu = nmg_mlv( lu->up.magic_p, (struct vertex *)NULL, OT_UNSPEC );
02613 NMG_CK_LOOPUSE(newlu);
02614 newlumate = newlu->lumate_p;
02615 NMG_CK_LOOPUSE(newlumate);
02616
02617
02618 nmg_kvu(BU_LIST_FIRST(vertexuse, &newlu->down_hd));
02619 nmg_kvu(BU_LIST_FIRST(vertexuse, &newlumate->down_hd));
02620
02621
02622
02623 for( iteration=0; iteration < 10000; iteration++ ) {
02624 struct edgeuse *eunext;
02625 eunext = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
02626
02627 BU_LIST_DEQUEUE(&eu->l);
02628 BU_LIST_INSERT(&newlu->down_hd, &eu->l);
02629 BU_LIST_DEQUEUE(&eu->eumate_p->l);
02630 BU_LIST_APPEND(&newlumate->down_hd, &eu->eumate_p->l);
02631
02632
02633 eu->up.lu_p = newlu;
02634 eu->eumate_p->up.lu_p = newlumate;
02635
02636
02637 eu = eunext;
02638
02639
02640 vu = eu->vu_p;
02641 NMG_CK_VERTEXUSE(vu);
02642 if( vu->v_p == split_v ) break;
02643 }
02644 if( iteration >= 10000 ) rt_bomb("nmg_split_lu_at_vu: infinite loop\n");
02645 out:
02646 if (rt_g.NMG_debug & DEBUG_BASIC) {
02647 bu_log("nmg_split_lu_at_vu( lu=x%x, split_vu=x%x ) newlu=x%x\n",
02648 lu, split_vu, newlu );
02649 }
02650 return newlu;
02651 }
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664 struct vertexuse *
02665 nmg_find_repeated_v_in_lu(struct vertexuse *vu)
02666 {
02667 struct vertexuse *tvu;
02668 struct loopuse *lu;
02669 struct vertex *v;
02670
02671 v = vu->v_p;
02672 NMG_CK_VERTEX(v);
02673
02674 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
02675 return (struct vertexuse *)0;
02676 if( *vu->up.eu_p->up.magic_p != NMG_LOOPUSE_MAGIC )
02677 return (struct vertexuse *)0;
02678 lu = vu->up.eu_p->up.lu_p;
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688 for( BU_LIST_FOR( tvu, vertexuse, &v->vu_hd ) ) {
02689 struct edgeuse *teu;
02690 struct loopuse *tlu;
02691
02692 if( tvu == vu ) continue;
02693 if( *tvu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
02694 teu = tvu->up.eu_p;
02695 NMG_CK_EDGEUSE(teu);
02696 if( *teu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
02697 tlu = teu->up.lu_p;
02698 NMG_CK_LOOPUSE(tlu);
02699 if( tlu != lu ) continue;
02700
02701
02702
02703 return tvu;
02704 }
02705 return (struct vertexuse *)0;
02706 }
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718 void
02719 nmg_split_touchingloops(struct loopuse *lu, const struct bn_tol *tol)
02720 {
02721 struct edgeuse *eu;
02722 struct vertexuse *vu;
02723 struct loopuse *newlu;
02724 struct vertexuse *vu_save;
02725
02726 NMG_CK_LOOPUSE(lu);
02727 BN_CK_TOL(tol);
02728 if (rt_g.NMG_debug & DEBUG_BASIC) {
02729 bu_log("nmg_split_touchingloops( lu=x%x )\n", lu);
02730 }
02731 top:
02732 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02733 return;
02734
02735 vu_save = (struct vertexuse *)NULL;
02736
02737
02738 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
02739
02740 struct edgeuse *other_eu;
02741 struct vertexuse *other_vu;
02742 int vu_is_part_of_crack=0;
02743
02744 vu = eu->vu_p;
02745 NMG_CK_VERTEXUSE(vu);
02746
02747 #if 1
02748 if( !nmg_find_repeated_v_in_lu( vu ) ) continue;
02749
02750
02751 for( BU_LIST_FOR( other_vu, vertexuse, &vu->v_p->vu_hd ) )
02752 {
02753 if( nmg_find_lu_of_vu( other_vu ) != lu )
02754 continue;
02755 if( *other_vu->up.magic_p != NMG_EDGEUSE_MAGIC )
02756 continue;
02757 other_eu = other_vu->up.eu_p;
02758 if( nmg_eu_is_part_of_crack( other_eu ) )
02759 {
02760 vu_save = other_vu;
02761 vu_is_part_of_crack = 1;
02762 break;
02763 }
02764 }
02765
02766 if( vu_is_part_of_crack )
02767 continue;
02768
02769
02770
02771
02772
02773 newlu = nmg_split_lu_at_vu( lu, vu );
02774 NMG_CK_LOOPUSE(newlu);
02775 NMG_CK_LOOP(newlu->l_p);
02776 nmg_loop_g(newlu->l_p, tol);
02777
02778
02779 nmg_split_touchingloops(newlu, tol);
02780
02781
02782
02783
02784 goto top;
02785 }
02786
02787 if( vu_save )
02788 {
02789
02790 newlu = nmg_split_lu_at_vu( lu, vu_save );
02791 NMG_CK_LOOPUSE(newlu);
02792 NMG_CK_LOOP(newlu->l_p);
02793 nmg_loop_g(newlu->l_p, tol);
02794
02795
02796 nmg_split_touchingloops(newlu, tol);
02797
02798
02799
02800
02801 goto top;
02802 }
02803
02804 #else
02805 v = vu->v_p;
02806 NMG_CK_VERTEX(v);
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816 for( BU_LIST_FOR( tvu, vertexuse, &v->vu_hd ) ) {
02817 struct edgeuse *teu;
02818 struct loopuse *tlu;
02819
02820 if( tvu == vu ) continue;
02821 if( *tvu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
02822 teu = tvu->up.eu_p;
02823 NMG_CK_EDGEUSE(teu);
02824 if( *teu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
02825 tlu = teu->up.lu_p;
02826 NMG_CK_LOOPUSE(tlu);
02827 if( tlu != lu ) continue;
02828
02829
02830
02831
02832 newlu = nmg_split_lu_at_vu( lu, vu );
02833 NMG_CK_LOOPUSE(newlu);
02834 NMG_CK_LOOP(newlu->l_p);
02835 nmg_loop_g(newlu->l_p, tol);
02836
02837
02838 nmg_split_touchingloops(newlu, tol);
02839
02840
02841
02842
02843 goto top;
02844 }
02845 }
02846 #endif
02847 }
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860 int
02861 nmg_join_touchingloops(struct loopuse *lu)
02862 {
02863 struct faceuse *fu;
02864 struct edgeuse *eu;
02865 struct vertexuse *vu;
02866 struct vertex *v;
02867 int count = 0;
02868
02869 if (rt_g.NMG_debug & DEBUG_BASIC) {
02870 bu_log("nmg_join_touchingloops( lu=x%x )\n", lu);
02871 }
02872 NMG_CK_LOOPUSE(lu);
02873 fu = lu->up.fu_p;
02874 NMG_CK_FACEUSE(fu);
02875
02876 top:
02877 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02878 return count;
02879
02880
02881 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
02882 struct vertexuse *tvu;
02883
02884 vu = eu->vu_p;
02885 NMG_CK_VERTEXUSE(vu);
02886 v = vu->v_p;
02887 NMG_CK_VERTEX(v);
02888
02889
02890
02891
02892
02893
02894
02895 for( BU_LIST_FOR( tvu, vertexuse, &v->vu_hd ) ) {
02896 struct edgeuse *teu;
02897 struct loopuse *tlu;
02898
02899 if( tvu == vu ) continue;
02900 if( *tvu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
02901 teu = tvu->up.eu_p;
02902 NMG_CK_EDGEUSE(teu);
02903 if( *teu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
02904 tlu = teu->up.lu_p;
02905 NMG_CK_LOOPUSE(tlu);
02906 if( tlu == lu ) {
02907
02908 #if 0
02909 bu_log("INFO: nmg_join_touchingloops() lu=x%x touches itself at vu1=x%x, vu2=x%x, skipping\n",
02910 lu, vu, tvu );
02911 #endif
02912 continue;
02913 }
02914 if( *tlu->up.magic_p != NMG_FACEUSE_MAGIC ) continue;
02915 if( tlu->up.fu_p != fu ) continue;
02916
02917
02918
02919
02920
02921
02922
02923 if (rt_g.NMG_debug & DEBUG_BASIC) {
02924 bu_log("nmg_join_touchingloops(): lu=x%x, vu=x%x, tvu=x%x\n", lu, vu, tvu);
02925 }
02926 tvu = nmg_join_2loops( vu, tvu );
02927 NMG_CK_VERTEXUSE(tvu);
02928 count++;
02929 goto top;
02930 }
02931 }
02932 return count;
02933 }
02934
02935
02936 #define JS_UNKNOWN 0
02937 #define JS_SPLIT 1
02938 #define JS_JAUNT 2
02939 #define JS_TOUCHING_JAUNT 3
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958 int
02959 nmg_get_touching_jaunts(const struct loopuse *lu, struct bu_ptbl *tbl, int *need_init)
02960 {
02961 struct edgeuse *eu;
02962 int count=0;
02963
02964 NMG_CK_LOOPUSE( lu );
02965
02966 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02967 return( 0 );
02968
02969 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02970 {
02971 struct edgeuse *eu2,*eu3;
02972
02973 eu2 = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
02974 eu3 = BU_LIST_PNEXT_CIRC(edgeuse, &eu2->l);
02975
02976
02977 if( eu->vu_p == eu3->vu_p ) break;
02978
02979
02980 if( eu->vu_p->v_p != eu3->vu_p->v_p ) continue;
02981
02982
02983 if( nmg_find_repeated_v_in_lu(eu2->vu_p) == (struct vertexuse *)NULL )
02984 continue;
02985
02986
02987 if( *need_init )
02988 {
02989 bu_ptbl_init( tbl, 64, " tbl");
02990 *need_init = 0;
02991 }
02992
02993 bu_ptbl_ins( tbl, (long *)eu );
02994 count++;
02995 }
02996
02997 return( count );
02998 }
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026 static void
03027 nmg_check_proposed_loop(struct edgeuse *start_eu, struct edgeuse **next_start_eu, int *visit_count, int *jaunt_status, const struct bu_ptbl *jaunt_tbl, const int jaunt_no, const int which_loop)
03028 {
03029 struct edgeuse *loop_eu;
03030 struct edgeuse *last_eu;
03031 int j;
03032 int done=0;
03033
03034 NMG_CK_EDGEUSE( start_eu );
03035 BU_CK_PTBL( jaunt_tbl );
03036
03037
03038 for( j=0 ; j< BU_PTBL_END( jaunt_tbl ) ; j++ )
03039 visit_count[j] = 0;
03040
03041
03042 last_eu = NULL;
03043 loop_eu = start_eu;
03044 while( !done )
03045 {
03046 for( j=0 ; j<BU_PTBL_END( jaunt_tbl ) ; j++ )
03047 {
03048 struct edgeuse *jaunt_eu;
03049
03050
03051 if( j == jaunt_no )
03052 continue;
03053
03054 jaunt_eu = (struct edgeuse *)BU_PTBL_GET( jaunt_tbl, j );
03055 NMG_CK_EDGEUSE( jaunt_eu );
03056
03057
03058 if( last_eu && last_eu == jaunt_eu )
03059 jaunt_status[j] = JS_JAUNT;
03060
03061
03062
03063
03064 if( loop_eu->vu_p->v_p == jaunt_eu->eumate_p->vu_p->v_p )
03065 visit_count[j]++;
03066 }
03067 last_eu = loop_eu;
03068 loop_eu = BU_LIST_PNEXT_CIRC(edgeuse, &loop_eu->l);
03069
03070
03071
03072
03073 if( !which_loop && loop_eu->vu_p->v_p == start_eu->vu_p->v_p )
03074 done = 1;
03075 else if( which_loop && loop_eu == (*next_start_eu) )
03076 done = 1;
03077 }
03078 *next_start_eu = loop_eu;
03079
03080
03081
03082 for( j=0 ; j<BU_PTBL_END( jaunt_tbl ) ; j++ )
03083 {
03084 if( jaunt_status[j] == JS_JAUNT )
03085 {
03086 if( visit_count[j] > 1 )
03087 jaunt_status[j] = JS_TOUCHING_JAUNT;
03088 }
03089 }
03090
03091
03092
03093
03094 for( j=0 ; j<BU_PTBL_END( jaunt_tbl ) ; j++ )
03095 {
03096 struct edgeuse *jaunt_eu;
03097 struct edgeuse *jaunt_eu2;
03098
03099 jaunt_eu = (struct edgeuse *)BU_PTBL_GET( jaunt_tbl, j );
03100 jaunt_eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &jaunt_eu->l );
03101
03102 if( last_eu == jaunt_eu || start_eu == jaunt_eu2 )
03103 jaunt_status[j] = JS_SPLIT;
03104 }
03105
03106 return;
03107 }
03108
03109 void
03110 nmg_kill_accordions(struct loopuse *lu)
03111 {
03112 struct edgeuse *eu;
03113 struct edgeuse *jaunt_eu1;
03114 struct edgeuse *jaunt_eu2 = NULL;
03115 struct edgeuse *jaunt_eu3;
03116
03117 NMG_CK_LOOPUSE( lu );
03118
03119 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03120 return;
03121 top:
03122
03123 jaunt_eu1 = (struct edgeuse *)NULL;
03124 jaunt_eu3 = (struct edgeuse *)NULL;
03125 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03126 {
03127 struct edgeuse *eu2;
03128
03129 eu2 = BU_LIST_PPREV_CIRC( edgeuse, &eu->l );
03130 if( (eu2->vu_p->v_p == eu->eumate_p->vu_p->v_p) && (eu != eu2) )
03131 {
03132 struct edgeuse *eu3;
03133
03134
03135 jaunt_eu1 = eu;
03136 jaunt_eu2 = eu2;
03137
03138
03139 jaunt_eu3 = (struct edgeuse *)NULL;
03140 for( BU_LIST_FOR( eu3, edgeuse, &lu->down_hd ) )
03141 {
03142 if( eu3 == jaunt_eu1 || eu3 == jaunt_eu2 )
03143 continue;
03144
03145 if( NMG_ARE_EUS_ADJACENT( eu3, jaunt_eu1 ) )
03146 {
03147 jaunt_eu3 = eu3;
03148 break;
03149 }
03150 }
03151 }
03152 if( jaunt_eu3 )
03153 break;
03154 }
03155
03156 if( !jaunt_eu3 )
03157 return;
03158
03159 if( jaunt_eu2 != jaunt_eu1->eumate_p )
03160 {
03161 if ((rt_g.NMG_debug & DEBUG_BASIC) || (rt_g.NMG_debug & DEBUG_CUTLOOP))
03162 bu_log( "Killing jaunt in accordion eu's x%x and x%x\n", jaunt_eu1, jaunt_eu2 );
03163 (void)nmg_keu( jaunt_eu1 );
03164 (void)nmg_keu( jaunt_eu2 );
03165 }
03166 else
03167 {
03168 if ((rt_g.NMG_debug & DEBUG_BASIC) || (rt_g.NMG_debug & DEBUG_CUTLOOP))
03169 bu_log( "Killing jaunt in accordion eu x%x\n", jaunt_eu1 );
03170 (void)nmg_keu( jaunt_eu1 );
03171 }
03172
03173 goto top;
03174
03175 }
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190 int
03191 nmg_loop_split_at_touching_jaunt(struct loopuse *lu, const struct bn_tol *tol)
03192 {
03193 struct bu_ptbl jaunt_tbl;
03194 struct loopuse *new_lu;
03195 struct edgeuse *eu;
03196 struct edgeuse *eu2;
03197 int count=0;
03198 int jaunt_count;
03199 int jaunt_no;
03200 int need_init=1;
03201 int *visit_count;
03202 int *jaunt_status;
03203 int i;
03204
03205 NMG_CK_LOOPUSE(lu);
03206 BN_CK_TOL(tol);
03207
03208 if ((rt_g.NMG_debug & DEBUG_BASIC) || (rt_g.NMG_debug & DEBUG_CUTLOOP)) {
03209 bu_log("nmg_loop_split_at_touching_jaunt( lu=x%x ) START\n", lu);
03210 nmg_pr_lu_briefly( lu, "" );
03211 }
03212
03213
03214 nmg_kill_accordions( lu );
03215
03216 visit_count = (int *)NULL;
03217 jaunt_status = (int *)NULL;
03218
03219 top:
03220 jaunt_count = nmg_get_touching_jaunts( lu, &jaunt_tbl, &need_init );
03221 if( rt_g.NMG_debug & DEBUG_CUTLOOP )
03222 {
03223 bu_log( "nmg_loop_split_at_touching_jaunt: found %d touching jaunts in lu x%x\n", jaunt_count, lu );
03224 if( jaunt_count )
03225 {
03226 for( i=0 ; i<BU_PTBL_END( &jaunt_tbl ) ; i++ )
03227 {
03228 eu = (struct edgeuse *)BU_PTBL_GET( &jaunt_tbl, i );
03229 bu_log( "\tx%x\n" , eu );
03230 }
03231 }
03232 }
03233
03234 if( jaunt_count < 0 )
03235 {
03236 bu_log( "nmg_loop_split_at_touching_jaunt: nmg_get_touching_jaunts() returned %d for lu x%x\n", jaunt_count, lu );
03237 rt_bomb( "nmg_loop_split_at_touching_jaunt: bad jaunt count\n" );
03238 }
03239
03240 if( jaunt_count == 0 )
03241 {
03242 if( visit_count )
03243 bu_free( (char *)visit_count, "nmg_loop_split_at_touching_jaunt: visit_count[]\n" );
03244 if( jaunt_status )
03245 bu_free( (char *)jaunt_status, "nmg_loop_split_at_touching_jaunt: jaunt_status[]\n" );
03246 if( !need_init )
03247 bu_ptbl_free( &jaunt_tbl);
03248
03249 if ((rt_g.NMG_debug & DEBUG_BASIC) || (rt_g.NMG_debug & DEBUG_CUTLOOP)) {
03250 bu_log("nmg_loop_split_at_touching_jaunt( lu=x%x ) END count=%d\n",
03251 lu, count);
03252 }
03253 return( count );
03254 }
03255
03256 if( jaunt_count == 1 )
03257 {
03258
03259 BU_CK_PTBL( &jaunt_tbl );
03260
03261 eu = (struct edgeuse *)BU_PTBL_GET( &jaunt_tbl, 0 );
03262 NMG_CK_EDGEUSE( eu );
03263 eu2 = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
03264
03265 new_lu = nmg_split_lu_at_vu( lu, eu2->vu_p );
03266 count++;
03267 NMG_CK_LOOPUSE(new_lu);
03268 NMG_CK_LOOP(new_lu->l_p);
03269 nmg_loop_g(new_lu->l_p, tol);
03270
03271 bu_ptbl_free( &jaunt_tbl);
03272 if( visit_count )
03273 bu_free( (char *)visit_count, "nmg_loop_split_at_touching_jaunt: visit_count[]\n" );
03274 if( jaunt_status )
03275 bu_free( (char *)jaunt_status, "nmg_loop_split_at_touching_jaunt: jaunt_status[]\n" );
03276
03277 if ((rt_g.NMG_debug & DEBUG_BASIC) || (rt_g.NMG_debug & DEBUG_CUTLOOP)) {
03278 bu_log("nmg_loop_split_at_touching_jaunt( lu=x%x ) END count=%d\n",
03279 lu, count);
03280 }
03281 return( count );
03282 }
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299 BU_CK_PTBL( &jaunt_tbl );
03300
03301 if( visit_count )
03302 bu_free( (char *)visit_count, "nmg_loop_split_at_touching_jaunt: visit_count[]\n" );
03303 if( jaunt_status )
03304 bu_free( (char *)jaunt_status, "nmg_loop_split_at_touching_jaunt: jaunt_status[]\n" );
03305
03306 visit_count = (int *)bu_calloc( BU_PTBL_END( &jaunt_tbl ), sizeof( int ),
03307 "nmg_loop_split_at_touching_jaunt: visit_count[]" );
03308 jaunt_status = (int *)bu_calloc( BU_PTBL_END( &jaunt_tbl ), sizeof( int ),
03309 "nmg_loop_split_at_touching_jaunt: jaunt_status[]" );
03310
03311
03312 for( jaunt_no=0 ; jaunt_no<BU_PTBL_END( &jaunt_tbl ) ; jaunt_no++ )
03313 {
03314 struct edgeuse *start_eu1;
03315 struct edgeuse *start_eu2;
03316 int do_split=1;
03317
03318
03319 for( i=0 ; i<BU_PTBL_END( &jaunt_tbl ) ; i++ )
03320 jaunt_status[i] = JS_UNKNOWN;
03321
03322
03323 eu = (struct edgeuse *)BU_PTBL_GET( &jaunt_tbl, jaunt_no );
03324 NMG_CK_EDGEUSE( eu );
03325
03326
03327 start_eu1 = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
03328
03329 if( rt_g.NMG_debug & DEBUG_CUTLOOP )
03330 {
03331 bu_log( "\tConsider splitting lu x%x at vu=x%x\n", lu, start_eu1->vu_p );
03332 bu_log( "\t\t(jaunt number %d\n" , jaunt_no );
03333 }
03334
03335
03336 nmg_check_proposed_loop( start_eu1, &start_eu2, visit_count,
03337 jaunt_status, &jaunt_tbl, jaunt_no, 0 );
03338
03339
03340 nmg_check_proposed_loop( start_eu2, &start_eu1, visit_count,
03341 jaunt_status, &jaunt_tbl, jaunt_no, 1 );
03342
03343 if( rt_g.NMG_debug & DEBUG_CUTLOOP )
03344 {
03345 for( i=0 ; i<BU_PTBL_END( &jaunt_tbl ) ; i++ )
03346 {
03347 struct edgeuse *tmp_eu;
03348
03349 tmp_eu = (struct edgeuse *)BU_PTBL_GET( &jaunt_tbl, i );
03350 bu_log( "\t\tpredicted status of jaunt at eu x%x is ", tmp_eu );
03351 switch( jaunt_status[i] )
03352 {
03353 case JS_UNKNOWN:
03354 bu_log( "unknown\n" );
03355 break;
03356 case JS_SPLIT:
03357 bu_log( "split\n" );
03358 break;
03359 case JS_JAUNT:
03360 bu_log( "a jaunt\n" );
03361 break;
03362 case JS_TOUCHING_JAUNT:
03363 bu_log( "still a touching jaunt\n" );
03364 break;
03365 default:
03366 bu_log( "unrecognized status\n" );
03367 break;
03368 }
03369 }
03370 }
03371
03372
03373
03374
03375
03376 for( i=0 ; i<BU_PTBL_END( &jaunt_tbl ) ; i++ )
03377 {
03378 if(jaunt_status[i] != JS_SPLIT && jaunt_status[i] != JS_TOUCHING_JAUNT )
03379 {
03380 do_split = 0;
03381 break;
03382 }
03383 }
03384
03385
03386 if( !do_split )
03387 {
03388 if( rt_g.NMG_debug & DEBUG_CUTLOOP )
03389 {
03390 bu_log( "\t\tCannot split lu x%x at proposed vu\n" );
03391 }
03392 continue;
03393 }
03394
03395
03396 eu2 = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
03397
03398 new_lu = nmg_split_lu_at_vu( lu, eu2->vu_p );
03399
03400 if( rt_g.NMG_debug & DEBUG_CUTLOOP )
03401 {
03402 bu_log( "\tnmg_loop_split_at_touching_jaunt: splitting lu x%x at vu x%x\n", lu, eu2->vu_p );
03403 bu_log( "\t\tnew_lu is x%x\n" , new_lu );
03404 }
03405
03406 count++;
03407 NMG_CK_LOOPUSE(new_lu);
03408 NMG_CK_LOOP(new_lu->l_p);
03409 nmg_loop_g(new_lu->l_p, tol);
03410 bu_ptbl_reset( &jaunt_tbl);
03411
03412
03413 count += nmg_loop_split_at_touching_jaunt( new_lu, tol );
03414
03415
03416 goto top;
03417 }
03418
03419
03420 bu_log( "nmg_loop_split_at_touching_jaunt: Could not find a way to split lu x%x\n", lu );
03421 nmg_pr_lu_briefly( lu, " " );
03422 nmg_stash_model_to_file( "jaunt.g", nmg_find_model( &lu->l.magic ), "Can't split lu" );
03423 rt_bomb( "nmg_loop_split_at_touching_jaunt: Can't split lu\n" );
03424
03425
03426 return( count );
03427 }
03428
03429
03430
03431
03432
03433
03434 void
03435 nmg_simplify_loop(struct loopuse *lu)
03436 {
03437 struct edgeuse *eu, *eu_r, *tmpeu;
03438
03439 NMG_CK_LOOPUSE(lu);
03440 if (rt_g.NMG_debug & DEBUG_BASIC) {
03441 bu_log("nmg_simplify_loop(lu=x%x)\n", lu);
03442 }
03443
03444 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
03445 return;
03446
03447 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
03448 while (BU_LIST_NOT_HEAD(eu, &lu->down_hd) ) {
03449
03450 NMG_CK_EDGEUSE(eu);
03451
03452 eu_r = eu->radial_p;
03453 NMG_CK_EDGEUSE(eu_r);
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463 if (*eu_r->up.magic_p == NMG_LOOPUSE_MAGIC &&
03464 eu_r->up.lu_p->up.magic_p == lu->up.magic_p &&
03465 eu->eumate_p->radial_p == eu->radial_p->eumate_p &&
03466 eu_r->up.lu_p != lu) {
03467
03468 if( eu_r->up.lu_p->orientation != lu->orientation &&
03469 (lu->orientation != OT_SAME ||
03470 eu_r->up.lu_p->orientation != OT_OPPOSITE) ) {
03471
03472
03473
03474 eu = BU_LIST_PNEXT(edgeuse, eu);
03475 continue;
03476 }
03477
03478
03479
03480
03481
03482 tmpeu = BU_LIST_PLAST(edgeuse, eu);
03483
03484 nmg_jl(lu, eu);
03485
03486
03487
03488
03489
03490 eu = tmpeu;
03491
03492 if (rt_g.NMG_debug &(DEBUG_PLOTEM|DEBUG_PL_ANIM) &&
03493 *lu->up.magic_p == NMG_FACEUSE_MAGIC ) {
03494 static int fno=0;
03495
03496 nmg_pl_2fu("After_joinloop%d.pl", fno++,
03497 lu->up.fu_p, lu->up.fu_p->fumate_p, 0);
03498
03499 }
03500 }
03501 eu = BU_LIST_PNEXT(edgeuse, eu);
03502 }
03503 }
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515 int
03516 nmg_kill_snakes(struct loopuse *lu)
03517 {
03518 struct edgeuse *eu, *eu_r;
03519 struct vertexuse *vu;
03520 struct vertex *v;
03521
03522 NMG_CK_LOOPUSE(lu);
03523 if (rt_g.NMG_debug & DEBUG_BASIC) {
03524 bu_log("nmg_kill_snakes(lu=x%x)\n", lu);
03525 }
03526 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
03527 return 0;
03528
03529 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
03530 while (BU_LIST_NOT_HEAD(eu, &lu->down_hd) ) {
03531
03532 NMG_CK_EDGEUSE(eu);
03533
03534 eu_r = eu->radial_p;
03535 NMG_CK_EDGEUSE(eu_r);
03536
03537
03538
03539
03540
03541
03542 if (*eu_r->up.magic_p == NMG_LOOPUSE_MAGIC &&
03543 eu_r->up.lu_p == eu->up.lu_p &&
03544 eu->eumate_p->radial_p == eu->radial_p->eumate_p &&
03545 BU_LIST_PNEXT_CIRC(edgeuse, eu) == eu_r) {
03546
03547
03548
03549
03550
03551 v = eu->eumate_p->vu_p->v_p;
03552 vu = BU_LIST_FIRST(vertexuse, &v->vu_hd);
03553 while (BU_LIST_NOT_HEAD(vu, &v->vu_hd) &&
03554 (vu->up.eu_p == eu->eumate_p ||
03555 vu->up.eu_p == eu_r) )
03556 vu = BU_LIST_PNEXT(vertexuse, vu);
03557
03558 if (! BU_LIST_NOT_HEAD(vu, &v->vu_hd) ) {
03559
03560 (void)nmg_keu(eu_r);
03561 if( nmg_keu(eu) ) return 1;
03562 if( BU_LIST_IS_EMPTY( &lu->down_hd ) )
03563 return 1;
03564 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
03565
03566 if (rt_g.NMG_debug &(DEBUG_PLOTEM|DEBUG_PL_ANIM) &&
03567 *lu->up.magic_p == NMG_FACEUSE_MAGIC ) {
03568 static int fno=0;
03569
03570 nmg_pl_2fu("After_joinloop%d.pl", fno++,
03571 lu->up.fu_p, lu->up.fu_p->fumate_p, 0);
03572
03573 }
03574
03575
03576 } else
03577 eu = BU_LIST_PNEXT(edgeuse, eu);
03578 } else
03579 eu = BU_LIST_PNEXT(edgeuse, eu);
03580 }
03581 return 0;
03582 }
03583
03584
03585
03586
03587
03588
03589
03590 void
03591 nmg_mv_lu_between_shells(struct shell *dest, register struct shell *src, register struct loopuse *lu)
03592 {
03593 register struct loopuse *lumate;
03594
03595 NMG_CK_LOOPUSE(lu);
03596 lumate = lu->lumate_p;
03597 NMG_CK_LOOPUSE(lumate);
03598
03599 if( lu->up.s_p != src ) {
03600 bu_log("nmg_mv_lu_between_shells(dest=x%x, src=x%x, lu=x%x), lu->up.s_p=x%x isn't source shell\n",
03601 dest, src, lu, lu->up.s_p );
03602 rt_bomb("lu->up.s_p isn't source shell\n");
03603 }
03604 if( lumate->up.s_p != src ) {
03605 bu_log("nmg_mv_lu_between_shells(dest=x%x, src=x%x, lu=x%x), lumate->up.s_p=x%x isn't source shell\n",
03606 dest, src, lu, lumate->up.s_p );
03607 rt_bomb("lumate->up.s_p isn't source shell\n");
03608 }
03609
03610
03611 BU_LIST_DEQUEUE( &lu->l );
03612 if( BU_LIST_IS_EMPTY( &src->lu_hd ) ) {
03613
03614 bu_log("nmg_mv_lu_between_shells(dest=x%x, src=x%x, lu=x%x), lumate=x%x not in src shell\n",
03615 dest, src, lu, lumate );
03616 rt_bomb("src shell emptied before finding lumate\n");
03617 }
03618
03619
03620 BU_LIST_DEQUEUE( &lumate->l );
03621
03622
03623 BU_LIST_APPEND( &dest->lu_hd, &lu->l );
03624 BU_LIST_APPEND( &lu->l, &lumate->l );
03625
03626 lu->up.s_p = dest;
03627 lumate->up.s_p = dest;
03628
03629 if (rt_g.NMG_debug & DEBUG_BASIC) {
03630 bu_log("nmg_mv_lu_between_shells(dest=x%x, src=x%x, lu=x%x)\n",
03631 dest , src , lu);
03632 }
03633 }
03634
03635
03636
03637
03638
03639
03640
03641
03642 void nmg_moveltof(struct faceuse *fu, struct shell *s)
03643 {
03644 struct loopuse *lu1, *lu2;
03645
03646 NMG_CK_SHELL(s);
03647 NMG_CK_FACEUSE(fu);
03648 if (fu->s_p != s) {
03649 bu_log("nmg_moveltof() in %s at %d. Cannot move loop to face in another shell\n",
03650 __FILE__, __LINE__);
03651 }
03652 lu1 = BU_LIST_FIRST(loopuse, &s->lu_hd);
03653 NMG_CK_LOOPUSE(lu1);
03654 BU_LIST_DEQUEUE( &lu1->l );
03655
03656 lu2 = BU_LIST_FIRST(loopuse, &s->lu_hd);
03657 NMG_CK_LOOPUSE(lu2);
03658 BU_LIST_DEQUEUE( &lu2->l );
03659
03660 BU_LIST_APPEND( &fu->lu_hd, &lu1->l );
03661 BU_LIST_APPEND( &fu->fumate_p->lu_hd, &lu2->l );
03662
03663
03664 if (rt_g.NMG_debug & DEBUG_BASIC) {
03665 bu_log("nmg_moveltof(fu=x%x, s=x%x)\n",
03666 fu , s );
03667 }
03668 }
03669
03670
03671
03672
03673
03674
03675
03676
03677 struct loopuse *
03678 nmg_dup_loop(struct loopuse *lu, long int *parent, long int **trans_tbl)
03679
03680
03681
03682 {
03683 struct loopuse *new_lu = (struct loopuse *)NULL;
03684 struct vertexuse *new_vu = (struct vertexuse *)NULL;
03685 struct vertexuse *old_vu = (struct vertexuse *)NULL;
03686 struct vertex *old_v = (struct vertex *)NULL;
03687 struct vertex *new_v;
03688 struct edgeuse *new_eu = (struct edgeuse *)NULL;
03689 struct edgeuse *tbl_eu = (struct edgeuse *)NULL;
03690 struct edgeuse *eu = (struct edgeuse *)NULL;
03691
03692 NMG_CK_LOOPUSE(lu);
03693
03694
03695 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
03696 old_vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
03697 old_v = old_vu->v_p;
03698
03699
03700 if( trans_tbl )
03701 new_v = NMG_INDEX_GETP(vertex, trans_tbl, old_v);
03702 else
03703 new_v = (struct vertex *)NULL;
03704 new_lu = nmg_mlv(parent, new_v, lu->orientation);
03705 if (new_lu->orientation != lu->orientation) {
03706 bu_log("%s %d: I asked for a %s loop not a %s loop.\n",
03707 __FILE__, __LINE__,
03708 nmg_orientation(lu->orientation),
03709 nmg_orientation(new_lu->orientation));
03710 rt_bomb("bombing\n");
03711 }
03712 if( new_v ) {
03713
03714 bu_log("nmg_dup_loop() existing vertex in new model\n");
03715 return (struct loopuse *)NULL;
03716 }
03717
03718 bu_log("nmg_dup_loop() new vertex in new model\n");
03719
03720 new_vu = BU_LIST_FIRST(vertexuse, &new_lu->down_hd);
03721 new_v = new_vu->v_p;
03722
03723 if( trans_tbl )
03724 NMG_INDEX_ASSIGN( trans_tbl, old_v, (long *)new_v );
03725 if (old_v->vg_p) {
03726
03727 nmg_vertex_gv(new_v, old_v->vg_p->coord);
03728 }
03729 if (rt_g.NMG_debug & DEBUG_BASIC) {
03730 bu_log("nmg_dup_loop(lu=x%x, parent=x%x, trans_tbl=x%x) new_lu=x%x\n",
03731 lu , parent , trans_tbl , new_lu );
03732 }
03733 return new_lu;
03734 }
03735
03736
03737
03738
03739 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
03740
03741 NMG_CK_EDGEUSE(eu);
03742 NMG_CK_VERTEXUSE(eu->vu_p);
03743 NMG_CK_VERTEX(eu->vu_p->v_p);
03744 old_v = eu->vu_p->v_p;
03745
03746
03747 if( trans_tbl )
03748 new_v = NMG_INDEX_GETP(vertex, trans_tbl, old_v);
03749 else
03750 new_v = (struct vertex *)NULL;
03751
03752 if (new_lu == (struct loopuse *)NULL) {
03753
03754 new_lu = nmg_mlv(parent, new_v, lu->orientation);
03755 if (new_lu->orientation != lu->orientation) {
03756 bu_log("%s %d: I asked for a %s loop not a %s loop.\n",
03757 __FILE__, __LINE__,
03758 nmg_orientation(lu->orientation),
03759 nmg_orientation(new_lu->orientation));
03760 rt_bomb("bombing\n");
03761 }
03762
03763 new_vu = BU_LIST_FIRST(vertexuse, &new_lu->down_hd);
03764
03765 NMG_CK_VERTEXUSE(new_vu);
03766 NMG_CK_VERTEX(new_vu->v_p);
03767
03768 if( !new_v && trans_tbl ) {
03769
03770 NMG_INDEX_ASSIGN( trans_tbl, old_v,
03771 (long *)new_vu->v_p );
03772 }
03773 new_v = new_vu->v_p;
03774
03775 new_eu = nmg_meonvu(new_vu);
03776 } else {
03777
03778 new_eu = BU_LIST_LAST(edgeuse, &new_lu->down_hd);
03779 NMG_CK_EDGEUSE(new_eu);
03780
03781 new_eu = nmg_eusplit(new_v, new_eu, 0);
03782 new_vu = new_eu->vu_p;
03783
03784 if( !new_v && trans_tbl ) {
03785
03786 NMG_INDEX_ASSIGN( trans_tbl, old_v,
03787 (long *)new_vu->v_p );
03788 }
03789 new_v = new_vu->v_p;
03790 }
03791
03792 if (old_v->vg_p) {
03793 NMG_CK_VERTEX_G(old_v->vg_p);
03794 nmg_vertex_gv(new_v, old_v->vg_p->coord);
03795 }
03796
03797
03798
03799
03800 if( trans_tbl )
03801 tbl_eu = NMG_INDEX_GETP(edgeuse, trans_tbl, eu->e_p );
03802 else
03803 tbl_eu = (struct edgeuse *)NULL;
03804 if( !tbl_eu && trans_tbl ) {
03805
03806 NMG_INDEX_ASSIGN( trans_tbl, eu->e_p, (long *)new_eu );
03807 }
03808 if( trans_tbl )
03809 NMG_INDEX_ASSIGN( trans_tbl, eu, (long *)new_eu );
03810 }
03811 #if 0
03812
03813 if( trans_tbl )
03814 {
03815
03816 for(BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
03817
03818
03819 tbl_eu = NMG_INDEX_GETP(edgeuse, trans_tbl, eu->e_p );
03820 new_eu = NMG_INDEX_GETP(edgeuse, trans_tbl, eu );
03821 if( tbl_eu->e_p == new_eu->e_p ) continue;
03822
03823
03824
03825 nmg_je( tbl_eu, new_eu );
03826 }
03827 }
03828 #endif
03829
03830
03831
03832
03833
03834
03835 for(BU_LIST_FOR(new_eu, edgeuse, &new_lu->down_hd)) {
03836 NMG_CK_EDGEUSE(new_eu);
03837 NMG_CK_EDGE(new_eu->e_p);
03838 if( new_eu->g.magic_p ) continue;
03839 nmg_edge_g(new_eu);
03840 }
03841
03842 if (rt_g.NMG_debug & DEBUG_BASIC) {
03843 bu_log("nmg_dup_loop(lu=x%x(%s), parent=x%x, trans_tbl=x%x) new_lu=x%x(%s)\n",
03844 lu, nmg_orientation(lu->orientation),
03845 parent , trans_tbl , new_lu,
03846 nmg_orientation(new_lu->orientation) );
03847 }
03848 return (new_lu);
03849 }
03850
03851
03852
03853
03854
03855
03856
03857 void
03858 nmg_set_lu_orientation(struct loopuse *lu, int is_opposite)
03859 {
03860 NMG_CK_LOOPUSE(lu);
03861 NMG_CK_LOOPUSE(lu->lumate_p);
03862 if (rt_g.NMG_debug & DEBUG_BASIC) {
03863 bu_log("nmg_set_lu_orientation(lu=x%x, %s)\n",
03864 lu, is_opposite?"OT_OPPOSITE":"OT_SAME");
03865 }
03866 if( is_opposite ) {
03867
03868 lu->orientation = OT_OPPOSITE;
03869 lu->lumate_p->orientation = OT_OPPOSITE;
03870 } else {
03871
03872 lu->orientation = OT_SAME;
03873 lu->lumate_p->orientation = OT_SAME;
03874 }
03875 }
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887 void
03888 nmg_lu_reorient(struct loopuse *lu)
03889 {
03890 struct faceuse *fu;
03891 int geom_orient;
03892 plane_t norm;
03893 plane_t lu_pl;
03894
03895 NMG_CK_LOOPUSE(lu);
03896
03897 if (rt_g.NMG_debug & DEBUG_BASIC) {
03898 bu_log("nmg_lu_reorient(lu=x%x)\n", lu);
03899 }
03900
03901
03902 if( lu->orientation == OT_BOOLPLACE &&
03903 BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC )
03904 return;
03905
03906 fu = lu->up.fu_p;
03907 NMG_CK_FACEUSE(fu);
03908 if( fu->orientation != OT_SAME ) {
03909 lu = lu->lumate_p;
03910 NMG_CK_LOOPUSE(lu);
03911 fu = lu->up.fu_p;
03912 NMG_CK_FACEUSE(fu);
03913 if (rt_g.NMG_debug & DEBUG_BASIC)
03914 bu_log("nmg_lu_reorient() selecting other fu=x%x, lu=x%x\n", fu, lu);
03915 if( fu->orientation != OT_SAME )
03916 rt_bomb("nmg_lu_reorient() no OT_SAME fu?\n");
03917 }
03918
03919
03920
03921 NMG_GET_FU_PLANE( norm, fu );
03922 if (rt_g.NMG_debug & DEBUG_BASIC) {
03923 PLPRINT("\tfu peqn", norm);
03924 }
03925
03926 nmg_loop_plane_newell( lu, lu_pl );
03927
03928 if( lu->orientation == OT_OPPOSITE )
03929 HREVERSE( lu_pl, lu_pl );
03930
03931 if( VDOT( lu_pl, norm ) < 0.0 )
03932 geom_orient = OT_OPPOSITE;
03933 else
03934 geom_orient = OT_SAME;
03935
03936 if( lu->orientation == geom_orient ) return;
03937 if( rt_g.NMG_debug & DEBUG_BASIC ) {
03938 bu_log("nmg_lu_reorient(x%x): changing orientation: %s to %s\n",
03939 lu, nmg_orientation(lu->orientation),
03940 nmg_orientation(geom_orient) );
03941 }
03942
03943 lu->orientation = geom_orient;
03944 lu->lumate_p->orientation = geom_orient;
03945 }
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992 struct edgeuse *
03993 nmg_eusplit(struct vertex *v, struct edgeuse *oldeu, int share_geom)
03994 {
03995 struct edgeuse *eu1,
03996 *eu2,
03997 *oldeumate;
03998 struct shell *s = NULL;
03999 struct loopuse *lu;
04000
04001 NMG_CK_EDGEUSE(oldeu);
04002 if (v) {
04003 NMG_CK_VERTEX(v);
04004 }
04005 oldeumate = oldeu->eumate_p;
04006 NMG_CK_EDGEUSE( oldeumate );
04007
04008
04009
04010
04011
04012
04013 if (oldeu->radial_p != oldeumate)
04014 nmg_unglueedge(oldeu);
04015
04016 if (*oldeu->up.magic_p == NMG_SHELL_MAGIC) {
04017 s = oldeu->up.s_p;
04018 NMG_CK_SHELL(s);
04019
04020
04021
04022
04023
04024
04025
04026
04027 eu1 = nmg_me(v, oldeumate->vu_p->v_p, s);
04028 eu2 = eu1->eumate_p;
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043 nmg_movevu(oldeumate->vu_p, eu1->vu_p->v_p);
04044
04045
04046
04047
04048
04049
04050 if( BU_LIST_PNEXT(edgeuse, oldeu) != oldeumate ) {
04051 BU_LIST_DEQUEUE( &oldeumate->l );
04052 BU_LIST_APPEND( &oldeu->l, &oldeumate->l );
04053 }
04054 BU_LIST_DEQUEUE( &eu1->l );
04055 BU_LIST_DEQUEUE( &eu2->l );
04056 BU_LIST_APPEND( &oldeumate->l, &eu1->l );
04057 BU_LIST_APPEND( &eu1->l, &eu2->l );
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068 if( share_geom ) {
04069
04070 nmg_use_edge_g( eu1, oldeu->g.magic_p );
04071 nmg_use_edge_g( eu2, oldeumate->g.magic_p );
04072 } else {
04073
04074 nmg_use_edge_g( eu2, oldeu->g.magic_p );
04075
04076 BU_LIST_DEQUEUE( &oldeumate->l2 );
04077 nmg_keg( oldeumate );
04078 BU_LIST_DEQUEUE( &eu1->l2 );
04079 nmg_keg( eu1 );
04080 BU_LIST_INIT( &oldeumate->l2 );
04081 BU_LIST_INIT( &eu1->l2 );
04082 oldeumate->l2.magic = NMG_EDGEUSE2_MAGIC;
04083 eu1->l2.magic = NMG_EDGEUSE2_MAGIC;
04084 }
04085 goto out;
04086 }
04087 else if (*oldeu->up.magic_p != NMG_LOOPUSE_MAGIC) {
04088 bu_log("nmg_eusplit() in %s at %d invalid edgeuse parent\n",
04089 __FILE__, __LINE__);
04090 rt_bomb("nmg_eusplit\n");
04091 }
04092
04093
04094
04095 lu = oldeu->up.lu_p;
04096 NMG_CK_LOOPUSE(lu);
04097
04098
04099 if (*lu->up.magic_p == NMG_SHELL_MAGIC)
04100 s = lu->up.s_p;
04101 else if (*lu->up.magic_p == NMG_FACEUSE_MAGIC)
04102 s = lu->up.fu_p->s_p;
04103 else
04104 rt_bomb("nmg_eusplit() bad lu->up\n");
04105 NMG_CK_SHELL(s);
04106
04107
04108 if (v) {
04109
04110 eu1 = nmg_me(v, v, s);
04111 eu2 = eu1->eumate_p;
04112 } else {
04113
04114 eu1 = nmg_me((struct vertex *)NULL, (struct vertex *)NULL, s);
04115 eu2 = eu1->eumate_p;
04116
04117
04118
04119 nmg_movevu(eu2->vu_p, eu1->vu_p->v_p);
04120 }
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132
04133
04134
04135
04136
04137 BU_LIST_DEQUEUE( &eu1->l );
04138 BU_LIST_DEQUEUE( &eu2->l );
04139 BU_LIST_APPEND( &oldeu->l, &eu1->l );
04140 BU_LIST_APPEND( &oldeumate->l, &eu2->l );
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155 eu1->up.magic_p = oldeu->up.magic_p;
04156 eu1->orientation = oldeu->orientation;
04157
04158 eu2->up.magic_p = oldeumate->up.magic_p;
04159 eu2->orientation = oldeumate->orientation;
04160
04161
04162 eu1->eumate_p = oldeumate;
04163 oldeumate->eumate_p = eu1;
04164 eu2->eumate_p = oldeu;
04165 oldeu->eumate_p = eu2;
04166
04167
04168
04169
04170 eu1->radial_p = oldeumate;
04171 oldeumate->radial_p = eu1;
04172 eu2->radial_p = oldeu;
04173 oldeu->radial_p = eu2;
04174
04175
04176 oldeumate->e_p = eu1->e_p;
04177 eu2->e_p = oldeu->e_p;
04178
04179
04180 oldeumate->e_p->eu_p = oldeumate;
04181 eu2->e_p->eu_p = eu2;
04182
04183 if( share_geom ) {
04184
04185 nmg_use_edge_g( eu1, oldeu->g.magic_p );
04186
04187 nmg_use_edge_g( eu2, oldeumate->g.magic_p );
04188 } else {
04189
04190 nmg_use_edge_g( eu2, oldeu->g.magic_p );
04191
04192 BU_LIST_DEQUEUE( &oldeumate->l2 );
04193 nmg_keg( oldeumate );
04194 BU_LIST_DEQUEUE( &eu1->l2 );
04195 nmg_keg( eu1 );
04196 BU_LIST_INIT( &oldeumate->l2 );
04197 BU_LIST_INIT( &eu1->l2 );
04198 oldeumate->l2.magic = NMG_EDGEUSE2_MAGIC;
04199 eu1->l2.magic = NMG_EDGEUSE2_MAGIC;
04200 }
04201 if( oldeu->g.magic_p != oldeu->eumate_p->g.magic_p ) rt_bomb("nmg_eusplit() unshared geom\n");
04202
04203 out:
04204 if (rt_g.NMG_debug & DEBUG_BASIC) {
04205 bu_log("nmg_eusplit(v=x%x, eu=x%x, share=%d) new_eu=x%x, mate=x%x\n",
04206 v, oldeu, share_geom,
04207 eu1, eu1->eumate_p );
04208 }
04209 return(eu1);
04210 }
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267 struct edgeuse *
04268 nmg_esplit(struct vertex *v, struct edgeuse *eu, int share_geom)
04269
04270
04271
04272 {
04273 struct edge *e;
04274 struct edgeuse *teuX,
04275 *teuY,
04276 *neu1, *neu2;
04277 int notdone=1;
04278 struct vertex *vA, *vB;
04279
04280 neu1 = neu2 = (struct edgeuse *)NULL;
04281
04282 NMG_CK_EDGEUSE(eu);
04283 e = eu->e_p;
04284 NMG_CK_EDGE(e);
04285
04286 NMG_CK_VERTEXUSE(eu->vu_p);
04287 vA = eu->vu_p->v_p;
04288 NMG_CK_VERTEX(vA);
04289
04290 NMG_CK_EDGEUSE(eu->eumate_p);
04291 NMG_CK_VERTEXUSE(eu->eumate_p->vu_p);
04292 vB = eu->eumate_p->vu_p->v_p;
04293 NMG_CK_VERTEX(vB);
04294
04295 if( v && ( v == vA || v == vB ) ) {
04296 bu_log("WARNING: nmg_esplit(v=x%x) vertex is already an edge vertex\n", v);
04297 rt_bomb("nmg_esplit() new vertex is already an edge vertex\n");
04298 }
04299
04300
04301
04302
04303
04304 do {
04305
04306 teuX = eu->radial_p;
04307
04308 teuY = nmg_eusplit(v, teuX, share_geom);
04309
04310 NMG_CK_EDGEUSE(teuX);
04311 NMG_CK_EDGEUSE(teuY);
04312 NMG_TEST_EDGEUSE(teuX);
04313 NMG_TEST_EDGEUSE(teuY);
04314
04315 if (!v) {
04316
04317
04318
04319
04320 v = teuY->vu_p->v_p;
04321 NMG_CK_VERTEX(v);
04322 }
04323
04324 if (teuY->e_p == e || teuX->e_p == e) notdone = 0;
04325
04326
04327
04328
04329
04330
04331 NMG_CK_VERTEX(teuX->vu_p->v_p);
04332 if (teuX->vu_p->v_p == vA) {
04333 if (neu1) {
04334 nmg_je(neu1, teuX);
04335 nmg_je(neu2, teuY);
04336 }
04337 neu1 = teuX->eumate_p;
04338 neu2 = teuY->eumate_p;
04339 } else if (teuX->vu_p->v_p == vB) {
04340 if (neu1) {
04341 nmg_je(neu2, teuX);
04342 nmg_je(neu1, teuY);
04343 }
04344 neu2 = teuX->eumate_p;
04345 neu1 = teuY->eumate_p;
04346 } else {
04347 bu_log("nmg_esplit(v=x%x, e=x%x)\n", v, e);
04348 bu_log("nmg_esplit: teuX->vu_p->v_p=x%x, vA=x%x, vB=x%x\n", teuX->vu_p->v_p, vA, vB );
04349 rt_bomb("nmg_esplit() teuX->vu_p->v_p is neither vA nor vB\n");
04350 }
04351 } while (notdone);
04352
04353
04354
04355 if( neu2->vu_p->v_p == v && neu2->eumate_p->vu_p->v_p == vB ) {
04356 if (rt_g.NMG_debug & DEBUG_BASIC) {
04357 bu_log("nmg_esplit(v=x%x, eu=x%x, share=%d) neu2=x%x\n",
04358 v, eu, share_geom, neu2);
04359 }
04360 return neu2;
04361 }
04362 else if( neu1->vu_p->v_p == v && neu1->eumate_p->vu_p->v_p == vB ) {
04363 if (rt_g.NMG_debug & DEBUG_BASIC) {
04364 bu_log("nmg_esplit(v=x%x, eu=x%x, share=%d) neu1=x%x\n",
04365 v, eu, share_geom, neu1);
04366 }
04367 return neu1;
04368 }
04369
04370 rt_bomb("nmg_esplit() unable to find eu starting at new v\n");
04371
04372 return (struct edgeuse *)NULL;
04373 }
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384
04385 struct edgeuse *
04386 nmg_ebreak(struct vertex *v, struct edgeuse *eu)
04387
04388
04389 {
04390 struct edgeuse *new_eu;
04391
04392 NMG_CK_EDGEUSE(eu);
04393 if( eu->g.magic_p ) {
04394 NMG_CK_EDGE_G_LSEG(eu->g.lseg_p);
04395 }
04396
04397 new_eu = nmg_esplit(v, eu, 1);
04398 NMG_CK_EDGEUSE(eu);
04399 NMG_CK_EDGEUSE(new_eu);
04400
04401 if( eu->e_p == new_eu->e_p ) rt_bomb("nmb_ebreak() same edges?\n");
04402
04403 if (rt_g.NMG_debug & DEBUG_BASIC) {
04404 bu_log("nmg_ebreak( v=x%x, eu=x%x ) new_eu=x%x\n",
04405 v, eu, new_eu);
04406 }
04407 return new_eu;
04408 }
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421 struct edgeuse *
04422 nmg_ebreaker(struct vertex *v, struct edgeuse *eu, const struct bn_tol *tol)
04423
04424
04425
04426 {
04427 struct edgeuse *new_eu;
04428 struct edgeuse *oeu;
04429
04430 NMG_CK_EDGEUSE(eu);
04431 BN_CK_TOL(tol);
04432
04433 nmg_eu_radial_check( eu, nmg_find_s_of_eu(eu), tol );
04434 new_eu = nmg_ebreak(v, eu);
04435 if( v ) {
04436
04437
04438
04439
04440
04441 for(;;) {
04442 oeu = nmg_find_e( eu->vu_p->v_p,
04443 eu->eumate_p->vu_p->v_p,
04444 (struct shell *)NULL, eu->e_p );
04445 if( !oeu ) break;
04446 if (rt_g.NMG_debug & DEBUG_BASIC) {
04447 bu_log("nmg_ebreaker() joining eu=x%x to oeu=x%x\n",
04448 eu, oeu );
04449 }
04450 nmg_radial_join_eu( eu, oeu, tol );
04451 }
04452
04453 for(;;) {
04454 oeu = nmg_find_e( new_eu->vu_p->v_p,
04455 new_eu->eumate_p->vu_p->v_p,
04456 (struct shell *)NULL, new_eu->e_p );
04457 if( !oeu ) break;
04458 if (rt_g.NMG_debug & DEBUG_BASIC) {
04459 bu_log("nmg_ebreaker() joining new_eu=x%x to oeu=x%x\n",
04460 new_eu, oeu );
04461 }
04462 nmg_radial_join_eu( new_eu, oeu, tol );
04463 }
04464
04465 nmg_eu_radial_check( eu, nmg_find_s_of_eu(eu), tol );
04466 nmg_eu_radial_check( new_eu, nmg_find_s_of_eu(new_eu), tol );
04467 if( nmg_check_radial( eu, tol ) ) bu_log("ERROR ebreaker eu=x%x bad\n", eu);
04468 if( nmg_check_radial( new_eu, tol ) ) bu_log("ERROR ebreaker new_eu=x%x bad\n", new_eu);
04469 }
04470 if (rt_g.NMG_debug & DEBUG_BASIC) {
04471 bu_log("nmg_ebreaker( v=x%x, eu=x%x ) new_eu=x%x\n", v, eu, new_eu);
04472 }
04473 return new_eu;
04474 }
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484 struct vertex *
04485 nmg_e2break(struct edgeuse *eu1, struct edgeuse *eu2)
04486 {
04487 struct vertex *v;
04488 struct edgeuse *new_eu;
04489
04490 NMG_CK_EDGEUSE(eu1);
04491 NMG_CK_EDGEUSE(eu2);
04492
04493 new_eu = nmg_ebreak( NULL, eu1 );
04494 v = new_eu->vu_p->v_p;
04495 NMG_CK_VERTEX(v);
04496 (void)nmg_ebreak( v, eu2 );
04497
04498 if (rt_g.NMG_debug & DEBUG_BASIC) {
04499 bu_log("nmg_e2break( eu1=x%x, eu2=x%x ) v=x%x\n", eu1, eu2, v);
04500 }
04501 return v;
04502 }
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543 int
04544 nmg_unbreak_edge(struct edgeuse *eu1_first)
04545 {
04546 struct edgeuse *eu1;
04547 struct edgeuse *eu2;
04548 struct edgeuse *teu;
04549 struct edge *e1;
04550 struct edge_g_lseg *eg;
04551 struct vertexuse *vu;
04552 struct vertex *vb = 0;
04553 struct vertex *vc;
04554 struct vertex *va;
04555 struct shell *s1;
04556 int ret = 0;
04557
04558 NMG_CK_EDGEUSE( eu1_first );
04559 e1 = eu1_first->e_p;
04560 NMG_CK_EDGE( e1 );
04561
04562 if( eu1_first->g.magic_p != eu1_first->eumate_p->g.magic_p )
04563 rt_bomb("nmg_unbreak_edge() eu and mate don't share geometry\n");
04564
04565 eg = eu1_first->g.lseg_p;
04566 if( !eg ) {
04567 bu_log( "nmg_unbreak_edge: no geometry for edge1 x%x\n" , e1 );
04568 ret = -1;
04569 goto out;
04570 }
04571 NMG_CK_EDGE_G_LSEG(eg);
04572
04573
04574
04575 if( bu_list_len( &eg->eu_hd2 ) < 2*2 ) {
04576 ret = -2;
04577 goto out;
04578 }
04579
04580 s1 = nmg_find_s_of_eu(eu1_first);
04581 NMG_CK_SHELL(s1);
04582
04583 eu1 = eu1_first;
04584 eu2 = BU_LIST_PNEXT_CIRC( edgeuse , eu1 );
04585 if( eu2->g.lseg_p != eg ) {
04586 bu_log( "nmg_unbreak_edge: second eu geometry x%x does not match geometry x%x of edge1 x%x\n" ,
04587 eu2->g.magic_p, eg, e1 );
04588 ret = -3;
04589 goto out;
04590 }
04591
04592 va = eu1->vu_p->v_p;
04593 vb = eu2->vu_p->v_p;
04594 vc = eu2->eumate_p->vu_p->v_p;
04595
04596
04597
04598 for( BU_LIST_FOR( vu , vertexuse , &vb->vu_hd ) ) {
04599 NMG_CK_VERTEXUSE(vu);
04600 if( *(vu->up.magic_p) != NMG_EDGEUSE_MAGIC ) {
04601
04602 if( vu->up.lu_p->orientation == OT_BOOLPLACE ) {
04603
04604 continue;
04605 }
04606 ret = -4;
04607 goto out;
04608 }
04609 NMG_CK_EDGEUSE(vu->up.eu_p);
04610 if( vu->up.eu_p->g.lseg_p != eg ) {
04611 ret = -5;
04612 goto out;
04613 }
04614 }
04615
04616
04617 teu = eu1;
04618 for(;;) {
04619 register struct edgeuse *teu2;
04620 NMG_CK_EDGEUSE(teu);
04621 if( teu->vu_p->v_p != va || teu->eumate_p->vu_p->v_p != vb ) {
04622 ret = -6;
04623 goto out;
04624 }
04625
04626 teu2 = BU_LIST_PNEXT_CIRC( edgeuse, teu );
04627 NMG_CK_EDGEUSE(teu2);
04628 if( teu2->vu_p->v_p != vb || teu2->eumate_p->vu_p->v_p != vc ) {
04629 ret = -7;
04630 goto out;
04631 }
04632 teu = teu->eumate_p->radial_p;
04633 if( teu == eu1 ) break;
04634 }
04635
04636
04637 teu = eu2;
04638 for(;;) {
04639 NMG_CK_EDGEUSE(teu);
04640 if( teu->vu_p->v_p != vb || teu->eumate_p->vu_p->v_p != vc ) {
04641 ret = -8;
04642 goto out;
04643 }
04644 teu = teu->eumate_p->radial_p;
04645 if( teu == eu2 ) break;
04646 }
04647
04648
04649 if (rt_g.NMG_debug & DEBUG_BASIC) {
04650 bu_log("nmg_unbreak_edge va=x%x, vb=x%x, vc=x%x\n",
04651 va, vb, vc );
04652 bu_log("nmg_unbreak_edge A:(%g, %g, %g), B:(%g, %g, %g), C:(%g, %g, %g)\n",
04653 V3ARGS( va->vg_p->coord ),
04654 V3ARGS( vb->vg_p->coord ),
04655 V3ARGS( vc->vg_p->coord ) );
04656 }
04657
04658 if( va == vc )
04659 {
04660
04661 ret = -9;
04662 goto out;
04663 }
04664
04665
04666
04667 for(;;) {
04668
04669 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vb ) {
04670 bu_log( "nmg_unbreak_edge: eu1 does not got to/from correct vertices, x%x, %x\n",
04671 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04672 nmg_pr_eu_briefly( eu1, " " );
04673 rt_bomb( "nmg_unbreak_edge 1\n" );
04674 }
04675 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, eu1 );
04676 NMG_CK_EDGEUSE(eu2);
04677 if( eu2->g.lseg_p != eg ) {
04678 rt_bomb("nmg_unbreak_edge: eu2 geometry is wrong\n");
04679 }
04680 if( eu2->vu_p->v_p != vb || eu2->eumate_p->vu_p->v_p != vc ) {
04681 bu_log( "nmg_unbreak_edge: about to kill eu2, but does not got to/from correct vertices, x%x, x%x\n",
04682 eu2->vu_p->v_p, eu2->eumate_p->vu_p->v_p );
04683 nmg_pr_eu_briefly( eu2, " " );
04684 rt_bomb( "nmg_unbreak_edge 3\n" );
04685 }
04686
04687
04688 nmg_movevu( eu1->eumate_p->vu_p , vc );
04689
04690 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vc ) {
04691 bu_log( "nmg_unbreak_edge: extended eu1 does not got to/from correct vertices, x%x, x%x\n",
04692 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04693 nmg_pr_eu_briefly( eu1, " " );
04694 rt_bomb( "nmg_unbreak_edge 2\n" );
04695 }
04696
04697 if( eu2 != BU_LIST_PNEXT_CIRC( edgeuse, eu1 ) )
04698 rt_bomb("nmg_unbreak_edge eu2 unexpected altered\n");
04699
04700
04701 if( nmg_keu( eu2 ) )
04702 rt_bomb( "nmg_unbreak_edge: edgeuse parent is now empty!!\n" );
04703
04704 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vc ) {
04705 bu_log( "nmg_unbreak_edge: unbroken eu1 (after eu2 killed) does not got to/from correct vertices, x%x, x%x\n",
04706 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04707 nmg_pr_eu_briefly( eu1, " " );
04708 rt_bomb( "nmg_unbreak_edge 4\n" );
04709 }
04710 eu1 = eu1->eumate_p->radial_p;
04711 if( eu1 == eu1_first ) break;
04712 }
04713 out:
04714 if (rt_g.NMG_debug & DEBUG_BASIC) {
04715 bu_log("nmg_unbreak_edge(eu=x%x, vb=x%x) ret = %d\n",
04716 eu1_first, vb, ret);
04717 }
04718 return ret;
04719 }
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762 int
04763 nmg_unbreak_shell_edge_unsafe(struct edgeuse *eu1_first)
04764 {
04765 struct edgeuse *eu1;
04766 struct edgeuse *eu2;
04767 struct edgeuse *teu;
04768 struct edge *e1;
04769 struct edge_g_lseg *eg;
04770 struct vertexuse *vu;
04771 struct vertex *vb = 0;
04772 struct vertex *vc;
04773 struct vertex *va;
04774 struct shell *s1;
04775 int ret = 0;
04776
04777 NMG_CK_EDGEUSE( eu1_first );
04778 e1 = eu1_first->e_p;
04779 NMG_CK_EDGE( e1 );
04780
04781 if( eu1_first->g.magic_p != eu1_first->eumate_p->g.magic_p )
04782 {
04783 ret = -10;
04784 goto out;
04785 }
04786
04787 eg = eu1_first->g.lseg_p;
04788 if( !eg ) {
04789 ret = -1;
04790 goto out;
04791 }
04792 NMG_CK_EDGE_G_LSEG(eg);
04793
04794 s1 = nmg_find_s_of_eu(eu1_first);
04795 NMG_CK_SHELL(s1);
04796
04797 eu1 = eu1_first;
04798 eu2 = BU_LIST_PNEXT_CIRC( edgeuse , eu1 );
04799 if( eu2->g.lseg_p != eg ) {
04800 bu_log( "nmg_unbreak_edge: second eu geometry x%x does not match geometry x%x of edge1 x%x\n" ,
04801 eu2->g.magic_p, eg, e1 );
04802 ret = -3;
04803 goto out;
04804 }
04805
04806 va = eu1->vu_p->v_p;
04807 vb = eu2->vu_p->v_p;
04808 vc = eu2->eumate_p->vu_p->v_p;
04809
04810
04811
04812 for( BU_LIST_FOR( vu , vertexuse , &vb->vu_hd ) ) {
04813 NMG_CK_VERTEXUSE(vu);
04814 if( *(vu->up.magic_p) != NMG_EDGEUSE_MAGIC ) {
04815
04816 if( vu->up.lu_p->orientation == OT_BOOLPLACE ) {
04817
04818 continue;
04819 }
04820 ret = -4;
04821 goto out;
04822 }
04823 if( nmg_find_s_of_vu( vu ) != s1 )
04824 continue;
04825 NMG_CK_EDGEUSE(vu->up.eu_p);
04826 if( vu->up.eu_p->g.lseg_p != eg ) {
04827 ret = -5;
04828 goto out;
04829 }
04830 }
04831
04832
04833 teu = eu1;
04834 for(;;) {
04835 register struct edgeuse *teu2;
04836 NMG_CK_EDGEUSE(teu);
04837 if( teu->vu_p->v_p != va || teu->eumate_p->vu_p->v_p != vb ) {
04838 ret = -6;
04839 goto out;
04840 }
04841
04842 teu2 = BU_LIST_PNEXT_CIRC( edgeuse, teu );
04843 NMG_CK_EDGEUSE(teu2);
04844 if( teu2->vu_p->v_p != vb || teu2->eumate_p->vu_p->v_p != vc ) {
04845 ret = -7;
04846 goto out;
04847 }
04848 teu = teu->eumate_p->radial_p;
04849 if( teu == eu1 ) break;
04850 }
04851
04852
04853 teu = eu2;
04854 for(;;) {
04855 NMG_CK_EDGEUSE(teu);
04856 if( teu->vu_p->v_p != vb || teu->eumate_p->vu_p->v_p != vc ) {
04857 ret = -8;
04858 goto out;
04859 }
04860 teu = teu->eumate_p->radial_p;
04861 if( teu == eu2 ) break;
04862 }
04863
04864
04865 if (rt_g.NMG_debug & DEBUG_BASIC) {
04866 bu_log("nmg_unbreak_edge va=x%x, vb=x%x, vc=x%x\n",
04867 va, vb, vc );
04868 bu_log("nmg_unbreak_edge A:(%g, %g, %g), B:(%g, %g, %g), C:(%g, %g, %g)\n",
04869 V3ARGS( va->vg_p->coord ),
04870 V3ARGS( vb->vg_p->coord ),
04871 V3ARGS( vc->vg_p->coord ) );
04872 }
04873
04874 if( va == vc )
04875 {
04876
04877 ret = -9;
04878 goto out;
04879 }
04880
04881
04882
04883 for(;;) {
04884
04885 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vb ) {
04886 bu_log( "nmg_unbreak_edge: eu1 does not got to/from correct vertices, x%x, %x\n",
04887 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04888 nmg_pr_eu_briefly( eu1, " " );
04889 rt_bomb( "nmg_unbreak_edge 1\n" );
04890 }
04891 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, eu1 );
04892 NMG_CK_EDGEUSE(eu2);
04893 if( eu2->g.lseg_p != eg ) {
04894 rt_bomb("nmg_unbreak_edge: eu2 geometry is wrong\n");
04895 }
04896 if( eu2->vu_p->v_p != vb || eu2->eumate_p->vu_p->v_p != vc ) {
04897 bu_log( "nmg_unbreak_edge: about to kill eu2, but does not got to/from correct vertices, x%x, x%x\n",
04898 eu2->vu_p->v_p, eu2->eumate_p->vu_p->v_p );
04899 nmg_pr_eu_briefly( eu2, " " );
04900 rt_bomb( "nmg_unbreak_edge 3\n" );
04901 }
04902
04903
04904 nmg_movevu( eu1->eumate_p->vu_p , vc );
04905
04906 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vc ) {
04907 bu_log( "nmg_unbreak_edge: extended eu1 does not got to/from correct vertices, x%x, x%x\n",
04908 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04909 nmg_pr_eu_briefly( eu1, " " );
04910 rt_bomb( "nmg_unbreak_edge 2\n" );
04911 }
04912
04913 if( eu2 != BU_LIST_PNEXT_CIRC( edgeuse, eu1 ) )
04914 rt_bomb("nmg_unbreak_edge eu2 unexpected altered\n");
04915
04916
04917 if( nmg_keu( eu2 ) )
04918 rt_bomb( "nmg_unbreak_edge: edgeuse parent is now empty!!\n" );
04919
04920 if( eu1->vu_p->v_p != va || eu1->eumate_p->vu_p->v_p != vc ) {
04921 bu_log( "nmg_unbreak_edge: unbroken eu1 (after eu2 killed) does not got to/from correct vertices, x%x, x%x\n",
04922 eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p );
04923 nmg_pr_eu_briefly( eu1, " " );
04924 rt_bomb( "nmg_unbreak_edge 4\n" );
04925 }
04926 eu1 = eu1->eumate_p->radial_p;
04927 if( eu1 == eu1_first ) break;
04928 }
04929 out:
04930 if (rt_g.NMG_debug & DEBUG_BASIC) {
04931 bu_log("nmg_unbreak_edge(eu=x%x, vb=x%x) ret = %d\n",
04932 eu1_first, vb, ret);
04933 }
04934 return ret;
04935 }
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962 struct edgeuse *
04963 nmg_eins(struct edgeuse *eu)
04964 {
04965 struct edgeuse *eumate;
04966 struct edgeuse *eu1, *eu2;
04967 struct shell *s;
04968
04969 NMG_CK_EDGEUSE(eu);
04970 eumate = eu->eumate_p;
04971 NMG_CK_EDGEUSE(eumate);
04972
04973 if (*eu->up.magic_p == NMG_SHELL_MAGIC) {
04974 s = eu->up.s_p;
04975 NMG_CK_SHELL(s);
04976 }
04977 else {
04978 struct loopuse *lu;
04979
04980 lu = eu->up.lu_p;
04981 NMG_CK_LOOPUSE(lu);
04982 if (*lu->up.magic_p == NMG_SHELL_MAGIC) {
04983 s = lu->up.s_p;
04984 NMG_CK_SHELL(s);
04985 } else {
04986 struct faceuse *fu;
04987 fu = lu->up.fu_p;
04988 NMG_CK_FACEUSE(fu);
04989 s = fu->s_p;
04990 NMG_CK_SHELL(s);
04991 }
04992 }
04993
04994 eu1 = nmg_me(eu->vu_p->v_p, eu->vu_p->v_p, s);
04995 eu2 = eu1->eumate_p;
04996
04997 if (*eu->up.magic_p == NMG_LOOPUSE_MAGIC) {
04998 BU_LIST_DEQUEUE( &eu1->l );
04999 BU_LIST_DEQUEUE( &eu2->l );
05000
05001 BU_LIST_INSERT( &eu->l, &eu1->l );
05002 BU_LIST_APPEND( &eumate->l, &eu2->l );
05003
05004 eu1->up.lu_p = eu->up.lu_p;
05005 eu2->up.lu_p = eumate->up.lu_p;
05006 }
05007 else {
05008 rt_bomb("nmg_eins() Cannot yet insert null edge in shell\n");
05009 }
05010 if (rt_g.NMG_debug & DEBUG_BASIC) {
05011 bu_log("nmg_eins(eu=x%x) eu1=x%x\n", eu, eu1);
05012 }
05013 return(eu1);
05014 }
05015
05016
05017
05018
05019
05020
05021 void
05022 nmg_mv_eu_between_shells(struct shell *dest, register struct shell *src, register struct edgeuse *eu)
05023 {
05024 register struct edgeuse *eumate;
05025
05026 NMG_CK_EDGEUSE(eu);
05027 eumate = eu->eumate_p;
05028 NMG_CK_EDGEUSE(eumate);
05029
05030 if (eu->up.s_p != src) {
05031 bu_log("nmg_mv_eu_between_shells(dest=x%x, src=x%x, eu=x%x), eu->up.s_p=x%x isnt src shell\n",
05032 dest, src, eu, eu->up.s_p );
05033 rt_bomb("eu->up.s_p isnt source shell\n");
05034 }
05035 if (eumate->up.s_p != src) {
05036 bu_log("nmg_mv_eu_between_shells(dest=x%x, src=x%x, eu=x%x), eumate->up.s_p=x%x isn't src shell\n",
05037 dest, src, eu, eumate->up.s_p );
05038 rt_bomb("eumate->up.s_p isnt source shell\n");
05039 }
05040
05041
05042 BU_LIST_DEQUEUE( &eu->l );
05043 if( BU_LIST_IS_EMPTY( &src->eu_hd ) ) {
05044
05045 bu_log("nmg_mv_eu_between_shells(dest=x%x, src=x%x, eu=x%x), eumate=x%x not in src shell\n",
05046 dest, src, eu, eumate );
05047 rt_bomb("src shell emptied before finding eumate\n");
05048 }
05049
05050
05051 BU_LIST_DEQUEUE( &eumate->l );
05052
05053
05054 BU_LIST_APPEND( &dest->eu_hd, &eu->l );
05055 BU_LIST_APPEND( &eu->l, &eumate->l );
05056
05057 eu->up.s_p = dest;
05058 eumate->up.s_p = dest;
05059
05060 if (rt_g.NMG_debug & DEBUG_BASIC) {
05061 bu_log("nmg_mv_eu_between_shells( dest=x%x, src=x%x, eu=x%x ) new_eu=x%x\n",
05062 dest, src, eu);
05063 }
05064 }
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078 void
05079 nmg_mv_vu_between_shells(struct shell *dest, register struct shell *src, register struct vertexuse *vu)
05080 {
05081 NMG_CK_VERTEXUSE( vu );
05082 NMG_CK_VERTEX( vu->v_p );
05083
05084 if (rt_g.NMG_debug & DEBUG_BASIC) {
05085 bu_log("nmg_mv_vu_between_shells( dest_s=x%x, src_s=x%x, vu=x%x )\n",
05086 dest, src, vu);
05087 }
05088 (void) nmg_mlv( &(dest->l.magic), vu->v_p, OT_SAME );
05089 if (vu->v_p->vg_p) {
05090 NMG_CK_VERTEX_G(vu->v_p->vg_p);
05091 }
05092 nmg_kvu( vu );
05093 }
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103