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 #ifndef lint
00053 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_class.c,v 14.13 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00054 #endif
00055
00056 #include "common.h"
00057
00058
00059 #include <stdio.h>
00060 #include <math.h>
00061 #include "machine.h"
00062 #include "vmath.h"
00063 #include "nmg.h"
00064 #include "raytrace.h"
00065 #include "./debug.h"
00066 #include "plot3.h"
00067
00068 extern int nmg_class_nothing_broken;
00069
00070
00071 #define INSIDE 32
00072 #define ON_SURF 64
00073 #define OUTSIDE 128
00074
00075
00076
00077
00078 struct neighbor {
00079 union {
00080 const struct vertexuse *vu;
00081 const struct edgeuse *eu;
00082 } p;
00083
00084 fastf_t dist;
00085 int class;
00086 };
00087
00088 static void joint_hitmiss2 BU_ARGS( (struct neighbor *closest,
00089 const struct edgeuse *eu, const point_t pt,
00090 int code) );
00091 static void nmg_class_pt_e BU_ARGS( (struct neighbor *closest,
00092 const point_t pt, const struct edgeuse *eu,
00093 const struct bn_tol *tol) );
00094 static void nmg_class_pt_l BU_ARGS( (struct neighbor *closest,
00095 const point_t pt, const struct loopuse *lu,
00096 const struct bn_tol *tol) );
00097 static int class_vu_vs_s BU_ARGS( (struct vertexuse *vu, struct shell *sB,
00098 long *classlist[4], const struct bn_tol *tol) );
00099 static int class_eu_vs_s BU_ARGS( (struct edgeuse *eu, struct shell *s,
00100 long *classlist[4], const struct bn_tol *tol) );
00101 static int class_lu_vs_s BU_ARGS( (struct loopuse *lu, struct shell *s,
00102 long *classlist[4], const struct bn_tol *tol) );
00103 static void class_fu_vs_s BU_ARGS( (struct faceuse *fu, struct shell *s,
00104 long *classlist[4], const struct bn_tol *tol) );
00105
00106
00107
00108
00109
00110
00111 const char *
00112 nmg_class_status(int status)
00113 {
00114 switch(status) {
00115 case INSIDE:
00116 return "INSIDE";
00117 case OUTSIDE:
00118 return "OUTSIDE";
00119 case ON_SURF:
00120 return "ON_SURF";
00121 }
00122 return "BOGUS_CLASS_STATUS";
00123 }
00124
00125
00126
00127
00128 void
00129 nmg_pr_class_status(char *prefix, int status)
00130 {
00131 bu_log("%s has classification status %s\n",
00132 prefix, nmg_class_status(status) );
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 static void
00147 joint_hitmiss2(struct neighbor *closest, const struct edgeuse *eu, const fastf_t *pt, int code)
00148 {
00149 const struct edgeuse *eu_rinf;
00150
00151 eu_rinf = nmg_faceradial(eu);
00152
00153 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00154 bu_log("joint_hitmiss2\n");
00155 }
00156 if( eu_rinf == eu ) {
00157 rt_bomb("joint_hitmiss2: radial eu is me?\n");
00158 }
00159
00160
00161
00162
00163 if( eu->up.lu_p->orientation == eu_rinf->up.lu_p->orientation ) {
00164 if (eu->up.lu_p->orientation == OT_SAME) {
00165 closest->class = NMG_CLASS_AonBshared;
00166 } else if (eu->up.lu_p->orientation == OT_OPPOSITE) {
00167 closest->class = NMG_CLASS_AoutB;
00168 } else {
00169 nmg_pr_lu_briefly(eu->up.lu_p, (char *)0);
00170 rt_bomb("joint_hitmiss2: bad loop orientation\n");
00171 }
00172 closest->dist = 0.0;
00173 switch(code) {
00174 case 0:
00175
00176 closest->p.eu = eu;
00177 break;
00178 case 1:
00179
00180 closest->p.vu = eu->vu_p;
00181 break;
00182 case 2:
00183
00184 closest->p.vu = BU_LIST_PNEXT_CIRC(edgeuse,eu)->vu_p;
00185 break;
00186 }
00187 if (rt_g.NMG_debug & DEBUG_CLASSIFY) bu_log("\t\t%s\n", nmg_class_name(closest->class) );
00188 return;
00189 }
00190
00191
00192 rt_bomb("nmg_class.c/joint_hitmiss2() unable to resolve ray/edge hit\n");
00193 bu_log("joint_hitmiss2: NO CODE HERE, assuming miss\n");
00194
00195 if (rt_g.NMG_debug & (DEBUG_CLASSIFY|DEBUG_NMGRT) ) {
00196 nmg_euprint("Hard question time", eu);
00197 bu_log(" eu_rinf=x%x, eu->eumate_p=x%x, eu=x%x\n", eu_rinf, eu->eumate_p, eu);
00198 bu_log(" eu lu orient=%s, eu_rinf lu orient=%s\n",
00199 nmg_orientation(eu->up.lu_p->orientation),
00200 nmg_orientation(eu_rinf->up.lu_p->orientation) );
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 static void
00224 nmg_class_pt_e(struct neighbor *closest, const fastf_t *pt, const struct edgeuse *eu, const struct bn_tol *tol)
00225 {
00226 vect_t ptvec;
00227 vect_t left;
00228 const fastf_t *eupt;
00229 const fastf_t *matept;
00230 point_t pca;
00231 fastf_t dist;
00232 fastf_t dot;
00233 int code;
00234
00235 NMG_CK_EDGEUSE(eu);
00236 NMG_CK_EDGEUSE(eu->eumate_p);
00237 NMG_CK_VERTEX_G(eu->vu_p->v_p->vg_p);
00238 NMG_CK_VERTEX_G(eu->eumate_p->vu_p->v_p->vg_p);
00239 BN_CK_TOL(tol);
00240 VSETALL(left, 0);
00241
00242 eupt = eu->vu_p->v_p->vg_p->coord;
00243 matept = eu->eumate_p->vu_p->v_p->vg_p->coord;
00244
00245 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00246 VPRINT("nmg_class_pt_e\tPt", pt);
00247 nmg_euprint(" \tvs. eu", eu);
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 code = bn_dist_pt3_lseg3( &dist, pca, eu->vu_p->v_p->vg_p->coord,
00257 eu->eumate_p->vu_p->v_p->vg_p->coord,
00258 pt, tol);
00259 if( code <= 0 ) dist = 0;
00260 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00261 bu_log(" \tcode=%d, dist: %g\n", code, dist);
00262 VPRINT(" \tpca:", pca);
00263 }
00264
00265 if (dist >= closest->dist + tol->dist ) {
00266 if(rt_g.NMG_debug & DEBUG_CLASSIFY) {
00267 bu_log("\t\tskipping, earlier eu is closer (%g)\n", closest->dist);
00268 }
00269 return;
00270 }
00271 if( dist >= closest->dist - tol->dist ) {
00272
00273
00274
00275
00276
00277
00278
00279 if( closest->p.eu && closest->p.eu->up.lu_p == eu->up.lu_p ) {
00280 if( closest->class == NMG_CLASS_AoutB ||
00281 closest->class == NMG_CLASS_AonBshared ) {
00282 if(rt_g.NMG_debug & DEBUG_CLASSIFY)
00283 bu_log("\t\tSkipping, earlier eu from same lu at same dist, is OUT or ON.\n");
00284 return;
00285 }
00286 if(rt_g.NMG_debug & DEBUG_CLASSIFY)
00287 bu_log("\t\tEarlier eu from same lu at same dist, is IN, continue processing.\n");
00288 } else {
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 if( closest->class == NMG_CLASS_AinB ||
00302 closest->class == NMG_CLASS_AonBshared ) {
00303 if(rt_g.NMG_debug & DEBUG_CLASSIFY)
00304 bu_log("\t\tSkipping, earlier eu from other another lu at same dist, is IN or ON\n");
00305 return;
00306 }
00307 if(rt_g.NMG_debug & DEBUG_CLASSIFY)
00308 bu_log("\t\tEarlier eu from other lu at same dist, is OUT, continue processing.\n");
00309 }
00310 }
00311
00312
00313 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00314 bu_log("\t\tCLOSER dist=%g (closest=%g), tol=%g\n",
00315 dist, closest->dist, tol->dist);
00316 }
00317
00318 if (*eu->up.magic_p != NMG_LOOPUSE_MAGIC ||
00319 *eu->up.lu_p->up.magic_p != NMG_FACEUSE_MAGIC) {
00320 bu_log("Trying to classify a pt (%g, %g, %g)\n\tvs a wire edge? (%g, %g, %g -> %g, %g, %g)\n",
00321 V3ARGS(pt),
00322 V3ARGS(eupt),
00323 V3ARGS(matept)
00324 );
00325 return;
00326 }
00327
00328 if( code <= 2 ) {
00329
00330
00331 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00332 bu_log("\t\tThe point is ON the edge, calling joint_hitmiss2()\n");
00333 }
00334 joint_hitmiss2(closest, eu, pt, code);
00335 return;
00336 } else {
00337 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00338 bu_log("\t\tThe point is not on the edge\n");
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 if( nmg_find_eu_leftvec( left, eu ) < 0 ) rt_bomb("nmg_class_pt_e() bad LEFT vector\n");
00349
00350 VSUB2(ptvec, pt, pca);
00351 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00352 VPRINT("\t\tptvec unnorm", ptvec);
00353 VPRINT("\t\tleft", left);
00354 }
00355 VUNITIZE( ptvec );
00356
00357 dot = VDOT(left, ptvec);
00358 if( NEAR_ZERO( dot, RT_DOT_TOL ) ) {
00359 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00360 bu_log("\t\tpt lies on line of edge, outside verts. Skipping this edge\n");
00361 goto out;
00362 }
00363
00364 if (dot >= 0.0) {
00365 closest->dist = dist;
00366 closest->p.eu = eu;
00367 closest->class = NMG_CLASS_AinB;
00368 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00369 bu_log("\t\tpt is left of edge, INSIDE loop, dot=%g\n", dot);
00370 } else {
00371 closest->dist = dist;
00372 closest->p.eu = eu;
00373 closest->class = NMG_CLASS_AoutB;
00374 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00375 bu_log("\t\tpt is right of edge, OUTSIDE loop\n");
00376 }
00377
00378 out:
00379
00380
00381 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00382 struct faceuse *fu;
00383 char buf[128];
00384 static int num;
00385 FILE *fp;
00386 long *bits;
00387 point_t mid_pt;
00388 point_t left_pt;
00389 fu = eu->up.lu_p->up.fu_p;
00390 bits = (long *)bu_calloc( nmg_find_model(&fu->l.magic)->maxindex, sizeof(long), "bits[]");
00391 sprintf(buf,"faceclass%d.pl", num++);
00392 if( (fp = fopen(buf, "w")) == NULL) rt_bomb(buf);
00393 nmg_pl_fu( fp, fu, bits, 0, 0, 255 );
00394 pl_color( fp, 0, 255, 0 );
00395 pdv_3line( fp, pca, pt );
00396 pl_color( fp, 255, 0, 0 );
00397 VADD2SCALE( mid_pt, eupt, matept, 0.5 );
00398 VJOIN1( left_pt, mid_pt, 500, left);
00399 pdv_3line( fp, mid_pt, left_pt );
00400 fclose(fp);
00401 bu_free( (char *)bits, "bits[]");
00402 bu_log("wrote %s\n", buf);
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 static void
00426 nmg_class_pt_l(struct neighbor *closest, const fastf_t *pt, const struct loopuse *lu, const struct bn_tol *tol)
00427 {
00428 vect_t delta;
00429 pointp_t lu_pt;
00430 fastf_t dist;
00431 struct edgeuse *eu;
00432 struct loop_g *lg;
00433
00434 NMG_CK_LOOPUSE(lu);
00435 NMG_CK_LOOP(lu->l_p);
00436 lg = lu->l_p->lg_p;
00437 NMG_CK_LOOP_G(lg);
00438
00439 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00440 VPRINT("nmg_class_pt_l\tPt:", pt);
00441 }
00442
00443 if (*lu->up.magic_p != NMG_FACEUSE_MAGIC)
00444 return;
00445
00446 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00447 plane_t peqn;
00448 nmg_pr_lu_briefly(lu, 0);
00449 NMG_GET_FU_PLANE( peqn, lu->up.fu_p );
00450 HPRINT("\tplane eqn", peqn);
00451 }
00452
00453 if( !V3PT_IN_RPP_TOL( pt, lg->min_pt, lg->max_pt, tol ) ) {
00454 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00455 bu_log("\tPoint is outside loop RPP\n");
00456 return;
00457 }
00458 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
00459 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
00460 nmg_class_pt_e(closest, pt, eu, tol);
00461
00462 if( closest->class == NMG_CLASS_AonBshared ) break;
00463 }
00464 } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
00465 register struct vertexuse *vu;
00466 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00467 lu_pt = vu->v_p->vg_p->coord;
00468 VSUB2(delta, pt, lu_pt);
00469 if ( (dist = MAGNITUDE(delta)) < closest->dist) {
00470 if (lu->orientation == OT_OPPOSITE) {
00471 closest->class = NMG_CLASS_AoutB;
00472 } else if (lu->orientation == OT_SAME) {
00473 closest->class = NMG_CLASS_AonBshared;
00474 } else {
00475 nmg_pr_orient(lu->orientation, "\t");
00476 rt_bomb("nmg_class_pt_l: bad orientation for face loopuse\n");
00477 }
00478 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00479 bu_log("\t\t closer to loop pt (%g, %g, %g)\n",
00480 V3ARGS(lu_pt) );
00481
00482 closest->dist = dist;
00483 closest->p.vu = vu;
00484 }
00485 } else {
00486 rt_bomb("nmg_class_pt_l() bad child of loopuse\n");
00487 }
00488 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00489 bu_log("nmg_class_pt_l\treturning, closest=%g %s\n",
00490 closest->dist, nmg_class_name(closest->class) );
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 int
00517 nmg_class_lu_fu(const struct loopuse *lu, const struct bn_tol *tol)
00518 {
00519 const struct faceuse *fu;
00520 struct vertexuse *vu;
00521 const struct vertex_g *vg;
00522 struct edgeuse *eu;
00523 struct edgeuse *eu_first;
00524 fastf_t dist;
00525 plane_t n;
00526 int class;
00527
00528 NMG_CK_LOOPUSE(lu);
00529 BN_CK_TOL(tol);
00530
00531 fu = lu->up.fu_p;
00532 NMG_CK_FACEUSE(fu);
00533 NMG_CK_FACE(fu->f_p);
00534 NMG_CK_FACE_G_PLANE(fu->f_p->g.plane_p);
00535
00536 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00537 bu_log("nmg_class_lu_fu(lu=x%x) START\n", lu);
00538
00539
00540 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC ) {
00541 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00542 eu = (struct edgeuse *)NULL;
00543 } else {
00544 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
00545 NMG_CK_EDGEUSE(eu);
00546 vu = eu->vu_p;
00547 }
00548 eu_first = eu;
00549 again:
00550 NMG_CK_VERTEXUSE(vu);
00551 NMG_CK_VERTEX(vu->v_p);
00552 vg = vu->v_p->vg_p;
00553 NMG_CK_VERTEX_G(vg);
00554
00555 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00556 VPRINT("nmg_class_lu_fu\tPt:", vg->coord);
00557 }
00558
00559
00560 NMG_GET_FU_PLANE( n, fu );
00561 if( (dist=fabs(DIST_PT_PLANE( vg->coord, n ))) > tol->dist ) {
00562 bu_log("nmg_class_lu_fu() ERROR, point (%g,%g,%g) not on face, dist=%g\n",
00563 V3ARGS(vg->coord), dist );
00564 }
00565
00566
00567 class = nmg_class_pt_fu_except( vg->coord, fu, lu,
00568 NULL, NULL, NULL, 0, 0, tol );
00569
00570
00571 if( class == NMG_CLASS_AonBshared ) {
00572 if( !eu_first ) {
00573
00574 } else {
00575 eu = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
00576 if( eu != eu_first ) {
00577 vu = eu->vu_p;
00578 goto again;
00579 }
00580
00581 }
00582 }
00583
00584 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00585 bu_log("nmg_class_lu_fu(lu=x%x) END, ret=%s\n",
00586 lu,
00587 nmg_class_name(class) );
00588 }
00589 return class;
00590 }
00591
00592
00593 static const point_t nmg_good_dirs[10] = {
00594 #if 1
00595 {3, 2, 1},
00596 #else
00597 {1, 0, 0},
00598 #endif
00599 {1, 0, 0},
00600 {0, 1, 0},
00601 {0, 0, 1},
00602 {1, 1, 1},
00603 {-3,-2,-1},
00604 {-1,0, 0},
00605 {0,-1, 0},
00606 {0, 0,-1},
00607 {-1,-1,-1}
00608 };
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 int
00632 nmg_class_pt_s(const fastf_t *pt, const struct shell *s, const int in_or_out_only, const struct bn_tol *tol)
00633 {
00634 const struct faceuse *fu;
00635 struct model *m;
00636 long *faces_seen = NULL;
00637 vect_t region_diagonal;
00638 fastf_t region_diameter;
00639 int class;
00640 vect_t projection_dir;
00641 int try=0;
00642 struct xray rp;
00643
00644 NMG_CK_SHELL(s);
00645 BN_CK_TOL(tol);
00646
00647 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00648 bu_log("nmg_class_pt_s:\tpt=(%g, %g, %g), s=x%x\n",
00649 V3ARGS(pt), s );
00650
00651 if( !V3PT_IN_RPP_TOL(pt, s->sa_p->min_pt, s->sa_p->max_pt, tol) ) {
00652 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00653 bu_log(" OUT, point not in RPP\n");
00654 return NMG_CLASS_AoutB;
00655 }
00656
00657 m = s->r_p->m_p;
00658 NMG_CK_MODEL(m);
00659 if( !in_or_out_only )
00660 {
00661 faces_seen = (long *)bu_calloc( m->maxindex, sizeof(long), "nmg_class_pt_s faces_seen[]" );
00662
00663
00664
00665
00666 for( BU_LIST_FOR(fu, faceuse, &s->fu_hd) ) {
00667 plane_t n;
00668
00669
00670 if( NMG_INDEX_TEST( faces_seen, fu->f_p ) ) continue;
00671
00672
00673 if( fu->orientation != OT_SAME ) continue;
00674
00675
00676 NMG_GET_FU_PLANE( n, fu );
00677 if( (fabs(DIST_PT_PLANE(pt, n))) < tol->dist) {
00678
00679
00680
00681 class = nmg_class_pt_fu_except(pt, fu, (struct loopuse *)0,
00682 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0,
00683 0, tol);
00684 if( class == NMG_CLASS_AonBshared ) {
00685
00686
00687
00688 class = NMG_CLASS_AonBshared;
00689 goto out;
00690 }
00691 if( class == NMG_CLASS_AinB ) {
00692
00693
00694
00695 class = NMG_CLASS_AonBshared;
00696 goto out;
00697 }
00698
00699 }
00700
00701
00702 NMG_INDEX_SET(faces_seen, fu->f_p);
00703 }
00704 }
00705
00706
00707
00708
00709
00710
00711
00712 NMG_CK_REGION_A(s->r_p->ra_p);
00713 VSUB2( region_diagonal, s->r_p->ra_p->max_pt, s->r_p->ra_p->min_pt );
00714 region_diameter = MAGNITUDE(region_diagonal);
00715
00716
00717 try = 0;
00718 retry:
00719 VMOVE( projection_dir, nmg_good_dirs[try] );
00720 if( ++try > 10 ) rt_bomb("nmg_class_pt_s() retry count exhausted\n");
00721 VUNITIZE(projection_dir);
00722
00723 if (rt_g.NMG_debug & DEBUG_CLASSIFY )
00724 bu_log("\tPt=(%g, %g, %g) dir=(%g, %g, %g), reg_diam=%g\n",
00725 V3ARGS(pt), V3ARGS(projection_dir), region_diameter);
00726
00727 VMOVE(rp.r_pt, pt);
00728 VMOVE(rp.r_dir, projection_dir);
00729
00730
00731
00732 class = nmg_class_ray_vs_shell(&rp, s, in_or_out_only, tol);
00733 if( class == NMG_CLASS_Unknown ) goto retry;
00734
00735 out:
00736 if( !in_or_out_only )
00737 bu_free( (char *)faces_seen, "nmg_class_pt_s faces_seen[]" );
00738
00739 if (rt_g.NMG_debug & DEBUG_CLASSIFY )
00740 bu_log("nmg_class_pt_s: returning %s, s=x%x, try=%d\n",
00741 nmg_class_name(class), s, try );
00742 return class;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751 static int
00752 class_vu_vs_s(struct vertexuse *vu, struct shell *sB, long int **classlist, const struct bn_tol *tol)
00753 {
00754 struct vertexuse *vup;
00755 pointp_t pt;
00756 char *reason;
00757 int status = 0;
00758 int class;
00759
00760 NMG_CK_VERTEXUSE(vu);
00761 NMG_CK_SHELL(sB);
00762 BN_CK_TOL(tol);
00763
00764 pt = vu->v_p->vg_p->coord;
00765
00766 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00767 bu_log("class_vu_vs_s(vu=x%x, v=x%x) pt=(%g,%g,%g)\n", vu, vu->v_p, V3ARGS(pt) );
00768
00769
00770 reason = "of cached classification";
00771 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], vu->v_p) ) {
00772 status = INSIDE;
00773 goto out;
00774 }
00775 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBshared], vu->v_p) ) {
00776 status = ON_SURF;
00777 goto out;
00778 }
00779 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBanti], vu->v_p) ) {
00780 status = ON_SURF;
00781 goto out;
00782 }
00783 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], vu->v_p) ) {
00784 status = OUTSIDE;
00785 goto out;
00786 }
00787
00788
00789
00790
00791 for(BU_LIST_FOR(vup, vertexuse, &vu->v_p->vu_hd)) {
00792
00793 if (*vup->up.magic_p == NMG_LOOPUSE_MAGIC ) {
00794 if( nmg_find_s_of_lu(vup->up.lu_p) != sB) continue;
00795 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
00796 vu->v_p );
00797 reason = "a loopuse of vertex is on shell";
00798 status = ON_SURF;
00799 goto out;
00800 } else if (*vup->up.magic_p == NMG_EDGEUSE_MAGIC ) {
00801 if( nmg_find_s_of_eu(vup->up.eu_p) != sB) continue;
00802 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
00803 vu->v_p );
00804 reason = "an edgeuse of vertex is on shell";
00805 status = ON_SURF;
00806 goto out;
00807 } else if( *vup->up.magic_p == NMG_SHELL_MAGIC ) {
00808 if( vup->up.s_p != sB ) continue;
00809 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
00810 vu->v_p );
00811 reason = "vertex is shell's lone vertex";
00812 status = ON_SURF;
00813 goto out;
00814 } else {
00815 rt_bomb("class_vu_vs_s() bad vertex UP pointer\n");
00816 }
00817 }
00818
00819 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00820 bu_log("\tCan't classify vertex via topology\n");
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 {
00832
00833 struct vertex *sv;
00834 if( (sv = nmg_find_pt_in_shell( sB, pt, tol ) ) ) {
00835 bu_log("vu=x%x, v=x%x, sv=x%x, pt=(%g,%g,%g)\n",
00836 vu, vu->v_p, sv, V3ARGS(pt) );
00837 rt_bomb("nmg_class_pt_s() vertex topology not shared properly\n");
00838 }
00839 }
00840
00841 reason = "of nmg_class_pt_s()";
00842 class = nmg_class_pt_s(pt, sB, 1, tol);
00843
00844 if( class == NMG_CLASS_AoutB ) {
00845 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB], vu->v_p);
00846 status = OUTSIDE;
00847 } else if( class == NMG_CLASS_AinB ) {
00848 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], vu->v_p);
00849 status = INSIDE;
00850 } else if( class == NMG_CLASS_AonBshared ) {
00851 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared], vu->v_p);
00852 status = ON_SURF;
00853 } else {
00854 bu_log("class=%s\n", nmg_class_name(class) );
00855 VPRINT("pt", pt);
00856 rt_bomb("class_vu_vs_s: nmg_class_pt_s() failure\n");
00857 }
00858
00859 out:
00860 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
00861 bu_log("class_vu_vs_s(vu=x%x) return %s because %s\n",
00862 vu, nmg_class_status(status), reason );
00863 }
00864 return(status);
00865 }
00866
00867
00868
00869
00870 static int
00871 class_eu_vs_s(struct edgeuse *eu, struct shell *s, long int **classlist, const struct bn_tol *tol)
00872 {
00873 int euv_cl, matev_cl;
00874 int status = 0;
00875 struct edgeuse *eup;
00876 point_t pt;
00877 pointp_t eupt, matept;
00878 char *reason = "Unknown";
00879 int class;
00880
00881 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
00882 {
00883 bu_log( "class_eu_vs_s( eu=x%x (e_p=x%x, lu=x%x), s=x%x )\n", eu, eu->e_p, eu->up.lu_p, s );
00884 nmg_euprint("class_eu_vs_s\t", eu);
00885 }
00886
00887 NMG_CK_EDGEUSE(eu);
00888 NMG_CK_SHELL(s);
00889 BN_CK_TOL(tol);
00890
00891
00892 reason = "of cached classification";
00893 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], eu->e_p) ) {
00894 status = INSIDE;
00895 goto out;
00896 }
00897 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBshared], eu->e_p) ) {
00898 status = ON_SURF;
00899 goto out;
00900 }
00901 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBanti], eu->e_p) ) {
00902 status = ON_SURF;
00903 goto out;
00904 }
00905 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], eu->e_p) ) {
00906 status = OUTSIDE;
00907 goto out;
00908 }
00909
00910 euv_cl = class_vu_vs_s(eu->vu_p, s, classlist, tol);
00911 matev_cl = class_vu_vs_s(eu->eumate_p->vu_p, s, classlist, tol);
00912
00913
00914 if ((euv_cl == INSIDE && matev_cl == OUTSIDE) ||
00915 (euv_cl == OUTSIDE && matev_cl == INSIDE)) {
00916 static int num=0;
00917 char buf[128];
00918 FILE *fp;
00919
00920 sprintf(buf, "class%d.pl", num++ );
00921 if( (fp = fopen(buf, "w")) == NULL ) rt_bomb(buf);
00922 nmg_pl_s( fp, s );
00923
00924 pl_color(fp, 255, 255, 0);
00925 pdv_3line(fp, eu->vu_p->v_p->vg_p->coord,
00926 eu->eumate_p->vu_p->v_p->vg_p->coord );
00927 fclose(fp);
00928
00929 nmg_pr_class_status("eu vu", euv_cl);
00930 nmg_pr_class_status("eumate vu", matev_cl);
00931 if( RT_G_DEBUG || rt_g.NMG_debug ) {
00932
00933 bu_log("Edge not cut, doing it over\n");
00934 NMG_INDEX_CLEAR( classlist[NMG_CLASS_AinB], eu->vu_p);
00935 NMG_INDEX_CLEAR( classlist[NMG_CLASS_AoutB], eu->vu_p);
00936 NMG_INDEX_CLEAR( classlist[NMG_CLASS_AinB], eu->eumate_p->vu_p);
00937 NMG_INDEX_CLEAR( classlist[NMG_CLASS_AoutB], eu->eumate_p->vu_p);
00938
00939 rt_g.NMG_debug |= DEBUG_CLASSIFY;
00940 (void)class_vu_vs_s(eu->vu_p, s, classlist, tol);
00941 (void)class_vu_vs_s(eu->eumate_p->vu_p, s, classlist, tol);
00942 nmg_euprint("didn't this edge get cut?", eu);
00943 nmg_pr_eu(eu, " ");
00944 }
00945
00946 bu_log("wrote %s\n", buf);
00947 rt_bomb("class_eu_vs_s: edge didn't get cut\n");
00948 }
00949
00950 if (euv_cl == ON_SURF && matev_cl == ON_SURF) {
00951 vect_t eu_dir;
00952 int try;
00953
00954
00955 eup = eu->radial_p->eumate_p;
00956 do {
00957 NMG_CK_EDGEUSE(eup);
00958 if (nmg_find_s_of_eu(eup) == s) {
00959 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
00960 eu->e_p );
00961 reason = "a radial edgeuse is on shell";
00962 status = ON_SURF;
00963 goto out;
00964 }
00965 eup = eup->radial_p->eumate_p;
00966 } while (eup != eu->radial_p->eumate_p);
00967
00968
00969 if( nmg_find_matching_eu_in_s( eu, s ) )
00970 {
00971 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
00972 eu->e_p );
00973 reason = "another eu between same vertices is on shell";
00974 status = ON_SURF;
00975 goto out;
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 class = NMG_CLASS_Unknown;
01005 eupt = eu->vu_p->v_p->vg_p->coord;
01006 matept = eu->eumate_p->vu_p->v_p->vg_p->coord;
01007 #if 0
01008 {
01009
01010
01011 int in=0,out=0,on=0,unk=0;
01012 struct edgeuse *eu_loop;
01013 struct edgeuse *eu_on=(struct edgeuse *)NULL;
01014
01015 class_topo = NMG_CLASS_Unknown;
01016
01017 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01018 bu_log( "\tclass_eu_vs_s: attempting topological classification\n" );
01019
01020
01021
01022
01023
01024 eu_loop = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
01025 while( eu_loop != eu )
01026 {
01027 if( NMG_INDEX_TEST( classlist[NMG_CLASS_AinB], eu_loop->e_p ) )
01028 in++;
01029 else if( NMG_INDEX_TEST( classlist[NMG_CLASS_AoutB], eu_loop->e_p ) )
01030 out++;
01031 else if( NMG_INDEX_TEST( classlist[NMG_CLASS_AonBshared], eu_loop->e_p ) )
01032 {
01033 eu_on = eu_loop;
01034 on++;
01035 }
01036 else if( NMG_INDEX_TEST( classlist[NMG_CLASS_AonBanti], eu_loop->e_p ) )
01037 {
01038 eu_on = eu_loop;
01039 on++;
01040 }
01041 else
01042 unk++;
01043
01044 eu_loop = BU_LIST_PNEXT_CIRC( edgeuse, &eu_loop->l );
01045 }
01046
01047 if(in && out )
01048 {
01049
01050 bu_log( "loop crosses shell boundary!!!\n" );
01051 nmg_pr_fu_briefly( nmg_find_fu_of_eu( eu ), "" );
01052 rt_bomb( "loop crosses shell boundary!!!" );
01053 }
01054
01055 if( on )
01056 {
01057 struct edgeuse *eu_rad;
01058 struct edgeuse *eu_rad_too;
01059 struct faceuse *fu_rad;
01060 struct faceuse *fu_rad_too;
01061 struct faceuse *fu_eu;
01062
01063 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01064 bu_log( "\tclass_eu_vs_s: found other eu (x%x) in loop on shell\n", eu_on );
01065
01066
01067
01068
01069
01070
01071 fu_eu = nmg_find_fu_of_eu( eu );
01072 eu_rad = eu_on->radial_p;
01073 while( nmg_find_s_of_eu( eu_rad ) != s &&
01074 eu_rad != eu_on &&
01075 eu_rad != eu_on->eumate_p &&
01076 ( fu_rad = nmg_find_fu_of_eu( eu_rad )) != NULL )
01077 eu_rad = eu_rad->eumate_p->radial_p;
01078
01079
01080 eu_rad_too = eu_on->eumate_p->radial_p;
01081 while( nmg_find_s_of_eu( eu_rad_too ) != s &&
01082 eu_rad_too != eu_on &&
01083 eu_rad_too != eu_on->eumate_p &&
01084 ( fu_rad_too = nmg_find_fu_of_eu( eu_rad_too )) != NULL )
01085 eu_rad_too = eu_rad_too->eumate_p->radial_p;
01086
01087 fu_rad = nmg_find_fu_of_eu( eu_rad );
01088
01089 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01090 {
01091 bu_log( "\tclass_eu_vs_s: eu_rad=x%x, eu_rad_too=x%x\n",
01092 eu_rad, eu_rad_too );
01093 bu_log( "\t\tfu_rad=x%x, fu_rad_too=x%x, fu_eu=x%x, fu_eu->fumate_p=x%x\n",
01094 fu_rad, fu_rad_too, fu_eu, fu_eu->fumate_p );
01095 bu_log( "\t\ts=x%x, fu_rad->s_p=x%x\n", s, fu_rad->s_p );
01096 }
01097
01098 if( fu_rad && fu_rad->s_p == s && fu_rad != fu_eu &&
01099 fu_rad != fu_eu->fumate_p )
01100 {
01101 vect_t left_eu;
01102 vect_t left_rad;
01103 vect_t left_rad_too;
01104 double dot;
01105 double dot_too;
01106
01107 nmg_find_eu_leftvec( left_eu, eu_on );
01108 nmg_find_eu_leftvec( left_rad, eu_rad );
01109 nmg_find_eu_leftvec( left_rad_too, eu_rad_too );
01110
01111 dot = VDOT( left_eu, left_rad );
01112 dot_too = VDOT( left_eu, left_rad_too );
01113
01114 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01115 {
01116 bu_log( "\tclass_eu_vs_s eu_rad=x%x, eu_rad_too=x%x, dot=%f, dot_too=%f\n",
01117 eu_rad, eu_rad_too, dot, dot_too );
01118 }
01119
01120
01121
01122
01123 if( dot > tol->para )
01124 class_topo = NMG_CLASS_Unknown;
01125 else if( dot_too > tol->para )
01126 class_topo = NMG_CLASS_Unknown;
01127 else if( fu_rad->orientation == OT_SAME )
01128 {
01129 class_topo = NMG_CLASS_AoutB;
01130 reason = "nearest radial face is OT_SAME";
01131 }
01132 else if( fu_rad->orientation == OT_OPPOSITE )
01133 {
01134 class_topo = NMG_CLASS_AinB;
01135 reason = "nearest radial face is OT_OPPOSITE";
01136 }
01137 else
01138 {
01139 bu_log( "FU (x%x) has bad orientation (%s)\n", fu_rad, nmg_orientation( fu_rad->orientation ) );
01140 rt_bomb( "FU has bad orientation" );
01141 }
01142 if (rt_g.NMG_debug & DEBUG_CLASSIFY &&
01143 class_topo != NMG_CLASS_Unknown )
01144 {
01145 bu_log( "\tClassifiying EU using on eu (x%x) from fu (x%x)\n", eu_on, nmg_find_fu_of_eu( eu_on) );
01146 nmg_pr_fu_around_eu( eu_on, tol );
01147 }
01148 }
01149 }
01150 }
01151
01152 class = class_topo;
01153 #endif
01154 if( class == NMG_CLASS_Unknown )
01155 {
01156 VSUB2( eu_dir, matept, eupt );
01157 VUNITIZE( eu_dir );
01158 }
01159
01160 try = 0;
01161 while( class == NMG_CLASS_Unknown && try < 3 )
01162 {
01163
01164 switch( try )
01165 {
01166 case 0 :
01167 VADD2SCALE(pt, eupt, matept, 0.5);
01168 reason = "midpoint classification (both verts ON)";
01169 break;
01170 case 1:
01171 VJOIN1( pt, eupt, 1.05*tol->dist, eu_dir );
01172 reason = "point near EU start classification (both verts ON)";
01173 break;
01174 case 2:
01175 VJOIN1( pt, matept, -1.05*tol->dist, eu_dir );
01176 reason = "point near EU end classification (both verts ON)";
01177 break;
01178 }
01179 class = nmg_class_pt_s(pt, s, 1, tol);
01180 try++;
01181 }
01182
01183 if( class == NMG_CLASS_AoutB ) {
01184 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB], eu->e_p);
01185 status = OUTSIDE;
01186 } else if( class == NMG_CLASS_AinB ) {
01187 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], eu->e_p);
01188 status = INSIDE;
01189 } else if( class == NMG_CLASS_AonBshared ) {
01190 FILE *fp;
01191 #if 0
01192
01193 rt_g.NMG_debug |= DEBUG_FINDEU;
01194
01195 rt_g.NMG_debug |= DEBUG_BASIC;
01196 eup = nmg_findeu( eu->vu_p->v_p, eu->eumate_p->vu_p->v_p, s, eu, 0 );
01197 if(!eup) bu_log("Unable to find it\n");
01198 nmg_model_fuse( nmg_find_model((long*)eu), tol );
01199 #endif
01200 nmg_pr_fu_around_eu( eu, tol );
01201 VPRINT("class_eu_vs_s: midpoint of edge", pt);
01202 if( (fp = fopen("shell1.pl", "w")) ) {
01203 nmg_pl_s(fp, s);
01204 fclose(fp);
01205 bu_log("wrote shell1.pl\n");
01206 }
01207 if( (fp = fopen("shell2.pl", "w")) ) {
01208 nmg_pl_shell(fp, eu->up.lu_p->up.fu_p->s_p, 1 );
01209 fclose(fp);
01210 bu_log("wrote shell2.pl\n");
01211 }
01212 #if 0
01213
01214 rt_g.NMG_debug |= DEBUG_POLYSECT;
01215 rt_g.NMG_debug |= DEBUG_PLOTEM;
01216 rt_g.NMG_debug |= DEBUG_BASIC;
01217 bu_log("class_eu_vs_s: classifier found edge midpoint ON, edge topology should have been shared\n\n################ re-run face/face isect ############\n\n");
01218 {
01219 struct faceuse *fu1 = eu->up.lu_p->up.fu_p;
01220 struct faceuse *fu2;
01221
01222 NMG_CK_FACEUSE(fu1);
01223 for( BU_LIST_FOR( fu2, faceuse, &s->fu_hd ) ) {
01224 NMG_CK_FACEUSE(fu2);
01225 if( fu2->orientation != OT_SAME ) continue;
01226 nmg_isect_two_generic_faces( fu1, fu2, tol );
01227 }
01228 eup = nmg_findeu( eu->vu_p->v_p, eu->eumate_p->vu_p->v_p, s, eu, 0 );
01229 if(!eup) bu_log("Unable to find it\n");
01230 }
01231 #endif
01232 rt_bomb("class_eu_vs_s: classifier found edge midpoint ON, edge topology should have been shared\n");
01233 } else {
01234 bu_log("class=%s\n", nmg_class_name(class) );
01235 nmg_euprint("Why wasn't this edge in or out?", eu);
01236 rt_bomb("class_eu_vs_s: nmg_class_pt_s() midpoint failure\n");
01237 }
01238 goto out;
01239 }
01240
01241 if (euv_cl == OUTSIDE || matev_cl == OUTSIDE) {
01242 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB], eu->e_p);
01243 reason = "at least one vert OUT";
01244 status = OUTSIDE;
01245 goto out;
01246 }
01247 if( euv_cl == INSIDE && matev_cl == INSIDE ) {
01248 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], eu->e_p);
01249 reason = "both verts IN";
01250 status = INSIDE;
01251 goto out;
01252 }
01253 if( (euv_cl == INSIDE && matev_cl == ON_SURF) ||
01254 (euv_cl == ON_SURF && matev_cl == INSIDE) ) {
01255 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], eu->e_p);
01256 reason = "one vert IN, one ON";
01257 status = INSIDE;
01258 goto out;
01259 }
01260 bu_log("eu's vert is %s, mate's vert is %s\n",
01261 nmg_class_status(euv_cl), nmg_class_status(matev_cl) );
01262 rt_bomb("class_eu_vs_s() inconsistent edgeuse\n");
01263 out:
01264 if (rt_g.NMG_debug & DEBUG_GRAPHCL)
01265 nmg_show_broken_classifier_stuff((long *)eu, classlist, nmg_class_nothing_broken, 0, (char *)NULL);
01266 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
01267 bu_log("class_eu_vs_s(eu=x%x) return %s because %s\n",
01268 eu, nmg_class_status(status), reason );
01269 }
01270 return(status);
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 int
01290 nmg_2lu_identical(const struct edgeuse *eu1, const struct edgeuse *eu2)
01291 {
01292 const struct loopuse *lu1;
01293 const struct loopuse *lu2;
01294 const struct edgeuse *eu1_first;
01295 const struct faceuse *fu1;
01296 const struct faceuse *fu2;
01297 int ret;
01298
01299 NMG_CK_EDGEUSE(eu1);
01300 NMG_CK_EDGEUSE(eu2);
01301
01302 if( eu1->e_p != eu2->e_p ) rt_bomb("nmg_2lu_identical() differing edges?\n");
01303
01304
01305 if (eu2->vu_p->v_p != eu1->vu_p->v_p) {
01306 eu2 = eu2->eumate_p;
01307 if (eu2->vu_p->v_p != eu1->vu_p->v_p)
01308 rt_bomb("nmg_2lu_identical() radial edgeuse doesn't share verticies\n");
01309 }
01310
01311 lu1 = eu1->up.lu_p;
01312 lu2 = eu2->up.lu_p;
01313
01314 NMG_CK_LOOPUSE(lu1);
01315 NMG_CK_LOOPUSE(lu2);
01316
01317
01318
01319
01320 eu1_first = eu1;
01321 do {
01322 if( eu1->vu_p->v_p != eu2->vu_p->v_p ) {
01323 ret = 0;
01324 goto out;
01325 }
01326 eu1 = BU_LIST_PNEXT_CIRC(edgeuse, &eu1->l);
01327 eu2 = BU_LIST_PNEXT_CIRC(edgeuse, &eu2->l);
01328 } while ( eu1 != eu1_first );
01329
01330 if( *lu1->up.magic_p != NMG_FACEUSE_MAGIC ||
01331 *lu2->up.magic_p != NMG_FACEUSE_MAGIC ) {
01332 ret = 3;
01333 goto out;
01334 }
01335
01336 fu1 = lu1->up.fu_p;
01337 fu2 = lu2->up.fu_p;
01338
01339 if( fu1->f_p->g.plane_p != fu2->f_p->g.plane_p ) {
01340 vect_t fu1_norm,fu2_norm;
01341 #if 0
01342 bu_log("nmg_2lu_identical() loops lu1=x%x lu2=x%x are shared, face geometry is not? fg1=x%x, fg2=x%x\n",
01343 lu1, lu2, fu1->f_p->g.plane_p, fu2->f_p->g.plane_p);
01344 bu_log("---- fu1, f=x%x, flip=%d\n", fu1->f_p, fu1->f_p->flip);
01345 nmg_pr_fg(fu1->f_p->g.magic_p, 0);
01346 nmg_pr_fu_briefly(fu1, 0);
01347
01348 bu_log("---- fu2, f=x%x, flip=%d\n", fu2->f_p, fu2->f_p->flip);
01349 nmg_pr_fg(fu2->f_p->g.magic_p, 0);
01350 nmg_pr_fu_briefly(fu2, 0);
01351 #endif
01352
01353
01354 if( fu1->orientation != fu2->orientation )
01355 NMG_GET_FU_NORMAL( fu2_norm, fu2->fumate_p )
01356 else
01357 NMG_GET_FU_NORMAL( fu2_norm, fu2 )
01358
01359 NMG_GET_FU_NORMAL( fu1_norm, fu1 );
01360 if( VDOT( fu1_norm, fu2_norm ) < 0.0 )
01361 ret = 2;
01362 else
01363 ret = 1;
01364 goto out;
01365 }
01366
01367 if( rt_g.NMG_debug & DEBUG_BASIC ) {
01368 bu_log("---- fu1, f=x%x, flip=%d\n", fu1->f_p, fu1->f_p->flip);
01369 nmg_pr_fu_briefly(fu1, 0);
01370 bu_log("---- fu2, f=x%x, flip=%d\n", fu2->f_p, fu2->f_p->flip);
01371 nmg_pr_fu_briefly(fu2, 0);
01372 }
01373
01374
01375
01376
01377
01378
01379 if( fu1->f_p->flip != fu2->f_p->flip )
01380 ret = 2;
01381 else
01382 ret = 1;
01383 out:
01384 if( rt_g.NMG_debug & DEBUG_BASIC ) {
01385 bu_log("nmg_2lu_identical(eu1=x%x, eu2=x%x) ret=%d\n",
01386 eu1, eu2, ret);
01387 }
01388 return ret;
01389 }
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 void
01403 nmg_reclassify_lu_eu(struct loopuse *lu, long int **classlist, int newclass)
01404 {
01405 struct vertexuse *vu;
01406 struct edgeuse *eu;
01407 struct vertex *v;
01408
01409 NMG_CK_LOOPUSE(lu);
01410
01411 if (rt_g.NMG_debug & DEBUG_BASIC) {
01412 bu_log("nmg_reclassify_lu_eu(lu=x%x, classlist=x%x, newclass=%s)\n",
01413 lu, classlist, nmg_class_name(newclass) );
01414 }
01415
01416 if( newclass != NMG_CLASS_AonBshared && newclass != NMG_CLASS_AonBanti )
01417 rt_bomb("nmg_reclassify_lu_eu() bad newclass\n");
01418
01419 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
01420 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01421 NMG_CK_VERTEXUSE(vu);
01422 v = vu->v_p;
01423 NMG_CK_VERTEX(v);
01424
01425 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], v) ||
01426 NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], v) )
01427 rt_bomb("nmg_reclassify_lu_eu() changing in/out vert of lone vu loop to ON?\n");
01428
01429
01430 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBshared], v);
01431 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBanti], v);
01432
01433 NMG_INDEX_SET(classlist[newclass], v);
01434 return;
01435 }
01436
01437 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) {
01438 struct edge *e;
01439 NMG_CK_EDGEUSE(eu);
01440 e = eu->e_p;
01441 NMG_CK_EDGE(e);
01442
01443 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], e) ||
01444 NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], e) )
01445 rt_bomb("nmg_reclassify_lu_eu() changing in/out edge to ON?\n");
01446
01447
01448 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBshared], e);
01449 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBanti], e);
01450
01451 NMG_INDEX_SET(classlist[newclass], e);
01452
01453
01454 vu = eu->vu_p;
01455 NMG_CK_VERTEXUSE(vu);
01456 v = vu->v_p;
01457 NMG_CK_VERTEX(v);
01458
01459 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], v) ||
01460 NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], v) )
01461 rt_bomb("nmg_reclassify_lu_eu() changing in/out vert to ON?\n");
01462
01463
01464 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBshared], v);
01465 NMG_INDEX_CLEAR(classlist[NMG_CLASS_AonBanti], v);
01466
01467 NMG_INDEX_SET(classlist[newclass], v);
01468 }
01469 }
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499 static int
01500 class_shared_lu(const struct loopuse *lu, const struct loopuse *lu_ref, const struct bn_tol *tol)
01501 {
01502 struct shell *s_ref;
01503 struct edgeuse *eu;
01504 struct edgeuse *eu_ref;
01505 struct edgeuse *eu_start,*eu_tmp;
01506 struct faceuse *fu_of_lu;
01507 vect_t left;
01508 vect_t left_ref;
01509
01510 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01511 bu_log( "class_shared_lu: classifying lu x%x w.r.t. lu_ref x%x\n",
01512 lu, lu_ref );
01513
01514 NMG_CK_LOOPUSE( lu );
01515 NMG_CK_LOOPUSE( lu_ref );
01516 BN_CK_TOL( tol );
01517
01518 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
01519 for( BU_LIST_FOR( eu_ref, edgeuse, &lu_ref->down_hd ) )
01520 {
01521 if( eu_ref->e_p == eu->e_p )
01522 break;
01523 }
01524
01525 if( eu_ref->e_p != eu->e_p )
01526 {
01527 bu_log( "class_shared_lu() couldn't find a shared EU between LU's x%x and x%x\n",
01528 lu, lu_ref );
01529 rt_bomb( "class_shared_lu() couldn't find a shared EU between LU's\n" );
01530 }
01531
01532 if( nmg_find_eu_leftvec( left, eu ) )
01533 {
01534 bu_log( "class_shared_lu() couldn't get a left vector for EU x%x\n", eu );
01535 rt_bomb( "class_shared_lu() couldn't get a left vector for EU\n" );
01536 }
01537 if( nmg_find_eu_leftvec( left_ref, eu_ref ) )
01538 {
01539 bu_log( "class_shared_lu() couldn't get a left vector for EU x%x\n", eu_ref );
01540 rt_bomb( "class_shared_lu() couldn't get a left vector for EU\n" );
01541 }
01542
01543 if( VDOT( left, left_ref ) > 0.0 )
01544 {
01545 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01546 {
01547 bu_log( "eu x%x goes form v x%x to v x%x\n", eu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p );
01548 bu_log( "eu_ref x%x goes form v x%x to v x%x\n", eu_ref, eu_ref->vu_p->v_p, eu_ref->eumate_p->vu_p->v_p );
01549 }
01550
01551
01552 if( eu->vu_p->v_p == eu_ref->vu_p->v_p )
01553 {
01554 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01555 bu_log( "class_shared_lu returning NMG_CLASS_AonBshared\n" );
01556 return( NMG_CLASS_AonBshared );
01557 }
01558 else
01559 {
01560 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01561 bu_log( "class_shared_lu returning NMG_CLASS_AonBanti\n" );
01562 return( NMG_CLASS_AonBanti );
01563 }
01564 }
01565
01566
01567
01568
01569
01570 s_ref = nmg_find_s_of_eu( eu_ref );
01571 fu_of_lu = nmg_find_fu_of_lu( lu );
01572
01573 for( BU_LIST_FOR( eu_start, edgeuse, &lu->down_hd ) )
01574 {
01575 int use_this_eu=1;
01576
01577 eu_tmp = eu_start->eumate_p->radial_p;
01578 while( eu_tmp != eu_start )
01579 {
01580 struct faceuse *fu_tmp;
01581 struct loopuse *lu_tmp;
01582 int class;
01583
01584 fu_tmp = nmg_find_fu_of_eu( eu_tmp );
01585 if( fu_tmp != fu_of_lu && fu_tmp->fumate_p != fu_of_lu )
01586 {
01587 eu_tmp = eu_tmp->eumate_p->radial_p;
01588 continue;
01589 }
01590
01591
01592
01593 if( *eu_tmp->up.magic_p != NMG_LOOPUSE_MAGIC )
01594 {
01595 eu_tmp = eu_tmp->eumate_p->radial_p;
01596 continue;
01597 }
01598 lu_tmp = eu_tmp->up.lu_p;
01599 if( fu_tmp->fumate_p == fu_of_lu )
01600 lu_tmp = lu_tmp->lumate_p;
01601
01602 if( lu_tmp == lu )
01603 {
01604
01605 use_this_eu = 0;
01606 break;
01607 }
01608
01609 class = nmg_classify_lu_lu( lu_tmp, lu, tol );
01610 if( lu->orientation == OT_OPPOSITE && class == NMG_CLASS_AoutB )
01611 {
01612
01613 use_this_eu = 0;
01614 break;
01615 }
01616 else if( lu->orientation == OT_SAME && class == NMG_CLASS_AinB )
01617 {
01618
01619 use_this_eu = 0;
01620 break;
01621 }
01622
01623 eu_tmp = eu_tmp->eumate_p->radial_p;
01624 }
01625 if( !use_this_eu )
01626 continue;
01627
01628
01629
01630
01631 eu_tmp = eu_start->eumate_p->radial_p;
01632 while( eu_tmp != eu_start )
01633 {
01634 struct faceuse *fu_tmp;
01635
01636 if( nmg_find_s_of_eu( eu_tmp ) == s_ref )
01637 {
01638 fu_tmp = nmg_find_fu_of_eu( eu_tmp );
01639 if( fu_tmp->orientation == OT_SAME )
01640 return( NMG_CLASS_AoutB );
01641 else
01642 return( NMG_CLASS_AinB );
01643 }
01644
01645 eu_tmp = eu_tmp->eumate_p->radial_p;
01646 }
01647 }
01648
01649 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01650 bu_log( "class_shared_lu returning NMG_CLASS_Unknown at end\n" );
01651 return( NMG_CLASS_Unknown );
01652 }
01653
01654
01655
01656
01657
01658
01659
01660 static int
01661 class_lu_vs_s(struct loopuse *lu, struct shell *s, long int **classlist, const struct bn_tol *tol)
01662 {
01663 int class;
01664 unsigned int in, outside, on;
01665 struct edgeuse *eu, *p;
01666 struct loopuse *q_lu;
01667 struct vertexuse *vu;
01668 long magic1;
01669 char *reason = "Unknown";
01670 int seen_error = 0;
01671 int status = 0;
01672
01673 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01674 bu_log( "class_lu_vs_s( lu=x%x, s=x%x )\n", lu, s );
01675
01676 NMG_CK_LOOPUSE(lu);
01677 NMG_CK_SHELL(s);
01678 BN_CK_TOL(tol);
01679
01680 if( nmg_find_s_of_lu( lu ) == s )
01681 {
01682 bu_log( "class_lu_vs_s() is trying to classify lu x%x vs its own shell (x%x)\n",
01683 lu, s );
01684 rt_bomb( "class_lu_vs_s() is trying to classify lu vs its own shell" );
01685 }
01686
01687
01688 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], lu->l_p) ) {
01689 reason = "of classlist";
01690 class = NMG_CLASS_AinB;
01691 status = INSIDE;
01692 goto out;
01693 }
01694
01695 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBshared], lu->l_p) ) {
01696 reason = "of classlist";
01697 class = NMG_CLASS_AonBshared;
01698 status = ON_SURF;
01699 goto out;
01700 }
01701 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AonBanti], lu->l_p) ) {
01702 reason = "of classlist";
01703 class = NMG_CLASS_AonBanti;
01704 status = ON_SURF;
01705 goto out;
01706 }
01707
01708 if( NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], lu->l_p) ) {
01709 reason = "of classlist";
01710 class = NMG_CLASS_AoutB;
01711 status = OUTSIDE;
01712 goto out;
01713 }
01714
01715 magic1 = BU_LIST_FIRST_MAGIC( &lu->down_hd );
01716 if (magic1 == NMG_VERTEXUSE_MAGIC) {
01717
01718 reason = "of vertex classification";
01719 vu = BU_LIST_PNEXT( vertexuse, &lu->down_hd );
01720 NMG_CK_VERTEXUSE(vu);
01721 class = class_vu_vs_s(vu, s, classlist, tol);
01722 switch (class) {
01723 case INSIDE:
01724 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], lu->l_p);
01725 break;
01726 case OUTSIDE:
01727 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB], lu->l_p);
01728 break;
01729 case ON_SURF:
01730 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared], lu->l_p);
01731 break;
01732 default:
01733 rt_bomb("class_lu_vs_s: bad vertexloop classification\n");
01734 }
01735 status = class;
01736 goto out;
01737 } else if (magic1 != NMG_EDGEUSE_MAGIC) {
01738 rt_bomb("class_lu_vs_s: bad child of loopuse\n");
01739 }
01740
01741
01742 retry:
01743 in = outside = on = 0;
01744 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
01745
01746 class = class_eu_vs_s(eu, s, classlist, tol);
01747 switch (class) {
01748 case INSIDE : ++in;
01749 break;
01750 case OUTSIDE : ++outside;
01751 break;
01752 case ON_SURF : ++on;
01753 break;
01754 default : rt_bomb("class_lu_vs_s: bad class for edgeuse\n");
01755 }
01756 }
01757
01758 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01759 bu_log("class_lu_vs_s: Loopuse edges in:%d on:%d out:%d\n", in, on, outside);
01760
01761 if (in > 0 && outside > 0) {
01762 FILE *fp;
01763
01764 if( rt_g.NMG_debug & DEBUG_CLASSIFY ) {
01765 char buf[128];
01766 static int num;
01767 long *b;
01768 struct model *m;
01769
01770 m = nmg_find_model(lu->up.magic_p);
01771 b = (long *)bu_calloc(m->maxindex, sizeof(long), "nmg_pl_lu flag[]");
01772
01773 for(BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
01774 if (NMG_INDEX_TEST(classlist[NMG_CLASS_AinB], eu->e_p))
01775 nmg_euprint("In: edgeuse", eu);
01776 else if (NMG_INDEX_TEST(classlist[NMG_CLASS_AoutB], eu->e_p))
01777 nmg_euprint("Out: edgeuse", eu);
01778 else if (NMG_INDEX_TEST(classlist[NMG_CLASS_AonBshared], eu->e_p))
01779 nmg_euprint("OnShare: edgeuse", eu);
01780 else if (NMG_INDEX_TEST(classlist[NMG_CLASS_AonBanti], eu->e_p))
01781 nmg_euprint("OnAnti: edgeuse", eu);
01782 else
01783 nmg_euprint("BAD: edgeuse", eu);
01784 }
01785
01786 sprintf(buf, "badloop%d.pl", num++);
01787 if ((fp=fopen(buf, "w")) != NULL) {
01788 nmg_pl_lu(fp, lu, b, 255, 255, 255);
01789 nmg_pl_s(fp, s);
01790 fclose(fp);
01791 bu_log("wrote %s\n", buf);
01792 }
01793 nmg_pr_lu(lu, "");
01794 nmg_stash_model_to_file( "class.g", nmg_find_model((long *)lu), "class_ls_vs_s: loop transits plane of shell/face?");
01795 bu_free( (char *)b, "nmg_pl_lu flag[]" );
01796 }
01797 if(seen_error)
01798 rt_bomb("class_lu_vs_s: loop transits plane of shell/face?\n");
01799 seen_error = 1;
01800 goto retry;
01801 }
01802 if (outside > 0) {
01803 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB], lu->l_p);
01804 reason = "edgeuses were OUT and ON";
01805 class = NMG_CLASS_AoutB;
01806 status = OUTSIDE;
01807 goto out;
01808 } else if (in > 0) {
01809 NMG_INDEX_SET(classlist[NMG_CLASS_AinB], lu->l_p);
01810 reason = "edgeuses were IN and ON";
01811 class = NMG_CLASS_AinB;
01812 status = INSIDE;
01813 goto out;
01814 } else if (on == 0)
01815 rt_bomb("class_lu_vs_s: alright, who's the wiseguy that stole my edgeuses?\n");
01816
01817
01818 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01819 bu_log("\tAll edgeuses of loop are ON\n");
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 if (*lu->up.magic_p == NMG_SHELL_MAGIC) {
01839 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared], lu->l_p);
01840 reason = "loop is a wire loop in the shell";
01841 class = NMG_CLASS_AonBshared;
01842 status = ON_SURF;
01843 goto out;
01844 }
01845
01846 NMG_CK_FACEUSE(lu->up.fu_p);
01847
01848 #if 0
01849 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01850 for(
01851 eu = eu->radial_p->eumate_p;
01852 eu != BU_LIST_FIRST(edgeuse, &lu->down_hd);
01853 eu = eu->radial_p->eumate_p
01854 ) {
01855 int code;
01856
01857
01858
01859
01860 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
01861 q_lu = eu->up.lu_p;
01862 if( *q_lu->up.magic_p != NMG_FACEUSE_MAGIC ) continue;
01863
01864 if( q_lu == lu ) continue;
01865
01866
01867 if( q_lu->up.fu_p->s_p != s ) continue;
01868
01869 code = nmg_2lu_identical( eu,
01870 BU_LIST_FIRST(edgeuse, &lu->down_hd) );
01871 switch(code) {
01872 default:
01873 case 0:
01874
01875 break;
01876 case 1:
01877
01878 if( lu->orientation == OT_OPPOSITE ) {
01879 NMG_INDEX_SET(classlist[NMG_CLASS_AonBanti],
01880 lu->l_p );
01881 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01882 bu_log("Loop is on-antishared (lu orient is OT_OPPOSITE)\n");
01883 nmg_reclassify_lu_eu( lu, classlist, NMG_CLASS_AonBanti );
01884 } else {
01885 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
01886 lu->l_p );
01887 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01888 bu_log("Loop is on-shared\n");
01889
01890 }
01891 reason = "edges identical with radial face, normals colinear";
01892 status = ON_SURF;
01893 goto out;
01894 case 2:
01895
01896 if( lu->orientation == OT_OPPOSITE ) {
01897 NMG_INDEX_SET(classlist[NMG_CLASS_AonBshared],
01898 lu->l_p );
01899 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01900 bu_log("Loop is on-shared (lu orient is OT_OPPOSITE)\n");
01901
01902 } else {
01903 NMG_INDEX_SET(classlist[NMG_CLASS_AonBanti],
01904 lu->l_p );
01905 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01906 bu_log("Loop is on-antishared\n");
01907 nmg_reclassify_lu_eu( lu, classlist, NMG_CLASS_AonBanti );
01908 }
01909 reason = "edges identical with radial face, normals opposite";
01910 status = ON_SURF;
01911 goto out;
01912 case 3:
01913 rt_bomb("class_lu_vs_s() unexpected wire ON\n");
01914 }
01915 }
01916 #else
01917 class = NMG_CLASS_Unknown;
01918 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01919 for(
01920 eu = eu->radial_p->eumate_p;
01921 eu != BU_LIST_FIRST(edgeuse, &lu->down_hd) ;
01922 eu = eu->radial_p->eumate_p )
01923 {
01924 struct faceuse *fu_qlu;
01925 struct edgeuse *eu1;
01926 struct edgeuse *eu2;
01927 int found_match;
01928
01929
01930
01931
01932 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC ) continue;
01933 q_lu = eu->up.lu_p;
01934 if( *q_lu->up.magic_p != NMG_FACEUSE_MAGIC ) continue;
01935 fu_qlu = q_lu->up.fu_p;
01936 NMG_CK_FACEUSE( fu_qlu );
01937
01938 if( q_lu == lu ) continue;
01939
01940
01941 if( q_lu->up.fu_p->s_p != s ) continue;
01942
01943 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01944 bu_log( "\tfound radial lu (x%x), check for match\n", q_lu );
01945
01946
01947 eu1 = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01948 if( eu1->vu_p->v_p == eu->vu_p->v_p )
01949 eu2 = eu;
01950 else if( eu1->vu_p->v_p == eu->eumate_p->vu_p->v_p )
01951 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
01952 else
01953 eu2 = BU_LIST_PPREV_CIRC( edgeuse, &eu->l );
01954 found_match = 1;
01955 do
01956 {
01957 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01958 bu_log( "\t\tcompare vertex x%x to vertex x%x\n", eu1->vu_p->v_p, eu2->vu_p->v_p );
01959 if( eu1->vu_p->v_p != eu2->vu_p->v_p )
01960 {
01961 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01962 bu_log( "\t\t\tnot a match\n" );
01963 found_match = 0;
01964 break;
01965 }
01966 eu1 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
01967 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
01968 } while( eu1 != BU_LIST_FIRST(edgeuse, &lu->down_hd));
01969
01970 if( !found_match )
01971 {
01972
01973 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01974 bu_log( "\tChecking for match in opposite direction\n" );
01975 eu1 = BU_LIST_FIRST(edgeuse, &lu->down_hd);
01976 if( eu1->vu_p->v_p == eu->vu_p->v_p )
01977 eu2 = eu;
01978 else if( eu1->vu_p->v_p == eu->eumate_p->vu_p->v_p )
01979 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
01980 else
01981 eu2 = BU_LIST_PPREV_CIRC( edgeuse, &eu->l );
01982 found_match = 1;
01983 do
01984 {
01985 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01986 bu_log( "\t\tcompare vertex x%x to vertex x%x\n", eu1->vu_p->v_p, eu2->vu_p->v_p );
01987 if( eu1->vu_p->v_p != eu2->vu_p->v_p )
01988 {
01989 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
01990 bu_log( "\t\t\tnot a match\n" );
01991 found_match = 0;
01992 break;
01993 }
01994 eu1 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
01995 eu2 = BU_LIST_PPREV_CIRC( edgeuse, &eu2->l );
01996 } while( eu1 != BU_LIST_FIRST(edgeuse, &lu->down_hd));
01997 }
01998
01999 if( found_match )
02000 {
02001 int test_class = NMG_CLASS_Unknown;
02002
02003 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02004 bu_log( "\tFound a matching LU's x%x and x%x\n", lu, q_lu );
02005
02006 if( fu_qlu->orientation == OT_SAME )
02007 test_class = class_shared_lu( lu, q_lu, tol );
02008 else if( fu_qlu->orientation == OT_OPPOSITE )
02009 test_class = class_shared_lu( lu, q_lu->lumate_p, tol );
02010 else
02011 {
02012 bu_log( "class_lu_vs_s: FU x%x for lu x%x matching lu x%x has bad orientation (%s)\n",
02013 fu_qlu, lu, q_lu, nmg_orientation( fu_qlu->orientation ) );
02014 rt_bomb( "class_lu_vs_s: FU has bad orientation\n" );
02015 }
02016
02017 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02018 bu_log( "\tclass_shared_lu says %s\n", nmg_class_name( test_class ) );
02019
02020 if( class == NMG_CLASS_Unknown )
02021 class = test_class;
02022 else if( test_class == NMG_CLASS_AonBshared || test_class == NMG_CLASS_AonBanti )
02023 class = test_class;
02024
02025 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02026 bu_log( "\tclass set to %s\n", nmg_class_name( class ) );
02027
02028 if( class == NMG_CLASS_AonBshared )
02029 break;
02030 }
02031
02032 }
02033
02034 if( class != NMG_CLASS_Unknown )
02035 {
02036 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02037 bu_log( "Final class = %s\n", nmg_class_name( class ) );
02038 NMG_INDEX_SET( classlist[class],lu->l_p );
02039 if( class == NMG_CLASS_AonBanti )
02040 nmg_reclassify_lu_eu( lu, classlist, NMG_CLASS_AonBanti );
02041
02042 reason = "edges identical with radial face";
02043 status = ON_SURF;
02044 goto out;
02045 }
02046 #endif
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02058 {
02059 bu_log( "Checking radial faces:\n" );
02060 nmg_pr_fu_around_eu( eu, tol );
02061 }
02062
02063 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
02064
02065 p = eu->radial_p;
02066 do {
02067 if (*p->up.magic_p == NMG_LOOPUSE_MAGIC &&
02068 *p->up.lu_p->up.magic_p == NMG_FACEUSE_MAGIC &&
02069 p->up.lu_p->up.fu_p->s_p == s) {
02070
02071 if (p->up.lu_p->up.fu_p->orientation == OT_OPPOSITE) {
02072 NMG_INDEX_SET(classlist[NMG_CLASS_AinB],
02073 lu->l_p );
02074 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02075 bu_log("Loop is INSIDE of fu x%x\n", p->up.lu_p->up.fu_p);
02076 reason = "radial faceuse is OT_OPPOSITE";
02077 class = NMG_CLASS_AinB;
02078 status = INSIDE;
02079 goto out;
02080 } else if (p->up.lu_p->up.fu_p->orientation == OT_SAME) {
02081 NMG_INDEX_SET(classlist[NMG_CLASS_AoutB],
02082 lu->l_p );
02083 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02084 bu_log("Loop is OUTSIDEof fu x%x\n", p->up.lu_p->up.fu_p);
02085 reason = "radial faceuse is OT_SAME";
02086 class = NMG_CLASS_AoutB;
02087 status = OUTSIDE;
02088 goto out;
02089 } else {
02090 rt_bomb("class_lu_vs_s() bad fu orientation\n");
02091 }
02092 }
02093 p = p->eumate_p->radial_p;
02094 } while (p != eu->eumate_p);
02095
02096 }
02097
02098 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02099 bu_log("Loop is OUTSIDE 'cause it isn't anything else\n");
02100
02101
02102
02103
02104
02105 NMG_INDEX_SET( classlist[NMG_CLASS_AoutB], lu->l_p );
02106 reason = "loopuse is ON a wire loop in the shell";
02107 class = NMG_CLASS_AoutB;
02108 status = OUTSIDE;
02109 out:
02110 if (rt_g.NMG_debug & DEBUG_CLASSIFY) {
02111 bu_log("class_lu_vs_s(lu=x%x) return %s (%s) because %s\n",
02112 lu, nmg_class_status(status), nmg_class_name( class ), reason );
02113 }
02114 return status;
02115 }
02116
02117
02118
02119
02120
02121
02122
02123 static void
02124 class_fu_vs_s(struct faceuse *fu, struct shell *s, long int **classlist, const struct bn_tol *tol)
02125 {
02126 struct loopuse *lu;
02127 plane_t n;
02128
02129 NMG_CK_FACEUSE(fu);
02130 NMG_CK_SHELL(s);
02131
02132 NMG_GET_FU_PLANE( n, fu );
02133
02134 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02135 PLPRINT("\nclass_fu_vs_s plane equation:", n);
02136
02137 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02138 (void)class_lu_vs_s(lu, s, classlist, tol);
02139
02140 if (rt_g.NMG_debug & DEBUG_CLASSIFY)
02141 bu_log("class_fu_vs_s() END\n");
02142 }
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156 void
02157 nmg_class_shells(struct shell *sA, struct shell *sB, long int **classlist, const struct bn_tol *tol)
02158 {
02159 struct faceuse *fu;
02160 struct loopuse *lu;
02161 struct edgeuse *eu;
02162
02163 NMG_CK_SHELL(sA);
02164 NMG_CK_SHELL(sB);
02165 BN_CK_TOL(tol);
02166
02167 if (rt_g.NMG_debug & DEBUG_CLASSIFY &&
02168 BU_LIST_NON_EMPTY(&sA->fu_hd))
02169 bu_log("nmg_class_shells - doing faces\n");
02170
02171 fu = BU_LIST_FIRST(faceuse, &sA->fu_hd);
02172 while (BU_LIST_NOT_HEAD(fu, &sA->fu_hd)) {
02173
02174 class_fu_vs_s(fu, sB, classlist, tol);
02175
02176 if (BU_LIST_PNEXT(faceuse, fu) == fu->fumate_p)
02177 fu = BU_LIST_PNEXT_PNEXT(faceuse, fu);
02178 else
02179 fu = BU_LIST_PNEXT(faceuse, fu);
02180 }
02181
02182 if (rt_g.NMG_debug & DEBUG_CLASSIFY &&
02183 BU_LIST_NON_EMPTY(&sA->lu_hd))
02184 bu_log("nmg_class_shells - doing loops\n");
02185
02186 lu = BU_LIST_FIRST(loopuse, &sA->lu_hd);
02187 while (BU_LIST_NOT_HEAD(lu, &sA->lu_hd)) {
02188
02189 (void)class_lu_vs_s(lu, sB, classlist, tol);
02190
02191 if (BU_LIST_PNEXT(loopuse, lu) == lu->lumate_p)
02192 lu = BU_LIST_PNEXT_PNEXT(loopuse, lu);
02193 else
02194 lu = BU_LIST_PNEXT(loopuse, lu);
02195 }
02196
02197 if (rt_g.NMG_debug & DEBUG_CLASSIFY &&
02198 BU_LIST_NON_EMPTY(&sA->eu_hd))
02199 bu_log("nmg_class_shells - doing edges\n");
02200
02201 eu = BU_LIST_FIRST(edgeuse, &sA->eu_hd);
02202 while (BU_LIST_NOT_HEAD(eu, &sA->eu_hd)) {
02203
02204 (void)class_eu_vs_s(eu, sB, classlist, tol);
02205
02206 if (BU_LIST_PNEXT(edgeuse, eu) == eu->eumate_p)
02207 eu = BU_LIST_PNEXT_PNEXT(edgeuse, eu);
02208 else
02209 eu = BU_LIST_PNEXT(edgeuse, eu);
02210 }
02211
02212 if (sA->vu_p) {
02213 if (rt_g.NMG_debug)
02214 bu_log("nmg_class_shells - doing vertex\n");
02215 (void)class_vu_vs_s(sA->vu_p, sB, classlist, tol);
02216 }
02217 }
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231 int
02232 nmg_classify_pt_loop(const point_t pt,
02233 const struct loopuse *lu,
02234 const struct bn_tol *tol)
02235 {
02236 struct neighbor closest;
02237 struct faceuse *fu;
02238 plane_t n;
02239 fastf_t dist;
02240
02241 NMG_CK_LOOPUSE( lu );
02242 BN_CK_TOL( tol );
02243
02244 bu_log("DANGER: nmg_classify_pt_loop() is calling nmg_class_pt_l(), which does not work well\n");
02245 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
02246 {
02247 bu_log( "nmg_classify_pt_loop: lu not part of a faceuse!!\n" );
02248 return( -1 );
02249 }
02250
02251 fu = lu->up.fu_p;
02252
02253
02254 NMG_GET_FU_PLANE( n, fu );
02255 if( (dist=fabs(DIST_PT_PLANE( pt, n ))) > tol->dist ) {
02256 bu_log("nmg_classify_pt_l() ERROR, point (%g,%g,%g) not on face, dist=%g\n",
02257 V3ARGS(pt), dist );
02258 return( -1 );
02259 }
02260
02261
02262
02263 closest.dist = MAX_FASTF;
02264 closest.p.eu = (struct edgeuse *)NULL;
02265 closest.class = NMG_CLASS_AoutB;
02266
02267 nmg_class_pt_l( &closest , pt , lu , tol );
02268
02269 return( closest.class );
02270 }
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283 int
02284 nmg_get_interior_pt(fastf_t *pt, const struct loopuse *lu, const struct bn_tol *tol)
02285 {
02286 struct edgeuse *eu;
02287 fastf_t point_count=0.0;
02288 double one_over_count;
02289 point_t test_pt;
02290 point_t average_pt;
02291 int i;
02292
02293 NMG_CK_LOOPUSE( lu );
02294 BN_CK_TOL( tol );
02295
02296 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
02297 return( 1 );
02298
02299 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02300 return( 2 );
02301
02302 if( nmg_loop_is_a_crack( lu ) )
02303 return( 3 );
02304
02305
02306 VSETALL( average_pt, 0.0 );
02307 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02308 {
02309 struct vertex_g *vg;
02310 NMG_CK_EDGEUSE( eu );
02311
02312 vg = eu->vu_p->v_p->vg_p;
02313 NMG_CK_VERTEX_G( vg );
02314
02315 VADD2( average_pt, average_pt, vg->coord );
02316 point_count++;
02317 }
02318
02319 one_over_count = 1.0/point_count;
02320 VSCALE( average_pt, average_pt, one_over_count );
02321 VMOVE( test_pt, average_pt );
02322
02323 if (nmg_class_pt_lu_except( test_pt, lu, (struct edge *)NULL, tol ) == NMG_CLASS_AinB )
02324 {
02325 VMOVE( pt, test_pt );
02326 return( 0 );
02327 }
02328
02329 for( i=0 ; i<3 ; i++ )
02330 {
02331
02332 double tol_mult;
02333
02334
02335 switch( i )
02336 {
02337 case 0:
02338 tol_mult = 5.0 * tol->dist;
02339 break;
02340 case 1:
02341 tol_mult = 1.5 * tol->dist;
02342 break;
02343 case 2:
02344 tol_mult = 1.005 * tol->dist;
02345 break;
02346 default:
02347 tol_mult = 1;
02348 break;
02349 }
02350 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02351 {
02352 vect_t left;
02353 struct vertex_g *vg1,*vg2;
02354
02355 (void)nmg_find_eu_leftvec( left, eu );
02356
02357 vg1 = eu->vu_p->v_p->vg_p;
02358 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
02359
02360 VADD2( test_pt, vg1->coord, vg2->coord );
02361 VSCALE( test_pt, test_pt, 0.5 );
02362
02363 VJOIN1( test_pt, test_pt, tol_mult, left );
02364 if( nmg_class_pt_lu_except( test_pt, lu, (struct edge *)NULL, tol ) == NMG_CLASS_AinB )
02365 {
02366 VMOVE( pt, test_pt );
02367 return( 0 );
02368 }
02369 }
02370 }
02371
02372 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02373 {
02374 bu_log( "nmg_get_interior_pt: Couldn't find interior point for lu x%x\n", lu );
02375 nmg_pr_lu_briefly( lu, "" );
02376 }
02377
02378 VMOVE( pt, average_pt );
02379 return( 4 );
02380 }
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 int
02394 nmg_classify_lu_lu(const struct loopuse *lu1, const struct loopuse *lu2, const struct bn_tol *tol)
02395 {
02396 struct faceuse *fu1,*fu2;
02397 struct edgeuse *eu;
02398 int share_edges;
02399 int lu1_eu_count=0;
02400 int lu2_eu_count=0;
02401
02402 NMG_CK_LOOPUSE( lu1 );
02403 NMG_CK_LOOPUSE( lu2 );
02404 BN_CK_TOL( tol );
02405
02406 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02407 bu_log( "nmg_classify_lu_lu( lu1=x%x , lu2=x%x )\n", lu1, lu2 );
02408
02409 if( lu1 == lu2 || lu1 == lu2->lumate_p )
02410 return( NMG_CLASS_AonBshared );
02411
02412 if( *lu1->up.magic_p != NMG_FACEUSE_MAGIC )
02413 {
02414 bu_log( "nmg_classify_lu_lu: lu1 not part of a faceuse\n" );
02415 return( -1 );
02416 }
02417
02418 if( *lu2->up.magic_p != NMG_FACEUSE_MAGIC )
02419 {
02420 bu_log( "nmg_classify_lu_lu: lu2 not part of a faceuse\n" );
02421 return( -1 );
02422 }
02423
02424 fu1 = lu1->up.fu_p;
02425 NMG_CK_FACEUSE( fu1 );
02426 fu2 = lu2->up.fu_p;
02427 NMG_CK_FACEUSE( fu2 );
02428
02429 if( fu1->f_p != fu2->f_p )
02430 {
02431 bu_log( "nmg_classify_lu_lu: loops are not in same face\n" );
02432 return( -1 );
02433 }
02434
02435
02436 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_EDGEUSE_MAGIC &&
02437 BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_EDGEUSE_MAGIC )
02438 {
02439 struct edgeuse *eu1_start,*eu2_start;
02440 struct edgeuse *eu1,*eu2;
02441
02442
02443 for( BU_LIST_FOR( eu, edgeuse, &lu1->down_hd ) )
02444 lu1_eu_count++;
02445
02446
02447 for( BU_LIST_FOR( eu, edgeuse, &lu2->down_hd ) )
02448 lu2_eu_count++;
02449
02450 share_edges = 1;
02451 eu1_start = BU_LIST_FIRST( edgeuse , &lu1->down_hd );
02452 NMG_CK_EDGEUSE( eu1_start );
02453 eu2_start = BU_LIST_FIRST( edgeuse , &lu2->down_hd );
02454 NMG_CK_EDGEUSE( eu2_start );
02455 while( BU_LIST_NOT_HEAD( eu2_start , &lu2->down_hd ) &&
02456 eu2_start->e_p != eu1_start->e_p )
02457 {
02458 NMG_CK_EDGEUSE( eu2_start );
02459 eu2_start = BU_LIST_PNEXT( edgeuse , &eu2_start->l );
02460 }
02461
02462 if( BU_LIST_NOT_HEAD( eu2_start , &lu2->down_hd ) &&
02463 eu1_start->e_p == eu2_start->e_p )
02464 {
02465
02466 share_edges = 1;
02467 eu1 = eu1_start;
02468 eu2 = eu2_start;
02469 do
02470 {
02471 if( eu1->e_p != eu2->e_p )
02472 {
02473 share_edges = 0;
02474 break;
02475 }
02476 eu1 = BU_LIST_PNEXT_CIRC( edgeuse , &eu1->l );
02477 eu2 = BU_LIST_PNEXT_CIRC( edgeuse , &eu2->l );
02478 } while( eu1 != eu1_start );
02479
02480 if( !share_edges )
02481 {
02482
02483 share_edges = 1;
02484 eu1 = eu1_start;
02485 eu2 = eu2_start;
02486 do
02487 {
02488 if( eu1->e_p != eu2->e_p )
02489 {
02490 share_edges = 0;
02491 break;
02492 }
02493 eu1 = BU_LIST_PNEXT_CIRC( edgeuse , &eu1->l );
02494 eu2 = BU_LIST_PPREV_CIRC( edgeuse , &eu2->l );
02495 } while( eu1 != eu1_start );
02496 }
02497
02498 if( share_edges && lu1_eu_count == lu2_eu_count )
02499 {
02500 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02501 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AonBshared\n" );
02502 return( NMG_CLASS_AonBshared );
02503 }
02504 else
02505 {
02506 vect_t inward1,inward2;
02507
02508
02509
02510
02511
02512 for( BU_LIST_FOR( eu , edgeuse , &lu1->down_hd ) )
02513 {
02514 struct vertex_g *vg;
02515 int class;
02516
02517 NMG_CK_EDGEUSE( eu );
02518
02519 vg = eu->vu_p->v_p->vg_p;
02520 NMG_CK_VERTEX_G( vg );
02521
02522 if( nmg_find_vertex_in_lu( eu->vu_p->v_p, lu2 ) != NULL )
02523 continue;
02524
02525 class = nmg_class_pt_lu_except( vg->coord, lu2, (struct edge *)NULL, tol);
02526 if( class != NMG_CLASS_AonBshared && class != NMG_CLASS_AonBanti )
02527 {
02528 if( lu2->orientation == OT_SAME )
02529 {
02530 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02531 bu_log( "nmg_classify_lu_lu returning %s\n", nmg_class_name( class ) );
02532 return( class );
02533 }
02534 else
02535 {
02536 if( class == NMG_CLASS_AinB )
02537 {
02538 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02539 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AoutB\n" );
02540 return( NMG_CLASS_AoutB );
02541 }
02542 if( class == NMG_CLASS_AoutB )
02543 {
02544 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02545 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AinB\n" );
02546 return( NMG_CLASS_AinB );
02547 }
02548 }
02549 }
02550 }
02551
02552
02553
02554
02555
02556 nmg_find_eu_leftvec( inward1, eu1_start );
02557 if( lu1->orientation == OT_OPPOSITE )
02558 VREVERSE( inward1, inward1 );
02559
02560 nmg_find_eu_leftvec( inward2, eu2_start );
02561 if( lu2->orientation == OT_OPPOSITE )
02562 VREVERSE( inward2, inward2 );
02563
02564 if( VDOT( inward1, inward2 ) < 0.0 )
02565 return( NMG_CLASS_AoutB );
02566 else
02567 return( NMG_CLASS_AinB );
02568 }
02569 }
02570 else
02571 {
02572
02573 for( BU_LIST_FOR( eu , edgeuse , &lu1->down_hd ) )
02574 {
02575 struct vertex_g *vg;
02576 int class;
02577
02578 NMG_CK_EDGEUSE( eu );
02579
02580 vg = eu->vu_p->v_p->vg_p;
02581 NMG_CK_VERTEX_G( vg );
02582
02583 if( nmg_find_vertex_in_lu( eu->vu_p->v_p, lu2 ) != NULL )
02584 continue;
02585
02586 class = nmg_class_pt_lu_except( vg->coord, lu2, (struct edge *)NULL, tol);
02587 if( class != NMG_CLASS_AonBshared && class != NMG_CLASS_AonBanti )
02588 {
02589 if( lu2->orientation == OT_SAME )
02590 {
02591 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02592 bu_log( "nmg_classify_lu_lu returning %s\n", nmg_class_name( class ) );
02593 return( class );
02594 }
02595 else
02596 {
02597 if( class == NMG_CLASS_AinB )
02598 {
02599 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02600 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AoutB\n" );
02601 return( NMG_CLASS_AoutB );
02602 }
02603 if( class == NMG_CLASS_AoutB )
02604 {
02605 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02606 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AinB\n" );
02607 return( NMG_CLASS_AinB );
02608 }
02609 }
02610 }
02611 }
02612
02613
02614
02615
02616 for( BU_LIST_FOR( eu , edgeuse , &lu1->down_hd ) )
02617 {
02618 struct vertex_g *vg1,*vg2;
02619 int class;
02620 point_t mid_pt;
02621
02622 vg1 = eu->vu_p->v_p->vg_p;
02623 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
02624
02625 VADD2( mid_pt, vg1->coord, vg2->coord );
02626 VSCALE( mid_pt, mid_pt, 0.5 );
02627
02628 class = nmg_class_pt_lu_except( mid_pt, lu2, (struct edge *)NULL, tol);
02629 if( class != NMG_CLASS_AonBshared && class != NMG_CLASS_AonBanti )
02630 {
02631 if( lu2->orientation == OT_SAME )
02632 {
02633 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02634 bu_log( "nmg_classify_lu_lu returning %s\n", nmg_class_name( class ) );
02635 return( class );
02636 }
02637 else
02638 {
02639 if( class == NMG_CLASS_AinB )
02640 {
02641 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02642 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AoutB\n" );
02643 return( NMG_CLASS_AoutB );
02644 }
02645 if( class == NMG_CLASS_AoutB )
02646 {
02647 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02648 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AinB\n" );
02649 return( NMG_CLASS_AinB );
02650 }
02651 }
02652 }
02653 }
02654
02655
02656 bu_log( "nmg_classify_lu_lu: Cannot classify lu x%x w.r.t. lu x%x\n",
02657 lu1, lu2 );
02658 return( NMG_CLASS_Unknown );
02659 }
02660 }
02661 else if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_VERTEXUSE_MAGIC &&
02662 BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC )
02663 {
02664 struct vertexuse *vu1,*vu2;
02665
02666 vu1 = BU_LIST_FIRST( vertexuse , &lu1->down_hd );
02667 vu2 = BU_LIST_FIRST( vertexuse , &lu2->down_hd );
02668
02669 if( vu1->v_p == vu2->v_p )
02670 {
02671 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02672 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AonBshared\n" );
02673 return( NMG_CLASS_AonBshared );
02674 }
02675 else
02676 {
02677 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02678 bu_log( "nmg_classify_lu_lu returning NMG_CLASS_AoutB\n" );
02679 return( NMG_CLASS_AoutB );
02680 }
02681 }
02682
02683 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_VERTEXUSE_MAGIC )
02684 {
02685 struct vertexuse *vu;
02686 struct vertex_g *vg;
02687 int class;
02688
02689 vu = BU_LIST_FIRST( vertexuse , &lu1->down_hd );
02690 NMG_CK_VERTEXUSE( vu );
02691 vg = vu->v_p->vg_p;
02692 NMG_CK_VERTEX_G( vg );
02693
02694 class = nmg_class_pt_lu_except( vg->coord, lu2,
02695 (struct edge *)NULL, tol );
02696
02697 if( lu2->orientation == OT_OPPOSITE )
02698 {
02699 if( class == NMG_CLASS_AoutB )
02700 class = NMG_CLASS_AinB;
02701 else if( class == NMG_CLASS_AinB )
02702 class = NMG_CLASS_AoutB;
02703 }
02704 if( rt_g.NMG_debug & DEBUG_CLASSIFY )
02705 bu_log( "nmg_classify_lu_lu returning %s\n", nmg_class_name( class ) );
02706 return( class );
02707 }
02708 else if( BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC )
02709 return( NMG_CLASS_AoutB );
02710
02711 bu_log( "nmg_classify_lu_lu: ERROR, Should not get here!!!\n" );
02712 rt_bomb( "nmg_classify_lu_lu: ERROR, Should not get here!!!\n" );
02713
02714 return( -1);
02715 }
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 int
02731 nmg_classify_s_vs_s(struct shell *s2, struct shell *s, const struct bn_tol *tol)
02732 {
02733 int i;
02734 int class;
02735 struct faceuse *fu;
02736 struct loopuse *lu;
02737 struct edgeuse *eu;
02738 point_t pt_in_s2;
02739 struct bu_ptbl verts;
02740
02741 if( !V3RPP1_IN_RPP2( s2->sa_p->min_pt, s2->sa_p->max_pt, s->sa_p->min_pt, s->sa_p->max_pt ) )
02742 return( NMG_CLASS_AoutB );
02743
02744
02745
02746
02747 if( BU_LIST_NON_EMPTY( &s2->fu_hd ) )
02748 {
02749 fu = BU_LIST_FIRST( faceuse, &s2->fu_hd );
02750 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02751 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
02752 VMOVE( pt_in_s2, eu->vu_p->v_p->vg_p->coord );
02753 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02754 if( class == NMG_CLASS_AinB )
02755 return( NMG_CLASS_AinB );
02756 else if( class == NMG_CLASS_AoutB )
02757 return( NMG_CLASS_AoutB );
02758
02759
02760 VMOVE( pt_in_s2, eu->eumate_p->vu_p->v_p->vg_p->coord );
02761 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02762 if( class == NMG_CLASS_AinB )
02763 return( NMG_CLASS_AinB );
02764 else if( class == NMG_CLASS_AoutB )
02765 return( NMG_CLASS_AoutB );
02766 }
02767
02768 if( BU_LIST_NON_EMPTY( &s2->lu_hd ) )
02769 {
02770 lu = BU_LIST_FIRST( loopuse, &s2->lu_hd );
02771 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
02772 VMOVE( pt_in_s2, eu->vu_p->v_p->vg_p->coord );
02773 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02774 if( class == NMG_CLASS_AinB )
02775 return( NMG_CLASS_AinB );
02776 else if( class == NMG_CLASS_AoutB )
02777 return( NMG_CLASS_AoutB );
02778
02779
02780 VMOVE( pt_in_s2, eu->eumate_p->vu_p->v_p->vg_p->coord );
02781 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02782 if( class == NMG_CLASS_AinB )
02783 return( NMG_CLASS_AinB );
02784 else if( class == NMG_CLASS_AoutB )
02785 return( NMG_CLASS_AoutB );
02786 }
02787
02788 if( BU_LIST_NON_EMPTY( &s2->eu_hd ) )
02789 {
02790 eu = BU_LIST_FIRST( edgeuse, &s2->eu_hd );
02791 VMOVE( pt_in_s2, eu->vu_p->v_p->vg_p->coord );
02792 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02793 if( class == NMG_CLASS_AinB )
02794 return( NMG_CLASS_AinB );
02795 else if( class == NMG_CLASS_AoutB )
02796 return( NMG_CLASS_AoutB );
02797
02798
02799 VMOVE( pt_in_s2, eu->eumate_p->vu_p->v_p->vg_p->coord );
02800 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02801 if( class == NMG_CLASS_AinB )
02802 return( NMG_CLASS_AinB );
02803 else if( class == NMG_CLASS_AoutB )
02804 return( NMG_CLASS_AoutB );
02805 }
02806
02807 if( s2->vu_p && s2->vu_p->v_p->vg_p )
02808 {
02809 VMOVE( pt_in_s2, s2->vu_p->v_p->vg_p->coord );
02810 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02811 if( class == NMG_CLASS_AinB )
02812 return( NMG_CLASS_AinB );
02813 else if( class == NMG_CLASS_AoutB )
02814 return( NMG_CLASS_AoutB );
02815 }
02816
02817
02818 nmg_vertex_tabulate( &verts, &s2->l.magic );
02819 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
02820 {
02821 struct vertex *v;
02822
02823 v = (struct vertex *)BU_PTBL_GET( &verts, i );
02824
02825 VMOVE( pt_in_s2, v->vg_p->coord );
02826 class = nmg_class_pt_s(pt_in_s2, s, 0, tol);
02827 if( class == NMG_CLASS_AinB )
02828 {
02829 bu_ptbl_free( &verts );
02830 return( NMG_CLASS_AinB );
02831 }
02832 else if( class == NMG_CLASS_AoutB )
02833 {
02834 bu_ptbl_free( &verts );
02835 return( NMG_CLASS_AoutB );
02836 }
02837 }
02838 bu_ptbl_free( &verts );
02839
02840
02841 return( NMG_CLASS_Unknown );
02842 }
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852