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 #ifndef lint
00036 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_tri.c,v 14.14 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00037 #endif
00038
00039 #include "common.h"
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044
00045 #include "machine.h"
00046 #include "vmath.h"
00047 #include "nmg.h"
00048 #include "raytrace.h"
00049 #include "plot3.h"
00050
00051
00052
00053
00054 #define TOL_2D 1.0e-10
00055 #define P_GT_V(_p, _v) \
00056 (((_p)->coord[Y] - (_v)->coord[Y]) > TOL_2D || (NEAR_ZERO((_p)->coord[Y] - (_v)->coord[Y], TOL_2D) && (_p)->coord[X] < (_v)->coord[X]))
00057 #define P_LT_V(_p, _v) \
00058 (((_p)->coord[Y] - (_v)->coord[Y]) < (-TOL_2D) || (NEAR_ZERO((_p)->coord[Y] - (_v)->coord[Y], TOL_2D) && (_p)->coord[X] > (_v)->coord[X]))
00059 #define P_GE_V(_p, _v) \
00060 (((_p)->coord[Y] - (_v)->coord[Y]) > TOL_2D || (NEAR_ZERO((_p)->coord[Y] - (_v)->coord[Y], TOL_2D) && (_p)->coord[X] <= (_v)->coord[X]))
00061 #define P_LE_V(_p, _v) \
00062 (((_p)->coord[Y] - (_v)->coord[Y]) < (-TOL_2D) || (NEAR_ZERO((_p)->coord[Y] - (_v)->coord[Y], TOL_2D) && (_p)->coord[X] >= (_v)->coord[X]))
00063
00064 #define NMG_PT2D_MAGIC 0x2d2d2d2d
00065 #define NMG_TRAP_MAGIC 0x1ab1ab
00066 #define NMG_CK_PT2D(_p) NMG_CKMAG(_p, NMG_PT2D_MAGIC, "pt2d")
00067 #define NMG_CK_TRAP(_p) {NMG_CKMAG(_p, NMG_TRAP_MAGIC, "trap");\
00068 if ( ! BU_LIST_PREV(bu_list, &(_p)->l) ) {\
00069 bu_log("%s %d bad prev pointer of trapezoid 0x%08x\n",\
00070 __FILE__, __LINE__, &(_p)->l);\
00071 rt_bomb("NMG_CK_TRAP: aborting");\
00072 } else if (! BU_LIST_NEXT(bu_list, &(_p)->l) ) {\
00073 bu_log("%s %d bad next pointer of trapezoid 0x%08x\n",\
00074 __FILE__, __LINE__, &(_p)->l);\
00075 rt_bomb("NMG_CL_TRAP: aborting");\
00076 }}
00077
00078 #define NMG_TBL2D_MAGIC 0x3e3e3e3e
00079 #define NMG_CK_TBL2D(_p) NMG_CKMAG(_p, NMG_TBL2D_MAGIC, "tbl2d")
00080
00081
00082 #define PT2D_NEXT(tbl, pt) pt2d_pn(tbl, pt, 1)
00083 #define PT2D_PREV(tbl, pt) pt2d_pn(tbl, pt, -1)
00084
00085 struct pt2d {
00086 struct bu_list l;
00087 fastf_t coord[3];
00088 struct vertexuse *vu_p;
00089 };
00090
00091
00092 struct trap {
00093 struct bu_list l;
00094 struct pt2d *top;
00095 struct pt2d *bot;
00096 struct edgeuse *e_left;
00097 struct edgeuse *e_right;
00098 };
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 int PvsV(struct trap *p, struct trap *v)
00109 {
00110 NMG_CK_TRAP(p);
00111 NMG_CK_TRAP(v);
00112
00113 if (p->top->coord[Y] > v->top->coord[Y]) return(1);
00114 else if (p->top->coord[Y] < v->top->coord[Y]) return(-1);
00115 else if (p->top->coord[X] < v->top->coord[X]) return(1);
00116 else if (p->top->coord[X] > v->top->coord[X]) return(-1);
00117 else return(0);
00118 }
00119
00120
00121 static struct pt2d *find_pt2d(struct bu_list *tbl2d, struct vertexuse *vu);
00122 static FILE *plot_fd;
00123
00124 static void
00125 print_2d_eu(char *s, struct edgeuse *eu, struct bu_list *tbl2d)
00126 {
00127 struct pt2d *pt, *pt_next;
00128 NMG_CK_TBL2D(tbl2d);
00129 NMG_CK_EDGEUSE(eu);
00130
00131 pt = find_pt2d(tbl2d, eu->vu_p);
00132 pt_next = find_pt2d(tbl2d, (BU_LIST_PNEXT_CIRC(edgeuse, eu))->vu_p);
00133 bu_log("%s: 0x%08x %g %g -> %g %g\n", s, eu,
00134 pt->coord[X], pt->coord[Y],
00135 pt_next->coord[X], pt_next->coord[Y]);
00136 }
00137
00138
00139 static void
00140 print_trap(struct trap *tp, struct bu_list *tbl2d)
00141 {
00142 NMG_CK_TBL2D(tbl2d);
00143 NMG_CK_TRAP(tp);
00144
00145 bu_log("trap 0x%08x top pt2d: 0x%08x %g %g vu:0x%08x\n",
00146 tp,
00147 &tp->top, tp->top->coord[X], tp->top->coord[Y],
00148 tp->top->vu_p);
00149
00150 if (tp->bot)
00151 bu_log("\t\tbot pt2d: 0x%08x %g %g vu:0x%08x\n",
00152 &tp->bot, tp->bot->coord[X], tp->bot->coord[Y],
00153 tp->bot->vu_p);
00154 else {
00155 bu_log("\tbot (nil)\n");
00156 }
00157
00158 if (tp->e_left)
00159 print_2d_eu("\t\t e_left", tp->e_left, tbl2d);
00160
00161 if (tp->e_right)
00162 print_2d_eu("\t\t e_right", tp->e_right, tbl2d);
00163 }
00164 static void
00165 print_tlist(struct bu_list *tbl2d, struct bu_list *tlist)
00166 {
00167 struct trap *tp;
00168 NMG_CK_TBL2D(tbl2d);
00169
00170 bu_log("Trapezoid list start ----------\n");
00171 for (BU_LIST_FOR(tp, trap, tlist)) {
00172 NMG_CK_TRAP(tp);
00173 print_trap(tp, tbl2d);
00174 }
00175 bu_log("Trapezoid list end ----------\n");
00176 }
00177
00178 static int flatten_debug=1;
00179
00180 static struct pt2d *
00181 find_pt2d(struct bu_list *tbl2d, struct vertexuse *vu)
00182 {
00183 struct pt2d *p;
00184 NMG_CK_TBL2D(tbl2d);
00185 NMG_CK_VERTEXUSE(vu);
00186
00187 for (BU_LIST_FOR(p, pt2d, tbl2d)) {
00188 if (p->vu_p == vu) {
00189 return p;
00190 }
00191 }
00192 return (struct pt2d *)NULL;
00193 }
00194
00195 static void
00196 nmg_tri_plfu(struct faceuse *fu, struct bu_list *tbl2d)
00197 {
00198 static int file_number=0;
00199 FILE *fd;
00200 char name[25];
00201 char buf[80];
00202 long *b;
00203 struct loopuse *lu;
00204 struct edgeuse *eu;
00205 struct vertexuse *vu;
00206 struct pt2d *p;
00207
00208 NMG_CK_TBL2D(tbl2d);
00209 NMG_CK_FACEUSE(fu);
00210
00211 sprintf(name, "tri%02d.pl", file_number++);
00212 if ((fd=fopen(name, "w")) == (FILE *)NULL) {
00213 perror(name);
00214 abort();
00215 }
00216
00217 bu_log("\tplotting %s\n", name);
00218 b = (long *)bu_calloc( fu->s_p->r_p->m_p->maxindex,
00219 sizeof(long), "bit vec"),
00220
00221 pl_erase(fd);
00222 pd_3space(fd,
00223 fu->f_p->min_pt[0]-1.0,
00224 fu->f_p->min_pt[1]-1.0,
00225 fu->f_p->min_pt[2]-1.0,
00226 fu->f_p->max_pt[0]+1.0,
00227 fu->f_p->max_pt[1]+1.0,
00228 fu->f_p->max_pt[2]+1.0);
00229
00230 nmg_pl_fu(fd, fu, b, 255, 255, 255);
00231
00232 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
00233 NMG_CK_LOOPUSE(lu);
00234 if ( BU_LIST_IS_EMPTY(&lu->down_hd) ) {
00235 bu_log("Empty child list for loopuse %s %d\n", __FILE__, __LINE__);
00236 } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC){
00237 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00238 pdv_3move(fd, vu->v_p->vg_p->coord);
00239 if ( (p=find_pt2d(tbl2d, vu)) ) {
00240 sprintf(buf, "%g, %g",
00241 p->coord[0], p->coord[1]);
00242 pl_label(fd, buf);
00243 } else
00244 pl_label(fd, "X, Y (no 2D coords)");
00245
00246 } else {
00247 eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
00248 NMG_CK_EDGEUSE( eu );
00249
00250 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
00251 if ( (p=find_pt2d(tbl2d,eu->vu_p)) ) {
00252 pdv_3move(fd, eu->vu_p->v_p->vg_p->coord);
00253
00254 sprintf(buf, "%g, %g",
00255 p->coord[0], p->coord[1]);
00256 pl_label(fd, buf);
00257 } else
00258 pl_label(fd, "X, Y (no 2D coords)");
00259 }
00260 }
00261 }
00262
00263
00264 bu_free((char *)b, "plot table");
00265 fclose(fd);
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275 static struct pt2d *
00276 pt2d_pn(struct bu_list *tbl, struct pt2d *pt, int dir)
00277 {
00278 struct edgeuse *eu, *eu_other;
00279 struct pt2d *new_pt;
00280
00281 NMG_CK_TBL2D(tbl);
00282 NMG_CK_PT2D( pt );
00283 NMG_CK_VERTEXUSE( (pt)->vu_p );
00284
00285 if ( *(pt)->vu_p->up.magic_p == NMG_EDGEUSE_MAGIC) {
00286 eu = (pt)->vu_p->up.eu_p;
00287 NMG_CK_EDGEUSE( eu );
00288 if (dir < 0)
00289 eu_other = BU_LIST_PPREV_CIRC(edgeuse, eu);
00290 else
00291 eu_other = BU_LIST_PNEXT_CIRC(edgeuse, eu);
00292
00293 new_pt = find_pt2d(tbl, eu_other->vu_p);
00294 if (new_pt == (struct pt2d *)NULL) {
00295 if (dir < 0)
00296 bu_log("can't find prev of %g %g\n",
00297 pt->coord[X],
00298 pt->coord[Y]);
00299 else
00300 bu_log("can't find next of %g %g\n",
00301 pt->coord[X],
00302 pt->coord[Y]);
00303 rt_bomb("goodbye\n");
00304 }
00305 NMG_CK_PT2D( new_pt );
00306 return new_pt;
00307 }
00308
00309 if ( *(pt)->vu_p->up.magic_p != NMG_LOOPUSE_MAGIC) {
00310 bu_log("%s %d Bad vertexuse parent (%g %g %g)\n",
00311 __FILE__, __LINE__,
00312 V3ARGS( (pt)->vu_p->v_p->vg_p->coord ) );
00313 rt_bomb("goodbye\n");
00314 }
00315
00316 return pt;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 static void
00326 map_vu_to_2d(struct vertexuse *vu, struct bu_list *tbl2d, fastf_t *mat, struct faceuse *fu)
00327 {
00328 struct vertex_g *vg;
00329 struct vertexuse *vu_p;
00330 struct vertex *vp;
00331 struct pt2d *p, *np;
00332
00333 NMG_CK_TBL2D(tbl2d);
00334 NMG_CK_VERTEXUSE(vu);
00335 NMG_CK_FACEUSE(fu);
00336
00337
00338 if (find_pt2d(tbl2d, vu)) return;
00339
00340
00341 np = (struct pt2d *)bu_calloc(1, sizeof(struct pt2d), "pt2d struct");
00342 np->coord[2] = 0.0;
00343 np->vu_p = vu;
00344 BU_LIST_MAGIC_SET(&np->l, NMG_PT2D_MAGIC);
00345
00346
00347 for (BU_LIST_FOR(vu_p, vertexuse, &vu->v_p->vu_hd)) {
00348 if ( (p = find_pt2d(tbl2d, vu_p)) ) {
00349 VMOVE(np->coord, p->coord);
00350 return;
00351 }
00352 }
00353
00354
00355 vg = vu->v_p->vg_p;
00356 MAT4X3PNT(np->coord, mat, vg->coord);
00357
00358
00359 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug) bu_log(
00360 "Transforming 0x%x 3D(%g, %g, %g) to 2D(%g, %g, %g)\n",
00361 vu, V3ARGS(vg->coord), V3ARGS(np->coord) );
00362
00363
00364 for ( BU_LIST_FOR(p, pt2d, tbl2d) ) {
00365 if (P_GT_V(p, np)) continue;
00366 break;
00367 }
00368 BU_LIST_INSERT(&p->l, &np->l);
00369
00370 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00371 bu_log("transforming other vertexuses...\n");
00372
00373
00374
00375
00376 vp = vu->v_p;
00377
00378 for (BU_LIST_FOR(vu_p, vertexuse, &vp->vu_hd)) {
00379 register struct faceuse *fu_of_vu;
00380 NMG_CK_VERTEXUSE(vu_p);
00381
00382 if (vu_p == vu) continue;
00383
00384 fu_of_vu = nmg_find_fu_of_vu(vu_p);
00385 if( !fu_of_vu ) continue;
00386 NMG_CK_FACEUSE(fu_of_vu);
00387 if (fu_of_vu != fu) continue;
00388
00389 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00390 bu_log("transform 0x%x... ", vu_p);
00391
00392
00393 if (find_pt2d(tbl2d, vu_p)) {
00394 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug) {
00395 bu_log("vertexuse already transformed\n", vu);
00396 nmg_pr_vu(vu, NULL);
00397 }
00398 continue;
00399 }
00400
00401
00402 p = (struct pt2d *)bu_calloc(1, sizeof(struct pt2d), "pt2d");
00403 p->vu_p = vu_p;
00404 VMOVE(p->coord, np->coord);
00405 BU_LIST_MAGIC_SET(&p->l, NMG_PT2D_MAGIC);
00406
00407 BU_LIST_APPEND(&np->l, &p->l);
00408
00409 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00410 (void)bu_log( "vertexuse transformed\n");
00411 }
00412 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00413 (void)bu_log( "Done.\n");
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 struct bu_list *
00432 nmg_flatten_face(struct faceuse *fu, fastf_t *TformMat)
00433 {
00434 static const vect_t twoDspace = { 0.0, 0.0, 1.0 };
00435 struct bu_list *tbl2d;
00436 struct vertexuse *vu;
00437 struct loopuse *lu;
00438 struct edgeuse *eu;
00439 vect_t Normal;
00440
00441 NMG_CK_FACEUSE(fu);
00442
00443 tbl2d = (struct bu_list *)bu_calloc(1, sizeof(struct bu_list),
00444 "2D coordinate list");
00445
00446
00447
00448
00449
00450
00451 BU_LIST_INIT( tbl2d );
00452 BU_LIST_MAGIC_SET(tbl2d, NMG_TBL2D_MAGIC);
00453
00454
00455 NMG_GET_FU_NORMAL(Normal, fu);
00456 bn_mat_fromto( TformMat, Normal, twoDspace );
00457
00458 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00459 bn_mat_print( "TformMat", TformMat );
00460
00461
00462
00463 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
00464 if (rt_g.NMG_debug & DEBUG_TRI) {
00465 switch (lu->orientation) {
00466 case OT_NONE: bu_log("flattening OT_NONE loop\n"); break;
00467 case OT_SAME: bu_log("flattening OT_SAME loop\n"); break;
00468 case OT_OPPOSITE:bu_log("flattening OT_OPPOSITE loop\n"); break;
00469 case OT_UNSPEC: bu_log("flattening OT_UNSPEC loop\n"); break;
00470 case OT_BOOLPLACE:bu_log("flattening OT_BOOLPLACE loop\n"); break;
00471 default: bu_log("flattening bad orientation loop\n"); break;
00472 }
00473 }
00474 if (BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC) {
00475 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
00476 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00477 bu_log("vertex loop\n");
00478 map_vu_to_2d(vu, tbl2d, TformMat, fu);
00479
00480 } else if (BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_EDGEUSE_MAGIC) {
00481 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00482 bu_log("edge loop\n");
00483 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
00484 vu = eu->vu_p;
00485 if (rt_g.NMG_debug & DEBUG_TRI && flatten_debug)
00486 bu_log("(%g %g %g) -> (%g %g %g)\n",
00487 V3ARGS(vu->v_p->vg_p->coord),
00488 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord));
00489 map_vu_to_2d(vu, tbl2d, TformMat, fu);
00490 }
00491 } else rt_bomb("bad magic of loopuse child\n");
00492 }
00493
00494 return(tbl2d);
00495 }
00496
00497
00498
00499 static int
00500 is_convex(struct pt2d *a, struct pt2d *b, struct pt2d *c, const struct bn_tol *tol)
00501 {
00502 vect_t ab, bc, pv, N;
00503 double angle;
00504
00505 NMG_CK_PT2D(a);
00506 NMG_CK_PT2D(b);
00507 NMG_CK_PT2D(c);
00508
00509
00510 VSET(N, 0.0, 0.0, 1.0);
00511
00512
00513 VSUB2(ab, b->coord, a->coord);
00514
00515
00516 VCROSS(pv, N, ab);
00517
00518
00519 VSUB2(bc, c->coord, b->coord);
00520
00521
00522 angle = bn_angle_measure( bc, ab, pv );
00523
00524 if (rt_g.NMG_debug & DEBUG_TRI)
00525 bu_log("\tangle == %g tol angle: %g\n", angle, tol->perp);
00526
00527 return (angle > tol->perp && angle <= M_PI-tol->perp);
00528 }
00529
00530 #define POLY_SIDE 1
00531 #define HOLE_START 2
00532 #define POLY_START 3
00533 #define HOLE_END 4
00534 #define POLY_END 5
00535 #define HOLE_POINT 6
00536 #define POLY_POINT 7
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static int
00556 vtype2d(struct pt2d *v, struct bu_list *tbl2d, const struct bn_tol *tol)
00557 {
00558 struct pt2d *p, *n;
00559 struct loopuse *lu;
00560
00561 NMG_CK_TBL2D(tbl2d);
00562 NMG_CK_PT2D(v);
00563
00564
00565 p = PT2D_PREV(tbl2d, v);
00566 n = PT2D_NEXT(tbl2d, v);
00567
00568
00569 lu = nmg_find_lu_of_vu( v->vu_p );
00570
00571 if (p == n && n == v) {
00572
00573 if (lu->orientation == OT_SAME)
00574 return(POLY_POINT);
00575 else if (lu->orientation == OT_OPPOSITE)
00576 return(HOLE_POINT);
00577 }
00578
00579 if (P_GT_V(n, v) && P_GT_V(p, v)) {
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 if (p == n) {
00590 if (lu->orientation == OT_OPPOSITE)
00591 return(HOLE_END);
00592 else if (lu->orientation == OT_SAME)
00593 return(POLY_END);
00594 else {
00595 bu_log("%s: %d loopuse is not OT_SAME or OT_OPPOSITE\n",
00596 __FILE__, __LINE__);
00597 rt_bomb("bombing\n");
00598 }
00599 }
00600
00601 if (is_convex(p, v, n, tol)) return(POLY_END);
00602 else return(HOLE_END);
00603
00604 }
00605
00606 if (P_LT_V(n, v) && P_LT_V(p, v)) {
00607
00608
00609
00610
00611
00612
00613
00614
00615 if (p == n) {
00616 if (lu->orientation == OT_OPPOSITE)
00617 return(HOLE_START);
00618 else if (lu->orientation == OT_SAME)
00619 return(POLY_START);
00620 else {
00621 bu_log("%s: %d loopuse is not OT_SAME or OT_OPPOSITE\n",
00622 __FILE__, __LINE__);
00623 rt_bomb("bombing\n");
00624 }
00625 }
00626
00627 if (is_convex(p, v, n, tol))
00628 return(POLY_START);
00629 else
00630 return(HOLE_START);
00631 }
00632 if ( (P_GT_V(n, v) && P_LT_V(p, v)) ||
00633 (P_LT_V(n, v) && P_GT_V(p, v)) ) {
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 return(POLY_SIDE);
00644 }
00645 bu_log(
00646 "%s %d HELP! special case:\n(%g %g)->(%g %g)\n(%g %g)->(%g %g)\n",
00647 __FILE__, __LINE__,
00648 p->coord[X], p->coord[Y],
00649 v->coord[X], v->coord[Y],
00650 n->coord[X], n->coord[Y]);
00651
00652 return(0);
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 static void
00665 poly_start_vertex(struct pt2d *pt, struct bu_list *tbl2d, struct bu_list *tlist)
00666 {
00667 struct trap *new_trap;
00668
00669 NMG_CK_TBL2D(tbl2d);
00670 NMG_CK_PT2D(pt);
00671 if (rt_g.NMG_debug & DEBUG_TRI)
00672 bu_log( "%g %g is polygon start vertex\n",
00673 pt->coord[X], pt->coord[Y]);
00674
00675 new_trap = (struct trap *)bu_calloc(sizeof(struct trap), 1, "new poly_start trap");
00676 new_trap->top = pt;
00677 new_trap->bot = (struct pt2d *)NULL;
00678 new_trap->e_left = pt->vu_p->up.eu_p;
00679 new_trap->e_right = BU_LIST_PPREV_CIRC(edgeuse, pt->vu_p->up.eu_p);
00680 BU_LIST_MAGIC_SET(&new_trap->l, NMG_TRAP_MAGIC);
00681
00682
00683 BU_LIST_APPEND(tlist, &new_trap->l);
00684 NMG_CK_TRAP(new_trap);
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 static void
00699 poly_side_vertex(struct pt2d *pt, struct pt2d *tbl2d, struct bu_list *tlist)
00700 {
00701 struct trap *new_trap, *tp;
00702 struct edgeuse *upper_edge=NULL, *lower_edge=NULL;
00703 struct pt2d *pnext, *plast;
00704
00705 NMG_CK_TBL2D(tbl2d);
00706 NMG_CK_PT2D(pt);
00707 pnext = PT2D_NEXT(&tbl2d->l, pt);
00708 plast = PT2D_PREV(&tbl2d->l, pt);
00709 if (rt_g.NMG_debug & DEBUG_TRI) {
00710 bu_log( "%g %g is polygon side vertex\n",
00711 pt->coord[X], pt->coord[Y]);
00712 bu_log( "%g %g -> %g %g -> %g %g\n",
00713 plast->coord[X],
00714 plast->coord[Y],
00715 pt->coord[X], pt->coord[Y],
00716 pnext->coord[X],
00717 pnext->coord[Y]);
00718 }
00719
00720
00721 if (P_LT_V(plast, pt) && P_GT_V(pnext, pt)) {
00722
00723 upper_edge = pt->vu_p->up.eu_p;
00724 lower_edge = plast->vu_p->up.eu_p;
00725 } else if (P_LT_V(pnext, pt) && P_GT_V(plast, pt)) {
00726
00727 upper_edge = plast->vu_p->up.eu_p;
00728 lower_edge = pt->vu_p->up.eu_p;
00729 }
00730
00731 NMG_CK_EDGEUSE(upper_edge);
00732 NMG_CK_EDGEUSE(lower_edge);
00733
00734
00735
00736
00737
00738 for (BU_LIST_FOR(tp, trap, tlist)) {
00739 NMG_CK_TRAP(tp);
00740 NMG_CK_EDGEUSE(tp->e_left);
00741 NMG_CK_EDGEUSE(tp->e_right);
00742 if ((tp->e_left == upper_edge || tp->e_right == upper_edge) &&
00743 tp->bot == (struct pt2d *)NULL) {
00744 break;
00745 }
00746 }
00747
00748 if (BU_LIST_MAGIC_WRONG(&tp->l, NMG_TRAP_MAGIC))
00749 rt_bomb ("didn't find trapezoid parent\n");
00750
00751
00752 tp->bot = pt;
00753
00754
00755 new_trap = (struct trap *)bu_calloc(sizeof(struct trap), 1, "new side trap");
00756 BU_LIST_MAGIC_SET(&new_trap->l, NMG_TRAP_MAGIC);
00757 new_trap->top = pt;
00758 new_trap->bot = (struct pt2d *)NULL;
00759 if (tp->e_left == upper_edge) {
00760 new_trap->e_left = lower_edge;
00761 new_trap->e_right = tp->e_right;
00762 } else if (tp->e_right == upper_edge) {
00763 new_trap->e_right = lower_edge;
00764 new_trap->e_left = tp->e_left;
00765 } else
00766 rt_bomb("Why me? Always me!\n");
00767
00768 BU_LIST_INSERT(tlist, &new_trap->l);
00769 NMG_CK_TRAP(new_trap);
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 static void
00783 poly_end_vertex(struct pt2d *pt, struct bu_list *tbl2d, struct bu_list *tlist)
00784 {
00785 struct trap *tp;
00786 struct edgeuse *e_left, *e_right;
00787 struct pt2d *pprev;
00788
00789 NMG_CK_TBL2D(tbl2d);
00790 NMG_CK_PT2D(pt);
00791 if (rt_g.NMG_debug & DEBUG_TRI)
00792 bu_log( "%g %g is polygon end vertex\n",
00793 pt->coord[X], pt->coord[Y]);
00794
00795
00796 pprev = PT2D_PREV(tbl2d, pt);
00797 if (pprev == pt)
00798 rt_bomb("pprev == pt!\n");
00799
00800 e_left = pprev->vu_p->up.eu_p;
00801 e_right = pt->vu_p->up.eu_p;
00802
00803
00804
00805
00806 for (BU_LIST_FOR(tp, trap, tlist)) {
00807 NMG_CK_TRAP(tp);
00808 if (tp->e_left == e_left && tp->e_right == e_right && !tp->bot) {
00809 goto trap_found;
00810 } else if (tp->e_right == e_left && tp->e_left == e_right &&
00811 !tp->bot) {
00812
00813 e_right = tp->e_right;
00814 e_left = tp->e_left;
00815 goto trap_found;
00816 }
00817 }
00818
00819 rt_bomb("Didn't find trapezoid to close!\n");
00820
00821
00822 trap_found:
00823 tp->bot = pt;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 static void
00844 hole_start_vertex(struct pt2d *pt, struct bu_list *tbl2d, struct bu_list *tlist)
00845 {
00846 struct trap *tp, *new_trap;
00847 vect_t pv, ev, n;
00848 struct pt2d *e_pt, *next_pt;
00849
00850 NMG_CK_TBL2D(tbl2d);
00851 NMG_CK_PT2D(pt);
00852 if (rt_g.NMG_debug & DEBUG_TRI)
00853 bu_log( "%g %g is hole start vertex\n",
00854 pt->coord[X], pt->coord[Y]);
00855
00856
00857
00858
00859 for (BU_LIST_FOR(tp, trap, tlist)) {
00860 NMG_CK_TRAP(tp);
00861
00862
00863
00864 if (tp->bot) {
00865 if (rt_g.NMG_debug & DEBUG_TRI)
00866 bu_log("Trapezoid %g %g / %g %g completed... Skipping\n",
00867 tp->top->coord[X],
00868 tp->top->coord[Y],
00869 tp->bot->coord[X],
00870 tp->bot->coord[Y]);
00871 continue;
00872 }
00873
00874
00875
00876
00877
00878
00879 e_pt = find_pt2d(tbl2d, tp->e_left->vu_p);
00880 next_pt = find_pt2d(tbl2d,
00881 (BU_LIST_PNEXT_CIRC(edgeuse, tp->e_left))->vu_p);
00882
00883 if (e_pt->vu_p->v_p == pt->vu_p->v_p ||
00884 next_pt->vu_p->v_p == pt->vu_p->v_p)
00885 goto gotit;
00886
00887
00888
00889
00890
00891 e_pt = find_pt2d(tbl2d, tp->e_right->vu_p);
00892 next_pt = find_pt2d(tbl2d,
00893 (BU_LIST_PNEXT_CIRC(edgeuse, tp->e_right))->vu_p);
00894
00895 if (e_pt->vu_p->v_p == pt->vu_p->v_p ||
00896 next_pt->vu_p->v_p == pt->vu_p->v_p)
00897 goto gotit;
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 e_pt = find_pt2d(tbl2d, tp->e_left->vu_p);
00910 next_pt = find_pt2d(tbl2d,
00911 (BU_LIST_PNEXT_CIRC(edgeuse, tp->e_left))->vu_p);
00912 VSUB2(pv, pt->coord, e_pt->coord);
00913 VSUB2(ev, next_pt->coord, e_pt->coord);
00914 VCROSS(n, ev, pv);
00915 if (n[2] <= 0.0) {
00916 if (rt_g.NMG_debug & DEBUG_TRI)
00917 bu_log("Continue #1\n");
00918 continue;
00919 }
00920
00921 e_pt = find_pt2d(tbl2d, tp->e_right->vu_p);
00922 next_pt = find_pt2d(tbl2d,
00923 (BU_LIST_PNEXT_CIRC(edgeuse, tp->e_right))->vu_p);
00924 VSUB2(pv, pt->coord, e_pt->coord);
00925 VSUB2(ev, next_pt->coord, e_pt->coord);
00926 VCROSS(n, ev, pv);
00927 if (n[2] <= 0.0) {
00928 if (rt_g.NMG_debug & DEBUG_TRI)
00929 bu_log("Continue #2\n");
00930 continue;
00931 }
00932
00933 goto gotit;
00934
00935 }
00936
00937 bu_log("didn't find trapezoid for hole-start point at:\n\t%g %g %g\n",
00938 V3ARGS(pt->vu_p->v_p->vg_p->coord) );
00939
00940 nmg_stash_model_to_file("tri_lone_hole.g",
00941 nmg_find_model(&pt->vu_p->l.magic),
00942 "lone hole start");
00943
00944 rt_bomb("bombing\n");
00945 gotit:
00946
00947 tp->bot = pt;
00948
00949
00950 new_trap = (struct trap *)bu_calloc(sizeof(struct trap), 1, "New hole start trapezoids");
00951 new_trap->top = pt;
00952 new_trap->bot = (struct pt2d *)NULL;
00953 new_trap->e_left = tp->e_left;
00954 new_trap->e_right = BU_LIST_PPREV_CIRC(edgeuse, pt->vu_p->up.eu_p);
00955 BU_LIST_MAGIC_SET(&new_trap->l, NMG_TRAP_MAGIC);
00956 BU_LIST_APPEND(&tp->l, &new_trap->l);
00957
00958 new_trap = (struct trap *)bu_calloc(sizeof(struct trap), 1, "New hole start trapezoids");
00959 new_trap->top = pt;
00960 new_trap->bot = (struct pt2d *)NULL;
00961 new_trap->e_left = pt->vu_p->up.eu_p;
00962 new_trap->e_right = tp->e_right;
00963 BU_LIST_MAGIC_SET(&new_trap->l, NMG_TRAP_MAGIC);
00964 BU_LIST_APPEND(&tp->l, &new_trap->l);
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 static void
00981 hole_end_vertex(struct pt2d *pt, struct bu_list *tbl2d, struct bu_list *tlist)
00982 {
00983 struct edgeuse *eunext, *euprev;
00984 struct trap *tp, *tpnext, *tpprev;
00985
00986 NMG_CK_TBL2D(tbl2d);
00987 NMG_CK_PT2D(pt);
00988 if (rt_g.NMG_debug & DEBUG_TRI)
00989 bu_log( "%g %g is hole end vertex\n",
00990 pt->coord[X], pt->coord[Y]);
00991
00992
00993 eunext = pt->vu_p->up.eu_p;
00994 euprev = BU_LIST_PPREV_CIRC(edgeuse, eunext);
00995 tpnext = tpprev = (struct trap *)NULL;
00996
00997 if (rt_g.NMG_debug & DEBUG_TRI) {
00998 print_2d_eu("eunext", eunext, tbl2d);
00999 print_2d_eu("euprev", euprev, tbl2d);
01000 }
01001
01002 for (BU_LIST_FOR(tp, trap, tlist)) {
01003 NMG_CK_TRAP(tp);
01004
01005
01006
01007 NMG_CK_TRAP(tp);
01008
01009 if (tp->bot) {
01010 #if 0
01011 if (rt_g.NMG_debug & DEBUG_TRI) {
01012 print_trap(tp, tbl2d);
01013 bu_log("Completed... Skipping\n");
01014 }
01015 #endif
01016 continue;
01017 } else {
01018 if (rt_g.NMG_debug & DEBUG_TRI)
01019 print_trap(tp, tbl2d);
01020 }
01021
01022 if (tp->e_left == eunext || tp->e_right == eunext) {
01023 if (rt_g.NMG_debug & DEBUG_TRI)
01024 bu_log("Found tpnext\n");
01025 tpnext = tp;
01026 }
01027
01028 if (tp->e_right == euprev || tp->e_left == euprev) {
01029 if (rt_g.NMG_debug & DEBUG_TRI)
01030 bu_log("Found tpprev\n");
01031 tpprev = tp;
01032 }
01033 if (tpnext && tpprev)
01034 goto gotem;
01035 }
01036
01037 rt_bomb("couldn't find both trapezoids of hole closing vertex\n");
01038 gotem:
01039 NMG_CK_TRAP(tpnext);
01040 NMG_CK_TRAP(tpprev);
01041
01042
01043 tpnext->bot = pt;
01044 tpprev->bot = pt;
01045
01046
01047
01048 tp = (struct trap *)bu_calloc(1, sizeof(struct pt2d), "pt2d struct");
01049 tp->top = pt;
01050 tp->bot = (struct pt2d *)NULL;
01051 if (tpnext->e_left == eunext) {
01052 tp->e_right = tpnext->e_right;
01053 tp->e_left = tpprev->e_left;
01054 } else if (tpnext->e_right == eunext) {
01055 tp->e_left = tpnext->e_left;
01056 tp->e_right = tpprev->e_right;
01057 } else
01058 rt_bomb("Which is my left and which is my right?\n");
01059
01060 BU_LIST_MAGIC_SET(&tp->l, NMG_TRAP_MAGIC);
01061 BU_LIST_APPEND(&tpprev->l, &tp->l);
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071 static void
01072 nmg_trap_face(struct bu_list *tbl2d, struct bu_list *tlist, const struct bn_tol *tol)
01073 {
01074 struct pt2d *pt;
01075
01076 NMG_CK_TBL2D(tbl2d);
01077
01078 for (BU_LIST_FOR(pt, pt2d, tbl2d)) {
01079 NMG_CK_PT2D(pt);
01080 switch(vtype2d(pt, tbl2d, tol)) {
01081 case POLY_SIDE:
01082 poly_side_vertex(pt, (struct pt2d *)tbl2d, tlist);
01083 break;
01084 case HOLE_START:
01085 hole_start_vertex(pt, tbl2d, tlist);
01086 break;
01087 case POLY_START:
01088 poly_start_vertex(pt, tbl2d, tlist);
01089 break;
01090 case HOLE_END:
01091 hole_end_vertex(pt, tbl2d, tlist);
01092 break;
01093 case POLY_END:
01094 poly_end_vertex(pt, tbl2d, tlist);
01095 break;
01096 default:
01097 bu_log( "%g %g is UNKNOWN type vertex %s %d\n",
01098 pt->coord[X], pt->coord[Y],
01099 __FILE__, __LINE__);
01100 break;
01101 }
01102 }
01103
01104 }
01105
01106
01107 static void
01108 map_new_vertexuse(struct bu_list *tbl2d, struct vertexuse *vu_p)
01109 {
01110 struct vertexuse *vu;
01111 struct pt2d *p, *new_pt2d;
01112
01113 NMG_CK_TBL2D(tbl2d);
01114 NMG_CK_VERTEXUSE(vu_p);
01115
01116
01117 if ( (p = find_pt2d(tbl2d, vu_p)) ) {
01118 if (rt_g.NMG_debug & DEBUG_TRI)
01119 bu_log("%s %d map_new_vertexuse() vertexuse already mapped!\n",
01120 __FILE__, __LINE__);
01121 return;
01122 }
01123
01124 new_pt2d = (struct pt2d *)
01125 bu_calloc(1, sizeof(struct pt2d), "pt2d struct");
01126
01127
01128 for ( BU_LIST_FOR(vu, vertexuse, &vu_p->v_p->vu_hd) ) {
01129 NMG_CK_VERTEXUSE(vu);
01130 if (! (p=find_pt2d(tbl2d, vu)) )
01131 continue;
01132
01133
01134 new_pt2d->vu_p = vu_p;
01135 VMOVE(new_pt2d->coord, p->coord);
01136 BU_LIST_MAGIC_SET(&new_pt2d->l, NMG_PT2D_MAGIC);
01137 BU_LIST_APPEND(&p->l, &new_pt2d->l);
01138 return;
01139 }
01140
01141 rt_bomb("Couldn't find mapped vertexuse of vertex!\n");
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151 static void
01152 pick_edges(struct vertex *v, struct vertexuse **vu_first, int *min_dir, struct vertexuse **vu_last, int *max_dir, struct faceuse *fu, const struct bn_tol *tol, fastf_t *dir)
01153
01154
01155
01156
01157
01158
01159 {
01160 struct vertexuse *vu;
01161 struct edgeuse *eu_next, *eu_last;
01162 struct vertexuse *vu_next, *vu_prev;
01163 double dot_max = -2.0;
01164 double dot_min = 2.0;
01165 double vu_dot;
01166 double eu_length_sq;
01167 vect_t eu_dir;
01168 if (rt_g.NMG_debug & DEBUG_TRI)
01169 bu_log("\t pick_edges(v:(%g %g %g) dir:(%g %g %g))\n",
01170 V3ARGS(v->vg_p->coord), V3ARGS(dir));
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 *vu_last = *vu_first = (struct vertexuse *)NULL;
01182 for (BU_LIST_FOR(vu, vertexuse, &v->vu_hd)) {
01183 NMG_CK_VERTEXUSE(vu);
01184 NMG_CK_VERTEX(vu->v_p);
01185 NMG_CK_VERTEX_G(vu->v_p->vg_p);
01186
01187 if (vu->v_p != v)
01188 rt_bomb("vertexuse does not acknoledge parents\n");
01189
01190 if (nmg_find_fu_of_vu(vu) != fu ||
01191 *vu->up.magic_p == NMG_LOOPUSE_MAGIC) {
01192 if (rt_g.NMG_debug & DEBUG_TRI)
01193 bu_log("\t\tskipping irrelevant vertexuse\n");
01194 continue;
01195 }
01196
01197 NMG_CK_EDGEUSE(vu->up.eu_p);
01198
01199
01200 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, vu->up.eu_p);
01201 NMG_CK_EDGEUSE(eu_next);
01202 vu_next = eu_next->vu_p;
01203 NMG_CK_VERTEXUSE(vu_next);
01204 NMG_CK_VERTEX(vu_next->v_p);
01205 NMG_CK_VERTEX_G(vu_next->v_p->vg_p);
01206 VSUB2(eu_dir, vu_next->v_p->vg_p->coord, vu->v_p->vg_p->coord);
01207 eu_length_sq = MAGSQ(eu_dir);
01208 VUNITIZE(eu_dir);
01209
01210 if (rt_g.NMG_debug & DEBUG_TRI)
01211 bu_log("\t\tchecking forward edgeuse to %g %g %g\n",
01212 V3ARGS(vu_next->v_p->vg_p->coord) );
01213
01214 if (eu_length_sq >= SMALL_FASTF) {
01215 if ((vu_dot = VDOT(eu_dir, dir)) > dot_max) {
01216 if (rt_g.NMG_debug & DEBUG_TRI) {
01217 bu_log("\t\t\teu_dir %g %g %g\n",
01218 V3ARGS(eu_dir));
01219
01220 bu_log("\t\t\tnew_last/max 0x%08x %g %g %g -> %g %g %g vdot %g\n",
01221 vu,
01222 V3ARGS(vu->v_p->vg_p->coord),
01223 V3ARGS(vu_next->v_p->vg_p->coord),
01224 vu_dot);
01225 }
01226 dot_max = vu_dot;
01227 *vu_last = vu;
01228 *max_dir = 1;
01229 }
01230 if (vu_dot < dot_min) {
01231 if (rt_g.NMG_debug & DEBUG_TRI) {
01232 bu_log("\t\t\teu_dir %g %g %g\n", V3ARGS(eu_dir));
01233 bu_log("\t\t\tnew_first/min 0x%08x %g %g %g -> %g %g %g vdot %g\n",
01234 vu,
01235 V3ARGS(vu->v_p->vg_p->coord),
01236 V3ARGS(vu_next->v_p->vg_p->coord),
01237 vu_dot);
01238 }
01239
01240 dot_min = vu_dot;
01241 *vu_first = vu;
01242 *min_dir = 1;
01243 }
01244 }
01245
01246
01247
01248
01249
01250
01251 eu_last = BU_LIST_PPREV_CIRC(edgeuse, vu->up.eu_p);
01252 NMG_CK_EDGEUSE(eu_last);
01253 vu_prev = eu_last->vu_p;
01254 NMG_CK_VERTEXUSE(vu_prev);
01255 NMG_CK_VERTEX(vu_prev->v_p);
01256 NMG_CK_VERTEX_G(vu_prev->v_p->vg_p);
01257
01258
01259
01260 VSUB2(eu_dir, vu_prev->v_p->vg_p->coord, vu->v_p->vg_p->coord);
01261 eu_length_sq = MAGSQ(eu_dir);
01262 VUNITIZE(eu_dir);
01263
01264 if (rt_g.NMG_debug & DEBUG_TRI)
01265 bu_log("\t\tchecking reverse edgeuse to %g %g %g\n",
01266 V3ARGS(vu_prev->v_p->vg_p->coord) );
01267
01268 if (eu_length_sq >= SMALL_FASTF) {
01269 if ((vu_dot = VDOT(eu_dir, dir)) > dot_max) {
01270 if (rt_g.NMG_debug & DEBUG_TRI) {
01271 bu_log("\t\t\t-eu_dir %g %g %g\n",
01272 V3ARGS(eu_dir));
01273 bu_log("\t\t\tnew_last/max 0x%08x %g %g %g <- %g %g %g vdot %g\n",
01274 vu,
01275 V3ARGS(vu->v_p->vg_p->coord),
01276 V3ARGS(vu_prev->v_p->vg_p->coord),
01277 vu_dot);
01278 }
01279 dot_max = vu_dot;
01280 *vu_last = vu;
01281 *max_dir = -1;
01282 }
01283 if (vu_dot < dot_min) {
01284 if (rt_g.NMG_debug & DEBUG_TRI) {
01285 bu_log("\t\t\teu_dir %g %g %g\n", V3ARGS(eu_dir));
01286 bu_log("\t\t\tnew_first/min 0x%08x %g %g %g <- %g %g %g vdot %g\n",
01287 vu,
01288 V3ARGS(vu->v_p->vg_p->coord),
01289 V3ARGS(vu_prev->v_p->vg_p->coord),
01290 vu_dot);
01291 }
01292 dot_min = vu_dot;
01293 *vu_first = vu;
01294 *min_dir = -1;
01295 }
01296 }
01297 }
01298
01299 }
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 struct edgeuse *
01311 pick_eu(struct edgeuse *eu_p, struct faceuse *fu, fastf_t *dir, int find_max)
01312 {
01313 struct edgeuse *eu, *keep_eu=NULL, *eu_next;
01314 int go_radial_not_mate = 0;
01315 double dot_limit;
01316 double euleft_dot;
01317 vect_t left, eu_vect;
01318
01319 if (rt_g.NMG_debug & DEBUG_TRI)
01320 bu_log("\t pick_eu(%g %g %g <-> %g %g %g, dir:%g %g %g, %s)\n",
01321 V3ARGS(eu_p->vu_p->v_p->vg_p->coord ),
01322 V3ARGS(eu_p->eumate_p->vu_p->v_p->vg_p->coord ),
01323 V3ARGS(dir), (find_max==0?"find min":"find max") );
01324
01325 if (find_max) dot_limit = -2.0;
01326 else dot_limit = 2.0;
01327
01328
01329 eu = eu_p;
01330 do {
01331 if (nmg_find_fu_of_eu(eu) == fu) {
01332
01333 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, eu);
01334 VSUB2(eu_vect, eu_next->vu_p->v_p->vg_p->coord,
01335 eu->vu_p->v_p->vg_p->coord);
01336 VUNITIZE(eu_vect);
01337
01338
01339 if (nmg_find_eu_leftvec(left, eu)) {
01340 bu_log("%s %d: edgeuse no longer in faceuse?\n", __FILE__, __LINE__);
01341 rt_bomb("bombing");
01342 }
01343
01344 euleft_dot = VDOT(left, dir);
01345
01346 if (rt_g.NMG_debug & DEBUG_TRI)
01347 bu_log("\t\tchecking: %g %g %g -> %g %g %g left vdot:%g\n",
01348 V3ARGS(eu->vu_p->v_p->vg_p->coord),
01349 V3ARGS(eu_next->vu_p->v_p->vg_p->coord),
01350 euleft_dot);
01351
01352
01353
01354
01355
01356 if (find_max) {
01357 if (euleft_dot > dot_limit) {
01358 dot_limit = euleft_dot;
01359 keep_eu = eu;
01360 if (rt_g.NMG_debug & DEBUG_TRI)
01361 bu_log("\t\tnew max\n");
01362 }
01363 } else {
01364 if (euleft_dot < dot_limit) {
01365 dot_limit = euleft_dot;
01366 keep_eu = eu;
01367 if (rt_g.NMG_debug & DEBUG_TRI)
01368 bu_log("\t\tnew min\n");
01369 }
01370 }
01371 }
01372
01373 if (go_radial_not_mate) eu = eu->eumate_p;
01374 else eu = eu->radial_p;
01375 go_radial_not_mate = ! go_radial_not_mate;
01376
01377 } while ( eu != eu_p );
01378
01379 if (rt_g.NMG_debug & DEBUG_TRI)
01380 bu_log("\t\tpick_eu() returns %g %g %g -> %g %g %g\n\t\t\tbecause vdot(left) = %g\n",
01381 V3ARGS(keep_eu->vu_p->v_p->vg_p->coord),
01382 V3ARGS(keep_eu->eumate_p->vu_p->v_p->vg_p->coord),
01383 dot_limit);
01384
01385 return keep_eu;
01386 }
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 void
01419 nmg_find_first_last_use_of_v_in_fu(struct vertex *v, struct vertexuse **first_vu, struct vertexuse **last_vu, fastf_t *dir, struct faceuse *fu, const struct bn_tol *tol)
01420 {
01421 struct vertexuse *vu_first, *vu_last;
01422 int max_dir, min_dir;
01423 struct edgeuse *eu_first, *eu_last, *eu_p=NULL;
01424
01425 NMG_CK_VERTEX(v);
01426 NMG_CK_FACEUSE(fu);
01427 if (first_vu == (struct vertexuse **)(NULL)) {
01428 bu_log("%s: %d first_vu is null ptr\n", __FILE__, __LINE__);
01429 rt_bomb("terminating\n");
01430 }
01431 if (last_vu == (struct vertexuse **)(NULL)) {
01432 bu_log("%s: %d last_vu is null ptr\n", __FILE__, __LINE__);
01433 rt_bomb("terminating\n");
01434 }
01435
01436 VUNITIZE(dir);
01437
01438 if (rt_g.NMG_debug & DEBUG_TRI)
01439 bu_log("\t nmg_find_first(v:(%g %g %g) dir:(%g %g %g))\n",
01440 V3ARGS(v->vg_p->coord), V3ARGS(dir));
01441
01442
01443 pick_edges(v, &vu_first, &min_dir, &vu_last, &max_dir, fu, tol, dir);
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 NMG_CK_VERTEXUSE(vu_first);
01462 switch (min_dir) {
01463 case -1:
01464 eu_p = BU_LIST_PPREV_CIRC(edgeuse, vu_first->up.eu_p);
01465 break;
01466 case 1:
01467 eu_p = vu_first->up.eu_p;
01468 break;
01469 default:
01470 rt_bomb("bad max_dir\n");
01471 break;
01472 }
01473
01474 NMG_CK_EDGEUSE(eu_p);
01475 NMG_CK_VERTEXUSE(eu_p->vu_p);
01476
01477 eu_first = pick_eu(eu_p, fu, dir, 0);
01478 NMG_CK_EDGEUSE(eu_first);
01479 NMG_CK_VERTEXUSE(eu_first->vu_p);
01480 NMG_CK_VERTEX(eu_first->vu_p->v_p);
01481 NMG_CK_VERTEX_G(eu_first->vu_p->v_p->vg_p);
01482
01483 if (rt_g.NMG_debug & DEBUG_TRI)
01484 bu_log("\t first_eu: %g %g %g -> %g %g %g\n",
01485 V3ARGS(eu_first->vu_p->v_p->vg_p->coord),
01486 V3ARGS(eu_first->eumate_p->vu_p->v_p->vg_p->coord));
01487
01488
01489 if (eu_first->vu_p->v_p == v)
01490
01491
01492
01493
01494 *first_vu = eu_first->vu_p;
01495 else {
01496
01497
01498
01499
01500 NMG_CK_EDGEUSE(eu_first->eumate_p);
01501 NMG_CK_VERTEXUSE(eu_first->eumate_p->vu_p);
01502 NMG_CK_VERTEX(eu_first->eumate_p->vu_p->v_p);
01503
01504 if (eu_first->eumate_p->vu_p->v_p == v) {
01505 eu_p = BU_LIST_PNEXT_CIRC(edgeuse, eu_first);
01506 NMG_CK_EDGEUSE(eu_p);
01507 NMG_CK_VERTEXUSE(eu_p->vu_p);
01508 *first_vu = eu_p->vu_p;
01509 } else {
01510 bu_log("I got eu_first: %g %g %g -> %g %g %g but...\n",
01511 V3ARGS(eu_first->vu_p->v_p->vg_p->coord),
01512 V3ARGS(eu_first->eumate_p->vu_p->v_p->vg_p->coord));
01513 rt_bomb("I can't find the right vertex\n");
01514 }
01515 }
01516
01517
01518 NMG_CK_VERTEXUSE(vu_last);
01519 switch (max_dir) {
01520 case -1:
01521 eu_p = BU_LIST_PPREV_CIRC(edgeuse, vu_last->up.eu_p);
01522 break;
01523 case 1:
01524 eu_p = vu_last->up.eu_p;
01525 break;
01526 default:
01527 rt_bomb("bad min_dir\n");
01528 break;
01529 }
01530
01531 NMG_CK_EDGEUSE(eu_p);
01532 NMG_CK_VERTEXUSE(eu_p->vu_p);
01533
01534 eu_last = pick_eu(eu_p, fu, dir, 1);
01535
01536 NMG_CK_EDGEUSE(eu_last);
01537 NMG_CK_VERTEXUSE(eu_last->vu_p);
01538 NMG_CK_VERTEX(eu_last->vu_p->v_p);
01539 if (rt_g.NMG_debug & DEBUG_TRI)
01540 bu_log("\t last_eu: %g %g %g -> %g %g %g\n",
01541 V3ARGS(eu_last->vu_p->v_p->vg_p->coord),
01542 V3ARGS(eu_last->eumate_p->vu_p->v_p->vg_p->coord));
01543
01544
01545
01546 if (eu_last->vu_p->v_p == v)
01547
01548
01549
01550
01551 *last_vu = eu_last->vu_p;
01552 else {
01553
01554
01555
01556
01557 NMG_CK_EDGEUSE(eu_last->eumate_p);
01558 NMG_CK_VERTEXUSE(eu_last->eumate_p->vu_p);
01559 NMG_CK_VERTEX(eu_last->eumate_p->vu_p->v_p);
01560
01561 if (eu_last->eumate_p->vu_p->v_p == v) {
01562 eu_p = BU_LIST_PNEXT_CIRC(edgeuse, eu_last);
01563 NMG_CK_EDGEUSE(eu_p);
01564 NMG_CK_VERTEXUSE(eu_p->vu_p);
01565 *last_vu = eu_p->vu_p;
01566 } else {
01567 bu_log("I got eu_last: %g %g %g -> %g %g %g but...\n",
01568 V3ARGS(eu_last->vu_p->v_p->vg_p->coord),
01569 V3ARGS(eu_last->eumate_p->vu_p->v_p->vg_p->coord));
01570 rt_bomb("I can't find the right vertex\n");
01571 }
01572 }
01573
01574
01575 NMG_CK_VERTEXUSE(*first_vu);
01576 NMG_CK_VERTEXUSE(*last_vu);
01577 }
01578
01579 static void
01580 pick_pt2d_for_cutjoin(struct bu_list *tbl2d, struct pt2d **p1, struct pt2d **p2, const struct bn_tol *tol)
01581 {
01582 struct vertexuse *cut_vu1, *cut_vu2, *junk_vu;
01583 struct faceuse *fu;
01584 vect_t dir;
01585
01586 NMG_CK_TBL2D(tbl2d);
01587
01588 if (rt_g.NMG_debug & DEBUG_TRI)
01589 bu_log("\tpick_pt2d_for_cutjoin()\n");
01590
01591 BN_CK_TOL(tol);
01592 NMG_CK_PT2D(*p1);
01593 NMG_CK_PT2D(*p2);
01594 NMG_CK_VERTEXUSE((*p1)->vu_p);
01595 NMG_CK_VERTEXUSE((*p2)->vu_p);
01596
01597 cut_vu1 = (*p1)->vu_p;
01598 cut_vu2 = (*p2)->vu_p;
01599
01600 NMG_CK_VERTEX(cut_vu1->v_p);
01601 NMG_CK_VERTEX_G(cut_vu1->v_p->vg_p);
01602 NMG_CK_VERTEX(cut_vu2->v_p);
01603 NMG_CK_VERTEX_G(cut_vu2->v_p->vg_p);
01604
01605
01606 VSUB2(dir, cut_vu2->v_p->vg_p->coord,
01607 cut_vu1->v_p->vg_p->coord);
01608
01609 if (rt_g.NMG_debug & DEBUG_TRI)
01610 VPRINT("\t\tdir", dir);
01611
01612 if ( ! (fu = nmg_find_fu_of_vu(cut_vu1)) ) {
01613 bu_log("%s: %d no faceuse parent of vu\n", __FILE__, __LINE__);
01614 rt_bomb("Bye now\n");
01615 }
01616
01617 nmg_find_first_last_use_of_v_in_fu((*p1)->vu_p->v_p,
01618 &junk_vu, &cut_vu1, dir, fu, tol);
01619
01620 NMG_CK_VERTEXUSE(junk_vu);
01621 NMG_CK_VERTEXUSE(cut_vu1);
01622 *p1 = find_pt2d(tbl2d, cut_vu1);
01623
01624 if (rt_g.NMG_debug & DEBUG_TRI) {
01625 struct pt2d *pj, *pj_n, *p1_n;
01626
01627 pj = find_pt2d(tbl2d, junk_vu);
01628 pj_n = PT2D_NEXT(tbl2d, pj);
01629
01630 p1_n = PT2D_NEXT(tbl2d, (*p1));
01631
01632 bu_log("\tp1 pick %g %g -> %g %g (first)\n\t\t%g %g -> %g %g (last)\n",
01633 pj->coord[0], pj->coord[1],
01634 pj_n->coord[0], pj_n->coord[1],
01635 (*p1)->coord[0], (*p1)->coord[1],
01636 p1_n->coord[0], p1_n->coord[1]);
01637 }
01638
01639
01640 nmg_find_first_last_use_of_v_in_fu((*p2)->vu_p->v_p,
01641 &cut_vu2, &junk_vu, dir, fu, tol);
01642
01643
01644 *p2 = find_pt2d(tbl2d, cut_vu2);
01645 if (rt_g.NMG_debug & DEBUG_TRI) {
01646 struct pt2d *pj, *pj_n, *p2_n;
01647
01648 pj = find_pt2d(tbl2d, junk_vu);
01649 pj_n = PT2D_NEXT(tbl2d, pj);
01650
01651 p2_n = PT2D_NEXT(tbl2d, (*p2));
01652 bu_log("\tp2 pick %g %g -> %g %g (first)\n\t\t%g %g -> %g %g (last)\n",
01653 (*p2)->coord[0], (*p2)->coord[1],
01654 p2_n->coord[0], p2_n->coord[1],
01655 pj->coord[0], pj->coord[1],
01656 pj_n->coord[0], pj_n->coord[1]);
01657 }
01658
01659 }
01660
01661 static void join_mapped_loops(struct bu_list *tbl2d, struct pt2d *p1, struct pt2d *p2, const int *color, const struct bn_tol *tol);
01662
01663
01664
01665
01666
01667
01668
01669
01670 static struct pt2d *
01671 cut_mapped_loop(struct bu_list *tbl2d, struct pt2d *p1, struct pt2d *p2, const int *color, const struct bn_tol *tol, int void_ok)
01672 {
01673 struct loopuse *new_lu;
01674 struct loopuse *old_lu;
01675 struct edgeuse *eu;
01676
01677 NMG_CK_TBL2D(tbl2d);
01678 BN_CK_TOL(tol);
01679 NMG_CK_PT2D(p1);
01680 NMG_CK_PT2D(p2);
01681 NMG_CK_VERTEXUSE(p1->vu_p);
01682 NMG_CK_VERTEXUSE(p2->vu_p);
01683
01684 if (rt_g.NMG_debug & DEBUG_TRI)
01685 bu_log("\tcutting loop @ %g %g -> %g %g\n",
01686 p1->coord[X], p1->coord[Y],
01687 p2->coord[X], p2->coord[Y]);
01688
01689 if (p1->vu_p->up.eu_p->up.lu_p != p2->vu_p->up.eu_p->up.lu_p) {
01690 bu_log("parent loops are not the same %s %d\n", __FILE__, __LINE__);
01691 rt_bomb("cut_mapped_loop() goodnight 1\n");
01692 }
01693
01694 pick_pt2d_for_cutjoin(tbl2d, &p1, &p2, tol);
01695
01696 if (p1->vu_p->up.eu_p->up.lu_p != p2->vu_p->up.eu_p->up.lu_p) {
01697 if (void_ok) {
01698 if(rt_g.NMG_debug)
01699 bu_log("cut_mapped_loop() parent loops are not the same %s %d, trying join\n", __FILE__, __LINE__);
01700 join_mapped_loops(tbl2d, p1, p2, color, tol);
01701 return (struct pt2d *)NULL;
01702 } else {
01703 char buf[80];
01704 char name[32];
01705 static int iter=0;
01706 vect_t cut_vect, cut_start, cut_end;
01707 FILE *fd;
01708
01709 bu_log("parent loops are not the same %s %d\n",
01710 __FILE__, __LINE__);
01711
01712
01713 sprintf(buf, "cut %g %g %g -> %g %g %g\n",
01714 V3ARGS(p1->vu_p->v_p->vg_p->coord),
01715 V3ARGS(p2->vu_p->v_p->vg_p->coord) );
01716
01717 sprintf(name, "bad_tri_cut%d.g", iter++);
01718 if ((fd=fopen("bad_tri_cut.pl", "w")) == (FILE *)NULL)
01719 rt_bomb("cut_mapped_loop() goodnight 2\n");
01720
01721 VSUB2(cut_vect, p2->vu_p->v_p->vg_p->coord, p1->vu_p->v_p->vg_p->coord);
01722
01723 VJOIN1(cut_end, p2->vu_p->v_p->vg_p->coord, 0.5, cut_vect);
01724
01725 VJOIN1(cut_start, p1->vu_p->v_p->vg_p->coord, -0.25, cut_vect);
01726
01727 pl_color(fd, 100, 100, 100);
01728 pdv_3line(fd, cut_start, p1->vu_p->v_p->vg_p->coord);
01729 pl_color(fd, 255, 255, 255);
01730 pdv_3line(fd, p1->vu_p->v_p->vg_p->coord, p2->vu_p->v_p->vg_p->coord);
01731 pl_color(fd, 100, 100, 100);
01732 pdv_3line(fd, p2->vu_p->v_p->vg_p->coord, cut_end);
01733
01734 (void)fclose(fd);
01735 nmg_stash_model_to_file( "bad_tri_cut.g",
01736 nmg_find_model(&p1->vu_p->l.magic), buf );
01737
01738 rt_bomb("cut_mapped_loop() goodnight 2\n");
01739 }
01740 }
01741
01742 if (plot_fd) {
01743 pl_color(plot_fd, V3ARGS(color) );
01744 pdv_3line(plot_fd, p1->coord, p2->coord);
01745 }
01746
01747 old_lu = p1->vu_p->up.eu_p->up.lu_p;
01748 NMG_CK_LOOPUSE(old_lu);
01749 new_lu = nmg_cut_loop(p1->vu_p, p2->vu_p);
01750 NMG_CK_LOOPUSE(new_lu);
01751 NMG_CK_LOOP(new_lu->l_p);
01752 nmg_loop_g(new_lu->l_p, tol);
01753
01754
01755
01756
01757
01758
01759
01760 eu = BU_LIST_PPREV_CIRC(edgeuse, &new_lu->down_hd);
01761 NMG_CK_EDGEUSE(eu);
01762
01763
01764
01765
01766 if( p1->vu_p->a.magic_p && *p1->vu_p->a.magic_p == NMG_VERTEXUSE_A_PLANE_MAGIC )
01767 {
01768 struct vertexuse *vu;
01769 struct faceuse *fu;
01770 struct loopuse *lu;
01771 vect_t ot_same_normal;
01772 vect_t ot_opposite_normal;
01773
01774
01775 VMOVE( ot_same_normal , p1->vu_p->a.plane_p->N );
01776 fu = nmg_find_fu_of_vu( p1->vu_p );
01777 NMG_CK_FACEUSE( fu );
01778 if( fu->orientation == OT_OPPOSITE )
01779 VREVERSE( ot_same_normal , ot_same_normal )
01780
01781 VREVERSE( ot_opposite_normal , ot_same_normal );
01782
01783
01784 for( BU_LIST_FOR( vu , vertexuse , &p1->vu_p->v_p->vu_hd ) )
01785 {
01786 if( vu->a.magic_p )
01787 continue;
01788
01789 lu = nmg_find_lu_of_vu( vu );
01790 if( lu != old_lu && lu != old_lu->lumate_p &&
01791 lu != new_lu && lu != new_lu->lumate_p )
01792 continue;
01793
01794
01795 fu = nmg_find_fu_of_vu( vu );
01796 if( fu->orientation == OT_SAME )
01797 nmg_vertexuse_nv( vu , ot_same_normal );
01798 else if( fu->orientation == OT_OPPOSITE )
01799 nmg_vertexuse_nv( vu , ot_opposite_normal );
01800 }
01801 }
01802 if( p2->vu_p->a.magic_p && *p2->vu_p->a.magic_p == NMG_VERTEXUSE_A_PLANE_MAGIC )
01803 {
01804 struct vertexuse *vu;
01805 struct faceuse *fu;
01806 struct loopuse *lu;
01807 vect_t ot_same_normal;
01808 vect_t ot_opposite_normal;
01809
01810
01811 VMOVE( ot_same_normal , p2->vu_p->a.plane_p->N );
01812 fu = nmg_find_fu_of_vu( p2->vu_p );
01813 NMG_CK_FACEUSE( fu );
01814 if( fu->orientation == OT_OPPOSITE )
01815 VREVERSE( ot_same_normal , ot_same_normal )
01816
01817 VREVERSE( ot_opposite_normal , ot_same_normal );
01818
01819
01820 for( BU_LIST_FOR( vu , vertexuse , &p2->vu_p->v_p->vu_hd ) )
01821 {
01822 if( vu->a.magic_p )
01823 continue;
01824
01825 lu = nmg_find_lu_of_vu( vu );
01826 if( lu != old_lu && lu != old_lu->lumate_p &&
01827 lu != new_lu && lu != new_lu->lumate_p )
01828 continue;
01829
01830
01831 fu = nmg_find_fu_of_vu( vu );
01832 if( fu->orientation == OT_SAME )
01833 nmg_vertexuse_nv( vu , ot_same_normal );
01834 else if( fu->orientation == OT_OPPOSITE )
01835 nmg_vertexuse_nv( vu , ot_opposite_normal );
01836 }
01837 }
01838
01839
01840 map_new_vertexuse(tbl2d, eu->vu_p);
01841
01842
01843 NMG_CK_EDGEUSE(eu->radial_p);
01844 map_new_vertexuse(tbl2d, eu->radial_p->vu_p);
01845
01846 eu = BU_LIST_PPREV_CIRC( edgeuse, &(p1->vu_p->up.eu_p->l));
01847 return find_pt2d(tbl2d, eu->vu_p);
01848 }
01849
01850
01851
01852
01853
01854
01855 static void
01856 join_mapped_loops(struct bu_list *tbl2d, struct pt2d *p1, struct pt2d *p2, const int *color, const struct bn_tol *tol)
01857 {
01858 struct vertexuse *vu1, *vu2;
01859 struct vertexuse *vu;
01860 struct edgeuse *eu;
01861 struct loopuse *lu;
01862
01863 NMG_CK_TBL2D(tbl2d);
01864 NMG_CK_PT2D(p1);
01865 NMG_CK_PT2D(p2);
01866 BN_CK_TOL(tol);
01867
01868 vu1 = p1->vu_p;
01869 vu2 = p2->vu_p;
01870
01871 NMG_CK_VERTEXUSE(vu1);
01872 NMG_CK_VERTEXUSE(vu2);
01873
01874 if (rt_g.NMG_debug & DEBUG_TRI)
01875 bu_log("join_mapped_loops()\n");
01876
01877
01878 if (p1 == p2) {
01879 bu_log("%s %d: Attempting to join loop to itself at (%g %g %g)?\n",
01880 __FILE__, __LINE__,
01881 V3ARGS(p1->vu_p->v_p->vg_p->coord) );
01882 rt_bomb("bombing\n");
01883 } else if (p1->vu_p->up.eu_p->up.lu_p == p2->vu_p->up.eu_p->up.lu_p) {
01884 bu_log("parent loops are the same %s %d\n", __FILE__, __LINE__);
01885 rt_bomb("goodnight\n");
01886 }
01887
01888 if (p1->vu_p->v_p == p2->vu_p->v_p) {
01889 #if 1
01890 if (rt_g.NMG_debug & DEBUG_TRI)
01891 bu_log("Joining two loops that share a vertex at (%g %g %g)\n",
01892 V3ARGS(p1->vu_p->v_p->vg_p->coord) );
01893 (void)nmg_join_2loops(p1->vu_p, p2->vu_p);
01894 #else
01895 if (rt_g.NMG_debug & DEBUG_TRI)
01896 bu_log("NOT Joining two loops that share a vertex at (%g %g %g)\n",
01897 V3ARGS(p1->vu_p->v_p->vg_p->coord) );
01898 #endif
01899 return;
01900 }
01901
01902 pick_pt2d_for_cutjoin(tbl2d, &p1, &p2, tol);
01903
01904 vu1 = p1->vu_p;
01905 vu2 = p2->vu_p;
01906 NMG_CK_VERTEXUSE(vu1);
01907 NMG_CK_VERTEXUSE(vu2);
01908
01909 if (p1 == p2) {
01910 bu_log("%s: %d I'm a fool...\n\ttrying to join a vertexuse (%g %g %g) to itself\n",
01911 __FILE__, __LINE__,
01912 V3ARGS(p1->vu_p->v_p->vg_p->coord) );
01913 } else if (p1->vu_p->up.eu_p->up.lu_p == p2->vu_p->up.eu_p->up.lu_p) {
01914 if (rt_g.NMG_debug & DEBUG_TRI) {
01915 bu_log("parent loops are the same %s %d\n",
01916 __FILE__, __LINE__);
01917 }
01918 (void)cut_mapped_loop(tbl2d, p1, p2, color, tol, 1);
01919 return;
01920 }
01921
01922
01923
01924
01925
01926
01927
01928
01929 NMG_CK_EDGEUSE(vu2->up.eu_p);
01930
01931
01932
01933
01934 eu = BU_LIST_PPREV_CIRC(edgeuse, vu2->up.eu_p);
01935
01936
01937 if (rt_g.NMG_debug & DEBUG_TRI) {
01938 struct edgeuse *pr1_eu;
01939 struct edgeuse *pr2_eu;
01940
01941 pr1_eu = BU_LIST_PNEXT_CIRC(edgeuse, vu1->up.eu_p);
01942 pr2_eu = BU_LIST_PNEXT_CIRC(edgeuse, vu2->up.eu_p);
01943
01944 bu_log("joining loops between:\n\t%g %g %g -> (%g %g %g)\n\tand%g %g %g -> (%g %g %g)\n",
01945 V3ARGS(vu1->v_p->vg_p->coord),
01946 V3ARGS(pr1_eu->vu_p->v_p->vg_p->coord),
01947 V3ARGS(vu2->v_p->vg_p->coord),
01948 V3ARGS(pr2_eu->vu_p->v_p->vg_p->coord) );
01949 }
01950
01951 vu = nmg_join_2loops(vu1, vu2);
01952 if (plot_fd) {
01953 pl_color(plot_fd, V3ARGS(color) );
01954 pdv_3line(plot_fd, p1->coord, p2->coord);
01955 }
01956
01957
01958 NMG_CK_VERTEXUSE(vu);
01959
01960 if (vu == vu2)
01961 return;
01962
01963
01964
01965
01966
01967
01968
01969 NMG_CK_EDGEUSE(vu->up.eu_p);
01970 NMG_CK_LOOPUSE(vu->up.eu_p->up.lu_p);
01971 lu = vu->up.eu_p->up.lu_p;
01972 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
01973 if (! find_pt2d(tbl2d, eu->vu_p))
01974 map_new_vertexuse(tbl2d, eu->vu_p);
01975 }
01976 }
01977
01978
01979
01980
01981 static int
01982 skip_cut(struct bu_list *tbl2d, struct pt2d *top, struct pt2d *bot)
01983 {
01984 struct vertexuse *vu_top;
01985 struct vertexuse *vu_bot;
01986 struct vertexuse *vu;
01987 struct vertex *v;
01988 struct faceuse *fu;
01989 struct edgeuse *eu;
01990 struct edgeuse *eu_next;
01991 struct pt2d *top_next, *bot_next;
01992
01993 NMG_CK_TBL2D(tbl2d);
01994 NMG_CK_PT2D(top);
01995 NMG_CK_PT2D(bot);
01996
01997
01998 top_next = PT2D_NEXT(tbl2d, top);
01999 bot_next = PT2D_NEXT(tbl2d, bot);
02000
02001 if (top_next == bot || bot_next == top) {
02002 return 1;
02003 }
02004
02005 vu_top = top->vu_p;
02006 vu_bot = bot->vu_p;
02007 NMG_CK_VERTEXUSE(vu_top);
02008 NMG_CK_VERTEXUSE(vu_bot);
02009
02010 v = vu_top->v_p;
02011 NMG_CK_VERTEX(v);
02012 NMG_CK_VERTEX(vu_bot->v_p);
02013
02014 fu = nmg_find_fu_of_vu(vu_top);
02015
02016 for (BU_LIST_FOR(vu, vertexuse, &v->vu_hd)) {
02017
02018
02019
02020
02021 if (nmg_find_fu_of_vu(vu) != fu) continue;
02022 if (!vu->up.magic_p) {
02023 bu_log("NULL vertexuse up %s %d\n",
02024 __FILE__, __LINE__);
02025 rt_bomb("");
02026 }
02027 if (*vu->up.magic_p != NMG_EDGEUSE_MAGIC) continue;
02028 eu = vu->up.eu_p;
02029 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, eu);
02030
02031
02032 if (eu_next->vu_p->v_p == vu_bot->v_p)
02033 return 1;
02034 }
02035
02036 fu = nmg_find_fu_of_vu(vu_bot);
02037 v = vu_bot->v_p;
02038 for (BU_LIST_FOR(vu, vertexuse, &v->vu_hd)) {
02039
02040
02041
02042
02043 if (nmg_find_fu_of_vu(vu) != fu) continue;
02044 if (!vu->up.magic_p) {
02045 bu_log("NULL vertexuse up %s %d\n",
02046 __FILE__, __LINE__);
02047 rt_bomb("");
02048 }
02049 if (*vu->up.magic_p != NMG_EDGEUSE_MAGIC) continue;
02050 eu = vu->up.eu_p;
02051 eu_next = BU_LIST_PNEXT_CIRC(edgeuse, eu);
02052
02053
02054 if (eu_next->vu_p->v_p == vu_top->v_p)
02055 return 1;
02056 }
02057 return 0;
02058 }
02059
02060 static void
02061 cut_diagonals(struct bu_list *tbl2d, struct bu_list *tlist, const struct faceuse *fu, const struct bn_tol *tol)
02062 {
02063 struct trap *tp;
02064 int cut_count=0;
02065
02066 static const int cut_color[3] = {255, 80, 80};
02067 static const int join_color[3] = {80, 80, 255};
02068
02069 extern struct loopuse *nmg_find_lu_of_vu(const struct vertexuse *vu);
02070 struct loopuse *toplu, *botlu;
02071 struct loopuse *lu;
02072
02073 NMG_CK_TBL2D(tbl2d);
02074 BN_CK_TOL(tol);
02075
02076
02077 for (BU_LIST_FOR(tp, trap, tlist)) {
02078
02079
02080
02081
02082
02083
02084
02085 if( !tp->top || !tp->bot )
02086 {
02087 bu_log( "tp->top and/or tp->bot is/are NULL!!!!!!!\n" );
02088 if (rt_g.NMG_debug & DEBUG_TRI)
02089 {
02090 nmg_pr_fu_briefly( fu, "" );
02091 if( tp->top )
02092 bu_log( "tp->top is (%g %g %g)\n", V3ARGS( tp->top->vu_p->v_p->vg_p->coord ) );
02093 if( tp->bot )
02094 bu_log( "tp->bot is (%g %g %g)\n", V3ARGS( tp->bot->vu_p->v_p->vg_p->coord ) );
02095 }
02096 rt_bomb( "tp->top and/or tp->bot is/are NULL" );
02097 }
02098 if (nmg_find_eu_in_face(tp->top->vu_p->v_p, tp->bot->vu_p->v_p, fu,
02099 (struct edgeuse *)NULL, 0) != (struct edgeuse *)NULL) {
02100 if (rt_g.NMG_debug & DEBUG_TRI)
02101 bu_log("skipping %g %g/%g %g ... edge exists\n",
02102 tp->top->coord[X],
02103 tp->top->coord[Y],
02104 tp->bot->coord[X],
02105 tp->bot->coord[Y]);
02106 continue;
02107 }
02108
02109
02110 if (skip_cut(tbl2d, tp->top, tp->bot)) {
02111 if (rt_g.NMG_debug & DEBUG_TRI)
02112 bu_log("skipping %g %g/%g %g ... pts on same edge\n",
02113 tp->top->coord[X],
02114 tp->top->coord[Y],
02115 tp->bot->coord[X],
02116 tp->bot->coord[Y]);
02117 continue;
02118 }
02119
02120 if (rt_g.NMG_debug & DEBUG_TRI) {
02121 bu_log("trying to cut ...\n");
02122 print_trap(tp, tbl2d);
02123 }
02124
02125
02126
02127 toplu = nmg_find_lu_of_vu(tp->top->vu_p);
02128 botlu = nmg_find_lu_of_vu(tp->bot->vu_p);
02129 NMG_CK_VERTEXUSE(tp->top->vu_p);
02130 NMG_CK_VERTEXUSE(tp->bot->vu_p);
02131 NMG_CK_LOOPUSE(toplu);
02132 NMG_CK_LOOPUSE(botlu);
02133
02134 if (toplu == botlu){
02135
02136
02137 if (tp->top->vu_p->v_p == tp->bot->vu_p->v_p) {
02138
02139 int touching_jaunt=0;
02140 struct edgeuse *eu1, *eu2, *eu1_prev, *eu2_prev;
02141
02142 eu1 = tp->top->vu_p->up.eu_p;
02143 eu2 = tp->bot->vu_p->up.eu_p;
02144
02145 eu1_prev = BU_LIST_PPREV_CIRC( edgeuse, &eu1->l );
02146 eu2_prev = BU_LIST_PPREV_CIRC( edgeuse, &eu2->l );
02147 if( NMG_ARE_EUS_ADJACENT( eu1, eu1_prev ) )
02148 touching_jaunt = 1;
02149 else if( NMG_ARE_EUS_ADJACENT( eu2, eu2_prev ) )
02150 touching_jaunt = 1;
02151
02152 if( touching_jaunt )
02153 {
02154 if (rt_g.NMG_debug & DEBUG_TRI)
02155 bu_log("splitting self-touching jaunt loop at (%g %g %g)\n",
02156 V3ARGS(tp->bot->vu_p->v_p->vg_p->coord) );
02157
02158 nmg_loop_split_at_touching_jaunt(toplu, tol);
02159 }
02160 else
02161 {
02162 if (rt_g.NMG_debug & DEBUG_TRI)
02163 bu_log("splitting self-touching loop at (%g %g %g)\n",
02164 V3ARGS(tp->bot->vu_p->v_p->vg_p->coord) );
02165
02166 nmg_split_touchingloops(toplu, tol);
02167 }
02168 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02169 nmg_lu_reorient(lu);
02170
02171 if (rt_g.NMG_debug & DEBUG_TRI)
02172 {
02173 char fname[32];
02174
02175 sprintf( fname, "split%d.g", cut_count );
02176 nmg_stash_model_to_file( fname,
02177 nmg_find_model( &toplu->l.magic ),
02178 "after split_touching_loop()" );
02179 cut_count++;
02180 }
02181
02182 } else {
02183
02184
02185
02186 (void)cut_mapped_loop(tbl2d, tp->top,
02187 tp->bot, cut_color, tol, 1);
02188
02189 if (rt_g.NMG_debug & DEBUG_TRI)
02190 {
02191 char fname[32];
02192
02193 sprintf( fname, "cut%d.g", cut_count );
02194 nmg_stash_model_to_file( fname,
02195 nmg_find_model( &toplu->l.magic ),
02196 "after cut_mapped_loop()" );
02197 cut_count++;
02198 }
02199
02200 }
02201
02202 #if 0
02203
02204
02205
02206
02207
02208
02209 bot_next = PT2D_NEXT(tbl2d, tp->bot );
02210
02211 if ( P_LT_V( tp->bot, bot_next ) ) {
02212 register struct pt2d *new_pt;
02213 struct trap *trp;
02214
02215
02216 new_pt = PT2D_PREV(tbl2d, tp->top);
02217
02218
02219
02220
02221 for (BU_LIST_FOR(trp, trap, tlist)) {
02222 if (trp->top == tp->bot) {
02223 trp->top = new_pt;
02224 }
02225 }
02226
02227
02228
02229
02230 tp->top = PT2D_PREV( tbl2d, tp->bot );
02231 }
02232 #endif
02233 } else {
02234
02235
02236
02237
02238
02239 if (toplu->orientation == OT_OPPOSITE &&
02240 botlu->orientation == OT_OPPOSITE)
02241 rt_bomb("trying to join 2 interior loops in triangulator?\n");
02242
02243 if (rt_g.NMG_debug & DEBUG_TRI)
02244 bu_log("joining 2 loops @ %g %g -> %g %g\n",
02245 tp->top->coord[X],
02246 tp->top->coord[Y],
02247 tp->bot->coord[X],
02248 tp->bot->coord[Y]);
02249
02250 join_mapped_loops(tbl2d, tp->top, tp->bot, join_color, tol);
02251 NMG_CK_LOOPUSE(toplu);
02252
02253 if (rt_g.NMG_debug & DEBUG_TRI)
02254 {
02255 char fname[32];
02256
02257 sprintf( fname, "join%d.g", cut_count );
02258 nmg_stash_model_to_file( fname,
02259 nmg_find_model( &toplu->l.magic ),
02260 "after join_mapped_loop()" );
02261 cut_count++;
02262 }
02263
02264 }
02265
02266 if (rt_g.NMG_debug & DEBUG_TRI) {
02267 nmg_tri_plfu( nmg_find_fu_of_vu(tp->top->vu_p), tbl2d );
02268 print_tlist(tbl2d, tlist);
02269 }
02270 }
02271
02272 }
02273
02274
02275
02276
02277
02278
02279 static void
02280 cut_unimonotone(struct bu_list *tbl2d, struct bu_list *tlist, struct loopuse *lu, const struct bn_tol *tol)
02281 {
02282 struct pt2d *min, *max, *new, *first=NULL, *prev, *next, *current;
02283 struct edgeuse *eu;
02284 int verts=0;
02285 int vert_count_sq;
02286 int loop_count=0;
02287 static const int cut_color[3] = { 90, 255, 90};
02288
02289 NMG_CK_TBL2D(tbl2d);
02290 BN_CK_TOL(tol);
02291 NMG_CK_LOOPUSE(lu);
02292
02293 if (rt_g.NMG_debug & DEBUG_TRI)
02294 bu_log("cutting unimonotone:\n");
02295
02296 min = max = (struct pt2d *)NULL;
02297
02298
02299 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
02300 new = find_pt2d(tbl2d, eu->vu_p);
02301 if (!new) {
02302 bu_log("why can't I find a 2D point for %g %g %g?\n",
02303 V3ARGS(eu->vu_p->v_p->vg_p->coord));
02304 rt_bomb("bombing\n");
02305 }
02306
02307 if (rt_g.NMG_debug & DEBUG_TRI)
02308 bu_log("%g %g\n", new->coord[X], new->coord[Y]);
02309
02310 verts++;
02311
02312 if (!min || P_LT_V(new, min))
02313 min = new;
02314 if (!max || P_GT_V(new, max))
02315 max = new;
02316 }
02317 vert_count_sq = verts * verts;
02318
02319
02320
02321
02322 if (PT2D_NEXT(tbl2d, max) == min)
02323 first = min;
02324 else if (PT2D_NEXT(tbl2d, min) == max)
02325 first = max;
02326 else {
02327 bu_log("is this a unimonotone loop of just 2 points?:\t%g %g %g and %g %g %g?\n",
02328 V3ARGS(min->vu_p->v_p->vg_p->coord),
02329 V3ARGS(max->vu_p->v_p->vg_p->coord) );
02330
02331 rt_bomb("aborting\n");
02332 }
02333
02334
02335 if (rt_g.NMG_debug & DEBUG_TRI)
02336 bu_log("%d verts in unimonotone, Min: %g %g Max: %g %g first:%g %g 0x%08x\n", verts,
02337 min->coord[X], min->coord[Y],
02338 max->coord[X], max->coord[Y],
02339 first->coord[X], first->coord[Y], first);
02340
02341 current = PT2D_NEXT(tbl2d, first);
02342
02343 while (verts > 3) {
02344
02345 loop_count++;
02346 if( loop_count > vert_count_sq )
02347 {
02348 bu_log( "Cut_unimontone is in an infinite loop!!!\n" );
02349 rt_bomb( "Cut_unimontone is in an infinite loop" );
02350 }
02351
02352 prev = PT2D_PREV(tbl2d, current);
02353 next = PT2D_NEXT(tbl2d, current);
02354
02355 if (rt_g.NMG_debug & DEBUG_TRI)
02356 bu_log("%g %g -> %g %g -> %g %g ...\n",
02357 prev->coord[X],
02358 prev->coord[Y],
02359 current->coord[X],
02360 current->coord[Y],
02361 next->coord[X],
02362 next->coord[Y]);
02363
02364 if (is_convex(prev, current, next, tol)) {
02365 struct pt2d *t;
02366
02367
02368
02369 NMG_CK_LOOPUSE(lu);
02370 if (rt_g.NMG_debug & DEBUG_TRI)
02371 {
02372 bu_log( "Before cut loop:\n" );
02373 nmg_pr_fu_briefly( lu->up.fu_p, "" );
02374 }
02375 current = cut_mapped_loop(tbl2d, next, prev, cut_color, tol, 0);
02376 if (rt_g.NMG_debug & DEBUG_TRI)
02377 {
02378 bu_log( "After cut loop:\n" );
02379 nmg_pr_fu_briefly( lu->up.fu_p, "" );
02380 }
02381 verts--;
02382 NMG_CK_LOOPUSE(lu);
02383
02384 if (rt_g.NMG_debug & DEBUG_TRI)
02385 nmg_tri_plfu( lu->up.fu_p, tbl2d );
02386
02387 if (current->vu_p->v_p == first->vu_p->v_p) {
02388 t = PT2D_NEXT(tbl2d, first);
02389 if (rt_g.NMG_debug & DEBUG_TRI)
02390 bu_log("\tfirst(0x%08x -> %g %g\n", first, t->coord[X], t->coord[Y]);
02391 t = PT2D_NEXT(tbl2d, current);
02392
02393 if (rt_g.NMG_debug & DEBUG_TRI)
02394 bu_log("\tcurrent(0x%08x) -> %g %g\n", current, t->coord[X], t->coord[Y]);
02395
02396 current = PT2D_NEXT(tbl2d, current);
02397 if (rt_g.NMG_debug & DEBUG_TRI)
02398 bu_log("\tcurrent(0x%08x) -> %g %g\n", current, t->coord[X], t->coord[Y]);
02399 }
02400 } else {
02401 if (rt_g.NMG_debug & DEBUG_TRI)
02402 bu_log("\tConcave, moving ahead\n");
02403 current = next;
02404 }
02405 }
02406 }
02407
02408
02409
02410 static void
02411 nmg_plot_flat_face(struct faceuse *fu, struct bu_list *tbl2d)
02412 {
02413 struct loopuse *lu;
02414 struct edgeuse *eu;
02415 char buf[80];
02416 vect_t pt;
02417 struct pt2d *p, *pn;
02418
02419 NMG_CK_TBL2D(tbl2d);
02420 NMG_CK_FACEUSE(fu);
02421
02422 if (!plot_fd && (plot_fd = fopen("triplot.pl", "w")) == (FILE *)NULL) {
02423 bu_log( "cannot open triplot.pl\n");
02424 }
02425
02426 pl_erase(plot_fd);
02427 pd_3space(plot_fd,
02428 fu->f_p->min_pt[0]-1.0,
02429 fu->f_p->min_pt[1]-1.0,
02430 fu->f_p->min_pt[2]-1.0,
02431 fu->f_p->max_pt[0]+1.0,
02432 fu->f_p->max_pt[1]+1.0,
02433 fu->f_p->max_pt[2]+1.0);
02434
02435 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
02436 if (BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC) {
02437 register struct vertexuse *vu;
02438
02439 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
02440 if (rt_g.NMG_debug & DEBUG_TRI)
02441 bu_log( "lone vert @ %g %g %g\n",
02442 V3ARGS(vu->v_p->vg_p->coord) );
02443
02444 pl_color(plot_fd, 200, 200, 100);
02445
02446 if (! (p=find_pt2d(tbl2d, vu)) )
02447 rt_bomb("didn't find vertexuse in list!\n");
02448
02449 pdv_3point(plot_fd, p->coord);
02450 sprintf(buf, "%g, %g", p->coord[0], p->coord[1]);
02451 pl_label(plot_fd, buf);
02452
02453 continue;
02454 }
02455
02456 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd ) ) {
02457 register struct edgeuse *eu_pnext;
02458
02459 eu_pnext = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
02460
02461 #if 0
02462 if (rt_g.NMG_debug & DEBUG_TRI)
02463 bu_log( "eu vert @ %g %g %g\n",
02464 V3ARGS(eu->vu_p->v_p->vg_p->coord) );
02465
02466 #endif
02467 if (! (p=find_pt2d(tbl2d, eu->vu_p)) )
02468 rt_bomb("didn't find vertexuse in list!\n");
02469
02470 if (! (pn=find_pt2d(tbl2d, eu_pnext->vu_p)) )
02471 rt_bomb("didn't find vertexuse in list!\n");
02472
02473
02474 VSUB2(pt, pn->coord, p->coord);
02475
02476 VSCALE(pt, pt, 0.80);
02477 VADD2(pt, p->coord, pt);
02478
02479 pl_color(plot_fd, 200, 200, 200);
02480 pdv_3line(plot_fd, p->coord, pt);
02481 pd_3move(plot_fd, V3ARGS(p->coord));
02482
02483 sprintf(buf, "%g, %g", p->coord[0], p->coord[1]);
02484 pl_label(plot_fd, buf);
02485 }
02486 }
02487 }
02488
02489
02490 void
02491 nmg_triangulate_fu(struct faceuse *fu, const struct bn_tol *tol)
02492 {
02493 mat_t TformMat;
02494 struct bu_list *tbl2d;
02495 struct loopuse *lu;
02496 struct edgeuse *eu;
02497 struct vertexuse *vu;
02498 struct bu_list tlist;
02499 struct trap *tp;
02500 struct pt2d *pt;
02501 int vert_count;
02502 static int iter=0;
02503 static int monotone=0;
02504 vect_t N;
02505
02506 char db_name[32];
02507
02508 BN_CK_TOL(tol);
02509 NMG_CK_FACEUSE(fu);
02510
02511 if (rt_g.NMG_debug & DEBUG_TRI) {
02512 NMG_GET_FU_NORMAL(N, fu);
02513 bu_log("---------------- Triangulate face %g %g %g\n",
02514 V3ARGS(N));
02515 }
02516
02517
02518
02519 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
02520 if (lu->orientation != OT_SAME) {
02521 if (rt_g.NMG_debug & DEBUG_TRI)
02522 bu_log("faceuse has non-OT_SAME orientation loop\n");
02523 goto triangulate;
02524 }
02525 vert_count = 0;
02526 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd ))
02527 if (++vert_count > 3) {
02528 if (rt_g.NMG_debug & DEBUG_TRI)
02529 bu_log("loop has more than 3 verticies\n");
02530 goto triangulate;
02531 }
02532 }
02533
02534 if (rt_g.NMG_debug & DEBUG_TRI) {
02535 bu_log("---------------- face %g %g %g already triangular\n",
02536 V3ARGS(N));
02537
02538 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02539 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd ))
02540 VPRINT("pt", eu->vu_p->v_p->vg_p->coord );
02541
02542 }
02543 return;
02544
02545 triangulate:
02546 if (rt_g.NMG_debug & DEBUG_TRI) {
02547 vect_t N;
02548 NMG_GET_FU_NORMAL(N, fu);
02549 bu_log("---------------- proceeding to triangulate face %g %g %g\n", V3ARGS(N));
02550 }
02551
02552
02553
02554 tbl2d = nmg_flatten_face(fu, TformMat);
02555
02556
02557 {
02558 struct pt2d *pt1, *pt2;
02559
02560 pt1 = BU_LIST_FIRST( pt2d, tbl2d );
02561 pt2 = BU_LIST_PNEXT( pt2d, &pt1->l );
02562
02563 if( vtype2d( pt1, tbl2d, tol ) == HOLE_START &&
02564 pt1->vu_p->v_p == pt2->vu_p->v_p )
02565 {
02566
02567 if (rt_g.NMG_debug & DEBUG_TRI)
02568 bu_log( "Swapping first two points on vertex list (first one was a HOLE_START)\n" );
02569
02570 BU_LIST_DEQUEUE( &pt1->l );
02571 BU_LIST_APPEND( &pt2->l, &pt1->l );
02572 }
02573 }
02574
02575 if (rt_g.NMG_debug & DEBUG_TRI) {
02576 struct pt2d *pt;
02577 bu_log( "Face Flattened\n");
02578 bu_log( "Vertex list:\n");
02579 for (BU_LIST_FOR(pt, pt2d, tbl2d)) {
02580 bu_log("\tpt2d %26.20e %26.20e\n", pt->coord[0], pt->coord[1]);
02581 }
02582
02583 nmg_tri_plfu( fu, tbl2d );
02584 nmg_plot_flat_face(fu, tbl2d);
02585 bu_log( "Face plotted\n\tmaking trapezoids...\n");
02586 }
02587
02588
02589 BU_LIST_INIT(&tlist);
02590 nmg_trap_face(tbl2d, &tlist, tol);
02591
02592 if (rt_g.NMG_debug & DEBUG_TRI){
02593 print_tlist(tbl2d, &tlist);
02594
02595 bu_log("Cutting diagonals ----------\n");
02596 }
02597 cut_diagonals(tbl2d, &tlist, fu, tol);
02598 if (rt_g.NMG_debug & DEBUG_TRI)
02599 bu_log("Diagonals are cut ----------\n");
02600
02601 if (rt_g.NMG_debug & DEBUG_TRI) {
02602 sprintf(db_name, "uni%d.g", iter);
02603 nmg_stash_model_to_file(db_name,
02604 nmg_find_model(&fu->s_p->l.magic),
02605 "trangles and unimonotones");
02606 }
02607
02608 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02609 (void)nmg_loop_split_at_touching_jaunt(lu, tol);
02610
02611 if (rt_g.NMG_debug & DEBUG_TRI) {
02612 sprintf(db_name, "uni_sj%d.g", iter);
02613 nmg_stash_model_to_file(db_name,
02614 nmg_find_model(&fu->s_p->l.magic),
02615 "after split_at_touching_jaunt");
02616 }
02617
02618 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02619 nmg_split_touchingloops( lu, tol );
02620
02621 if (rt_g.NMG_debug & DEBUG_TRI) {
02622 sprintf(db_name, "uni_split%d.g", iter++);
02623 nmg_stash_model_to_file(db_name,
02624 nmg_find_model(&fu->s_p->l.magic),
02625 "split trangles and unimonotones");
02626 }
02627
02628
02629
02630
02631 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
02632
02633 if (BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC) {
02634 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
02635
02636 bu_log("How did I miss this vertex loop %g %g %g?\n%s\n",
02637 V3ARGS(vu->v_p->vg_p->coord),
02638 "I'm supposed to be dealing with unimonotone loops now");
02639 rt_bomb("aborting\n");
02640
02641 } else if (BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_EDGEUSE_MAGIC) {
02642 vert_count = 0;
02643 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd )) {
02644 if (++vert_count > 3) {
02645 cut_unimonotone(tbl2d, &tlist, lu, tol);
02646
02647 if (rt_g.NMG_debug & DEBUG_TRI) {
02648 sprintf(db_name, "uni_mono%d.g", monotone++);
02649 nmg_stash_model_to_file(db_name,
02650 nmg_find_model(&fu->s_p->l.magic),
02651 "newly cut unimonotone");
02652 }
02653
02654 break;
02655 }
02656 }
02657 }
02658 }
02659
02660
02661 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
02662 nmg_lu_reorient(lu);
02663
02664 if (rt_g.NMG_debug & DEBUG_TRI)
02665 nmg_tri_plfu( fu, tbl2d );
02666
02667 while (BU_LIST_WHILE(tp, trap, &tlist)) {
02668 BU_LIST_DEQUEUE(&tp->l);
02669 bu_free((char *)tp, "trapezoid free");
02670 }
02671
02672 while (BU_LIST_WHILE(pt, pt2d, tbl2d)) {
02673 BU_LIST_DEQUEUE(&pt->l);
02674 bu_free((char *)pt, "pt2d free");
02675 }
02676 bu_free((char *)tbl2d, "discard tbl2d");
02677
02678 return;
02679 }
02680
02681 void
02682 nmg_triangulate_shell(struct shell *s, const struct bn_tol *tol)
02683 {
02684 struct faceuse *fu;
02685
02686 BN_CK_TOL(tol);
02687 NMG_CK_SHELL( s );
02688
02689 for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
02690 NMG_CK_FACEUSE(fu);
02691 if (fu->orientation == OT_SAME)
02692 nmg_triangulate_fu(fu, tol);
02693 }
02694 }
02695
02696 void
02697 nmg_triangulate_model(struct model *m, const struct bn_tol *tol)
02698 {
02699 struct nmgregion *r;
02700 struct shell *s;
02701 struct faceuse *fu;
02702
02703 BN_CK_TOL(tol);
02704 NMG_CK_MODEL(m);
02705 nmg_vmodel(m);
02706
02707 if (rt_g.NMG_debug & DEBUG_TRI)
02708 bu_log("Triangulating NMG\n");
02709
02710 (void)nmg_model_edge_g_fuse( m, tol );
02711
02712 (void)nmg_unbreak_region_edges( &m->magic );
02713
02714 for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
02715 NMG_CK_REGION(r);
02716 for (BU_LIST_FOR(s, shell, &r->s_hd)) {
02717 NMG_CK_SHELL(s);
02718 nmg_s_split_touchingloops(s, tol);
02719
02720 for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
02721 NMG_CK_FACEUSE(fu);
02722 if (fu->orientation == OT_SAME)
02723 nmg_triangulate_fu(fu, tol);
02724 }
02725 }
02726 }
02727 nmg_vmodel(m);
02728
02729 if (rt_g.NMG_debug & DEBUG_TRI)
02730 bu_log("Triangulation completed\n");
02731 }
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741