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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #ifndef lint
00064 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_inter.c,v 14.13 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00065 #endif
00066
00067 #include "common.h"
00068
00069 #include <stddef.h>
00070 #include <stdio.h>
00071 #include <math.h>
00072 #include <string.h>
00073
00074 #include "machine.h"
00075 #include "vmath.h"
00076 #include "nmg.h"
00077 #include "raytrace.h"
00078 #include "./debug.h"
00079 #include "plot3.h"
00080
00081 #define ISECT_NONE 0
00082 #define ISECT_SHARED_V 1
00083 #define ISECT_SPLIT1 2
00084 #define ISECT_SPLIT2 4
00085
00086 struct ee_2d_state {
00087 struct nmg_inter_struct *is;
00088 struct edgeuse *eu;
00089 point_t start;
00090 point_t end;
00091 vect_t dir;
00092 };
00093
00094
00095 static int nmg_isect_edge2p_face2p BU_ARGS((struct nmg_inter_struct *is,
00096 struct edgeuse *eu, struct faceuse *fu,
00097 struct faceuse *eu_fu));
00098
00099
00100 static struct nmg_inter_struct *nmg_hack_last_is;
00101
00102
00103
00104 struct vertexuse *
00105 nmg_make_dualvu(struct vertex *v, struct faceuse *fu, const struct bn_tol *tol)
00106 {
00107 struct loopuse *lu;
00108 struct vertexuse *dualvu;
00109 struct edgeuse *new_eu;
00110
00111 NMG_CK_VERTEX( v );
00112 NMG_CK_FACEUSE( fu );
00113 BN_CK_TOL( tol );
00114
00115 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00116 bu_log( "nmg_make_dualvu( v=x%x, fu=x%x )\n", v, fu );
00117
00118
00119 if( (dualvu=nmg_find_v_in_face( v, fu )) )
00120 {
00121 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00122 bu_log( "\tdualvu already exists (x%x)\n", dualvu );
00123 return( dualvu );
00124 }
00125
00126 new_eu = (struct edgeuse *)NULL;
00127
00128
00129 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00130 bu_log( "\tLooking for an edge to split\n" );
00131 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
00132 {
00133 struct edgeuse *eu;
00134
00135 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00136 continue;
00137
00138 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
00139 {
00140 int code;
00141 fastf_t dist;
00142 point_t pca;
00143
00144 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00145 bu_log( "\tChecking eu x%x (%f %f %f) <-> (%f %f %f)\n",
00146 eu,
00147 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
00148 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
00149
00150 code = bn_dist_pt3_lseg3( &dist, pca,
00151 eu->vu_p->v_p->vg_p->coord,
00152 eu->eumate_p->vu_p->v_p->vg_p->coord,
00153 v->vg_p->coord, tol );
00154
00155 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00156 bu_log( "bn_dist_pt3_lseg3 returns %d, dist=%f\n", code, dist );
00157
00158 if( code > 2 )
00159 continue;
00160
00161
00162 if( code > 0 )
00163 continue;
00164
00165
00166 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00167 bu_log( "nmg_make_dualvu is splitting eu x%x at v x%x\n", eu, v );
00168 new_eu = nmg_esplit( v, eu, 1 );
00169 }
00170 }
00171
00172 if( new_eu )
00173 return( new_eu->vu_p );
00174
00175
00176 lu = nmg_mlv( &fu->l.magic, v, OT_BOOLPLACE );
00177 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00178 bu_log( "nmg_make_dualvu is makeing a self_loop (lu=x%x, vu=x%x) for v=x%x\n", lu, BU_LIST_FIRST( vertexuse, &lu->down_hd ), v );
00179 nmg_loop_g( lu->l_p, tol );
00180 return( BU_LIST_FIRST( vertexuse, &lu->down_hd ) );
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 struct vertexuse *
00210 nmg_enlist_vu(struct nmg_inter_struct *is, const struct vertexuse *vu, struct vertexuse *dualvu, fastf_t dist)
00211
00212
00213
00214
00215 {
00216 struct shell *sv;
00217 struct loopuse *lu;
00218 struct faceuse *dualfu = (struct faceuse *)NULL;
00219 struct shell *duals = (struct shell *)NULL;
00220 struct faceuse *fuv;
00221
00222 NMG_CK_INTER_STRUCT(is);
00223 NMG_CK_VERTEXUSE(vu);
00224 if(dualvu) {
00225 NMG_CK_VERTEXUSE(dualvu);
00226 if( vu == dualvu ) rt_bomb("nmg_enlist_vu() vu == dualvu\n");
00227 }
00228
00229 if( is->mag_len <= BU_PTBL_END( is->l1 ) || is->mag_len <= BU_PTBL_END( is->l2 ) )
00230 bu_log( "Array for distances to vertexuses is too small (%d)\n" , is->mag_len );
00231
00232 #if 0
00233
00234 if( bn_distsq_line3_pt3(is->pt, is->dir, vu->v_p->vg_p->coord) > is->tol.dist_sq ) {
00235 bu_log("nmg_enlist_vu() WARNING: vu=x%x, v=x%x not within tolerance of intersect line\n",
00236 vu, vu->v_p);
00237 }
00238 #endif
00239
00240 sv = nmg_find_s_of_vu( vu );
00241 fuv = nmg_find_fu_of_vu( vu );
00242
00243
00244 if( sv == is->s1 ) {
00245 bu_ptbl_ins_unique( is->l1, (long *)&vu->l.magic );
00246 if( is->mag_len <= BU_PTBL_END( is->l1 ) )
00247 {
00248 if( is->mag_len )
00249 {
00250 is->mag_len *= 2;
00251 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
00252 "is->mag1" );
00253 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
00254 "is->mag2" );
00255 }
00256 else
00257 {
00258 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
00259 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
00260 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
00261 }
00262
00263 }
00264 if( dist < MAX_FASTF )
00265 is->mag1[bu_ptbl_locate( is->l1, (long *)&vu->l.magic )] = dist;
00266 duals = is->s2;
00267 dualfu = is->fu2;
00268 if( is->fu1 && is->fu1->s_p != is->s1 ) rt_bomb("nmg_enlist_vu() fu1/s1 mismatch\n");
00269 if( fuv != is->fu1 ) {
00270 bu_log("fuv=x%x, fu1=x%x, fu2=x%x\n", fuv, is->fu1, is->fu2);
00271 bu_log( "\tvu=x%x (x%x)\n", vu, vu->v_p );
00272 rt_bomb("nmg_enlist_vu() vu/fu1 mis-match\n");
00273 }
00274 } else if( sv == is->s2 ) {
00275 bu_ptbl_ins_unique( is->l2, (long *)&vu->l.magic );
00276 if( is->mag_len <= BU_PTBL_END( is->l2 ) )
00277 {
00278 if( is->mag_len )
00279 {
00280 is->mag_len *= 2;
00281 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
00282 "is->mag1" );
00283 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
00284 "is->mag2" );
00285 }
00286 else
00287 {
00288 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
00289 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
00290 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
00291 }
00292
00293 }
00294 if( dist < MAX_FASTF )
00295 is->mag2[bu_ptbl_locate( is->l2, (long *)&vu->l.magic )] = dist;
00296 duals = is->s1;
00297 dualfu = is->fu1;
00298 if( is->fu2 && is->fu2->s_p != is->s2 ) rt_bomb("nmg_enlist_vu() fu2/s2 mismatch\n");
00299 if( fuv != is->fu2 ) {
00300 bu_log("fuv=x%x, fu1=x%x, fu2=x%x\n", fuv, is->fu1, is->fu2);
00301 bu_log( "\tvu=x%x (x%x)\n", vu, vu->v_p );
00302 rt_bomb("nmg_enlist_vu() vu/fu2 mis-match\n");
00303 }
00304 } else {
00305 bu_log("nmg_enlist_vu(vu=x%x,dv=x%x) sv=x%x, s1=x%x, s2=x%x\n",
00306 vu, dualvu, sv, is->s1, is->s2 );
00307 rt_bomb("nmg_enlist_vu: vu is not in s1 or s2\n");
00308 }
00309
00310 if( dualvu ) {
00311 if( vu->v_p != dualvu->v_p ) rt_bomb("nmg_enlist_vu() dual vu has different vertex\n");
00312 if( nmg_find_s_of_vu(dualvu) != duals ) {
00313 bu_log("nmg_enlist_vu(vu=x%x,dv=x%x) sv=x%x, s1=x%x, s2=x%x, sdual=x%x\n",
00314 vu, dualvu,
00315 sv, is->s1, is->s2, nmg_find_s_of_vu(dualvu) );
00316 rt_bomb("nmg_enlist_vu() dual vu shell mis-match\n");
00317 }
00318 if( dualfu && nmg_find_fu_of_vu(dualvu) != dualfu) rt_bomb("nmg_enlist_vu() dual vu has wrong fu\n");
00319 }
00320
00321
00322 if( dualfu ) {
00323 NMG_CK_FACEUSE(dualfu);
00324 if( dualfu->s_p != duals ) rt_bomb("nmg_enlist_vu() dual fu's shell is not dual's shell?\n");
00325 if( !dualvu )
00326 dualvu = nmg_make_dualvu( vu->v_p, dualfu, &(is->tol) );
00327 else {
00328 if( rt_g.NMG_debug & DEBUG_POLYSECT ) {
00329 bu_log("nmg_enlist_vu(vu=x%x,dv=x%x) re-using dualvu=x%x from dualfu=x%x\n",
00330 vu, dualvu,
00331 dualvu, dualfu);
00332 }
00333 }
00334 } else {
00335
00336 bu_log("\tvu=x%x, %s, fu1=x%x, fu2=x%x\n", vu, (sv==is->s1)?"shell 1":"shell 2", is->fu1, is->fu2);
00337 bu_log("nmg_enlist_vu(): QUESTION: What do I search for wire intersections? Making self-loop\n");
00338 if( !dualvu && !(dualvu = nmg_find_v_in_shell( vu->v_p, duals, 0 )) ) {
00339
00340 lu = nmg_mlv( &duals->l.magic, vu->v_p, OT_BOOLPLACE );
00341 nmg_loop_g( lu->l_p, &(is->tol) );
00342 dualvu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
00343 } else {
00344 if( rt_g.NMG_debug & DEBUG_POLYSECT ) {
00345 bu_log("nmg_enlist_vu(vu=x%x) re-using dualvu=x%x from dualshell=x%x\n",
00346 vu,
00347 dualvu, duals);
00348 }
00349 }
00350 }
00351 NMG_CK_VERTEXUSE(dualvu);
00352
00353
00354 if( sv == is->s1 ) {
00355 bu_ptbl_ins_unique( is->l2, (long *)&dualvu->l.magic );
00356 if( is->mag_len <= BU_PTBL_END( is->l2 ) )
00357 {
00358 if( is->mag_len )
00359 {
00360 is->mag_len *= 2;
00361 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
00362 "is->mag1" );
00363 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
00364 "is->mag2" );
00365 }
00366 else
00367 {
00368 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
00369 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
00370 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
00371 }
00372
00373 }
00374 if( dist < MAX_FASTF )
00375 is->mag2[bu_ptbl_locate( is->l2, (long *)&dualvu->l.magic )] = dist;
00376 } else {
00377 bu_ptbl_ins_unique( is->l1, (long *)&dualvu->l.magic );
00378 if( is->mag_len <= BU_PTBL_END( is->l1 ) )
00379 {
00380 if( is->mag_len )
00381 {
00382 is->mag_len *= 2;
00383 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
00384 "is->mag1" );
00385 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
00386 "is->mag2" );
00387 }
00388 else
00389 {
00390 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
00391 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
00392 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
00393 }
00394
00395 }
00396 if( dist < MAX_FASTF )
00397 is->mag1[bu_ptbl_locate( is->l1, (long *)&dualvu->l.magic )] = dist;
00398 }
00399
00400 if( rt_g.NMG_debug & DEBUG_POLYSECT ) {
00401 bu_log("nmg_enlist_vu(vu=x%x,dv=x%x) v=x%x, dist=%g (%s) ret=x%x\n",
00402 vu, dualvu, vu->v_p, dist,
00403 (sv == is->s1) ? "shell 1" : "shell 2",
00404 dualvu );
00405 }
00406
00407
00408 if( (rt_g.NMG_debug & DEBUG_VERIFY) && is->fu1 && is->fu2 ) {
00409 nmg_ck_v_in_2fus(vu->v_p, is->fu1, is->fu2, &(is->tol));
00410 }
00411 return dualvu;
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 static void
00432 nmg_get_2d_vertex(fastf_t *v2d, struct vertex *v, struct nmg_inter_struct *is, const long int *assoc_use)
00433
00434
00435
00436
00437 {
00438 register fastf_t *pt2d;
00439 point_t pt;
00440 struct vertex_g *vg;
00441 long *this;
00442
00443 NMG_CK_INTER_STRUCT(is);
00444 NMG_CK_VERTEX(v);
00445
00446
00447 if( !is->vert2d ) {
00448 nmg_isect2d_prep( is, assoc_use );
00449 }
00450
00451 if( *assoc_use == NMG_FACEUSE_MAGIC ) {
00452 this = &((struct faceuse *)assoc_use)->f_p->l.magic;
00453 if( this != is->twod )
00454 goto bad;
00455 } else if ( *assoc_use == NMG_EDGEUSE_MAGIC ) {
00456 this = &((struct edgeuse *)assoc_use)->e_p->magic;
00457 if( this != is->twod )
00458 goto bad;
00459 } else {
00460 this = (long *)NULL;
00461 bad:
00462 bu_log("nmg_get_2d_vertex(,assoc_use=%x %s) this=x%x %s, is->twod=%x %s\n",
00463 assoc_use, bu_identify_magic(*assoc_use),
00464 this, bu_identify_magic(*this),
00465 is->twod, bu_identify_magic(*(is->twod)) );
00466 rt_bomb("nmg_get_2d_vertex: 2d association mis-match\n");
00467 }
00468
00469 if( !v->vg_p ) {
00470 bu_log("nmg_get_2d_vertex: v=x%x, assoc_use=x%x, null vg_p\n",
00471 v, assoc_use);
00472 rt_bomb("nmg_get_2d_vertex: vertex with no geometry!\n");
00473 }
00474 vg = v->vg_p;
00475 NMG_CK_VERTEX_G(vg);
00476 if( v->index >= is->maxindex ) {
00477 struct model *m;
00478 int oldmax;
00479 register int i;
00480
00481 oldmax = is->maxindex;
00482 m = nmg_find_model(&v->magic);
00483 NMG_CK_MODEL(m);
00484 bu_log("nmg_get_2d_vertex: v=x%x, v->index=%d, is->maxindex=%d, m->maxindex=%d\n",
00485 v, v->index, is->maxindex, m->maxindex );
00486 if( v->index >= m->maxindex ) {
00487
00488 VPRINT("3d vertex", vg->coord);
00489 rt_bomb("nmg_get_2d_vertex: array overrun\n");
00490 }
00491
00492 is->maxindex = m->maxindex * 4;
00493 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
00494 bu_log("nmg_get_2d_vertex() extending vert2d array from %d to %d points (m max=%d)\n",
00495 oldmax, is->maxindex, m->maxindex);
00496 }
00497 is->vert2d = (fastf_t *)rt_realloc( (char *)is->vert2d,
00498 is->maxindex * 3 * sizeof(fastf_t), "vert2d[]");
00499
00500
00501 for( i = (3*is->maxindex)-1-2; i >= oldmax*3; i -= 3 ) {
00502 VSET( &is->vert2d[i], 0, 0, -1 );
00503 }
00504 }
00505 pt2d = &is->vert2d[v->index*3];
00506 if( pt2d[2] == 0 ) {
00507
00508 v2d[0] = pt2d[0];
00509 v2d[1] = pt2d[1];
00510 v2d[2] = 0;
00511 return;
00512 }
00513
00514 MAT4X3PNT( pt, is->proj, vg->coord );
00515 v2d[0] = pt2d[0] = pt[0];
00516 v2d[1] = pt2d[1] = pt[1];
00517 v2d[2] = pt2d[2] = 0;
00518
00519 if( !NEAR_ZERO( pt[2], is->tol.dist ) ) {
00520 struct faceuse *fu = (struct faceuse *)assoc_use;
00521 plane_t n;
00522 fastf_t dist;
00523 NMG_GET_FU_PLANE( n, fu );
00524 dist = DIST_PT_PLANE(vg->coord, n);
00525 bu_log("nmg_get_2d_vertex ERROR #%d (%g %g %g) becomes (%g,%g)\n\t%g != zero, dist3d=%g, %g*tol\n",
00526 v->index, V3ARGS(vg->coord), V3ARGS(pt),
00527 dist, dist/is->tol.dist );
00528 if( !NEAR_ZERO( dist, is->tol.dist ) &&
00529 !NEAR_ZERO( pt[2], 10*is->tol.dist ) ) {
00530 bu_log("nmg_get_2d_vertex(,assoc_use=%x) f=x%x, is->twod=%x\n",
00531 assoc_use, fu->f_p, is->twod);
00532 PLPRINT("fu->f_p N", n);
00533 rt_bomb("3D->2D point projection error\n");
00534 }
00535 }
00536
00537 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
00538 bu_log("2d #%d (%g %g %g) becomes (%g,%g) %g\n",
00539 v->index, V3ARGS(vg->coord), V3ARGS(pt) );
00540 }
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 void
00564 nmg_isect2d_prep(struct nmg_inter_struct *is, const long int *assoc_use)
00565 {
00566 struct model *m;
00567 struct face_g_plane *fg;
00568 vect_t to;
00569 point_t centroid;
00570 point_t centroid_proj;
00571 plane_t n;
00572 register int i;
00573
00574 NMG_CK_INTER_STRUCT(is);
00575
00576 if( *assoc_use == NMG_FACEUSE_MAGIC ) {
00577 if( &((struct faceuse *)assoc_use)->f_p->l.magic == is->twod )
00578 return;
00579 } else if( *assoc_use == NMG_EDGEUSE_MAGIC ) {
00580 if( &((struct edgeuse *)assoc_use)->e_p->magic == is->twod )
00581 return;
00582 } else {
00583 rt_bomb("nmg_isect2d_prep() bad assoc_use magic\n");
00584 }
00585
00586 nmg_isect2d_cleanup(is);
00587 nmg_hack_last_is = is;
00588
00589 m = nmg_find_model( assoc_use );
00590
00591 is->maxindex = ( 2 * m->maxindex );
00592 is->vert2d = (fastf_t *)bu_malloc( is->maxindex * 3 * sizeof(fastf_t), "vert2d[]");
00593
00594 if( *assoc_use == NMG_FACEUSE_MAGIC ) {
00595 struct faceuse *fu1 = (struct faceuse *)assoc_use;
00596 struct face *f1;
00597
00598 f1 = fu1->f_p;
00599 fg = f1->g.plane_p;
00600 NMG_CK_FACE_G_PLANE(fg);
00601 is->twod = &f1->l.magic;
00602 if( f1->flip ) {
00603 VREVERSE( n, fg->N );
00604 n[3] = -fg->N[3];
00605 } else {
00606 HMOVE( n, fg->N );
00607 }
00608 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
00609 bu_log("nmg_isect2d_prep(f=x%x) flip=%d\n", f1, f1->flip);
00610 PLPRINT("N", n);
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 VSET( to, 0, 0, 1 );
00623 bn_mat_fromto( is->proj, n, to );
00624 VADD2SCALE( centroid, f1->max_pt, f1->min_pt, 0.5 );
00625 MAT4X3PNT( centroid_proj, is->proj, centroid );
00626 centroid_proj[Z] = n[3];
00627 MAT_DELTAS_VEC_NEG( is->proj, centroid_proj );
00628 } else if( *assoc_use == NMG_EDGEUSE_MAGIC ) {
00629 struct edgeuse *eu1 = (struct edgeuse *)assoc_use;
00630 struct edge *e1;
00631 struct edge_g_lseg *eg;
00632
00633 bu_log("2d prep for edgeuse\n");
00634 e1 = eu1->e_p;
00635 NMG_CK_EDGE(e1);
00636 eg = eu1->g.lseg_p;
00637 NMG_CK_EDGE_G_LSEG(eg);
00638 is->twod = &e1->magic;
00639
00640
00641
00642
00643
00644
00645
00646 VSET( to, 1, 0, 0 );
00647 bn_mat_fromto( is->proj, eg->e_dir, to );
00648 MAT_DELTAS_VEC_NEG( is->proj, eg->e_pt );
00649 } else {
00650 rt_bomb("nmg_isect2d_prep() bad assoc_use magic\n");
00651 }
00652
00653
00654 for( i = (3*is->maxindex)-1-2; i >= 0; i -= 3 ) {
00655 VSET( &is->vert2d[i], 0, 0, -1 );
00656 }
00657 }
00658
00659
00660
00661
00662
00663
00664 void
00665 nmg_isect2d_cleanup(struct nmg_inter_struct *is)
00666 {
00667 NMG_CK_INTER_STRUCT(is);
00668
00669 nmg_hack_last_is = (struct nmg_inter_struct *)NULL;
00670
00671 if( !is->vert2d ) return;
00672 bu_free( (char *)is->vert2d, "vert2d");
00673 is->vert2d = (fastf_t *)NULL;
00674 is->twod = (long *)NULL;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 void
00688 nmg_isect2d_final_cleanup(void)
00689 {
00690 if( nmg_hack_last_is && nmg_hack_last_is->magic == NMG_INTER_STRUCT_MAGIC )
00691 nmg_isect2d_cleanup( nmg_hack_last_is );
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 void
00712 nmg_isect_vert2p_face2p(struct nmg_inter_struct *is, struct vertexuse *vu1, struct faceuse *fu2)
00713 {
00714 struct vertexuse *vu2;
00715 struct loopuse *lu2;
00716 pointp_t pt;
00717 int ret = 0;
00718
00719 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00720 bu_log("nmg_isect_vert2p_face2p(, vu1=x%x, fu2=x%x)\n", vu1, fu2);
00721 NMG_CK_INTER_STRUCT(is);
00722 NMG_CK_VERTEXUSE(vu1);
00723 NMG_CK_FACEUSE(fu2);
00724
00725 pt = vu1->v_p->vg_p->coord;
00726
00727
00728 nmg_isect2d_prep( is, &fu2->l.magic );
00729
00730
00731 for( BU_LIST_FOR( lu2, loopuse, &fu2->lu_hd ) ) {
00732 struct edgeuse *eu2;
00733
00734 NMG_CK_LOOPUSE(lu2);
00735 if( BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC ) {
00736 vu2 = BU_LIST_FIRST( vertexuse, &lu2->down_hd );
00737 if( vu1->v_p == vu2->v_p ) {
00738
00739 if( is->l1 ) nmg_enlist_vu( is, vu1, vu2, MAX_FASTF );
00740 ret++;
00741 continue;
00742 }
00743
00744 if( bn_pt3_pt3_equal( pt, vu2->v_p->vg_p->coord, &is->tol ) ) {
00745
00746 nmg_jv( vu1->v_p, vu2->v_p );
00747 if( is->l1 ) nmg_enlist_vu( is, vu1, vu2, MAX_FASTF );
00748 ret++;
00749 continue;
00750 }
00751 continue;
00752 }
00753 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) ) {
00754 struct edgeuse *new_eu;
00755
00756 if( eu2->vu_p->v_p == vu1->v_p ) {
00757 if( is->l1 ) nmg_enlist_vu( is, vu1, eu2->vu_p, MAX_FASTF );
00758 ret++;
00759 continue;
00760 }
00761
00762 new_eu = nmg_break_eu_on_v(eu2, vu1->v_p, fu2, is);
00763 if ( new_eu )
00764 {
00765 if( is->l1 ) nmg_enlist_vu( is, vu1, new_eu->vu_p, MAX_FASTF );
00766 ret++;
00767 continue;
00768 }
00769 }
00770 }
00771
00772 if( ret == 0 ) {
00773
00774 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00775 VPRINT("Making vertexloop", pt);
00776
00777 lu2 = nmg_mlv(&fu2->l.magic, vu1->v_p, OT_BOOLPLACE);
00778 nmg_loop_g( lu2->l_p, &is->tol );
00779 vu2 = BU_LIST_FIRST( vertexuse, &lu2->down_hd );
00780 if(is->l1) nmg_enlist_vu( is, vu1, vu2, MAX_FASTF );
00781 }
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 static void
00795 nmg_isect_3vertex_3face(struct nmg_inter_struct *is, struct vertexuse *vu, struct faceuse *fu)
00796 {
00797 struct vertexuse *vup;
00798 pointp_t pt;
00799 fastf_t dist;
00800 plane_t n;
00801
00802 NMG_CK_INTER_STRUCT(is);
00803 NMG_CK_VERTEXUSE(vu);
00804 NMG_CK_VERTEX(vu->v_p);
00805 NMG_CK_FACEUSE(fu);
00806
00807 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00808 bu_log("nmg_isect_3vertex_3face(, vu=x%x, fu=x%x) v=x%x\n", vu, fu, vu->v_p);
00809
00810
00811 vup=nmg_find_v_in_face(vu->v_p, fu);
00812 if (vup) {
00813 if (rt_g.NMG_debug & DEBUG_POLYSECT) bu_log("\tvu lies in face (topology 1)\n");
00814 (void)bu_ptbl_ins_unique(is->l1, &vu->l.magic);
00815 (void)bu_ptbl_ins_unique(is->l2, &vup->l.magic);
00816 return;
00817 }
00818
00819
00820
00821
00822
00823 pt = vu->v_p->vg_p->coord;
00824 NMG_GET_FU_PLANE( n, fu );
00825 dist = DIST_PT_PLANE(pt, n);
00826
00827 if ( !NEAR_ZERO(dist, is->tol.dist) ) {
00828 if (rt_g.NMG_debug & DEBUG_POLYSECT) bu_log("\tvu not on face (geometry)\n");
00829 return;
00830 }
00831
00832
00833
00834
00835
00836 (void)nmg_isect_vert2p_face2p( is, vu, fu );
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 static struct vertexuse *
00850 nmg_break_3edge_at_plane(const fastf_t *hit_pt, struct faceuse *fu2, struct nmg_inter_struct *is, struct edgeuse *eu1)
00851
00852
00853
00854
00855 {
00856 struct vertexuse *vu1_final;
00857 struct vertexuse *vu2_final;
00858 struct vertex *v2;
00859 struct loopuse *plu2;
00860 struct edgeuse *eu1forw;
00861 struct vertex *v1;
00862 struct vertex *v1mate;
00863 fastf_t dist;
00864
00865 NMG_CK_INTER_STRUCT(is);
00866 NMG_CK_EDGEUSE(eu1);
00867
00868 v1 = eu1->vu_p->v_p;
00869 NMG_CK_VERTEX(v1);
00870 v1mate = eu1->eumate_p->vu_p->v_p;
00871 NMG_CK_VERTEX(v1mate);
00872
00873
00874
00875
00876 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
00877 bu_log("nmg_break_3edge_at_plane() Splitting %g, %g, %g <-> %g, %g, %g\n",
00878 V3ARGS(v1->vg_p->coord),
00879 V3ARGS(v1mate->vg_p->coord) );
00880 VPRINT("\tAt point of intersection", hit_pt);
00881 }
00882
00883
00884 if( bn_pt3_pt3_equal( hit_pt, v1->vg_p->coord, &is->tol ) )
00885 rt_bomb("nmg_break_3edge_at_plane() hit_pt equal to v1\n");
00886 if( bn_pt3_pt3_equal( hit_pt, v1mate->vg_p->coord, &is->tol ) )
00887 rt_bomb("nmg_break_3edge_at_plane() hit_pt equal to v1mate\n");
00888
00889 {
00890 vect_t va, vb;
00891 VSUB2( va, hit_pt, eu1->vu_p->v_p->vg_p->coord );
00892 VSUB2( vb, eu1->eumate_p->vu_p->v_p->vg_p->coord, hit_pt );
00893 VUNITIZE(va);
00894 VUNITIZE(vb);
00895 if( VDOT( va, vb ) <= 0.7071 ) {
00896 rt_bomb("nmg_break_3edge_at_plane() eu1 changes direction?\n");
00897 }
00898 }
00899 {
00900 struct bn_tol t2;
00901 t2 = is->tol;
00902
00903 t2.dist = is->tol.dist * 4;
00904 t2.dist_sq = t2.dist * t2.dist;
00905 dist = DIST_PT_PT(hit_pt, v1->vg_p->coord);
00906 if( bn_pt3_pt3_equal( hit_pt, v1->vg_p->coord, &t2 ) )
00907 bu_log("NOTICE: nmg_break_3edge_at_plane() hit_pt nearly equal to v1 %g*tol\n", dist/is->tol.dist);
00908 dist = DIST_PT_PT(hit_pt, v1mate->vg_p->coord);
00909 if( bn_pt3_pt3_equal( hit_pt, v1mate->vg_p->coord, &t2 ) )
00910 bu_log("NOTICE: nmg_break_3edge_at_plane() hit_pt nearly equal to v1mate %g*tol\n", dist/is->tol.dist);
00911 }
00912
00913
00914
00915
00916
00917
00918 v2 = nmg_find_pt_in_model(fu2->s_p->r_p->m_p, hit_pt, &(is->tol));
00919 if (v2) {
00920
00921 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00922 bu_log("re-using vertex v=x%x from other shell\n", v2);
00923
00924 eu1forw = nmg_ebreaker(v2, eu1, &(is->tol));
00925 vu1_final = eu1forw->vu_p;
00926 vu2_final = nmg_enlist_vu( is, vu1_final, 0, MAX_FASTF );
00927 } else {
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 int class;
00938 class = nmg_class_pt_fu_except( hit_pt, fu2,
00939 (struct loopuse *)NULL,
00940 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0,
00941 0, &is->tol );
00942 if( class == NMG_CLASS_AoutB ) {
00943
00944 #if 0
00945 bu_log("%%%%%% point is outside face loop, no need to break eu1?\n");
00946 return (struct vertexuse *)NULL;
00947 #endif
00948
00949
00950
00951
00952 }
00953
00954 eu1forw = nmg_ebreaker((struct vertex *)NULL, eu1, &is->tol);
00955 vu1_final = eu1forw->vu_p;
00956 nmg_vertex_gv(vu1_final->v_p, hit_pt);
00957 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00958 bu_log("Made new vertex vu=x%x, v=x%x\n", vu1_final, vu1_final->v_p);
00959
00960 NMG_CK_VERTEX_G(eu1->vu_p->v_p->vg_p);
00961 NMG_CK_VERTEX_G(eu1->eumate_p->vu_p->v_p->vg_p);
00962 NMG_CK_VERTEX_G(eu1forw->vu_p->v_p->vg_p);
00963 NMG_CK_VERTEX_G(eu1forw->eumate_p->vu_p->v_p->vg_p);
00964
00965 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
00966 register pointp_t p1 = eu1->vu_p->v_p->vg_p->coord;
00967 register pointp_t p2 = eu1->eumate_p->vu_p->v_p->vg_p->coord;
00968
00969 bu_log("After split eu1 x%x= %g, %g, %g -> %g, %g, %g\n",
00970 eu1,
00971 V3ARGS(p1), V3ARGS(p2) );
00972 p1 = eu1forw->vu_p->v_p->vg_p->coord;
00973 p2 = eu1forw->eumate_p->vu_p->v_p->vg_p->coord;
00974 bu_log("\teu1forw x%x = %g, %g, %g -> %g, %g, %g\n",
00975 eu1forw,
00976 V3ARGS(p1), V3ARGS(p2) );
00977 }
00978
00979 switch(class) {
00980 case NMG_CLASS_AinB:
00981
00982 break;
00983 case NMG_CLASS_AonBshared:
00984
00985 if (rt_g.NMG_debug & DEBUG_POLYSECT)
00986 bu_log("%%%%%% point is on loop boundary. Break fu2 loop too?\n");
00987 nmg_isect_3vertex_3face( is, vu1_final, fu2 );
00988
00989 vu2_final = nmg_find_v_in_face( vu1_final->v_p, fu2 );
00990 if( !vu2_final ) rt_bomb("%%%%%% missed!\n");
00991 NMG_CK_VERTEXUSE(vu2_final);
00992 nmg_enlist_vu( is, vu1_final, vu2_final, MAX_FASTF );
00993 return vu2_final;
00994 case NMG_CLASS_AoutB:
00995
00996 break;
00997 default:
00998 rt_bomb("nmg_break_3edge_at_plane() bad classification return from nmg_class_pt_f()\n");
00999 }
01000
01001
01002
01003
01004
01005 plu2 = nmg_mlv(&fu2->l.magic, vu1_final->v_p, OT_BOOLPLACE);
01006 vu2_final = BU_LIST_FIRST( vertexuse, &plu2->down_hd );
01007 NMG_CK_VERTEXUSE(vu2_final);
01008 nmg_loop_g(plu2->l_p, &is->tol);
01009
01010 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01011 bu_log("Made vertexloop in other face. lu=x%x vu=x%x on v=x%x\n",
01012 plu2,
01013 vu2_final, vu2_final->v_p);
01014 }
01015 vu2_final = nmg_enlist_vu( is, vu1_final, vu2_final, MAX_FASTF );
01016 }
01017
01018 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01019 register pointp_t p1, p2;
01020 p1 = eu1->vu_p->v_p->vg_p->coord;
01021 p2 = eu1->eumate_p->vu_p->v_p->vg_p->coord;
01022 bu_log("\tNow %g, %g, %g <-> %g, %g, %g\n",
01023 V3ARGS(p1), V3ARGS(p2) );
01024 p1 = eu1forw->vu_p->v_p->vg_p->coord;
01025 p2 = eu1forw->eumate_p->vu_p->v_p->vg_p->coord;
01026 bu_log("\tand %g, %g, %g <-> %g, %g, %g\n\n",
01027 V3ARGS(p1), V3ARGS(p2) );
01028 }
01029 return vu2_final;
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 struct edgeuse *
01055 nmg_break_eu_on_v(struct edgeuse *eu1, struct vertex *v2, struct faceuse *fu, struct nmg_inter_struct *is)
01056
01057
01058
01059
01060 {
01061 point_t a;
01062 point_t b;
01063 point_t p;
01064 int code;
01065 fastf_t dist;
01066 struct vertex *v1a;
01067 struct vertex *v1b;
01068 struct edgeuse *new_eu = (struct edgeuse *)0;
01069
01070 NMG_CK_EDGEUSE(eu1);
01071 NMG_CK_VERTEX(v2);
01072 NMG_CK_FACEUSE(fu);
01073 NMG_CK_INTER_STRUCT(is);
01074
01075 v1a = eu1->vu_p->v_p;
01076 v1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p->v_p;
01077
01078
01079 if( v1a == v2 || v1b == v2 ) {
01080 goto out;
01081 }
01082
01083
01084 nmg_get_2d_vertex( a, v1a, is, &fu->l.magic );
01085 nmg_get_2d_vertex( b, v1b, is, &fu->l.magic );
01086 nmg_get_2d_vertex( p, v2, is, &fu->l.magic );
01087
01088 dist = -INFINITY;
01089 code = bn_isect_pt2_lseg2( &dist, a, b, p, &(is->tol) );
01090
01091 switch(code) {
01092 case -2:
01093
01094 break;
01095 default:
01096 case -1:
01097
01098 #if 0
01099
01100 V2PRINT("a", a);
01101 V2PRINT("p", p);
01102 V2PRINT("b", b);
01103 VPRINT("A", v1a->vg_p->coord);
01104 VPRINT("P", v2->vg_p->coord);
01105 VPRINT("B", v1b->vg_p->coord);
01106 rt_bomb("nmg_break_eu_on_v() P not on line?\n");
01107 #endif
01108 break;
01109 case 1:
01110
01111 nmg_jv( v2, v1a );
01112 break;
01113 case 2:
01114
01115 nmg_jv( v2, v1b );
01116 break;
01117 case 3:
01118
01119 new_eu = nmg_ebreaker( v2, eu1, &is->tol );
01120 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01121 bu_log("nmg_break_eu_on_v() breaking eu=x%x on v=x%x, new_eu=x%x\n",
01122 eu1, v2, new_eu );
01123 }
01124 break;
01125 }
01126
01127 out:
01128 return new_eu;
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 void
01143 nmg_break_eg_on_v(const struct edge_g_lseg *eg, struct vertex *v, const struct bn_tol *tol)
01144 {
01145 register struct edgeuse **eup;
01146 struct bu_ptbl eutab;
01147 vect_t dir;
01148 double vdist;
01149
01150 NMG_CK_EDGE_G_LSEG(eg);
01151 NMG_CK_VERTEX(v);
01152 BN_CK_TOL(tol);
01153
01154 VMOVE( dir, eg->e_dir );
01155 VUNITIZE( dir );
01156 vdist = bn_dist_pt3_along_line3( eg->e_pt, dir, v->vg_p->coord );
01157
01158
01159
01160
01161 nmg_edgeuse_with_eg_tabulate( &eutab, eg );
01162
01163 for( eup = (struct edgeuse **)BU_PTBL_LASTADDR(&eutab);
01164 eup >= (struct edgeuse **)BU_PTBL_BASEADDR(&eutab);
01165 eup--
01166 ) {
01167 struct vertex *va;
01168 struct vertex *vb;
01169 double a;
01170 double b;
01171 struct edgeuse *new_eu;
01172
01173 NMG_CK_EDGEUSE(*eup);
01174 if( (*eup)->g.lseg_p != eg ) rt_bomb("nmg_break_eg_on_v() eu disowns eg\n");
01175
01176 va = (*eup)->vu_p->v_p;
01177 vb = (*eup)->eumate_p->vu_p->v_p;
01178 if( v == va || v == vb ) continue;
01179 if( bn_pt3_pt3_equal( v->vg_p->coord, va->vg_p->coord, tol ) ) {
01180 nmg_jv( v, va );
01181 continue;
01182 }
01183 if( bn_pt3_pt3_equal( v->vg_p->coord, vb->vg_p->coord, tol ) ) {
01184 nmg_jv( v, vb );
01185 continue;
01186 }
01187 a = bn_dist_pt3_along_line3( eg->e_pt, dir, va->vg_p->coord );
01188 b = bn_dist_pt3_along_line3( eg->e_pt, dir, vb->vg_p->coord );
01189 if( NEAR_ZERO( a-vdist, tol->dist ) ) continue;
01190 if( NEAR_ZERO( b-vdist, tol->dist ) ) continue;
01191 if( !bn_between( a, vdist, b, tol ) ) continue;
01192 new_eu = nmg_ebreaker( v, *eup, tol );
01193 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01194 bu_log("nmg_break_eg_on_v( eg=x%x, v=x%x ) new_eu=x%x\n",
01195 eg, v, new_eu );
01196 }
01197 }
01198 bu_ptbl_free( &eutab);
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239 int
01240 nmg_isect_2colinear_edge2p(struct edgeuse *eu1, struct edgeuse *eu2, struct faceuse *fu, struct nmg_inter_struct *is, struct bu_ptbl *l1, struct bu_ptbl *l2)
01241
01242
01243
01244
01245
01246
01247 {
01248 struct edgeuse *eu[10];
01249 struct vertexuse *vu[4];
01250 register int i;
01251 register int j;
01252 int neu;
01253
01254 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01255 bu_log("nmg_isect_2colinear_edge2p(eu1=x%x, eu2=x%x) START\n",
01256 eu1, eu2);
01257 }
01258
01259 NMG_CK_EDGEUSE(eu1);
01260 NMG_CK_EDGEUSE(eu2);
01261 NMG_CK_FACEUSE(fu);
01262 NMG_CK_INTER_STRUCT(is);
01263 if( l1 ) BU_CK_PTBL(l1);
01264 if( l2 ) BU_CK_PTBL(l2);
01265
01266 vu[0] = eu1->vu_p;
01267 vu[1] = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
01268 vu[2] = eu2->vu_p;
01269 vu[3] = BU_LIST_PNEXT_CIRC( edgeuse, eu2 )->vu_p;
01270
01271 eu[0] = eu1;
01272 eu[1] = eu2;
01273 neu = 2;
01274
01275 for( i=0; i < neu; i++ ) {
01276 for( j=0; j<4; j++ ) {
01277 eu[neu] = nmg_break_eu_on_v(eu[i],vu[j]->v_p,fu,is);
01278 if( eu[neu] ) {
01279 nmg_enlist_vu( is, eu[neu]->vu_p, vu[j], MAX_FASTF );
01280 if( l1 && eu[neu]->e_p == eu1->e_p )
01281 bu_ptbl_ins_unique(l1, &eu[neu]->l.magic );
01282 else if( l2 && eu[neu]->e_p == eu2->e_p )
01283 bu_ptbl_ins_unique(l2, &eu[neu]->l.magic );
01284 neu++;
01285 }
01286 }
01287 }
01288
01289
01290
01291
01292 for( i=0; i < neu-1; i++ ) {
01293 for( j=i+1; j < neu; j++ ) {
01294 if( !NMG_ARE_EUS_ADJACENT(eu[i],eu[j]) ) continue;
01295 nmg_radial_join_eu( eu[i], eu[j], &(is->tol) );
01296 }
01297 }
01298
01299
01300 for( i=0; i < 4; i++ ) {
01301 for( j=0; j < 4; j++ ) {
01302 if( i==j ) continue;
01303 if( vu[i] == vu[j] ) continue;
01304 if( vu[i]->v_p == vu[j]->v_p ) {
01305 nmg_enlist_vu( is, vu[i], vu[j], MAX_FASTF );
01306 goto next_i;
01307 }
01308 }
01309
01310 nmg_enlist_vu( is, vu[i], 0, MAX_FASTF );
01311 next_i: ;
01312 }
01313
01314 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01315 bu_log("nmg_isect_2colinear_edge2p(eu1=x%x, eu2=x%x) ret #eu=%d\n",
01316 eu1, eu2, neu);
01317 }
01318 return neu;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 int
01337 nmg_isect_edge2p_edge2p(struct nmg_inter_struct *is, struct edgeuse *eu1, struct edgeuse *eu2, struct faceuse *fu1, struct faceuse *fu2)
01338
01339
01340
01341
01342
01343 {
01344 point_t eu1_start;
01345 point_t eu1_end;
01346 vect_t eu1_dir;
01347 point_t eu2_start;
01348 point_t eu2_end;
01349 vect_t eu2_dir;
01350 vect_t dir3d;
01351 fastf_t dist[2];
01352 int status;
01353 point_t hit_pt;
01354 struct vertexuse *vu;
01355 struct vertexuse *vu1a, *vu1b;
01356 struct vertexuse *vu2a, *vu2b;
01357 struct model *m;
01358 int ret = 0;
01359
01360 NMG_CK_INTER_STRUCT(is);
01361 NMG_CK_EDGEUSE(eu1);
01362 NMG_CK_EDGEUSE(eu2);
01363 m = nmg_find_model(&eu1->l.magic);
01364 NMG_CK_MODEL(m);
01365
01366
01367
01368
01369
01370 vu1a = eu1->vu_p;
01371 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
01372 vu2a = eu2->vu_p;
01373 vu2b = BU_LIST_PNEXT_CIRC( edgeuse, eu2 )->vu_p;
01374 NMG_CK_VERTEXUSE(vu1a);
01375 NMG_CK_VERTEXUSE(vu1b);
01376 NMG_CK_VERTEXUSE(vu2a);
01377 NMG_CK_VERTEXUSE(vu2b);
01378
01379 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01380 bu_log("nmg_isect_edge2p_edge2p(eu1=x%x, eu2=x%x) START\n\tfu1=x%x, fu2=x%x\n\tvu1a=%x vu1b=%x, vu2a=%x vu2b=%x\n\tv1a=%x v1b=%x, v2a=%x v2b=%x\n",
01381 eu1, eu2,
01382 fu1, fu2,
01383 vu1a, vu1b, vu2a, vu2b,
01384 vu1a->v_p, vu1b->v_p, vu2a->v_p, vu2b->v_p );
01385 }
01386
01387
01388
01389
01390
01391 if( vu1a->v_p == vu2a->v_p && vu1b->v_p == vu2b->v_p ) {
01392 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01393 bu_log("nmg_isect_edge2p_edge2p: shared edge topology, both ends\n");
01394 nmg_radial_join_eu(eu1, eu2, &is->tol );
01395 nmg_enlist_vu( is, vu1a, vu2a, MAX_FASTF );
01396 nmg_enlist_vu( is, vu1b, vu2b, MAX_FASTF );
01397 ret = ISECT_SHARED_V;
01398 goto out;
01399 }
01400 if( vu1a->v_p == vu2b->v_p && vu1b->v_p == vu2a->v_p ) {
01401 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01402 bu_log("nmg_isect_edge2p_edge2p: shared edge topology, both ends, reversed.\n");
01403 nmg_radial_join_eu(eu1, eu2, &is->tol );
01404 nmg_enlist_vu( is, vu1a, vu2b, MAX_FASTF );
01405 nmg_enlist_vu( is, vu1b, vu2a, MAX_FASTF );
01406 ret = ISECT_SHARED_V;
01407 goto out;
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 nmg_get_2d_vertex( eu1_start, vu1a->v_p, is, &fu2->l.magic );
01421 nmg_get_2d_vertex( eu1_end, vu1b->v_p, is, &fu2->l.magic );
01422 VSUB2_2D( eu1_dir, eu1_end, eu1_start );
01423
01424 nmg_get_2d_vertex( eu2_start, vu2a->v_p, is, &fu2->l.magic );
01425 nmg_get_2d_vertex( eu2_end, vu2b->v_p, is, &fu2->l.magic );
01426 VSUB2_2D( eu2_dir, eu2_end, eu2_start );
01427
01428 dist[0] = dist[1] = 0;
01429
01430
01431
01432
01433
01434
01435
01436 status = bn_isect_line2_lseg2( dist, eu1_start, eu1_dir,
01437 eu2_start, eu2_dir, &is->tol );
01438
01439 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01440 bu_log("\tbn_isect_line2_lseg2()=%d, dist: %g, %g\n",
01441 status, dist[0], dist[1] );
01442 }
01443
01444
01445
01446
01447
01448
01449
01450
01451 if( status != 0 &&
01452 (vu1a->v_p == vu2a->v_p || vu1a->v_p == vu2b->v_p ||
01453 vu1b->v_p == vu2a->v_p || vu1b->v_p == vu2b->v_p )
01454 ) {
01455 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01456 bu_log("edge2p_edge2p: non-colinear edges share one vertex (topology)\n");
01457 if( vu1a->v_p == vu2a->v_p )
01458 nmg_enlist_vu( is, vu1a, vu2a, MAX_FASTF );
01459 else if( vu1a->v_p == vu2b->v_p )
01460 nmg_enlist_vu( is, vu1a, vu2b, MAX_FASTF );
01461
01462 if( vu1b->v_p == vu2a->v_p )
01463 nmg_enlist_vu( is, vu1b, vu2a, MAX_FASTF );
01464 else if( vu1b->v_p == vu2b->v_p )
01465 nmg_enlist_vu( is, vu1b, vu2b, MAX_FASTF );
01466
01467 ret = ISECT_SHARED_V;
01468 goto out;
01469 }
01470
01471 if (status < 0) {
01472 ret = ISECT_NONE;
01473 goto topo;
01474 }
01475
01476 if( status == 0 ) {
01477
01478
01479 if( nmg_isect_2colinear_edge2p( eu1, eu2, fu2, is, (struct bu_ptbl *)0, (struct bu_ptbl *)0 ) > 2 ) {
01480
01481 ret = ISECT_SPLIT1 | ISECT_SPLIT2;
01482 } else {
01483
01484
01485 ret = ISECT_NONE;
01486 }
01487 goto out;
01488 }
01489
01490
01491
01492
01493
01494
01495
01496
01497 VSUB2( dir3d, vu1b->v_p->vg_p->coord, vu1a->v_p->vg_p->coord );
01498 VJOIN1( hit_pt, vu1a->v_p->vg_p->coord, dist[0], dir3d );
01499
01500 if ( dist[0] == 0 ) {
01501
01502 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01503 bu_log("\tvu=x%x vu1a is intersect point\n", vu1a);
01504 if( dist[1] < 0 || dist[1] > 1 ) {
01505 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01506 bu_log("\teu1 line intersects eu2 outside vu2a...vu2b range, ignore.\n");
01507 ret = ISECT_NONE;
01508 goto topo;
01509 }
01510
01511
01512
01513
01514 if( dist[1] == 0 ) {
01515 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01516 bu_log("\tvu2a matches vu1a\n");
01517 nmg_jv(vu1a->v_p, vu2a->v_p);
01518 nmg_enlist_vu( is, vu1a, vu2a, MAX_FASTF );
01519 ret = ISECT_SHARED_V;
01520 goto topo;
01521 }
01522 if( dist[1] == 1 ) {
01523 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01524 bu_log("\tsecond point of eu2 matches vu1a\n");
01525 nmg_jv(vu1a->v_p, vu2b->v_p);
01526 nmg_enlist_vu( is, vu1a, vu2b, MAX_FASTF );
01527 ret = ISECT_SHARED_V;
01528 goto topo;
01529 }
01530
01531 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01532 bu_log("\tbreaking eu2 on vu1a\n");
01533 vu = nmg_ebreaker( vu1a->v_p, eu2, &is->tol )->vu_p;
01534 nmg_enlist_vu( is, vu1a, vu, MAX_FASTF );
01535 ret = ISECT_SPLIT2;
01536 goto topo;
01537 }
01538
01539 if ( dist[0] == 1 ) {
01540
01541 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01542 bu_log("\tvu=x%x vu1b is intersect point\n", vu1b);
01543 if( dist[1] < 0 || dist[1] > 1 ) {
01544 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01545 bu_log("\teu1 line intersects eu2 outside vu2a...vu2b range, ignore.\n");
01546 ret = ISECT_NONE;
01547 goto topo;
01548 }
01549
01550
01551
01552
01553 if( dist[1] == 0 ) {
01554 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01555 bu_log("\tvu2a matches vu1b\n");
01556 nmg_jv(vu1b->v_p, vu2a->v_p);
01557 nmg_enlist_vu( is, vu1b, vu2a, MAX_FASTF );
01558 ret = ISECT_SHARED_V;
01559 goto topo;
01560 }
01561 if( dist[1] == 1 ) {
01562 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01563 bu_log("\tsecond point of eu2 matches vu1b\n");
01564 nmg_jv(vu1b->v_p, vu2b->v_p);
01565 nmg_enlist_vu( is, vu1b, vu2b, MAX_FASTF );
01566 ret = ISECT_SHARED_V;
01567 goto topo;
01568 }
01569
01570 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01571 bu_log("\tbreaking eu2 on vu1b\n");
01572 vu = nmg_ebreaker( vu1b->v_p, eu2, &is->tol )->vu_p;
01573 nmg_enlist_vu( is, vu1b, vu, MAX_FASTF );
01574 ret = ISECT_SPLIT2;
01575 goto topo;
01576 }
01577
01578
01579
01580
01581 if( dist[0] < 0 || dist[0] > 1 ) {
01582 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01583 bu_log("\tIntersect point on eu2 is outside vu1a...vu1b. Break eu2 anyway.\n");
01584
01585 if( dist[1] == 0 ) {
01586 nmg_enlist_vu( is, vu2a, 0, MAX_FASTF );
01587 ret = ISECT_SHARED_V;
01588 goto topo;
01589 } else if( dist[1] == 1 ) {
01590 nmg_enlist_vu( is, vu2b, 0, MAX_FASTF );
01591 ret = ISECT_SHARED_V;
01592 goto topo;
01593 } else if( dist[1] > 0 && dist[1] < 1 ) {
01594
01595 struct vertexuse *new_vu2;
01596 struct vertex *new_v2;
01597 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01598 VPRINT("\t\tBreaking eu2 at intersect point", hit_pt);
01599 new_v2 = nmg_find_pt_in_model(m, hit_pt, &(is->tol) );
01600 new_vu2 = nmg_ebreaker( new_v2, eu2, &is->tol )->vu_p;
01601 if( !new_v2 ) {
01602
01603 nmg_vertex_gv( new_vu2->v_p, hit_pt );
01604 }
01605 nmg_enlist_vu( is, new_vu2, 0, MAX_FASTF );
01606 ret = ISECT_SPLIT2;
01607 goto topo;
01608 }
01609
01610
01611 ret = ISECT_NONE;
01612 goto topo;
01613 }
01614
01615
01616
01617 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01618 bu_log("\tintersect is in middle of eu1, breaking it\n");
01619
01620
01621
01622
01623 if( dist[1] == 0 ) {
01624 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01625 bu_log("\t\tintersect point is vu2a\n");
01626 vu = nmg_ebreaker( vu2a->v_p, eu1, &is->tol )->vu_p;
01627 nmg_enlist_vu( is, vu2a, vu, MAX_FASTF );
01628 ret |= ISECT_SPLIT1;
01629 goto topo;
01630 } else if( dist[1] == 1 ) {
01631 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01632 bu_log("\t\tintersect point is vu2b\n");
01633 vu = nmg_ebreaker( vu2b->v_p, eu1, &is->tol )->vu_p;
01634 nmg_enlist_vu( is, vu2b, vu, MAX_FASTF );
01635 ret |= ISECT_SPLIT1;
01636 goto topo;
01637 } else if( dist[1] > 0 && dist[1] < 1 ) {
01638
01639 struct vertex *new_v;
01640 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01641 VPRINT("\t\tBreaking both edges at intersect point", hit_pt);
01642 ret = ISECT_SPLIT1 | ISECT_SPLIT2;
01643 new_v = nmg_e2break( eu1, eu2 );
01644 nmg_vertex_gv( new_v, hit_pt );
01645
01646
01647 if( eu1->eumate_p->vu_p->v_p != new_v ) rt_bomb("new_v 1\n");
01648 if( eu2->eumate_p->vu_p->v_p != new_v ) rt_bomb("new_v 2\n");
01649
01650 nmg_enlist_vu( is, BU_LIST_PNEXT_CIRC(edgeuse,eu1)->vu_p,
01651 BU_LIST_PNEXT_CIRC(edgeuse,eu2)->vu_p, MAX_FASTF );
01652 goto topo;
01653 } else {
01654
01655
01656
01657
01658
01659 ret = ISECT_NONE;
01660 goto topo;
01661 }
01662
01663 topo:
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678 nmg_enlist_vu( is, vu1a, 0, MAX_FASTF );
01679 nmg_enlist_vu( is, vu1b, 0, MAX_FASTF );
01680 out:
01681
01682 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01683 bu_log("nmg_isect_edge2p_edge2p(eu1=x%x, eu2=x%x) END, ret=%d %s%s%s\n",
01684 eu1, eu2, ret,
01685 (ret&ISECT_SHARED_V)? "SHARED_V|" :
01686 ((ret==0) ? "NONE" : ""),
01687 (ret&ISECT_SPLIT1)? "SPLIT1|" : "",
01688 (ret&ISECT_SPLIT2)? "SPLIT2" : ""
01689 );
01690 }
01691
01692 return ret;
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 static int
01710 nmg_isect_wireedge3p_face3p(struct nmg_inter_struct *is, struct edgeuse *eu1, struct faceuse *fu2)
01711 {
01712 struct vertexuse *vu1_final = (struct vertexuse *)NULL;
01713 struct vertexuse *vu2_final = (struct vertexuse *)NULL;
01714 struct vertex *v1a;
01715 struct vertex *v1b;
01716 point_t hit_pt;
01717 vect_t edge_vect;
01718 fastf_t edge_len;
01719 fastf_t dist;
01720 fastf_t dist_to_plane;
01721 int status;
01722 vect_t start_pt;
01723 struct edgeuse *eunext;
01724 struct faceuse *fu1;
01725 plane_t n2;
01726 int ret = 0;
01727
01728 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01729 bu_log("nmg_isect_wireedge3p_face3p(, eu1=x%x, fu2=x%x) START\n", eu1, fu2);
01730
01731 NMG_CK_INTER_STRUCT(is);
01732 NMG_CK_EDGEUSE(eu1);
01733 NMG_CK_VERTEXUSE(eu1->vu_p);
01734 v1a = eu1->vu_p->v_p;
01735 NMG_CK_VERTEX(v1a);
01736 NMG_CK_VERTEX_G(v1a->vg_p);
01737
01738 NMG_CK_EDGEUSE(eu1->eumate_p);
01739 NMG_CK_VERTEXUSE(eu1->eumate_p->vu_p);
01740 v1b = eu1->eumate_p->vu_p->v_p;
01741 NMG_CK_VERTEX(v1b);
01742 NMG_CK_VERTEX_G(v1b->vg_p);
01743
01744 NMG_CK_FACEUSE(fu2);
01745 if( fu2->orientation != OT_SAME ) rt_bomb("nmg_isect_wireedge3p_face3p() fu2 not OT_SAME\n");
01746 fu1 = nmg_find_fu_of_eu(eu1);
01747
01748
01749
01750
01751
01752 VSUB2(edge_vect, v1b->vg_p->coord, v1a->vg_p->coord);
01753 edge_len = MAGNITUDE(edge_vect);
01754
01755 VMOVE( start_pt, v1a->vg_p->coord );
01756
01757 {
01758
01759 double dot;
01760 dot = fabs( VDOT( is->dir, edge_vect ) / edge_len ) - 1;
01761 if( !NEAR_ZERO( dot, .01 ) ) {
01762 bu_log("HACK HACK cough cough. Resetting is->pt, is->dir\n");
01763 VPRINT("old is->pt ", is->pt);
01764 VPRINT("old is->dir", is->dir);
01765 VMOVE( is->pt, start_pt );
01766 VMOVE( is->dir, edge_vect );
01767 VUNITIZE(is->dir);
01768 VPRINT("new is->pt ", is->pt);
01769 VPRINT("new is->dir", is->dir);
01770 }
01771 }
01772
01773 NMG_GET_FU_PLANE( n2, fu2 );
01774 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01775 bu_log("Testing (%g, %g, %g) -> (%g, %g, %g) dir=(%g, %g, %g)\n",
01776 V3ARGS(start_pt),
01777 V3ARGS(v1b->vg_p->coord),
01778 V3ARGS(edge_vect) );
01779 PLPRINT("\t", n2);
01780 }
01781
01782 status = bn_isect_line3_plane(&dist, start_pt, edge_vect,
01783 n2, &is->tol);
01784
01785 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01786 if (status >= 0)
01787 bu_log("\tHit. bn_isect_line3_plane=%d, dist=%g (%e)\n",
01788 status, dist, dist);
01789 else
01790 bu_log("\tMiss. Boring status of bn_isect_line3_plane: %d\n",
01791 status);
01792 }
01793 if( status == 0 ) {
01794 struct nmg_inter_struct is2;
01795
01796
01797
01798
01799
01800
01801
01802 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01803 bu_log("nmg_isect_wireedge3p_face3p: edge lies ON face, using 2D code\n@ @ @ @ @ @ @ @ @ @ 2D CODE, START\n");
01804 bu_log(" The status of the face/face intersect line, before 2d:\n");
01805 nmg_pr_ptbl_vert_list( "l1", is->l1, is->mag1 );
01806 nmg_pr_ptbl_vert_list( "l2", is->l2, is->mag2 );
01807 }
01808
01809 is2 = *is;
01810 is2.vert2d = 0;
01811
01812 ret = nmg_isect_edge2p_face2p( &is2, eu1, fu2, fu1 );
01813
01814 nmg_isect2d_cleanup( &is2 );
01815
01816
01817
01818
01819
01820
01821
01822
01823 if (rt_g.NMG_debug & DEBUG_POLYSECT && ret == 0) {
01824 bu_log("nmg_isect_wireedge3p_face3p: @ @ @ @ @ @ @ @ @ @ 2D CODE, END, resume 3d problem.\n");
01825 bu_log(" The status of the face/face intersect line, so far:\n");
01826 nmg_pr_ptbl_vert_list( "l1", is->l1, is->mag1 );
01827 nmg_pr_ptbl_vert_list( "l2", is->l2, is->mag2 );
01828 }
01829
01830
01831 if ( (vu2_final=nmg_find_v_in_face(eu1->vu_p->v_p, fu2)) ) {
01832 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01833 bu_log("\tEdge start vertex lies on other face (2d topology).\n");
01834 vu1_final = eu1->vu_p;
01835 (void)bu_ptbl_ins_unique(is->l1, &vu1_final->l.magic);
01836 (void)bu_ptbl_ins_unique(is->l2, &vu2_final->l.magic);
01837 }
01838
01839 vu1_final = vu2_final = (struct vertexuse *)NULL;
01840 goto out;
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856 if ( (vu2_final=nmg_find_v_in_face(v1a, fu2)) ) {
01857 vu1_final = eu1->vu_p;
01858 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
01859 bu_log("\tEdge start vertex lies on other face (topology).\n\tAdding vu1_final=x%x (v=x%x), vu2_final=x%x (v=x%x)\n",
01860 vu1_final, vu1_final->v_p,
01861 vu2_final, vu2_final->v_p);
01862 }
01863 (void)bu_ptbl_ins_unique(is->l1, &vu1_final->l.magic);
01864 (void)bu_ptbl_ins_unique(is->l2, &vu2_final->l.magic);
01865 goto out;
01866 }
01867
01868 if (status < 0) {
01869
01870
01871
01872 dist = VDOT( start_pt, n2 ) - n2[3];
01873 if( !NEAR_ZERO( dist, is->tol.dist ) )
01874 goto out;
01875
01876
01877
01878
01879 rt_bomb("nmg_isect_wireedge3p_face3p: Edge start vertex lies on other face (geometry)\n");
01880
01881
01882 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01883 bu_log("\tEdge start vertex lies on other face (geometry)\n");
01884 dist = VSUB2DOT( v1a->vg_p->coord, start_pt, edge_vect )
01885 / edge_len;
01886 }
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 dist_to_plane = edge_len * dist;
01899
01900 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01901 bu_log("\tedge_len=%g, dist=%g, dist_to_plane=%g\n",
01902 edge_len, dist, dist_to_plane);
01903
01904 if ( dist_to_plane < -is->tol.dist ) {
01905
01906 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01907 bu_log("\tplane behind first point\n");
01908 goto out;
01909 }
01910
01911 if ( dist_to_plane > edge_len + is->tol.dist) {
01912 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01913 bu_log("\tplane beyond second point\n");
01914 goto out;
01915 }
01916
01917 VJOIN1( hit_pt, start_pt, dist, edge_vect );
01918
01919
01920 {
01921 fastf_t ff_dist;
01922 ff_dist = bn_dist_line3_pt3( is->pt, is->dir, hit_pt );
01923 if( ff_dist > is->tol.dist ) {
01924 bu_log("WARNING nmg_isect_wireedge3p_face3p() hit_pt off f/f line %g*tol (%e, tol=%e)\n",
01925 ff_dist/is->tol.dist,
01926 ff_dist, is->tol.dist);
01927
01928 }
01929 }
01930
01931
01932
01933
01934
01935
01936
01937 if ( dist_to_plane < is->tol.dist ) {
01938
01939 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01940 bu_log("\tedge starts at plane intersect\n");
01941 vu1_final = eu1->vu_p;
01942 vu2_final = nmg_enlist_vu( is, vu1_final, 0, MAX_FASTF );
01943 goto out;
01944 }
01945
01946 if ( dist_to_plane < edge_len - is->tol.dist) {
01947
01948
01949
01950 vu2_final = nmg_break_3edge_at_plane(hit_pt, fu2, is, eu1);
01951 if( vu2_final )
01952 vu1_final = BU_LIST_PNEXT_CIRC(edgeuse,eu1)->vu_p;
01953 goto out;
01954 }
01955
01956 #if 0
01957 if ( dist_to_plane <= edge_len + is->tol.dist)
01958 #endif
01959 {
01960
01961 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01962 bu_log("\tedge ends at plane intersect\n");
01963
01964 eunext = BU_LIST_PNEXT_CIRC(edgeuse,eu1);
01965 NMG_CK_EDGEUSE(eunext);
01966 if( eunext->vu_p->v_p != v1b )
01967 rt_bomb("nmg_isect_wireedge3p_face3p: discontinuous eu loop\n");
01968
01969 vu1_final = eunext->vu_p;
01970 vu2_final = nmg_enlist_vu( is, vu1_final, 0, MAX_FASTF );
01971 goto out;
01972 }
01973
01974 out:
01975
01976 if( vu1_final && vu2_final ) {
01977 fastf_t dist;
01978
01979 if( vu1_final->v_p != vu2_final->v_p ) rt_bomb("nmg_isect_wireedge3p_face3p() vertex mis-match\n");
01980
01981 dist = bn_dist_line3_pt3( is->pt, is->dir,
01982 vu1_final->v_p->vg_p->coord );
01983 if( dist > 100*is->tol.dist ) {
01984 bu_log("ERROR nmg_isect_wireedge3p_face3p() vu1=x%x point off line by %g > 100*dist_tol (%g)\n",
01985 vu1_final, dist, 100*is->tol.dist);
01986 VPRINT("is->pt|", is->pt);
01987 VPRINT("is->dir", is->dir);
01988 VPRINT(" coord ", vu1_final->v_p->vg_p->coord );
01989 rt_bomb("nmg_isect_wireedge3p_face3p()\n");
01990 }
01991 if( dist > is->tol.dist ) {
01992 bu_log("WARNING nmg_isect_wireedge3p_face3p() vu1=x%x pt off line %g*tol (%e, tol=%e)\n",
01993 vu1_final, dist/is->tol.dist,
01994 dist, is->tol.dist);
01995 }
01996 }
01997
01998 if (rt_g.NMG_debug & DEBUG_POLYSECT)
01999 bu_log("nmg_isect_wireedge3p_face3p(, eu1=x%x, fu2=x%x) ret=%d END\n", eu1, fu2, ret);
02000 return ret;
02001 }
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013 static int
02014 nmg_isect_wireloop3p_face3p(struct nmg_inter_struct *bs, struct loopuse *lu, struct faceuse *fu)
02015 {
02016 struct edgeuse *eu;
02017 long magic1;
02018 int discards = 0;
02019
02020 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02021 plane_t n;
02022 bu_log("nmg_isect_wireloop3p_face3p(, lu=x%x, fu=x%x) START\n", lu, fu);
02023 NMG_GET_FU_PLANE( n, fu );
02024 HPRINT(" fg N", n);
02025 }
02026
02027 NMG_CK_INTER_STRUCT(bs);
02028 NMG_CK_LOOPUSE(lu);
02029 NMG_CK_LOOP(lu->l_p);
02030 NMG_CK_LOOP_G(lu->l_p->lg_p);
02031
02032 NMG_CK_FACEUSE(fu);
02033
02034 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
02035 if (magic1 == NMG_VERTEXUSE_MAGIC) {
02036 struct vertexuse *vu = BU_LIST_FIRST(vertexuse,&lu->down_hd);
02037
02038
02039
02040 nmg_isect_3vertex_3face(bs, vu, fu);
02041 return 0;
02042 } else if (magic1 != NMG_EDGEUSE_MAGIC) {
02043 rt_bomb("nmg_isect_wireloop3p_face3p() Unknown type of NMG loopuse\n");
02044 }
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 for( eu = BU_LIST_LAST(edgeuse, &lu->down_hd );
02056 BU_LIST_NOT_HEAD(eu,&lu->down_hd);
02057 eu = BU_LIST_PLAST(edgeuse,eu) ) {
02058 NMG_CK_EDGEUSE(eu);
02059
02060 if (eu->up.magic_p != &lu->l.magic) {
02061 rt_bomb("nmg_isect_wireloop3p_face3p: edge does not share loop\n");
02062 }
02063
02064 discards += nmg_isect_wireedge3p_face3p(bs, eu, fu);
02065
02066 nmg_ck_lueu(lu, "nmg_isect_wireloop3p_face3p");
02067 }
02068
02069 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02070 bu_log("nmg_isect_wireloop3p_face3p(, lu=x%x, fu=x%x) END, discards=%d\n", lu, fu, discards);
02071 }
02072 return discards;
02073 }
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098 int
02099 nmg_isect_construct_nice_ray(struct nmg_inter_struct *is, struct faceuse *fu2)
02100 {
02101 struct xray line;
02102 vect_t invdir;
02103
02104 NMG_CK_INTER_STRUCT(is);
02105 NMG_CK_FACEUSE(fu2);
02106
02107 VMOVE( line.r_pt, is->on_eg->e_pt );
02108 VMOVE( line.r_dir, is->on_eg->e_dir );
02109 VUNITIZE( line.r_dir );
02110 VINVDIR( invdir, line.r_dir );
02111
02112
02113 if( !rt_in_rpp( &line, invdir, fu2->f_p->min_pt, fu2->f_p->max_pt ) ) {
02114
02115 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02116 VPRINT("r_pt ", line.r_pt);
02117 VPRINT("r_dir", line.r_dir);
02118 VPRINT("fu2 min", fu2->f_p->min_pt);
02119 VPRINT("fu2 max", fu2->f_p->max_pt);
02120 bu_log("r_min=%g, r_max=%g\n", line.r_min, line.r_max);
02121 bu_log("nmg_isect_construct_nice_ray() edge ray missed face bounding RPP, ret=1\n");
02122 }
02123 return 1;
02124 }
02125 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02126 VPRINT("fu2 min", fu2->f_p->min_pt);
02127 VPRINT("fu2 max", fu2->f_p->max_pt);
02128 bu_log("r_min=%g, r_max=%g\n", line.r_min, line.r_max);
02129 }
02130
02131 VJOIN1( is->pt, line.r_pt, line.r_min, line.r_dir );
02132 if( line.r_min > line.r_max ) {
02133
02134 VREVERSE( is->dir, line.r_dir );
02135 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02136 bu_log("flipping dir\n");
02137 } else {
02138 VMOVE( is->dir, line.r_dir );
02139 }
02140 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02141 VPRINT("r_pt ", line.r_pt);
02142 VPRINT("r_dir", line.r_dir);
02143 VPRINT("->pt ", is->pt);
02144 VPRINT("->dir", is->dir);
02145 bu_log("nmg_isect_construct_nice_ray() ret=0\n");
02146 }
02147 return 0;
02148 }
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187 static int
02188 nmg_isect_edge2p_face2p(struct nmg_inter_struct *is, struct edgeuse *eu1, struct faceuse *fu2, struct faceuse *fu1)
02189
02190
02191
02192
02193 {
02194 struct bu_ptbl vert_list1, vert_list2;
02195 fastf_t *mag1, *mag2;
02196 struct vertexuse *vu1;
02197 struct vertexuse *vu2;
02198 struct edgeuse *fu2_eu;
02199 int total_splits = 0;
02200 int ret = 0;
02201 struct bu_ptbl eu1_list;
02202 struct bu_ptbl eu2_list;
02203
02204 NMG_CK_INTER_STRUCT(is);
02205 NMG_CK_EDGEUSE(eu1);
02206 NMG_CK_FACEUSE(fu2);
02207 if(fu1) NMG_CK_FACEUSE(fu1);
02208
02209 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02210 bu_log("nmg_isect_edge2p_face2p(eu1=x%x, fu2=x%x, fu1=x%x) START\n", eu1, fu2, fu1);
02211
02212 if( fu2->orientation != OT_SAME ) rt_bomb("nmg_isect_edge2p_face2p() fu2 not OT_SAME\n");
02213 if( fu1 && fu1->orientation != OT_SAME ) rt_bomb("nmg_isect_edge2p_face2p() fu1 not OT_SAME\n");
02214
02215 mag1 = (fastf_t *)NULL;
02216 mag2 = (fastf_t *)NULL;
02217
02218
02219 fu2_eu = nmg_find_eu_in_face( eu1->vu_p->v_p, eu1->eumate_p->vu_p->v_p,
02220 fu2, (const struct edgeuse *)NULL, 0 );
02221 if( fu2_eu != (struct edgeuse *)NULL ) {
02222
02223 NMG_CK_EDGEUSE(fu2_eu);
02224 if( fu2_eu->e_p != eu1->e_p ) {
02225
02226 bu_log("nmg_isect_edge2p_face2p() fusing unshared shared edge\n");
02227 nmg_radial_join_eu( eu1, fu2_eu, &is->tol );
02228 }
02229
02230 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02231 bu_log("nmg_isect_edge2p_face2p() topology is shared\n");
02232 ret = 0;
02233 goto do_ret;
02234 }
02235
02236 (void)bu_ptbl(&vert_list1, BU_PTBL_INIT,(long *)NULL);
02237 (void)bu_ptbl(&vert_list2, BU_PTBL_INIT,(long *)NULL);
02238 (void)bu_ptbl(&eu1_list, BU_PTBL_INIT,(long *)NULL);
02239 (void)bu_ptbl(&eu2_list, BU_PTBL_INIT,(long *)NULL);
02240
02241 NMG_CK_EDGE_G_LSEG(eu1->g.lseg_p);
02242 is->on_eg = eu1->g.lseg_p;
02243 is->l1 = &vert_list1;
02244 is->l2 = &vert_list2;
02245 is->s1 = nmg_find_s_of_eu(eu1);
02246 is->s2 = fu2->s_p;
02247 is->fu1 = fu1;
02248 is->fu2 = fu2;
02249
02250 if ( fu1 && rt_g.NMG_debug & (DEBUG_POLYSECT|DEBUG_FCUT|DEBUG_MESH)
02251 && rt_g.NMG_debug & DEBUG_PLOTEM) {
02252 nmg_pl_2fu( "Iface%d.pl", 0, fu2, fu1, 0 );
02253 }
02254
02255 vu1 = eu1->vu_p;
02256 vu2 = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
02257 if( vu1->v_p == vu2->v_p ) {
02258 bu_log("nmg_isect_edge2p_face2p(eu1=x%x) skipping 0-len edge (topology)\n", eu1);
02259
02260 goto out;
02261 }
02262
02263
02264
02265
02266
02267 if( nmg_isect_construct_nice_ray( is, fu2 ) ) goto out;
02268
02269 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
02270 nmg_fu_touchingloops(fu2);
02271 if(fu1)nmg_fu_touchingloops(fu1);
02272 nmg_region_v_unique( is->s1->r_p, &is->tol );
02273 nmg_region_v_unique( is->s2->r_p, &is->tol );
02274 }
02275
02276
02277 if( fu1 ) {
02278 nmg_edgeuse_tabulate( &eu1_list, &fu1->l.magic );
02279 } else {
02280 nmg_edgeuse_tabulate( &eu1_list, &eu1->l.magic );
02281 }
02282 nmg_edgeuse_tabulate( &eu2_list, &fu2->l.magic );
02283
02284 is->mag_len = 2 * (BU_PTBL_END( &eu1_list ) + BU_PTBL_END( &eu2_list ) );
02285 mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag1" );
02286 mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag2" );
02287
02288 is->mag1 = mag1;
02289 is->mag2 = mag2;
02290
02291
02292 total_splits = 1;
02293 nmg_isect_line2_face2pNEW( is, fu2, fu1, &eu2_list, &eu1_list );
02294
02295
02296 if( fu1 ) {
02297
02298 nmg_isect_line2_face2pNEW( is, fu1, fu2, &eu1_list, &eu2_list );
02299 }
02300 if (rt_g.NMG_debug & DEBUG_POLYSECT )
02301 bu_log("nmg_isect_edge2p_face2p(): total_splits=%d\n", total_splits);
02302
02303 if( total_splits <= 0 ) goto out;
02304
02305 if (rt_g.NMG_debug & DEBUG_FCUT) {
02306 bu_log("nmg_isect_edge2p_face2p(eu1=x%x, fu2=x%x) vert_lists C:\n", eu1, fu2 );
02307 nmg_pr_ptbl_vert_list( "vert_list1", &vert_list1, mag1 );
02308 nmg_pr_ptbl_vert_list( "vert_list2", &vert_list2, mag2 );
02309 }
02310 #if 0
02311 nmg_purge_unwanted_intersection_points(&vert_list1, mag1, fu2, &is->tol);
02312 if(fu1)nmg_purge_unwanted_intersection_points(&vert_list2, mag2, fu1, &is->tol);
02313 #endif
02314 if (rt_g.NMG_debug & DEBUG_FCUT) {
02315 bu_log("nmg_isect_edge2p_face2p(eu1=x%x, fu2=x%x) vert_lists D:\n", eu1, fu2 );
02316 nmg_pr_ptbl_vert_list( "vert_list1", &vert_list1, mag1 );
02317 nmg_pr_ptbl_vert_list( "vert_list2", &vert_list2, mag2 );
02318 }
02319
02320 if (vert_list1.end == 0 && vert_list2.end == 0) goto out;
02321
02322
02323 is->on_eg = nmg_face_cutjoin(&vert_list1, &vert_list2, mag1, mag2, fu1, fu2, is->pt, is->dir, is->on_eg, &is->tol);
02324 ret = 1;
02325
02326 out:
02327 (void)bu_ptbl_free(&vert_list1);
02328 (void)bu_ptbl_free(&vert_list2);
02329 (void)bu_ptbl_free(&eu1_list);
02330 (void)bu_ptbl_free(&eu2_list);
02331 if( mag1 )
02332 bu_free( (char *)mag1, "nmg_isect_edge2p_face2p: mag1" );
02333 if( mag2 )
02334 bu_free( (char *)mag2, "nmg_isect_edge2p_face2p: mag2" );
02335
02336 do_ret:
02337 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02338 bu_log("nmg_isect_edge2p_face2p(eu1=x%x, fu2=x%x) ret=%d\n",
02339 eu1, fu2, ret);
02340 }
02341 return ret;
02342 }
02343
02344
02345
02346 void
02347 nmg_enlist_one_vu(struct nmg_inter_struct *is, const struct vertexuse *vu, fastf_t dist)
02348
02349
02350
02351 {
02352 struct shell *sv;
02353
02354 NMG_CK_INTER_STRUCT(is);
02355 NMG_CK_VERTEXUSE(vu);
02356
02357 if( is->mag_len <= BU_PTBL_END( is->l1 ) || is->mag_len <= BU_PTBL_END( is->l2 ) )
02358 bu_log( "Array for distances to vertexuses is too small (%d)\n" , is->mag_len );
02359
02360 sv = nmg_find_s_of_vu( vu );
02361
02362
02363 if( sv == is->s1 ) {
02364 bu_ptbl_ins_unique( is->l1, (long *)&vu->l.magic );
02365 if( is->mag_len <= BU_PTBL_END( is->l1 ) )
02366 {
02367 if( is->mag_len )
02368 {
02369 is->mag_len *= 2;
02370 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
02371 "is->mag1" );
02372 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
02373 "is->mag2" );
02374 }
02375 else
02376 {
02377 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
02378 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
02379 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
02380 }
02381
02382 }
02383 if( dist < MAX_FASTF )
02384 is->mag1[bu_ptbl_locate( is->l1, (long *)&vu->l.magic )] = dist;
02385 } else if( sv == is->s2 ) {
02386 bu_ptbl_ins_unique( is->l2, (long *)&vu->l.magic );
02387 if( is->mag_len <= BU_PTBL_END( is->l2 ) )
02388 {
02389 if( is->mag_len )
02390 {
02391 is->mag_len *= 2;
02392 is->mag1 = (fastf_t *)rt_realloc( (char *)is->mag1, is->mag_len*sizeof( fastf_t),
02393 "is->mag1" );
02394 is->mag2 = (fastf_t *)rt_realloc( (char *)is->mag2, is->mag_len*sizeof( fastf_t),
02395 "is->mag2" );
02396 }
02397 else
02398 {
02399 is->mag_len = 2*(BU_PTBL_END( is->l1 ) + BU_PTBL_END( is->l2 ));
02400 is->mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag1" );
02401 is->mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "is->mag2" );
02402 }
02403
02404 }
02405 if( dist < MAX_FASTF )
02406 is->mag2[bu_ptbl_locate( is->l2, (long *)&vu->l.magic )] = dist;
02407 } else {
02408 bu_log("nmg_enlist_one_vu(vu=x%x) sv=x%x, s1=x%x, s2=x%x\n",
02409 vu, sv, is->s1, is->s2 );
02410 rt_bomb("nmg_enlist_one_vu: vu is not in s1 or s2\n");
02411 }
02412
02413 if( rt_g.NMG_debug & DEBUG_POLYSECT ) {
02414 bu_log("nmg_enlist_one_vu(vu=x%x) v=x%x, dist=%g (%s)\n",
02415 vu, vu->v_p, dist,
02416 (sv == is->s1) ? "shell 1" : "shell 2" );
02417 }
02418
02419
02420 if( (rt_g.NMG_debug & DEBUG_VERIFY) && is->fu1 && is->fu2 ) {
02421 nmg_ck_v_in_2fus(vu->v_p, is->fu1, is->fu2, &(is->tol));
02422 }
02423 }
02424
02425 static void
02426 nmg_coplanar_face_vertex_fuse(struct faceuse *fu1, struct faceuse *fu2, struct bn_tol *tol)
02427 {
02428 struct bu_ptbl fu1_verts;
02429 struct bu_ptbl fu2_verts;
02430 int i, j;
02431 vect_t norm;
02432
02433 NMG_CK_FACEUSE( fu1 );
02434 NMG_CK_FACEUSE( fu2 );
02435 BN_CK_TOL( tol );
02436
02437 NMG_GET_FU_NORMAL( norm, fu1 );
02438
02439 nmg_vertex_tabulate( &fu1_verts, &fu1->l.magic );
02440 nmg_vertex_tabulate( &fu2_verts, &fu2->l.magic );
02441
02442 for( i=0 ; i<BU_PTBL_END( &fu1_verts ) ; i++ )
02443 {
02444 struct vertex *v1;
02445
02446 v1 = (struct vertex *)BU_PTBL_GET( &fu1_verts, i );
02447
02448 for( j=0 ; j<BU_PTBL_END( &fu2_verts ) ; j++ )
02449 {
02450 struct vertex *v2;
02451 vect_t diff;
02452 vect_t diff_unit;
02453 fastf_t len_sq, inv_len;
02454 fastf_t dot;
02455
02456 v2 = (struct vertex *)BU_PTBL_GET( &fu2_verts, j );
02457
02458 if( v1 == v2 )
02459 continue;
02460
02461 VSUB2( diff, v1->vg_p->coord, v2->vg_p->coord );
02462 len_sq = MAGSQ( diff );
02463 if( len_sq > 4.0*tol->dist_sq )
02464 continue;
02465
02466 inv_len = 1.0 / sqrt( len_sq );
02467
02468 VSCALE( diff_unit, diff, inv_len );
02469
02470 dot = VDOT( norm, diff_unit );
02471 if( BN_VECT_ARE_PARALLEL( dot, tol ) )
02472 {
02473
02474 nmg_jv( v2, v1 );
02475 break;
02476 }
02477 }
02478 }
02479 }
02480
02481 static void
02482 nmg_isect_two_face2p_jra(struct nmg_inter_struct *is, struct faceuse *fu1, struct faceuse *fu2)
02483 {
02484 struct model *m;
02485 struct loopuse *lu;
02486 struct bu_ptbl eu1_list;
02487 struct bu_ptbl eu2_list;
02488 struct bu_ptbl v_list;
02489 struct bu_ptbl vert_list1,vert_list2;
02490 fastf_t *mag1,*mag2;
02491 int i,j;
02492
02493 NMG_CK_FACEUSE( fu1 );
02494 NMG_CK_FACEUSE( fu2 );
02495 NMG_CK_INTER_STRUCT(is);
02496
02497 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02498 bu_log( "nmg_isect_two)face2p_jra: fu1=x%x, fu2=x%x\n" );
02499
02500 nmg_coplanar_face_vertex_fuse( fu1, fu2, &is->tol );
02501
02502 m = nmg_find_model( &fu1->l.magic );
02503 NMG_CK_MODEL( m );
02504
02505 nmg_edgeuse_tabulate( &eu1_list, &fu1->l.magic );
02506 nmg_edgeuse_tabulate( &eu2_list, &fu2->l.magic );
02507
02508 is->mag_len = 2 * (BU_PTBL_END( &eu1_list ) + BU_PTBL_END( &eu2_list ) );
02509 mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag1" );
02510 mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag2" );
02511
02512 for( i=0 ; i<is->mag_len ; i++ )
02513 {
02514 mag1[i] = MAX_FASTF;
02515 mag2[i] = MAX_FASTF;
02516 }
02517
02518
02519 is->s1 = fu1->s_p;
02520 is->s2 = fu2->s_p;
02521 is->fu1 = fu1;
02522 is->fu2 = fu2;
02523 is->mag1 = mag1;
02524 is->mag2 = mag2;
02525
02526
02527 for( i=0 ; i<BU_PTBL_END( &eu1_list ) ; i++ )
02528 {
02529 struct edgeuse *eu1;
02530 struct vertex_g *vg1a,*vg1b;
02531 vect_t vt1_3d;
02532
02533 eu1 = (struct edgeuse *)BU_PTBL_GET( &eu1_list, i );
02534 NMG_CK_EDGEUSE( eu1 );
02535
02536 vg1a = eu1->vu_p->v_p->vg_p;
02537 NMG_CK_VERTEX_G( vg1a );
02538 vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
02539 NMG_CK_VERTEX_G( vg1b );
02540
02541 VSUB2( vt1_3d, vg1b->coord, vg1a->coord );
02542 #if 0
02543 nmg_get_2d_vertex( pt1a, eu1->vu_p->v_p, is, (long *)fu1 );
02544 nmg_get_2d_vertex( pt1b, eu1->eumate_p->vu_p->v_p, is, (long *)fu1 );
02545 VSUB2( vt1, pt1b, pt1a );
02546 #endif
02547 for( j=0 ; j<BU_PTBL_END( &eu2_list ) ; j++ )
02548 {
02549 struct edgeuse *eu2;
02550 struct vertex_g *vg2a, *vg2b;
02551 int code;
02552 vect_t vt2_3d;
02553 fastf_t dist[2];
02554 point_t hit_pt;
02555 int hit_no;
02556 int hit_count;
02557
02558 eu2 = (struct edgeuse *)BU_PTBL_GET( &eu2_list, j );
02559 NMG_CK_EDGEUSE( eu2 );
02560 #if 0
02561 nmg_get_2d_vertex( pt2a, eu2->vu_p->v_p, is, (long *)fu1 );
02562 nmg_get_2d_vertex( pt2b, eu2->eumate_p->vu_p->v_p, is, (long *)fu1 );
02563 VSUB2( vt2, pt2b, pt2a );
02564 #endif
02565 vg2a = eu2->vu_p->v_p->vg_p;
02566 vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
02567 VSUB2( vt2_3d, vg2b->coord, vg2a->coord );
02568 #if 0
02569 code = bn_isect_lseg2_lseg2( dist, pt1a, vt1,
02570 pt2a, vt2, &is->tol );
02571 #else
02572 code = bn_isect_lseg3_lseg3( dist, vg1a->coord, vt1_3d,
02573 vg2a->coord, vt2_3d, &is->tol );
02574 #endif
02575
02576 if( code < 0 )
02577 continue;
02578
02579 if( code == 0 )
02580 {
02581 hit_count = 2;
02582 if( dist[0] < dist[1] )
02583 {
02584 fastf_t tmp;
02585
02586 tmp = dist[0];
02587 dist[0] = dist[1];
02588 dist[1] = tmp;
02589 }
02590 }
02591 else
02592 hit_count = 1;
02593
02594 for( hit_no=0 ; hit_no < hit_count ; hit_no++ )
02595 {
02596 struct edgeuse *new_eu;
02597 struct vertex *hitv;
02598 struct vertexuse *hit_vu = NULL;
02599
02600 if( dist[hit_no] < 0.0 || dist[hit_no] > 1.0 )
02601 continue;
02602
02603 hitv = (struct vertex *)NULL;
02604
02605 if( dist[hit_no] == 0.0 )
02606 {
02607 hit_vu = eu1->vu_p;
02608 hitv = hit_vu->v_p;
02609 VMOVE( hit_pt, hitv->vg_p->coord );
02610 }
02611 else if( dist[hit_no] == 1.0 )
02612 {
02613 hit_vu = eu1->eumate_p->vu_p;
02614 hitv = hit_vu->v_p;
02615 VMOVE( hit_pt, hitv->vg_p->coord );
02616 }
02617 else
02618 VJOIN1( hit_pt, vg1a->coord , dist[hit_no], vt1_3d )
02619
02620 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02621 bu_log( "eus x%x and x%x intersect #%d at (%f %f %f)\n",
02622 eu1, eu2, hit_no, V3ARGS( hit_pt ) );
02623
02624 if( !hit_vu )
02625 hit_vu = nmg_find_pt_in_face( fu2, hit_pt, &is->tol );
02626
02627 if( !hit_vu )
02628 hitv = nmg_find_pt_in_model( nmg_find_model( &fu1->l.magic ), hit_pt, &is->tol );
02629
02630 if (rt_g.NMG_debug & DEBUG_POLYSECT && hitv)
02631 bu_log( "Found vertex (x%x) at hit_pt\n", hitv );
02632
02633 if( hitv != eu1->vu_p->v_p && hitv != eu1->eumate_p->vu_p->v_p )
02634 {
02635 struct edgeuse *next_eu, *prev_eu;
02636
02637 next_eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
02638 prev_eu = BU_LIST_PPREV_CIRC( edgeuse, &eu1->l );
02639
02640 if( hitv != prev_eu->vu_p->v_p && hitv != next_eu->eumate_p->vu_p->v_p )
02641 {
02642 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02643 bu_log( "Splitting eu1 x%x\n", eu1 );
02644 new_eu = nmg_esplit( hitv, eu1, 1 );
02645 hitv = new_eu->vu_p->v_p;
02646 if( !hitv->vg_p )
02647 nmg_vertex_gv( hitv, hit_pt );
02648 vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
02649 VSUB2( vt1_3d, vg1b->coord, vg1a->coord );
02650 #if 0
02651 bu_ptbl_ins( &eu1_list, (long *)new_eu );
02652 nmg_get_2d_vertex( pt1b, eu1->eumate_p->vu_p->v_p, is, (long *)fu1 );
02653 VSUB2( vt1, pt1b, pt1a );
02654 #endif
02655 }
02656 }
02657 if( code == 1 && hitv != eu2->vu_p->v_p && hitv != eu2->eumate_p->vu_p->v_p )
02658 {
02659 struct edgeuse *next_eu, *prev_eu;
02660
02661 next_eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
02662 prev_eu = BU_LIST_PPREV_CIRC( edgeuse, &eu2->l );
02663
02664 if( hitv != prev_eu->vu_p->v_p && hitv != next_eu->eumate_p->vu_p->v_p )
02665 {
02666 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02667 {
02668 vect_t tmp1, tmp2;
02669 VSUB2( tmp1, hit_pt, eu2->vu_p->v_p->vg_p->coord )
02670 VSUB2( tmp2, hit_pt, eu2->eumate_p->vu_p->v_p->vg_p->coord )
02671 bu_log( "Splitting eu2 x%x\n", eu2 );
02672 bu_log( "Distance to hit_pt = %g from vu1, %g from vu2\n",
02673 MAGNITUDE( tmp1 ), MAGNITUDE( tmp2 ) );
02674 }
02675 new_eu = nmg_esplit( hitv, eu2, 1 );
02676 hitv = new_eu->vu_p->v_p;
02677 if( !hitv->vg_p )
02678 nmg_vertex_gv( hitv, hit_pt );
02679 bu_ptbl_ins( &eu2_list, (long *)new_eu );
02680 }
02681 }
02682
02683 if( hitv )
02684 (void)nmg_break_all_es_on_v( &m->magic, hitv, &is->tol );
02685 }
02686 }
02687 }
02688
02689 bu_ptbl_free( &eu1_list);
02690 bu_ptbl_free( &eu2_list);
02691
02692
02693
02694
02695 nmg_vertex_tabulate( &v_list, &fu1->l.magic );
02696
02697 for( i=0 ; i<BU_PTBL_END( &v_list ) ; i++ )
02698 {
02699 struct vertex *v;
02700 int class;
02701
02702 v = (struct vertex *)BU_PTBL_GET( &v_list, i );
02703 NMG_CK_VERTEX( v );
02704
02705 if( nmg_find_v_in_face( v, fu2 ) )
02706 continue;
02707
02708
02709 class = nmg_class_pt_fu_except( v->vg_p->coord, fu2, NULL, NULL, NULL,
02710 (char *)NULL, 0, 0, &is->tol );
02711
02712 if( class == NMG_CLASS_AinB )
02713 {
02714 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02715 bu_log( "Making dualvu of vertex x%x in fu2 x%x\n", v, fu2 );
02716 (void)nmg_make_dualvu( v, fu2, &is->tol );
02717 }
02718 }
02719 bu_ptbl_reset( &v_list);
02720
02721
02722 nmg_vertex_tabulate( &v_list, &fu2->l.magic );
02723
02724 for( i=0 ; i<BU_PTBL_END( &v_list ) ; i++ )
02725 {
02726 struct vertex *v;
02727 int class;
02728
02729 v = (struct vertex *)BU_PTBL_GET( &v_list, i );
02730 NMG_CK_VERTEX( v );
02731
02732 if( nmg_find_v_in_face( v, fu1 ) )
02733 continue;
02734
02735
02736 class = nmg_class_pt_fu_except( v->vg_p->coord, fu1, NULL, NULL, NULL,
02737 (char *)NULL, 0, 0, &is->tol );
02738
02739 if( class == NMG_CLASS_AinB )
02740 {
02741 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02742 bu_log( "Making dualvu of vertex x%x in fu1 x%x\n", v, fu1 );
02743 (void)nmg_make_dualvu( v, fu1, &is->tol );
02744 }
02745 }
02746
02747 bu_ptbl_free( &v_list);
02748
02749 bu_ptbl_init( &vert_list1, 64, " &vert_list1");
02750 bu_ptbl_init( &vert_list2, 64, " &vert_list2");
02751 is->l1 = &vert_list1;
02752 is->l2 = &vert_list2;
02753
02754 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
02755 {
02756 struct edgeuse *eu;
02757
02758 NMG_CK_LOOPUSE( lu );
02759
02760 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02761 continue;
02762
02763 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02764 {
02765 struct vertexuse *vu;
02766 struct vertex *v1,*v2;
02767
02768 NMG_CK_EDGEUSE( eu );
02769
02770 v1 = eu->vu_p->v_p;
02771 NMG_CK_VERTEX( v1 );
02772 v2 = eu->eumate_p->vu_p->v_p;
02773 NMG_CK_VERTEX( v2 );
02774
02775 if( !nmg_find_v_in_face( v1, fu2 ) ||
02776 !nmg_find_v_in_face( v2, fu2 ) )
02777 continue;
02778
02779 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02780 bu_log( "Making EU x%x an intersect line for face cutting\n", eu );
02781
02782 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
02783 {
02784 struct faceuse *fu;
02785
02786 fu = nmg_find_fu_of_vu( vu );
02787
02788 if( fu == fu2 )
02789 nmg_enlist_one_vu( is, vu, 0.0 );
02790 }
02791
02792 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
02793 {
02794 struct faceuse *fu;
02795
02796 fu = nmg_find_fu_of_vu( vu );
02797
02798 if( fu == fu2 )
02799 nmg_enlist_one_vu( is, vu, 1.0 );
02800 }
02801
02802
02803 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02804 bu_log( "Calling face cutter for fu2 x%x\n", fu2 );
02805 nmg_fcut_face_2d( is->l2, is->mag2, fu2, fu1, &is->tol );
02806
02807 bu_ptbl_reset( is->l1);
02808 bu_ptbl_reset( is->l2);
02809 }
02810 }
02811
02812 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
02813 {
02814 struct edgeuse *eu;
02815
02816 NMG_CK_LOOPUSE( lu );
02817
02818 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02819 continue;
02820
02821 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02822 {
02823 struct vertexuse *vu;
02824 struct vertex *v1,*v2;
02825
02826 NMG_CK_EDGEUSE( eu );
02827
02828 v1 = eu->vu_p->v_p;
02829 NMG_CK_VERTEX( v1 );
02830 v2 = eu->eumate_p->vu_p->v_p;
02831 NMG_CK_VERTEX( v2 );
02832
02833 if( !nmg_find_v_in_face( v1, fu1 ) ||
02834 !nmg_find_v_in_face( v2, fu1 ) )
02835 continue;
02836
02837 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02838 bu_log( "Making EU x%x an intersect line for face cutting\n", eu );
02839
02840 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
02841 {
02842 struct faceuse *fu;
02843
02844 fu = nmg_find_fu_of_vu( vu );
02845
02846 if( fu == fu1 )
02847 nmg_enlist_one_vu( is, vu, 0.0 );
02848 }
02849
02850 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
02851 {
02852 struct faceuse *fu;
02853
02854 fu = nmg_find_fu_of_vu( vu );
02855
02856 if( fu == fu1 )
02857 nmg_enlist_one_vu( is, vu, 1.0 );
02858 }
02859
02860
02861 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02862 bu_log( "Calling face cutter for fu1 x%x\n", fu1 );
02863 nmg_fcut_face_2d( is->l1, is->mag1, fu1, fu2, &is->tol );
02864
02865 bu_ptbl_reset( is->l1);
02866 bu_ptbl_reset( is->l2);
02867 }
02868 }
02869 if( mag1 )
02870 bu_free( (char *)mag1, "mag1" );
02871 if( mag2 )
02872 bu_free( (char *)mag2, "mag2" );
02873
02874 bu_ptbl_free( is->l1);
02875 bu_ptbl_free( is->l2);
02876 }
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903 #if 0
02904 static void
02905 nmg_isect_two_face2p( is, fu1, fu2 )
02906 struct nmg_inter_struct *is;
02907 struct faceuse *fu1, *fu2;
02908 {
02909 struct model *m;
02910 struct loopuse *lu;
02911 struct edgeuse *eu;
02912 struct vertexuse *vu;
02913 unsigned char *tags;
02914 int tagsize;
02915
02916 NMG_CK_INTER_STRUCT(is);
02917 NMG_CK_FACEUSE(fu1);
02918 NMG_CK_FACEUSE(fu2);
02919 m = fu1->s_p->r_p->m_p;
02920 NMG_CK_MODEL(m);
02921
02922 is->l1 = 0;
02923 is->l2 = 0;
02924 is->fu1 = fu1;
02925 is->fu2 = fu2;
02926
02927 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02928 bu_log("nmg_isect_two_face2p(fu1=x%x, fu2=x%x) START\n", fu1, fu2);
02929
02930
02931 tagsize = 4 * m->maxindex+1;
02932 tags = (unsigned char *)bu_calloc( tagsize, 1, "nmg_isect_two_face2p() tags[]" );
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942 bzero( (char *)tags, tagsize );
02943 f1_again:
02944 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
02945 nmg_fu_touchingloops(fu1);
02946 nmg_fu_touchingloops(fu2);
02947 nmg_region_v_unique( fu1->s_p->r_p, &is->tol );
02948 nmg_region_v_unique( fu2->s_p->r_p, &is->tol );
02949 }
02950 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) ) {
02951 NMG_CK_LOOPUSE(lu);
02952 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC ) {
02953 is->l1 = 0;
02954 is->l2 = 0;
02955 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
02956 if( !NMG_INDEX_FIRST_TIME(tags, vu->v_p) ) continue;
02957 nmg_isect_vert2p_face2p( is, vu, fu2 );
02958 continue;
02959 }
02960 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
02961 struct edge_g_lseg *eg;
02962
02963 NMG_CK_EDGEUSE(eu);
02964 eg = eu->g.lseg_p;
02965
02966 if( eg && !NMG_INDEX_FIRST_TIME(tags, eg) ) continue;
02967
02968 if( nmg_isect_edge2p_face2p( is, eu, fu2, fu1 ) ) {
02969
02970
02971
02972 goto f1_again;
02973 }
02974 }
02975 }
02976
02977
02978 nmg_isect2d_cleanup(is);
02979
02980
02981 bzero( (char *)tags, tagsize );
02982 f2_again:
02983 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
02984 nmg_fu_touchingloops(fu1);
02985 nmg_fu_touchingloops(fu2);
02986 nmg_region_v_unique( fu1->s_p->r_p, &is->tol );
02987 nmg_region_v_unique( fu2->s_p->r_p, &is->tol );
02988 }
02989 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) ) {
02990 NMG_CK_LOOPUSE(lu);
02991 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC ) {
02992 is->l1 = 0;
02993 is->l2 = 0;
02994 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
02995 if( !NMG_INDEX_FIRST_TIME(tags, vu->v_p) ) continue;
02996 nmg_isect_vert2p_face2p( is, vu, fu1 );
02997 continue;
02998 }
02999 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
03000 struct edge_g_lseg *eg;
03001
03002 NMG_CK_EDGEUSE(eu);
03003 eg = eu->g.lseg_p;
03004
03005 if( eg && !NMG_INDEX_FIRST_TIME(tags, eg) ) continue;
03006
03007 if( nmg_isect_edge2p_face2p( is, eu, fu1, fu2 ) ) {
03008
03009 goto f2_again;
03010 }
03011 }
03012 }
03013 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
03014 nmg_fu_touchingloops(fu1);
03015 nmg_fu_touchingloops(fu2);
03016 nmg_region_v_unique( fu1->s_p->r_p, &is->tol );
03017 nmg_region_v_unique( fu2->s_p->r_p, &is->tol );
03018 }
03019 bu_free( (char *)tags, "tags[]" );
03020 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03021 bu_log("nmg_isect_two_face2p(fu1=x%x, fu2=x%x) END\n", fu1, fu2);
03022 }
03023 #endif
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 int
03038 nmg_isect_line2_edge2p(struct nmg_inter_struct *is, struct bu_ptbl *list, struct edgeuse *eu1, struct faceuse *fu1, struct faceuse *fu2)
03039 {
03040 point_t eu1_start;
03041 point_t eu1_end;
03042 vect_t eu1_dir;
03043 fastf_t dist[2];
03044 int status;
03045 point_t hit_pt;
03046 struct vertexuse *vu1a, *vu1b;
03047 int ret = 0;
03048
03049 NMG_CK_INTER_STRUCT(is);
03050 BU_CK_PTBL(list);
03051 NMG_CK_EDGEUSE(eu1);
03052 NMG_CK_FACEUSE(fu1);
03053 NMG_CK_FACEUSE(fu2);
03054
03055
03056
03057
03058
03059
03060 vu1a = eu1->vu_p;
03061 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
03062 NMG_CK_VERTEXUSE(vu1a);
03063 NMG_CK_VERTEXUSE(vu1b);
03064
03065 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03066 bu_log("nmg_isect_line2_edge2p(eu1=x%x, fu1=x%x)\n\tvu1a=%x vu1b=%x\n\tv2a=%x v2b=%x\n",
03067 eu1, fu1,
03068 vu1a, vu1b,
03069 vu1a->v_p, vu1b->v_p );
03070 }
03071
03072
03073
03074
03075 nmg_get_2d_vertex( eu1_start, vu1a->v_p, is, &fu1->l.magic );
03076 nmg_get_2d_vertex( eu1_end, vu1b->v_p, is, &fu1->l.magic );
03077 VSUB2_2D( eu1_dir, eu1_end, eu1_start );
03078
03079 dist[0] = dist[1] = 0;
03080
03081
03082 status = bn_isect_line2_lseg2( dist, is->pt2d, is->dir2d,
03083 eu1_start, eu1_dir, &is->tol );
03084
03085 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03086 bu_log("\tbn_isect_line2_lseg2()=%d, dist: %g, %g\n",
03087 status, dist[0], dist[1] );
03088 }
03089
03090 if (status < 0) goto out;
03091
03092 if( status == 0 ) {
03093
03094
03095
03096
03097 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03098 bu_log("\t\tedge colinear with isect line. Listing vu1a, vu1b\n");
03099 nmg_enlist_vu(is, vu1a, 0, MAX_FASTF);
03100 nmg_enlist_vu(is, vu1b, 0, MAX_FASTF);
03101 ret = 0;
03102 goto out;
03103 }
03104
03105
03106
03107 VJOIN1( hit_pt, is->pt, dist[0], is->dir );
03108
03109
03110
03111
03112 if( status == 1 || dist[1] == 0 ) {
03113 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03114 bu_log("\t\tintersect point is vu1a\n");
03115 if( !bn_pt3_pt3_equal(hit_pt, vu1a->v_p->vg_p->coord, &(is->tol) ) )
03116 rt_bomb("vu1a does not match calculated point\n");
03117 nmg_enlist_vu(is, vu1a, 0, MAX_FASTF);
03118 ret = 0;
03119 } else if( status == 2 || dist[1] == 1 ) {
03120 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03121 bu_log("\t\tintersect point is vu1b\n");
03122 if( !bn_pt3_pt3_equal(hit_pt, vu1b->v_p->vg_p->coord, &(is->tol) ) )
03123 rt_bomb("vu1b does not match calculated point\n");
03124 nmg_enlist_vu(is, vu1b, 0, MAX_FASTF);
03125 ret = 0;
03126 } else {
03127
03128 struct vertexuse *vu1_final;
03129 struct vertex *new_v;
03130 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03131 fastf_t dist;
03132 int code;
03133 bu_log("\t2D: pt2d=(%g, %g), dir2d=(%g, %g)\n",
03134 is->pt2d[X], is->pt2d[Y],
03135 is->dir2d[X], is->dir2d[Y] );
03136 bu_log("\t2D: eu1_start=(%g, %g), eu1_dir=(%g, %g)\n",
03137 eu1_start[X], eu1_start[Y],
03138 eu1_dir[X], eu1_dir[Y] );
03139 VPRINT("\t3D: is->pt ", is->pt);
03140 VPRINT("\t3D: is->dir", is->dir);
03141 bu_log("\t2d: Breaking eu1 at isect.\n");
03142 VPRINT(" vu1a", vu1a->v_p->vg_p->coord);
03143 VPRINT("hit_pt", hit_pt);
03144 VPRINT(" vu1b", vu1b->v_p->vg_p->coord);
03145
03146 code = bn_isect_pt_lseg( &dist, vu1a->v_p->vg_p->coord,
03147 vu1b->v_p->vg_p->coord,
03148 hit_pt, &(is->tol) );
03149 bu_log("\tbn_isect_pt_lseg() dist=%g, ret=%d\n", dist, code);
03150 if( code < 0 ) rt_bomb("3D point not on 3D lseg\n");
03151
03152
03153 if( !bn_between(vu1a->v_p->vg_p->coord[X], hit_pt[X], vu1b->v_p->vg_p->coord[X], &(is->tol)) ||
03154 !bn_between(vu1a->v_p->vg_p->coord[Y], hit_pt[Y], vu1b->v_p->vg_p->coord[Y], &(is->tol)) ||
03155 !bn_between(vu1a->v_p->vg_p->coord[Z], hit_pt[Z], vu1b->v_p->vg_p->coord[Z], &(is->tol)) ) {
03156 VPRINT("vu1a", vu1a->v_p->vg_p->coord);
03157 VPRINT("hitp", hit_pt);
03158 VPRINT("vu1b", vu1b->v_p->vg_p->coord);
03159 rt_bomb("nmg_isect_line2_edge2p() hit point not between edge verts!\n");
03160 }
03161
03162 }
03163
03164
03165
03166
03167
03168
03169 new_v = nmg_find_pt_in_model(fu2->s_p->r_p->m_p, hit_pt, &(is->tol));
03170 vu1_final = nmg_ebreaker(new_v, eu1, &is->tol)->vu_p;
03171 ret = 1;
03172 if( !new_v ) {
03173 nmg_vertex_gv( vu1_final->v_p, hit_pt );
03174 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03175 bu_log("\t\tmaking new vertex vu=x%x v=x%x\n",
03176 vu1_final, vu1_final->v_p);
03177 } else {
03178 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03179 bu_log("\t\tre-using vertex v=x%x vu=x%x\n", new_v, vu1_final);
03180 }
03181 nmg_enlist_vu(is, vu1_final, 0, MAX_FASTF);
03182
03183 nmg_ck_face_worthless_edges( fu1 );
03184 }
03185
03186 out:
03187 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03188 bu_log("nmg_isect_line2_edge2p(eu1=x%x, fu1=x%x) END ret=%d\n", eu1, fu1, ret);
03189 return ret;
03190 }
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200 void
03201 nmg_isect_line2_vertex2(struct nmg_inter_struct *is, struct vertexuse *vu1, struct faceuse *fu1)
03202 {
03203
03204 NMG_CK_INTER_STRUCT(is);
03205 NMG_CK_VERTEXUSE(vu1);
03206 NMG_CK_FACEUSE(fu1);
03207
03208 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03209 bu_log("nmg_isect_line2_vertex2(vu=x%x)\n", vu1);
03210
03211
03212 if( bn_distsq_line3_pt3( is->pt, is->dir, vu1->v_p->vg_p->coord ) > is->tol.dist_sq )
03213 return;
03214
03215 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03216 bu_log("nmg_isect_line2_vertex2(vu=x%x) line hits vertex v=x%x\n", vu1, vu1->v_p);
03217
03218 nmg_enlist_vu( is, vu1, 0, MAX_FASTF );
03219 }
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231 int
03232 nmg_isect_two_ptbls(struct nmg_inter_struct *is, const struct bu_ptbl *t1, const struct bu_ptbl *t2)
03233 {
03234 const struct edgeuse **eu1;
03235 const struct edgeuse **eu2;
03236 struct vertexuse *vu1a;
03237 struct vertexuse *vu1b;
03238
03239 NMG_CK_INTER_STRUCT(is);
03240 BU_CK_PTBL(t1);
03241
03242 for( eu1 = (const struct edgeuse **)BU_PTBL_LASTADDR(t1);
03243 eu1 >= (const struct edgeuse **)BU_PTBL_BASEADDR(t1); eu1--
03244 ) {
03245 struct vertex *v1a;
03246 struct vertex *v1b;
03247
03248 vu1a = (*eu1)->vu_p;
03249 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, (*eu1) )->vu_p;
03250 NMG_CK_VERTEXUSE(vu1a);
03251 NMG_CK_VERTEXUSE(vu1b);
03252 v1a = vu1a->v_p;
03253 v1b = vu1b->v_p;
03254
03255 for( eu2 = (const struct edgeuse **)BU_PTBL_LASTADDR(t2);
03256 eu2 >= (const struct edgeuse **)BU_PTBL_BASEADDR(t2); eu2--
03257 ) {
03258 register struct vertexuse *vu2a;
03259 register struct vertexuse *vu2b;
03260
03261 vu2a = (*eu2)->vu_p;
03262 vu2b = BU_LIST_PNEXT_CIRC( edgeuse, (*eu2) )->vu_p;
03263 NMG_CK_VERTEXUSE(vu2a);
03264 NMG_CK_VERTEXUSE(vu2b);
03265
03266 if( v1a == vu2a->v_p ) {
03267 vu1b = vu2a;
03268 goto enlist;
03269 }
03270 if( v1a == vu2b->v_p ) {
03271 vu1b = vu2b;
03272 goto enlist;
03273 }
03274 if( v1b == vu2a->v_p ) {
03275 vu1a = vu1b;
03276 vu1b = vu2a;
03277 goto enlist;
03278 }
03279 if( v1b == vu2b->v_p ) {
03280 vu1a = vu1b;
03281 vu1b = vu2b;
03282 goto enlist;
03283 }
03284 }
03285 }
03286 return 0;
03287 enlist:
03288
03289 if( nmg_find_s_of_vu(vu1a) == nmg_find_s_of_vu(vu1b) ) {
03290 vu1b = 0;
03291 }
03292
03293 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03294 bu_log("nmg_isect_two_ptbls() intersection! vu=x%x, vu_dual=x%x\n",
03295 vu1a, vu1b );
03296 }
03297 nmg_enlist_vu( is, vu1a, vu1b, MAX_FASTF );
03298 return 1;
03299 }
03300
03301
03302
03303
03304
03305
03306
03307 struct edge_g_lseg *
03308 nmg_find_eg_on_line(const long int *magic_p, const fastf_t *pt, const fastf_t *dir, const struct bn_tol *tol)
03309 {
03310 struct bu_ptbl eutab;
03311 struct edgeuse **eup;
03312 struct edge_g_lseg *ret = (struct edge_g_lseg *)NULL;
03313 vect_t dir1, dir2;
03314
03315 BN_CK_TOL(tol);
03316
03317 nmg_edgeuse_on_line_tabulate( &eutab, magic_p, pt, dir, tol );
03318
03319 for( eup = (struct edgeuse **)BU_PTBL_LASTADDR(&eutab);
03320 eup >= (struct edgeuse **)BU_PTBL_BASEADDR(&eutab); eup--
03321 ) {
03322 if( !ret ) {
03323
03324 ret = (*eup)->g.lseg_p;
03325 continue;
03326 }
03327 if( (*eup)->g.lseg_p == ret ) continue;
03328
03329
03330 VMOVE( dir1, ret->e_dir );
03331 VUNITIZE(dir1);
03332 VMOVE( dir2, (*eup)->g.lseg_p->e_dir );
03333 VUNITIZE(dir2);
03334 if( fabs(VDOT(dir1,dir)) > fabs(VDOT(dir2,dir)) ) {
03335
03336 } else {
03337
03338 ret = (*eup)->g.lseg_p;
03339 }
03340 bu_log("nmg_find_eg_on_line() 2 different eg's, taking better one.\n");
03341 }
03342 (void)bu_ptbl_free( &eutab);
03343 if( rt_g.NMG_debug & DEBUG_POLYSECT) {
03344 bu_log("rt_find_eg_on_line( x%x ) ret=x%x\n", magic_p, ret);
03345 }
03346 return ret;
03347 }
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358 int
03359 nmg_k0eu(struct vertex *v)
03360 {
03361 struct edgeuse *eu;
03362 struct vertexuse *vu;
03363 int count = 0;
03364
03365 NMG_CK_VERTEX(v);
03366 top:
03367 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) ) {
03368 NMG_CK_VERTEXUSE(vu);
03369 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
03370 eu = vu->up.eu_p;
03371 NMG_CK_EDGEUSE(eu);
03372 if( eu->eumate_p->vu_p->v_p != v ) continue;
03373 bu_log("nmg_k0eu(v=x%x) killing 0-len eu=x%x, mate=x%x\n",
03374 v, eu, eu->eumate_p);
03375 nmg_pr_eu_briefly(eu, 0);
03376 nmg_pr_eu_briefly(eu->eumate_p, 0);
03377 if( nmg_keu(eu) ) {
03378 bu_log("nmg_k0eu() WARNING: parent now has no edgeuses\n");
03379
03380 }
03381 count++;
03382 goto top;
03383 }
03384 return count;
03385 }
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398 struct vertex *
03399 nmg_repair_v_near_v(struct vertex *hit_v, struct vertex *v, const struct edge_g_lseg *eg1, const struct edge_g_lseg *eg2, int bomb, const struct bn_tol *tol)
03400
03401
03402
03403
03404
03405
03406 {
03407 NMG_CK_VERTEX(hit_v);
03408 NMG_CK_VERTEX(v);
03409 if(eg1) NMG_CK_EDGE_G_LSEG(eg1);
03410 NMG_CK_EDGE_G_LSEG(eg2);
03411 BN_CK_TOL(tol);
03412
03413 bu_log("nmg_repair_v_near_v(hit_v=x%x, v=x%x)\n", hit_v, v );
03414
03415 VPRINT("v ", v->vg_p->coord);
03416 VPRINT("hit", hit_v->vg_p->coord);
03417 bu_log("dist v-hit=%g, equal=%d\n",
03418 bn_dist_pt3_pt3(v->vg_p->coord, hit_v->vg_p->coord),
03419 bn_pt3_pt3_equal(v->vg_p->coord, hit_v->vg_p->coord, tol)
03420 );
03421 if( eg1 ) {
03422 if( bn_2line3_colinear( eg1->e_pt, eg1->e_dir, eg2->e_pt, eg2->e_dir, 1e5, tol ) )
03423 rt_bomb("ERROR: nmg_repair_v_near_v() eg1 and eg2 are colinear!\n");
03424 bu_log("eg1: line/ vu dist=%g, hit dist=%g\n",
03425 bn_dist_line3_pt3( eg1->e_pt, eg1->e_dir, v->vg_p->coord ),
03426 bn_dist_line3_pt3( eg1->e_pt, eg1->e_dir, hit_v->vg_p->coord ) );
03427 bu_log("eg2: line/ vu dist=%g, hit dist=%g\n",
03428 bn_dist_line3_pt3( eg2->e_pt, eg2->e_dir, v->vg_p->coord ),
03429 bn_dist_line3_pt3( eg2->e_pt, eg2->e_dir, hit_v->vg_p->coord ) );
03430 nmg_pr_eg(&eg1->l.magic, 0);
03431 nmg_pr_eg(&eg2->l.magic, 0);
03432 }
03433
03434 if( bn_dist_pt3_pt3(v->vg_p->coord,
03435 hit_v->vg_p->coord) < 10 * tol->dist ) {
03436 struct edgeuse *eu0;
03437 bu_log("NOTICE: The intersection of two lines has resulted in 2 different intersect points\n");
03438 bu_log(" Since the two points are 'close', they are being fused.\n");
03439
03440
03441 eu0 = nmg_findeu(hit_v, v, (struct shell *)NULL,
03442 (struct edgeuse *)NULL, 0);
03443 if( eu0 ) {
03444 bu_log("DANGER: a 0-length edge is being created eu0=x%x\n", eu0);
03445 }
03446
03447 nmg_jv(hit_v, v);
03448 (void)nmg_k0eu(hit_v);
03449 goto out;
03450 }
03451
03452
03453 rt_bomb("nmg_repair_v_near_v() separation is too great to repair.\n");
03454 hit_v = (struct vertex *)NULL;
03455 out:
03456 bu_log("nmg_repair_v_near_v(v=x%x) ret=x%x\n", v, hit_v);
03457 return hit_v;
03458 }
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471 struct vertex *
03472 nmg_search_v_eg(const struct edgeuse *eu, int second, const struct edge_g_lseg *eg1, const struct edge_g_lseg *eg2, register struct vertex *hit_v, const struct bn_tol *tol)
03473
03474
03475
03476
03477
03478
03479 {
03480 struct vertex *v;
03481 register struct vertexuse *vu1;
03482 register struct edgeuse *seen1 = (struct edgeuse *)NULL;
03483 register struct edgeuse *seen2 = (struct edgeuse *)NULL;
03484
03485 NMG_CK_EDGEUSE(eu);
03486 NMG_CK_EDGE_G_LSEG(eg1);
03487 NMG_CK_EDGE_G_LSEG(eg2);
03488 BN_CK_TOL(tol);
03489
03490 if( second ) {
03491 v = BU_LIST_PNEXT_CIRC(edgeuse, eu)->vu_p->v_p;
03492 if( v != eu->eumate_p->vu_p->v_p )
03493 rt_bomb("nmg_search_v_eg() next vu not mate's vu?\n");
03494 } else {
03495 v = eu->vu_p->v_p;
03496 }
03497 NMG_CK_VERTEX(v);
03498
03499 if( eu->g.lseg_p != eg1 ) rt_bomb("nmg_search_v_eg() eu not on eg1\n");
03500
03501
03502 if( bn_distsq_line3_pt3( eg1->e_pt, eg1->e_dir, v->vg_p->coord ) > tol->dist_sq ) {
03503 VPRINT("v", v->vg_p->coord);
03504 nmg_pr_eu( eu, (char *)NULL );
03505 nmg_pr_eg( &eg1->l.magic, 0 );
03506 rt_bomb("nmg_search_v_eg() eu vertex not on eg line\n");
03507 }
03508
03509
03510 for( BU_LIST_FOR( vu1, vertexuse, &v->vu_hd ) ) {
03511 register struct edgeuse *eu1;
03512
03513 if( *vu1->up.magic_p != NMG_EDGEUSE_MAGIC ) continue;
03514 eu1 = vu1->up.eu_p;
03515 if( eu1->g.lseg_p == eg1 ) seen1 = eu1;
03516 if( eu1->g.lseg_p == eg2 ) seen2 = eu1;
03517 if( !seen1 || !seen2 ) continue;
03518
03519
03520 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03521 bu_log(" seen1=x%x, seen2=x%x, hit_v=x%x, v=x%x\n",
03522 seen1, seen2, hit_v, v);
03523 }
03524 if( !hit_v ) {
03525 hit_v = v;
03526 break;
03527 }
03528
03529
03530 if( hit_v == v ) break;
03531
03532
03533 bu_log("ERROR seen1=x%x, seen2=x%x, hit_v=x%x != v=x%x\n",
03534 seen1, seen2, hit_v, v);
03535 if( nmg_repair_v_near_v( hit_v, v, eg1, eg2, 0, tol ) )
03536 break;
03537
03538 rt_bomb("nmg_search_v_eg() two different vertices for intersect point?\n");
03539 }
03540 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03541 bu_log("nmg_search_v_eg(eu=x%x, %d, eg1=x%x, eg2=x%x) ret=x%x\n",
03542 eu, second, eg1, eg2, hit_v);
03543 }
03544 return hit_v;
03545 }
03546
03547
03548
03549
03550
03551
03552
03553 struct vertex *
03554 nmg_common_v_2eg(struct edge_g_lseg *eg1, struct edge_g_lseg *eg2, const struct bn_tol *tol)
03555 {
03556 struct edgeuse *eu1;
03557 struct vertex *hit_v = (struct vertex *)NULL;
03558 struct bu_list *midway;
03559
03560 NMG_CK_EDGE_G_LSEG(eg1);
03561 NMG_CK_EDGE_G_LSEG(eg2);
03562 BN_CK_TOL(tol);
03563
03564 if( eg1 == eg2 )
03565 rt_bomb("nmg_common_v_2eg() eg1 and eg2 are colinear\n");
03566
03567
03568 for( BU_LIST_FOR( midway, bu_list, &eg1->eu_hd2 ) ) {
03569 NMG_CKMAG(midway, NMG_EDGEUSE2_MAGIC, "edgeuse2 [l2]");
03570 eu1 = BU_LIST_MAIN_PTR( edgeuse, midway, l2 );
03571 NMG_CK_EDGEUSE(eu1);
03572 if( eu1->g.lseg_p != eg1 ) rt_bomb("nmg_common_v_2eg() eu disavows eg\n");
03573
03574 hit_v = nmg_search_v_eg( eu1, 0, eg1, eg2, hit_v, tol );
03575 hit_v = nmg_search_v_eg( eu1, 1, eg1, eg2, hit_v, tol );
03576 }
03577 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
03578 bu_log("nmg_common_v_2eg(eg1=x%x, eg2=x%x) hit_v=x%x\n",
03579 eg1, eg2, hit_v);
03580 }
03581 return hit_v;
03582 }
03583
03584 #define VDIST( a, b ) sqrt( (a[X]-b[X])*(a[X]-b[X]) + (a[Y]-b[Y])*(a[Y]-b[Y]) + (a[Z]-b[Z])*(a[Z]-b[Z]) )
03585 #define VDIST_SQ( a, b ) ( (a[X]-b[X])*(a[X]-b[X]) + (a[Y]-b[Y])*(a[Y]-b[Y]) + (a[Z]-b[Z])*(a[Z]-b[Z]) )
03586
03587 int
03588 nmg_is_vertex_on_inter(struct vertex *v, struct faceuse *fu1, struct faceuse *fu2, struct nmg_inter_struct *is)
03589 {
03590 struct vertex_g *vg;
03591 plane_t pl1,pl2;
03592 int code;
03593 fastf_t dist;
03594
03595 NMG_CK_VERTEX( v );
03596 NMG_CK_FACEUSE( fu1 );
03597 NMG_CK_FACEUSE( fu2 );
03598 NMG_CK_INTER_STRUCT(is);
03599
03600 if( nmg_find_v_in_face( v, fu1 ) && nmg_find_v_in_face( v, fu2 ) )
03601 return( 1 );
03602
03603 NMG_GET_FU_PLANE( pl1, fu1 );
03604 NMG_GET_FU_PLANE( pl2, fu2 );
03605
03606 vg = v->vg_p;
03607 NMG_CK_VERTEX_G( vg );
03608
03609
03610 dist = fabs( DIST_PT_PLANE( vg->coord, pl1 ) );
03611 if( dist > is->tol.dist )
03612 return( 0 );
03613 dist = fabs( DIST_PT_PLANE( vg->coord, pl2 ) );
03614 if( dist > is->tol.dist )
03615 return( 0 );
03616
03617
03618 if( bn_distsq_line3_pt3( is->pt, is->dir, vg->coord ) > is->tol.dist_sq )
03619 return( 0 );
03620
03621
03622 code = nmg_class_pt_fu_except( vg->coord, fu1, (struct loopuse *)NULL,
03623 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0, 0, &is->tol );
03624 if( code != NMG_CLASS_AinB )
03625 return( 0 );
03626
03627 code = nmg_class_pt_fu_except( vg->coord, fu2, (struct loopuse *)NULL,
03628 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0, 0, &is->tol );
03629 if( code != NMG_CLASS_AinB )
03630 return( 0 );
03631
03632 return( 1 );
03633 }
03634
03635 void
03636 nmg_isect_eu_verts(struct edgeuse *eu, struct vertex_g *vg1, struct vertex_g *vg2, struct bu_ptbl *verts, struct bu_ptbl *inters, const struct bn_tol *tol)
03637 {
03638 int i;
03639 struct vertex *v1,*v2;
03640
03641 NMG_CK_EDGEUSE( eu );
03642 NMG_CK_VERTEX_G( vg1 );
03643 NMG_CK_VERTEX_G( vg2 );
03644 BU_CK_PTBL( verts );
03645 BU_CK_PTBL( inters );
03646 BN_CK_TOL( tol );
03647
03648 v1 = eu->vu_p->v_p;
03649 v2 = eu->eumate_p->vu_p->v_p;
03650
03651 for( i=0 ; i<BU_PTBL_END( verts ) ; i++ )
03652 {
03653 struct vertex *v;
03654 fastf_t dist;
03655 point_t pca;
03656 int code;
03657
03658 v = (struct vertex *)BU_PTBL_GET( verts, i );
03659 if( v == v1 || v == v2 )
03660 {
03661 bu_ptbl_ins_unique( inters, (long *)v );
03662 continue;
03663 }
03664
03665 code = bn_dist_pt3_lseg3( &dist, pca, vg1->coord,
03666 vg2->coord, v->vg_p->coord, tol );
03667
03668 if( code )
03669 continue;
03670
03671 bu_ptbl_ins_unique( inters, (long *)v );
03672 }
03673
03674 return;
03675 }
03676
03677 void
03678 nmg_isect_eu_eu(struct edgeuse *eu1, struct vertex_g *vg1a, struct vertex_g *vg1b, fastf_t *dir1, struct edgeuse *eu2, struct bu_ptbl *verts, struct bu_ptbl *inters, const struct bn_tol *tol)
03679 {
03680 struct model *m;
03681 struct vertex_g *vg2a,*vg2b;
03682 vect_t dir2;
03683 fastf_t dist[2];
03684 int code;
03685 point_t hit_pt;
03686 vect_t diff;
03687
03688 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03689 bu_log( "nmg_isect_eu_eu( eu1=x%x, eu2=x%x )\n", eu1, eu2 );
03690
03691 NMG_CK_EDGEUSE( eu1 );
03692 NMG_CK_VERTEX_G( vg1a );
03693 NMG_CK_VERTEX_G( vg1b );
03694 NMG_CK_EDGEUSE( eu2 );
03695 BN_CK_TOL( tol );
03696 BU_CK_PTBL( inters );
03697 BU_CK_PTBL( verts );
03698
03699 m = nmg_find_model( &eu1->l.magic );
03700 NMG_CK_MODEL( m );
03701
03702 vg2a = eu2->vu_p->v_p->vg_p;
03703 NMG_CK_VERTEX_G( vg2a );
03704
03705 vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
03706 NMG_CK_VERTEX_G( vg2b );
03707
03708 VSUB2( dir2, vg2b->coord, vg2a->coord );
03709
03710 code = bn_isect_lseg3_lseg3( dist, vg1a->coord, dir1, vg2a->coord, dir2, tol );
03711
03712 if( code < 0 )
03713 {
03714 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03715 bu_log( "\tnmg_isect_eu_eu: No intersection\n" );
03716 return;
03717 }
03718
03719 if( code == 1 )
03720 {
03721 point_t hit_pt1,hit_pt2;
03722 struct vertex *v=(struct vertex *)NULL;
03723 struct edgeuse *new_eu;
03724
03725
03726
03727 if( eu1->vu_p->v_p == eu2->vu_p->v_p ||
03728 eu1->vu_p->v_p == eu2->eumate_p->vu_p->v_p ||
03729 eu1->eumate_p->vu_p->v_p == eu2->vu_p->v_p ||
03730 eu1->eumate_p->vu_p->v_p == eu2->eumate_p->vu_p->v_p )
03731 return;
03732
03733 if( dist[0] == 0.0 || dist[0] == 1.0 )
03734 return;
03735
03736 if( dist[1] == 0.0 )
03737 {
03738 bu_ptbl_ins_unique( inters, (long *)eu2->vu_p->v_p );
03739 return;
03740 }
03741 if( dist[1] == 1.0 )
03742 {
03743 bu_ptbl_ins_unique( inters, (long *)eu2->eumate_p->vu_p->v_p );
03744 return;
03745 }
03746
03747 VJOIN1( hit_pt1, vg1a->coord, dist[0], dir1 );
03748 VJOIN1( hit_pt2, vg2a->coord, dist[1], dir2 );
03749
03750 VBLEND2( hit_pt, 0.5, hit_pt1, 0.5, hit_pt2 );
03751
03752 v = nmg_find_pt_in_model( m, hit_pt, tol );
03753
03754 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03755 {
03756 bu_log( "nmg_isect_eu_eu: intersection at (%g %g %g)\n", V3ARGS( hit_pt ) );
03757 bu_log( "splitting eu x%x at v=x%x\n", eu2, v );
03758 }
03759 new_eu = nmg_esplit( v, eu2, 1 );
03760 if( !v )
03761 {
03762 v = new_eu->vu_p->v_p;
03763 nmg_vertex_gv( v, hit_pt );
03764 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03765 bu_log( "\tcreated new vertex x%x\n", v );
03766 }
03767 bu_ptbl_ins_unique( inters, (long *)v );
03768 bu_ptbl_ins_unique( verts, (long *)v );
03769 return;
03770 }
03771
03772
03773
03774
03775
03776 VSUB2( diff, vg2a->coord, vg1a->coord );
03777 if( VDOT( diff, dir1 ) > 0.0 )
03778 {
03779 VSUB2( diff, vg1b->coord, vg2a->coord );
03780 if( VDOT( diff, dir1 ) > 0.0 )
03781 bu_ptbl_ins_unique( inters, (long *)eu2->vu_p->v_p );
03782 }
03783
03784 VSUB2( diff, vg2b->coord, vg1a->coord );
03785 if( VDOT( diff, dir1 ) > 0.0 )
03786 {
03787 VSUB2( diff, vg1b->coord, vg2b->coord );
03788 if( VDOT( diff, dir1 ) > 0.0 )
03789 bu_ptbl_ins_unique( inters, (long *)eu2->eumate_p->vu_p->v_p );
03790 }
03791 }
03792
03793 void
03794 nmg_isect_eu_fu(struct nmg_inter_struct *is, struct bu_ptbl *verts, struct edgeuse *eu, struct faceuse *fu)
03795 {
03796 struct model *m;
03797 struct vertex_g *vg1,*vg2;
03798 struct loopuse *lu;
03799 plane_t pl;
03800 fastf_t dist;
03801 fastf_t eu_len;
03802 fastf_t one_over_len;
03803 point_t hit_pt;
03804 vect_t edir;
03805 vect_t dir;
03806 struct bu_ptbl inters;
03807 fastf_t *inter_dist;
03808 int i;
03809
03810 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03811 bu_log( "nmg_isect_eu_fu: eu=x%x, fu=x%x START\n", eu, fu );
03812
03813 NMG_CK_INTER_STRUCT( is );
03814 NMG_CK_FACEUSE( fu );
03815 NMG_CK_EDGEUSE( eu );
03816 BU_CK_PTBL( verts );
03817
03818 if( nmg_find_fu_of_eu( eu ) == fu )
03819 {
03820 bu_log( "nmg_isect_eu_fu() called with eu (x%x) from its own fu (x%x)\n",eu , fu );
03821 rt_bomb( "nmg_isect_eu_fu() called with eu from its own fu" );
03822 }
03823
03824 m = nmg_find_model( &fu->l.magic );
03825 NMG_CK_MODEL( m );
03826 if( nmg_find_model( &eu->l.magic ) != m )
03827 {
03828 bu_log( "nmg_isect_eu_fu() called with EU (x%x) from model (x%x)\n", eu, nmg_find_model( &eu->l.magic ) );
03829 bu_log( "\tand FU (x%x) from model (x%x)\n", fu, m );
03830 rt_bomb( "nmg_isect_eu_fu() called with EU and FU from different models" );
03831 }
03832
03833 vg1 = eu->vu_p->v_p->vg_p;
03834 NMG_CK_VERTEX_G( vg1 );
03835 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
03836 NMG_CK_VERTEX_G( vg2 );
03837
03838 VSUB2( dir, vg2->coord, vg1->coord );
03839 VMOVE( edir, dir );
03840 eu_len = MAGNITUDE( dir );
03841 if( eu_len < is->tol.dist || eu_len < SMALL_FASTF )
03842 {
03843 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03844 bu_log( "\tnmg_isec_eu_fu: 0 length edge\n" );
03845 return;
03846 }
03847
03848 one_over_len = 1.0/eu_len;
03849 VSCALE( dir, dir, one_over_len );
03850
03851 NMG_GET_FU_PLANE( pl, fu );
03852
03853 if( bn_isect_line3_plane( &dist, vg1->coord, dir, pl, &is->tol ) < 1 )
03854 {
03855 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03856 bu_log( "\tnmg_isec_eu_fu: no intersection\n" );
03857 return;
03858 }
03859 #if 0
03860
03861 if( dist < (-is->tol.dist) || dist > eu_len+is->tol.dist )
03862 {
03863 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03864 bu_log( "\tnmg_isec_eu_fu: intersection beyond ends of EU\n" );
03865 return;
03866 }
03867
03868 if( dist <= is->tol.dist )
03869 {
03870 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03871 bu_log( "\tintersection at eu_vu_p\n" );
03872 (void)nmg_make_dualvu( eu->vu_p->v_p, fu, &is->tol );
03873 return;
03874 }
03875
03876 if( dist >= eu_len - is->tol.dist )
03877 {
03878 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03879 bu_log( "\tintersection at eu->eumate_p->vu_p\n" );
03880 (void)nmg_make_dualvu( eu->eumate_p->vu_p->v_p, fu, &is->tol );
03881 return;
03882 }
03883 #endif
03884 VJOIN1( hit_pt, vg1->coord, dist, dir );
03885
03886 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03887 bu_log( "\tintersection point at (%g %g %g)\n", V3ARGS( hit_pt ) );
03888
03889
03890 bu_ptbl_init( &inters, 64, " &inters");
03891
03892
03893 nmg_isect_eu_verts( eu, vg1, vg2, verts, &inters, &is->tol );
03894
03895
03896 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
03897 {
03898 struct edgeuse *eu_fu;
03899
03900 NMG_CK_LOOPUSE( lu );
03901
03902
03903 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03904 continue;
03905
03906 for( BU_LIST_FOR( eu_fu, edgeuse, &lu->down_hd ) )
03907 {
03908 NMG_CK_EDGEUSE( eu_fu );
03909
03910 nmg_isect_eu_eu( eu, vg1, vg2, edir, eu_fu, verts, &inters, &is->tol );
03911
03912 }
03913 }
03914
03915
03916
03917 if( BU_PTBL_END( &inters ) == 0 )
03918 {
03919 struct vertex *v=(struct vertex *)NULL;
03920 int class;
03921 fastf_t dist_to_plane;
03922
03923 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03924 bu_log( "\tNo intersection points found\n" );
03925
03926
03927
03928
03929 dist_to_plane = DIST_PT_PLANE( vg1->coord, pl );
03930 if( dist_to_plane < 0.0 )
03931 dist_to_plane = (-dist_to_plane);
03932 if( dist_to_plane <= is->tol.dist )
03933 {
03934
03935 class = nmg_class_pt_fu_except( vg1->coord, fu, (struct loopuse *)NULL,
03936 0, 0, (char *)NULL, 0, 0, &is->tol );
03937 if( class != NMG_CLASS_AinB )
03938 goto out;
03939
03940 v = eu->vu_p->v_p;
03941 if( v && !nmg_find_v_in_face( v, fu ) )
03942 {
03943 struct vertexuse *new_vu;
03944
03945 new_vu = nmg_make_dualvu( v, fu, &is->tol );
03946 bu_ptbl_ins_unique( verts, (long *)new_vu->v_p );
03947 }
03948 goto out;
03949 }
03950
03951 dist_to_plane = DIST_PT_PLANE( vg2->coord, pl );
03952 if( dist_to_plane < 0.0 )
03953 dist_to_plane = (-dist_to_plane);
03954 if( dist_to_plane <= is->tol.dist )
03955 {
03956
03957 class = nmg_class_pt_fu_except( vg2->coord, fu, (struct loopuse *)NULL,
03958 0, 0, (char *)NULL, 0, 0, &is->tol );
03959 if( class != NMG_CLASS_AinB )
03960 goto out;
03961
03962 v = eu->eumate_p->vu_p->v_p;
03963 if( v && !nmg_find_v_in_face( v, fu ) )
03964 {
03965 struct vertexuse *new_vu;
03966
03967 new_vu = nmg_make_dualvu( v, fu, &is->tol );
03968 bu_ptbl_ins_unique( verts, (long *)new_vu->v_p );
03969 }
03970 goto out;
03971 }
03972
03973
03974
03975
03976 if( dist < (-is->tol.dist) || dist > eu_len+is->tol.dist )
03977 {
03978 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03979 bu_log( "\tnmg_isec_eu_fu: intersection beyond ends of EU\n" );
03980 goto out;
03981 }
03982
03983
03984 if( VDIST_SQ( hit_pt, vg1->coord ) <= is->tol.dist_sq )
03985 {
03986 v = eu->vu_p->v_p;
03987 VMOVE( hit_pt, vg1->coord );
03988 }
03989 else if( VDIST_SQ( hit_pt, vg2->coord ) <= is->tol.dist_sq )
03990 {
03991 v = eu->eumate_p->vu_p->v_p;
03992 VMOVE( hit_pt, vg2->coord );
03993 }
03994
03995 if (rt_g.NMG_debug & DEBUG_POLYSECT)
03996 {
03997 bu_log( "\tHit point is not within tolerance of eu endpoints\n" );
03998 bu_log( "\t\thit_pt=( %g %g %g ), eu=(%g %g %g)<->(%g %g %g)\n",
03999 V3ARGS( hit_pt), V3ARGS( vg1->coord ), V3ARGS( vg2->coord ) );
04000 }
04001
04002
04003 class = nmg_class_pt_fu_except( hit_pt, fu, (struct loopuse *)NULL,
04004 0, 0, (char *)NULL, 0, 0, &is->tol );
04005
04006 if( class == NMG_CLASS_AinB )
04007 {
04008 struct edgeuse *new_eu;
04009
04010
04011 if( !v )
04012 v = nmg_find_pt_in_model( m, hit_pt, &is->tol );
04013 if( v != eu->vu_p->v_p && v != eu->eumate_p->vu_p->v_p )
04014 {
04015 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04016 bu_log( "\tsplitting eu (x%x) at hit_pt (v=x%x)\n", eu, v );
04017
04018 new_eu = nmg_esplit( v, eu, 1 );
04019 if( !v )
04020 {
04021 v = new_eu->vu_p->v_p;
04022 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04023 bu_log( "\tnew vertex at hit point is x%x\n", v );
04024 nmg_vertex_gv( v, hit_pt );
04025 }
04026 }
04027
04028 if( v && !nmg_find_v_in_face( v, fu ) )
04029 {
04030 struct vertexuse *new_vu;
04031
04032 new_vu = nmg_make_dualvu( v, fu, &is->tol );
04033 bu_ptbl_ins_unique( verts, (long *)new_vu->v_p );
04034 }
04035
04036 }
04037 goto out;
04038 }
04039
04040 if( BU_PTBL_END( &inters ) == 1 )
04041 {
04042 struct vertex *v;
04043
04044
04045 v = (struct vertex *)BU_PTBL_GET( &inters, 0 );
04046 NMG_CK_VERTEX( v );
04047
04048 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04049 bu_log( "Only one intersect vertex (x%x), just split all EU's at (x%x)\n", v, eu );
04050
04051 if( v == eu->vu_p->v_p || v == eu->eumate_p->vu_p->v_p )
04052 goto out;
04053
04054 (void)nmg_break_all_es_on_v( &m->magic, v, &is->tol );
04055
04056 goto out;
04057 }
04058
04059
04060 inter_dist = (fastf_t *)bu_calloc( BU_PTBL_END( &inters ), sizeof( fastf_t ),
04061 "nmg_isect_eu_fu: inter_dist" );
04062
04063 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04064 bu_log( "%d intersect vertices along eu (x%x)\n", BU_PTBL_END( &inters ), eu );
04065
04066 for( i=0 ; i<BU_PTBL_END( &inters ) ; i++ )
04067 {
04068 struct vertex *v;
04069 struct vertex_g *vg;
04070 vect_t diff;
04071
04072 v = (struct vertex *)BU_PTBL_GET( &inters, i );
04073 NMG_CK_VERTEX( v );
04074 vg = v->vg_p;
04075 NMG_CK_VERTEX_G( vg );
04076
04077 VSUB2( diff, vg->coord, vg1->coord );
04078 if( VDOT( diff, dir ) < 0.0 )
04079 rt_bomb( "nmg_isect_eu_fu: intersection point not on eu\n" );
04080
04081 inter_dist[i] = MAGSQ( diff );
04082 }
04083
04084 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04085 {
04086 bu_log( "Intersect vertices along eu x%x:\n", eu );
04087 for( i=0 ; i<BU_PTBL_END( &inters ) ; i++ )
04088 bu_log( "%d x%x %g\n", i+1, BU_PTBL_GET( &inters, i ), inter_dist[i] );
04089 }
04090
04091 while( 1 )
04092 {
04093 struct vertex *v;
04094 fastf_t max_dist;
04095 int index_at_max;
04096
04097 max_dist = (-1.0);
04098 index_at_max = (-1);
04099
04100 for( i=0 ; i<BU_PTBL_END( &inters ) ; i++ )
04101 {
04102 if( inter_dist[i] > max_dist )
04103 {
04104 max_dist = inter_dist[i];
04105 index_at_max = i;
04106 }
04107 }
04108
04109 if( index_at_max < 0 )
04110 break;
04111
04112 v = (struct vertex *)BU_PTBL_GET( &inters, index_at_max );
04113 NMG_CK_VERTEX( v );
04114
04115 if( v != eu->vu_p->v_p && v != eu->eumate_p->vu_p->v_p )
04116 {
04117 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04118 bu_log( "Breaking edges at vertex #%d, dist=%g, v=x%x\n", i+1, inter_dist[i], v );
04119 (void)nmg_break_all_es_on_v( &m->magic, v, &is->tol );
04120 }
04121
04122 inter_dist[index_at_max] = (-10.0);
04123 }
04124
04125 bu_free( (char *)inter_dist, "nmg_isect_eu_fu: inter_dist" );
04126
04127 out:
04128 bu_ptbl_free( &inters);
04129
04130 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04131 bu_log( "nmg_isect_eu_fu: eu=x%x, fu=x%x END\n", eu, fu );
04132
04133 }
04134
04135 void
04136 nmg_isect_fu_jra(struct nmg_inter_struct *is, struct faceuse *fu1, struct faceuse *fu2, struct bu_ptbl *eu1_list, struct bu_ptbl *eu2_list)
04137 {
04138 struct model *m;
04139 struct bu_ptbl verts1,verts2;
04140 struct loopuse *lu;
04141 int i;
04142
04143 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04144 bu_log( "nmg_isect_fu_jra( fu1=x%x, fu2=x%x ) START\n", fu1, fu2 );
04145
04146 NMG_CK_INTER_STRUCT(is);
04147 NMG_CK_FACEUSE(fu1);
04148 NMG_CK_FACEUSE(fu2);
04149 BU_CK_PTBL(eu1_list);
04150 BU_CK_PTBL(eu2_list);
04151
04152 m = nmg_find_model( &fu1->l.magic );
04153 NMG_CK_MODEL( m );
04154
04155 nmg_vertex_tabulate( &verts2, &fu2->l.magic );
04156
04157
04158 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
04159 {
04160 struct edgeuse *eu;
04161
04162 NMG_CK_LOOPUSE( lu );
04163
04164 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04165 continue;
04166
04167 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
04168 {
04169 NMG_CK_EDGEUSE( eu );
04170
04171 nmg_isect_eu_fu( is, &verts2, eu, fu2 );
04172 }
04173 }
04174
04175 bu_ptbl_free( &verts2);
04176 nmg_vertex_tabulate( &verts1, &fu1->l.magic );
04177
04178
04179 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
04180 {
04181 struct edgeuse *eu;
04182
04183 NMG_CK_LOOPUSE( lu );
04184
04185 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04186 continue;
04187
04188 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
04189 {
04190 NMG_CK_EDGEUSE( eu );
04191
04192 nmg_isect_eu_fu( is, &verts1, eu, fu1 );
04193 }
04194 }
04195
04196
04197 bu_ptbl_free( &verts1);
04198
04199
04200
04201
04202 nmg_vertex_tabulate( &verts1, &fu1->l.magic );
04203 nmg_vertex_tabulate( &verts2, &fu2->l.magic );
04204
04205
04206 for( i=0 ; i<BU_PTBL_END( &verts2 ) ; i++ )
04207 {
04208 struct vertex *v;
04209
04210 v = (struct vertex *)BU_PTBL_GET( &verts2, i );
04211 NMG_CK_VERTEX( v );
04212
04213 bu_ptbl_ins_unique( &verts1, (long *)v );
04214 }
04215 bu_ptbl_free( &verts2);
04216
04217 for( i=0 ; i< BU_PTBL_END( &verts1 ) ; i++ )
04218 {
04219 struct vertex *v;
04220 struct vertexuse *vu;
04221 fastf_t dist;
04222
04223 v = (struct vertex *)BU_PTBL_GET( &verts1, i );
04224 NMG_CK_VERTEX( v );
04225
04226 if( !nmg_is_vertex_on_inter( v, fu1, fu2, is ) )
04227 continue;
04228
04229
04230 dist = VDIST( is->pt, v->vg_p->coord );
04231
04232
04233
04234
04235 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) )
04236 {
04237 struct faceuse *fu_tmp;
04238
04239 fu_tmp = nmg_find_fu_of_vu( vu );
04240 if( fu_tmp == fu1 || fu_tmp == fu2 )
04241 {
04242 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04243 bu_log( "\tenlisting vu x%x (x%x) from fu (x%x)\n", vu, v, fu_tmp );
04244 nmg_enlist_one_vu( is, vu, dist );
04245 }
04246 }
04247 }
04248
04249 bu_ptbl_free( &verts1);
04250
04251 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04252 bu_log( "nmg_isect_fu_jra( fu1=x%x, fu2=x%x ) END\n", fu1, fu2 );
04253 }
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276 void
04277 nmg_isect_line2_face2pNEW(struct nmg_inter_struct *is, struct faceuse *fu1, struct faceuse *fu2, struct bu_ptbl *eu1_list, struct bu_ptbl *eu2_list)
04278 {
04279 struct bu_ptbl eg_list;
04280 struct edge_g_lseg **eg1;
04281 struct edgeuse *eu1;
04282 struct edgeuse *eu2;
04283 fastf_t dist[2];
04284 int code;
04285 point_t eg_pt2d;
04286 vect_t eg_dir2d;
04287 struct loopuse *lu1;
04288 point_t hit3d;
04289 point_t hit2d;
04290 struct edgeuse *new_eu;
04291 int eu1_index;
04292 int eu2_index;
04293 int class;
04294
04295 NMG_CK_INTER_STRUCT(is);
04296 NMG_CK_FACEUSE(fu1);
04297 NMG_CK_FACEUSE(fu2);
04298 BU_CK_PTBL(eu1_list);
04299 BU_CK_PTBL(eu2_list);
04300
04301 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04302 bu_log("nmg_isect_line2_face2pNEW(, fu1=x%x, fu2=x%x) on_eg=x%x\n", fu1, fu2, is->on_eg);
04303
04304
04305 nmg_isect2d_prep( is, &fu1->l.magic );
04306
04307 MAT4X3PNT( is->pt2d, is->proj, is->pt );
04308 MAT4X3VEC( is->dir2d, is->proj, is->dir );
04309
04310 re_tabulate:
04311
04312
04313 nmg_edge_g_tabulate( &eg_list, &fu1->l.magic );
04314
04315
04316 for( eg1 = (struct edge_g_lseg **)BU_PTBL_LASTADDR(&eg_list);
04317 eg1 >= (struct edge_g_lseg **)BU_PTBL_BASEADDR(&eg_list); eg1--
04318 ) {
04319 struct vertex *hit_v = (struct vertex *)NULL;
04320
04321 NMG_CK_EDGE_G_LSEG(*eg1);
04322
04323 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04324 bu_log( "\tChecking eg=x%x\n", *eg1 );
04325 }
04326
04327 if( *eg1 == is->on_eg ) {
04328 #if 0
04329 colinear:
04330
04331
04332
04333
04334
04335
04336 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04337 bu_log("\tThis edge_geom generated the line. Enlisting.\n");
04338 }
04339 for( eu1_index=0; eu1_index < BU_PTBL_END(eu1_list); eu1_index++ ) {
04340 eu1 = (struct edgeuse *)BU_PTBL_GET(eu1_list, eu1_index);
04341 NMG_CK_EDGEUSE(eu1);
04342 if( eu1->g.lseg_p != is->on_eg ) continue;
04343
04344
04345 for( eu2_index=0; eu2_index < BU_PTBL_END(eu2_list); eu2_index++ ) {
04346 eu2 = (struct edgeuse *)BU_PTBL_GET(eu2_list, eu2_index);
04347 NMG_CK_EDGEUSE(eu2);
04348
04349 if( eu2->g.lseg_p != is->on_eg ) continue;
04350
04351
04352
04353
04354
04355 (void)nmg_isect_2colinear_edge2p( eu1, eu2,
04356 fu1, is, eu1_list, eu2_list);
04357 }
04358
04359
04360 nmg_enlist_vu(is, eu1->vu_p, 0, MAX_FASTF );
04361 nmg_enlist_vu(is, BU_LIST_PNEXT_CIRC(edgeuse, eu1)->vu_p, 0, MAX_FASTF );
04362 }
04363 continue;
04364 #else
04365 fastf_t dist;
04366 point_t pca;
04367 struct edgeuse *eu_end;
04368 struct vertex_g *vg;
04369 plane_t pl1,pl2;
04370
04371 colinear:
04372 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04373 bu_log("\tThis edge_geom generated the line. Enlisting.\n");
04374 }
04375
04376 NMG_GET_FU_PLANE( pl1, is->fu1 );
04377 NMG_GET_FU_PLANE( pl2, is->fu2 );
04378 for( eu1_index=0; eu1_index < BU_PTBL_END(eu1_list); eu1_index++ )
04379 {
04380 eu1 = (struct edgeuse *)BU_PTBL_GET(eu1_list, eu1_index);
04381 NMG_CK_EDGEUSE(eu1);
04382 if( eu1->g.lseg_p != is->on_eg ) continue;
04383
04384
04385 vg = eu1->vu_p->v_p->vg_p;
04386 NMG_CK_VERTEX_G( vg );
04387 (void)rt_dist_pt3_line3( &dist, pca, is->pt, is->dir, vg->coord, &(is->tol) );
04388 if( dist <= is->tol.dist )
04389 {
04390
04391
04392 if( DIST_PT_PLANE( vg->coord, pl2 ) <= is->tol.dist )
04393 {
04394
04395 if( nmg_class_pt_fu_except( vg->coord, fu2, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) ) != NMG_CLASS_AoutB )
04396 {
04397
04398 dist = VDIST( is->pt, vg->coord );
04399 nmg_enlist_vu( is, eu1->vu_p, 0, dist );
04400 }
04401 }
04402 }
04403 eu_end = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
04404 vg = eu_end->vu_p->v_p->vg_p;
04405 NMG_CK_VERTEX_G( vg );
04406 code = rt_dist_pt3_line3( &dist, pca, is->pt, is->dir, eu_end->vu_p->v_p->vg_p->coord, &(is->tol) );
04407 if( dist <= is->tol.dist )
04408 {
04409
04410
04411 if( DIST_PT_PLANE( vg->coord, pl2 ) <= is->tol.dist )
04412 {
04413
04414 if( nmg_class_pt_fu_except( vg->coord, fu2, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) ) != NMG_CLASS_AoutB )
04415 {
04416
04417 dist = VDIST( is->pt, vg->coord );
04418 nmg_enlist_vu( is, eu_end->vu_p, 0, dist );
04419 }
04420 }
04421 }
04422 }
04423
04424 for( eu2_index=0; eu2_index < BU_PTBL_END(eu2_list); eu2_index++ )
04425 {
04426 eu2 = (struct edgeuse *)BU_PTBL_GET(eu2_list, eu2_index);
04427 NMG_CK_EDGEUSE(eu2);
04428
04429 if( eu2->g.lseg_p != is->on_eg ) continue;
04430
04431
04432 vg = eu2->vu_p->v_p->vg_p;
04433 NMG_CK_VERTEX_G( vg );
04434 code = rt_dist_pt3_line3( &dist, pca, is->pt, is->dir, vg->coord, &(is->tol) );
04435 if( dist <= is->tol.dist )
04436 {
04437
04438
04439 if( DIST_PT_PLANE( vg->coord, pl1 ) <= is->tol.dist )
04440 {
04441
04442 if( nmg_class_pt_fu_except( vg->coord, fu1, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) ) != NMG_CLASS_AoutB )
04443 {
04444
04445 dist = VDIST( is->pt, vg->coord );
04446 nmg_enlist_vu( is, eu2->vu_p, 0, dist );
04447 }
04448 }
04449 }
04450 eu_end = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
04451 vg = eu_end->vu_p->v_p->vg_p;
04452 NMG_CK_VERTEX_G( vg );
04453 code = rt_dist_pt3_line3( &dist, pca, is->pt, is->dir, eu_end->vu_p->v_p->vg_p->coord, &(is->tol) );
04454 if( dist <= is->tol.dist )
04455 {
04456
04457
04458 if( DIST_PT_PLANE( vg->coord, pl1 ) <= is->tol.dist )
04459 {
04460
04461 if( nmg_class_pt_fu_except( vg->coord, fu1, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) ) != NMG_CLASS_AoutB )
04462 {
04463
04464 dist = VDIST( is->pt, vg->coord );
04465 nmg_enlist_vu( is, eu_end->vu_p, 0, dist );
04466 }
04467 }
04468 }
04469 }
04470 continue;
04471 #endif
04472 }
04473
04474
04475
04476
04477
04478
04479
04480 MAT4X3PNT( eg_pt2d, is->proj, (*eg1)->e_pt );
04481 MAT4X3VEC( eg_dir2d, is->proj, (*eg1)->e_dir );
04482
04483
04484 dist[0] = dist[1] = -INFINITY;
04485 code = bn_isect_line2_line2( dist, is->pt2d, is->dir2d,
04486 eg_pt2d, eg_dir2d, &(is->tol) );
04487
04488
04489 if( code == 0 ) {
04490
04491 if( is->on_eg ) {
04492 bu_log("nmg_isect_line2_face2pNEW() edge_g not shared, geometry says lines are colinear.\n");
04493 goto fixup;
04494 }
04495
04496 if( rt_g.NMG_debug & DEBUG_POLYSECT )
04497 bu_log("NOTICE: setting on_eg to eg1 and continuing with colinear case.\n");
04498 is->on_eg = (*eg1);
04499 goto colinear;
04500 }
04501
04502
04503 if( is->on_eg && bn_2line3_colinear(
04504 (*eg1)->e_pt, (*eg1)->e_dir,
04505 is->on_eg->e_pt, is->on_eg->e_dir, 1e5, &(is->tol) ) ) {
04506 fixup:
04507 nmg_pr_eg(&(*eg1)->l.magic, 0);
04508 nmg_pr_eg(&is->on_eg->l.magic, 0);
04509 bu_log("nmg_isect_line2_face2pNEW() eg1 colinear to on_eg?\n");
04510 #if 0
04511
04512 nmg_model_fuse( nmg_find_model(&fu1->l.magic), &(is->tol) );
04513 rt_bomb("nmg_isect_line2_face2pNEW() eg1 colinear to on_eg?\n");
04514 #else
04515
04516 bu_log("fusing eg1 with on_eg, handling as colinear\n");
04517 nmg_jeg( is->on_eg, *eg1 );
04518 goto colinear;
04519 #endif
04520 }
04521
04522
04523 if( is->on_eg && !hit_v ) {
04524 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04525 bu_log("non-colinear. Searching for topological intersection between on_eg and eg1\n");
04526 }
04527
04528 hit_v = nmg_common_v_2eg( *eg1, is->on_eg, &(is->tol) );
04529
04530
04531
04532
04533
04534
04535 if(hit_v) {
04536 fastf_t dist1,dist2;
04537 plane_t n1, n2;
04538
04539 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04540 static int num=0;
04541 char buf[128];
04542 FILE *fp;
04543 sprintf(buf, "Itopo%d.pl", num++);
04544 if( (fp=fopen(buf,"w")) != NULL ) {
04545 pl_color(fp, 255, 0, 0);
04546 pdv_3ray( fp, is->on_eg->e_pt, is->on_eg->e_dir, 1.0 );
04547 pdv_3cont( fp, hit_v->vg_p->coord );
04548 pl_color(fp, 255,255, 0);
04549 pdv_3ray( fp, (*eg1)->e_pt, (*eg1)->e_dir, 1.0 );
04550 pdv_3cont( fp, hit_v->vg_p->coord );
04551 fclose(fp);
04552 bu_log("overlay %s red is on_eg, yellow is eg1\n", buf);
04553 } else perror(buf);
04554 bu_log("\tTopology intersection. hit_v=x%x (%g, %g, %g)\n",
04555 hit_v,
04556 V3ARGS(hit_v->vg_p->coord) );
04557 }
04558
04559
04560
04561
04562
04563
04564
04565
04566 if( !V3PT_IN_RPP( hit_v->vg_p->coord, fu1->f_p->min_pt, fu1->f_p->max_pt ) &&
04567 !V3PT_IN_RPP( hit_v->vg_p->coord, fu2->f_p->min_pt, fu2->f_p->max_pt )
04568 ) {
04569
04570 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04571 VPRINT("\t\tisect pt outside fu1 & fu2 RPP:", hit_v->vg_p->coord );
04572 bu_log("\t\tfu1 RPP: ( %g %g %g ) <-> ( %g %g %g )\n",
04573 V3ARGS( fu1->f_p->min_pt ), V3ARGS( fu1->f_p->max_pt ) );
04574 bu_log("\t\tfu2 RPP: ( %g %g %g ) <-> ( %g %g %g )\n",
04575 V3ARGS( fu2->f_p->min_pt ), V3ARGS( fu2->f_p->max_pt ) );
04576 }
04577 continue;
04578 }
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600 NMG_GET_FU_PLANE(n1, fu1);
04601 NMG_GET_FU_PLANE(n2, fu2);
04602 dist1 = DIST_PT_PLANE( hit_v->vg_p->coord , n1 );
04603 dist2 = DIST_PT_PLANE( hit_v->vg_p->coord , n2 );
04604
04605 if( !NEAR_ZERO( dist1 , is->tol.dist ) || !NEAR_ZERO( dist2 , is->tol.dist ) ) {
04606 continue;
04607 }
04608 if( (class=nmg_class_pt_fu_except( hit_v->vg_p->coord, fu1, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) )) == NMG_CLASS_AoutB )
04609 {
04610 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04611 {
04612 VPRINT("\t\tisect pt outside face fu1 (nmg_class_pt_fu_except):", hit_v->vg_p->coord );
04613 }
04614 continue;
04615 }
04616 else if( (class=nmg_class_pt_fu_except( hit_v->vg_p->coord, fu2, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) )) == NMG_CLASS_AoutB )
04617 {
04618 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04619 {
04620 VPRINT("\t\tisect pt outside face fu2 (nmg_class_pt_fu_except):", hit_v->vg_p->coord );
04621 }
04622 continue;
04623 }
04624
04625
04626
04627 goto force_isect;
04628 }
04629 }
04630
04631
04632
04633 if( code < 0 ) {
04634
04635 if( hit_v ) {
04636 bu_log("NOTICE: geom/topo mis-match, enlisting topo vu, hit_v=x%x\n", hit_v);
04637 VPRINT("hit_v", hit_v->vg_p->coord);
04638 nmg_pr_eg(&(*eg1)->l.magic, 0);
04639 nmg_pr_eg(&is->on_eg->l.magic, 0);
04640 bu_log(" dist to eg1=%e, dist to on_eg=%e\n",
04641 bn_dist_line3_pt3((*eg1)->e_pt, (*eg1)->e_dir, hit_v->vg_p->coord),
04642 bn_dist_line3_pt3(is->on_eg->e_pt, is->on_eg->e_dir, hit_v->vg_p->coord) );
04643 VPRINT("is->pt2d ", is->pt2d);
04644 VPRINT("is->dir2d", is->dir2d);
04645 VPRINT("eg_pt2d ", eg_pt2d);
04646 VPRINT("eg_dir2d ", eg_dir2d);
04647 bu_log(" 3d line isect, code=%d\n",
04648 bn_isect_line3_line3( &dist[0], &dist[1],
04649 is->pt, is->dir,
04650 (*eg1)->e_pt,
04651 (*eg1)->e_dir,
04652 &(is->tol)
04653 ) );
04654 goto force_isect;
04655 }
04656 continue;
04657 }
04658
04659 VJOIN1( hit3d, is->pt, dist[0], is->dir );
04660 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04661 VPRINT("\t2 lines intersect at", hit3d);
04662 }
04663 #if 1
04664 if( !V3PT_IN_RPP( hit3d, fu1->f_p->min_pt, fu1->f_p->max_pt ) ) {
04665
04666 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04667 VPRINT("\t\tisect pt outside fu1 face RPP:", hit3d );
04668 bu_log("\t\tface RPP: ( %g %g %g ) <-> ( %g %g %g )\n",
04669 V3ARGS( fu1->f_p->min_pt ), V3ARGS( fu1->f_p->max_pt ) );
04670 }
04671 continue;
04672 }
04673
04674 if( (class=nmg_class_pt_fu_except( hit3d, fu1, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) )) == NMG_CLASS_AoutB )
04675 {
04676 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04677 {
04678 VPRINT("\t\tisect pt outside face fu1 (nmg_class_pt_fu_except):", hit3d );
04679 }
04680 continue;
04681 }
04682 else if( (class=nmg_class_pt_fu_except( hit3d, fu2, (struct loopuse *)NULL, NULL, NULL, (char *)NULL, 0, 0, &(is->tol) )) == NMG_CLASS_AoutB )
04683 {
04684 if (rt_g.NMG_debug & DEBUG_POLYSECT)
04685 {
04686 VPRINT("\t\tisect pt outside face fu2 (nmg_class_pt_fu_except):", hit3d );
04687 }
04688 continue;
04689 }
04690 else if(rt_g.NMG_debug & DEBUG_POLYSECT)
04691 {
04692 bu_log( "\t\tnmg_class_pt_fu_except(fu1) returns %s\n", nmg_class_name(class) );
04693 }
04694 #endif
04695 VJOIN1_2D( hit2d, is->pt2d, dist[0], is->dir2d );
04696
04697
04698 if( hit_v ) {
04699 force_isect:
04700
04701 VMOVE(hit3d, hit_v->vg_p->coord);
04702 nmg_get_2d_vertex( hit2d, hit_v, is, &fu1->l.magic );
04703 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04704 bu_log("hit_v=x%x\n", hit_v);
04705 VPRINT("hit3d", hit3d);
04706 V2PRINT("hit2d", hit2d);
04707 }
04708 }
04709
04710 eu_search:
04711
04712
04713
04714 for( eu1_index=0; eu1_index < BU_PTBL_END(eu1_list); eu1_index++ ) {
04715 struct vertexuse *vu1a, *vu1b;
04716 struct vertexuse *vu1_midpt;
04717 fastf_t ldist;
04718 point_t eu1_pt2d;
04719 point_t eu1_end2d;
04720 double tmp_dist_sq;
04721
04722 eu1 = (struct edgeuse *)BU_PTBL_GET(eu1_list, eu1_index);
04723
04724
04725 if( eu1->l.magic != NMG_EDGEUSE_MAGIC )
04726 continue;
04727
04728 NMG_CK_EDGEUSE(eu1);
04729
04730 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04731 bu_log( "\tChecking eu x%x\n", eu1 );
04732 }
04733
04734 if( eu1->g.lseg_p != *eg1 )
04735 {
04736 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04737 bu_log( "\t\teg x%x is not eg1=x%x\n", eu1->g.lseg_p, *eg1 );
04738 }
04739 continue;
04740 }
04741 vu1a = eu1->vu_p;
04742 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
04743
04744
04745 if( vu1a->v_p == hit_v ) {
04746 hit_a:
04747 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04748 bu_log("\tlisting intersect point at vu1a=x%x\n", vu1a);
04749 }
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759 nmg_enlist_vu(is, vu1a, 0, dist[0]);
04760 }
04761 if( vu1b->v_p == hit_v ) {
04762 hit_b:
04763 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04764 bu_log("\tlisting intersect point at vu1b=x%x\n", vu1b);
04765 }
04766
04767 nmg_enlist_vu(is, vu1b, 0, dist[0]);
04768 }
04769 if( vu1a->v_p == hit_v || vu1b->v_p == hit_v ) continue;
04770
04771
04772
04773
04774
04775 tmp_dist_sq = bn_distsq_line3_pt3( is->pt, is->dir, vu1a->v_p->vg_p->coord );
04776 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04777 bu_log( "\tvu1a is sqrt(%g) from the intersect line\n" , tmp_dist_sq );
04778 }
04779 if( tmp_dist_sq <= is->tol.dist_sq ) {
04780 if( !hit_v ) {
04781 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04782 bu_log( "\tnmg_isect_line2_face2pNEW: using nearby vu1a vertex x%x from eu x%x\n", vu1a->v_p, eu1 );
04783 }
04784 hit_v = vu1a->v_p;
04785 goto hit_a;
04786 }
04787 if( hit_v == vu1a->v_p ) goto hit_a;
04788 #if 0
04789 nmg_repair_v_near_v( hit_v, vu1a->v_p,
04790 is->on_eg, *eg1, 1, &(is->tol) );
04791 bu_ptbl_free( &eg_list);
04792 goto re_tabulate;
04793 #else
04794
04795 #endif
04796 }
04797 tmp_dist_sq = bn_distsq_line3_pt3( is->pt, is->dir, vu1b->v_p->vg_p->coord );
04798 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04799 bu_log( "\tvu1b is sqrt(%g) from the intersect line\n" , tmp_dist_sq );
04800 }
04801 if(tmp_dist_sq <= is->tol.dist_sq ) {
04802 if( !hit_v ) {
04803 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04804 bu_log( "\tnmg_isect_line2_face2pNEW: using nearby vu1b vertex x%x from eu x%x\n", vu1b->v_p, eu1 );
04805 }
04806 hit_v = vu1b->v_p;
04807 goto hit_b;
04808 }
04809 if( hit_v == vu1b->v_p ) goto hit_b;
04810 #if 0
04811 nmg_repair_v_near_v( hit_v, vu1b->v_p,
04812 is->on_eg, *eg1, 1, &(is->tol) );
04813 bu_ptbl_free( &eg_list);
04814 goto re_tabulate;
04815 #else
04816
04817 #endif
04818 }
04819
04820
04821 nmg_get_2d_vertex( eu1_pt2d, vu1a->v_p, is, &fu1->l.magic );
04822 nmg_get_2d_vertex( eu1_end2d, vu1b->v_p, is, &fu1->l.magic );
04823 ldist = 0;
04824 code = bn_isect_pt2_lseg2( &ldist, eu1_pt2d, eu1_end2d, hit2d, &(is->tol) );
04825 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04826 bu_log("\tbn_isect_pt2_lseg2() returned %d, ldist=%g\n", code, ldist);
04827 }
04828 switch(code) {
04829 case -2:
04830 continue;
04831 default:
04832 case -1:
04833 continue;
04834 case 1:
04835
04836 if( hit_v && hit_v != vu1a->v_p ) {
04837 nmg_repair_v_near_v( hit_v, vu1a->v_p,
04838 is->on_eg, *eg1, 1, &(is->tol) );
04839 bu_ptbl_free( &eg_list);
04840 goto re_tabulate;
04841 }
04842 hit_v = vu1a->v_p;
04843 if (rt_g.NMG_debug & DEBUG_POLYSECT) bu_log("\thit_v = x%x (vu1a)\n", hit_v);
04844 goto hit_a;
04845 case 2:
04846
04847 if( hit_v && hit_v != vu1b->v_p ) {
04848 nmg_repair_v_near_v( hit_v, vu1b->v_p,
04849 is->on_eg, *eg1, 1, &(is->tol) );
04850 bu_ptbl_free( &eg_list);
04851 goto re_tabulate;
04852 }
04853 hit_v = vu1b->v_p;
04854 if (rt_g.NMG_debug & DEBUG_POLYSECT) bu_log("\thit_v = x%x (vu1b)\n", hit_v);
04855 goto hit_b;
04856 case 3:
04857
04858
04859
04860
04861 if( !hit_v ) {
04862 hit_v = nmg_find_pt_in_model(fu1->s_p->r_p->m_p,
04863 hit3d, &(is->tol));
04864 if( hit_v == vu1a->v_p || hit_v == vu1b->v_p )
04865 rt_bomb("About to make 0-length edge!\n");
04866 }
04867 new_eu = nmg_ebreaker(hit_v, eu1, &is->tol);
04868 bu_ptbl_ins_unique( eu1_list, &new_eu->l.magic );
04869
04870 vu1_midpt = new_eu->vu_p;
04871 if( !hit_v ) {
04872 hit_v = vu1_midpt->v_p;
04873 nmg_vertex_gv( hit_v, hit3d );
04874 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04875 bu_log("\tmaking new vertex vu=x%x hit_v=x%x\n",
04876 vu1_midpt, hit_v);
04877 }
04878
04879
04880
04881
04882
04883 if( is->on_eg ) {
04884 nmg_break_eg_on_v( is->on_eg,
04885 hit_v, &(is->tol) );
04886 }
04887 } else {
04888 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04889 bu_log("\tre-using hit_v=x%x, vu=x%x\n", hit_v, vu1_midpt);
04890 }
04891 if( hit_v != vu1_midpt->v_p ) rt_bomb("hit_v changed?\n");
04892 }
04893 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04894 bu_log( "Faceuses after nmg_ebreaker() call\n") ;
04895 bu_log( "fu1:\n" );
04896 nmg_pr_fu_briefly( fu1 , "\t" );
04897 bu_log( "fu2:\n" );
04898 nmg_pr_fu_briefly( fu2 , "\t" );
04899 }
04900 nmg_enlist_vu(is, vu1_midpt, 0, dist[0]);
04901
04902
04903 goto eu_search;
04904 }
04905 }
04906 }
04907
04908
04909 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) ) {
04910 struct vertexuse *vu1;
04911
04912 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_VERTEXUSE_MAGIC ) continue;
04913
04914
04915 vu1 = BU_LIST_FIRST( vertexuse, &lu1->down_hd );
04916 NMG_CK_VERTEXUSE(vu1);
04917
04918
04919 if( bn_distsq_line3_pt3( is->pt, is->dir,
04920 vu1->v_p->vg_p->coord ) > is->tol.dist_sq )
04921 continue;
04922
04923 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
04924 bu_log("\tself-loop vu=x%x lies on line of intersection\n", vu1 );
04925 }
04926
04927
04928 if( is->on_eg ) {
04929 nmg_break_eg_on_v( is->on_eg, vu1->v_p, &(is->tol) );
04930 nmg_enlist_vu(is, vu1, 0, MAX_FASTF );
04931 }
04932
04933 #if 1
04934
04935
04936
04937
04938
04939
04940
04941 for( eu1_index=0; eu1_index < BU_PTBL_END(eu1_list); eu1_index++ ) {
04942 eu1 = (struct edgeuse *)BU_PTBL_GET(eu1_list, eu1_index);
04943
04944
04945 if( eu1->l.magic != NMG_EDGEUSE_MAGIC )
04946 continue;
04947
04948 NMG_CK_EDGEUSE(eu1);
04949 if( eu1->g.lseg_p != is->on_eg ) continue;
04950
04951 new_eu = nmg_break_eu_on_v( eu1, vu1->v_p, fu1, is );
04952 if( !new_eu ) continue;
04953 bu_ptbl_ins_unique( eu1_list, &new_eu->l.magic );
04954 nmg_enlist_vu(is, new_eu->vu_p, 0, MAX_FASTF );
04955 }
04956
04957
04958 for( eu2_index=0; eu2_index < BU_PTBL_END(eu2_list); eu2_index++ ) {
04959 eu2 = (struct edgeuse *)BU_PTBL_GET(eu2_list, eu2_index);
04960
04961
04962 if( eu2->l.magic != NMG_EDGEUSE_MAGIC )
04963 continue;
04964
04965 NMG_CK_EDGEUSE(eu2);
04966 if( eu2->g.lseg_p != is->on_eg ) continue;
04967
04968 new_eu = nmg_break_eu_on_v( eu2, vu1->v_p, fu1, is );
04969 if( !new_eu ) continue;
04970 bu_ptbl_ins_unique( eu2_list, &new_eu->l.magic );
04971 nmg_enlist_vu(is, new_eu->vu_p, 0, MAX_FASTF );
04972 }
04973 #endif
04974 }
04975
04976 bu_ptbl_free( &eg_list);
04977 }
04978
04979
04980
04981
04982
04983 int
04984 nmg_is_eu_on_line3(const struct edgeuse *eu, const fastf_t *pt, const fastf_t *dir, const struct bn_tol *tol)
04985 {
04986 struct edge_g_lseg *eg;
04987
04988 NMG_CK_EDGEUSE(eu);
04989 BN_CK_TOL(tol);
04990
04991 eg = eu->g.lseg_p;
04992 NMG_CK_EDGE_G_LSEG(eg);
04993
04994
04995
04996
04997 if( fabs(VDOT(eg->e_dir, dir)) <
04998 0.9 * MAGNITUDE(eg->e_dir) * MAGNITUDE(dir) ) return 0;
04999
05000
05001 if( bn_distsq_line3_pt3( eg->e_pt, eg->e_dir,
05002 eu->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) return 0;
05003 if( bn_distsq_line3_pt3( eg->e_pt, eg->e_dir,
05004 eu->eumate_p->vu_p->v_p->vg_p->coord ) > tol->dist_sq ) return 0;
05005
05006 return 1;
05007 }
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028 struct edge_g_lseg *
05029 nmg_find_eg_between_2fg(const struct faceuse *ofu1, const struct faceuse *fu2, const struct bn_tol *tol)
05030 {
05031 const struct faceuse *fu1;
05032 const struct loopuse *lu1;
05033 const struct face_g_plane *fg1;
05034 const struct face_g_plane *fg2;
05035 const struct face *f1;
05036 struct edgeuse *ret = (struct edgeuse *)NULL;
05037 int coincident;
05038
05039 NMG_CK_FACEUSE(ofu1);
05040 NMG_CK_FACEUSE(fu2);
05041 BN_CK_TOL(tol);
05042
05043 fg1 = ofu1->f_p->g.plane_p;
05044 fg2 = fu2->f_p->g.plane_p;
05045 NMG_CK_FACE_G_PLANE(fg1);
05046 NMG_CK_FACE_G_PLANE(fg2);
05047
05048 if( fg1 == fg2 ) rt_bomb("nmg_find_eg_between_2fg() face_g_plane shared, infinitely many results\n");
05049
05050 if (rt_g.NMG_debug & DEBUG_BASIC) {
05051 nmg_pr_fus_in_fg( &fg1->magic );
05052 nmg_pr_fus_in_fg( &fg2->magic );
05053 }
05054
05055
05056 for( BU_LIST_FOR( f1, face, &fg1->f_hd ) ) {
05057 NMG_CK_FACE(f1);
05058
05059
05060 fu1 = f1->fu_p;
05061 NMG_CK_FACEUSE(fu1);
05062
05063 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) ) {
05064 const struct edgeuse *eu1;
05065 NMG_CK_LOOPUSE(lu1);
05066 if( BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC )
05067 continue;
05068 if (rt_g.NMG_debug & DEBUG_BASIC) {
05069 bu_log(" visiting lu1=x%x, fu1=x%x, fg1=x%x\n",
05070 lu1, fu1, fg1 );
05071 }
05072 restart:
05073 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) ) {
05074 struct edgeuse *eur;
05075
05076 NMG_CK_EDGEUSE(eu1);
05077
05078 for(
05079 eur = eu1->radial_p;
05080 eur != eu1->eumate_p;
05081 eur = eur->eumate_p->radial_p
05082 ) {
05083 const struct faceuse *tfu;
05084
05085 if (*eur->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
05086 if( *eur->up.lu_p->up.magic_p != NMG_FACEUSE_MAGIC ) continue;
05087 tfu = eur->up.lu_p->up.fu_p;
05088 if( tfu->f_p->g.plane_p != fg2 ) continue;
05089 NMG_CK_EDGE_G_EITHER( eur->g.lseg_p );
05090
05091
05092 if (rt_g.NMG_debug & DEBUG_BASIC) {
05093 bu_log(" Found shared edge, eur=x%x, eg=x%x\n", eur, eur->g.lseg_p );
05094 nmg_pr_eu_briefly( eur, (char *)NULL );
05095 nmg_pr_eu_briefly( eur->eumate_p, (char *)NULL );
05096 nmg_pr_eg( eur->g.magic_p, 0 );
05097 nmg_pr_fu_around_eu( eur, tol );
05098 }
05099
05100 if( !ret ) {
05101
05102 if (rt_g.NMG_debug & DEBUG_BASIC) {
05103 nmg_pl_lu_around_eu(eur);
05104 }
05105 ret = eur;
05106 continue;
05107 }
05108
05109
05110 if( eur->g.lseg_p == ret->g.lseg_p ) continue;
05111
05112
05113 if( NMG_ARE_EUS_ADJACENT(eur, ret) ) {
05114 if (rt_g.NMG_debug & DEBUG_BASIC) {
05115 bu_log("nmg_find_eg_between_2fg() joining edges eur=x%x, ret=x%x\n",
05116 eur, ret );
05117 }
05118 nmg_radial_join_eu(ret, eur, tol);
05119 goto restart;
05120 }
05121
05122
05123 bu_log("eur=x%x, eg_p=x%x; ret=x%x, eg_p=x%x\n",
05124 eur, eur->g.lseg_p,
05125 ret, ret->g.lseg_p);
05126 nmg_pr_eg( eur->g.magic_p, 0 );
05127 nmg_pr_eg( ret->g.magic_p, 0 );
05128 nmg_pr_eu_endpoints( eur, 0 );
05129 nmg_pr_eu_endpoints( ret, 0 );
05130
05131 coincident = nmg_2edgeuse_g_coincident( eur, ret, tol );
05132 if( coincident ) {
05133
05134 bu_log("nmg_find_eg_between_2fg() belatedly fusing e1=x%x, eg1=x%x, e2=x%x, eg2=x%x\n",
05135 eur->e_p, eur->g.lseg_p,
05136 ret->e_p, ret->g.lseg_p );
05137 nmg_jeg( ret->g.lseg_p, eur->g.lseg_p );
05138
05139 nmg_model_fuse( nmg_find_model(&eur->l.magic), tol );
05140 } else {
05141 rt_bomb("nmg_find_eg_between_2fg() 2 faces intersect with differing edge geometries?\n");
05142 }
05143 goto restart;
05144 }
05145 }
05146 }
05147 }
05148 if (rt_g.NMG_debug & DEBUG_BASIC) {
05149 bu_log("nmg_find_eg_between_2fg(fu1=x%x, fu2=x%x) edge_g=x%x\n",
05150 ofu1, fu2, ret ? ret->g.lseg_p : 0);
05151 }
05152 if( ret )
05153 return ret->g.lseg_p;
05154 return (struct edge_g_lseg *)NULL;
05155 }
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169 struct edgeuse *
05170 nmg_does_fu_use_eg(const struct faceuse *fu1, const long int *eg)
05171 {
05172 const struct loopuse *lu1;
05173 register struct edgeuse *eu1;
05174
05175 NMG_CK_FACEUSE(fu1);
05176 NMG_CK_EDGE_G_EITHER(eg);
05177
05178 for( BU_LIST_FOR( lu1, loopuse, &fu1->lu_hd ) ) {
05179 NMG_CK_LOOPUSE(lu1);
05180 if( BU_LIST_FIRST_MAGIC(&lu1->down_hd) == NMG_VERTEXUSE_MAGIC )
05181 continue;
05182 if (rt_g.NMG_debug & DEBUG_BASIC) {
05183 bu_log(" visiting lu1=x%x, fu1=x%x\n",
05184 lu1, fu1 );
05185 }
05186 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) ) {
05187 if( eu1->g.magic_p == eg ) goto out;
05188 }
05189 }
05190 eu1 = (struct edgeuse *)NULL;
05191 out:
05192 if (rt_g.NMG_debug & DEBUG_BASIC) {
05193 bu_log("nmg_does_fu_use_eg(fu1=x%x, eg=x%x) eu1=x%x\n",
05194 fu1, eg, eu1 );
05195 }
05196 return eu1;
05197 }
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207 int
05208 rt_line_on_plane(const fastf_t *pt, const fastf_t *dir, const fastf_t *plane, const struct bn_tol *tol)
05209 {
05210 vect_t unitdir;
05211 fastf_t dist;
05212
05213 BN_CK_TOL(tol);
05214
05215 dist = DIST_PT_PLANE( pt, plane );
05216 if( !NEAR_ZERO( dist, tol->dist ) ) return 0;
05217
05218 VMOVE( unitdir, dir );
05219 VUNITIZE( unitdir );
05220
05221 if( fabs(VDOT(unitdir, plane)) >= tol->para ) {
05222
05223
05224 return 1;
05225 }
05226 return 0;
05227 }
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241 static void
05242 nmg_isect_two_face3p(struct nmg_inter_struct *is, struct faceuse *fu1, struct faceuse *fu2)
05243 {
05244 struct bu_ptbl vert_list1, vert_list2;
05245 struct bu_ptbl eu1_list;
05246 struct bu_ptbl eu2_list;
05247 fastf_t *mag1=(fastf_t *)NULL;
05248 fastf_t *mag2=(fastf_t *)NULL;
05249 int i;
05250
05251 NMG_CK_INTER_STRUCT(is);
05252 NMG_CK_FACEUSE(fu1);
05253 NMG_CK_FACEUSE(fu2);
05254
05255 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
05256 bu_log("nmg_isect_two_face3p( fu1=x%x, fu2=x%x ) START12\n", fu1, fu2);
05257 VPRINT("isect ray is->pt ", is->pt);
05258 VPRINT("isect ray is->dir", is->dir);
05259 }
05260
05261 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05262 nmg_vfu( &fu1->s_p->fu_hd, fu1->s_p );
05263 nmg_vfu( &fu2->s_p->fu_hd, fu2->s_p );
05264 nmg_fu_touchingloops(fu1);
05265 nmg_fu_touchingloops(fu2);
05266 }
05267
05268
05269 #if TOO_STRICT
05270 NMG_GET_FU_PLANE(n1, fu1);
05271 if( !rt_line_on_plane( is->pt, is->dir, n1, &(is->tol) ) )
05272 bu_log("WARNING: intersect line not on plane of fu1\n");
05273 NMG_GET_FU_PLANE(n2, fu2);
05274 if( !rt_line_on_plane( is->pt, is->dir, n2, &(is->tol) ) )
05275 bu_log("WARNING: intersect line not on plane of fu2\n");
05276 #endif
05277
05278 if (rt_g.NMG_debug & (DEBUG_POLYSECT|DEBUG_FCUT|DEBUG_MESH)
05279 && rt_g.NMG_debug & DEBUG_PLOTEM) {
05280 nmg_pl_2fu( "Iface%d.pl", 0, fu1, fu2, 0 );
05281 }
05282 #if 0
05283
05284
05285 if( (is->on_eg = nmg_find_eg_between_2fg(fu1, fu2, &(is->tol))) ) {
05286 NMG_CK_EDGE_G_LSEG(is->on_eg);
05287 #if TOO_STRICT
05288
05289 if( !rt_line_on_plane( is->on_eg->e_pt, is->on_eg->e_dir, n1, &(is->tol) ) ) {
05290 bu_log("WARNING: shared on_eg not on plane of fu1, omitting.\n");
05291 is->on_eg = NULL;
05292 } else if( !rt_line_on_plane( is->on_eg->e_pt, is->on_eg->e_dir, n2, &(is->tol) ) ) {
05293 bu_log("WARNING: shared on_eg not on plane of fu2, omitting.\n");
05294 is->on_eg = NULL;
05295 }
05296 #endif
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306 VMOVE( unit_e_dir, is->on_eg->e_dir );
05307 VUNITIZE( unit_e_dir );
05308 dot = VDOT(is->dir, unit_e_dir);
05309 if( fabs(dot) < is->tol.para &&
05310 !bn_2line3_colinear(
05311 is->pt, is->dir,
05312 is->on_eg->e_pt, unit_e_dir, 1000.0, &(is->tol) ) ) {
05313 ang = acos(fabs(dot));
05314 bu_log("WARNING nmg_isect_two_face3p() is->pt and on_eg lines differ by %g deg. (shared topo)\n",
05315 ang * bn_radtodeg );
05316 }
05317
05318 nmg_isect_construct_nice_ray( is, fu2 );
05319 }
05320 if( !is->on_eg ) {
05321
05322 if( !(is->on_eg = nmg_find_eg_on_line( &fu1->l.magic, is->pt, is->dir, &(is->tol) ) ) ) {
05323 is->on_eg = nmg_find_eg_on_line( &fu2->l.magic, is->pt, is->dir, &(is->tol) );
05324 }
05325 if( is->on_eg ) {
05326
05327 VMOVE( unit_e_dir, is->on_eg->e_dir );
05328 VUNITIZE( unit_e_dir );
05329 dot = VDOT(is->dir, unit_e_dir);
05330 if( fabs(dot) < is->tol.para &&
05331 !bn_2line3_colinear(
05332 is->pt, is->dir,
05333 is->on_eg->e_pt, unit_e_dir, 1000.0, &(is->tol) ) ) {
05334 ang = acos(fabs(dot));
05335 bu_log("WARNING nmg_isect_two_face3p() is->pt and on_eg lines differ by %g deg. (geom search)\n",
05336 ang * bn_radtodeg );
05337 if( ang * bn_radtodeg > 1.0 ) {
05338
05339 bu_log("nmg_isect_two_face3p() line direction mismatch (geom), clearing on_eg.\n");
05340 is->on_eg = (struct edge_g_lseg *)NULL;
05341 }
05342 }
05343 }
05344 }
05345 if( is->on_eg ) {
05346 if( rt_g.NMG_debug & DEBUG_POLYSECT) {
05347 VPRINT("is->on_eg->e_pt ", is->on_eg->e_pt);
05348 VPRINT("is->on_eg->e_dir", is->on_eg->e_dir);
05349 }
05350 }
05351 #endif
05352 (void)bu_ptbl(&vert_list1, BU_PTBL_INIT,(long *)NULL);
05353 (void)bu_ptbl(&vert_list2, BU_PTBL_INIT,(long *)NULL);
05354
05355
05356 nmg_edgeuse_tabulate( &eu1_list, &fu1->l.magic );
05357 nmg_edgeuse_tabulate( &eu2_list, &fu2->l.magic );
05358
05359 is->mag_len = 2 * (BU_PTBL_END( &eu1_list ) + BU_PTBL_END( &eu2_list ) );
05360 mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag1" );
05361 mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag2" );
05362
05363 for( i=0 ; i<is->mag_len ; i++ )
05364 {
05365 mag1[i] = MAX_FASTF;
05366 mag2[i] = MAX_FASTF;
05367 }
05368
05369
05370 is->l1 = &vert_list1;
05371 is->l2 = &vert_list2;
05372 is->s1 = fu1->s_p;
05373 is->s2 = fu2->s_p;
05374 is->fu1 = fu1;
05375 is->fu2 = fu2;
05376 is->mag1 = mag1;
05377 is->mag2 = mag2;
05378 #if 0
05379
05380
05381
05382 nmg_isect_line2_face2pNEW(is, fu1, fu2, &eu1_list, &eu2_list);
05383
05384 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05385 nmg_fu_touchingloops(fu1);
05386 nmg_fu_touchingloops(fu2);
05387 nmg_vfu( &fu1->s_p->fu_hd, fu1->s_p );
05388 nmg_vfu( &fu2->s_p->fu_hd, fu2->s_p );
05389 }
05390
05391
05392
05393
05394 if (rt_g.NMG_debug & DEBUG_FCUT) {
05395 bu_log("nmg_isect_two_face3p(fu1=x%x, fu2=x%x) vert_lists A:\n", fu1, fu2);
05396 nmg_pr_ptbl_vert_list( "vert_list1", &vert_list1, mag1 );
05397 nmg_pr_ptbl_vert_list( "vert_list2", &vert_list2, mag2 );
05398 }
05399
05400 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
05401 bu_log("nmg_isect_two_face3p( fu1=x%x, fu2=x%x ) START21\n", fu1, fu2);
05402 }
05403 #endif
05404
05405
05406
05407
05408 is->l2 = &vert_list1;
05409 is->l1 = &vert_list2;
05410 is->s2 = fu1->s_p;
05411 is->s1 = fu2->s_p;
05412 is->fu2 = fu1;
05413 is->fu1 = fu2;
05414 is->mag1 = mag2;
05415 is->mag2 = mag1;
05416
05417 is->on_eg = (struct edge_g_lseg *)NULL;
05418 nmg_isect_fu_jra(is, fu1, fu2, &eu1_list, &eu2_list);
05419
05420 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05421 nmg_fu_touchingloops(fu1);
05422 nmg_fu_touchingloops(fu2);
05423 nmg_vfu( &fu1->s_p->fu_hd, fu1->s_p );
05424 nmg_vfu( &fu2->s_p->fu_hd, fu2->s_p );
05425 }
05426 #if 0
05427 nmg_purge_unwanted_intersection_points(&vert_list1, mag1, fu2, &is->tol);
05428 nmg_purge_unwanted_intersection_points(&vert_list2, mag2, fu1, &is->tol);
05429 #endif
05430 if (rt_g.NMG_debug & DEBUG_FCUT) {
05431 bu_log("nmg_isect_two_face3p(fu1=x%x, fu2=x%x) vert_lists B:\n", fu1, fu2);
05432 nmg_pr_ptbl_vert_list( "vert_list1", &vert_list1, mag1 );
05433 nmg_pr_ptbl_vert_list( "vert_list2", &vert_list2, mag2 );
05434 }
05435
05436 if (vert_list1.end == 0 && vert_list2.end == 0) {
05437
05438 goto out;
05439 }
05440
05441 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
05442 bu_log("nmg_isect_two_face3p( fu1=x%x, fu2=x%x ) MIDDLE\n", fu1, fu2);
05443 }
05444
05445 is->on_eg = nmg_face_cutjoin(&vert_list1, &vert_list2, mag1, mag2, fu1, fu2, is->pt, is->dir, is->on_eg, &is->tol);
05446
05447 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05448 nmg_fu_touchingloops(fu1);
05449 nmg_fu_touchingloops(fu2);
05450 nmg_region_v_unique( fu1->s_p->r_p, &is->tol );
05451 nmg_region_v_unique( fu2->s_p->r_p, &is->tol );
05452 nmg_vfu( &fu1->s_p->fu_hd, fu1->s_p );
05453 nmg_vfu( &fu2->s_p->fu_hd, fu2->s_p );
05454 }
05455
05456 nmg_mesh_faces(fu1, fu2, &is->tol);
05457 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05458 nmg_fu_touchingloops(fu1);
05459 nmg_fu_touchingloops(fu2);
05460 }
05461
05462 #if 0
05463 nmg_show_broken_classifier_stuff((long *)fu1, (long **)NULL, 1, 0);
05464 nmg_show_broken_classifier_stuff((long *)fu2, (long **)NULL, 1, 0);
05465 #endif
05466
05467 out:
05468 (void)bu_ptbl_free(&vert_list1);
05469 (void)bu_ptbl_free(&vert_list2);
05470 (void)bu_ptbl_free(&eu1_list);
05471 (void)bu_ptbl_free(&eu2_list);
05472 if( mag1 )
05473 bu_free( (char *)mag1, "nmg_isect_two_face3p: mag1" );
05474 if( mag2 )
05475 bu_free( (char *)mag2, "nmg_isect_two_face3p: mag2" );
05476
05477
05478 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
05479 nmg_vfu( &fu1->s_p->fu_hd, fu1->s_p );
05480 nmg_vfu( &fu2->s_p->fu_hd, fu2->s_p );
05481 }
05482 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
05483 bu_log("nmg_isect_two_face3p( fu1=x%x, fu2=x%x ) END\n", fu1, fu2);
05484 VPRINT("isect ray is->pt ", is->pt);
05485 VPRINT("isect ray is->dir", is->dir);
05486 }
05487 }
05488
05489 void
05490 nmg_cut_lu_into_coplanar_and_non(struct loopuse *lu, fastf_t *pl, struct nmg_inter_struct *is)
05491 {
05492 struct model *m;
05493 struct edgeuse *eu;
05494 struct vertex_g *vg2;
05495 struct vertex *vcut1,*vcut2;
05496 struct bu_ptbl cut_list;
05497 fastf_t dist,dist2;
05498 int class1,class2;
05499 int in=0;
05500 int on=0;
05501 int out=0;
05502 int i;
05503
05504 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05505 bu_log( "nmg_cut_lu_into_coplanar_and_non( lu=x%x, pl=%g %g %g %g )\n", lu, V4ARGS( pl ) );
05506
05507 NMG_CK_LOOPUSE( lu );
05508 NMG_CK_INTER_STRUCT( is );
05509
05510 m = nmg_find_model( &is->fu1->l.magic );
05511
05512
05513 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
05514 return;
05515
05516 bu_ptbl_init( &cut_list, 64, " &cut_list");
05517
05518 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
05519 vg2 = eu->vu_p->v_p->vg_p;
05520 NMG_CK_VERTEX_G( vg2 );
05521 dist2 = DIST_PT_PLANE( vg2->coord, pl );
05522 if( dist2 > is->tol.dist )
05523 {
05524 class2 = NMG_CLASS_AoutB;
05525 out++;
05526 }
05527 else if( dist2 < (-is->tol.dist) )
05528 {
05529 class2 = NMG_CLASS_AinB;
05530 in++;
05531 }
05532 else
05533 {
05534 class2 = NMG_CLASS_AonBshared;
05535 on++;
05536 }
05537
05538 vcut1 = (struct vertex *)NULL;
05539 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
05540 {
05541 class1 = class2;
05542
05543 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
05544 dist2 = DIST_PT_PLANE( vg2->coord, pl );
05545
05546 if( dist2 > is->tol.dist )
05547 {
05548 class2 = NMG_CLASS_AoutB;
05549 out++;
05550 }
05551 else if( dist2 < (-is->tol.dist) )
05552 {
05553 class2 = NMG_CLASS_AinB;
05554 in++;
05555 }
05556 else
05557 {
05558 class2 = NMG_CLASS_AonBshared;
05559 on++;
05560 }
05561
05562 if( class1 == NMG_CLASS_AonBshared && class2 != class1 )
05563 {
05564 if( !vcut1 )
05565 {
05566 vcut1 = eu->vu_p->v_p;
05567 }
05568 else if( vcut1 != eu->vu_p->v_p )
05569 {
05570 bu_ptbl_ins( &cut_list, (long *)vcut1 );
05571 bu_ptbl_ins( &cut_list, (long *)eu->vu_p->v_p );
05572 vcut1 = (struct vertex *)NULL;
05573 }
05574 }
05575 else if( class2 == NMG_CLASS_AonBshared && class1 != class2 )
05576 {
05577 if( !vcut1 )
05578 {
05579 vcut1 = eu->eumate_p->vu_p->v_p;
05580 }
05581 else if( vcut1 != eu->eumate_p->vu_p->v_p )
05582 {
05583 bu_ptbl_ins( &cut_list, (long *)vcut1 );
05584 bu_ptbl_ins( &cut_list, (long *)eu->eumate_p->vu_p->v_p );
05585 vcut1 = (struct vertex *)NULL;
05586 }
05587 }
05588 }
05589
05590 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05591 {
05592 bu_log( "\t pl=( %g %g %g %g )\n", V4ARGS( pl ) );
05593 bu_log( "\tcut_lists=%d, on=%d, in=%d, out=%d\n", BU_PTBL_END( &cut_list ),on,in,out );
05594 if( BU_PTBL_END( &cut_list ) )
05595 {
05596 bu_log( "\tcut_lists:\n" );
05597 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05598 {
05599 struct vertex *v;
05600
05601 v = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05602 bu_log( "\t\t%d, x%x\n", i+1, v );
05603 }
05604 }
05605 }
05606
05607 if( !on )
05608 return;
05609
05610 if( BU_PTBL_END( &cut_list ) < 2 )
05611 {
05612 bu_ptbl_free( &cut_list);
05613
05614 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05615 bu_log( "No loops need cutting\n" );
05616 return;
05617 }
05618
05619 if( nmg_loop_is_a_crack( lu ) )
05620 {
05621 struct bu_ptbl lus;
05622
05623 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05624 bu_log( "Loop is a crack\n" );
05625
05626 i = 0;
05627 while( i < BU_PTBL_END( &cut_list ) )
05628 {
05629 struct vertexuse *vu;
05630
05631 vcut1 = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05632 for( BU_LIST_FOR( vu, vertexuse, &vcut1->vu_hd ) )
05633 {
05634 if( nmg_find_lu_of_vu( vu ) != lu )
05635 continue;
05636
05637 eu = vu->up.eu_p;
05638 if( NMG_ARE_EUS_ADJACENT( eu, BU_LIST_PNEXT_CIRC( edgeuse, &eu->l ) ) )
05639 {
05640 i--;
05641 bu_ptbl_rm( &cut_list, (long *)vcut1 );
05642 }
05643 else if( NMG_ARE_EUS_ADJACENT( eu, BU_LIST_PPREV_CIRC( edgeuse, &eu->l ) ) )
05644 {
05645 i--;
05646 bu_ptbl_rm( &cut_list, (long *)vcut1 );
05647 }
05648 }
05649 i++;
05650 }
05651
05652 if( BU_PTBL_END( &cut_list ) == 0 )
05653 {
05654 bu_ptbl_free( &cut_list);
05655
05656 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05657 bu_log( "no loops need cutting\n" );
05658 return;
05659 }
05660
05661 bu_ptbl_init( &lus, 64, " &lus");
05662 bu_ptbl_ins( &lus, (long *)lu );
05663 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05664 {
05665 int j;
05666
05667 vcut1 = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05668
05669 for( j=0 ; j<BU_PTBL_END( &lus ) ; j++ )
05670 {
05671 int did_split=0;
05672 struct loopuse *lu1;
05673 struct vertexuse *vu1;
05674 struct loopuse *new_lu;
05675
05676 lu1 = (struct loopuse *)BU_PTBL_GET( &lus, j );
05677
05678 for( BU_LIST_FOR( vu1, vertexuse, &vcut1->vu_hd ) )
05679 {
05680 if( nmg_find_lu_of_vu( vu1 ) == lu1 )
05681 {
05682 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05683 bu_log( "Splitting lu x%x at vu x%x\n", lu1, vu1 );
05684 new_lu = nmg_split_lu_at_vu( lu1, vu1 );
05685 nmg_lu_reorient( lu1 );
05686 nmg_lu_reorient( new_lu );
05687 nmg_loop_g( new_lu->l_p, &is->tol );
05688 nmg_loop_g( lu1->l_p, &is->tol );
05689 bu_ptbl_ins( &lus, (long *)new_lu );
05690 did_split = 1;
05691 break;
05692 }
05693 }
05694 if( did_split )
05695 break;
05696 }
05697 }
05698 bu_ptbl_free( &lus);
05699 bu_ptbl_free( &cut_list);
05700 return;
05701 }
05702
05703 if( BU_PTBL_END( &cut_list )%2 )
05704 {
05705 bu_log( "Uneven number (%d) of vertices on cut list\n" , BU_PTBL_END( &cut_list ) );
05706 rt_bomb( "Uneven number of vertices on cut list" );
05707 }
05708
05709
05710 if( BU_PTBL_END( &cut_list ) > 2 )
05711 {
05712 struct vertex *v1=(struct vertex *)NULL;
05713 struct vertex *v2=(struct vertex *)NULL;
05714 struct vertex *end1 = NULL, *end2 = NULL;
05715 fastf_t max_dist = 0.0;
05716 vect_t diff;
05717 fastf_t *dist_array;
05718 int done;
05719
05720
05721 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05722 {
05723 int j;
05724
05725 v1 = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05726
05727 for( j=i ; j<BU_PTBL_END( &cut_list ) ; j++ )
05728 {
05729 fastf_t tmp_dist;
05730
05731 v2 = (struct vertex *)BU_PTBL_GET( &cut_list, j );
05732 VSUB2( diff, v1->vg_p->coord, v2->vg_p->coord )
05733 tmp_dist = MAGSQ( diff );
05734 if( tmp_dist > max_dist )
05735 {
05736 max_dist = tmp_dist;
05737 end1 = v1;
05738 end2 = v2;
05739 }
05740 }
05741 }
05742 if( !end1 || !end2 )
05743 {
05744 bu_log( "nmg_cut_lu_into_coplanar_and_non: Cannot find endpoints\n" );
05745 rt_bomb( "nmg_cut_lu_into_coplanar_and_non: Cannot find endpoints\n" );
05746 }
05747
05748
05749 dist_array = (fastf_t *)bu_calloc( sizeof( fastf_t ), BU_PTBL_END( &cut_list ), "distance array" );
05750 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05751 {
05752 v1 = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05753 if( v1 == end1 )
05754 {
05755 dist_array[i] = 0.0;
05756 continue;
05757 }
05758 if( v1 == end2 )
05759 {
05760 dist_array[i] = max_dist;
05761 continue;
05762 }
05763
05764 VSUB2( diff, v1->vg_p->coord, end1->vg_p->coord )
05765 dist_array[i] = MAGSQ( diff );
05766 }
05767
05768
05769 done = 0;
05770 while( !done )
05771 {
05772 fastf_t tmp_dist;
05773 long *tmp_v;
05774
05775 done = 1;
05776 for( i=1 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05777 {
05778 if( dist_array[i-1] <= dist_array[i] )
05779 continue;
05780
05781
05782 tmp_dist = dist_array[i];
05783 dist_array[i] = dist_array[i-1];
05784 dist_array[i-1] = tmp_dist;
05785
05786
05787 tmp_v = cut_list.buffer[i];
05788 cut_list.buffer[i] = cut_list.buffer[i-1];
05789 cut_list.buffer[i-1] = tmp_v;
05790
05791 done = 0;
05792 }
05793 }
05794
05795 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05796 {
05797 bu_log( "After sorting:\n" );
05798 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i++ )
05799 bu_log( "v=x%x, dist=%g\n", BU_PTBL_GET( &cut_list, i ), dist_array[i] );
05800 }
05801
05802 bu_free( (char *)dist_array, "distance array" );
05803 }
05804
05805 for( i=0 ; i<BU_PTBL_END( &cut_list ) ; i += 2 )
05806 {
05807 struct loopuse *lu1;
05808 struct vertexuse *vu;
05809 vect_t dir;
05810 point_t hit_pt;
05811 struct vertex *hit_v;
05812 struct vertexuse *hit_vu;
05813 struct edgeuse *new_eu;
05814 fastf_t len;
05815 fastf_t inv_len;
05816 int skip=0;
05817
05818 vcut1 = (struct vertex *)BU_PTBL_GET( &cut_list, i );
05819 vcut2 = (struct vertex *)BU_PTBL_GET( &cut_list, i+1 );
05820
05821 if( vcut1 == vcut2 )
05822 continue;
05823
05824
05825 for( BU_LIST_FOR( vu, vertexuse, &vcut1->vu_hd ) )
05826 {
05827 if( nmg_find_lu_of_vu( vu ) != lu )
05828 continue;
05829
05830 eu = vu->up.eu_p;
05831 if( eu->eumate_p->vu_p->v_p == vcut2 )
05832 {
05833
05834 skip = 1;
05835 break;
05836 }
05837 }
05838 if( skip )
05839 continue;
05840
05841
05842 VMOVE( is->pt, vcut1->vg_p->coord );
05843 VSUB2( dir, vcut2->vg_p->coord, vcut1->vg_p->coord );
05844 len = MAGNITUDE( dir );
05845 if( len <= is->tol.dist )
05846 continue;
05847
05848 inv_len = 1.0/len;
05849 VSCALE( is->dir, dir, inv_len );
05850
05851
05852 bu_ptbl_reset( is->l1);
05853
05854
05855 for( BU_LIST_FOR( vu, vertexuse, &vcut1->vu_hd ) )
05856 {
05857 if( nmg_find_fu_of_vu( vu ) == is->fu1 )
05858 nmg_enlist_one_vu( is, vu, 0.0 );
05859 }
05860
05861
05862 for( BU_LIST_FOR( vu, vertexuse, &vcut2->vu_hd ) )
05863 {
05864 if( nmg_find_fu_of_vu( vu ) == is->fu1 )
05865 nmg_enlist_one_vu( is, vu, len );
05866 }
05867
05868
05869 for( BU_LIST_FOR( lu1, loopuse, &is->fu1->lu_hd ) )
05870 {
05871 struct edgeuse *eu1;
05872
05873 NMG_CK_LOOPUSE( lu1 );
05874
05875 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_EDGEUSE_MAGIC )
05876 continue;
05877
05878 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) )
05879 {
05880 int code;
05881 fastf_t dists[2];
05882 vect_t dir2;
05883
05884 NMG_CK_EDGEUSE( eu1 );
05885
05886 VSUB2( dir2, eu1->eumate_p->vu_p->v_p->vg_p->coord, eu1->vu_p->v_p->vg_p->coord );
05887 code = bn_isect_lseg3_lseg3( dists, is->pt, dir,
05888 eu1->vu_p->v_p->vg_p->coord, dir2, &is->tol );
05889 if( code < 0 )
05890 continue;
05891
05892 if( code == 0 )
05893 {
05894 if( dists[0] > 0.0 && dists[0] < 1.0 )
05895 {
05896 dist = dists[0]*len;
05897 for( BU_LIST_FOR( vu, vertexuse, &eu1->vu_p->v_p->vu_hd ) )
05898 {
05899 if( nmg_find_fu_of_vu( vu ) == is->fu1 )
05900 nmg_enlist_one_vu( is, vu, dist );
05901 }
05902 }
05903 if( dists[1] > 0.0 && dists[1] < 1.0 )
05904 {
05905 dist = dists[1]*len;
05906 for( BU_LIST_FOR( vu, vertexuse, &eu1->eumate_p->vu_p->v_p->vu_hd ) )
05907 {
05908 if( nmg_find_fu_of_vu( vu ) == is->fu1 )
05909 nmg_enlist_one_vu( is, vu, len );
05910 }
05911 }
05912 continue;
05913 }
05914
05915
05916 if( dists[0] <= 0.0 || dists[0] >= 1.0 )
05917 continue;
05918
05919 if( dists[1] <= 0.0 || dists[1] >= 1.0 )
05920 continue;
05921
05922 VJOIN1( hit_pt, is->pt, dists[0], dir );
05923 hit_vu = (struct vertexuse *)NULL;
05924 hit_v = (struct vertex *)NULL;
05925
05926 hit_vu = nmg_find_pt_in_face( is->fu1, hit_pt, &is->tol );
05927 if( hit_vu )
05928 hit_v = hit_vu->v_p;
05929
05930 if( !hit_v )
05931 hit_v = nmg_find_pt_in_model( m, hit_pt, &is->tol );
05932 new_eu = nmg_esplit( hit_v, eu1, 1 );
05933 hit_v = new_eu->vu_p->v_p;
05934 if( !hit_v->vg_p )
05935 nmg_vertex_gv( hit_v, hit_pt );
05936
05937
05938 dist = dists[0]*len;
05939 for( BU_LIST_FOR( vu, vertexuse, &hit_v->vu_hd ) )
05940 {
05941 if( nmg_find_fu_of_vu( vu ) == is->fu1 )
05942 nmg_enlist_one_vu( is, vu, dist );
05943 }
05944 }
05945 }
05946
05947 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05948 bu_log( "nmg_cut_lu_into_coplanar_and_non: calling face cutter\n" );
05949 bu_ptbl_reset( is->l2);
05950 (void)nmg_face_cutjoin( is->l1, is->l2, is->mag1, is->mag2, is->fu1,
05951 is->fu2, is->pt, is->dir, is->on_eg, &is->tol);
05952
05953 vcut1 = (struct vertex *)NULL;
05954 vcut2 = (struct vertex *)NULL;
05955 }
05956
05957 bu_ptbl_free( &cut_list);
05958 }
05959
05960 static void
05961 nmg_isect_coplanar_edges(struct nmg_inter_struct *is, struct bu_ptbl *eu1_list, struct bu_ptbl *eu2_list)
05962 {
05963 struct model *m;
05964 struct loopuse *lu;
05965 struct bu_ptbl v_list;
05966 int i,j;
05967 plane_t pl1,pl2;
05968
05969 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05970 bu_log( "nmg_isect_coplanar_edges START\n" );
05971
05972 NMG_CK_INTER_STRUCT( is );
05973 BU_CK_PTBL( eu1_list );
05974 BU_CK_PTBL( eu2_list );
05975
05976 m = nmg_find_model( &is->fu1->l.magic );
05977
05978 NMG_GET_FU_PLANE( pl1, is->fu1 );
05979 NMG_GET_FU_PLANE( pl2, is->fu2 );
05980
05981 if (rt_g.NMG_debug & DEBUG_POLYSECT)
05982 {
05983 bu_log( "pl1 = %g %g %g %g\n", V4ARGS( pl1 ) );
05984 bu_log( "pl2 = %g %g %g %g\n", V4ARGS( pl2 ) );
05985 }
05986
05987
05988 for( i=0 ; i<BU_PTBL_END( eu1_list ) ; i++ )
05989 {
05990 struct edgeuse *eu1;
05991 double len_vt1;
05992 vect_t vt1;
05993 struct vertex_g *vg1a,*vg1b;
05994
05995 eu1 = (struct edgeuse *)BU_PTBL_GET( eu1_list, i );
05996 NMG_CK_EDGEUSE( eu1 );
05997
05998 vg1a = eu1->vu_p->v_p->vg_p;
05999 NMG_CK_VERTEX_G( vg1a );
06000 vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
06001 NMG_CK_VERTEX_G( vg1b );
06002
06003 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06004 bu_log( "Considering EU x%x (%g %g %g) <-> (%g %g %g)\n",
06005 eu1, V3ARGS( vg1a->coord ), V3ARGS( vg1b->coord ) );
06006
06007 #if 0
06008
06009 if( !NEAR_ZERO( DIST_PT_PLANE( vg1a->coord, pl2 ), is->tol.dist ) )
06010 {
06011 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06012 bu_log( "\tvg1a is not in other plane (%g)\n", DIST_PT_PLANE( vg1a->coord, pl2 ) );
06013 continue;
06014 }
06015 if( !NEAR_ZERO( DIST_PT_PLANE( vg1b->coord, pl2 ), is->tol.dist ) )
06016 {
06017 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06018 bu_log( "\tvg1b is not in other plane (%g)\n", DIST_PT_PLANE( vg1b->coord, pl2 ) );
06019 continue;
06020 }
06021 #endif
06022
06023 VSUB2( vt1, vg1b->coord, vg1a->coord );
06024 len_vt1 = MAGNITUDE( vt1 );
06025 VSCALE( vt1, vt1, 1.0/len_vt1 );
06026
06027 for( j=0 ; j<BU_PTBL_END( eu2_list ) ; j++ )
06028 {
06029 struct edgeuse *eu2;
06030 struct vertex_g *vg2a,*vg2b;
06031 int code;
06032 vect_t vt2;
06033 double len_vt2;
06034 fastf_t dist[2];
06035 point_t hit_pt;
06036 int hit_no;
06037 int hit_count;
06038 struct vertex *hitv;
06039 struct vertexuse *hit_vu;
06040
06041 eu2 = (struct edgeuse *)BU_PTBL_GET( eu2_list, j );
06042 NMG_CK_EDGEUSE( eu2 );
06043
06044 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06045 bu_log( "\tConsidering EU2 x%x (%g %g %g) <-> (%g %g %g)\n",
06046 eu2, V3ARGS( eu2->vu_p->v_p->vg_p->coord ), V3ARGS( eu2->eumate_p->vu_p->v_p->vg_p->coord ) );
06047 #if 0
06048
06049 if( !NEAR_ZERO( DIST_PT_PLANE( eu2->vu_p->v_p->vg_p->coord, pl1 ), is->tol.dist ) )
06050 {
06051 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06052 bu_log( "\t\tEU2 start pt not in other plane (%g)\n",
06053 DIST_PT_PLANE( eu2->vu_p->v_p->vg_p->coord, pl1 ) );
06054 continue;
06055 }
06056 if( !NEAR_ZERO( DIST_PT_PLANE( eu2->eumate_p->vu_p->v_p->vg_p->coord, pl1 ), is->tol.dist ) )
06057 {
06058 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06059 bu_log( "\t\tEU2 end pt not in other plane (%g)\n",
06060 DIST_PT_PLANE( eu2->eumate_p->vu_p->v_p->vg_p->coord, pl1 ) );
06061 continue;
06062 }
06063 #endif
06064
06065
06066 if( eu1->vu_p->v_p == eu2->vu_p->v_p &&
06067 eu1->eumate_p->vu_p->v_p == eu2->eumate_p->vu_p->v_p )
06068 continue;
06069
06070 if( eu1->vu_p->v_p == eu2->eumate_p->vu_p->v_p &&
06071 eu1->eumate_p->vu_p->v_p == eu2->vu_p->v_p )
06072 continue;
06073
06074 vg2a = eu2->vu_p->v_p->vg_p;
06075 NMG_CK_VERTEX_G( vg2a );
06076 vg2b = eu2->eumate_p->vu_p->v_p->vg_p;
06077 NMG_CK_VERTEX_G( vg2b );
06078 VSUB2( vt2, vg2b->coord, vg2a->coord );
06079 len_vt2 = MAGNITUDE( vt2 );
06080 VSCALE( vt2, vt2, 1.0/len_vt2 );
06081
06082 code = rt_dist_line3_line3( dist, vg1a->coord, vt1,
06083 vg2a->coord, vt2, &is->tol );
06084
06085 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06086 bu_log( "\tcode = %d\n", code );
06087
06088 if( code == (-2) || code == 1 )
06089 continue;
06090
06091 if( code == (-1) )
06092 {
06093 fastf_t tmp;
06094 vect_t tmp_vect;
06095 fastf_t dist1[2];
06096
06097 hit_count = 0;
06098
06099
06100 VSUB2( tmp_vect, vg2a->coord, vg1a->coord );
06101 dist1[0] = VDOT( tmp_vect, vt1 );
06102 if( NEAR_ZERO( dist1[0], is->tol.dist ) )
06103 dist1[0] = 0.0;
06104 else if( NEAR_ZERO( dist1[0] - len_vt1, is->tol.dist ) )
06105 dist1[0] = len_vt1;
06106 VSUB2( tmp_vect, vg2b->coord, vg1a->coord );
06107 dist1[1] = VDOT( tmp_vect, vt1 );
06108 if( NEAR_ZERO( dist1[1], is->tol.dist ) )
06109 dist1[1] = 0.0;
06110 else if( NEAR_ZERO( dist1[1] - len_vt1, is->tol.dist ) )
06111 dist1[1] = len_vt1;
06112
06113 if( (dist1[0] >= 0.0 && dist1[0] <= len_vt1 ) )
06114 {
06115 dist[hit_count] = dist1[0];
06116 hit_count++;
06117 }
06118 if ( (dist1[1] >= 0.0 && dist1[1] <= len_vt1 ) )
06119 {
06120 dist[hit_count] = dist1[1];
06121 hit_count++;
06122 }
06123
06124 if( hit_count == 0 )
06125 continue;
06126
06127 if( hit_count == 2 && dist[0] < dist[1] )
06128 {
06129 tmp = dist[0];
06130 dist[0] = dist[1];
06131 dist[1] = tmp;
06132 }
06133 }
06134 else
06135 {
06136 if( NEAR_ZERO( dist[0], is->tol.dist ) )
06137 dist[0] = 0.0;
06138 else if( NEAR_ZERO( dist[0] - len_vt1, is->tol.dist ) )
06139 dist[0] = len_vt1;
06140 if( NEAR_ZERO( dist[1], is->tol.dist ) )
06141 dist[1] = 0.0;
06142 else if( NEAR_ZERO( dist[1] - len_vt2, is->tol.dist ) )
06143 dist[1] = len_vt2;
06144 if( dist[0] < 0.0 || dist[0] > len_vt1 )
06145 continue;
06146 if( dist[1] < 0.0 || dist[1] > len_vt2 )
06147 continue;
06148 hit_count = 1;
06149 }
06150
06151 for( hit_no=0 ; hit_no < hit_count ; hit_no++ )
06152 {
06153 struct edgeuse *new_eu;
06154
06155 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06156 bu_log( "\tdist[%d] = %g\n", hit_no, dist[hit_no] );
06157
06158 hitv = (struct vertex *)NULL;
06159 hit_vu = (struct vertexuse *)NULL;
06160
06161 if( dist[hit_no] == 0.0 )
06162 {
06163 hit_vu = eu1->vu_p;
06164 hitv = hit_vu->v_p;
06165 VMOVE( hit_pt, hitv->vg_p->coord );
06166 }
06167 else if( dist[hit_no] == len_vt1 )
06168 {
06169 hit_vu = eu1->eumate_p->vu_p;
06170 hitv = hit_vu->v_p;
06171 VMOVE( hit_pt, hitv->vg_p->coord );
06172 }
06173 else
06174 VJOIN1( hit_pt, vg1a->coord , dist[hit_no], vt1 )
06175
06176 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06177 bu_log( "eus x%x and x%x intersect #%d at (%g %g %g)\n",
06178 eu1, eu2, hit_no, V3ARGS( hit_pt ) );
06179
06180 if( !hit_vu )
06181 hit_vu = nmg_find_pt_in_face( is->fu2, hit_pt, &is->tol );
06182
06183 if( !hit_vu )
06184 hitv = nmg_find_pt_in_model( nmg_find_model( &is->fu1->l.magic ), hit_pt, &is->tol );
06185 else
06186 hitv = hit_vu->v_p;
06187
06188 if (rt_g.NMG_debug & DEBUG_POLYSECT && hitv)
06189 bu_log( "Found vertex (x%x) at hit_pt\n", hitv );
06190
06191 if( hitv != eu1->vu_p->v_p && hitv != eu1->eumate_p->vu_p->v_p )
06192 {
06193 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06194 bu_log( "Splitting eu1 x%x\n", eu1 );
06195 new_eu = nmg_esplit( hitv, eu1, 1 );
06196 hitv = new_eu->vu_p->v_p;
06197 if( !hitv->vg_p )
06198 nmg_vertex_gv( hitv, hit_pt );
06199 vg1b = eu1->eumate_p->vu_p->v_p->vg_p;
06200 VSUB2( vt1, vg1b->coord, vg1a->coord );
06201 len_vt1 = MAGNITUDE( vt1 );
06202 VSCALE( vt1, vt1, 1.0/len_vt1 );
06203 bu_ptbl_ins( eu1_list, (long *)new_eu );
06204 }
06205 if( code == 0 && hitv != eu2->vu_p->v_p && hitv != eu2->eumate_p->vu_p->v_p )
06206 {
06207 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06208 bu_log( "Splitting eu2 x%x at hitv = x%x\n", eu2, hitv );
06209 new_eu = nmg_esplit( hitv, eu2, 1 );
06210 hitv = new_eu->vu_p->v_p;
06211 if( !hitv->vg_p )
06212 nmg_vertex_gv( hitv, hit_pt );
06213 bu_ptbl_ins( eu2_list, (long *)new_eu );
06214 }
06215
06216 if( hitv )
06217 (void)nmg_break_all_es_on_v( &m->magic, hitv, &is->tol );
06218 }
06219 }
06220 }
06221
06222 bu_ptbl_free( eu1_list);
06223 bu_ptbl_free( eu2_list);
06224
06225
06226
06227
06228 nmg_vertex_tabulate( &v_list, &is->fu1->l.magic );
06229
06230 for( i=0 ; i<BU_PTBL_END( &v_list ) ; i++ )
06231 {
06232 struct vertex *v;
06233 int class;
06234
06235 v = (struct vertex *)BU_PTBL_GET( &v_list, i );
06236 NMG_CK_VERTEX( v );
06237
06238 if( nmg_find_v_in_face( v, is->fu2 ) )
06239 continue;
06240
06241
06242 if( !NEAR_ZERO( DIST_PT_PLANE( v->vg_p->coord, pl2 ), is->tol.dist ) )
06243 continue;
06244
06245 class = nmg_class_pt_fu_except( v->vg_p->coord, is->fu2, NULL, NULL, NULL,
06246 (char *)NULL, 0, 0, &is->tol );
06247
06248 if( class == NMG_CLASS_AinB )
06249 {
06250 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06251 bu_log( "Making dualvu of vertex x%x in is->fu2 x%x\n", v, is->fu2 );
06252 (void)nmg_make_dualvu( v, is->fu2, &is->tol );
06253 }
06254 }
06255 bu_ptbl_reset( &v_list);
06256
06257
06258 nmg_vertex_tabulate( &v_list, &is->fu2->l.magic );
06259
06260 for( i=0 ; i<BU_PTBL_END( &v_list ) ; i++ )
06261 {
06262 struct vertex *v;
06263 int class;
06264
06265 v = (struct vertex *)BU_PTBL_GET( &v_list, i );
06266 NMG_CK_VERTEX( v );
06267
06268 if( nmg_find_v_in_face( v, is->fu1 ) )
06269 continue;
06270
06271
06272 if( !NEAR_ZERO( DIST_PT_PLANE( v->vg_p->coord, pl1 ), is->tol.dist ) )
06273 continue;
06274
06275 class = nmg_class_pt_fu_except( v->vg_p->coord, is->fu1, NULL, NULL, NULL,
06276 (char *)NULL, 0, 0, &is->tol );
06277
06278 if( class == NMG_CLASS_AinB )
06279 {
06280 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06281 bu_log( "Making dualvu of vertex x%x in fu1 x%x\n", v, is->fu1 );
06282 (void)nmg_make_dualvu( v, is->fu1, &is->tol );
06283 }
06284 }
06285
06286 bu_ptbl_free( &v_list);
06287
06288 bu_ptbl_reset( is->l1);
06289 bu_ptbl_reset( is->l2);
06290
06291 for( BU_LIST_FOR( lu, loopuse, &is->fu1->lu_hd ) )
06292 {
06293 struct edgeuse *eu;
06294
06295 NMG_CK_LOOPUSE( lu );
06296
06297 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06298 continue;
06299
06300 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06301 {
06302 struct vertexuse *vu;
06303 struct vertex *v1,*v2;
06304
06305 NMG_CK_EDGEUSE( eu );
06306
06307 v1 = eu->vu_p->v_p;
06308 NMG_CK_VERTEX( v1 );
06309 v2 = eu->eumate_p->vu_p->v_p;
06310 NMG_CK_VERTEX( v2 );
06311
06312 if( !NEAR_ZERO( DIST_PT_PLANE( v1->vg_p->coord, pl2), is->tol.dist ) )
06313 continue;
06314 if( !NEAR_ZERO( DIST_PT_PLANE( v2->vg_p->coord, pl2), is->tol.dist ) )
06315 continue;
06316
06317 if( !nmg_find_v_in_face( v1, is->fu2 ) ||
06318 !nmg_find_v_in_face( v2, is->fu2 ) )
06319 continue;
06320
06321 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06322 bu_log( "Making EU x%x an intersect line for face cutting\n", eu );
06323
06324 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
06325 {
06326 struct faceuse *fu;
06327
06328 fu = nmg_find_fu_of_vu( vu );
06329
06330 if( fu == is->fu2 )
06331 nmg_enlist_one_vu( is, vu, 0.0 );
06332 }
06333
06334 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
06335 {
06336 struct faceuse *fu;
06337
06338 fu = nmg_find_fu_of_vu( vu );
06339
06340 if( fu == is->fu2 )
06341 nmg_enlist_one_vu( is, vu, 1.0 );
06342 }
06343
06344
06345 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06346 bu_log( "Calling face cutter for fu2 x%x\n", is->fu2 );
06347 nmg_fcut_face_2d( is->l2, is->mag2, is->fu2, is->fu1, &is->tol );
06348
06349 bu_ptbl_reset( is->l1);
06350 bu_ptbl_reset( is->l2);
06351 }
06352 }
06353
06354 for( BU_LIST_FOR( lu, loopuse, &is->fu2->lu_hd ) )
06355 {
06356 struct edgeuse *eu;
06357
06358 NMG_CK_LOOPUSE( lu );
06359
06360 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06361 continue;
06362
06363 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06364 {
06365 struct vertexuse *vu;
06366 struct vertex *v1,*v2;
06367
06368 NMG_CK_EDGEUSE( eu );
06369
06370 v1 = eu->vu_p->v_p;
06371 NMG_CK_VERTEX( v1 );
06372 v2 = eu->eumate_p->vu_p->v_p;
06373 NMG_CK_VERTEX( v2 );
06374
06375 if( !NEAR_ZERO( DIST_PT_PLANE( v1->vg_p->coord, pl1), is->tol.dist ) )
06376 continue;
06377 if( !NEAR_ZERO( DIST_PT_PLANE( v2->vg_p->coord, pl1), is->tol.dist ) )
06378 continue;
06379
06380 if( !nmg_find_v_in_face( v1, is->fu1 ) ||
06381 !nmg_find_v_in_face( v2, is->fu1 ) )
06382 continue;
06383
06384 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06385 bu_log( "Making EU x%x an intersect line for face cutting\n", eu );
06386
06387 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
06388 {
06389 struct faceuse *fu;
06390
06391 fu = nmg_find_fu_of_vu( vu );
06392
06393 if( fu == is->fu1 )
06394 nmg_enlist_one_vu( is, vu, 0.0 );
06395 }
06396
06397 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
06398 {
06399 struct faceuse *fu;
06400
06401 fu = nmg_find_fu_of_vu( vu );
06402
06403 if( fu == is->fu1 )
06404 nmg_enlist_one_vu( is, vu, 1.0 );
06405 }
06406
06407
06408 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06409 bu_log( "Calling face cutter for fu1 x%x\n", is->fu1 );
06410 nmg_fcut_face_2d( is->l1, is->mag1, is->fu1, is->fu2, &is->tol );
06411
06412 bu_ptbl_reset( is->l1);
06413 bu_ptbl_reset( is->l2);
06414 }
06415 }
06416 }
06417
06418 #if 0
06419 static void
06420 jra_save_fu_data( fu1, fu2, pl1, pl2 )
06421 struct faceuse *fu1,*fu2;
06422 plane_t pl1,pl2;
06423 {
06424 NMG_CK_FACEUSE( fu1 );
06425 NMG_CK_FACEUSE( fu2 );
06426
06427 bu_log( "STARTDATA\n" );
06428 bu_log( "%f %f %f %f\n", V4ARGS( pl1 ) );
06429 bu_log( "%f %f %f %f\n", V4ARGS( pl2 ) );
06430 nmg_pr_fu_briefly( fu1, "" );
06431 nmg_pr_fu_briefly( fu2, "" );
06432 bu_log( "ENDDATA\n" );
06433 }
06434 #endif
06435 #define MAX_FACES 200
06436 void
06437 nmg_check_radial_angles(char *str, struct shell *s, const struct bn_tol *tol)
06438 {
06439 struct bu_ptbl edges;
06440 vect_t xvec,yvec,zvec;
06441 int i,j;
06442 double angle[MAX_FACES];
06443 struct faceuse *fus[MAX_FACES];
06444 int face_count;
06445 int increasing;
06446
06447 NMG_CK_SHELL( s );
06448 BN_CK_TOL( tol );
06449
06450 bu_ptbl_init( &edges, 64, " &edges");
06451 nmg_edge_tabulate( &edges, &s->l.magic );
06452
06453 for( i=0 ; i<BU_PTBL_END( &edges ) ; i++ )
06454 {
06455 struct edge *e;
06456 struct edgeuse *eu_start;
06457 struct edgeuse *eu;
06458 struct faceuse *fu;
06459 int start;
06460
06461 e = (struct edge *)BU_PTBL_GET( &edges, i );
06462 NMG_CK_EDGE( e );
06463
06464 eu_start = e->eu_p;
06465 NMG_CK_EDGEUSE( eu_start );
06466
06467 eu = eu_start;
06468 do
06469 {
06470 fu = nmg_find_fu_of_eu( eu );
06471 } while( !fu && eu != eu_start );
06472
06473 if( !fu )
06474 continue;
06475
06476 eu_start = eu;
06477 if( nmg_find_eu_leftvec( xvec, eu ) )
06478 rt_bomb( "nmg_check_radial_angles() eu not part of a face!!" );
06479
06480 VSUB2( zvec, eu->eumate_p->vu_p->v_p->vg_p->coord, eu->vu_p->v_p->vg_p->coord );
06481 VUNITIZE( zvec );
06482 VCROSS( yvec, zvec, xvec );
06483
06484 face_count = 0;
06485
06486 eu = eu_start;
06487 do
06488 {
06489 fu = nmg_find_fu_of_eu( eu );
06490 if( fu )
06491 {
06492 if( face_count >= MAX_FACES )
06493 {
06494 bu_log( "Too many faces in nmg_check_radial_angles (%d)\n", face_count );
06495 rt_bomb( "Too many faces in nmg_check_radial_angles\n" );
06496 }
06497 angle[face_count] = nmg_measure_fu_angle( eu, xvec, yvec, zvec );
06498 fus[face_count] = fu;
06499 face_count++;
06500 }
06501 eu = eu->eumate_p->radial_p;
06502 } while( eu != eu_start );
06503
06504
06505 increasing = (-1);
06506 start = 1;
06507 for( j=2 ; j<=face_count ; j++ )
06508 {
06509 if( angle[j] == 0.0 || angle[j] == bn_twopi )
06510 continue;
06511 if( angle[j] == angle[j-1] )
06512 continue;
06513 else if( angle[j] > angle[j-1] )
06514 {
06515 start = j;
06516 increasing = 1;
06517 break;
06518 }
06519 else
06520 {
06521 start = j;
06522 increasing = 0;
06523 break;
06524 }
06525 }
06526
06527 if( increasing == (-1 ) )
06528 continue;
06529
06530 for( j=start+1 ; j<face_count ; j++ )
06531 {
06532 if( (increasing && angle[j] < angle[j-1]) ||
06533 (!increasing && angle[j] > angle[j-1]) )
06534 {
06535 bu_log( str );
06536 bu_log( "nmg_check_radial_angles(): angles not monotonically increasing or decreasing\n" );
06537 bu_log( "start=%d, increasing = %d\n", start, increasing );
06538 bu_log( "\tfaces around eu x%x\n", eu_start );
06539 for( j=0 ; j<face_count ; j++ )
06540 bu_log( "\t\tfu=x%x, angle=%g\n", fus[j], angle[j]*180.0/bn_pi );
06541 rt_bomb( "nmg_check_radial_angles(): angles not monotonically increasing or decreasing\n" );
06542 }
06543 }
06544 }
06545 bu_ptbl_free( &edges);
06546 }
06547
06548
06549
06550
06551
06552
06553
06554
06555
06556
06557
06558
06559
06560
06561
06562
06563 static void
06564 nmg_isect_nearly_coplanar_faces(struct nmg_inter_struct *is, struct faceuse *fu1, struct faceuse *fu2)
06565 {
06566 int i;
06567 struct model *m;
06568 struct edgeuse *eu;
06569 struct loopuse *lu;
06570 struct bu_ptbl loops;
06571 plane_t pl1;
06572 plane_t pl2;
06573 fastf_t *mag1,*mag2;
06574 struct bu_ptbl eu1_list;
06575 struct bu_ptbl vert_list1;
06576 struct bu_ptbl eu2_list;
06577 struct bu_ptbl vert_list2;
06578 struct bu_ptbl verts;
06579
06580 NMG_CK_FACEUSE( fu1 );
06581 NMG_CK_FACEUSE( fu2 );
06582 NMG_CK_INTER_STRUCT(is);
06583
06584 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06585 bu_log( "nmg_isect_nearly_coplanar_faces( fu1=x%x, fu2=x%x )\n", fu1, fu2 );
06586
06587 m = nmg_find_model( &fu1->l.magic );
06588 NMG_CK_MODEL( m );
06589
06590 NMG_GET_FU_PLANE( pl1, fu1 );
06591 NMG_GET_FU_PLANE( pl2, fu2 );
06592
06593 #if 0
06594 jra_save_fu_data( fu1, fu2, pl1, pl2 );
06595 #endif
06596
06597 nmg_edgeuse_tabulate( &eu1_list, &fu1->l.magic );
06598 nmg_edgeuse_tabulate( &eu2_list, &fu2->l.magic );
06599
06600 is->mag_len = 2 * (BU_PTBL_END( &eu1_list ) + BU_PTBL_END( &eu2_list ) );
06601 mag1 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag1" );
06602 mag2 = (fastf_t *)bu_calloc( is->mag_len, sizeof( fastf_t ), "mag2" );
06603
06604 for( i=0 ; i<is->mag_len ; i++ )
06605 {
06606 mag1[i] = MAX_FASTF;
06607 mag2[i] = MAX_FASTF;
06608 }
06609
06610 bu_ptbl_init( &vert_list1, 64, " &vert_list1");
06611 bu_ptbl_init( &vert_list2, 64, " &vert_list2");
06612
06613 is->s1 = fu1->s_p;
06614 is->s2 = fu2->s_p;
06615 is->fu1 = fu1;
06616 is->fu2 = fu2;
06617 is->l1 = &vert_list1;
06618 is->l2 = &vert_list2;
06619 is->mag1 = mag1;
06620 is->mag2 = mag2;
06621 is->on_eg = (struct edge_g_lseg *)NULL;
06622
06623
06624 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
06625 {
06626 NMG_CK_LOOPUSE( lu );
06627 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06628 continue;
06629
06630 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06631 {
06632 int code;
06633 int class1,class2;
06634 fastf_t dist;
06635 struct vertex_g *vg1,*vg2;
06636 vect_t dir;
06637 point_t hit_pt;
06638 struct vertexuse *hit_vu;
06639 struct vertex *hit_v=(struct vertex *)NULL;
06640 struct edgeuse *new_eu;
06641
06642 NMG_CK_EDGEUSE( eu );
06643
06644 vg1 = eu->vu_p->v_p->vg_p;
06645 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
06646
06647 dist = DIST_PT_PLANE( vg1->coord, pl2 );
06648 if( dist > is->tol.dist )
06649 class1 = NMG_CLASS_AoutB;
06650 else if( dist < (-is->tol.dist ) )
06651 class1 = NMG_CLASS_AinB;
06652 else
06653 class1 = NMG_CLASS_AonBshared;
06654
06655 dist = DIST_PT_PLANE( vg2->coord, pl2 );
06656 if( dist > is->tol.dist )
06657 class2 = NMG_CLASS_AoutB;
06658 else if( dist < (-is->tol.dist ) )
06659 class2 = NMG_CLASS_AinB;
06660 else
06661 class2 = NMG_CLASS_AonBshared;
06662
06663 if( class1 == class2 )
06664 continue;
06665
06666 if( class1 == NMG_CLASS_AonBshared || class2 == NMG_CLASS_AonBshared )
06667 continue;
06668
06669
06670 VSUB2( dir, vg2->coord, vg1->coord )
06671
06672 code = bn_isect_line3_plane( &dist, vg1->coord, dir, pl2, &is->tol );
06673 if( code < 1 )
06674 {
06675 bu_log( "nmg_isect_nearly_coplanar_faces: EU (x%x) goes from %s to %s\n",
06676 eu, nmg_class_name( class1 ), nmg_class_name( class2 ) );
06677 bu_log( "But bn_isect_line3_plane() returns %d\n", code );
06678 bu_log( "pl2 = ( %g %g %g %g )\n", V4ARGS( pl2 ) );
06679 nmg_pr_lu_briefly( lu, "" );
06680 rt_bomb( "nmg_isect_nearly_coplanar_faces: BAD EU" );
06681 }
06682
06683 if( dist <= 0.0 || dist >= 1.0 )
06684 {
06685 bu_log( "nmg_isect_nearly_coplanar_faces: EU (x%x) goes from %s to %s\n",
06686 eu, nmg_class_name( class1 ), nmg_class_name( class2 ) );
06687 bu_log( "But bn_isect_line3_plane() returns %d and dist=%g\n", code, dist );
06688 bu_log( "pl2 = ( %g %g %g %g )\n", V4ARGS( pl2 ) );
06689 nmg_pr_lu_briefly( lu, "" );
06690 rt_bomb( "nmg_isect_nearly_coplanar_faces: BAD EU" );
06691 }
06692
06693 VJOIN1( hit_pt, vg1->coord, dist, dir );
06694
06695 hit_vu = nmg_find_pt_in_face( fu2, hit_pt, &is->tol );
06696 if( !hit_vu )
06697 hit_v = nmg_find_pt_in_model( m, hit_pt, &is->tol );
06698 else
06699 hit_v = hit_vu->v_p;
06700
06701 new_eu = nmg_esplit( hit_v, eu, 1 );
06702 hit_v = new_eu->vu_p->v_p;
06703 if( !hit_v->vg_p )
06704 nmg_vertex_gv( hit_v, hit_pt );
06705
06706 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06707 {
06708 bu_log( "nmg_cut_lu_into_coplanar_and_non:\n" );
06709 bu_log( "\tsplitting eu x%x at v=x%x (%g %g %g)\n",
06710 eu, hit_v, V3ARGS( hit_v->vg_p->coord ) );
06711 }
06712
06713 }
06714 }
06715
06716
06717 bu_ptbl_init( &loops, 64, " &loops");
06718 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
06719 bu_ptbl( &loops, BU_PTBL_INS, (long *)lu );
06720
06721
06722
06723
06724 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ )
06725 {
06726 lu = (struct loopuse *)BU_PTBL_GET( &loops, i );
06727 NMG_CK_LOOPUSE( lu );
06728
06729 nmg_cut_lu_into_coplanar_and_non( lu, pl2, is );
06730 }
06731
06732
06733 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
06734 {
06735 NMG_CK_LOOPUSE( lu );
06736 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06737 continue;
06738
06739 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06740 {
06741 int code;
06742 int class1,class2;
06743 fastf_t dist;
06744 struct vertex_g *vg1,*vg2;
06745 vect_t dir;
06746 point_t hit_pt;
06747 struct vertexuse *hit_vu;
06748 struct vertex *hit_v=(struct vertex *)NULL;
06749 struct edgeuse *new_eu;
06750
06751 NMG_CK_EDGEUSE( eu );
06752
06753 vg1 = eu->vu_p->v_p->vg_p;
06754 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
06755
06756 dist = DIST_PT_PLANE( vg1->coord, pl1 );
06757 if( dist > is->tol.dist )
06758 class1 = NMG_CLASS_AoutB;
06759 else if( dist < (-is->tol.dist ) )
06760 class1 = NMG_CLASS_AinB;
06761 else
06762 class1 = NMG_CLASS_AonBshared;
06763
06764 dist = DIST_PT_PLANE( vg2->coord, pl1 );
06765 if( dist > is->tol.dist )
06766 class2 = NMG_CLASS_AoutB;
06767 else if( dist < (-is->tol.dist ) )
06768 class2 = NMG_CLASS_AinB;
06769 else
06770 class2 = NMG_CLASS_AonBshared;
06771
06772 if( class1 == class2 )
06773 continue;
06774
06775 if( class1 == NMG_CLASS_AonBshared || class2 == NMG_CLASS_AonBshared )
06776 continue;
06777
06778
06779 VSUB2( dir, vg2->coord, vg1->coord )
06780
06781 code = bn_isect_line3_plane( &dist, vg1->coord, dir, pl1, &is->tol );
06782 if( code < 1 )
06783 {
06784 bu_log( "nmg_isect_nearly_coplanar_faces: EU (x%x) goes from %s to %s\n",
06785 eu, nmg_class_name( class1 ), nmg_class_name( class2 ) );
06786 bu_log( "But bn_isect_line3_plane() returns %d\n", code );
06787 bu_log( "pl1 = ( %g %g %g %g )\n", V4ARGS( pl1 ) );
06788 nmg_pr_lu_briefly( lu, "" );
06789 rt_bomb( "nmg_isect_nearly_coplanar_faces: BAD EU" );
06790 }
06791
06792 if( dist <= 0.0 || dist >= 1.0 )
06793 {
06794 bu_log( "nmg_isect_nearly_coplanar_faces: EU (x%x) goes from %s to %s\n",
06795 eu, nmg_class_name( class1 ), nmg_class_name( class2 ) );
06796 bu_log( "But bn_isect_line3_plane() returns %d and dist=%g\n", code, dist );
06797 bu_log( "pl1 = ( %g %g %g %g )\n", V4ARGS( pl1 ) );
06798 nmg_pr_lu_briefly( lu, "" );
06799 rt_bomb( "nmg_isect_nearly_coplanar_faces: BAD EU" );
06800 }
06801 VJOIN1( hit_pt, vg1->coord, dist, dir );
06802
06803 hit_vu = nmg_find_pt_in_face( fu2, hit_pt, &is->tol );
06804 if( !hit_vu )
06805 hit_v = nmg_find_pt_in_model( m, hit_pt, &is->tol );
06806 else
06807 hit_v = hit_vu->v_p;
06808
06809 new_eu = nmg_esplit( hit_v, eu, 1 );
06810 hit_v = new_eu->vu_p->v_p;
06811 if( !hit_v->vg_p )
06812 nmg_vertex_gv( hit_v, hit_pt );
06813 }
06814 }
06815
06816
06817 bu_ptbl_reset( &loops);
06818 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
06819 bu_ptbl( &loops, BU_PTBL_INS, (long *)lu );
06820
06821
06822
06823
06824 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ )
06825 {
06826 lu = (struct loopuse *)BU_PTBL_GET( &loops, i );
06827 NMG_CK_LOOPUSE( lu );
06828
06829 nmg_cut_lu_into_coplanar_and_non( lu, pl1, is );
06830 }
06831
06832
06833 nmg_vertex_tabulate( &verts, &m->magic );
06834
06835 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
06836 {
06837 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06838 continue;
06839
06840 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06841 {
06842 if( bu_ptbl_locate( &eu1_list, (long *)eu ) != (-1) )
06843 continue;
06844
06845
06846 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
06847 {
06848 struct vertex *v;
06849 int code;
06850 fastf_t dist[2];
06851 point_t pca;
06852
06853 v = (struct vertex *)BU_PTBL_GET( &verts , i );
06854
06855 if( v == eu->vu_p->v_p )
06856 continue;
06857
06858 if( v == eu->eumate_p->vu_p->v_p )
06859 continue;
06860
06861 code = bn_dist_pt3_lseg3( dist, pca, eu->vu_p->v_p->vg_p->coord,
06862 eu->eumate_p->vu_p->v_p->vg_p->coord, v->vg_p->coord, &is->tol );
06863
06864 if( code > 2 )
06865 continue;
06866
06867 if( code == 1 )
06868 bu_log( "nmg_isect_nearly_coplanar_faces: vertices should have been fused x%x and x%x\n", v, eu->vu_p->v_p );
06869 else if( code == 2 )
06870 bu_log( "nmg_isect_nearly_coplanar_faces: vertices should have been fused x%x and x%x\n", v, eu->eumate_p->vu_p->v_p );
06871 else
06872 {
06873
06874 (void)nmg_esplit( v, eu, 1 );
06875 }
06876 }
06877 }
06878 }
06879
06880
06881 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
06882 {
06883 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06884 continue;
06885
06886 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06887 {
06888 if( bu_ptbl_locate( &eu1_list, (long *)eu ) != (-1) )
06889 continue;
06890
06891
06892 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
06893 {
06894 struct vertex *v;
06895 int code;
06896 fastf_t dist[2];
06897 point_t pca;
06898
06899 v = (struct vertex *)BU_PTBL_GET( &verts , i );
06900
06901 if( v == eu->vu_p->v_p )
06902 continue;
06903
06904 if( v == eu->eumate_p->vu_p->v_p )
06905 continue;
06906
06907 code = bn_dist_pt3_lseg3( dist, pca, eu->vu_p->v_p->vg_p->coord,
06908 eu->eumate_p->vu_p->v_p->vg_p->coord, v->vg_p->coord, &is->tol );
06909
06910 if( code > 2 )
06911 continue;
06912
06913 if( code == 1 )
06914 bu_log( "nmg_isect_nearly_coplanar_faces: vertices should have been fused x%x and x%x\n", v, eu->vu_p->v_p );
06915 else if( code == 2 )
06916 bu_log( "nmg_isect_nearly_coplanar_faces: vertices should have been fused x%x and x%x\n", v, eu->eumate_p->vu_p->v_p );
06917 else
06918 {
06919
06920 (void)nmg_esplit( v, eu, 1 );
06921 }
06922 }
06923 }
06924 }
06925
06926 bu_ptbl_free( &loops);
06927 bu_ptbl_free( &verts);
06928
06929 if (rt_g.NMG_debug & DEBUG_POLYSECT)
06930 {
06931 plane_t pl1,pl2;
06932 fastf_t dist;
06933
06934 bu_log( "After splitting loops into coplanar and non:\n" );
06935 nmg_pr_fu_briefly( fu1, "" );
06936 nmg_pr_fu_briefly( fu2, "" );
06937
06938 NMG_GET_FU_PLANE( pl1, fu1 );
06939 NMG_GET_FU_PLANE( pl2, fu2 );
06940
06941 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
06942 {
06943 int in=0,on=0,out=0;
06944
06945 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06946 {
06947 struct vertex_g *vg;
06948
06949 vg = eu->vu_p->v_p->vg_p;
06950
06951 dist = DIST_PT_PLANE( vg->coord, pl2 );
06952
06953 if( dist > is->tol.dist )
06954 out++;
06955 else if( dist < (-is->tol.dist ))
06956 in++;
06957 else
06958 on++;
06959 }
06960
06961 if( in && out )
06962 bu_log( "lu x%x is in and out of fu x%x\n", lu, fu2 );
06963 else if( in )
06964 bu_log( "lu x%x is inside of fu x%x\n", lu, fu2 );
06965 else if( out )
06966 bu_log( "lu x%x is outside of fu x%x\n", lu, fu2 );
06967 else if( on )
06968 bu_log( "lu x%x is on of fu x%x\n", lu, fu2 );
06969 else
06970 bu_log( "Can't figure lu x%x w.r.t fu x%x, on=%d, in=%d, out=%d\n",
06971 lu, fu2, on,in,out);
06972 }
06973
06974 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
06975 {
06976 int in=0,on=0,out=0;
06977
06978 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
06979 {
06980 struct vertex_g *vg;
06981
06982 vg = eu->vu_p->v_p->vg_p;
06983
06984 dist = DIST_PT_PLANE( vg->coord, pl1 );
06985
06986 if( dist > is->tol.dist )
06987 out++;
06988 else if( dist < (-is->tol.dist ))
06989 in++;
06990 else
06991 on++;
06992 }
06993
06994 if( in && out )
06995 bu_log( "lu x%x is in and out of fu x%x\n", lu, fu1 );
06996 else if( in )
06997 bu_log( "lu x%x is inside of fu x%x\n", lu, fu1 );
06998 else if( out )
06999 bu_log( "lu x%x is outside of fu x%x\n", lu, fu1 );
07000 else if( on )
07001 bu_log( "lu x%x is on of fu x%x\n", lu, fu1 );
07002 else
07003 bu_log( "Can't figure lu x%x w.r.t fu x%x, on=%d, in=%d, out=%d\n",
07004 lu, fu1, on,in,out);
07005 }
07006 }
07007
07008
07009 bu_ptbl_reset( &eu1_list);
07010 bu_ptbl_reset( &eu2_list);
07011 nmg_edgeuse_tabulate( &eu1_list, &fu1->l.magic );
07012 nmg_edgeuse_tabulate( &eu2_list, &fu2->l.magic );
07013 nmg_isect_coplanar_edges( is, &eu1_list, &eu2_list );
07014
07015 if( mag1 )
07016 bu_free( (char *)mag1, "mag1" );
07017 if( mag2 )
07018 bu_free( (char *)mag2, "mag2" );
07019
07020 bu_ptbl_free( is->l1);
07021 bu_ptbl_free( is->l2);
07022
07023 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07024 {
07025 plane_t pl1,pl2;
07026 fastf_t dist;
07027
07028 bu_log( "After intersection nearly coplanar faces:\n" );
07029 nmg_pr_fu_briefly( fu1, "" );
07030 nmg_pr_fu_briefly( fu2, "" );
07031
07032 NMG_GET_FU_PLANE( pl1, fu1 );
07033 NMG_GET_FU_PLANE( pl2, fu2 );
07034
07035 for( BU_LIST_FOR( lu, loopuse, &fu1->lu_hd ) )
07036 {
07037 int in=0,on=0,out=0;
07038
07039 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
07040 {
07041 struct vertex_g *vg;
07042
07043 vg = eu->vu_p->v_p->vg_p;
07044
07045 dist = DIST_PT_PLANE( vg->coord, pl2 );
07046
07047 if( dist > is->tol.dist )
07048 out++;
07049 else if( dist < (-is->tol.dist ))
07050 in++;
07051 else
07052 on++;
07053 }
07054
07055 if( in && out )
07056 bu_log( "lu x%x is in and out of fu x%x\n", lu, fu2 );
07057 else if( in )
07058 bu_log( "lu x%x is inside of fu x%x\n", lu, fu2 );
07059 else if( out )
07060 bu_log( "lu x%x is outside of fu x%x\n", lu, fu2 );
07061 else if( on )
07062 bu_log( "lu x%x is on of fu x%x\n", lu, fu2 );
07063 else
07064 bu_log( "Can't figure lu x%x w.r.t fu x%x, on=%d, in=%d, out=%d\n",
07065 lu, fu2, on,in,out);
07066 }
07067
07068 for( BU_LIST_FOR( lu, loopuse, &fu2->lu_hd ) )
07069 {
07070 int in=0,on=0,out=0;
07071
07072 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
07073 {
07074 struct vertex_g *vg;
07075
07076 vg = eu->vu_p->v_p->vg_p;
07077
07078 dist = DIST_PT_PLANE( vg->coord, pl1 );
07079
07080 if( dist > is->tol.dist )
07081 out++;
07082 else if( dist < (-is->tol.dist ))
07083 in++;
07084 else
07085 on++;
07086 }
07087
07088 if( in && out )
07089 bu_log( "lu x%x is in and out of fu x%x\n", lu, fu1 );
07090 else if( in )
07091 bu_log( "lu x%x is inside of fu x%x\n", lu, fu1 );
07092 else if( out )
07093 bu_log( "lu x%x is outside of fu x%x\n", lu, fu1 );
07094 else if( on )
07095 bu_log( "lu x%x is on of fu x%x\n", lu, fu1 );
07096 else
07097 bu_log( "Can't figure lu x%x w.r.t fu x%x, on=%d, in=%d, out=%d\n",
07098 lu, fu1, on,in,out);
07099 }
07100 }
07101
07102 }
07103
07104
07105
07106
07107
07108
07109
07110
07111
07112
07113
07114
07115 int
07116 nmg_faces_can_be_intersected(struct nmg_inter_struct *bs, const struct faceuse *fu1, const struct faceuse *fu2, const struct bn_tol *tol)
07117 {
07118 plane_t pl1,pl2;
07119 point_t min_pt;
07120 struct face *f1,*f2;
07121 double dir_len_sq;
07122 double one_over_dir_len;
07123 plane_t tmp_pl;
07124 vect_t left;
07125 struct bu_ptbl verts;
07126 int on_line, above_left, below_left, on_left, above_right, below_right, on_right;
07127 int i;
07128
07129 NMG_CK_FACEUSE( fu1 );
07130 NMG_CK_FACEUSE( fu2 );
07131 BN_CK_TOL( tol );
07132
07133 NMG_GET_FU_PLANE( pl1, fu1 );
07134 NMG_GET_FU_PLANE( pl2, fu2 );
07135
07136 f1 = fu1->f_p;
07137 f2 = fu2->f_p;
07138
07139 NMG_CK_FACE( f1 );
07140 NMG_CK_FACE( f2 );
07141
07142 VMOVE(min_pt, f1->min_pt);
07143 VMIN(min_pt, f2->min_pt);
07144
07145 VCROSS( bs->dir, pl1, pl2 );
07146 dir_len_sq = MAGSQ( bs->dir );
07147 if( dir_len_sq <= SMALL_FASTF )
07148 return( 0 );
07149
07150 one_over_dir_len = 1.0/sqrt( dir_len_sq );
07151 VSCALE( bs->dir, bs->dir, one_over_dir_len );
07152 VMOVE( tmp_pl, bs->dir );
07153 tmp_pl[3] = VDOT( tmp_pl, min_pt );
07154
07155 if( bn_mkpoint_3planes( bs->pt, tmp_pl, pl1, pl2 ) )
07156 return( 0 );
07157
07158 VCROSS( left, pl1, bs->dir );
07159
07160
07161 nmg_vertex_tabulate( &verts, &fu1->l.magic );
07162 on_line = 0;
07163 above_left = 0;
07164 below_left = 0;
07165 on_left = 0;
07166 above_right = 0;
07167 below_right = 0;
07168 on_right = 0;
07169 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
07170 {
07171 struct vertex *v;
07172 point_t pca;
07173 fastf_t dist;
07174 int code;
07175 vect_t to_v;
07176
07177 v = (struct vertex *)BU_PTBL_GET( &verts, i );
07178
07179 code = rt_dist_pt3_line3( &dist, pca, bs->pt, bs->dir, v->vg_p->coord, tol );
07180
07181 if( code == 0 || code == 1 )
07182 {
07183 on_line++;
07184 continue;
07185 }
07186
07187 VSUB2( to_v, v->vg_p->coord, pca );
07188 dist = DIST_PT_PLANE( v->vg_p->coord, pl2 );
07189 if( VDOT( to_v, left ) > 0.0 )
07190 {
07191
07192 if( dist > tol->dist )
07193 above_left++;
07194 else if( dist < (-tol->dist) )
07195 below_left++;
07196 else
07197 on_left++;
07198 }
07199 else
07200 {
07201
07202 if( dist > tol->dist )
07203 above_right++;
07204 else if( dist < (-tol->dist) )
07205 below_right++;
07206 else
07207 on_right++;
07208 }
07209 }
07210 bu_ptbl_free( &verts);
07211
07212 if( above_left && below_left )
07213 return( 0 );
07214 if( on_left )
07215 return( 0 );
07216 if( above_right && below_right )
07217 return( 0 );
07218 if( on_right )
07219 return( 0 );
07220
07221
07222 nmg_vertex_tabulate( &verts, &fu2->l.magic );
07223 on_line = 0;
07224 above_left = 0;
07225 below_left = 0;
07226 on_left = 0;
07227 above_right = 0;
07228 below_right = 0;
07229 on_right = 0;
07230 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
07231 {
07232 struct vertex *v;
07233 point_t pca;
07234 fastf_t dist;
07235 int code;
07236 vect_t to_v;
07237
07238 v = (struct vertex *)BU_PTBL_GET( &verts, i );
07239
07240 code = rt_dist_pt3_line3( &dist, pca, bs->pt, bs->dir, v->vg_p->coord, tol );
07241
07242 if( code == 0 || code == 1 )
07243 {
07244 on_line++;
07245 continue;
07246 }
07247
07248 VSUB2( to_v, v->vg_p->coord, pca );
07249 dist = DIST_PT_PLANE( v->vg_p->coord, pl1 );
07250 if( VDOT( to_v, left ) > 0.0 )
07251 {
07252
07253 if( dist > tol->dist )
07254 above_left++;
07255 else if( dist < (-tol->dist) )
07256 below_left++;
07257 else
07258 on_left++;
07259 }
07260 else
07261 {
07262
07263 if( dist > tol->dist )
07264 above_right++;
07265 else if( dist < (-tol->dist) )
07266 below_right++;
07267 else
07268 on_right++;
07269 }
07270 }
07271 bu_ptbl_free( &verts);
07272
07273 if( above_left && below_left )
07274 return( 0 );
07275 if( on_left )
07276 return( 0 );
07277 if( above_right && below_right )
07278 return( 0 );
07279 if( on_right )
07280 return( 0 );
07281
07282 return( 1 );
07283 }
07284
07285
07286
07287
07288
07289
07290 void
07291 nmg_isect_two_generic_faces(struct faceuse *fu1, struct faceuse *fu2, const struct bn_tol *tol)
07292 {
07293 struct nmg_inter_struct bs;
07294 plane_t pl1, pl2;
07295 struct face *f1;
07296 struct face *f2;
07297 point_t min_pt;
07298 int status;
07299 int i;
07300
07301 BN_CK_TOL(tol);
07302 bs.magic = NMG_INTER_STRUCT_MAGIC;
07303 bs.vert2d = (fastf_t *)NULL;
07304 bs.tol = *tol;
07305
07306 NMG_CK_FACEUSE(fu1);
07307 f1 = fu1->f_p;
07308 NMG_CK_FACE(f1);
07309 NMG_CK_FACE_G_PLANE(f1->g.plane_p);
07310
07311 NMG_CK_FACEUSE(fu2);
07312 f2 = fu2->f_p;
07313 NMG_CK_FACE(f2);
07314 NMG_CK_FACE_G_PLANE(f2->g.plane_p);
07315
07316 NMG_GET_FU_PLANE( pl1, fu1 );
07317 NMG_GET_FU_PLANE( pl2, fu2 );
07318
07319 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07320 bu_log("\nnmg_isect_two_generic_faces(fu1=x%x, fu2=x%x)\n", fu1, fu2);
07321
07322 bu_log("Planes\t%gx + %gy + %gz = %g\n\t%gx + %gy + %gz = %g\n",
07323 pl1[0], pl1[1], pl1[2], pl1[3],
07324 pl2[0], pl2[1], pl2[2], pl2[3]);
07325 bu_log( "Cosine of angle between planes = %g\n" , VDOT( pl1 , pl2 ) );
07326 bu_log( "fu1:\n" );
07327 nmg_pr_fu_briefly( fu1 , "\t" );
07328 bu_log( "fu2:\n" );
07329 nmg_pr_fu_briefly( fu2 , "\t" );
07330 nmg_fu_touchingloops(fu1);
07331 nmg_fu_touchingloops(fu2);
07332 }
07333
07334 status = 10;
07335 if( f1->g.plane_p == f2->g.plane_p ) {
07336 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07337 bu_log("co-planar faces (shared fg)\n");
07338 }
07339 status = (-1);
07340 }
07341
07342 if ( !V3RPP_OVERLAP_TOL(f2->min_pt, f2->max_pt,
07343 f1->min_pt, f1->max_pt, &bs.tol) ) return;
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364 VMOVE(min_pt, f1->min_pt);
07365 VMIN(min_pt, f2->min_pt);
07366 if( status == 10 )
07367 {
07368 status = bn_isect_2planes( bs.pt, bs.dir, pl1, pl2,
07369 min_pt, tol );
07370
07371 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07372 bu_log( "\tnmg_isect_two_generic_faces: intersect ray start (%f , %f , %f )\n\t\tin direction (%f , %f , %f )\n",
07373 bs.pt[X],
07374 bs.pt[Y],
07375 bs.pt[Z],
07376 bs.dir[X],
07377 bs.dir[Y],
07378 bs.dir[Z] );
07379 }
07380 }
07381
07382 switch( status ) {
07383 case 0:
07384 if( fu1->f_p->g.plane_p == fu2->f_p->g.plane_p ) {
07385 rt_bomb("nmg_isect_two_generic_faces: co-planar faces not detected\n");
07386 }
07387
07388 bs.coplanar = 0;
07389 nmg_isect_two_face3p( &bs, fu1, fu2 );
07390 break;
07391 case -1:
07392 case -2:
07393
07394 {
07395 int coplanar1=0;
07396 int coplanar2=0;
07397 int coplanar=0;
07398 int parallel=0;
07399 fastf_t max_dist1;
07400 fastf_t min_dist1;
07401 fastf_t max_dist2;
07402 fastf_t min_dist2;
07403 fastf_t dist;
07404 struct bu_ptbl verts;
07405
07406 if( f1->g.plane_p == f2->g.plane_p )
07407 goto cplanar;
07408
07409
07410
07411 min_dist1 = MAX_FASTF;
07412 max_dist1 = (-MAX_FASTF);
07413 min_dist2 = MAX_FASTF;
07414 max_dist2 = (-MAX_FASTF);
07415 nmg_vertex_tabulate( &verts, &fu1->l.magic );
07416 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
07417 {
07418 struct vertex *v;
07419
07420 v = (struct vertex *)BU_PTBL_GET( &verts, i );
07421 dist = DIST_PT_PLANE( v->vg_p->coord, pl2 );
07422 if( dist > max_dist1 )
07423 max_dist1 = dist;
07424 if( dist < min_dist1 )
07425 min_dist1 = dist;
07426 }
07427 bu_ptbl_free( &verts);
07428
07429 if( min_dist1 > tol->dist )
07430 {
07431 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07432 {
07433 bu_log( "nmg_isect_two_generic_faces: bn_isect_2planes() says faces are coplanar.\n" );
07434 bu_log( "\tbut all vertices of fu1 (x%x) are at least %gmm above plane of fu2 (x%x)\n",
07435 fu1, min_dist1, fu2 );
07436 }
07437 parallel = 1;
07438 }
07439 else if( max_dist1 < (-tol->dist ) )
07440 {
07441 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07442 {
07443 bu_log( "nmg_isect_two_generic_faces: bn_isect_2planes() says faces are coplanar.\n" );
07444 bu_log( "\tbut all vertices of fu1 (x%x) are at least %gmm below plane of fu2 (x%x)\n",
07445 fu1, -max_dist1, fu2 );
07446 }
07447 parallel = 1;
07448 }
07449 else if( max_dist1 <= tol->dist && min_dist1 >= (-tol->dist) )
07450 {
07451 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07452 bu_log( "nmg_isect_two_generic_faces: coplanar faces don't share face geometry, intersecting anyway\n" );
07453 coplanar1 = 1;
07454 }
07455
07456 if( !parallel )
07457 {
07458
07459 nmg_vertex_tabulate( &verts, &fu2->l.magic );
07460 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
07461 {
07462 struct vertex *v;
07463
07464 v = (struct vertex *)BU_PTBL_GET( &verts, i );
07465 dist = DIST_PT_PLANE( v->vg_p->coord, pl1 );
07466 if( dist > max_dist2 )
07467 max_dist2 = dist;
07468 if( dist < min_dist2 )
07469 min_dist2 = dist;
07470 }
07471 bu_ptbl_free( &verts);
07472
07473 if( min_dist2 > tol->dist )
07474 {
07475 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07476 {
07477 bu_log( "nmg_isect_two_generic_faces: bn_isect_2planes() says faces are coplanar.\n" );
07478 bu_log( "\tbut all vertices of fu2 (x%x) are at least %gmm above plane of fu1 (x%x)\n",
07479 fu2, min_dist2, fu1 );
07480 }
07481 parallel = 1;
07482 }
07483 else if( max_dist2 < (-tol->dist ) )
07484 {
07485 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07486 {
07487 bu_log( "nmg_isect_two_generic_faces: bn_isect_2planes() says faces are coplanar.\n" );
07488 bu_log( "\tbut all vertices of fu2 (x%x) are at least %gmm below plane of fu1 (x%x)\n",
07489 fu2, -max_dist2, fu1 );
07490 }
07491 parallel = 1;
07492 }
07493 else if( max_dist2 <= tol->dist && min_dist2 >= (-tol->dist) )
07494 {
07495 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07496 bu_log( "nmg_isect_two_generic_faces: coplanar faces don't share face geometry, intersecting anyway\n" );
07497 coplanar2 = 1;
07498 }
07499 }
07500
07501 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07502 {
07503 bu_log( "nmg_isect_two_generic_faces: FUs x%x and x%x do not share face geometry\n", fu1, fu2 );
07504 bu_log( "\tbut bn_isect_2planes() says they are coplanar or parallel\n" );
07505 bu_log( "max_dist1 = %g, min_dist1 = %g\n", max_dist1, min_dist1 );
07506 bu_log( "max_dist2 = %g, min_dist2 = %g\n", max_dist2, min_dist2 );
07507 }
07508
07509 if( coplanar1 && coplanar2 )
07510 coplanar = 1;
07511
07512 if( coplanar )
07513 {
07514 cplanar:
07515 bs.coplanar = 1;
07516 nmg_isect_two_face2p_jra( &bs, fu1, fu2 );
07517 break;
07518 }
07519 else if( parallel )
07520 break;
07521 else
07522 {
07523 if( nmg_faces_can_be_intersected( &bs, fu1, fu2, tol ) )
07524 {
07525 bs.coplanar = 0;
07526 nmg_isect_two_face3p( &bs, fu1, fu2 );
07527 }
07528 else
07529 nmg_isect_nearly_coplanar_faces( &bs, fu1, fu2 );
07530 }
07531 }
07532 break;
07533 default:
07534
07535 bu_log("ERROR nmg_isect_two_generic_faces() unable to find plane intersection\n");
07536 break;
07537 }
07538
07539 nmg_isect2d_cleanup( &bs );
07540 #if 0
07541
07542
07543 nmg_sanitize_fu( fu1 );
07544 nmg_sanitize_fu( fu2 );
07545 #endif
07546
07547 (void)nmg_unbreak_region_edges( &fu1->l.magic );
07548 (void)nmg_unbreak_region_edges( &fu2->l.magic );
07549
07550 if ( fu1 && rt_g.NMG_debug & (DEBUG_POLYSECT|DEBUG_FCUT|DEBUG_MESH)
07551 && rt_g.NMG_debug & DEBUG_PLOTEM) {
07552 static int nshell = 1;
07553 char name[32];
07554 FILE *fp;
07555
07556
07557
07558 nmg_pl_2fu( "Iface%d.pl", 0, fu2, fu1, 0 );
07559
07560
07561 nmg_face_plot( fu1 );
07562 nmg_face_plot( fu2 );
07563
07564 sprintf(name, "shellA%d.pl", nshell);
07565 if( (fp = fopen(name, "w")) != NULL ) {
07566 bu_log("overlay %s\n", name);
07567 nmg_pl_s( fp, fu1->s_p );
07568 fclose(fp);
07569 }
07570
07571 sprintf(name, "shellB%d.pl", nshell++);
07572 if( (fp = fopen(name, "w")) != NULL ) {
07573 bu_log("overlay %s\n", name);
07574 nmg_pl_s( fp, fu2->s_p );
07575 fclose(fp);
07576 }
07577
07578 #if 0
07579
07580 sprintf(name, "model%d.g", nshell);
07581 nmg_stash_model_to_file( name, m, "After 2d isect" );
07582 nshell++;
07583 #endif
07584 }
07585
07586 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
07587 nmg_region_v_unique( fu1->s_p->r_p, &bs.tol );
07588 nmg_region_v_unique( fu2->s_p->r_p, &bs.tol );
07589 nmg_fu_touchingloops(fu1);
07590 nmg_fu_touchingloops(fu2);
07591 nmg_ck_face_worthless_edges( fu1 );
07592 nmg_ck_face_worthless_edges( fu2 );
07593 }
07594 }
07595
07596
07597
07598
07599
07600
07601
07602
07603
07604
07605
07606 static void
07607 nmg_isect_edge3p_edge3p(struct nmg_inter_struct *is, struct edgeuse *eu1, struct edgeuse *eu2)
07608 {
07609 struct vertexuse *vu1a;
07610 struct vertexuse *vu1b;
07611 struct vertexuse *vu2a;
07612 struct vertexuse *vu2b;
07613 vect_t eu1_dir;
07614 vect_t eu2_dir;
07615 fastf_t dist[2];
07616 int status;
07617 struct vertex *new_v;
07618 point_t hit_pt;
07619
07620 NMG_CK_INTER_STRUCT(is);
07621 NMG_CK_EDGEUSE(eu1);
07622 NMG_CK_EDGEUSE(eu2);
07623
07624 vu1a = eu1->vu_p;
07625 vu1b = BU_LIST_PNEXT_CIRC( edgeuse, eu1 )->vu_p;
07626 vu2a = eu2->vu_p;
07627 vu2b = BU_LIST_PNEXT_CIRC( edgeuse, eu2 )->vu_p;
07628 NMG_CK_VERTEXUSE(vu1a);
07629 NMG_CK_VERTEXUSE(vu1b);
07630 NMG_CK_VERTEXUSE(vu2a);
07631 NMG_CK_VERTEXUSE(vu2b);
07632
07633 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07634 bu_log("nmg_isect_edge3p_edge3p(eu1=x%x, eu2=x%x)\n\tvu1a=%x vu1b=%x, vu2a=%x vu2b=%x\n\tv1a=%x v1b=%x, v2a=%x v2b=%x\n",
07635 eu1, eu2,
07636 vu1a, vu1b, vu2a, vu2b,
07637 vu1a->v_p, vu1b->v_p, vu2a->v_p, vu2b->v_p );
07638
07639
07640
07641
07642
07643 if( (vu1a->v_p == vu2a->v_p && vu1b->v_p == vu2b->v_p) ||
07644 (vu1a->v_p == vu2b->v_p && vu1b->v_p == vu2a->v_p) ) {
07645 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07646 bu_log("nmg_isect_edge3p_edge3p: shared edge topology, both ends\n");
07647 if( eu1->e_p != eu2->e_p )
07648 nmg_radial_join_eu(eu1, eu2, &is->tol );
07649 return;
07650 }
07651 VSUB2( eu1_dir, vu1b->v_p->vg_p->coord, vu1a->v_p->vg_p->coord );
07652 VSUB2( eu2_dir, vu2b->v_p->vg_p->coord, vu2a->v_p->vg_p->coord );
07653
07654 dist[0] = dist[1] = 0;
07655
07656 status = bn_isect_lseg3_lseg3( dist,
07657 vu1a->v_p->vg_p->coord, eu1_dir,
07658 vu2a->v_p->vg_p->coord, eu2_dir, &is->tol );
07659
07660 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07661 bu_log("\trt_isect_line3_lseg3()=%d, dist: %g, %g\n",
07662 status, dist[0], dist[1] );
07663 }
07664
07665 if( status < 0 ) {
07666
07667 return;
07668 }
07669
07670 if( status == 0 ) {
07671
07672 bu_log("nmg_isect_edge3p_edge3p() colinear case. Untested waters.\n");
07673
07674 nmg_isect2d_prep( is, &eu1->l.magic );
07675
07676
07677 (void)nmg_isect_2colinear_edge2p( eu1, eu2, (struct faceuse *)NULL, is, (struct bu_ptbl *)0, (struct bu_ptbl *)0 );
07678 return;
07679 }
07680
07681
07682
07683
07684
07685
07686
07687 if( dist[0] == 0 ) {
07688
07689 if( dist[1] == 0 ) {
07690
07691 nmg_jv( vu1a->v_p, vu2a->v_p );
07692 return;
07693 } else if( dist[1] == 1 ) {
07694
07695 nmg_jv( vu1a->v_p, vu2b->v_p );
07696 return;
07697 }
07698
07699 nmg_ebreaker( vu1a->v_p, eu2, &is->tol );
07700 return;
07701 } else if( dist[0] == 1 ) {
07702
07703 if( dist[1] == 0 ) {
07704
07705 nmg_jv( vu1b->v_p, vu2a->v_p );
07706 return;
07707 } else if( dist[1] == 1 ) {
07708
07709 nmg_jv( vu1b->v_p, vu2b->v_p );
07710 return;
07711 }
07712
07713 nmg_ebreaker( vu1b->v_p, eu2, &is->tol );
07714 return;
07715 } else {
07716
07717 if( dist[1] < 0 || dist[1] > 1 ) return;
07718
07719 if( dist[1] == 0 ) {
07720
07721 nmg_ebreaker( vu2a->v_p, eu1, &is->tol );
07722 return;
07723 } else if( dist[1] == 1 ) {
07724
07725 nmg_ebreaker( vu2b->v_p, eu1, &is->tol );
07726 return;
07727 }
07728
07729 new_v = nmg_e2break( eu1, eu2 );
07730
07731 VJOIN1( hit_pt, vu2a->v_p->vg_p->coord, dist[1], eu2_dir );
07732 nmg_vertex_gv(new_v, hit_pt);
07733 }
07734 }
07735
07736
07737
07738
07739
07740
07741 static void
07742 nmg_isect_vertex3_edge3p(struct nmg_inter_struct *is, struct vertexuse *vu1, struct edgeuse *eu2)
07743 {
07744 fastf_t dist;
07745 int code;
07746 struct vertexuse *vu2 = (struct vertexuse *)NULL;
07747
07748 NMG_CK_INTER_STRUCT(is);
07749 NMG_CK_VERTEXUSE(vu1);
07750 NMG_CK_EDGEUSE(eu2);
07751
07752 code = bn_isect_pt_lseg( &dist, eu2->vu_p->v_p->vg_p->coord,
07753 eu2->vu_p->v_p->vg_p->coord,
07754 vu1->v_p->vg_p->coord, &is->tol );
07755
07756 if( code < 0 ) return;
07757 switch( code ) {
07758 case 1:
07759
07760 vu2 = eu2->vu_p;
07761 break;
07762 case 2:
07763
07764 vu2 = BU_LIST_NEXT( edgeuse, &eu2->l)->vu_p;
07765 break;
07766 case 3:
07767
07768 vu2 = nmg_ebreaker( vu1->v_p, eu2, &is->tol )->vu_p;
07769 break;
07770 default:
07771 rt_bomb("nmg_isect_vertex3_edge3p()\n");
07772 }
07773
07774 nmg_jv( vu1->v_p, vu2->v_p );
07775 (void)bu_ptbl_ins_unique(is->l1, &vu1->l.magic);
07776 (void)bu_ptbl_ins_unique(is->l2, &vu2->l.magic);
07777 }
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795
07796
07797
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808
07809 static void
07810 nmg_isect_edge3p_shell(struct nmg_inter_struct *is, struct edgeuse *eu1, struct shell *s2)
07811 {
07812 struct faceuse *fu2;
07813 struct loopuse *lu2;
07814 struct edgeuse *eu2;
07815 struct vertexuse *vu2;
07816 point_t midpt;
07817
07818 NMG_CK_INTER_STRUCT(is);
07819 NMG_CK_EDGEUSE(eu1);
07820 NMG_CK_SHELL(s2);
07821
07822 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07823 bu_log("nmg_isect_edge3p_shell(, eu1=x%x, s2=x%x) START\n",
07824 eu1, s2 );
07825 }
07826
07827 if ( (eu2 = nmg_find_matching_eu_in_s( eu1, s2 )) ) {
07828
07829 nmg_radial_join_eu( eu1, eu2, &is->tol );
07830 return;
07831 }
07832
07833
07834 VMOVE( is->pt, eu1->vu_p->v_p->vg_p->coord );
07835 VSUB2( is->dir, eu1->eumate_p->vu_p->v_p->vg_p->coord, is->pt );
07836 VUNITIZE( is->dir );
07837
07838
07839 for( BU_LIST_FOR( fu2, faceuse, &s2->fu_hd ) ) {
07840 NMG_CK_FACEUSE(fu2);
07841 if( fu2->orientation != OT_SAME ) continue;
07842 is->fu2 = fu2;
07843
07844
07845 (void)nmg_isect_wireedge3p_face3p( is, eu1, fu2 );
07846 }
07847
07848
07849 is->fu2 = (struct faceuse *)NULL;
07850 for( BU_LIST_FOR( lu2, loopuse, &s2->lu_hd ) ) {
07851 NMG_CK_LOOPUSE(lu2);
07852
07853 if( BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC) {
07854
07855 vu2 = BU_LIST_FIRST( vertexuse, &lu2->down_hd );
07856 NMG_CK_VERTEXUSE(vu2);
07857 nmg_isect_vertex3_edge3p( is, vu2, eu1 );
07858 continue;
07859 }
07860 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) ) {
07861 NMG_CK_EDGEUSE(eu2);
07862 nmg_isect_edge3p_edge3p( is, eu1, eu2 );
07863 }
07864 }
07865
07866
07867 for( BU_LIST_FOR( eu2, edgeuse, &s2->eu_hd ) ) {
07868 NMG_CK_EDGEUSE(eu2);
07869 nmg_isect_edge3p_edge3p( is, eu1, eu2 );
07870 }
07871
07872
07873 if( s2->vu_p ) {
07874 nmg_isect_vertex3_edge3p( is, s2->vu_p, eu1 );
07875 }
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886 if ((eu2 = nmg_find_matching_eu_in_s( eu1, s2 )) ) {
07887
07888 goto out;
07889 }
07890
07891
07892
07893
07894
07895 VADD2SCALE( midpt, eu1->vu_p->v_p->vg_p->coord,
07896 eu1->eumate_p->vu_p->v_p->vg_p->coord, 0.5 );
07897 if( nmg_class_pt_s( midpt, s2, 0, &is->tol ) == NMG_CLASS_AoutB )
07898 goto out;
07899
07900
07901 lu2 = nmg_mlv( &s2->l.magic, eu1->vu_p->v_p, OT_UNSPEC );
07902 NMG_CK_LOOPUSE(lu2);
07903 {
07904 struct edgeuse *neu1, *neu2;
07905
07906 neu1 = nmg_meonvu( BU_LIST_FIRST( vertexuse, &lu2->down_hd ) );
07907 neu2 = nmg_eusplit( eu1->eumate_p->vu_p->v_p, neu1, 0 );
07908 NMG_CK_EDGEUSE(eu1);
07909
07910 nmg_use_edge_g( neu1, eu1->g.magic_p );
07911 nmg_use_edge_g( neu2, eu1->g.magic_p );
07912 nmg_radial_join_eu( eu1, neu2, &is->tol );
07913 nmg_radial_join_eu( eu1, neu1, &is->tol );
07914 }
07915 nmg_loop_g(lu2->l_p, &is->tol);
07916 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07917 bu_log("nmg_isect_edge3p_shell(, eu1=x%x, s2=x%x) Added wire lu=x%x\n",
07918 eu1, s2, lu2 );
07919 }
07920
07921 out:
07922 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
07923 bu_log("nmg_isect_edge3p_shell(, eu1=x%x, s2=x%x) END\n",
07924 eu1, s2 );
07925 }
07926 return;
07927 }
07928
07929
07930
07931
07932
07933
07934
07935 void
07936 nmg_crackshells(struct shell *s1, struct shell *s2, const struct bn_tol *tol)
07937 {
07938 struct bu_ptbl vert_list1, vert_list2;
07939 struct nmg_inter_struct is;
07940 struct shell_a *sa1, *sa2;
07941 struct face *f1;
07942 struct faceuse *fu1, *fu2;
07943 struct loopuse *lu1;
07944 struct loopuse *lu2;
07945 struct edgeuse *eu1;
07946 struct edgeuse *eu2;
07947 char *flags;
07948 int flag_len;
07949
07950 if (rt_g.NMG_debug & DEBUG_POLYSECT)
07951 bu_log("nmg_crackshells(s1=x%x, s2=x%x)\n", s1, s2);
07952
07953 BN_CK_TOL(tol);
07954 NMG_CK_SHELL(s1);
07955 sa1 = s1->sa_p;
07956 NMG_CK_SHELL_A(sa1);
07957
07958 NMG_CK_SHELL(s2);
07959 sa2 = s2->sa_p;
07960 NMG_CK_SHELL_A(sa2);
07961
07962 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
07963 nmg_ck_vs_in_region( s1->r_p, tol );
07964 nmg_ck_vs_in_region( s2->r_p, tol );
07965 }
07966
07967
07968 is.magic = NMG_INTER_STRUCT_MAGIC;
07969 is.vert2d = (fastf_t *)NULL;
07970 is.tol = *tol;
07971 is.l1 = &vert_list1;
07972 is.l2 = &vert_list2;
07973 is.s1 = s1;
07974 is.s2 = s2;
07975 is.fu1 = (struct faceuse *)NULL;
07976 is.fu2 = (struct faceuse *)NULL;
07977 (void)bu_ptbl_init(&vert_list1, 64, "&vert_list1");
07978 (void)bu_ptbl_init(&vert_list2, 64, "&vert_list2");
07979
07980 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
07981 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
07982 nmg_vshell( &s2->r_p->s_hd, s2->r_p );
07983 }
07984
07985
07986 if ( ! V3RPP_OVERLAP_TOL(sa1->min_pt, sa1->max_pt,
07987 sa2->min_pt, sa2->max_pt, tol) )
07988 return;
07989
07990
07991 flag_len = s1->r_p->m_p->maxindex * 10;
07992 flags = (char *)bu_calloc( flag_len, sizeof(char),
07993 "nmg_crackshells flags[]" );
07994
07995
07996
07997
07998
07999 for( BU_LIST_FOR( fu1, faceuse, &s1->fu_hd ) ) {
08000 if( s1->r_p->m_p->maxindex >= flag_len ) rt_bomb("nmg_crackshells() flag_len overrun\n");
08001 NMG_CK_FACEUSE(fu1);
08002 f1 = fu1->f_p;
08003 NMG_CK_FACE(f1);
08004
08005 if( fu1->orientation != OT_SAME ) continue;
08006 if( NMG_INDEX_IS_SET(flags, f1) ) continue;
08007 NMG_CK_FACE_G_PLANE(f1->g.plane_p);
08008
08009
08010 if( ! V3RPP_OVERLAP_TOL(sa2->min_pt, sa2->max_pt,
08011 f1->min_pt, f1->max_pt, tol) )
08012 continue;
08013
08014 is.fu1 = fu1;
08015
08016
08017
08018
08019
08020 for( BU_LIST_FOR( fu2, faceuse, &s2->fu_hd ) ) {
08021 NMG_CK_FACEUSE(fu2);
08022 NMG_CK_FACE(fu2->f_p);
08023 if( fu2->orientation != OT_SAME ) continue;
08024
08025 is.fu2 = fu2;
08026 nmg_isect_two_generic_faces(fu1, fu2, tol);
08027 }
08028
08029
08030
08031
08032
08033
08034
08035
08036
08037
08038
08039
08040 is.fu2 = (struct faceuse *)NULL;
08041
08042
08043 for( BU_LIST_FOR( lu2, loopuse, &s2->lu_hd ) ) {
08044 NMG_CK_LOOPUSE(lu2);
08045
08046 (void)nmg_isect_wireloop3p_face3p( &is, lu2, fu1 );
08047 }
08048
08049
08050 for( BU_LIST_FOR( eu2, edgeuse, &s2->eu_hd ) ) {
08051 NMG_CK_EDGEUSE(eu2);
08052
08053 nmg_isect_wireedge3p_face3p( &is, eu2, fu1 );
08054 }
08055
08056
08057 if( s2->vu_p ) {
08058 nmg_isect_3vertex_3face( &is, s2->vu_p, fu1 );
08059 }
08060
08061 NMG_INDEX_SET(flags, f1);
08062
08063 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
08064 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
08065 nmg_vshell( &s2->r_p->s_hd, s2->r_p );
08066 }
08067 }
08068
08069
08070 is.fu1 = (struct faceuse *)NULL;
08071 is.fu2 = (struct faceuse *)NULL;
08072 for( BU_LIST_FOR( lu1, loopuse, &s1->lu_hd ) ) {
08073 NMG_CK_LOOPUSE( lu1 );
08074
08075 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) != NMG_EDGEUSE_MAGIC )
08076 continue;
08077
08078 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) ) {
08079 NMG_CK_EDGEUSE(eu1);
08080
08081 nmg_isect_edge3p_shell( &is, eu1, s2 );
08082 }
08083 }
08084
08085
08086 for( BU_LIST_FOR( eu1, edgeuse, &s1->eu_hd ) ) {
08087 NMG_CK_EDGEUSE( eu1 );
08088 nmg_isect_edge3p_shell( &is, eu1, s2 );
08089 }
08090
08091
08092 if( s1->vu_p ) {
08093
08094 for( BU_LIST_FOR( fu2, faceuse, &s2->fu_hd ) ) {
08095 NMG_CK_FACEUSE(fu2);
08096 if( fu2->orientation != OT_SAME ) continue;
08097 nmg_isect_3vertex_3face( &is, s1->vu_p, fu2 );
08098 }
08099
08100 for( BU_LIST_FOR( lu2, loopuse, &s2->lu_hd ) ) {
08101 NMG_CK_LOOPUSE(lu2);
08102
08103
08104 for( BU_LIST_FOR( eu2, edgeuse, &lu2->down_hd ) ) {
08105 NMG_CK_EDGEUSE(eu2);
08106 nmg_isect_vertex3_edge3p( &is, s1->vu_p, eu2 );
08107 }
08108 }
08109
08110 for( BU_LIST_FOR( eu2, edgeuse, &s2->eu_hd ) ) {
08111 NMG_CK_EDGEUSE(eu2);
08112 nmg_isect_vertex3_edge3p( &is, s1->vu_p, eu2 );
08113 }
08114
08115
08116
08117 }
08118 if( s1->r_p->m_p->maxindex >= flag_len ) rt_bomb("nmg_crackshells() flag_len overrun by end\n");
08119
08120
08121 (void)bu_ptbl_free(&vert_list1);
08122 (void)bu_ptbl_free(&vert_list2);
08123
08124 bu_free( (char *)flags, "nmg_crackshells flags[]" );
08125
08126
08127 (void)nmg_unbreak_region_edges( &s1->l.magic );
08128 (void)nmg_unbreak_region_edges( &s2->l.magic );
08129 #if 0
08130
08131
08132 nmg_sanitize_s_lv(s1, OT_BOOLPLACE);
08133 nmg_sanitize_s_lv(s2, OT_BOOLPLACE);
08134 #endif
08135 nmg_isect2d_cleanup(&is);
08136
08137 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
08138 nmg_vshell( &s1->r_p->s_hd, s1->r_p );
08139 nmg_vshell( &s2->r_p->s_hd, s2->r_p );
08140 nmg_ck_vs_in_region( s1->r_p, tol );
08141 nmg_ck_vs_in_region( s2->r_p, tol );
08142 }
08143 }
08144
08145
08146
08147
08148 int
08149 nmg_fu_touchingloops(const struct faceuse *fu)
08150 {
08151 const struct loopuse *lu;
08152 const struct vertexuse *vu;
08153
08154 NMG_CK_FACEUSE(fu);
08155 for (BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
08156 NMG_CK_LOOPUSE(lu);
08157 if ((vu = nmg_loop_touches_self( lu )) ) {
08158 NMG_CK_VERTEXUSE(vu);
08159 #if 0
08160
08161
08162
08163
08164
08165 bu_log("nmg_fu_touchingloops(lu=x%x, vu=x%x, v=x%x)\n",
08166 lu, vu, vu->v_p );
08167 nmg_pr_lu_briefly(lu,0);
08168 rt_bomb("nmg_fu_touchingloops()\n");
08169 #else
08170
08171 #endif
08172 return 1;
08173 }
08174 }
08175 return 0;
08176 }
08177
08178
08179
08180
08181
08182
08183
08184
08185
08186