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_fuse.c,v 14.15 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00042 #endif
00043
00044 #include "common.h"
00045
00046 #include <stddef.h>
00047 #include <stdio.h>
00048 #ifdef HAVE_STRING_H
00049 # include <string.h>
00050 #else
00051 # include <strings.h>
00052 #endif
00053 #include <math.h>
00054
00055 #include "machine.h"
00056 #include "vmath.h"
00057 #include "nmg.h"
00058 #include "raytrace.h"
00059 #include "nurb.h"
00060 #include "./debug.h"
00061
00062 extern int debug_file_count;
00063
00064
00065 struct pt_list
00066 {
00067 struct bu_list l;
00068 point_t xyz;
00069 fastf_t t;
00070 };
00071
00072 BU_EXTERN(void nmg_split_trim,
00073 (const struct edge_g_cnurb *cnrb,
00074 const struct face_g_snurb *snrb,
00075 fastf_t t,
00076 struct pt_list *pt0, struct pt_list *pt1,
00077 const struct bn_tol *tol));
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 int
00089 nmg_is_common_bigloop(const struct face *f1, const struct face *f2)
00090 {
00091 const struct faceuse *fu1;
00092 const struct loopuse *lu1;
00093 const struct edgeuse *eu1;
00094 const long *magic1 = (long *)NULL;
00095 const long *magic2 = (long *)NULL;
00096 int nverts;
00097 int nbadv;
00098 int got_three;
00099
00100 NMG_CK_FACE(f1);
00101 NMG_CK_FACE(f2);
00102
00103 fu1 = f1->fu_p;
00104 NMG_CK_FACEUSE(fu1);
00105
00106
00107 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) ) {
00108 if( BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC )
00109 continue;
00110 nverts = 0;
00111 nbadv = 0;
00112 magic1 = (long *)NULL;
00113 magic2 = (long *)NULL;
00114 got_three = 0;
00115 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) ) {
00116 nverts++;
00117 NMG_CK_EDGE_G_LSEG(eu1->g.lseg_p);
00118 if( !magic1 ) {
00119 magic1 = eu1->g.magic_p;
00120 } else if( !magic2 ) {
00121 if( eu1->g.magic_p != magic1 ) {
00122 magic2 = eu1->g.magic_p;
00123 }
00124 } else {
00125 if( eu1->g.magic_p != magic1 &&
00126 eu1->g.magic_p != magic2 ) {
00127 got_three = 1;
00128 }
00129 }
00130 if( nmg_is_vertex_in_face( eu1->vu_p->v_p, f2 ) )
00131 continue;
00132 nbadv++;
00133 break;
00134 }
00135 if( nbadv <= 0 && nverts >= 3 && got_three ) return 1;
00136 }
00137 return 0;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 void
00148 nmg_region_v_unique(struct nmgregion *r1, const struct bn_tol *tol)
00149 {
00150 int i;
00151 int j;
00152 struct bu_ptbl t;
00153
00154 NMG_CK_REGION(r1);
00155 BN_CK_TOL(tol);
00156
00157 nmg_vertex_tabulate( &t, &r1->l.magic );
00158
00159 for( i = BU_PTBL_END(&t)-1; i >= 0; i-- ) {
00160 register struct vertex *vi;
00161 vi = (struct vertex *)BU_PTBL_GET(&t, i);
00162 NMG_CK_VERTEX(vi);
00163 if( !vi->vg_p ) continue;
00164
00165 for( j = i-1; j >= 0; j-- ) {
00166 register struct vertex *vj;
00167 vj = (struct vertex *)BU_PTBL_GET(&t, j);
00168 NMG_CK_VERTEX(vj);
00169 if( !vj->vg_p ) continue;
00170 if( !bn_pt3_pt3_equal( vi->vg_p->coord, vj->vg_p->coord, tol ) )
00171 continue;
00172
00173 bu_log("nmg_region_v_unique(): 2 verts are the same, within tolerance\n");
00174 nmg_pr_v( vi, 0 );
00175 nmg_pr_v( vj, 0 );
00176 rt_bomb("nmg_region_v_unique()\n");
00177 }
00178 }
00179 bu_ptbl_free( &t);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 int
00191 nmg_ptbl_vfuse(struct bu_ptbl *t, const struct bn_tol *tol)
00192 {
00193 int count = 0;
00194 int i;
00195 int j;
00196
00197 for( i = BU_PTBL_END(t)-1; i >= 0; i-- ) {
00198 register struct vertex *vi;
00199 vi = (struct vertex *)BU_PTBL_GET(t, i);
00200 NMG_CK_VERTEX(vi);
00201 if( !vi->vg_p ) continue;
00202
00203 for( j = i-1; j >= 0; j-- ) {
00204 register struct vertex *vj;
00205 vj = (struct vertex *)BU_PTBL_GET(t, j);
00206 NMG_CK_VERTEX(vj);
00207 if( !vj->vg_p ) continue;
00208 if( !bn_pt3_pt3_equal( vi->vg_p->coord, vj->vg_p->coord, tol ) )
00209 continue;
00210
00211 nmg_jv( vj, vi );
00212 bu_ptbl_rm( t, (long *)vi );
00213 count++;
00214 break;
00215 }
00216 }
00217 return count;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 int
00232 nmg_region_both_vfuse(struct bu_ptbl *t1, struct bu_ptbl *t2, const struct bn_tol *tol)
00233 {
00234 int count = 0;
00235 int i;
00236 int j;
00237
00238
00239 for( j = BU_PTBL_END(t2)-1; j >= 0; j-- ) {
00240 register struct vertex *vj;
00241 vj = (struct vertex *)BU_PTBL_GET(t2, j);
00242 NMG_CK_VERTEX(vj);
00243 }
00244
00245 for( i = BU_PTBL_END(t1)-1; i >= 0; i-- ) {
00246 register struct vertex *vi;
00247 vi = (struct vertex *)BU_PTBL_GET(t1, i);
00248 NMG_CK_VERTEX(vi);
00249 if( !vi->vg_p ) continue;
00250
00251 for( j = BU_PTBL_END(t2)-1; j >= 0; j-- ) {
00252 register struct vertex *vj;
00253 vj = (struct vertex *)BU_PTBL_GET(t2, j);
00254 if(!vj) continue;
00255 NMG_CK_VERTEX(vj);
00256 if( !vj->vg_p ) continue;
00257 if( !bn_pt3_pt3_equal( vi->vg_p->coord, vj->vg_p->coord, tol ) )
00258 continue;
00259
00260 nmg_jv( vi, vj );
00261 BU_PTBL_GET(t2, j) = 0;
00262 count++;
00263 }
00264 }
00265 return count;
00266 }
00267
00268 #if 0
00269
00270
00271
00272
00273
00274 int
00275 nmg_two_region_vertex_fuse( r1, r2, tol )
00276 struct nmgregion *r1;
00277 struct nmgregion *r2;
00278 const struct bn_tol *tol;
00279 {
00280 struct bu_ptbl t1;
00281 struct bu_ptbl t2;
00282 int total = 0;
00283
00284 NMG_CK_REGION(r1);
00285 NMG_CK_REGION(r2);
00286 BN_CK_TOL(tol);
00287
00288 if( r1->m_p != r2->m_p ) rt_bomb("nmg_two_region_vertex_fuse: regions not in same model\n");
00289
00290 nmg_vertex_tabulate( &t1, &r1->l.magic );
00291 nmg_vertex_tabulate( &t2, &r2->l.magic );
00292
00293 total = nmg_ptbl_vfuse( &t1, tol );
00294 total += nmg_region_both_vfuse( &t1, &t2, tol );
00295
00296 bu_ptbl_free( &t1);
00297 bu_ptbl_free( &t2);
00298
00299 return total;
00300 }
00301 #endif
00302
00303
00304
00305
00306
00307
00308
00309 int
00310 nmg_model_vertex_fuse(struct model *m, const struct bn_tol *tol)
00311 {
00312 struct bu_ptbl t1;
00313 int total = 0;
00314
00315 NMG_CK_MODEL(m);
00316 BN_CK_TOL(tol);
00317
00318 nmg_vertex_tabulate( &t1, &m->magic );
00319
00320 total = nmg_ptbl_vfuse( &t1, tol );
00321
00322 bu_ptbl_free( &t1);
00323
00324 if( rt_g.NMG_debug & DEBUG_BASIC && total > 0 )
00325 bu_log("nmg_model_vertex_fuse() %d\n", total);
00326 return total;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 int
00340 nmg_cnurb_is_linear(const struct edge_g_cnurb *cnrb)
00341 {
00342 int i;
00343 int coords;
00344 int last_index;
00345 int linear=0;
00346
00347 NMG_CK_EDGE_G_CNURB( cnrb );
00348
00349 if( rt_g.NMG_debug & DEBUG_MESH )
00350 {
00351 bu_log( "nmg_cnurb_is_linear( x%x )\n", cnrb );
00352 rt_nurb_c_print( cnrb );
00353 }
00354
00355 if( cnrb->order <= 0 )
00356 {
00357 linear = 1;
00358 goto out;
00359 }
00360
00361 if( cnrb->order == 2 )
00362 {
00363 if( cnrb->c_size == 2 )
00364 {
00365 linear = 1;
00366 goto out;
00367 }
00368 }
00369
00370 coords = RT_NURB_EXTRACT_COORDS( cnrb->pt_type );
00371 last_index = (cnrb->c_size - 1)*coords;
00372
00373
00374 for( i=1 ; i<cnrb->c_size-2 ; i++ )
00375 {
00376 if( VEQUAL( &cnrb->ctl_points[0], &cnrb->ctl_points[i] ) )
00377 continue;
00378 if( VEQUAL( &cnrb->ctl_points[last_index], &cnrb->ctl_points[i] ) )
00379 continue;
00380
00381 goto out;
00382 }
00383
00384 linear = 1;
00385
00386 out:
00387 if( rt_g.NMG_debug & DEBUG_MESH )
00388 bu_log( "nmg_cnurb_is_linear( x%x ) returning %d\n", cnrb, linear );
00389
00390 return( linear );
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 int
00404 nmg_snurb_is_planar(const struct face_g_snurb *srf, const struct bn_tol *tol)
00405 {
00406 plane_t pl = {(fastf_t)0.0};
00407 int i;
00408 int coords;
00409 mat_t matrix;
00410 mat_t inverse;
00411 vect_t vsum;
00412 double det;
00413 double one_over_vertex_count;
00414 int planar=0;
00415
00416 NMG_CK_FACE_G_SNURB( srf );
00417 BN_CK_TOL( tol );
00418
00419 if( rt_g.NMG_debug & DEBUG_MESH )
00420 {
00421 bu_log( "nmg_snurb_is_planar( x%x )\n", srf );
00422 #if 1
00423 rt_nurb_s_print( "", srf );
00424 #endif
00425 }
00426
00427 if( srf->order[0] == 2 && srf->order[1] == 2 )
00428 {
00429 if( srf->s_size[0] == 2 && srf->s_size[1] == 2 )
00430 {
00431 planar = 1;
00432 goto out;
00433 }
00434 }
00435
00436
00437 MAT_ZERO( matrix );
00438 VSET( vsum , 0.0 , 0.0 , 0.0 );
00439
00440 one_over_vertex_count = 1.0/(double)(srf->s_size[0]*srf->s_size[1]);
00441 coords = RT_NURB_EXTRACT_COORDS( srf->pt_type );
00442
00443
00444 for( i=0 ; i<srf->s_size[0]*srf->s_size[1] ; i++ )
00445 {
00446 fastf_t *pt;
00447
00448 pt = &srf->ctl_points[ i*coords ];
00449
00450 matrix[0] += pt[X] * pt[X];
00451 matrix[1] += pt[X] * pt[Y];
00452 matrix[2] += pt[X] * pt[Z];
00453 matrix[5] += pt[Y] * pt[Y];
00454 matrix[6] += pt[Y] * pt[Z];
00455 matrix[10] += pt[Z] * pt[Z];
00456
00457 vsum[X] += pt[X];
00458 vsum[Y] += pt[Y];
00459 vsum[Z] += pt[Z];
00460 }
00461 matrix[4] = matrix[1];
00462 matrix[8] = matrix[2];
00463 matrix[9] = matrix[6];
00464 matrix[15] = 1.0;
00465
00466
00467 det = bn_mat_determinant( matrix );
00468
00469 if( !NEAR_ZERO( det , SMALL_FASTF ) )
00470 {
00471 fastf_t inv_len_pl;
00472
00473
00474 bn_mat_inv( inverse , matrix );
00475
00476
00477 MAT4X3PNT( pl , inverse , vsum );
00478
00479
00480 inv_len_pl = 1.0/(MAGNITUDE( pl ));
00481 HSCALE( pl , pl , inv_len_pl );
00482
00483
00484 VSCALE( vsum, vsum, one_over_vertex_count );
00485
00486
00487 pl[H] = VDOT( pl , vsum );
00488
00489 }
00490 else
00491 {
00492 int x_same=1;
00493 int y_same=1;
00494 int z_same=1;
00495
00496
00497
00498
00499 for( i=1 ; i<srf->s_size[0]*srf->s_size[1] ; i++ )
00500 {
00501 if( srf->ctl_points[i*coords+X] != srf->ctl_points[X] )
00502 x_same = 0;
00503 if( srf->ctl_points[i*coords+Y] != srf->ctl_points[Y] )
00504 y_same = 0;
00505 if( srf->ctl_points[i*coords+Z] != srf->ctl_points[Z] )
00506 z_same = 0;
00507
00508 if( !x_same && !y_same && !z_same )
00509 break;
00510 }
00511
00512 if( x_same )
00513 {
00514 VSET( pl , 1.0 , 0.0 , 0.0 );
00515 }
00516 else if( y_same )
00517 {
00518 VSET( pl , 0.0 , 1.0 , 0.0 );
00519 }
00520 else if( z_same )
00521 {
00522 VSET( pl , 0.0 , 0.0 , 1.0 );
00523 }
00524
00525 if( x_same || y_same || z_same )
00526 {
00527
00528 VSCALE( vsum, vsum, one_over_vertex_count );
00529
00530
00531 pl[H] = VDOT( pl , vsum );
00532
00533 }
00534 else
00535 {
00536 bu_log( "nmg_snurb_is_plana: Cannot calculate plane for snurb x%x\n" , srf );
00537 rt_nurb_s_print( "", srf );
00538 rt_bomb( "nmg_snurb_is_plana: Cannot calculate plane for snurb\n" );
00539 }
00540 }
00541
00542
00543 for( i=0 ; i<srf->s_size[0]*srf->s_size[1] ; i++ )
00544 {
00545 fastf_t *pt;
00546 fastf_t dist;
00547
00548 pt = &srf->ctl_points[ i*coords ];
00549
00550 dist = DIST_PT_PLANE( pt, pl );
00551 if( dist > tol->dist )
00552 goto out;
00553 }
00554
00555 planar = 1;
00556 out:
00557 if( rt_g.NMG_debug & DEBUG_MESH )
00558 bu_log( "nmg_snurb_is_planar( x%x ) returning %d\n", srf, planar );
00559
00560 return( planar );
00561
00562 }
00563
00564 void
00565 nmg_eval_linear_trim_curve(const struct face_g_snurb *snrb, const fastf_t *uvw, fastf_t *xyz)
00566 {
00567 int coords;
00568 hpoint_t xyz1;
00569
00570 if( snrb )
00571 {
00572 NMG_CK_FACE_G_SNURB( snrb );
00573 rt_nurb_s_eval( snrb, uvw[0], uvw[1], xyz1 );
00574 if( RT_NURB_IS_PT_RATIONAL( snrb->pt_type ) )
00575 {
00576 fastf_t inverse_weight;
00577
00578 coords = RT_NURB_EXTRACT_COORDS( snrb->pt_type );
00579 inverse_weight = 1.0/xyz1[coords-1];
00580
00581 VSCALE( xyz, xyz1, inverse_weight );
00582 }
00583 else
00584 VMOVE( xyz, xyz1 )
00585 }
00586 else
00587 VMOVE( xyz, uvw )
00588
00589 }
00590
00591 void
00592 nmg_eval_trim_curve(const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, const fastf_t t, fastf_t *xyz)
00593 {
00594 hpoint_t uvw;
00595 hpoint_t xyz1;
00596 int coords;
00597
00598 NMG_CK_EDGE_G_CNURB( cnrb );
00599 if( snrb )
00600 {
00601 NMG_CK_FACE_G_SNURB( snrb )
00602 }
00603
00604 rt_nurb_c_eval( cnrb, t, uvw );
00605
00606 if( RT_NURB_IS_PT_RATIONAL( cnrb->pt_type ) )
00607 {
00608 fastf_t inverse_weight;
00609
00610 coords = RT_NURB_EXTRACT_COORDS( cnrb->pt_type );
00611 inverse_weight = 1.0/uvw[coords-1];
00612
00613 VSCALE( uvw, uvw, inverse_weight );
00614 }
00615
00616 if( snrb )
00617 {
00618 rt_nurb_s_eval( snrb, uvw[0], uvw[1], xyz1 );
00619 if( RT_NURB_IS_PT_RATIONAL( snrb->pt_type ) )
00620 {
00621 fastf_t inverse_weight;
00622
00623 coords = RT_NURB_EXTRACT_COORDS( snrb->pt_type );
00624 inverse_weight = 1.0/xyz1[coords-1];
00625
00626 VSCALE( xyz, xyz1, inverse_weight );
00627 }
00628 else
00629 VMOVE( xyz, xyz1 )
00630 }
00631 else
00632 VMOVE( xyz, uvw )
00633
00634 #if 0
00635 if( rt_g.NMG_debug & DEBUG_MESH )
00636 bu_log( "nmg_eval_trim_curve returning (%g %g %g )\n", V3ARGS( xyz ) );
00637 #endif
00638
00639 }
00640
00641 void
00642 nmg_split_trim(const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, fastf_t t, struct pt_list *pt0, struct pt_list *pt1, const struct bn_tol *tol)
00643 {
00644 struct pt_list *pt_new;
00645 fastf_t t_sub;
00646 vect_t seg;
00647
00648 NMG_CK_EDGE_G_CNURB( cnrb );
00649 NMG_CK_FACE_G_SNURB( snrb );
00650 BN_CK_TOL( tol );
00651 #if 0
00652 if( rt_g.NMG_debug & DEBUG_MESH )
00653 bu_log( "nmg_split_trim( cnrb=x%x, snrb=x%x, t=%g, pt0=x%x, pt1=x%x )START\n",
00654 cnrb, snrb, t, pt0, pt1 );
00655 #endif
00656 pt_new = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "g_split_trim: pt_new" );
00657 pt_new->t = t;
00658
00659 if( pt_new->t < pt0->t || pt_new->t > pt1->t )
00660 {
00661 bu_log( "nmg_split_trim: split parameter (%g) is not between ends (%g and %g)\n",
00662 t, pt0->t, pt1->t );
00663 rt_bomb( "nmg_split_trim: split parameteris not between ends\n" );
00664 }
00665
00666 nmg_eval_trim_curve( cnrb, snrb, pt_new->t, pt_new->xyz );
00667
00668 BU_LIST_INSERT( &pt1->l, &pt_new->l );
00669
00670 VSUB2( seg, pt0->xyz, pt_new->xyz );
00671 if( MAGSQ( seg ) > tol->dist_sq )
00672 {
00673 t_sub = (pt0->t + pt_new->t)/2.0;
00674 #if 0
00675 if( rt_g.NMG_debug & DEBUG_MESH )
00676 bu_log( "nmg_split_trim: recursing at t=%g (%g,%g)\n",
00677 t_sub, pt0->t, pt_new->t );
00678 #endif
00679 nmg_split_trim( cnrb, snrb, t_sub, pt0, pt_new, tol );
00680 }
00681
00682 VSUB2( seg, pt_new->xyz, pt1->xyz );
00683 if( MAGSQ( seg ) > tol->dist_sq )
00684 {
00685 t_sub = (pt_new->t + pt1->t)/2.0;
00686 #if 0
00687 if( rt_g.NMG_debug & DEBUG_MESH )
00688 bu_log( "nmg_split_trim: recursing at t=%g (%g,%g)\n",
00689 t_sub, pt_new->t, pt1->t );
00690 #endif
00691 nmg_split_trim( cnrb, snrb, t_sub, pt_new, pt1, tol );
00692 }
00693 #if 0
00694 if( rt_g.NMG_debug & DEBUG_MESH )
00695 bu_log( "nmg_split_trim( cnrb=x%x, snrb=x%x, t=%g, pt0=x%x, pt1=x%x ) END\n",
00696 cnrb, snrb, t, pt0, pt1 );
00697 #endif
00698
00699 }
00700
00701 void
00702 nmg_eval_trim_to_tol(const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, const fastf_t t0, const fastf_t t1, struct bu_list *head, const struct bn_tol *tol)
00703 {
00704 fastf_t t;
00705 struct pt_list *pt0,*pt1;
00706
00707 NMG_CK_EDGE_G_CNURB( cnrb );
00708 NMG_CK_FACE_G_SNURB( snrb );
00709 BN_CK_TOL( tol );
00710
00711 if( rt_g.NMG_debug & DEBUG_MESH )
00712 bu_log( "nmg_eval_trim_to_tol( cnrb=x%x, snrb=x%x, t0=%g, t1=%g ) START\n",
00713 cnrb, snrb, t0, t1 );
00714
00715 pt0 = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "nmg_eval_trim_to_tol: pt0 " );
00716 pt0->t = t0;
00717 nmg_eval_trim_curve( cnrb, snrb, pt0->t, pt0->xyz );
00718 BU_LIST_INSERT( head, &pt0->l );
00719
00720 pt1 = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "nmg_eval_trim_to_tol: pt1 " );
00721 pt1->t = t1;
00722 nmg_eval_trim_curve( cnrb, snrb, pt1->t, pt1->xyz );
00723 BU_LIST_INSERT( head, &pt1->l );
00724
00725 t = (t0 + t1)/2.0;
00726 nmg_split_trim( cnrb, snrb, t, pt0, pt1, tol );
00727
00728 if( rt_g.NMG_debug & DEBUG_MESH )
00729 bu_log( "nmg_eval_trim_to_tol( cnrb=x%x, snrb=x%x, t0=%g, t1=%g ) END\n",
00730 cnrb, snrb, t0, t1 );
00731 }
00732
00733 void
00734 nmg_split_linear_trim(const struct face_g_snurb *snrb, const fastf_t *uvw1, const fastf_t *uvw, const fastf_t *uvw2, struct pt_list *pt0, struct pt_list *pt1, const struct bn_tol *tol)
00735 {
00736 struct pt_list *pt_new;
00737 fastf_t t_sub;
00738 fastf_t uvw_sub[3];
00739 vect_t seg;
00740
00741 if( snrb )
00742 NMG_CK_FACE_G_SNURB( snrb );
00743 BN_CK_TOL( tol );
00744 #if 0
00745 if( rt_g.NMG_debug & DEBUG_MESH )
00746 bu_log( "nmg_split_linear_trim( snrb=x%x, pt0=x%x, pt1=x%x )START\n",
00747 snrb, pt0, pt1 );
00748 #endif
00749 pt_new = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "g_split_trim: pt_new" );
00750 pt_new->t = 0.5*(pt0->t + pt1->t);
00751
00752 VBLEND2( uvw_sub, 1.0 - pt_new->t, uvw1, pt_new->t, uvw2 );
00753 nmg_eval_linear_trim_curve( snrb, uvw_sub, pt_new->xyz );
00754
00755 BU_LIST_INSERT( &pt1->l, &pt_new->l );
00756
00757 #if 0
00758 if( rt_g.NMG_debug & DEBUG_MESH )
00759 bu_log( "nmg_split_linear_trim: new segments (%g %g %g) <-> (%g %g %g) <-> (%g %g %g)\n",
00760 V3ARGS( pt0->xyz ), V3ARGS( pt_new->xyz ), V3ARGS( pt1->xyz ) );
00761 #endif
00762
00763 VSUB2( seg, pt0->xyz, pt_new->xyz );
00764 if( MAGSQ( seg ) > tol->dist_sq )
00765 {
00766 t_sub = (pt0->t + pt_new->t)/2.0;
00767 VBLEND2( uvw_sub, 1.0 - t_sub, uvw1, t_sub, uvw2 );
00768 #if 0
00769 if( rt_g.NMG_debug & DEBUG_MESH )
00770 bu_log( "nmg_split_linear_trim: recursing at t=%g (%g,%g)\n",
00771 t_sub, pt0->t, pt_new->t );
00772 #endif
00773 nmg_split_linear_trim( snrb, uvw1, uvw_sub, uvw2, pt0, pt_new, tol );
00774 }
00775
00776 VSUB2( seg, pt_new->xyz, pt1->xyz );
00777 if( MAGSQ( seg ) > tol->dist_sq )
00778 {
00779 t_sub = (pt_new->t + pt1->t)/2.0;
00780 VBLEND2( uvw_sub, 1.0 - t_sub, uvw1, t_sub, uvw2 );
00781 #if 0
00782 if( rt_g.NMG_debug & DEBUG_MESH )
00783 bu_log( "nmg_split_linear_trim: recursing at t=%g (%g,%g)\n",
00784 t_sub, pt_new->t, pt1->t );
00785 #endif
00786 nmg_split_linear_trim( snrb, uvw1, uvw_sub, uvw2, pt0, pt_new, tol );
00787 }
00788 #if 0
00789 if( rt_g.NMG_debug & DEBUG_MESH )
00790 bu_log( "nmg_split_linear_trim( snrb=x%x, pt0=x%x, pt1=x%x ) END\n",
00791 snrb, pt0, pt1 );
00792 #endif
00793
00794 }
00795
00796 void
00797 nmg_eval_linear_trim_to_tol(const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, const fastf_t *uvw1, const fastf_t *uvw2, struct bu_list *head, const struct bn_tol *tol)
00798 {
00799 fastf_t uvw[3];
00800 struct pt_list *pt0,*pt1;
00801
00802 NMG_CK_EDGE_G_CNURB( cnrb );
00803 NMG_CK_FACE_G_SNURB( snrb );
00804 BN_CK_TOL( tol );
00805
00806 NMG_CK_EDGE_G_CNURB( cnrb );
00807 NMG_CK_FACE_G_SNURB( snrb );
00808 BN_CK_TOL( tol );
00809
00810 if( rt_g.NMG_debug & DEBUG_MESH )
00811 bu_log( "nmg_eval_linear_trim_to_tol( cnrb=x%x, snrb=x%x, uvw1=( %g %g %g), uvw2=( %g %g %g ) ) START\n",
00812 cnrb, snrb, V3ARGS( uvw1 ), V3ARGS( uvw2 ) );
00813
00814 pt0 = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "nmg_eval_linear_trim_to_tol: pt0 " );
00815 pt0->t = 0.0;
00816 nmg_eval_linear_trim_curve( snrb, uvw1, pt0->xyz );
00817 BU_LIST_INSERT( head, &pt0->l );
00818
00819 pt1 = (struct pt_list *)bu_malloc( sizeof( struct pt_list ), "nmg_eval_linear_trim_to_tol: pt1 " );
00820 pt1->t = 1.0;
00821 nmg_eval_linear_trim_curve( snrb, uvw2, pt1->xyz );
00822 BU_LIST_INSERT( head, &pt1->l );
00823
00824
00825 VBLEND2( uvw, 0.5, uvw1, 0.5, uvw2 )
00826 nmg_split_linear_trim( snrb, uvw1, uvw, uvw2, pt0, pt1, tol );
00827
00828 if( rt_g.NMG_debug & DEBUG_MESH )
00829 bu_log( "nmg_eval_linear_trim_to_tol( cnrb=x%x, snrb=x%x ) END\n",
00830 cnrb, snrb );
00831 }
00832
00833
00834 #define CHECK_NUMBER 20
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 int
00848 nmg_cnurb_lseg_coincident(const struct edgeuse *eu1, const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, const fastf_t *pt1, const fastf_t *pt2, const struct bn_tol *tol)
00849 {
00850 fastf_t t0,t1,t;
00851 fastf_t delt;
00852 int coincident=0;
00853 int i;
00854
00855
00856 NMG_CK_EDGEUSE( eu1 );
00857 NMG_CK_EDGE_G_CNURB( cnrb );
00858
00859 if( rt_g.NMG_debug & DEBUG_MESH )
00860 bu_log( "nmg_cnurb_lseg_coincident( eu1=x%x, cnrb=x%x, snrb=x%x, pt1=(%g %g %g), pt2=(%g %g %g)\n",
00861 eu1, cnrb, snrb, V3ARGS( pt1 ), V3ARGS( pt2 ) );
00862
00863 if( eu1->g.cnurb_p != cnrb )
00864 {
00865 bu_log( "nmg_cnurb_lseg_coincident: cnrb x%x isn't from eu x%x\n",
00866 cnrb, eu1 );
00867 rt_bomb( "nmg_cnurb_lseg_coincident: cnrb and eu1 disagree\n" );
00868 }
00869
00870 if( snrb )
00871 NMG_CK_FACE_G_SNURB( snrb );
00872
00873 BN_CK_TOL( tol );
00874
00875 if( cnrb->order <= 0 )
00876 {
00877
00878 struct vertexuse *vu1;
00879 struct vertexuse *vu2;
00880 struct vertexuse_a_cnurb *vua1;
00881 struct vertexuse_a_cnurb *vua2;
00882
00883 if( !snrb )
00884 rt_bomb( "nmg_cnurb_lseg_coincident: No CNURB nor SNURB!!\n" );
00885
00886 vu1 = eu1->vu_p;
00887 NMG_CK_VERTEXUSE( vu1 );
00888 if( !vu1->a.magic_p )
00889 {
00890 bu_log( "nmg_cnurb_lseg_coincident: vu (x%x) has no attributes\n",
00891 vu1 );
00892 rt_bomb( "nmg_cnurb_lseg_coincident: vu has no attributes\n" );
00893 }
00894
00895 if( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
00896 {
00897 bu_log( "nmg_cnurb_lseg_coincident: vu (x%x) from CNURB EU (x%x) is not CNURB\n",
00898 vu1, eu1 );
00899 rt_bomb( "nmg_cnurb_lseg_coincident: vu from CNURB EU is not CNURB\n" );
00900 }
00901
00902 vua1 = vu1->a.cnurb_p;
00903 NMG_CK_VERTEXUSE_A_CNURB( vua1 );
00904
00905 vu2 = eu1->eumate_p->vu_p;
00906 NMG_CK_VERTEXUSE( vu2 );
00907 if( !vu2->a.magic_p )
00908 {
00909 bu_log( "nmg_cnurb_lseg_coincident: vu (x%x) has no attributes\n",
00910 vu2 );
00911 rt_bomb( "nmg_cnurb_lseg_coincident: vu has no attributes\n" );
00912 }
00913
00914 if( *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
00915 {
00916 bu_log( "nmg_cnurb_lseg_coincident: vu (x%x) from CNURB EU (x%x) is not CNURB\n",
00917 vu2, eu1 );
00918 rt_bomb( "nmg_cnurb_lseg_coincident: vu from CNURB EU is not CNURB\n" );
00919 }
00920
00921 vua2 = vu2->a.cnurb_p;
00922 NMG_CK_VERTEXUSE_A_CNURB( vua2 );
00923
00924 coincident = 1;
00925 for( i=0 ; i<CHECK_NUMBER ; i++ )
00926 {
00927 point_t uvw;
00928 point_t xyz;
00929 fastf_t blend;
00930 fastf_t dist;
00931 point_t pca;
00932
00933 blend = (double)(i+1)/(double)(CHECK_NUMBER+1);
00934 VBLEND2( uvw, blend, vua1->param, (1.0-blend), vua2->param );
00935
00936 nmg_eval_linear_trim_curve( snrb, uvw, xyz );
00937
00938 if( bn_dist_pt3_lseg3( &dist, pca, pt1, pt2, xyz, tol ) > 2 )
00939 {
00940 coincident = 0;
00941 break;
00942 }
00943 }
00944 if( rt_g.NMG_debug & DEBUG_MESH )
00945 bu_log( "nmg_cnurb_lseg_coincident returning %d\n", coincident );
00946 return( coincident );
00947 }
00948
00949 t0 = cnrb->k.knots[0];
00950 t1 = cnrb->k.knots[cnrb->k.k_size-1];
00951 delt = (t1 - t0)/(double)(CHECK_NUMBER+1);
00952
00953 coincident = 1;
00954 for( i=0 ; i<CHECK_NUMBER ; i++ )
00955 {
00956 point_t xyz;
00957 fastf_t dist;
00958 point_t pca;
00959
00960 t = t0 + (double)(i+1)*delt;
00961
00962 nmg_eval_trim_curve( cnrb, snrb, t, xyz );
00963
00964 if( bn_dist_pt3_lseg3( &dist, pca, pt1, pt2, xyz, tol ) > 2 )
00965 {
00966 coincident = 0;
00967 break;
00968 }
00969 }
00970 if( rt_g.NMG_debug & DEBUG_MESH )
00971 bu_log( "nmg_cnurb_lseg_coincident returning %d\n", coincident );
00972 return( coincident );
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 int
00986 nmg_cnurb_is_on_crv(const struct edgeuse *eu, const struct edge_g_cnurb *cnrb, const struct face_g_snurb *snrb, const struct bu_list *head, const struct bn_tol *tol)
00987 {
00988 int i;
00989 int coincident;
00990 fastf_t t, t0, t1;
00991 fastf_t delt;
00992
00993 NMG_CK_EDGEUSE( eu );
00994 NMG_CK_EDGE_G_CNURB( cnrb );
00995 if( snrb )
00996 NMG_CK_FACE_G_SNURB( snrb );
00997 BU_CK_LIST_HEAD( head );
00998 BN_CK_TOL( tol );
00999
01000 if( rt_g.NMG_debug & DEBUG_MESH )
01001 bu_log( "nmg_cnurb_is_on_crv( eu=x%x, cnrb=x%x, snrb=x%x, head=x%x )\n",
01002 eu, cnrb, snrb, head );
01003 if( cnrb->order <= 0 )
01004 {
01005 struct vertexuse *vu1,*vu2;
01006 struct vertexuse_a_cnurb *vu1a,*vu2a;
01007 fastf_t blend;
01008 point_t uvw;
01009 point_t xyz;
01010
01011
01012
01013 vu1 = eu->vu_p;
01014 NMG_CK_VERTEXUSE( vu1 );
01015 vu2 = eu->eumate_p->vu_p;
01016 NMG_CK_VERTEXUSE( vu2 );
01017
01018 if( !vu1->a.magic_p )
01019 {
01020 bu_log( "nmg_cnurb_is_on_crv(): vu (x%x) on CNURB EU (x%x) has no attributes\n",
01021 vu1, eu );
01022 rt_bomb( "nmg_cnurb_is_on_crv(): vu on CNURB EU has no attributes\n" );
01023 }
01024 if( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
01025 {
01026 bu_log( "nmg_cnurb_is_on_crv(): vu (x%x) on CNURB EU (x%x) is not CNURB\n",
01027 vu1, eu );
01028 rt_bomb( "nmg_cnurb_is_on_crv(): vu on CNURB EU is not CNURB\n" );
01029 }
01030 vu1a = vu1->a.cnurb_p;
01031 NMG_CK_VERTEXUSE_A_CNURB( vu1a );
01032
01033 if( !vu2->a.magic_p )
01034 {
01035 bu_log( "nmg_cnurb_is_on_crv(): vu (x%x) on CNURB EU (x%x) has no attributes\n",
01036 vu2, eu->eumate_p );
01037 rt_bomb( "nmg_cnurb_is_on_crv(): vu on CNURB EU has no attributes\n" );
01038 }
01039 if( *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
01040 {
01041 bu_log( "nmg_cnurb_is_on_crv(): vu (x%x) on CNURB EU (x%x) is not CNURB\n",
01042 vu2, eu->eumate_p );
01043 rt_bomb( "nmg_cnurb_is_on_crv(): vu on CNURB EU is not CNURB\n" );
01044 }
01045 vu2a = vu2->a.cnurb_p;
01046 NMG_CK_VERTEXUSE_A_CNURB( vu2a );
01047
01048 coincident = 1;
01049 for( i=0 ; i<CHECK_NUMBER ; i++ )
01050 {
01051 struct pt_list *pt;
01052 int found=0;
01053
01054 blend = (double)(i+1)/(double)(CHECK_NUMBER+1);
01055
01056 VBLEND2( uvw, blend, vu1a->param, (1.0-blend), vu2a->param );
01057
01058 nmg_eval_linear_trim_curve( snrb, uvw, xyz );
01059
01060 for( BU_LIST_FOR( pt, pt_list, head ) )
01061 {
01062 vect_t diff;
01063
01064 VSUB2( diff, xyz, pt->xyz );
01065 if( MAGSQ( diff ) <= tol->dist_sq )
01066 {
01067 found = 1;
01068 break;
01069 }
01070 }
01071 if( !found )
01072 {
01073 coincident = 0;
01074 break;
01075 }
01076 }
01077 if( rt_g.NMG_debug & DEBUG_MESH )
01078 bu_log( "nmg_cnurb_is_on_crv() returning %d\n", coincident );
01079 return( coincident );
01080 }
01081
01082 coincident = 1;
01083 t0 = cnrb->k.knots[0];
01084 t1 = cnrb->k.knots[cnrb->k.k_size-1];
01085 delt = (t1 - t0)/(double)(CHECK_NUMBER+1);
01086 for( i=0 ; i<CHECK_NUMBER ; i++ )
01087 {
01088 point_t xyz;
01089 struct pt_list *pt;
01090 int found;
01091
01092 t = t0 + (double)(i+1)*delt;
01093
01094 nmg_eval_trim_curve( cnrb, snrb, t, xyz );
01095
01096 found = 0;
01097 for( BU_LIST_FOR( pt, pt_list, head ) )
01098 {
01099 vect_t diff;
01100
01101 VSUB2( diff, xyz, pt->xyz );
01102 if( MAGSQ( diff ) <= tol->dist_sq )
01103 {
01104 found = 1;
01105 break;
01106 }
01107 }
01108 if( !found )
01109 {
01110 coincident = 0;
01111 break;
01112 }
01113 }
01114
01115 if( rt_g.NMG_debug & DEBUG_MESH )
01116 bu_log( "nmg_cnurb_is_on_crv returning %d\n", coincident );
01117 return( coincident );
01118 }
01119
01120
01121
01122
01123 #if 0
01124 int
01125 nmg_model_edge_fuse( m, tol )
01126 struct model *m;
01127 const struct bn_tol *tol;
01128 {
01129 struct bu_ptbl eutab;
01130 int total = 0;
01131 int non_lseg=0;
01132 register int i,j;
01133
01134 NMG_CK_MODEL(m);
01135 BN_CK_TOL(tol);
01136
01137
01138 again:
01139 total = 0;
01140 nmg_edgeuse_tabulate( &eutab, &m->magic );
01141
01142 for( i = BU_PTBL_END(&eutab)-1; i >= 0; i-- ) {
01143 struct edgeuse *eu1;
01144 struct edge *e1;
01145 register struct vertex *v1a, *v1b;
01146 int lseg1=0;
01147 int lseg2;
01148
01149 eu1 = (struct edgeuse *)BU_PTBL_GET(&eutab, i);
01150 NMG_CK_EDGEUSE(eu1);
01151 e1 = eu1->e_p;
01152 NMG_CK_EDGE(e1);
01153 NMG_CK_EDGE_G_EITHER(eu1->g.magic_p);
01154
01155 v1a = eu1->vu_p->v_p;
01156 v1b = eu1->eumate_p->vu_p->v_p;
01157 NMG_CK_VERTEX(v1a);
01158 NMG_CK_VERTEX(v1b);
01159
01160 if( v1a == v1b ) {
01161 if( *eu1->g.magic_p == NMG_EDGE_G_LSEG_MAGIC ) {
01162
01163
01164 if( nmg_keu( eu1 ) ) {
01165 bu_log("nmg_model_edge_fuse() WARNING: deletion of 0-length edgeuse=x%x caused parent to go empty.\n", eu1);
01166 }
01167 bu_log("nmg_model_edge_fuse() 0-length edgeuse=x%x deleted\n", eu1);
01168
01169 bu_ptbl_free( &eutab);
01170 goto again;
01171 }
01172
01173 }
01174
01175 if( !eu1->g.magic_p )
01176 {
01177 bu_log( "nmg_model_edge_fuse() WARNING: eu (x%x) has no geometry\n" , eu1 );
01178 continue;
01179 }
01180
01181
01182 if( *eu1->g.magic_p == NMG_EDGE_G_LSEG_MAGIC )
01183 lseg1 = 1;
01184 else if( *eu1->g.magic_p == NMG_EDGE_G_CNURB_MAGIC )
01185 {
01186 non_lseg++;
01187 continue;
01188 }
01189 else
01190
01191 {
01192 bu_log( "nmg_model_edge_fuse() WARNING: eu (x%x) has unknown geometry\n" , eu1 );
01193 continue;
01194 }
01195
01196
01197 for( j = i-1; j >= 0; j-- ) {
01198 register struct edgeuse *eu2;
01199 register struct vertex *v2a, *v2b;
01200 int eus_are_coincident=0;
01201
01202
01203 eu2 = (struct edgeuse *)BU_PTBL_GET(&eutab,j);
01204
01205 if( rt_g.NMG_debug & DEBUG_MESH )
01206 bu_log( "nmg_mode_edge_fuse: checking eus x%x and x%x\n", eu1, eu2 );
01207
01208
01209 v2a = eu2->vu_p->v_p;
01210 if( v2a != v1a && v2a != v1b ) continue;
01211
01212 if( e1 == eu2->e_p ) continue;
01213
01214 v2b = eu2->eumate_p->vu_p->v_p;
01215 if( (v2a != v1a || v2b != v1b) &&
01216 (v2b != v1a || v2a != v1b) )
01217 continue;
01218
01219 if( !eu2->g.magic_p )
01220 {
01221 bu_log( "nmg_model_edge_fuse() WARNING: eu (x%x) has no geometry\n" , eu2 );
01222 continue;
01223 }
01224
01225
01226 lseg2 = 0;
01227 if( *eu2->g.magic_p == NMG_EDGE_G_LSEG_MAGIC )
01228 lseg2 = 1;
01229 else if( *eu2->g.magic_p == NMG_EDGE_G_CNURB_MAGIC )
01230 continue;
01231 else
01232 {
01233 bu_log( "nmg_model_edge_fuse() WARNING: eu (x%x) has unknown geometry\n" , eu2 );
01234 continue;
01235 }
01236
01237
01238 if( lseg1 && lseg2 )
01239 {
01240
01241 nmg_radial_join_eu(eu1, eu2, tol);
01242 total++;
01243 }
01244 }
01245
01246 }
01247 if( rt_g.NMG_debug & DEBUG_BASIC && total > 0 )
01248 bu_log("nmg_model_edge_fuse(): %d edges fused\n", total);
01249 bu_ptbl_free( &eutab);
01250
01251 if( non_lseg )
01252 bu_log( "Warning: CNURB edges not fused!!!\n" );
01253
01254 return total;
01255 }
01256 #else
01257 int
01258 nmg_model_edge_fuse(struct model *m, const struct bn_tol *tol)
01259 {
01260 struct bu_ptbl edges;
01261 int i, j;
01262 int count=0;
01263
01264 NMG_CK_MODEL( m );
01265 BN_CK_TOL( tol );
01266
01267 nmg_edge_tabulate( &edges, &m->magic );
01268
01269 for( i=0 ; i<BU_PTBL_END( &edges )-1 ; i++ )
01270 {
01271 struct edge *e1;
01272 struct edgeuse *eu1;
01273
01274 e1 = (struct edge *)BU_PTBL_GET( &edges, i );
01275 if(!e1 || !e1->index || e1->magic != NMG_EDGE_MAGIC )
01276 continue;
01277 eu1 = e1->eu_p;
01278 if( !eu1 )
01279 continue;
01280 if( *eu1->g.magic_p != NMG_EDGE_G_LSEG_MAGIC )
01281 continue;
01282
01283 for( j=i+1 ; j<BU_PTBL_END( &edges ) ; j++ )
01284 {
01285 struct edge *e2;
01286 struct edgeuse *eu2;
01287
01288 e2 = (struct edge *)BU_PTBL_GET( &edges, j );
01289 if( !e2 || !e2->index || e2->magic != NMG_EDGE_MAGIC )
01290 continue;
01291 eu2 = e2->eu_p;
01292 if( !eu2 )
01293 continue;
01294 if( *eu2->g.magic_p != NMG_EDGE_G_LSEG_MAGIC )
01295 continue;
01296
01297 if( NMG_ARE_EUS_ADJACENT( eu1, eu2 ) )
01298 {
01299 count++;
01300 nmg_radial_join_eu(eu1, eu2, tol);
01301 if(!e2->magic)
01302 bu_ptbl_zero( &edges, (long *)e2 );
01303 }
01304 }
01305 }
01306
01307 bu_ptbl_free( &edges );
01308
01309 return( count );
01310 }
01311 #endif
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 int
01322 nmg_model_edge_g_fuse(struct model *m, const struct bn_tol *tol)
01323 {
01324 struct bu_ptbl etab;
01325 int total = 0;
01326 register int i,j;
01327
01328 NMG_CK_MODEL(m);
01329 BN_CK_TOL(tol);
01330
01331
01332 nmg_edge_g_tabulate( &etab, &m->magic );
01333
01334 for( i = BU_PTBL_END(&etab)-1; i >= 0; i-- ) {
01335 struct edge_g_lseg *eg1;
01336 struct edgeuse *eu1;
01337
01338 eg1 = (struct edge_g_lseg *)BU_PTBL_GET(&etab, i);
01339 NMG_CK_EDGE_G_EITHER(eg1);
01340
01341
01342 if( eg1->l.magic == NMG_EDGE_G_CNURB_MAGIC ) {
01343 continue;
01344 }
01345
01346 NMG_CK_EDGE_G_LSEG(eg1);
01347 eu1 = BU_LIST_MAIN_PTR( edgeuse, BU_LIST_FIRST( bu_list, &eg1->eu_hd2 ), l2 );
01348 NMG_CK_EDGEUSE(eu1);
01349
01350 for( j = i-1; j >= 0; j-- ) {
01351 struct edge_g_lseg *eg2;
01352 struct edgeuse *eu2;
01353
01354 eg2 = (struct edge_g_lseg *)BU_PTBL_GET(&etab,j);
01355 NMG_CK_EDGE_G_EITHER(eg2);
01356 if( eg2->l.magic == NMG_EDGE_G_CNURB_MAGIC ) continue;
01357 NMG_CK_EDGE_G_LSEG(eg2);
01358 eu2 = BU_LIST_MAIN_PTR( edgeuse, BU_LIST_FIRST( bu_list, &eg2->eu_hd2 ), l2 );
01359 NMG_CK_EDGEUSE(eu2);
01360
01361 if( eg1 == eg2 ) rt_bomb("nmg_model_edge_g_fuse() edge_g listed twice in ptbl?\n");
01362
01363 if( !nmg_2edgeuse_g_coincident( eu1, eu2, tol ) ) continue;
01364
01365
01366
01367
01368
01369
01370 total++;
01371 nmg_jeg( eg2, eg1 );
01372 BU_PTBL_GET(&etab,i) = (long *)NULL;
01373 break;
01374 }
01375 }
01376 bu_ptbl_free( &etab);
01377 if( rt_g.NMG_debug & DEBUG_BASIC && total > 0 )
01378 bu_log("nmg_model_edge_g_fuse(): %d edge_g_lseg's fused\n", total);
01379 return total;
01380 }
01381
01382 #define TOL_MULTIPLES 1.0
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 int
01398 nmg_ck_fu_verts(struct faceuse *fu1, struct face *f2, const struct bn_tol *tol)
01399 {
01400 const struct face_g_plane *fg2;
01401 FAST fastf_t dist;
01402 fastf_t worst = 0;
01403 int count = 0;
01404 struct loopuse *lu;
01405
01406 NMG_CK_FACEUSE( fu1 );
01407 NMG_CK_FACE( f2 );
01408 BN_CK_TOL(tol);
01409
01410 fg2 = f2->g.plane_p;
01411 NMG_CK_FACE_G_PLANE(fg2);
01412
01413 for ( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) ) {
01414 struct edgeuse *eu;
01415
01416 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
01417 register struct vertexuse *vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
01418 register struct vertex *v = vu->v_p;
01419 register struct vertex_g *vg;
01420
01421 NMG_CK_VERTEX(v);
01422 vg = v->vg_p;
01423 if( !vg ) rt_bomb("nmg_ck_fu_verts(): vertex with no geometry?\n");
01424 NMG_CK_VERTEX_G(vg);
01425
01426
01427 dist = DIST_PT_PLANE(vg->coord, fg2->N);
01428 if( dist > tol->dist || dist < (-tol->dist) ) {
01429 if (rt_g.NMG_debug & DEBUG_MESH) {
01430 bu_log("nmg_ck_fu_verts(x%x, x%x) v x%x off face by %e\n",
01431 fu1, f2, v, dist );
01432 VPRINT(" pt", vg->coord);
01433 PLPRINT(" fg2", fg2->N);
01434 }
01435 count++;
01436 if( dist < 0.0 ) {
01437 dist = (-dist);
01438 }
01439 if( dist > worst ) {
01440 worst = dist;
01441 }
01442 }
01443 }
01444
01445 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
01446 struct vertex *v = eu->vu_p->v_p;
01447 struct vertex_g *vg;
01448
01449 NMG_CK_VERTEX(v);
01450 vg = v->vg_p;
01451 if( !vg ) rt_bomb("nmg_ck_fu_verts(): vertex with no geometry?\n");
01452 NMG_CK_VERTEX_G(vg);
01453
01454
01455 dist = DIST_PT_PLANE(vg->coord, fg2->N);
01456 if( dist > tol->dist || dist < (-tol->dist) ) {
01457 if (rt_g.NMG_debug & DEBUG_MESH) {
01458 bu_log("nmg_ck_fu_verts(x%x, x%x) v x%x off face by %e\n",
01459 fu1, f2, v, dist );
01460 VPRINT(" pt", vg->coord);
01461 PLPRINT(" fg2", fg2->N);
01462 }
01463 count++;
01464 if( dist < 0.0 ) {
01465 dist = (-dist);
01466 }
01467 if( dist > worst ) {
01468 worst = dist;
01469 }
01470 }
01471 }
01472 }
01473
01474 if (worst > TOL_MULTIPLES*tol->dist) {
01475 return count;
01476 } else {
01477 return( 0 );
01478 }
01479 }
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495 int
01496 nmg_ck_fg_verts(struct faceuse *fu1, struct face *f2, const struct bn_tol *tol)
01497 {
01498 struct face_g_plane *fg1;
01499 struct faceuse *fu;
01500 struct face *f;
01501 int count=0;
01502
01503 NMG_CK_FACEUSE( fu1 );
01504 NMG_CK_FACE( f2 );
01505 BN_CK_TOL( tol );
01506
01507 NMG_CK_FACE( fu1->f_p );
01508 fg1 = fu1->f_p->g.plane_p;
01509 NMG_CK_FACE_G_PLANE( fg1 );
01510
01511 for( BU_LIST_FOR( f , face , &fg1->f_hd ) )
01512 {
01513 NMG_CK_FACE( f );
01514
01515 fu = f->fu_p;
01516 NMG_CK_FACEUSE( fu );
01517
01518 count += nmg_ck_fu_verts( fu , f2 , tol );
01519 }
01520
01521 return( count );
01522 }
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 int
01543 nmg_two_face_fuse(struct face *f1, struct face *f2, const struct bn_tol *tol)
01544 {
01545 register struct face_g_plane *fg1;
01546 register struct face_g_plane *fg2;
01547 int flip2 = 0;
01548
01549 NMG_CK_FACE(f1);
01550 NMG_CK_FACE(f2);
01551 BN_CK_TOL(tol);
01552
01553 fg1 = f1->g.plane_p;
01554 fg2 = f2->g.plane_p;
01555
01556 if( !fg1 || !fg2 ) {
01557 if (rt_g.NMG_debug & DEBUG_MESH) {
01558 bu_log("nmg_two_face_fuse(x%x, x%x) null fg fg1=x%x, fg2=x%x\n",
01559 f1, f2, fg1, fg2);
01560 }
01561 return 0;
01562 }
01563
01564 NMG_CK_FACE_G_PLANE(fg1);
01565 NMG_CK_FACE_G_PLANE(fg2);
01566
01567 if( fg1 == fg2 ) {
01568 if (rt_g.NMG_debug & DEBUG_MESH) {
01569 bu_log("nmg_two_face_fuse(x%x, x%x) fg already shared\n",
01570 f1, f2);
01571 }
01572 return 0;
01573 }
01574 #ifdef TOPOLOGY_CHECK
01575
01576
01577
01578
01579
01580
01581
01582 if( fabs(VDOT(fg1->N, fg2->N)) >= 0.99 &&
01583 fabs(fg1->N[3]) - fabs(fg2->N[3]) < 100 * tol->dist &&
01584 nmg_is_common_bigloop( f1, f2 ) ) {
01585 if( VDOT( fg1->N, fg2->N ) < 0 ) flip2 = 1;
01586 if (rt_g.NMG_debug & DEBUG_MESH) {
01587 bu_log("nmg_two_face_fuse(x%x, x%x) faces have a common loop, they MUST be fused. flip2=%d\n",
01588 f1, f2, flip2);
01589 }
01590 goto must_fuse;
01591 }
01592
01593
01594 code = bn_coplanar( fg1->N, fg2->N, tol );
01595 if( code <= 0 ) {
01596 if (rt_g.NMG_debug & DEBUG_MESH) {
01597 bu_log("nmg_two_face_fuse(x%x, x%x) faces non-coplanar\n",
01598 f1, f2);
01599 }
01600 return 0;
01601 }
01602 if( code == 1 )
01603 flip2 = 0;
01604 else
01605 flip2 = 1;
01606
01607 if (rt_g.NMG_debug & DEBUG_MESH) {
01608 bu_log("nmg_two_face_fuse(x%x, x%x) coplanar faces, bn_coplanar code=%d, flip2=%d\n",
01609 f1, f2, code, flip2);
01610 }
01611 #else
01612 if( VDOT( fg1->N, fg2->N ) > 0.0 )
01613 flip2 = 0;
01614 else
01615 flip2 = 1;
01616
01617 if( nmg_ck_fg_verts( f1->fu_p, f2, tol ) != 0 ) {
01618 if (rt_g.NMG_debug & DEBUG_MESH) {
01619 bu_log("nmg_two_face_fuse: f1 verts not within tol of f2's surface, can't fuse\n");
01620 }
01621 return 0;
01622 }
01623 #endif
01624
01625
01626
01627
01628
01629
01630
01631 if( nmg_ck_fg_verts( f2->fu_p, f1, tol ) != 0 ) {
01632 if (rt_g.NMG_debug & DEBUG_MESH) {
01633 bu_log("nmg_two_face_fuse: f2 verts not within tol of f1's surface, can't fuse\n");
01634 }
01635 return 0;
01636 }
01637
01638 #ifdef TOPPLOGY_CHECK
01639 must_fuse:
01640 #endif
01641
01642 if( flip2 == 0 ) {
01643 if (rt_g.NMG_debug & DEBUG_MESH) {
01644 bu_log("joining face geometry (same dir) f1=x%x, f2=x%x\n", f1, f2);
01645 PLPRINT(" fg1", fg1->N);
01646 PLPRINT(" fg2", fg2->N);
01647 }
01648 nmg_jfg( f1, f2 );
01649 } else {
01650 register struct face *fn;
01651 if (rt_g.NMG_debug & DEBUG_MESH) {
01652 bu_log("joining face geometry (opposite dirs)\n");
01653
01654 bu_log(" f1=x%x, flip=%d", f1, f1->flip);
01655 PLPRINT(" fg1", fg1->N);
01656
01657 bu_log(" f2=x%x, flip=%d", f2, f2->flip);
01658 PLPRINT(" fg2", fg2->N);
01659 }
01660
01661 for( BU_LIST_FOR( fn, face, &fg2->f_hd ) ) {
01662 NMG_CK_FACE(fn);
01663 fn->flip = !fn->flip;
01664 if (rt_g.NMG_debug & DEBUG_MESH) {
01665 bu_log("f=x%x, new flip=%d\n", fn, fn->flip);
01666 }
01667 }
01668 nmg_jfg( f1, f2 );
01669 }
01670 return 1;
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 int
01687 nmg_model_face_fuse(struct model *m, const struct bn_tol *tol)
01688 {
01689 struct bu_ptbl ftab;
01690 int total = 0;
01691 register int i,j;
01692
01693 NMG_CK_MODEL(m);
01694 BN_CK_TOL(tol);
01695
01696
01697 nmg_face_tabulate( &ftab, &m->magic );
01698
01699 for( i = BU_PTBL_END(&ftab)-1; i >= 0; i-- ) {
01700 register struct face *f1;
01701 register struct face_g_plane *fg1;
01702 f1 = (struct face *)BU_PTBL_GET(&ftab, i);
01703 NMG_CK_FACE(f1);
01704 NMG_CK_FACE_G_EITHER(f1->g.magic_p);
01705
01706 if( *f1->g.magic_p == NMG_FACE_G_SNURB_MAGIC ) {
01707
01708 continue;
01709 }
01710
01711 fg1 = f1->g.plane_p;
01712 NMG_CK_FACE_G_PLANE(fg1);
01713
01714
01715 if( nmg_ck_fu_verts( f1->fu_p, f1, tol ) != 0 ) {
01716 if( rt_g.NMG_debug ) {
01717 PLPRINT(" f1", f1->g.plane_p->N);
01718 nmg_pr_fu_briefly(f1->fu_p, 0);
01719 }
01720 rt_bomb("nmg_model_face_fuse(): verts not within tol of containing face\n");
01721 }
01722
01723 for( j = i-1; j >= 0; j-- ) {
01724 register struct face *f2;
01725 register struct face_g_plane *fg2;
01726
01727 f2 = (struct face *)BU_PTBL_GET(&ftab, j);
01728 NMG_CK_FACE(f2);
01729 fg2 = f2->g.plane_p;
01730 if( !fg2 ) continue;
01731 NMG_CK_FACE_G_PLANE(fg2);
01732
01733 if( fg1 == fg2 ) continue;
01734
01735 if( nmg_two_face_fuse( f1, f2, tol ) > 0 )
01736 total++;
01737 }
01738 }
01739 bu_ptbl_free( &ftab);
01740 if( rt_g.NMG_debug & DEBUG_BASIC && total > 0 )
01741 bu_log("nmg_model_face_fuse: %d faces fused\n", total);
01742 return total;
01743 }
01744
01745 int
01746 nmg_break_all_es_on_v(long int *magic_p, struct vertex *v, const struct bn_tol *tol)
01747 {
01748 struct bu_ptbl eus;
01749 int i;
01750 int count=0;
01751 const char *magic_type;
01752
01753 if( rt_g.NMG_debug & DEBUG_BOOL )
01754 bu_log( "nmg_break_all_es_on_v( magic=x%x, v=x%x )\n", magic_p, v );
01755
01756 NMG_CK_VERTEX( v );
01757 BN_CK_TOL( tol );
01758
01759 magic_type = bu_identify_magic( *magic_p );
01760 if ( !strcmp( magic_type, "NULL" ) ||
01761 !strcmp( magic_type, "Unknown_Magic" ) )
01762 {
01763 bu_log( "Bad magic pointer passed to nmg_break_all_es_on_v (%s)\n", magic_type );
01764 rt_bomb( "Bad magic pointer passed to nmg_break_all_es_on_v()\n" );
01765 }
01766
01767 nmg_edgeuse_tabulate( &eus, magic_p );
01768
01769 for( i=0 ; i<BU_PTBL_END( &eus ) ; i++ )
01770 {
01771 struct edgeuse *eu;
01772 struct edgeuse *eu_next, *eu_prev;
01773 struct vertex *va;
01774 struct vertex *vb;
01775 fastf_t dist;
01776 int code;
01777
01778 eu = (struct edgeuse *)BU_PTBL_GET( &eus, i );
01779 NMG_CK_EDGEUSE( eu );
01780
01781 if( eu->g.magic_p && *eu->g.magic_p == NMG_EDGE_G_CNURB_MAGIC )
01782 continue;
01783 va = eu->vu_p->v_p;
01784 vb = eu->eumate_p->vu_p->v_p;
01785 NMG_CK_VERTEX(va);
01786 NMG_CK_VERTEX(vb);
01787
01788 if( va == v ) continue;
01789 if( vb == v ) continue;
01790
01791 eu_next = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
01792 eu_prev = BU_LIST_PPREV_CIRC( edgeuse, &eu->l );
01793
01794 if( eu_prev->vu_p->v_p == v )
01795 continue;
01796
01797 if( eu_next->eumate_p->vu_p->v_p == v )
01798 continue;
01799
01800 code = bn_isect_pt_lseg( &dist, va->vg_p->coord, vb->vg_p->coord,
01801 v->vg_p->coord, tol );
01802 if( code < 1 ) continue;
01803 if( code == 1 || code == 2 ) {
01804 bu_log("nmg_break_all_es_on_v() code=%d, why wasn't this vertex fused?\n", code);
01805 bu_log( "\teu=x%x, v=x%x\n", eu, v );
01806 continue;
01807 }
01808
01809
01810 if( rt_g.NMG_debug & DEBUG_BOOL )
01811 bu_log( "\tnmg_break_all_es_on_v: breaking eu x%x on v x%x\n", eu, v );
01812
01813 (void)nmg_ebreak( v, eu );
01814 count++;
01815 }
01816 bu_ptbl_free( &eus);
01817 return( count );
01818 }
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 int
01838 nmg_model_break_e_on_v(struct model *m, const struct bn_tol *tol)
01839 {
01840 int count = 0;
01841 struct bu_ptbl verts;
01842 struct bu_ptbl edgeuses;
01843 struct bu_ptbl new_edgeuses;
01844 register struct edgeuse **eup;
01845
01846 NMG_CK_MODEL(m);
01847 BN_CK_TOL(tol);
01848
01849 nmg_e_and_v_tabulate( &edgeuses, &verts, &m->magic );
01850
01851
01852 while( BU_PTBL_LEN( &edgeuses ) > 0 ) {
01853 (void)bu_ptbl_init( &new_edgeuses, 64, " &new_edgeuses");
01854
01855 for( eup = (struct edgeuse **)BU_PTBL_LASTADDR(&edgeuses);
01856 eup >= (struct edgeuse **)BU_PTBL_BASEADDR(&edgeuses);
01857 eup--
01858 ) {
01859 register struct edgeuse *eu;
01860 register struct vertex *va;
01861 register struct vertex *vb;
01862 register struct vertex **vp;
01863
01864 eu = *eup;
01865 NMG_CK_EDGEUSE(eu);
01866 if( eu->g.magic_p && *eu->g.magic_p == NMG_EDGE_G_CNURB_MAGIC )
01867 continue;
01868 va = eu->vu_p->v_p;
01869 vb = eu->eumate_p->vu_p->v_p;
01870 NMG_CK_VERTEX(va);
01871 NMG_CK_VERTEX(vb);
01872 for( vp = (struct vertex **)BU_PTBL_LASTADDR(&verts);
01873 vp >= (struct vertex **)BU_PTBL_BASEADDR(&verts);
01874 vp--
01875 ) {
01876 register struct vertex *v;
01877 fastf_t dist;
01878 int code;
01879 struct edgeuse *new_eu;
01880
01881 v = *vp;
01882
01883
01884 if( va == v ) continue;
01885 if( vb == v ) continue;
01886
01887
01888 code = bn_isect_pt_lseg( &dist,
01889 va->vg_p->coord,
01890 vb->vg_p->coord,
01891 v->vg_p->coord, tol );
01892 if( code < 1 ) continue;
01893 if( code == 1 || code == 2 ) {
01894 bu_log("nmg_model_break_e_on_v() code=%d, why wasn't this vertex fused?\n", code);
01895 continue;
01896 }
01897
01898 if (rt_g.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC) )
01899 bu_log( "nmg_model_break_e_on_v(): breaking eu x%x (e=x%x) at vertex x%x\n", eu,eu->e_p, v );
01900
01901
01902 new_eu = nmg_ebreak( v, eu );
01903
01904 bu_ptbl_ins( &new_edgeuses, &new_eu->l.magic );
01905
01906
01907 vb = eu->eumate_p->vu_p->v_p;
01908 count++;
01909 }
01910 }
01911 bu_ptbl_free( &edgeuses);
01912 edgeuses = new_edgeuses;
01913 }
01914 bu_ptbl_free( &edgeuses);
01915 bu_ptbl_free( &verts);
01916 if (rt_g.NMG_debug & (DEBUG_BOOL|DEBUG_BASIC) )
01917 bu_log("nmg_model_break_e_on_v() broke %d edges\n", count);
01918 return count;
01919 }
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941 int
01942 nmg_model_fuse(struct model *m, const struct bn_tol *tol)
01943 {
01944 int total = 0;
01945
01946 NMG_CK_MODEL(m);
01947 BN_CK_TOL(tol);
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 if( rt_g.NMG_debug & DEBUG_BASIC )
01959 bu_log( "nmg_model_fuse: vertices\n" );
01960 total += nmg_model_vertex_fuse( m, tol );
01961
01962
01963 if( rt_g.NMG_debug & DEBUG_BASIC )
01964 bu_log( "nmg_model_fuse: break edges\n" );
01965 total += nmg_model_break_e_on_v( m, tol );
01966
01967 if( total )
01968 {
01969 struct nmgregion *r;
01970 struct shell *s;
01971
01972
01973
01974
01975
01976 for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )
01977 {
01978 for( BU_LIST_FOR( s, shell, &r->s_hd ) )
01979 nmg_make_faces_within_tol( s, tol );
01980 }
01981 }
01982
01983
01984 if( rt_g.NMG_debug & DEBUG_BASIC )
01985 bu_log( "nmg_model_fuse: faces\n" );
01986 total += nmg_model_face_fuse( m, tol );
01987
01988
01989 if( rt_g.NMG_debug & DEBUG_BASIC )
01990 bu_log( "nmg_model_fuse: edges\n" );
01991 total += nmg_model_edge_fuse( m, tol );
01992
01993
01994 if( rt_g.NMG_debug & DEBUG_BASIC )
01995 bu_log( "nmg_model_fuse: edge geometries\n" );
01996 total += nmg_model_edge_g_fuse( m, tol );
01997
01998 if( rt_g.NMG_debug & DEBUG_BASIC && total > 0 )
01999 bu_log("nmg_model_fuse(): %d entities fused\n", total);
02000 return total;
02001 }
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014 void
02015 nmg_radial_sorted_list_insert(struct bu_list *hd, struct nmg_radial *rad)
02016 {
02017 struct nmg_radial *cur;
02018 register fastf_t rad_ang;
02019
02020 BU_CK_LIST_HEAD(hd);
02021 NMG_CK_RADIAL(rad);
02022
02023 if(BU_LIST_IS_EMPTY(hd)) {
02024 BU_LIST_APPEND( hd, &rad->l );
02025 return;
02026 }
02027
02028
02029 if( rad->fu == (struct faceuse *)NULL ) {
02030
02031 BU_LIST_APPEND( hd, &rad->l );
02032 return;
02033 }
02034
02035 rad_ang = rad->ang;
02036
02037
02038
02039
02040 cur = BU_LIST_PREV(nmg_radial, hd);
02041 if( cur->fu && rad_ang >= cur->ang ) {
02042 BU_LIST_INSERT( hd, &rad->l );
02043 return;
02044 }
02045
02046
02047 for( BU_LIST_FOR_BACKWARDS( cur, nmg_radial, hd ) ) {
02048 if( cur->fu == (struct faceuse *)NULL ) continue;
02049 if( rad_ang >= cur->ang ) {
02050 BU_LIST_APPEND( &cur->l, &rad->l );
02051 return;
02052 }
02053 }
02054
02055
02056 BU_LIST_APPEND( hd, &rad->l );
02057 }
02058
02059
02060
02061
02062
02063 void
02064 nmg_radial_verify_pointers(const struct bu_list *hd, const struct bn_tol *tol)
02065 {
02066 register struct nmg_radial *rad;
02067 register fastf_t amin = -64;
02068 register struct nmg_radial *prev;
02069 register struct nmg_radial *next;
02070
02071 BU_CK_LIST_HEAD(hd);
02072 BN_CK_TOL(tol);
02073
02074
02075 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02076
02077 prev = BU_LIST_PPREV_CIRC(nmg_radial, rad);
02078 next = BU_LIST_PNEXT_CIRC(nmg_radial, rad);
02079 if( rad->eu != prev->eu->radial_p->eumate_p )
02080 rt_bomb("nmg_radial_verify_pointers() eu not radial+mate forw from prev\n");
02081 if( rad->eu->eumate_p != prev->eu->radial_p )
02082 rt_bomb("nmg_radial_verify_pointers() eumate not radial from prev\n");
02083 if( rad->eu != next->eu->eumate_p->radial_p )
02084 rt_bomb("nmg_radial_verify_pointers() eu not mate+radial back from next\n");
02085 if( rad->eu->eumate_p != next->eu->eumate_p->radial_p->eumate_p )
02086 rt_bomb("nmg_radial_verify_pointers() eumate not mate+radial+mate back from next\n");
02087
02088 if( rad->fu == (struct faceuse *)NULL ) continue;
02089 if( rad->ang < amin ) {
02090 nmg_pr_radial_list( hd, tol );
02091 bu_log(" previous angle=%g > current=%g\n",
02092 amin*bn_radtodeg, rad->ang*bn_radtodeg);
02093 rt_bomb("nmg_radial_verify_pointers() not monotone increasing\n");
02094 }
02095 amin = rad->ang;
02096 }
02097 }
02098
02099
02100
02101
02102
02103
02104 void
02105 nmg_radial_verify_monotone(const struct bu_list *hd, const struct bn_tol *tol)
02106 {
02107 register struct nmg_radial *rad;
02108 register fastf_t amin = -64;
02109
02110 BU_CK_LIST_HEAD(hd);
02111 BN_CK_TOL(tol);
02112
02113
02114 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02115 if( rad->fu == (struct faceuse *)NULL ) continue;
02116 if( rad->ang < amin ) {
02117 nmg_pr_radial_list( hd, tol );
02118 bu_log(" previous angle=%g > current=%g\n",
02119 amin*bn_radtodeg, rad->ang*bn_radtodeg);
02120 rt_bomb("nmg_radial_verify_monotone() not monotone increasing\n");
02121 }
02122 amin = rad->ang;
02123 }
02124 }
02125
02126
02127
02128
02129
02130
02131
02132 void
02133 nmg_insure_radial_list_is_increasing(struct bu_list *hd, fastf_t amin, fastf_t amax)
02134 {
02135 struct nmg_radial *rad;
02136 fastf_t cur_value=(-MAX_FASTF);
02137 int increasing=1;
02138
02139 BU_CK_LIST_HEAD( hd );
02140
02141
02142
02143 if( bu_list_len( hd ) < 3 )
02144 return;
02145
02146 for( BU_LIST_FOR( rad, nmg_radial, hd ) )
02147 {
02148
02149 if( rad->fu == (struct faceuse *)NULL )
02150 continue;
02151
02152
02153 if( rad->ang >= cur_value )
02154 {
02155 cur_value = rad->ang;
02156 continue;
02157 }
02158
02159
02160 if( rad->ang == amin && cur_value == amax )
02161 {
02162
02163 cur_value = rad->ang;
02164 continue;
02165 }
02166
02167
02168 increasing = 0;
02169 break;
02170 }
02171
02172 if( increasing )
02173 return;
02174
02175
02176 bu_list_reverse( hd );
02177
02178
02179 for( BU_LIST_FOR( rad, nmg_radial, hd ) )
02180 {
02181 rad->eu = rad->eu->eumate_p;
02182 rad->fu = nmg_find_fu_of_eu( rad->eu );
02183 }
02184 }
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212 void
02213 nmg_radial_build_list(struct bu_list *hd, struct bu_ptbl *shell_tbl, int existing, struct edgeuse *eu, const fastf_t *xvec, const fastf_t *yvec, const fastf_t *zvec, const struct bn_tol *tol)
02214
02215
02216
02217
02218
02219
02220
02221
02222 {
02223 struct edgeuse *teu;
02224 struct nmg_radial *rad;
02225 fastf_t amin;
02226 fastf_t amax;
02227 int non_wire_edges=0;
02228 struct nmg_radial *rmin = (struct nmg_radial *)NULL;
02229 struct nmg_radial *rmax = (struct nmg_radial *)NULL;
02230 struct nmg_radial *first;
02231
02232 BU_CK_LIST_HEAD(hd);
02233 if(shell_tbl) BU_CK_PTBL(shell_tbl);
02234 NMG_CK_EDGEUSE(eu);
02235 BN_CK_TOL(tol);
02236
02237 if( rt_g.NMG_debug & DEBUG_BASIC || rt_g.NMG_debug & DEBUG_MESH_EU )
02238 bu_log("nmg_radial_build_list( existing=%d, eu=x%x )\n", existing, eu );
02239
02240 amin = 64;
02241 amax = -64;
02242
02243 teu = eu;
02244 for(;;) {
02245 BU_GETSTRUCT( rad, nmg_radial );
02246 rad->l.magic = NMG_RADIAL_MAGIC;
02247 rad->eu = teu;
02248 rad->fu = nmg_find_fu_of_eu( teu );
02249 if( rad->fu ) {
02250
02251 rad->ang = nmg_measure_fu_angle( teu, xvec, yvec, zvec );
02252 non_wire_edges++;
02253
02254 if( rad->ang < amin ) {
02255 amin = rad->ang;
02256 rmin = rad;
02257 }
02258 if( rad->ang > amax ) {
02259 amax = rad->ang;
02260 rmax = rad;
02261 }
02262 } else {
02263
02264 rad->ang = -bn_pi;
02265 }
02266 rad->s = nmg_find_s_of_eu( teu );
02267 rad->existing_flag = existing;
02268 rad->needs_flip = 0;
02269 rad->is_crack = 0;
02270 rad->is_outie = 0;
02271
02272 if( rt_g.NMG_debug & DEBUG_MESH_EU )
02273 bu_log( "\trad->eu = %x, rad->ang = %g\n", rad->eu, rad->ang );
02274
02275
02276 BU_LIST_INSERT( hd, &(rad->l) );
02277
02278
02279 if(shell_tbl) bu_ptbl_ins_unique( shell_tbl, &(rad->s->l.magic) );
02280
02281
02282 teu = teu->radial_p->eumate_p;
02283 if( teu == eu ) break;
02284 }
02285
02286 nmg_insure_radial_list_is_increasing( hd, amin, amax );
02287
02288
02289 if( !rmin ) {
02290
02291 return;
02292 }
02293
02294
02295 if( non_wire_edges < 2 )
02296 {
02297
02298 return;
02299 }
02300
02301 if( rt_g.NMG_debug & DEBUG_MESH_EU )
02302 {
02303 struct nmg_radial *next;
02304
02305 bu_log("amin=%g min_eu=x%x, amax=%g max_eu=x%x\n",
02306 rmin->ang * bn_radtodeg, rmin->eu,
02307 rmax->ang * bn_radtodeg, rmax->eu );
02308
02309 for( BU_LIST_FOR( next, nmg_radial, hd ) )
02310 bu_log( "%x: eu=%x, fu=%x, ang=%g\n" , next, next->eu, next->fu, next->ang );
02311 }
02312
02313
02314 first = rmax;
02315 for(;;) {
02316 struct nmg_radial *next;
02317 next = rmax;
02318 do {
02319 next = BU_LIST_PNEXT_CIRC(nmg_radial, next);
02320 } while( next->fu == (struct faceuse *)NULL );
02321 if( next->ang >= amax )
02322 {
02323 rmax = next;
02324 if( rmax == first )
02325 break;
02326 }
02327 else
02328 break;
02329 }
02330
02331 first = rmin;
02332 for(;;) {
02333 struct nmg_radial *next;
02334
02335 while( (next = BU_LIST_PPREV_CIRC(nmg_radial, rmin))->fu == (struct faceuse *)NULL )
02336 rmin = next;
02337 next = BU_LIST_PPREV_CIRC(nmg_radial, rmin);
02338 if( next->ang <= amin )
02339 {
02340 rmin = next;
02341 if( rmin == first )
02342 {
02343
02344 rmin = BU_LIST_PNEXT_CIRC( nmg_radial, rmax );
02345 break;
02346 }
02347 }
02348 else
02349 break;
02350 }
02351
02352
02353 if( BU_LIST_PNEXT_CIRC(nmg_radial, rmax) == rmin ) {
02354
02355 BU_LIST_DEQUEUE( hd );
02356
02357 BU_LIST_APPEND( &(rmax->l), hd );
02358 nmg_radial_verify_pointers( hd, tol );
02359 } else {
02360 bu_log(" %f %f %f --- %f %f %f\n",
02361 V3ARGS(eu->vu_p->v_p->vg_p->coord),
02362 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
02363 bu_log("amin=%g min_eu=x%x, amax=%g max_eu=x%x B\n",
02364 rmin->ang * bn_radtodeg, rmin->eu,
02365 rmax->ang * bn_radtodeg, rmax->eu );
02366 nmg_pr_radial_list( hd, tol );
02367 nmg_pr_fu_around_eu_vecs( eu, xvec, yvec, zvec, tol );
02368 rt_bomb("nmg_radial_build_list() min and max angle not adjacent in list (or list not monotone increasing)\n");
02369 }
02370 }
02371
02372
02373
02374
02375
02376
02377 void
02378 nmg_radial_merge_lists(struct bu_list *dest, struct bu_list *src, const struct bn_tol *tol)
02379 {
02380 struct nmg_radial *rad;
02381
02382 BU_CK_LIST_HEAD(dest);
02383 BU_CK_LIST_HEAD(src);
02384 BN_CK_TOL(tol);
02385
02386 while( BU_LIST_WHILE( rad, nmg_radial, src ) ) {
02387 BU_LIST_DEQUEUE( &rad->l );
02388 nmg_radial_sorted_list_insert( dest, rad );
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
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444 int
02445 nmg_is_crack_outie(const struct edgeuse *eu, const struct bn_tol *tol)
02446 {
02447 const struct loopuse *lu;
02448 const struct edge *e;
02449 point_t midpt;
02450 const fastf_t *a, *b;
02451 int class;
02452
02453 NMG_CK_EDGEUSE(eu);
02454 BN_CK_TOL(tol);
02455
02456 lu = eu->up.lu_p;
02457 NMG_CK_LOOPUSE(lu);
02458 e = eu->e_p;
02459 NMG_CK_EDGE(e);
02460
02461
02462 if( nmg_loop_is_a_crack( lu ) ) return 1;
02463
02464 a = eu->vu_p->v_p->vg_p->coord;
02465 b = eu->eumate_p->vu_p->v_p->vg_p->coord;
02466 VADD2SCALE( midpt, a, b, 0.5 );
02467
02468
02469 {
02470 #if 1
02471
02472
02473
02474 struct bn_tol tmp_tol;
02475 struct faceuse *fu;
02476 plane_t pl;
02477 fastf_t dist;
02478
02479 tmp_tol = (*tol);
02480 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
02481 rt_bomb( "Nmg_is_crack_outie called with non-face loop" );
02482
02483 fu = lu->up.fu_p;
02484 NMG_CK_FACEUSE( fu );
02485 NMG_GET_FU_PLANE( pl, fu );
02486 dist = DIST_PT_PLANE( midpt, pl );
02487 VJOIN1( midpt, midpt , -dist, pl )
02488 dist = fabs( DIST_PT_PLANE( midpt, pl ) );
02489 if( dist > SQRT_SMALL_FASTF )
02490 {
02491 tmp_tol.dist = dist*2.0;
02492 tmp_tol.dist_sq = tmp_tol.dist * tmp_tol.dist;
02493 }
02494 else
02495 {
02496 tmp_tol.dist = SQRT_SMALL_FASTF;
02497 tmp_tol.dist_sq = SMALL_FASTF;
02498 }
02499 class = nmg_class_pt_lu_except( midpt, lu, e, &tmp_tol );
02500 #else
02501 rt_pr_tol(tol);
02502 bu_log(" eu=x%x, len=%g\n", eu, MAGNITUDE(diff) );
02503 rt_bomb("nmg_is_crack_outie() edge is too short to bisect. Increase tolerance and re-run.\n");
02504 #endif
02505 }
02506 if( rt_g.NMG_debug & DEBUG_BASIC ) {
02507 bu_log("nmg_is_crack_outie(eu=x%x) lu=x%x, e=x%x, class=%s\n",
02508 eu, lu, e, nmg_class_name(class) );
02509 }
02510
02511 if( lu->orientation == OT_SAME ) {
02512 if( class == NMG_CLASS_AinB || class == NMG_CLASS_AonBshared )
02513 return 0;
02514 if( class == NMG_CLASS_AoutB )
02515 return 1;
02516 } else {
02517
02518 if( class == NMG_CLASS_AinB || class == NMG_CLASS_AonBshared )
02519 return 1;
02520 if( class == NMG_CLASS_AoutB )
02521 return 0;
02522 }
02523
02524
02525 bu_log("nmg_is_crack_outie(eu=x%x), lu=x%x(%s)\n midpt_class=%s, midpt=(%g, %g, %g)\n",
02526 eu,
02527 lu, nmg_orientation(lu->orientation),
02528 nmg_class_name(class),
02529 V3ARGS(midpt) );
02530 nmg_pr_lu_briefly( lu, 0 );
02531 rt_bomb("nmg_is_crack_outie() got unexpected midpt classification from nmg_class_pt_lu_except()\n");
02532
02533 return( -1 );
02534 }
02535
02536
02537
02538
02539 struct nmg_radial *
02540 nmg_find_radial_eu(const struct bu_list *hd, const struct edgeuse *eu)
02541 {
02542 register struct nmg_radial *rad;
02543
02544 BU_CK_LIST_HEAD(hd);
02545 NMG_CK_EDGEUSE(eu);
02546
02547 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02548 if( rad->eu == eu ) return rad;
02549 if( rad->eu->eumate_p == eu ) return rad;
02550 }
02551 bu_log("nmg_find_radial_eu() eu=x%x\n", eu);
02552 rt_bomb("nmg_find_radial_eu() given edgeuse not found on list\n");
02553
02554 return( (struct nmg_radial *)NULL );
02555 }
02556
02557
02558
02559
02560
02561
02562
02563 const struct edgeuse *
02564 nmg_find_next_use_of_2e_in_lu(const struct edgeuse *eu, const struct edge *e1, const struct edge *e2)
02565
02566
02567
02568 {
02569 register const struct edgeuse *neu;
02570
02571 NMG_CK_EDGEUSE(eu);
02572 NMG_CK_LOOPUSE(eu->up.lu_p);
02573 NMG_CK_EDGE(e1);
02574 if(e2) NMG_CK_EDGE(e2);
02575
02576 neu = eu;
02577 do {
02578 neu = BU_LIST_PNEXT_CIRC( edgeuse, &neu->l );
02579 } while( neu->e_p != e1 && neu->e_p != e2 );
02580 return neu;
02581
02582 }
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600 void
02601 nmg_radial_mark_cracks(struct bu_list *hd, const struct edge *e1, const struct edge *e2, const struct bn_tol *tol)
02602
02603
02604
02605
02606 {
02607 struct nmg_radial *rad;
02608 struct nmg_radial *other;
02609 const struct loopuse *lu;
02610 const struct edgeuse *eu;
02611 register int uses;
02612 int outie = -1;
02613
02614 BU_CK_LIST_HEAD(hd);
02615 NMG_CK_EDGE(e1);
02616 if(e2) NMG_CK_EDGE(e2);
02617 BN_CK_TOL(tol);
02618
02619 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02620 NMG_CK_RADIAL(rad);
02621 if( rad->is_crack ) continue;
02622 if( !rad->fu ) continue;
02623 lu = rad->eu->up.lu_p;
02624 uses = 0;
02625
02626
02627 for( other = BU_LIST_PNEXT( nmg_radial, rad );
02628 BU_LIST_NOT_HEAD( other, hd );
02629 other = BU_LIST_PNEXT( nmg_radial, other )
02630 ) {
02631 if( !other->fu ) continue;
02632
02633 if( other->eu->up.lu_p != lu &&
02634 other->eu->eumate_p->up.lu_p != lu )
02635 continue;
02636 uses++;
02637 }
02638 if( uses <= 0 ) {
02639
02640 continue;
02641 }
02642 uses++;
02643
02644
02645 if( (uses & 1) == 0 ) {
02646
02647 outie = nmg_is_crack_outie( rad->eu, tol );
02648 rad->is_crack = 1;
02649 rad->is_outie = outie;
02650 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02651 bu_log( "nmg_radial_mark_cracks() EVEN crack eu=x%x, uses=%d, outie=%d\n",
02652 rad->eu, uses, outie );
02653 }
02654
02655 for( other = BU_LIST_PNEXT( nmg_radial, rad );
02656 BU_LIST_NOT_HEAD( other, hd );
02657 other = BU_LIST_PNEXT( nmg_radial, other )
02658 ) {
02659 if( !other->fu ) continue;
02660
02661 if( other->eu->up.lu_p != lu &&
02662 other->eu->eumate_p->up.lu_p != lu )
02663 continue;
02664 other->is_crack = 1;
02665 other->is_outie = outie;
02666 }
02667 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02668 bu_log("Printing loopuse and resulting radial list:\n");
02669 nmg_pr_lu_briefly( lu, 0 );
02670 nmg_pr_radial_list( hd, tol );
02671 }
02672 continue;
02673 }
02674
02675
02676
02677
02678 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02679 bu_log( "nmg_radial_mark_cracks() ODD crack eu=x%x, uses=%d, outie=%d\n",
02680 rad->eu, uses, outie );
02681 }
02682
02683 eu = rad->eu;
02684 for( ; uses >= 2; uses-- ) {
02685 eu = nmg_find_next_use_of_2e_in_lu( eu, e1, e2 );
02686 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02687 bu_log("rad->eu=x%x, eu=x%x, uses=%d\n",
02688 rad->eu, eu, uses);
02689 }
02690 if( eu == rad->eu ) {
02691 nmg_pr_lu_briefly( lu, 0 );
02692 nmg_pr_radial_list( hd, tol );
02693 rt_bomb("nmg_radial_mark_cracks() loop too short!\n");
02694 }
02695
02696 other = nmg_find_radial_eu( hd, eu );
02697
02698 other->is_crack = 1;
02699 other->is_outie = 1;
02700 }
02701
02702
02703 eu = nmg_find_next_use_of_2e_in_lu( eu, e1, e2 );
02704 if( eu != rad->eu ) {
02705 nmg_pr_lu_briefly( lu, 0 );
02706 nmg_pr_radial_list( hd, tol );
02707 rt_bomb("nmg_radial_mark_cracks() loop didn't return to start\n");
02708 }
02709
02710 rad->is_crack = 1;
02711 rad->is_outie = 0;
02712 }
02713 }
02714
02715
02716
02717
02718
02719
02720
02721
02722 struct nmg_radial *
02723 nmg_radial_find_an_original(const struct bu_list *hd, const struct shell *s, const struct bn_tol *tol)
02724 {
02725 register struct nmg_radial *rad;
02726 struct nmg_radial *fallback = (struct nmg_radial *)NULL;
02727 int seen_shell = 0;
02728
02729 BU_CK_LIST_HEAD(hd);
02730 NMG_CK_SHELL(s);
02731
02732
02733 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02734 NMG_CK_RADIAL(rad);
02735 if( rad->s != s ) continue;
02736 seen_shell++;
02737 if( rad->is_outie ) {
02738 fallback = rad;
02739 continue;
02740 }
02741 if( !rad->fu ) continue;
02742 if( rad->existing_flag ) return rad;
02743 }
02744 if( !seen_shell ) return (struct nmg_radial *)NULL;
02745
02746
02747 if(fallback) return fallback;
02748
02749
02750 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02751 if( rad->s != s ) continue;
02752 if( rad->is_outie ) {
02753 fallback = rad;
02754 continue;
02755 }
02756 if( !rad->fu ) {
02757 continue;
02758 }
02759 return rad;
02760 }
02761
02762 if(fallback) return fallback;
02763
02764
02765 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02766 if( rad->s != s ) continue;
02767 if( rad->is_outie ) {
02768 continue;
02769 }
02770 if( !rad->fu ) {
02771 fallback = rad;
02772 continue;
02773 }
02774 return rad;
02775 }
02776 if(fallback) return fallback;
02777
02778 bu_log("nmg_radial_find_an_original() shell=x%x\n", s);
02779 nmg_pr_radial_list( hd, tol );
02780 rt_bomb("nmg_radial_find_an_original() No entries from indicated shell\n");
02781
02782 return( (struct nmg_radial *)NULL );
02783 }
02784
02785
02786
02787
02788
02789
02790
02791 int
02792 nmg_radial_mark_flips(struct bu_list *hd, const struct shell *s, const struct bn_tol *tol)
02793 {
02794 struct nmg_radial *rad;
02795 struct nmg_radial *orig;
02796 register int expected_ot;
02797 int count = 0;
02798 int nflip = 0;
02799
02800 BU_CK_LIST_HEAD(hd);
02801 NMG_CK_SHELL(s);
02802 BN_CK_TOL(tol);
02803
02804 orig = nmg_radial_find_an_original( hd, s, tol );
02805 NMG_CK_RADIAL(orig);
02806 if( orig->is_outie ) {
02807
02808 return 0;
02809 }
02810
02811 if( !orig->fu )
02812 {
02813
02814 return( 0 );
02815 }
02816 if( !orig->existing_flag ) {
02817
02818 if( !orig->fu ) {
02819
02820 return 0;
02821 }
02822 #if 0
02823
02824
02825
02826
02827 rad = BU_LIST_PPREV_CIRC( nmg_radial, orig );
02828
02829 if( rad->eu->vu_p->v_p == orig->eu->vu_p->v_p ) {
02830
02831 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02832 if( rad->s != s ) continue;
02833 if( !rad->fu ) continue;
02834 rad->needs_flip = !rad->needs_flip;
02835 }
02836 }
02837 #endif
02838 }
02839
02840 expected_ot = !(orig->fu->orientation == OT_SAME);
02841 if( !orig->is_outie ) count++;
02842
02843 for( BU_LIST_FOR_CIRC( rad, nmg_radial, orig ) ) {
02844 if( rad->s != s ) continue;
02845 if( !rad->fu ) continue;
02846 if( rad->is_outie ) continue;
02847 count++;
02848 if( expected_ot == (rad->fu->orientation == OT_SAME) ) {
02849 expected_ot = !expected_ot;
02850 continue;
02851 }
02852
02853 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02854 bu_log("nmg_radial_mark_flips() Mis-match detected, setting flip flag eu=x%x\n", rad->eu);
02855 }
02856 rad->needs_flip = !rad->needs_flip;
02857 nflip++;
02858
02859 expected_ot = !expected_ot;
02860 }
02861
02862 if( count & 1 ) {
02863 #if 0
02864 bu_log("nmg_radial_mark_flips() NOTICE dangling fu=x%x detected at eu=x%x in shell=x%x, proceeding.\n %g %g %g --- %g %g %g\n",
02865 orig->fu, orig->eu, s,
02866 V3ARGS(orig->eu->vu_p->v_p->vg_p->coord),
02867 V3ARGS(orig->eu->eumate_p->vu_p->v_p->vg_p->coord)
02868 );
02869 nmg_pr_radial_list( hd, tol );
02870 #endif
02871 return count;
02872 }
02873
02874 if( expected_ot == (orig->fu->orientation == OT_SAME) )
02875 return nflip;
02876
02877 bu_log("nmg_radial_mark_flips() unable to establish proper orientation parity.\n eu count=%d, shell=x%x, expectation=%d\n",
02878 count, s, expected_ot);
02879 nmg_pr_radial_list( hd, tol );
02880 rt_bomb("nmg_radial_mark_flips() unable to establish proper orientation parity.\n");
02881
02882 return( 0 );
02883 }
02884
02885
02886
02887
02888
02889
02890 int
02891 nmg_radial_check_parity(const struct bu_list *hd, const struct bu_ptbl *shells, const struct bn_tol *tol)
02892 {
02893 struct nmg_radial *rad;
02894 struct shell **sp;
02895 struct nmg_radial *orig;
02896 register int expected_ot;
02897 int count = 0;
02898
02899 BU_CK_LIST_HEAD(hd);
02900 BU_CK_PTBL(shells);
02901 BN_CK_TOL(tol);
02902
02903 for( sp = (struct shell **)BU_PTBL_LASTADDR(shells);
02904 sp >= (struct shell **)BU_PTBL_BASEADDR(shells); sp--
02905 ) {
02906
02907 NMG_CK_SHELL(*sp);
02908 orig = nmg_radial_find_an_original( hd, *sp, tol );
02909 if( !orig ) continue;
02910 NMG_CK_RADIAL(orig);
02911 if( !orig->existing_flag ) {
02912
02913 if( !orig->fu ) continue;
02914 }
02915 if( orig->is_outie ) continue;
02916 expected_ot = !(orig->fu->orientation == OT_SAME);
02917
02918 for( BU_LIST_FOR_CIRC( rad, nmg_radial, orig ) ) {
02919 if( rad->s != *sp ) continue;
02920 if( !rad->fu ) continue;
02921 if( rad->is_outie ) continue;
02922 if( expected_ot == (rad->fu->orientation == OT_SAME) ) {
02923 expected_ot = !expected_ot;
02924 continue;
02925 }
02926
02927 bu_log("nmg_radial_check_parity() bad parity eu=x%x, s=x%x\n",
02928 rad->eu, *sp);
02929 count++;
02930
02931 expected_ot = !expected_ot;
02932 }
02933 if( expected_ot == (orig->fu->orientation == OT_SAME) )
02934 continue;
02935 bu_log("nmg_radial_check_parity() bad parity at END eu=x%x, s=x%x\n",
02936 rad->eu, *sp);
02937 count++;
02938 }
02939 return count;
02940 }
02941
02942
02943
02944
02945
02946
02947
02948 void
02949 nmg_radial_implement_decisions(struct bu_list *hd, const struct bn_tol *tol, struct edgeuse *eu1, fastf_t *xvec, fastf_t *yvec, fastf_t *zvec)
02950
02951
02952
02953
02954 {
02955 struct nmg_radial *rad;
02956 struct nmg_radial *prev;
02957 int skipped;
02958
02959 BU_CK_LIST_HEAD(hd);
02960 BN_CK_TOL(tol);
02961
02962 if( rt_g.NMG_debug & DEBUG_BASIC )
02963 bu_log("nmg_radial_implement_decisions() BEGIN\n");
02964
02965 again:
02966 skipped = 0;
02967 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
02968 struct edgeuse *dest;
02969
02970 if( rad->existing_flag ) continue;
02971 prev = BU_LIST_PPREV_CIRC( nmg_radial, rad );
02972 if( !prev->existing_flag ) {
02973
02974 skipped++;
02975 continue;
02976 }
02977
02978
02979
02980
02981
02982 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
02983 bu_log("Before -- ");
02984 nmg_pr_fu_around_eu_vecs( eu1, xvec, yvec, zvec, tol );
02985 nmg_pr_radial("prev:", (const struct nmg_radial *)prev);
02986 nmg_pr_radial(" rad:", (const struct nmg_radial *)rad);
02987 }
02988 dest = prev->eu;
02989 if( rad->needs_flip ) {
02990 struct edgeuse *other_eu = rad->eu->eumate_p;
02991
02992 nmg_je( dest, rad->eu );
02993 rad->eu = other_eu;
02994 rad->fu = nmg_find_fu_of_eu( other_eu );
02995 rad->needs_flip = 0;
02996 } else {
02997 nmg_je( dest, rad->eu->eumate_p );
02998 }
02999 rad->existing_flag = 1;
03000 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03001 bu_log("After -- ");
03002 nmg_pr_fu_around_eu_vecs( eu1, xvec, yvec, zvec, tol );
03003 }
03004 }
03005 if( skipped ) {
03006 if( rt_g.NMG_debug & DEBUG_BASIC )
03007 bu_log("nmg_radial_implement_decisions() %d remaining, go again\n", skipped);
03008 goto again;
03009 }
03010
03011 if( rt_g.NMG_debug & DEBUG_BASIC )
03012 bu_log("nmg_radial_implement_decisions() END\n");
03013 }
03014
03015
03016
03017
03018 void
03019 nmg_pr_radial(const char *title, const struct nmg_radial *rad)
03020 {
03021 struct face *f;
03022 int orient;
03023
03024 NMG_CK_RADIAL(rad);
03025 if( !rad->fu ) {
03026 f = (struct face *)NULL;
03027 orient = 'W';
03028 } else {
03029 f = rad->fu->f_p;
03030 orient = nmg_orientation(rad->fu->orientation)[3];
03031 }
03032 bu_log("%s%8.8x, mate of \\/\n",
03033 title,
03034 rad->eu->eumate_p
03035 );
03036 bu_log("%s%8.8x, f=%8.8x, fu=%8.8x=%c, s=%8.8x %s %c%c%c %g deg\n",
03037 title,
03038 rad->eu,
03039 f, rad->fu, orient,
03040 rad->s,
03041 rad->existing_flag ? "old" : "new",
03042 rad->needs_flip ? 'F' : '/',
03043 rad->is_crack ? 'C' : '/',
03044 rad->is_outie ? 'O' : (rad->is_crack ? 'I' : '/'),
03045 rad->ang * bn_radtodeg
03046 );
03047 }
03048
03049
03050
03051
03052
03053
03054 void
03055 nmg_pr_radial_list(const struct bu_list *hd, const struct bn_tol *tol)
03056
03057
03058 {
03059 struct nmg_radial *rad;
03060
03061 BU_CK_LIST_HEAD(hd);
03062 BN_CK_TOL(tol);
03063
03064 bu_log("nmg_pr_radial_list( hd=x%x )\n", hd);
03065
03066 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
03067 NMG_CK_RADIAL(rad);
03068 nmg_pr_radial(" ", rad);
03069 }
03070 }
03071
03072
03073
03074
03075
03076
03077
03078
03079 void
03080 nmg_do_radial_flips(struct bu_list *hd)
03081 {
03082 struct nmg_radial *start_same;
03083 struct bn_tol tol;
03084
03085 tol.magic = BN_TOL_MAGIC;
03086 tol.dist = 0.005;
03087 tol.dist_sq = tol.dist * tol.dist;
03088 tol.perp = 1e-6;
03089 tol.para = 1 - tol.perp;
03090
03091 BU_CK_LIST_HEAD( hd );
03092
03093 start_same = BU_LIST_FIRST( nmg_radial, hd );
03094 while( BU_LIST_NOT_HEAD( &start_same->l, hd ) )
03095 {
03096 struct nmg_radial *next_after_same;
03097 struct nmg_radial *end_same;
03098 struct nmg_radial *same;
03099 struct nmg_radial *check;
03100
03101 if( !start_same->fu )
03102 {
03103 start_same = BU_LIST_PNEXT( nmg_radial, &start_same->l );
03104 continue;
03105 }
03106
03107 end_same = BU_LIST_PNEXT_CIRC( nmg_radial, &start_same->l );
03108 while( (end_same->ang == start_same->ang && end_same != start_same)
03109 || !end_same->fu )
03110 end_same = BU_LIST_PNEXT_CIRC( nmg_radial, &end_same->l );
03111 end_same = BU_LIST_PPREV_CIRC( nmg_radial, &end_same->l );
03112
03113 if( start_same == end_same )
03114 {
03115 start_same = BU_LIST_PNEXT( nmg_radial, &start_same->l );
03116 continue;
03117 }
03118
03119
03120 next_after_same = BU_LIST_PNEXT_CIRC( nmg_radial, &end_same->l );
03121 while( !next_after_same->fu && next_after_same != start_same )
03122 next_after_same = BU_LIST_PNEXT_CIRC( nmg_radial, &next_after_same->l );
03123
03124 if( next_after_same == start_same )
03125 {
03126
03127 return;
03128 }
03129
03130 check = next_after_same;
03131 while( start_same != end_same && check != start_same )
03132 {
03133 same = end_same;
03134 while( same->s != check->s && same != start_same )
03135 same = BU_LIST_PPREV_CIRC( nmg_radial, &same->l );
03136
03137 if( same->s != check->s )
03138 {
03139
03140
03141
03142
03143 check = BU_LIST_PNEXT_CIRC( nmg_radial, &check->l );
03144 continue;
03145 }
03146
03147
03148 if( same == start_same )
03149 {
03150
03151
03152
03153 start_same = BU_LIST_PNEXT_CIRC( nmg_radial, &start_same->l );
03154 BU_LIST_DEQUEUE( &same->l );
03155 BU_LIST_APPEND( &end_same->l, &same->l );
03156 }
03157 else if( same == end_same )
03158 {
03159
03160 end_same = BU_LIST_PPREV_CIRC( nmg_radial, &end_same->l );
03161 }
03162 else
03163 {
03164 BU_LIST_DEQUEUE( &same->l );
03165 BU_LIST_APPEND( &end_same->l, &same->l );
03166 }
03167
03168 check = BU_LIST_PNEXT_CIRC( nmg_radial, &check->l );
03169 }
03170
03171 start_same = BU_LIST_PNEXT( nmg_radial, &end_same->l );
03172 }
03173 }
03174
03175
03176
03177
03178
03179
03180
03181 void
03182 nmg_do_radial_join(struct bu_list *hd, struct edgeuse *eu1ref, fastf_t *xvec, fastf_t *yvec, fastf_t *zvec, const struct bn_tol *tol)
03183 {
03184 struct nmg_radial *rad;
03185 struct nmg_radial *prev;
03186 vect_t ref_dir;
03187 int skipped;
03188
03189 BU_CK_LIST_HEAD( hd );
03190 NMG_CK_EDGEUSE( eu1ref );
03191 BN_CK_TOL( tol );
03192
03193 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03194 bu_log( "nmg_do_radial_join() START\n" );
03195
03196 nmg_do_radial_flips( hd );
03197
03198 VSUB2( ref_dir, eu1ref->eumate_p->vu_p->v_p->vg_p->coord, eu1ref->vu_p->v_p->vg_p->coord );
03199
03200 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03201 bu_log( "ref_dir = ( %g %g %g )\n", V3ARGS( ref_dir ) );
03202
03203 top:
03204
03205 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03206 {
03207 bu_log( "At top of nmg_do_radial_join:\n" );
03208 nmg_pr_radial_list( hd, tol );
03209 }
03210
03211 skipped = 0;
03212 for( BU_LIST_FOR( rad, nmg_radial, hd ) )
03213 {
03214 struct edgeuse *dest;
03215 struct edgeuse *src;
03216 vect_t src_dir;
03217 vect_t dest_dir;
03218
03219 if( rad->existing_flag )
03220 continue;
03221
03222 prev = BU_LIST_PPREV_CIRC( nmg_radial, rad );
03223 if( !prev->existing_flag )
03224 {
03225 skipped++;
03226 continue;
03227 }
03228
03229 VSUB2( dest_dir, prev->eu->eumate_p->vu_p->v_p->vg_p->coord, prev->eu->vu_p->v_p->vg_p->coord );
03230 VSUB2( src_dir, rad->eu->eumate_p->vu_p->v_p->vg_p->coord, rad->eu->vu_p->v_p->vg_p->coord );
03231
03232 if( !prev->fu || !rad->fu )
03233 {
03234 nmg_je( prev->eu, rad->eu );
03235 continue;
03236 }
03237
03238 if( VDOT( dest_dir, ref_dir ) < 0.0 )
03239 dest = prev->eu->eumate_p;
03240 else
03241 dest = prev->eu;
03242
03243 if( VDOT( src_dir, ref_dir ) > 0.0 )
03244 src = rad->eu->eumate_p;
03245 else
03246 src = rad->eu;
03247
03248 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03249 {
03250 bu_log("Before -- ");
03251 nmg_pr_fu_around_eu_vecs( eu1ref, xvec, yvec, zvec, tol );
03252 nmg_pr_radial("prev:", prev);
03253 nmg_pr_radial(" rad:", rad);
03254
03255 if( VDOT( dest_dir, ref_dir ) < 0.0 )
03256 bu_log( "dest_dir disagrees with eu1ref\n" );
03257 else
03258 bu_log( "dest_dir agrees with eu1ref\n" );
03259
03260 if( VDOT( src_dir, ref_dir ) < 0.0 )
03261 bu_log( "src_dir disagrees with eu1ref\n" );
03262 else
03263 bu_log( "src_dir agrees with eu1ref\n" );
03264
03265 bu_log( "Joining dest_eu=x%x to src_eu=x%x\n", dest, src );
03266 }
03267
03268 nmg_je( dest, src );
03269 rad->existing_flag = 1;
03270 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03271 {
03272 bu_log("After -- ");
03273 nmg_pr_fu_around_eu_vecs( eu1ref, xvec, yvec, zvec, tol );
03274 }
03275 }
03276
03277 if( skipped )
03278 goto top;
03279
03280 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03281 bu_log( "nmg_do_radial_join() DONE\n\n" );
03282 }
03283
03284
03285
03286
03287
03288
03289
03290 void
03291 nmg_radial_join_eu_NEW(struct edgeuse *eu1, struct edgeuse *eu2, const struct bn_tol *tol)
03292 {
03293 struct edgeuse *eu1ref;
03294 struct edgeuse *eu2ref;
03295 struct faceuse *fu1;
03296 struct faceuse *fu2;
03297 struct nmg_radial *rad;
03298 vect_t xvec, yvec, zvec;
03299 struct bu_list list1;
03300 struct bu_list list2;
03301 struct bu_ptbl shell_tbl;
03302
03303 NMG_CK_EDGEUSE(eu1);
03304 NMG_CK_EDGEUSE(eu2);
03305 BN_CK_TOL(tol);
03306
03307 if( eu1->e_p == eu2->e_p ) return;
03308
03309 if( !NMG_ARE_EUS_ADJACENT(eu1, eu2) )
03310 rt_bomb("nmg_radial_join_eu_NEW() edgeuses don't share vertices.\n");
03311
03312 if( eu1->vu_p->v_p == eu1->eumate_p->vu_p->v_p ) rt_bomb("nmg_radial_join_eu_NEW(): 0 length edge (topology)\n");
03313
03314 if( bn_pt3_pt3_equal( eu1->vu_p->v_p->vg_p->coord,
03315 eu1->eumate_p->vu_p->v_p->vg_p->coord, tol ) )
03316 rt_bomb("nmg_radial_join_eu_NEW(): 0 length edge (geometry)\n");
03317
03318
03319 fu1 = nmg_find_fu_of_eu(eu1);
03320 fu2 = nmg_find_fu_of_eu(eu2);
03321 if( fu1 && fu2 ) {
03322 if( fu1->orientation != fu2->orientation ){
03323 eu2 = eu2->eumate_p;
03324 fu2 = nmg_find_fu_of_eu(eu2);
03325 if( fu1->orientation != fu2->orientation )
03326 rt_bomb( "nmg_radial_join_eu_NEW(): Cannot find matching orientations for faceuses\n" );
03327 }
03328 }
03329
03330 if( eu1->eumate_p->radial_p == eu1 && eu2->eumate_p->radial_p == eu2 &&
03331 nmg_find_s_of_eu( eu1 ) == nmg_find_s_of_eu( eu2 ) )
03332 {
03333
03334 nmg_je( eu1, eu2 );
03335 if( eu1->g.magic_p && eu2->g.magic_p )
03336 {
03337 if( eu1->g.magic_p != eu2->g.magic_p )
03338 nmg_jeg( eu1->g.lseg_p, eu2->g.lseg_p );
03339 }
03340 else if( eu1->g.magic_p && !eu2->g.magic_p )
03341 (void)nmg_use_edge_g( eu2, eu1->g.magic_p );
03342 else if( !eu1->g.magic_p && eu2->g.magic_p )
03343 (void)nmg_use_edge_g( eu1, eu2->g.magic_p );
03344 else
03345 {
03346 nmg_edge_g( eu1 );
03347 nmg_use_edge_g( eu2, eu1->g.magic_p );
03348 }
03349 return;
03350 }
03351
03352
03353 if( fu1 && fu1->f_p->g.magic_p && *fu1->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC ) return;
03354 if( fu2 && fu2->f_p->g.magic_p && *fu2->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC ) return;
03355
03356
03357
03358
03359 if( fu1 ) {
03360 if( fu1->orientation == OT_SAME )
03361 eu1ref = eu1;
03362 else
03363 eu1ref = eu1->eumate_p;
03364 } else {
03365
03366 eu1ref = nmg_find_ot_same_eu_of_e(eu1->e_p);
03367 }
03368 if( eu1ref->vu_p->v_p == eu2->vu_p->v_p ) {
03369 eu2ref = eu2;
03370 } else {
03371 eu2ref = eu2->eumate_p;
03372 }
03373 nmg_eu_2vecs_perp( xvec, yvec, zvec, eu1ref, tol );
03374
03375
03376 BU_LIST_INIT( &list1 );
03377 BU_LIST_INIT( &list2 );
03378 bu_ptbl_init( &shell_tbl, 64, " &shell_tbl");
03379
03380 nmg_radial_build_list( &list1, &shell_tbl, 1, eu1ref, xvec, yvec, zvec, tol );
03381 nmg_radial_build_list( &list2, &shell_tbl, 0, eu2ref, xvec, yvec, zvec, tol );
03382
03383 #if 0
03384
03385 nmg_pr_radial_list( &list1, tol );
03386 nmg_pr_radial_list( &list2, tol );
03387 nmg_pr_ptbl( "Participating shells", &shell_tbl, 1 );
03388 #endif
03389
03390 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03391 bu_log("nmg_radial_join_eu_NEW(eu1=x%x, eu2=x%x) e1=x%x, e2=x%x\n",
03392 eu1, eu2,
03393 eu1->e_p, eu2->e_p);
03394 nmg_euprint("\tJoining", eu1);
03395 bu_log( "Faces around eu1:\n" );
03396 nmg_pr_fu_around_eu_vecs( eu1ref, xvec, yvec, zvec, tol );
03397 nmg_pr_radial_list( &list1, tol );
03398
03399 bu_log( "Faces around eu2:\n" );
03400 nmg_pr_fu_around_eu_vecs( eu2ref, xvec, yvec, zvec, tol );
03401 nmg_pr_radial_list( &list2, tol );
03402 nmg_pr_ptbl( "Participating shells", &shell_tbl, 1 );
03403 }
03404
03405 #if 0
03406 count1 = nmg_radial_check_parity( &list1, &shell_tbl, tol );
03407 count2 = nmg_radial_check_parity( &list2, &shell_tbl, tol );
03408 if( count1 || count2 ) bu_log("nmg_radial_join_eu_NEW() bad parity at the outset, %d, %d\n", count1, count2);
03409 #endif
03410
03411
03412 nmg_radial_merge_lists( &list1, &list2, tol );
03413 nmg_radial_verify_monotone( &list1, tol );
03414
03415 #if 1
03416 if (rt_g.NMG_debug & DEBUG_MESH_EU )
03417 {
03418 bu_log( "Before nmg_do_radial_join():\n" );
03419 bu_log( "xvec=(%g %g %g), yvec=(%g %g %g), zvec=(%g %g %g)\n" , V3ARGS( xvec ), V3ARGS( yvec ), V3ARGS( zvec ) );
03420 nmg_pr_fu_around_eu_vecs( eu2ref, xvec, yvec, zvec, tol );
03421 }
03422 nmg_do_radial_join( &list1, eu1ref, xvec, yvec, zvec, tol );
03423
03424
03425 bu_ptbl_free( &shell_tbl);
03426 while( BU_LIST_WHILE( rad, nmg_radial, &list1 ) ) {
03427 BU_LIST_DEQUEUE( &rad->l );
03428 bu_free( (char *)rad, "nmg_radial" );
03429 }
03430 return;
03431 #else
03432
03433 nmg_radial_mark_cracks( &list1, eu1->e_p, eu2->e_p, tol );
03434
03435 for( sp = (struct shell **)BU_PTBL_LASTADDR(&shell_tbl);
03436 sp >= (struct shell **)BU_PTBL_BASEADDR(&shell_tbl); sp--
03437 ) {
03438 nmg_radial_mark_flips( &list1, *sp, tol );
03439 }
03440
03441 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03442 bu_log("marked list:\n");
03443 bu_log(" edge: %g %g %g -> %g %g %g\n",
03444 V3ARGS(eu1ref->vu_p->v_p->vg_p->coord),
03445 V3ARGS(eu1ref->eumate_p->vu_p->v_p->vg_p->coord) );
03446 nmg_pr_radial_list( &list1, tol );
03447 }
03448
03449 nmg_radial_implement_decisions( &list1, tol, eu1ref, xvec, yvec, zvec );
03450
03451 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03452
03453 nmg_pr_radial_list( &list1, tol );
03454 nmg_pr_fu_around_eu_vecs( eu1ref, xvec, yvec, zvec, tol );
03455 }
03456 count1 = nmg_radial_check_parity( &list1, &shell_tbl, tol );
03457 if( count1 ) bu_log("nmg_radial_join_eu_NEW() bad parity at completion, %d\n", count1);
03458 nmg_radial_verify_pointers( &list1, tol );
03459
03460 nmg_eu_radial_check( eu1ref, nmg_find_s_of_eu(eu1), tol );
03461 #endif
03462 }
03463
03464
03465
03466
03467
03468
03469 void
03470 nmg_radial_exchange_marked(struct bu_list *hd, const struct bn_tol *tol)
03471
03472
03473 {
03474 struct nmg_radial *rad;
03475
03476 BU_CK_LIST_HEAD(hd);
03477 BN_CK_TOL(tol);
03478
03479 for( BU_LIST_FOR( rad, nmg_radial, hd ) ) {
03480 struct edgeuse *eu;
03481 struct edgeuse *eumate;
03482 struct edgeuse *before;
03483 struct edgeuse *after;
03484
03485 if( !rad->needs_flip ) continue;
03486
03487
03488
03489
03490
03491 eu = rad->eu;
03492 eumate = eu->eumate_p;
03493 before = eu->radial_p;
03494 after = eumate->radial_p;
03495
03496
03497
03498
03499
03500 before->radial_p = eumate;
03501 eumate->radial_p = before;
03502
03503 after->radial_p = eu;
03504 eu->radial_p = after;
03505
03506 rad->eu = eumate;
03507 rad->fu = nmg_find_fu_of_eu( rad->eu );
03508 rad->needs_flip = 0;
03509 }
03510 }
03511
03512
03513
03514
03515
03516
03517
03518
03519 void
03520 nmg_s_radial_harmonize(struct shell *s, const struct bn_tol *tol)
03521 {
03522 struct bu_ptbl edges;
03523 struct edgeuse *eu;
03524 struct bu_list list;
03525 vect_t xvec, yvec, zvec;
03526 struct edge **ep;
03527
03528 NMG_CK_SHELL(s);
03529 BN_CK_TOL(tol);
03530
03531 if( rt_g.NMG_debug & DEBUG_BASIC )
03532 bu_log("nmg_s_radial_harmonize( s=x%x ) BEGIN\n", s);
03533
03534 nmg_edge_tabulate( &edges, &s->l.magic );
03535 for( ep = (struct edge **)BU_PTBL_LASTADDR(&edges);
03536 ep >= (struct edge **)BU_PTBL_BASEADDR(&edges); ep--
03537 ) {
03538 struct nmg_radial *rad;
03539 int nflip;
03540
03541 NMG_CK_EDGE(*ep);
03542 eu = nmg_find_ot_same_eu_of_e( *ep );
03543 nmg_eu_2vecs_perp( xvec, yvec, zvec, eu, tol );
03544
03545 BU_LIST_INIT( &list );
03546
03547 nmg_radial_build_list( &list, (struct bu_ptbl *)NULL, 1, eu, xvec, yvec, zvec, tol );
03548 nflip = nmg_radial_mark_flips( &list, s, tol );
03549 if( nflip ) {
03550 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03551 bu_log("Flips needed:\n");
03552 nmg_pr_radial_list( &list, tol );
03553 }
03554
03555 nmg_radial_exchange_marked( &list, tol );
03556 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03557 nmg_pr_fu_around_eu_vecs( eu, xvec, yvec, zvec, tol );
03558 }
03559 }
03560
03561 while( BU_LIST_WHILE( rad, nmg_radial, &list ) ) {
03562 BU_LIST_DEQUEUE( &rad->l );
03563 bu_free( (char *)rad, "nmg_radial" );
03564 }
03565 }
03566
03567 bu_ptbl_free( &edges);
03568
03569 if( rt_g.NMG_debug & DEBUG_BASIC )
03570 bu_log("nmg_s_radial_harmonize( s=x%x ) END\n", s);
03571 }
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582 int
03583 nmg_eu_radial_check(const struct edgeuse *eu, const struct shell *s, const struct bn_tol *tol)
03584 {
03585 #if 1
03586 return( 0 );
03587 #else
03588 struct bu_list list;
03589 vect_t xvec, yvec, zvec;
03590 struct nmg_radial *rad;
03591 int nflip;
03592
03593 NMG_CK_EDGEUSE(eu);
03594 BN_CK_TOL(tol);
03595
03596 if (rt_g.NMG_debug & DEBUG_BASIC) {
03597 bu_log("nmg_eu_radial_check(eu=x%x, s=x%x)\n", eu, s);
03598 }
03599
03600 fu = nmg_find_fu_of_eu(eu);
03601 if( fu && fu->orientation != OT_SAME ) eu = eu->eumate_p;
03602 nmg_eu_2vecs_perp( xvec, yvec, zvec, eu, tol );
03603
03604 BU_LIST_INIT( &list );
03605
03606
03607 nmg_radial_build_list( &list, NULL, 1, eu, xvec, yvec, zvec, tol );
03608
03609 nmg_radial_mark_cracks( &list, eu->e_p, NULL, tol );
03610
03611 nflip = nmg_radial_mark_flips( &list, s, tol );
03612 if( nflip ) {
03613 struct nmg_radial *rad;
03614 bu_log("nmg_eu_radial_check(x%x) %d flips needed\n %g %g %g --- %g %g %g\n",
03615 s, nflip,
03616 V3ARGS(eu->vu_p->v_p->vg_p->coord),
03617 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
03618 nmg_pr_radial_list( &list, tol );
03619 if (rt_g.NMG_debug & DEBUG_MESH_EU ) {
03620 nmg_pr_fu_around_eu_vecs( eu, xvec, yvec, zvec, tol );
03621 }
03622
03623 if (rt_g.NMG_debug)
03624 {
03625 char tmp_name[256];
03626
03627 sprintf( tmp_name, "radial_check_%d.g", debug_file_count );
03628 nmg_stash_model_to_file( tmp_name, nmg_find_model( &eu->l.magic ), "error" );
03629 for( BU_LIST_FOR( rad, nmg_radial, &list ) )
03630 nmg_pr_fu_briefly( rad->fu, "" );
03631 }
03632 }
03633
03634
03635 while( BU_LIST_WHILE( rad, nmg_radial, &list ) ) {
03636 BU_LIST_DEQUEUE( &rad->l );
03637 bu_free( (char *)rad, "nmg_radial" );
03638 }
03639 return nflip;
03640 #endif
03641 }
03642
03643
03644
03645
03646
03647
03648 void
03649 nmg_s_radial_check(struct shell *s, const struct bn_tol *tol)
03650 {
03651 struct bu_ptbl edges;
03652 struct edgeuse *eu;
03653 struct edge **ep;
03654
03655 NMG_CK_SHELL(s);
03656 BN_CK_TOL(tol);
03657
03658 if( rt_g.NMG_debug & DEBUG_BASIC )
03659 bu_log("nmg_s_radial_check( s=x%x ) BEGIN\n", s);
03660
03661 nmg_edge_tabulate( &edges, &s->l.magic );
03662 for( ep = (struct edge **)BU_PTBL_LASTADDR(&edges);
03663 ep >= (struct edge **)BU_PTBL_BASEADDR(&edges); ep--
03664 ) {
03665 NMG_CK_EDGE(*ep);
03666 eu = nmg_find_ot_same_eu_of_e( *ep );
03667 nmg_eu_radial_check( eu, s, tol );
03668 }
03669
03670 bu_ptbl_free( &edges);
03671
03672 if( rt_g.NMG_debug & DEBUG_BASIC )
03673 bu_log("nmg_s_radial_check( s=x%x ) END\n", s);
03674 }
03675
03676
03677
03678
03679 void
03680 nmg_r_radial_check(const struct nmgregion *r, const struct bn_tol *tol)
03681 {
03682 struct shell *s;
03683
03684 NMG_CK_REGION(r);
03685 BN_CK_TOL(tol);
03686
03687 if( rt_g.NMG_debug & DEBUG_BASIC )
03688 bu_log("nmg_r_radial_check( r=x%x )\n", r);
03689
03690 for( BU_LIST_FOR( s, shell, &r->s_hd ) ) {
03691 NMG_CK_SHELL(s);
03692 nmg_s_radial_check( s, tol );
03693 }
03694 }
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704