00001 #define PLOT_BOTH_FACES 1
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 #ifndef lint
00034 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_fcut.c,v 14.8 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00035 #endif
00036
00037 #include "common.h"
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <string.h>
00042 #include <math.h>
00043 #include "machine.h"
00044 #include "vmath.h"
00045 #include "nmg.h"
00046 #include "raytrace.h"
00047
00048
00049
00050
00051 #define NMG_STATE_ERROR 0
00052 #define NMG_STATE_OUT 1
00053 #define NMG_STATE_ON_L 2
00054 #define NMG_STATE_ON_R 3
00055 #define NMG_STATE_ON_B 4
00056 #define NMG_STATE_ON_N 5
00057 #define NMG_STATE_IN 6
00058 static const char *nmg_state_names[] = {
00059 "*ERROR*",
00060 "out",
00061 "on_L",
00062 "on_R",
00063 "on_both",
00064 "on_neither",
00065 "in",
00066 "TOOBIG"
00067 };
00068
00069 #define NMG_E_ASSESSMENT_LEFT 0
00070 #define NMG_E_ASSESSMENT_RIGHT 1
00071 #define NMG_E_ASSESSMENT_ON_FORW 2
00072 #define NMG_E_ASSESSMENT_ON_REV 3
00073 #define NMG_E_ASSESSMENT_ERROR 4
00074
00075 #define NMG_V_ASSESSMENT_LONE 16
00076 #define NMG_V_ASSESSMENT_ERROR 17
00077 #define NMG_V_COMB(_p,_n) (((_p)<<2)|(_n))
00078
00079
00080 #define NMG_V_ASSESSMENT_PREV(_a) (((_a)>>2)&3)
00081 #define NMG_V_ASSESSMENT_NEXT(_a) ((_a)&3)
00082
00083 static const char *nmg_v_assessment_names[32] = {
00084 "Left,Left",
00085 "Left,Right",
00086 "Left,On_Forw",
00087 "Left,On_Rev",
00088 "Right,Left",
00089 "Right,Right",
00090 "Right,On_Forw",
00091 "Right,On_Rev",
00092 "On_Forw,Left",
00093 "On_Forw,Right",
00094 "On_Forw,On_Forw",
00095 "On_Forw,On_Rev",
00096 "On_Rev,Left",
00097 "On_Rev,Right",
00098 "On_Rev,On_Forw",
00099 "On_Rev,On_Rev",
00100 "LONE_V",
00101 "V_ERROR",
00102 "?18",
00103 "?19",
00104 "?20",
00105 "?21",
00106 "?22",
00107 "?23",
00108 "?24",
00109 "?25",
00110 "?26",
00111 "?27",
00112 "?28",
00113 "?29",
00114 "?30",
00115 "?31"
00116 };
00117 #define NMG_LEFT_LEFT NMG_V_COMB(NMG_E_ASSESSMENT_LEFT,NMG_E_ASSESSMENT_LEFT)
00118 #define NMG_LEFT_RIGHT NMG_V_COMB(NMG_E_ASSESSMENT_LEFT,NMG_E_ASSESSMENT_RIGHT)
00119 #define NMG_LEFT_ON_FORW NMG_V_COMB(NMG_E_ASSESSMENT_LEFT,NMG_E_ASSESSMENT_ON_FORW)
00120 #define NMG_LEFT_ON_REV NMG_V_COMB(NMG_E_ASSESSMENT_LEFT,NMG_E_ASSESSMENT_ON_REV)
00121 #define NMG_RIGHT_LEFT NMG_V_COMB(NMG_E_ASSESSMENT_RIGHT,NMG_E_ASSESSMENT_LEFT)
00122 #define NMG_RIGHT_RIGHT NMG_V_COMB(NMG_E_ASSESSMENT_RIGHT,NMG_E_ASSESSMENT_RIGHT)
00123 #define NMG_RIGHT_ON_FORW NMG_V_COMB(NMG_E_ASSESSMENT_RIGHT,NMG_E_ASSESSMENT_ON_FORW)
00124 #define NMG_RIGHT_ON_REV NMG_V_COMB(NMG_E_ASSESSMENT_RIGHT,NMG_E_ASSESSMENT_ON_REV)
00125 #define NMG_ON_FORW_LEFT NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW,NMG_E_ASSESSMENT_LEFT)
00126 #define NMG_ON_FORW_RIGHT NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW,NMG_E_ASSESSMENT_RIGHT)
00127 #define NMG_ON_FORW_ON_FORW NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW,NMG_E_ASSESSMENT_ON_FORW)
00128 #define NMG_ON_FORW_ON_REV NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW,NMG_E_ASSESSMENT_ON_REV)
00129 #define NMG_ON_REV_LEFT NMG_V_COMB(NMG_E_ASSESSMENT_ON_REV,NMG_E_ASSESSMENT_LEFT)
00130 #define NMG_ON_REV_RIGHT NMG_V_COMB(NMG_E_ASSESSMENT_ON_REV,NMG_E_ASSESSMENT_RIGHT)
00131 #define NMG_ON_REV_ON_FORW NMG_V_COMB(NMG_E_ASSESSMENT_ON_REV,NMG_E_ASSESSMENT_ON_FORW)
00132 #define NMG_ON_REV_ON_REV NMG_V_COMB(NMG_E_ASSESSMENT_ON_REV,NMG_E_ASSESSMENT_ON_REV)
00133 #define NMG_LONE NMG_V_ASSESSMENT_LONE
00134
00135 static const char *nmg_e_assessment_names[6] = {
00136 "LEFT",
00137 "RIGHT",
00138 "ON_FORW",
00139 "ON_REV",
00140 "E_ERROR",
00141 "E_5?"
00142 };
00143
00144
00145
00146
00147 #define NMG_ACTION_ERROR 0
00148 #define NMG_ACTION_NONE 1
00149 #define NMG_ACTION_NONE_OPTIM 2
00150 #define NMG_ACTION_VFY_EXT 3
00151 #define NMG_ACTION_VFY_MULTI 4
00152 #define NMG_ACTION_LONE_V_ESPLIT 5
00153 #define NMG_ACTION_LONE_V_JAUNT 6
00154 #define NMG_ACTION_CUTJOIN 7
00155 static const char *action_names[] = {
00156 "*ERROR*",
00157 "NONE",
00158 "NONE_OPTIM",
00159 "VFY_EXT",
00160 "VFY_MULTI",
00161 "LONE_V_ESPLIT",
00162 "LONE_V_JAUNT",
00163 "CUTJOIN",
00164 "*TOOBIG*"
00165 };
00166
00167
00168 struct nmg_ray_state {
00169 long magic;
00170 struct vertexuse **vu;
00171 int nvu;
00172 point_t pt;
00173 vect_t dir;
00174 struct edge_g_lseg *eg_p;
00175 struct shell *sA;
00176 struct shell *sB;
00177 struct faceuse *fu1;
00178 struct faceuse *fu2;
00179 vect_t left;
00180 int state;
00181 int last_action;
00182 vect_t ang_x_dir;
00183 vect_t ang_y_dir;
00184 const struct bn_tol *tol;
00185 };
00186 #define NMG_RAYSTATE_MAGIC 0x54322345
00187 #define NMG_CK_RAYSTATE(_p) NMG_CKMAG(_p, NMG_RAYSTATE_MAGIC, "nmg_ray_state")
00188
00189 struct loop_cuts {
00190 struct loopuse *lu;
00191 struct vertexuse *vu1;
00192 struct vertexuse *vu2;
00193 };
00194 int
00195 nmg_face_state_transition(struct nmg_ray_state *rs,
00196 int pos,
00197 int multi,
00198 int other_rs_state);
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static void ptbl_vsort(struct bu_ptbl *b, struct faceuse *fu1, struct faceuse *fu2, fastf_t *pt, fastf_t *dir, fastf_t *mag, fastf_t dist_tol)
00213
00214
00215
00216
00217
00218
00219
00220 {
00221 register struct vertexuse **vu;
00222 register int i, j;
00223
00224 vu = (struct vertexuse **)b->buffer;
00225
00226 if( rt_g.NMG_debug ) {
00227
00228 for(i = 0 ; i < b->end ; ++i) {
00229 fastf_t dist;
00230
00231 NMG_CK_VERTEXUSE(vu[i]);
00232 dist = bn_dist_line3_pt3( pt, dir, vu[i]->v_p->vg_p->coord );
00233 if( dist > dist_tol ) {
00234 bu_log("WARNING ptbl_vsort() vu=x%x point off line by %e %g*tol, tol=%e\n",
00235 vu[i], dist,
00236 dist/dist_tol, dist_tol);
00237 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
00238 VPRINT(" vu", vu[i]->v_p->vg_p->coord);
00239 VPRINT(" pt", pt);
00240 VPRINT(" dir", dir);
00241 }
00242 }
00243 if( dist > 100*dist_tol ) {
00244 bu_log("ERROR ptbl_vsort() vu=x%x point off line by %g > 100*dist_tol\n",
00245 vu[i], dist);
00246 rt_bomb("ptbl_vsort()\n");
00247 }
00248 }
00249 }
00250
00251
00252 for(i = 0 ; i < b->end ; ++i) {
00253 vect_t vect;
00254 NMG_CK_VERTEXUSE(vu[i]);
00255
00256 if( mag[i] == MAX_FASTF )
00257 {
00258 VSUB2(vect, vu[i]->v_p->vg_p->coord, pt);
00259 mag[i] = VDOT( vect, dir );
00260 }
00261
00262
00263 for( j = 0; j < i; j++ ) {
00264 register fastf_t tmag;
00265
00266 tmag = mag[i] - mag[j];
00267 if( tmag < -dist_tol ) continue;
00268 if( tmag > dist_tol ) continue;
00269
00270 if( mag[i] != mag[j] &&
00271 vu[i]->v_p == vu[j]->v_p ) {
00272 bu_log("ptbl_vsort: forcing vu=x%x & vu=x%x mag equal\n", vu[i], vu[j]);
00273 mag[j] = mag[i];
00274 }
00275 }
00276 }
00277
00278 for(i=0 ; i < b->end - 1 ; ++i) {
00279 for (j=i+1; j < b->end ; ++j) {
00280
00281 if( mag[i] < mag[j] ) continue;
00282 if( mag[i] == mag[j] ) {
00283 if( vu[i]->v_p < vu[j]->v_p ) continue;
00284 if( vu[i]->v_p == vu[j]->v_p ) {
00285 if( vu[i] < vu[j] ) continue;
00286 if( vu[i] == vu[j] ) {
00287 int last = b->end - 1;
00288
00289 bu_log("ptbl_vsort: vu duplication eliminated\n");
00290 if( j >= last ) {
00291
00292 b->end--;
00293 break;
00294 }
00295
00296 vu[j] = vu[last];
00297 mag[j] = mag[last];
00298 b->end--;
00299
00300 j--;
00301 continue;
00302 }
00303
00304 }
00305
00306 }
00307
00308
00309
00310 {
00311 register struct vertexuse *tvu;
00312 tvu = vu[i];
00313 vu[i] = vu[j];
00314 vu[j] = tvu;
00315 }
00316
00317 {
00318 register fastf_t tmag;
00319 tmag = mag[i];
00320 mag[i] = mag[j];
00321 mag[j] = tmag;
00322 }
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 int
00338 nmg_ck_vu_ptbl(struct bu_ptbl *p, struct faceuse *fu)
00339 {
00340 struct vertex *v;
00341 struct vertexuse *vu;
00342 struct vertexuse *tvu;
00343 struct faceuse *tfu;
00344 int i;
00345 int ret = 0;
00346
00347 BU_CK_PTBL(p);
00348 NMG_CK_FACEUSE(fu);
00349
00350 top:
00351 for( i=0; i < BU_PTBL_END(p); i++ ) {
00352 vu = (struct vertexuse *)BU_PTBL_GET(p, i);
00353 NMG_CK_VERTEXUSE(vu);
00354 v = vu->v_p;
00355 NMG_CK_VERTEX(v);
00356 tfu = nmg_find_fu_of_vu(vu);
00357 if( tfu != fu ) {
00358 bu_log("ERROR: vu=x%x v=x%x up_fu=x%x != arg_fu=x%x\n",
00359 vu, v, tfu, fu );
00360 rt_bomb("nmg_ck_vu_ptbl() intersect list is confused about which face it belongs to.\n");
00361 }
00362 for( BU_LIST_FOR( tvu, vertexuse, &v->vu_hd ) ) {
00363 NMG_CK_VERTEXUSE(tvu);
00364 if( tvu == vu ) continue;
00365 if( (tfu = nmg_find_fu_of_vu( tvu )) == (struct faceuse *)NULL )
00366 continue;
00367 if( tfu != fu ) continue;
00368
00369 if( bu_ptbl_locate(p, &tvu->l.magic ) >= 0 ) continue;
00370
00371 bu_log("ERROR: vu=x%x v=x%x %s=x%x is on isect line, tvu=x%x %s=x%x isn't.\n",
00372 vu, v,
00373 bu_identify_magic( *vu->up.magic_p ),
00374 vu->up.magic_p,
00375 tvu,
00376 bu_identify_magic( *tvu->up.magic_p ),
00377 tvu->up.magic_p );
00378
00379 nmg_pr_ptbl( "intersect line vu table", p, 1 );
00380 rt_bomb("nmg_ck_vu_ptbl() missing vertexuse\n");
00381
00382
00383 (void)bu_ptbl_ins( p, &tvu->l.magic );
00384 ret++;
00385 goto top;
00386 }
00387 }
00388 if(ret)bu_log("nmg_ck_vu_ptbl() ret=%d\n", ret);
00389 return ret;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 double
00412 nmg_vu_angle_measure(struct vertexuse *vu, fastf_t *x_dir, fastf_t *y_dir, int assessment, int in)
00413
00414
00415
00416
00417
00418 {
00419 struct loopuse *lu;
00420 struct edgeuse *this_eu;
00421 struct edgeuse *prev_eu;
00422 vect_t vec;
00423 fastf_t ang;
00424 int this_ass;
00425
00426 NMG_CK_VERTEXUSE( vu );
00427 if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC ) {
00428 return 0;
00429 }
00430
00431
00432
00433
00434
00435 if( in )
00436 this_ass = NMG_V_ASSESSMENT_PREV( assessment );
00437 else
00438 this_ass = NMG_V_ASSESSMENT_NEXT( assessment );
00439 if( this_ass == NMG_E_ASSESSMENT_ON_FORW ) {
00440 if( in ) ang = 0;
00441 else ang = bn_pi;
00442 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00443 bu_log("nmg_vu_angle_measure: NMG_E_ASSESSMENT_ON_FORW, ang=%g\n", ang);
00444 return ang;
00445 }
00446 if( this_ass == NMG_E_ASSESSMENT_ON_REV ) {
00447 if( in ) ang = bn_pi;
00448 else ang = 0;
00449 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00450 bu_log("nmg_vu_angle_measure: NMG_E_ASSESSMENT_ON_REV, ang=%g\n", ang);
00451 return ang;
00452 }
00453
00454
00455
00456
00457 lu = nmg_find_lu_of_vu(vu);
00458 NMG_CK_LOOPUSE(lu);
00459 this_eu = nmg_find_eu_with_vu_in_lu( lu, vu );
00460 prev_eu = this_eu;
00461 do {
00462 prev_eu = in ? BU_LIST_PPREV_CIRC( edgeuse, prev_eu ) :
00463 BU_LIST_PNEXT_CIRC( edgeuse, prev_eu );
00464 if( prev_eu == this_eu ) {
00465 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00466 bu_log("nmg_vu_angle_measure: prev eu is this eu, ang=0\n");
00467 return 0;
00468 }
00469
00470 } while( prev_eu->vu_p->v_p == this_eu->vu_p->v_p );
00471
00472
00473
00474 VSUB2( vec, prev_eu->vu_p->v_p->vg_p->coord, vu->v_p->vg_p->coord );
00475
00476 ang = bn_angle_measure( vec, x_dir, y_dir );
00477 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00478 bu_log("nmg_vu_angle_measure: measured angle=%e\n", ang*bn_radtodeg);
00479
00480
00481
00482
00483
00484 #define RADIAN_TWEEK 1.0e-14
00485 if( ang == 0 ) {
00486 if( this_ass == NMG_E_ASSESSMENT_RIGHT ) {
00487 ang = RADIAN_TWEEK;
00488 } else {
00489
00490 ang = bn_twopi - RADIAN_TWEEK;
00491 }
00492 } else if( ang == bn_pi ) {
00493 if( this_ass == NMG_E_ASSESSMENT_RIGHT ) {
00494 ang = bn_pi - RADIAN_TWEEK;
00495 } else {
00496 ang = bn_pi + RADIAN_TWEEK;
00497 }
00498 }
00499
00500
00501
00502
00503
00504 if( ang > bn_pi ) {
00505 if( this_ass != NMG_E_ASSESSMENT_LEFT ) {
00506 bu_log("*** ERROR topology/geometry conflict, ang=%e, ass=%s\n",
00507 ang*bn_radtodeg,
00508 nmg_e_assessment_names[this_ass] );
00509 }
00510 } else if( ang < bn_pi ) {
00511 if( this_ass != NMG_E_ASSESSMENT_RIGHT ) {
00512 bu_log("*** ERROR topology/geometry conflict, ang=%e, ass=%s\n",
00513 ang*bn_radtodeg,
00514 nmg_e_assessment_names[this_ass] );
00515 }
00516 }
00517 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00518 bu_log(" final ang=%g (%e), vec=(%g,%g,%g)\n", ang*bn_radtodeg, ang*bn_radtodeg, V3ARGS(vec) );
00519 return ang;
00520 }
00521
00522
00523
00524
00525 int
00526 nmg_is_v_on_rs_list(const struct nmg_ray_state *rs, const struct vertex *v)
00527 {
00528 register int i;
00529
00530 NMG_CK_VERTEX(v);
00531 for( i=rs->nvu-1; i >= 0; i-- ) {
00532 if( !rs->vu[i] ) continue;
00533 if( rs->vu[i]->v_p == v ) return i;
00534 }
00535 return -1;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 int
00550 nmg_assess_eu(struct edgeuse *eu, int forw, struct nmg_ray_state *rs, int pos)
00551 {
00552 struct vertex *v;
00553 struct vertex *otherv = (struct vertex *)0;
00554 struct edgeuse *othereu;
00555 vect_t heading;
00556 int ret;
00557 register int i;
00558
00559 NMG_CK_EDGEUSE(eu);
00560 NMG_CK_RAYSTATE(rs);
00561 BN_CK_TOL(rs->tol);
00562 v = eu->vu_p->v_p;
00563 NMG_CK_VERTEX(v);
00564 othereu = eu;
00565 if( forw ) {
00566 othereu = BU_LIST_PNEXT_CIRC( edgeuse, othereu );
00567 } else {
00568 othereu = BU_LIST_PPREV_CIRC( edgeuse, othereu );
00569 }
00570 if( othereu == eu ) {
00571
00572 if(rt_g.NMG_debug) nmg_pr_eu(eu, NULL);
00573 rt_bomb("nmg_assess_eu() no edges leave the vertex!\n");
00574 }
00575 otherv = othereu->vu_p->v_p;
00576 if( otherv == v ) {
00577
00578 if(rt_g.NMG_debug) nmg_pr_eu(eu, NULL);
00579 rt_bomb("nmg_assess_eu() edge runs from&to same vertex!\n");
00580 }
00581
00582
00583
00584
00585
00586
00587 if( (i = nmg_is_v_on_rs_list(rs, otherv)) > -1 ) {
00588 struct vertex *farv;
00589 struct edgeuse *fareu;
00590 int start, end;
00591
00592 fareu = othereu;
00593 again:
00594
00595 if(rt_g.NMG_debug&DEBUG_FCUT)
00596 bu_log("eu ON ray: vu[%d]=x%x, other:vu[%d]=x%x\n",
00597 pos, rs->vu[pos], i, otherv );
00598
00599
00600
00601
00602
00603
00604
00605 if( forw ) {
00606 fareu = BU_LIST_PNEXT_CIRC( edgeuse, fareu );
00607 } else {
00608 fareu = BU_LIST_PPREV_CIRC( edgeuse, fareu );
00609 }
00610 if( fareu == eu ) goto really_on;
00611 if( fareu->g.lseg_p != eu->g.lseg_p ) goto really_on;
00612 farv = fareu->vu_p->v_p;
00613 if(rt_g.NMG_debug&DEBUG_FCUT)
00614 bu_log("nmg_assess_eu() farv = x%x, on_index=%d\n", farv, nmg_is_v_on_rs_list(rs, farv) );
00615 if( nmg_is_v_on_rs_list(rs, farv) > -1 ) {
00616
00617 goto again;
00618 }
00619
00620
00621 otherv = farv;
00622 if(rt_g.NMG_debug&DEBUG_FCUT)
00623 bu_log("nmg_assess_eu() assessing farv\n");
00624 goto left_right;
00625
00626
00627 really_on:
00628 #if 0
00629 if( forw ) {
00630
00631 VSUB2( heading, otherv->vg_p->coord, v->vg_p->coord );
00632 } else {
00633
00634 VSUB2( heading, v->vg_p->coord, otherv->vg_p->coord );
00635 }
00636 if( MAGSQ(heading) < SMALL_FASTF ) rt_bomb("nmg_assess_eu() null heading\n");
00637 if( MAGSQ(heading) < rs->tol->dist_sq ) rt_bomb("nmg_assess_eu() edge len < dist tol\n");
00638 if( VDOT( heading, rs->dir ) < 0 ) {
00639 ret = NMG_E_ASSESSMENT_ON_REV;
00640 } else {
00641 ret = NMG_E_ASSESSMENT_ON_FORW;
00642 }
00643
00644 if( i > pos ) {
00645 start = pos+1;
00646 end = i;
00647 } else {
00648 start = i+1;
00649 end = pos;
00650 }
00651 #else
00652
00653
00654
00655
00656
00657
00658 if( i > pos ) {
00659 if( forw )
00660 ret = NMG_E_ASSESSMENT_ON_FORW;
00661 else
00662 ret = NMG_E_ASSESSMENT_ON_REV;
00663 start = pos+1;
00664 end = i;
00665 } else {
00666
00667 if( forw )
00668 ret = NMG_E_ASSESSMENT_ON_REV;
00669 else
00670 ret = NMG_E_ASSESSMENT_ON_FORW;
00671 start = i+1;
00672 end = pos;
00673 }
00674 #endif
00675
00676
00677
00678
00679
00680 for( i=start; i<end; i++ ) {
00681 int j;
00682 if( !rs->vu[i] ) continue;
00683 if( rs->vu[i]->v_p == v ||
00684 rs->vu[i]->v_p == otherv )
00685 continue;
00686 if(rt_g.NMG_debug&DEBUG_FCUT) {
00687 bu_log("In edge interval (%d,%d), ON vertexuse [%d] = x%x appears?\n",
00688 start-1, end, i, rs->vu[i] );
00689 for( j=start-1; j<=end; j++ ) {
00690 if( !rs->vu[i] ) continue;
00691 bu_log(" %d ", j);
00692 nmg_pr_vu_briefly( rs->vu[j], (char *)0 );
00693 }
00694 bu_log("nmg_assess_eu(): ON vertexuse in middle of edge?\n");
00695 }
00696
00697 ret = NMG_E_ASSESSMENT_ERROR;
00698 return -i;
00699 }
00700 goto out;
00701 }
00702
00703
00704
00705
00706
00707
00708 left_right:
00709 VSUB2( heading, otherv->vg_p->coord, v->vg_p->coord );
00710 if( MAGSQ(heading) < SMALL_FASTF ) rt_bomb("nmg_assess_eu() null heading 2\n");
00711 if( VDOT( heading, rs->left ) < 0 ) {
00712 ret = NMG_E_ASSESSMENT_RIGHT;
00713 } else {
00714 ret = NMG_E_ASSESSMENT_LEFT;
00715 }
00716 out:
00717 if(rt_g.NMG_debug&DEBUG_FCUT) {
00718 bu_log("nmg_assess_eu(x%x, fw=%d, pos=%d) v=x%x otherv=x%x: %s\n",
00719 eu, forw, pos, v, otherv,
00720 nmg_e_assessment_names[ret] );
00721 bu_log(" v(%g, %g, %g) other(%g, %g, %g)\n",
00722 V3ARGS(v->vg_p->coord), V3ARGS(otherv->vg_p->coord) );
00723 bu_log(" rs->left(%g, %g, %g) heading(%g, %g, %g)\n",
00724 V3ARGS(rs->left), V3ARGS(heading) );
00725 }
00726 return ret;
00727 }
00728
00729
00730
00731
00732 int
00733 nmg_assess_vu(struct nmg_ray_state *rs, int pos)
00734 {
00735 struct vertexuse *vu;
00736 struct loopuse *lu;
00737 struct edgeuse *this_eu;
00738 int next_ass;
00739 int prev_ass;
00740 int ass;
00741
00742 NMG_CK_RAYSTATE(rs);
00743 vu = rs->vu[pos];
00744 NMG_CK_VERTEXUSE( vu );
00745 if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC ) {
00746 return NMG_V_ASSESSMENT_LONE;
00747 }
00748 if( (lu = nmg_find_lu_of_vu(vu)) == (struct loopuse *)0 )
00749 rt_bomb("nmg_assess_vu: no lu\n");
00750 this_eu = nmg_find_eu_with_vu_in_lu( lu, vu );
00751
00752 if( this_eu != vu->up.eu_p ) bu_log("nmg_assess_vu() eu mis-match? x%x x%x\n", this_eu, vu->up.eu_p);
00753 prev_ass = nmg_assess_eu( this_eu, 0, rs, pos );
00754 next_ass = nmg_assess_eu( this_eu, 1, rs, pos );
00755 if( prev_ass < 0 || next_ass < 0 ) {
00756 ass = NMG_V_ASSESSMENT_ERROR;
00757 } else {
00758 ass = NMG_V_COMB( prev_ass, next_ass );
00759 }
00760
00761
00762
00763
00764
00765
00766
00767 if( ass==NMG_ON_REV_ON_FORW || ass==NMG_ON_FORW_ON_REV ) {
00768 struct edgeuse *prev;
00769 struct edgeuse *next;
00770 prev = BU_LIST_PPREV_CIRC( edgeuse, this_eu );
00771 next = BU_LIST_PNEXT_CIRC( edgeuse, this_eu );
00772 if( prev->vu_p->v_p != next->vu_p->v_p ) {
00773 bu_log("nmg_assess_vu() %s, v=x%x, prev_v=x%x, next_v=x%x\n",
00774 nmg_v_assessment_names[ass],
00775 this_eu->vu_p->v_p,
00776 prev->vu_p->v_p, next->vu_p->v_p );
00777 bu_log("nmg_assess_vu() ON/ON edgeuse ends on different vertices.\n");
00778 VPRINT("vu ", this_eu->vu_p->v_p->vg_p->coord);
00779 VPRINT("prev", prev->vu_p->v_p->vg_p->coord);
00780 VPRINT("next", next->vu_p->v_p->vg_p->coord);
00781
00782
00783 bu_log("vu dist=%e, next dist=%e, tol=%e\n",
00784 bn_dist_line3_pt3( rs->pt, rs->dir, this_eu->vu_p->v_p->vg_p->coord ),
00785 bn_dist_line3_pt3( rs->pt, rs->dir, prev->vu_p->v_p->vg_p->coord ),
00786 rs->tol->dist );
00787 #if 0
00788
00789 if( nmg_break_long_edges( nmg_find_s_of_eu(this_eu), rs->tol ) > 0 )
00790 bu_log("\tnmg_break_long_edges succeeded\n");
00791 #endif
00792 rt_bomb("nmg_assess_vu() ON/ON edgeuse ends on different vertices.\n");
00793 }
00794 }
00795 if(rt_g.NMG_debug&DEBUG_FCUT) {
00796 bu_log("nmg_assess_vu() vu[%d]=x%x, v=x%x: %s\n",
00797 pos, vu, vu->v_p, nmg_v_assessment_names[ass] );
00798 }
00799 return ass;
00800 }
00801
00802 struct nmg_vu_stuff {
00803 struct vertexuse *vu;
00804 int loop_index;
00805 struct nmg_loop_stuff *lsp;
00806 fastf_t in_vu_angle;
00807 fastf_t out_vu_angle;
00808 fastf_t min_vu_dot;
00809 fastf_t lo_ang;
00810 fastf_t hi_ang;
00811 int seq;
00812 int wedge_class;
00813 };
00814 struct nmg_loop_stuff {
00815 struct loopuse *lu;
00816 fastf_t min_dot;
00817 struct vertexuse *min_vu;
00818 int n_vu_in_loop;
00819 };
00820
00821 #define WEDGE_LEFT 0
00822 #define WEDGE_CROSS 1
00823 #define WEDGE_RIGHT 2
00824 #define WEDGE_ON 3
00825 #define WEDGECLASS2STR(_cl) nmg_wedgeclass_string[(_cl)]
00826 static const char *nmg_wedgeclass_string[] = {
00827 "LEFT",
00828 "CROSS",
00829 "RIGHT",
00830 "ON",
00831 "???"
00832 };
00833
00834
00835
00836
00837 void
00838 nmg_pr_vu_stuff(const struct nmg_vu_stuff *vs)
00839 {
00840 bu_log("nmg_pr_vu_stuff(x%x) vu=x%x, loop_index=%d, lsp=x%x\n",
00841 vs, vs->vu, vs->loop_index, vs->lsp);
00842 bu_log(" in_vu_angle=%g, out_vu_angle=%g, min_vu_dot=%g\n",
00843 vs->in_vu_angle, vs->out_vu_angle, vs->min_vu_dot);
00844 bu_log(" lo_ang=%g, hi_ang=%g, seq=%d, wedge_class=%s\n",
00845 vs->lo_ang, vs->hi_ang, vs->seq,
00846 WEDGECLASS2STR(vs->wedge_class) );
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 int
00869 nmg_wedge_class(int ass, double a, double b)
00870
00871
00872
00873 {
00874 double ha, hb;
00875 register int ret;
00876
00877 ha = a - 180;
00878 hb = b - 180;
00879
00880 if( ass == NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW, NMG_E_ASSESSMENT_ON_FORW) ) {
00881 ret = WEDGE_ON;
00882 goto out;
00883 }
00884 if( ass == NMG_V_COMB(NMG_E_ASSESSMENT_ON_REV, NMG_E_ASSESSMENT_ON_REV) ) {
00885 ret = WEDGE_ON;
00886 goto out;
00887 }
00888
00889 if( NEAR_ZERO( ha, .01 ) ) {
00890
00891 if( NEAR_ZERO( hb, .01 ) ) {
00892
00893
00894
00895
00896
00897 if(rt_g.NMG_debug&DEBUG_VU_SORT)
00898 bu_log("nmg_wedge_class() 0-angle wedge\n");
00899 ret = WEDGE_CROSS;
00900 goto out;
00901 }
00902 if( hb < 0 ) {
00903 ret = WEDGE_RIGHT;
00904 goto out;
00905 }
00906 ret = WEDGE_LEFT;
00907 goto out;
00908 }
00909 if( ha < 0 ) {
00910
00911 if( hb <= 0 ) {
00912 ret = WEDGE_RIGHT;
00913 goto out;
00914 }
00915 ret = WEDGE_CROSS;
00916 goto out;
00917 }
00918
00919 if( NEAR_ZERO( hb, .01 ) ) {
00920
00921 ret = WEDGE_LEFT;
00922 goto out;
00923 }
00924 if( hb >= 0 ) {
00925
00926 ret = WEDGE_LEFT;
00927 goto out;
00928 }
00929
00930 ret = WEDGE_CROSS;
00931 out:
00932 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
00933 bu_log("nmg_wedge_class(%g,%g) = %s\n",
00934 a, b, WEDGECLASS2STR(ret) );
00935 }
00936 return ret;
00937 }
00938
00939 static const char *nmg_wedge2_string[] = {
00940 "WEDGE2_OVERLAP",
00941 "WEDGE2_NO_OVERLAP",
00942 "WEDGE2_AB_IN_CD",
00943 "WEDGE2_CD_IN_AB",
00944 "WEDGE2_IDENTICAL",
00945 "WEDGE2_TOUCH_AT_BC",
00946 "WEDGE2_TOUCH_AT_DA",
00947 "WEDGE2_???"
00948 };
00949 #define WEDGE2_TO_STRING(_class2) (nmg_wedge2_string[(_class2)+2])
00950
00951 #define WEDGE2_OVERLAP -2
00952 #define WEDGE2_NO_OVERLAP -1
00953 #define WEDGE2_AB_IN_CD 0
00954 #define WEDGE2_CD_IN_AB 1
00955 #define WEDGE2_IDENTICAL 2
00956 #define WEDGE2_TOUCH_AT_BC 3
00957 #define WEDGE2_TOUCH_AT_DA 4
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 static int
00972 nmg_compare_2_wedges(double a, double b, double c, double d)
00973 {
00974 double t;
00975 int a_in_cd = 0;
00976 int b_in_cd = 0;
00977 int c_in_ab = 0;
00978 int d_in_ab = 0;
00979 int a_eq_b = 0;
00980 int a_eq_c = 0;
00981 int a_eq_d = 0;
00982 int b_eq_c = 0;
00983 int b_eq_d = 0;
00984 int c_eq_d = 0;
00985 int ret;
00986
00987 #define WEDGE_ANG_TOL 0.001
00988 #define ANG_SMASH(_a) {\
00989 if( _a <= WEDGE_ANG_TOL ) _a = 0; \
00990 else if( NEAR_ZERO( _a - 180, WEDGE_ANG_TOL ) ) _a = 180; \
00991 else if( _a >= 360 - WEDGE_ANG_TOL ) _a = 360; }
00992
00993 ANG_SMASH(a);
00994 ANG_SMASH(b);
00995 ANG_SMASH(c);
00996 ANG_SMASH(d);
00997
00998
00999 if( a > b ) {
01000 t = a;
01001 a = b;
01002 b = t;
01003 }
01004
01005 if( c > d ) {
01006 t = c;
01007 c = d;
01008 d = t;
01009 }
01010
01011 if( NEAR_ZERO( a-b, WEDGE_ANG_TOL ) ) a_eq_b = 1;
01012 if( NEAR_ZERO( a-c, WEDGE_ANG_TOL ) ) a_eq_c = 1;
01013 if( NEAR_ZERO( a-d, WEDGE_ANG_TOL ) ) a_eq_d = 1;
01014 if( NEAR_ZERO( b-c, WEDGE_ANG_TOL ) ) b_eq_c = 1;
01015 if( NEAR_ZERO( b-d, WEDGE_ANG_TOL ) ) b_eq_d = 1;
01016 if( NEAR_ZERO( c-d, WEDGE_ANG_TOL ) ) c_eq_d = 1;
01017
01018
01019
01020
01021
01022
01023 if( b_eq_c ) {
01024
01025 if( a_eq_d )
01026 ret = WEDGE2_IDENTICAL;
01027 else
01028 ret = WEDGE2_TOUCH_AT_BC;
01029 goto out;
01030 }
01031
01032 if( a_eq_d ) {
01033
01034 if( b_eq_c ) {
01035 ret = WEDGE2_IDENTICAL;
01036 goto out;
01037 }
01038 if( a_eq_b ) {
01039 ret = WEDGE2_AB_IN_CD;
01040 } else if( c_eq_d ) {
01041 ret = WEDGE2_CD_IN_AB;
01042 } else {
01043 ret = WEDGE2_TOUCH_AT_DA;
01044 }
01045 goto out;
01046 }
01047
01048 if( a_eq_c ) {
01049 if( b_eq_d ) {
01050 ret = WEDGE2_IDENTICAL;
01051 goto out;
01052 }
01053
01054 if( b < d ) ret = WEDGE2_AB_IN_CD;
01055 else ret = WEDGE2_CD_IN_AB;
01056 goto out;
01057 }
01058
01059 if( b_eq_d ) {
01060
01061 if( a < c ) ret = WEDGE2_CD_IN_AB;
01062 else ret = WEDGE2_AB_IN_CD;
01063 goto out;
01064 }
01065
01066
01067 if( c <= a && a <= d ) a_in_cd = 1;
01068 if( c <= b && b <= d ) b_in_cd = 1;
01069
01070 if( a < c && c < b ) c_in_ab = 1;
01071 if( a < d && d < b ) d_in_ab = 1;
01072
01073 if( a_in_cd && b_in_cd ) {
01074 if( c_in_ab || d_in_ab ) {
01075 ret = WEDGE2_OVERLAP;
01076 goto out;
01077 }
01078 ret = WEDGE2_AB_IN_CD;
01079 goto out;
01080 }
01081 if( c_in_ab && d_in_ab ) {
01082 if( a_in_cd || b_in_cd ) {
01083 ret = WEDGE2_OVERLAP;
01084 goto out;
01085 }
01086 ret = WEDGE2_CD_IN_AB;
01087 goto out;
01088 }
01089 if( a_in_cd + b_in_cd + c_in_ab + d_in_ab <= 0 ) {
01090 ret = WEDGE2_NO_OVERLAP;
01091 goto out;
01092 }
01093 ret = WEDGE2_OVERLAP;
01094 out:
01095 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01096 bu_log(" a_in_cd=%d, b_in_cd=%d, c_in_ab=%d, d_in_ab=%d\n",
01097 a_in_cd, b_in_cd, c_in_ab, d_in_ab );
01098 bu_log("nmg_compare_2_wedges(%g,%g, %g,%g) = %d %s\n",
01099 a, b, c, d, ret, WEDGE2_TO_STRING(ret) );
01100 }
01101 if(ret <= WEDGE2_OVERLAP ) {
01102 bu_log("nmg_compare_2_wedges(%g,%g, %g,%g) ERROR!\n", a, b, c, d);
01103 rt_bomb("nmg_compare_2_wedges() ERROR\n");
01104 }
01105 return ret;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 static int
01126 nmg_find_vu_in_wedge(struct nmg_vu_stuff *vs, int start, int end, double lo_ang, double hi_ang, int wclass, int *skip_array)
01127
01128
01129
01130
01131
01132
01133
01134 {
01135 register int i;
01136 double cand_lo;
01137 double cand_hi;
01138 int candidate;
01139
01140 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01141 bu_log("nmg_find_vu_in_wedge(start=%d,end=%d, lo=%g, hi=%g) START\n",
01142 start, end, lo_ang, hi_ang);
01143
01144 candidate = -1;
01145 cand_lo = lo_ang;
01146 cand_hi = hi_ang;
01147
01148
01149 for( i=start; i < end; i++ ) {
01150 int this_wrt_orig;
01151 int this_wrt_cand;
01152
01153 NMG_CK_VERTEXUSE( vs[i].vu );
01154 if( skip_array[i] ) {
01155 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01156 bu_log("Skipping index %d\n", i);
01157 continue;
01158 }
01159
01160
01161 if( vs[i].wedge_class != wclass && vs[i].wedge_class != WEDGE_ON ) {
01162 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01163 bu_log("Seeking wedge_class=%s, [%d] has wedge_class %s\n",
01164 WEDGECLASS2STR(wclass), i, WEDGECLASS2STR(vs[i].wedge_class) );
01165 }
01166 continue;
01167 }
01168
01169 if( vs[i].wedge_class == WEDGE_ON ) {
01170
01171 if( wclass == WEDGE_RIGHT ) {
01172 vs[i].lo_ang = 0;
01173 vs[i].hi_ang = 180;
01174 } else {
01175 vs[i].lo_ang = 360;
01176 vs[i].hi_ang = 180;
01177 }
01178 }
01179
01180 this_wrt_orig = nmg_compare_2_wedges(
01181 vs[i].lo_ang, vs[i].hi_ang,
01182 lo_ang, hi_ang );
01183 switch( this_wrt_orig ) {
01184 case WEDGE2_AB_IN_CD:
01185 break;
01186 case WEDGE2_IDENTICAL:
01187 candidate = i;
01188 goto out;
01189 default:
01190 continue;
01191 }
01192
01193 if( candidate < 0 ) {
01194
01195
01196
01197 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01198 bu_log("Initial candidate %d selected\n", i);
01199 candidate = i;
01200 cand_lo = vs[i].lo_ang;
01201 cand_hi = vs[i].hi_ang;
01202 continue;
01203 }
01204
01205 this_wrt_cand = nmg_compare_2_wedges(
01206 vs[i].lo_ang, vs[i].hi_ang,
01207 cand_lo, cand_hi );
01208 switch( this_wrt_cand ) {
01209 case WEDGE2_CD_IN_AB:
01210
01211
01212 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01213 bu_log("This candidate %d is closer\n", i);
01214 candidate = i;
01215 cand_lo = vs[i].lo_ang;
01216 cand_hi = vs[i].hi_ang;
01217 break;
01218 case WEDGE2_NO_OVERLAP:
01219
01220 if( vs[i].lo_ang < cand_lo ) {
01221 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01222 bu_log("Taking lower angle %d\n", i);
01223 candidate = i;
01224 cand_lo = vs[i].lo_ang;
01225 cand_hi = vs[i].hi_ang;
01226 }
01227 break;
01228 default:
01229 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01230 bu_log("Continuing with search\n");
01231 continue;
01232 }
01233 }
01234 out:
01235 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01236 bu_log("nmg_find_vu_in_wedge(start=%d,end=%d, lo=%g, hi=%g) END candidate=%d\n",
01237 start, end, lo_ang, hi_ang,
01238 candidate);
01239 return candidate;
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 static int
01254 nmg_is_wedge_before_cross(const struct nmg_vu_stuff *wedge, const struct nmg_vu_stuff *cross)
01255 {
01256 int class2;
01257 int ret = -1;
01258
01259 if( cross->wedge_class != WEDGE_CROSS || wedge->wedge_class == WEDGE_CROSS )
01260 rt_bomb("nmg_is_wedge_before_cross() bad input\n");
01261
01262
01263 class2 = nmg_compare_2_wedges( wedge->lo_ang, wedge->hi_ang,
01264 cross->lo_ang, cross->hi_ang );
01265
01266 switch(class2) {
01267 default:
01268 bu_log("nmg_is_wedge_before_cross() class2=%s\n",
01269 WEDGE2_TO_STRING(class2) );
01270 rt_bomb("nmg_is_wedge_before_cross(): bad wedge comparison\n");
01271 case WEDGE2_NO_OVERLAP:
01272
01273
01274 ret = 1;
01275 break;
01276 case WEDGE2_TOUCH_AT_BC:
01277
01278 if( wedge->wedge_class != WEDGE_RIGHT )
01279 rt_bomb("WEDGE not RIGHT with WEDGE2_TOUCH_AT_BC?\n");
01280 ret = 1;
01281 break;
01282 case WEDGE2_TOUCH_AT_DA:
01283
01284 if( wedge->wedge_class != WEDGE_LEFT )
01285 rt_bomb("WEDGE not LEFT with WEDGE2_TOUCH_AT_DA?\n");
01286 ret = 1;
01287 break;
01288 case WEDGE2_AB_IN_CD:
01289
01290 ret = 0;
01291 break;
01292 }
01293 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01294 bu_log("nmg_is_wedge_before_cross() class2=%s, ret=%d\n",
01295 WEDGE2_TO_STRING(class2), ret );
01296 }
01297 return ret;
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315 #define A_LT_B {ret = -1; goto out;}
01316 #define AB_EQUAL {ret = 0; goto out;}
01317 #define A_GT_B {ret = 1; goto out;}
01318 static int
01319 nmg_face_vu_compare(const void *aa, const void *bb)
01320 #if __STDC__
01321
01322
01323 #else
01324
01325
01326 #endif
01327 {
01328 register const struct nmg_vu_stuff *a = (const struct nmg_vu_stuff *)aa;
01329 register const struct nmg_vu_stuff *b = (const struct nmg_vu_stuff *)bb;
01330 register double diff;
01331 int lo_equal = 0;
01332 int hi_equal = 0;
01333 register int ret = 0;
01334
01335 lo_equal = NEAR_ZERO( a->lo_ang - b->lo_ang, WEDGE_ANG_TOL );
01336 hi_equal = NEAR_ZERO( a->hi_ang - b->hi_ang, WEDGE_ANG_TOL );
01337
01338 if( a->wedge_class == b->wedge_class && lo_equal && hi_equal ) {
01339
01340 tie_break:
01341 if( a->loop_index == b->loop_index ) {
01342
01343 if( a->seq < b->seq ) A_LT_B;
01344 if( a->seq == b->seq ) AB_EQUAL;
01345 A_GT_B;
01346 }
01347
01348 diff = a->in_vu_angle - b->in_vu_angle;
01349 if( NEAR_ZERO( diff, WEDGE_ANG_TOL ) ) {
01350
01351 bu_log("nmg_face_vu_compare(): two loops (single vertex) have same in_vu_angle%g?\n",
01352 a->in_vu_angle);
01353 nmg_pr_vu_stuff(a);
01354 nmg_pr_vu_stuff(b);
01355 rt_bomb("nmg_face_vu_compare(): can't decide\n");
01356 AB_EQUAL;
01357 }
01358 if( diff < 0 ) A_LT_B;
01359 A_GT_B;
01360 }
01361 switch( a->wedge_class ) {
01362 case WEDGE_ON:
01363 switch( b->wedge_class ) {
01364 case WEDGE_ON:
01365 goto tie_break;
01366 default:
01367 nmg_pr_vu_stuff(a);
01368 nmg_pr_vu_stuff(b);
01369 rt_bomb("nmg_face_vu_compare() WEDGE_ON 1?\n");
01370 }
01371 break;
01372 case WEDGE_LEFT:
01373 switch( b->wedge_class ) {
01374 case WEDGE_LEFT:
01375 if( lo_equal ) {
01376
01377 if( a->hi_ang < b->hi_ang ) A_LT_B;
01378 A_GT_B;
01379 }
01380 if( a->lo_ang > b->lo_ang ) A_LT_B;
01381 A_GT_B;
01382 case WEDGE_CROSS:
01383
01384 if( nmg_is_wedge_before_cross( a, b ) ) A_LT_B;
01385 A_GT_B;
01386 case WEDGE_RIGHT:
01387 diff = 360 - a->lo_ang;
01388 if( b->lo_ang <= diff ) A_GT_B;
01389 A_LT_B;
01390 case WEDGE_ON:
01391 nmg_pr_vu_stuff(a);
01392 nmg_pr_vu_stuff(b);
01393 rt_bomb("nmg_face_vu_compare() WEDGE_ON 2?\n");
01394 }
01395 case WEDGE_CROSS:
01396 switch( b->wedge_class ) {
01397 case WEDGE_LEFT:
01398
01399 if( nmg_is_wedge_before_cross( b, a ) ) A_GT_B;
01400 A_LT_B;
01401 case WEDGE_CROSS:
01402 if( lo_equal ) {
01403 if( a->hi_ang > b->hi_ang ) A_LT_B;
01404 A_GT_B;
01405 }
01406 if( a->lo_ang < b->lo_ang ) A_LT_B;
01407 A_GT_B;
01408 case WEDGE_RIGHT:
01409
01410 if( nmg_is_wedge_before_cross( b, a ) ) A_GT_B;
01411 A_LT_B;
01412 case WEDGE_ON:
01413 nmg_pr_vu_stuff(a);
01414 nmg_pr_vu_stuff(b);
01415 rt_bomb("nmg_face_vu_compare() WEDGE_ON 3?\n");
01416 }
01417 case WEDGE_RIGHT:
01418 switch( b->wedge_class ) {
01419 case WEDGE_LEFT:
01420 diff = 360 - b->lo_ang;
01421 if( a->lo_ang <= diff ) A_LT_B;
01422 A_GT_B;
01423 case WEDGE_CROSS:
01424
01425 if( nmg_is_wedge_before_cross( a, b ) ) A_LT_B;
01426 A_GT_B;
01427 case WEDGE_RIGHT:
01428 if( lo_equal ) {
01429 if( a->hi_ang < b->hi_ang ) A_GT_B;
01430 A_LT_B;
01431 }
01432 if( a->lo_ang < b->lo_ang ) A_LT_B;
01433 A_GT_B;
01434 case WEDGE_ON:
01435 nmg_pr_vu_stuff(a);
01436 nmg_pr_vu_stuff(b);
01437 rt_bomb("nmg_face_vu_compare() WEDGE_ON 4?\n");
01438 }
01439 }
01440 out:
01441 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01442 bu_log("nmg_face_vu_compare(vu=x%x, vu=x%x) %s %s, %s\n",
01443 a->vu, b->vu,
01444 WEDGECLASS2STR(a->wedge_class),
01445 WEDGECLASS2STR(b->wedge_class),
01446 ret==(-1) ? "A<B" : (ret==0 ? "A==B" : "A>B") );
01447 }
01448 return ret;
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 static void
01462 nmg_face_vu_dot(struct nmg_vu_stuff *vsp, struct loopuse *lu, const struct nmg_ray_state *rs, int ass)
01463 {
01464 struct edgeuse *this_eu;
01465 struct edgeuse *othereu;
01466 vect_t vec;
01467 fastf_t dot;
01468 struct vertexuse *vu;
01469 int this;
01470
01471 NMG_CK_RAYSTATE(rs);
01472 vu = vsp->vu;
01473 NMG_CK_VERTEXUSE(vu);
01474 NMG_CK_LOOPUSE(lu);
01475 this_eu = nmg_find_eu_with_vu_in_lu( lu, vu );
01476
01477
01478 this = NMG_V_ASSESSMENT_PREV(ass);
01479 if( this == NMG_E_ASSESSMENT_ON_REV ) {
01480 vsp->min_vu_dot = -1;
01481 } else if( this == NMG_E_ASSESSMENT_ON_FORW ) {
01482 vsp->min_vu_dot = 1;
01483 } else {
01484 othereu = BU_LIST_PPREV_CIRC( edgeuse, this_eu );
01485 if( vu->v_p != othereu->vu_p->v_p ) {
01486
01487 VSUB2( vec, vu->v_p->vg_p->coord,
01488 othereu->vu_p->v_p->vg_p->coord );
01489 VUNITIZE(vec);
01490 vsp->min_vu_dot = VDOT( vec, rs->dir );
01491 } else {
01492 vsp->min_vu_dot = 99;
01493 }
01494 }
01495
01496
01497 this = NMG_V_ASSESSMENT_NEXT(ass);
01498 if( this == NMG_E_ASSESSMENT_ON_REV ) {
01499 dot = -1;
01500 if( dot < vsp->min_vu_dot ) vsp->min_vu_dot = dot;
01501 } else if( this == NMG_E_ASSESSMENT_ON_FORW ) {
01502 dot = 1;
01503 if( dot < vsp->min_vu_dot ) vsp->min_vu_dot = dot;
01504 } else {
01505 othereu = BU_LIST_PNEXT_CIRC( edgeuse, this_eu );
01506 if( vu->v_p != othereu->vu_p->v_p ) {
01507
01508 VSUB2( vec, vu->v_p->vg_p->coord,
01509 othereu->vu_p->v_p->vg_p->coord );
01510 VUNITIZE(vec);
01511 dot = VDOT( vec, rs->dir );
01512 if( dot < vsp->min_vu_dot ) {
01513 vsp->min_vu_dot = dot;
01514 }
01515 }
01516 }
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 static int
01534 nmg_special_wedge_processing(struct nmg_vu_stuff *vs, int start, int end, double lo_ang, double hi_ang, int wclass, int *exclude, const struct bn_tol *tol)
01535
01536
01537
01538
01539
01540
01541
01542
01543 {
01544 register int i;
01545 int outer_wedge;
01546 int inner_wedge;
01547 int class2;
01548 struct loopuse *outer_lu;
01549 struct loopuse *inner_lu;
01550 int not_these[128];
01551
01552 BN_CK_TOL(tol);
01553
01554 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01555 char buf[128];
01556 FILE *fp;
01557 struct model *m;
01558 long *b;
01559 struct bn_vlblock *vbp;
01560 static int num = 0;
01561
01562 bu_log("nmg_special_wedge_processing(start=%d,end=%d, lo=%g, hi=%g, wclass=%s)\n",
01563 start, end, lo_ang, hi_ang,
01564 WEDGECLASS2STR(wclass) );
01565 VPRINT("\tvertex", vs[start].vu->v_p->vg_p->coord);
01566
01567
01568 m = nmg_find_model((long *)vs[start].vu);
01569 b = (long *)bu_calloc( m->maxindex, sizeof(long), "nmg_special_wedge_processing flag[]" );
01570 vbp = rt_vlblock_init();
01571 for( i=start; i < end; i++ ) {
01572 struct loopuse *lu;
01573 lu = nmg_find_lu_of_vu(vs[i].vu);
01574 bu_log("\tvu[%d]=x%x, lu=x%x\n", i, vs[i].vu, lu);
01575 nmg_vlblock_lu(vbp, lu, b, 255, 0, 0, 0, 0 );
01576 }
01577 for( i=start; i < end; i++ ) {
01578 struct loopuse *lu;
01579 lu = nmg_find_lu_of_vu(vs[i].vu);
01580 nmg_pr_lu_briefly(lu,0);
01581 }
01582 sprintf(buf, "wedge%d.pl", num++);
01583 fp = fopen(buf, "w");
01584 rt_plot_vlblock( fp, vbp );
01585 fclose(fp);
01586 bu_log("wrote %s\n", buf);
01587 bu_free( (char *)b, "nmg_special_wedge_processing flag[]" );
01588 rt_vlblock_free(vbp);
01589 }
01590
01591 if( end-start >= 128 ) rt_bomb("nmg_special_wedge_processing: array overflow\n");
01592 if( !exclude ) {
01593 bzero( (char *)not_these, sizeof(not_these) );
01594 exclude = not_these;
01595 }
01596
01597 again:
01598
01599 outer_wedge = nmg_find_vu_in_wedge( vs, start, end,
01600 lo_ang, hi_ang, wclass, exclude );
01601 if( outer_wedge <= -1 ) return 0;
01602
01603 exclude[outer_wedge] = 1;
01604
01605
01606 outer_lu = nmg_find_lu_of_vu( vs[outer_wedge].vu );
01607 NMG_CK_LOOPUSE(outer_lu);
01608
01609 again_inner:
01610 inner_wedge = nmg_find_vu_in_wedge( vs, start, end,
01611 vs[outer_wedge].lo_ang, vs[outer_wedge].hi_ang,
01612 wclass, exclude );
01613 if( inner_wedge <= -1 ) {
01614
01615
01616
01617
01618
01619 goto again;
01620 }
01621 if( inner_wedge == outer_wedge ) rt_bomb("nmg_special_wedge_processing() identical vu selections?\n");
01622
01623 class2 = nmg_compare_2_wedges( vs[outer_wedge].lo_ang, vs[outer_wedge].hi_ang,
01624 vs[inner_wedge].lo_ang, vs[inner_wedge].hi_ang );
01625 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01626 bu_log("+++nmg_special_wedge_processing() outer=%d, inner=%d, class2=%s\n", outer_wedge, inner_wedge, WEDGE2_TO_STRING(class2) );
01627
01628 inner_lu = nmg_find_lu_of_vu( vs[inner_wedge].vu );
01629 NMG_CK_LOOPUSE(inner_lu);
01630
01631 if( outer_lu == inner_lu ) {
01632 struct loopuse *new_lu;
01633 if( class2 == WEDGE2_IDENTICAL &&
01634 NEAR_ZERO( vs[inner_wedge].hi_ang - vs[inner_wedge].lo_ang, WEDGE_ANG_TOL )
01635 ) {
01636 #if 0
01637 rt_g.NMG_debug |= DEBUG_VU_SORT|DEBUG_FCUT;
01638 #endif
01639 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01640 bu_log("nmg_special_wedge_processing: inner and outer wedges from same loop, WEDGE2_IDENTICAL & 0deg spread, already in final form.\n");
01641 exclude[inner_wedge] = 1;
01642
01643 goto again_inner;
01644 }
01645 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01646 bu_log("nmg_special_wedge_processing: inner and outer wedges from same loop, cutting loop\n");
01647 new_lu = nmg_cut_loop( vs[outer_wedge].vu, vs[inner_wedge].vu );
01648 NMG_CK_LOOPUSE(new_lu);
01649 NMG_CK_LOOPUSE(inner_lu);
01650 nmg_loop_g( inner_lu->l_p, tol );
01651 nmg_loop_g( new_lu->l_p, tol );
01652 nmg_lu_reorient(inner_lu);
01653 nmg_lu_reorient(new_lu);
01654 return 1;
01655 }
01656
01657
01658
01659 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01660 bu_log("wedge at vu[%d] is inside wedge at vu[%d]\n", inner_wedge, outer_wedge);
01661
01662 if( outer_lu->orientation == inner_lu->orientation ) {
01663
01664
01665
01666
01667 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01668 bu_log("joining loops\n");
01669 vs[inner_wedge].vu = nmg_join_2loops( vs[outer_wedge].vu,
01670 vs[inner_wedge].vu );
01671 nmg_loop_g( outer_lu->l_p, tol );
01672 return 1;
01673 }
01674
01675
01676 if( nmg_special_wedge_processing( vs, start, end,
01677 vs[inner_wedge].lo_ang, vs[inner_wedge].hi_ang, wclass, exclude, tol ) )
01678 return 1;
01679
01680
01681
01682
01683
01684
01685
01686 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01687 bu_log("Inner wedge is simple, join inner and outer loops.\n");
01688
01689 vs[inner_wedge].vu = nmg_join_2loops( vs[outer_wedge].vu,
01690 vs[inner_wedge].vu );
01691 nmg_loop_g( outer_lu->l_p, tol );
01692 return 1;
01693 }
01694
01695
01696
01697
01698
01699
01700
01701 int
01702 nmg_face_coincident_vu_sort(struct nmg_ray_state *rs, int start, int end)
01703
01704
01705
01706 {
01707 int num;
01708 struct nmg_vu_stuff *vs;
01709 struct nmg_loop_stuff *ls;
01710 int nloop;
01711 unsigned nvu;
01712 int i;
01713 struct loopuse *lu;
01714 int ass;
01715 int l;
01716 int retries = 0;
01717
01718 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01719 bu_log("nmg_face_coincident_vu_sort(, %d, %d) START\n", start, end);
01720
01721 NMG_CK_RAYSTATE(rs);
01722
01723 num = end - start;
01724 vs = (struct nmg_vu_stuff *)bu_malloc( sizeof(struct nmg_vu_stuff)*num,
01725 "nmg_vu_stuff" );
01726 ls = (struct nmg_loop_stuff *)bu_malloc( sizeof(struct nmg_loop_stuff)*num,
01727 "nmg_loop_stuff" );
01728
01729 top:
01730 #if 0
01731 if( retries > 20 ) rt_g.NMG_debug |= DEBUG_VU_SORT;
01732 #endif
01733 if( retries++ > 24 ) rt_bomb("nmg_face_coincident_vu_sort() infinite loop\n");
01734
01735 nloop = 0;
01736 nvu = 0;
01737 for( i = end-1; i >= start; i-- ) {
01738 lu = nmg_find_lu_of_vu( rs->vu[i] );
01739 NMG_CK_LOOPUSE(lu);
01740 ass = nmg_assess_vu( rs, i );
01741 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01742 bu_log("vu[%d]=x%x v=x%x assessment=%s\n",
01743 i, rs->vu[i], rs->vu[i]->v_p, nmg_v_assessment_names[ass] );
01744
01745
01746
01747 if( *(rs->vu[i]->up.magic_p) == NMG_LOOPUSE_MAGIC ) {
01748 if( nvu > 0 || i > start ) {
01749
01750 lu->orientation =
01751 lu->lumate_p->orientation = OT_BOOLPLACE;
01752
01753 continue;
01754 }
01755 }
01756
01757 vs[nvu].vu = rs->vu[i];
01758 vs[nvu].seq = -1;
01759
01760
01761 vs[nvu].in_vu_angle = nmg_vu_angle_measure( rs->vu[i],
01762 rs->ang_x_dir, rs->ang_y_dir, ass, 1 ) * bn_radtodeg;
01763 vs[nvu].out_vu_angle = nmg_vu_angle_measure( rs->vu[i],
01764 rs->ang_x_dir, rs->ang_y_dir, ass, 0 ) * bn_radtodeg;
01765
01766
01767 if( ass == NMG_V_COMB(NMG_E_ASSESSMENT_ON_FORW, NMG_E_ASSESSMENT_LEFT) )
01768 vs[nvu].in_vu_angle = 360;
01769 else if( ass == NMG_V_COMB(NMG_E_ASSESSMENT_LEFT, NMG_E_ASSESSMENT_ON_REV) )
01770 vs[nvu].out_vu_angle = 360;
01771
01772 vs[nvu].wedge_class = nmg_wedge_class( ass, vs[nvu].in_vu_angle, vs[nvu].out_vu_angle );
01773 if(rt_g.NMG_debug&DEBUG_VU_SORT) bu_log("nmg_wedge_class = %d %s\n", vs[nvu].wedge_class, WEDGECLASS2STR(vs[nvu].wedge_class));
01774
01775 if( (vs[nvu].wedge_class == WEDGE_LEFT && vs[nvu].in_vu_angle > vs[nvu].out_vu_angle) ||
01776 (vs[nvu].wedge_class != WEDGE_LEFT && vs[nvu].in_vu_angle < vs[nvu].out_vu_angle) ) {
01777 vs[nvu].lo_ang = vs[nvu].in_vu_angle;
01778 vs[nvu].hi_ang = vs[nvu].out_vu_angle;
01779 } else {
01780 vs[nvu].lo_ang = vs[nvu].out_vu_angle;
01781 vs[nvu].hi_ang = vs[nvu].in_vu_angle;
01782 }
01783
01784
01785
01786
01787 nmg_face_vu_dot( &vs[nvu], lu, rs, ass );
01788
01789
01790 for( l = 0; l < nloop; l++ ) {
01791 if( ls[l].lu == lu ) goto got_loop;
01792 }
01793
01794 l = nloop++;
01795 ls[l].lu = lu;
01796 ls[l].n_vu_in_loop = 0;
01797 ls[l].min_dot = 99;
01798 got_loop:
01799 ls[l].n_vu_in_loop++;
01800 vs[nvu].loop_index = l;
01801 vs[nvu].lsp = &ls[l];
01802 if( vs[nvu].min_vu_dot < ls[l].min_dot ) {
01803 ls[l].min_dot = vs[nvu].min_vu_dot;
01804 ls[l].min_vu = vs[nvu].vu;
01805 }
01806 nvu++;
01807 }
01808
01809
01810
01811
01812
01813
01814
01815 for( l=0; l < nloop; l++ ) {
01816 register struct edgeuse *eu;
01817 struct edgeuse *first_eu;
01818 int seq = 0;
01819
01820 if( ls[l].n_vu_in_loop <= 1 ) continue;
01821
01822 first_eu = nmg_find_eu_with_vu_in_lu( ls[l].lu, ls[l].min_vu );
01823 eu = first_eu;
01824 do {
01825 register struct vertexuse *vu = eu->vu_p;
01826 NMG_CK_VERTEXUSE(vu);
01827 for( i=0; i < nvu; i++ ) {
01828 if( vs[i].vu == vu ) {
01829 vs[i].seq = seq++;
01830 break;
01831 }
01832 }
01833 eu = BU_LIST_PNEXT_CIRC(edgeuse,eu);
01834 } while( eu != first_eu );
01835 }
01836
01837
01838
01839
01840
01841 if( nmg_special_wedge_processing( vs, 0, nvu, 0.0, 180.0, WEDGE_RIGHT, (int *)0, rs->tol ) ) {
01842 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01843 bu_log("*** nmg_face_coincident_vu_sort(, %d, %d) restarting after 0--180 wedge\n", start, end);
01844 goto top;
01845 }
01846
01847 if( nmg_special_wedge_processing( vs, 0, nvu, 360.0, 180.0, WEDGE_LEFT, (int *)0, rs->tol ) ) {
01848 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01849 bu_log("*** nmg_face_coincident_vu_sort(, %d, %d) restarting after 180-360 wedge\n", start, end);
01850 goto top;
01851 }
01852
01853 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01854 {
01855 bu_log("Loop table (before sort):\n");
01856 for( l=0; l < nloop; l++ ) {
01857 bu_log(" index=%d, lu=x%x, min_dot=%g, #vu=%d\n",
01858 l, ls[l].lu, ls[l].min_dot,
01859 ls[l].n_vu_in_loop );
01860 }
01861 }
01862
01863
01864 qsort( (genptr_t)vs, (unsigned)nvu, (unsigned)sizeof(*vs),
01865 nmg_face_vu_compare );
01866
01867 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01868 {
01869 bu_log("Vertexuse table (after sort):\n");
01870 for( i=0; i < nvu; i++ ) {
01871 bu_log(" x%x, l=%d, in/o=(%g, %g), lo/hi=(%g,%g), %s, sq=%d\n",
01872 vs[i].vu, vs[i].loop_index,
01873 vs[i].in_vu_angle, vs[i].out_vu_angle,
01874 vs[i].lo_ang, vs[i].hi_ang,
01875 WEDGECLASS2STR(vs[i].wedge_class),
01876 vs[i].seq );
01877 }
01878 }
01879
01880
01881 #if 0
01882
01883 if( rs->state == NMG_STATE_IN ) {
01884
01885
01886
01887
01888
01889
01890 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01891 bu_log("Reversed processing order, state=IN.\n");
01892 for( i=0; i < nvu; i++ ) {
01893 rs->vu[start+i] = vs[nvu-1-i].vu;
01894 }
01895 } else
01896 #endif
01897 {
01898 for( i=0; i < nvu; i++ ) {
01899 rs->vu[start+i] = vs[i].vu;
01900 }
01901 }
01902 if(rt_g.NMG_debug&DEBUG_VU_SORT) {
01903 for( i=0; i < nvu; i++ ) {
01904 bu_log(" vu[%d]=x%x, v=x%x\n",
01905 start+i, rs->vu[start+i], rs->vu[start+i]->v_p );
01906 }
01907 }
01908
01909 bu_free( (char *)vs, "nmg_vu_stuff");
01910 bu_free( (char *)ls, "nmg_loop_stuff");
01911
01912 if(rt_g.NMG_debug&DEBUG_VU_SORT)
01913 bu_log("nmg_face_coincident_vu_sort(, %d, %d) END, ret=%d\n", start, end, start+nvu);
01914
01915 return start+nvu;
01916 }
01917
01918
01919
01920
01921
01922
01923 void
01924 nmg_sanitize_fu(struct faceuse *fu)
01925 {
01926 struct loopuse *lu;
01927 struct loopuse *lunext;
01928
01929 NMG_CK_FACEUSE(fu);
01930
01931 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
01932 while( BU_LIST_NOT_HEAD(lu, &fu->lu_hd) ) {
01933 NMG_CK_LOOPUSE(lu);
01934 lunext = BU_LIST_PNEXT(loopuse,lu);
01935 if( lu->orientation == OT_BOOLPLACE ) {
01936
01937 if( nmg_klu(lu) ) rt_bomb("nmg_sanitize_fu() nmg_klu() emptied face?\n");
01938 }
01939 lu = lunext;
01940 }
01941 }
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 void
01957 nmg_face_rs_init(struct nmg_ray_state *rs, struct bu_ptbl *b, struct faceuse *fu1, struct faceuse *fu2, fastf_t *pt, fastf_t *dir, struct edge_g_lseg *eg, const struct bn_tol *tol)
01958
01959
01960
01961
01962
01963
01964
01965
01966 {
01967 plane_t n1;
01968
01969 BN_CK_TOL(tol);
01970 BU_CK_PTBL(b);
01971 NMG_CK_FACEUSE(fu1);
01972 NMG_CK_FACEUSE(fu2);
01973 if(eg) NMG_CK_EDGE_G_LSEG(eg);
01974
01975 bzero( (char *)rs, sizeof(*rs) );
01976 rs->magic = NMG_RAYSTATE_MAGIC;
01977 rs->tol = tol;
01978 rs->vu = (struct vertexuse **)b->buffer;
01979 rs->nvu = b->end;
01980 rs->eg_p = eg;
01981 rs->sA = fu1->s_p;
01982 rs->sB = fu2->s_p;
01983 rs->fu1 = fu1;
01984 rs->fu2 = fu2;
01985 VMOVE( rs->pt, pt );
01986 VMOVE( rs->dir, dir );
01987 NMG_GET_FU_PLANE( n1, fu1 );
01988 VCROSS( rs->left, n1, dir );
01989 VUNITIZE( rs->left );
01990 switch( fu1->orientation ) {
01991 case OT_SAME:
01992 break;
01993 case OT_OPPOSITE:
01994 VREVERSE(rs->left, rs->left);
01995 break;
01996 default:
01997 rt_bomb("nmg_face_rs_init: bad orientation\n");
01998 }
01999 if(rt_g.NMG_debug&DEBUG_FCUT) {
02000 struct loopuse *lu;
02001 struct edgeuse *eu;
02002 struct vertexuse *vu;
02003 int i;
02004
02005 bu_log("\tfu->orientation=%s\n", nmg_orientation(fu1->orientation) );
02006 HPRINT("\tfg N", n1);
02007 VPRINT("\t pt", pt);
02008 VPRINT("\t dir", dir);
02009 VPRINT("\tleft", rs->left);
02010 bu_log( "\tvertexuses in fu that are on lintersect line:\n" );
02011 for( i=0 ; i<BU_PTBL_END( b ) ; i++ )
02012 {
02013 vu = (struct vertexuse *)BU_PTBL_GET( b , i );
02014 nmg_pr_vu_briefly( vu , "\t " );
02015 }
02016 bu_log( "\tLoopuse in fu (x%x):\n" , fu1 );
02017 for( BU_LIST_FOR( lu , loopuse , &fu1->lu_hd ) )
02018 {
02019 bu_log( "\tLOOPUSE x%x:\n" , lu );
02020 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
02021 {
02022 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
02023 nmg_pr_vu_briefly( vu , "\tVertex Loop: " );
02024 }
02025 else
02026 {
02027 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
02028 {
02029 struct edgeuse *eu_next;
02030 vect_t eu_dir;
02031 fastf_t eu_len;
02032 double inv_len;
02033
02034 nmg_pr_eu_briefly( eu , "\t\t" );
02035 eu_next = BU_LIST_PNEXT_CIRC( edgeuse , eu );
02036 VSUB2( eu_dir , eu_next->vu_p->v_p->vg_p->coord , eu->vu_p->v_p->vg_p->coord );
02037 eu_len = MAGNITUDE( eu_dir );
02038 if( eu_len < VDIVIDE_TOL )
02039 inv_len = 0.0;
02040 else
02041 inv_len = 1.0/eu_len;
02042 for( i=0 ; i<3 ; i++ )
02043 eu_dir[i] = eu_dir[i] * inv_len;
02044 bu_log( "\t\t\teu_dir = ( %g , %g , %g ), length = %g\n", V3ARGS( eu_dir ) , eu_len );
02045 }
02046 }
02047 }
02048 }
02049 rs->state = NMG_STATE_OUT;
02050
02051
02052 VREVERSE( rs->ang_x_dir, dir );
02053 VREVERSE( rs->ang_y_dir, rs->left );
02054 }
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067 HIDDEN int
02068 nmg_face_next_vu_interval(struct nmg_ray_state *rs, int cur, fastf_t *mag, int other_rs_state)
02069 {
02070 int j;
02071 int k;
02072 int m;
02073 struct vertex *v;
02074
02075 NMG_CK_RAYSTATE(rs);
02076 BN_CK_TOL(rs->tol);
02077 if(rs->eg_p) NMG_CK_EDGE_G_LSEG(rs->eg_p);
02078
02079 if( cur == rs->nvu-1 || mag[cur+1] != mag[cur] ) {
02080
02081 if(rt_g.NMG_debug&DEBUG_FCUT)
02082 bu_log("nmg_face_next_vu_interval() fu=x%x, single vertexuse at index %d\n", rs->fu1, cur);
02083 nmg_face_state_transition( rs, cur, 0, other_rs_state );
02084 #if PLOT_BOTH_FACES
02085 nmg_2face_plot( rs->fu1, rs->fu2 );
02086 #else
02087 nmg_face_plot( rs->fu1 );
02088 #endif
02089 return cur+1;
02090 }
02091
02092
02093 v = rs->vu[cur]->v_p;
02094 for( j = cur+1; j < rs->nvu; j++ ) {
02095
02096 if( mag[j] != mag[cur] ) break;
02097 #if 0
02098
02099
02100
02101 if( rs->vu[j]->v_p != v ) break;
02102 #endif
02103 }
02104
02105
02106 if(rt_g.NMG_debug&DEBUG_FCUT)
02107 bu_log("nmg_face_next_vu_interval() fu=x%x vu's on list interval [%d] to [%d] equal\n", rs->fu1, cur, j-1 );
02108
02109
02110 for( k = cur+1; k < j; k++ ) {
02111 if( rs->vu[k]->v_p == v ) continue;
02112
02113 bu_log("At k=%d, vertex changed from v=x%x!\n", k, v);
02114 bu_log("pt_equality=%d\n", bn_pt3_pt3_equal(v->vg_p->coord,
02115 rs->vu[k]->v_p->vg_p->coord, rs->tol ) );
02116 for( k = cur; k < j; k++ ) {
02117 bu_log(" %d vu=%8x v=%8x mag=%g\n", k,
02118 rs->vu[k], rs->vu[k]->v_p, mag[k] );
02119 NMG_CK_VERTEX_G(rs->vu[k]->v_p->vg_p);
02120 VPRINT("\tpt", rs->vu[k]->v_p->vg_p->coord);
02121 }
02122 rt_bomb("nmg_face_combine: vu block with differing vertices\n");
02123 }
02124
02125 m = nmg_face_coincident_vu_sort( rs, cur, j );
02126
02127
02128 for( k = cur; k < m; k++ ) {
02129 nmg_face_state_transition( rs, k, 1, other_rs_state );
02130 #if PLOT_BOTH_FACES
02131 nmg_2face_plot( rs->fu1, rs->fu2 );
02132 #else
02133 nmg_face_plot( rs->fu1 );
02134 #endif
02135 }
02136 rs->vu[j-1] = rs->vu[m-1];
02137 if(rt_g.NMG_debug&DEBUG_FCUT)
02138 bu_log("nmg_face_next_vu_interval() vu[%d] set to x%x\n", j-1, rs->vu[j-1] );
02139 return j;
02140 }
02141
02142 #define VAVERAGE( a, b, c ) { \
02143 (a)[X] = ((b)[X] + (c)[X]) * 0.5;\
02144 (a)[Y] = ((b)[Y] + (c)[Y]) * 0.5;\
02145 (a)[Z] = ((b)[Z] + (c)[Z]) * 0.5;\
02146 }
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 void
02163 nmg_edge_geom_isect_line(struct edgeuse *eu, struct nmg_ray_state *rs, const char *reason)
02164 {
02165 register struct edge_g_lseg *eg;
02166
02167 NMG_CK_EDGEUSE(eu);
02168 NMG_CK_RAYSTATE(rs);
02169 if(eu->g.lseg_p) NMG_CK_EDGE_G_LSEG(eu->g.lseg_p);
02170 if(rs->eg_p) NMG_CK_EDGE_G_LSEG(rs->eg_p);
02171
02172 if(rt_g.NMG_debug&DEBUG_FCUT) {
02173 bu_log("nmg_edge_geom_isect_line(eu=x%x, %s)\n eu->g=x%x, rs->eg=x%x at START\n",
02174 eu, reason,
02175 eu->g.magic_p, rs->eg_p);
02176 }
02177 if( !eu->g.magic_p ) {
02178
02179
02180
02181 if( !rs->eg_p ) {
02182 nmg_edge_g( eu );
02183 eg = eu->g.lseg_p;
02184 NMG_CK_EDGE_G_LSEG(eg);
02185 VMOVE( eg->e_pt, rs->pt );
02186 VMOVE( eg->e_dir, rs->dir );
02187 rs->eg_p = eg;
02188 } else {
02189 NMG_CK_EDGE_G_LSEG(rs->eg_p);
02190 nmg_use_edge_g( eu, (long *)rs->eg_p );
02191 }
02192 goto out;
02193 }
02194
02195 if( eu->g.lseg_p == rs->eg_p ) return;
02196 if( !rs->eg_p ) {
02197
02198 eg = eu->g.lseg_p;
02199 NMG_CK_EDGE_G_LSEG(eg);
02200 rs->eg_p = eg;
02201 goto out;
02202 }
02203
02204
02205
02206
02207
02208
02209
02210
02211 nmg_jeg( rs->eg_p, eu->g.lseg_p );
02212 out:
02213 NMG_CK_EDGE_G_LSEG(rs->eg_p);
02214 if(rt_g.NMG_debug&DEBUG_FCUT) {
02215 bu_log("nmg_edge_geom_isect_line(eu=x%x) g=x%x, rs->eg=x%x at END\n",
02216 eu, eu->g.magic_p, rs->eg_p);
02217 }
02218 }
02219
02220 static struct bu_ptbl *
02221 find_loop_to_cut(int *index1, int *index2, int prior_start, int prior_end, int next_start, int next_end, fastf_t *mid_pt, struct nmg_ray_state *rs)
02222 {
02223 struct loopuse *lu1,*lu2;
02224 struct vertexuse *vu1 = (struct vertexuse *)NULL;
02225 struct vertexuse *vu2 = (struct vertexuse *)NULL;
02226 struct loopuse *match_lu=(struct loopuse *)NULL;
02227 struct loopuse *prior_lu,*next_lu;
02228 struct bu_ptbl *cuts=(struct bu_ptbl *)NULL;
02229 struct loop_cuts *lcut;
02230 int count=0;
02231 int i,j,k;
02232 int done=0;
02233
02234 if(rt_g.NMG_debug&DEBUG_FCUT)
02235 bu_log( "find_loop_to_cut: prior_start=%d, prior_end=%d, next_start=%d, next_end=%d, rs=x%x\n",
02236 prior_start, prior_end, next_start, next_end, rs );
02237
02238 NMG_CK_RAYSTATE(rs);
02239
02240
02241 while( !done )
02242 {
02243 done = 1;
02244 count++;
02245 if( count > 100 )
02246 {
02247 bu_log( "find_loop_to_cut: infinite loop\n" );
02248 bu_log( "prior_start = %d, prior_end = %d, next_start = %d next_nd = %d\n",
02249 prior_start, prior_end, next_start, next_end );
02250 bu_log( "mid_point = ( %f %f %f )\n", V3ARGS( mid_pt ) );
02251 for( i=0 ; i<rs->nvu ; i++ )
02252 bu_log( "\t%d x%x\n", i, rs->vu[i] );
02253 rt_bomb( "find_loop_to_cut: infinite loop" );
02254 }
02255 for( i=prior_start ; i < prior_end ; i++ )
02256 {
02257 int class_pt;
02258
02259 prior_lu = nmg_find_lu_of_vu( rs->vu[i] );
02260 class_pt = NMG_CLASS_Unknown;
02261 for( j=next_start ; j < next_end ; j++ )
02262 {
02263 next_lu = nmg_find_lu_of_vu( rs->vu[j] );
02264 if( prior_lu == next_lu )
02265 {
02266 int class_lu;
02267
02268 if( !match_lu )
02269 {
02270 match_lu = next_lu;
02271 cuts = (struct bu_ptbl *)bu_malloc( sizeof( struct bu_ptbl ), "cuts" );
02272 bu_ptbl_init( cuts, 64, " cuts");
02273 lcut = (struct loop_cuts *)bu_malloc( sizeof( struct loop_cuts ), "lcut" );
02274 lcut->lu = match_lu;
02275 bu_ptbl_ins( cuts, (long *)lcut );
02276 continue;
02277 }
02278
02279 if( match_lu == next_lu )
02280 continue;
02281
02282 if( class_pt == NMG_CLASS_Unknown )
02283 {
02284 class_pt = nmg_class_pt_lu_except( mid_pt,
02285 match_lu, (struct edge *)NULL, rs->tol );
02286 if( match_lu->orientation == OT_OPPOSITE )
02287 {
02288 if( class_pt == NMG_CLASS_AinB )
02289 class_pt = NMG_CLASS_AoutB;
02290 else if( class_pt == NMG_CLASS_AoutB )
02291 class_pt = NMG_CLASS_AinB;
02292 }
02293 }
02294 class_lu = nmg_classify_lu_lu( next_lu, match_lu, rs->tol );
02295
02296 if( class_lu == class_pt ||
02297 class_lu == NMG_CLASS_AonBshared )
02298 {
02299 int found=0;
02300
02301 match_lu = next_lu;
02302 for( k=0 ; k<BU_PTBL_END( cuts ) ; k++ )
02303 {
02304 lcut = (struct loop_cuts *)BU_PTBL_GET( cuts , k );
02305 if( lcut->lu == match_lu )
02306 {
02307 found = 1;
02308 break;
02309 }
02310 }
02311 if( !found )
02312 {
02313 done = 0;
02314 lcut = (struct loop_cuts *)bu_malloc( sizeof( struct loop_cuts ), "lcut" );
02315 lcut->lu = match_lu;
02316 bu_ptbl_ins( cuts, (long *)lcut );
02317 }
02318 }
02319 }
02320 }
02321 }
02322 }
02323
02324 if( cuts )
02325 {
02326 for( k=0 ; k<BU_PTBL_END( cuts ) ; k++ )
02327 {
02328 lcut = (struct loop_cuts *)BU_PTBL_GET( cuts, k );
02329 match_lu = lcut->lu;
02330
02331 if(rt_g.NMG_debug&DEBUG_FCUT)
02332 bu_log( "\tfind_loop_to_cut: matching lu's = x%x\n", match_lu );
02333 lu1 = match_lu;
02334 for( i=prior_start ; i < prior_end ; i++ )
02335 {
02336 if( nmg_find_lu_of_vu( rs->vu[i] ) == lu1 )
02337 {
02338 *index1 = i;
02339 vu1 = rs->vu[i];
02340 lcut->vu1 = vu1;
02341 break;
02342 }
02343 }
02344 lu2 = match_lu;
02345 for( i=next_start ; i < next_end ; i++ )
02346 {
02347 if( nmg_find_lu_of_vu( rs->vu[i] ) == lu2 )
02348 {
02349 *index2 = i;
02350 vu2 = rs->vu[i];
02351 lcut->vu2 = vu2;
02352 break;
02353 }
02354 }
02355 }
02356 }
02357 else
02358 {
02359 if(rt_g.NMG_debug&DEBUG_FCUT)
02360 bu_log( "\tfind_loop_to_cut returning 0\n" );
02361 return( (struct bu_ptbl *)NULL );
02362 }
02363
02364 for( k=0 ; k<BU_PTBL_END( cuts ) ; k++ )
02365 {
02366 lcut = (struct loop_cuts *)BU_PTBL_GET( cuts, k );
02367 lu1 = lcut->lu;
02368 lu2 = lu1;
02369
02370
02371 count = 0;
02372 for( i=next_start ; i<next_end ; i++ )
02373 {
02374 if( nmg_find_lu_of_vu( rs->vu[i] ) == lu2 )
02375 count++;
02376 }
02377
02378 if( count > 1 )
02379 {
02380 struct vertexuse *vu_best;
02381 fastf_t vu_angle;
02382 vect_t x_dir,y_dir;
02383 vect_t norm;
02384
02385 if(rt_g.NMG_debug&DEBUG_FCUT)
02386 bu_log( "\tfind_loop_to_cut: %d VU's from lu x%x\n", count, lu2 );
02387
02388
02389 vu_angle = (-bn_pi);
02390 vu_best = (struct vertexuse *)NULL;
02391
02392 VSUB2( x_dir, vu2->v_p->vg_p->coord, vu1->v_p->vg_p->coord );
02393 VUNITIZE( x_dir );
02394 NMG_GET_FU_NORMAL( norm, rs->fu1 );
02395
02396 VCROSS( y_dir, norm, x_dir );
02397 VUNITIZE( y_dir );
02398
02399 if(rt_g.NMG_debug&DEBUG_FCUT)
02400 bu_log( "\tx_dir=(%g %g %g), y_dir=(%g %g %g)\n",
02401 V3ARGS( x_dir ), V3ARGS( y_dir ) );
02402
02403 for( i=next_start ; i<next_end ; i++ )
02404 {
02405 struct edgeuse *eu;
02406 fastf_t angle;
02407 vect_t eu_dir;
02408
02409
02410 if( nmg_find_lu_of_vu( rs->vu[i] ) != lu2 )
02411 continue;
02412
02413 if( *(rs->vu[i]->up.magic_p) != NMG_EDGEUSE_MAGIC )
02414 {
02415 bu_log( "nmg_fcut_face: VU (x%x) is not from an EU\n", rs->vu[i] );
02416 rt_bomb( "nmg_fcut_face: VU is not from an EU" );
02417 }
02418
02419
02420
02421
02422 eu = rs->vu[i]->up.eu_p;
02423 VSUB2( eu_dir, eu->eumate_p->vu_p->v_p->vg_p->coord, eu->vu_p->v_p->vg_p->coord );
02424 angle = atan2( VDOT( y_dir,eu_dir ), VDOT( x_dir, eu_dir ) );
02425
02426 if(rt_g.NMG_debug&DEBUG_FCUT)
02427 bu_log( "\tangle for eu x%x (vu=x%x, #%d) is %g\n",
02428 eu, rs->vu[i], i, angle );
02429
02430
02431 if( angle > vu_angle )
02432 {
02433 if(rt_g.NMG_debug&DEBUG_FCUT)
02434 bu_log( "\t\tabove is the new best VU\n" );
02435 vu_angle = angle;
02436 vu_best = rs->vu[i];
02437 *index2 = i;
02438 }
02439 }
02440
02441 if( vu_best )
02442 {
02443 vu2 = vu_best;
02444 lcut->vu2 = vu2;
02445 }
02446
02447 if(rt_g.NMG_debug&DEBUG_FCUT)
02448 bu_log( "\tfind_loop_to_cut: selecting VU2 x%x\n", vu2 );
02449 }
02450
02451
02452 if( BU_PTBL_END( cuts ) > 1 )
02453 {
02454 for( i=0 ; i<BU_PTBL_END( cuts ) ; i++ )
02455 {
02456 struct loop_cuts *lcut1, *lcut2;
02457 int class1, class2;
02458
02459 lcut1 = (struct loop_cuts *)BU_PTBL_GET( cuts, i );
02460 for( j=i+1 ; j<BU_PTBL_END( cuts ) ; j++ )
02461 {
02462 lcut2 = (struct loop_cuts *)BU_PTBL_GET( cuts, j );
02463
02464 if( lcut1->vu1->v_p != lcut2->vu1->v_p ||
02465 lcut1->vu2->v_p != lcut2->vu2->v_p )
02466 continue;
02467
02468
02469 if( lcut1->lu->orientation == OT_OPPOSITE &&
02470 lcut2->lu->orientation == OT_OPPOSITE )
02471 {
02472 bu_log( "find_loop_to_cut: Two OT_OPPOSITE loops to be cut?? x%x and x%x\n",
02473 lcut1->lu, lcut2->lu );
02474 bu_bomb( "find_loop_to_cut: Two OT_OPPOSITE loops to be cut??\n" );
02475 }
02476 if( lcut1->lu->orientation == OT_OPPOSITE )
02477 {
02478
02479 bu_ptbl_rm( cuts, (long *)lcut1 );
02480 break;
02481 }
02482 if( lcut2->lu->orientation == OT_OPPOSITE )
02483 {
02484
02485 bu_ptbl_rm( cuts, (long *)lcut2 );
02486 break;
02487 }
02488 class1 = nmg_class_pt_lu_except( mid_pt, lcut1->lu,
02489 (struct edge *)NULL, rs->tol );
02490 class2 = nmg_class_pt_lu_except( mid_pt, lcut2->lu,
02491 (struct edge *)NULL, rs->tol );
02492
02493 if( class1 == NMG_CLASS_AoutB && class2 == NMG_CLASS_AoutB )
02494 {
02495 bu_log( "find_loop_to_cut: mid point is outside both loops??? x%x and x%x pt=(%g %g %g)\n",
02496 lcut1->lu, lcut2->lu, V3ARGS( mid_pt ) );
02497 bu_bomb( "find_loop_to_cut: mid point is outside both loops???\n" );
02498 }
02499
02500 if( class1 == NMG_CLASS_AoutB )
02501 {
02502
02503 bu_ptbl_rm( cuts, (long *)lcut1 );
02504 break;
02505 }
02506 if( class2 == NMG_CLASS_AoutB )
02507 {
02508
02509 bu_ptbl_rm( cuts, (long *)lcut2 );
02510 break;
02511 }
02512 }
02513 }
02514 }
02515
02516
02517 count = 0;
02518 for( i=prior_start ; i<prior_end ; i++ )
02519 {
02520 if( nmg_find_lu_of_vu( rs->vu[i] ) == lu1 )
02521 count++;
02522 }
02523
02524 if( count > 1 )
02525 {
02526 struct vertexuse *vu_best;
02527
02528 fastf_t vu_angle;
02529 vect_t x_dir,y_dir;
02530 vect_t norm;
02531
02532 if(rt_g.NMG_debug&DEBUG_FCUT)
02533 bu_log( "\tfind_loop_to_cut: %d VU's from lu x%x\n", count, lu1 );
02534
02535
02536 vu_angle = (-bn_pi);
02537 vu_best = (struct vertexuse *)NULL;
02538
02539 VSUB2( x_dir, vu1->v_p->vg_p->coord, vu2->v_p->vg_p->coord );
02540 VUNITIZE( x_dir );
02541 NMG_GET_FU_NORMAL( norm, rs->fu1 );
02542
02543 VCROSS( y_dir, norm, x_dir );
02544 VUNITIZE( y_dir );
02545
02546 if(rt_g.NMG_debug&DEBUG_FCUT)
02547 bu_log( "\tx_dir=(%g %g %g), y_dir=(%g %g %g)\n",
02548 V3ARGS( x_dir ), V3ARGS( y_dir ) );
02549
02550 for( i=prior_start ; i<prior_end ; i++ )
02551 {
02552 struct edgeuse *eu;
02553 fastf_t angle;
02554 vect_t eu_dir;
02555
02556 if( nmg_find_lu_of_vu( rs->vu[i] ) != lu1 )
02557 continue;
02558
02559 if( *(rs->vu[i]->up.magic_p) != NMG_EDGEUSE_MAGIC )
02560 {
02561 bu_log( "nmg_fcut_face: VU (x%x) is not from an EU\n", rs->vu[i] );
02562 rt_bomb( "nmg_fcut_face: VU is not from an EU" );
02563 }
02564
02565
02566
02567
02568 eu = rs->vu[i]->up.eu_p;
02569 VSUB2( eu_dir, eu->eumate_p->vu_p->v_p->vg_p->coord, eu->vu_p->v_p->vg_p->coord );
02570 angle = atan2( VDOT( y_dir,eu_dir ), VDOT( x_dir, eu_dir ) );
02571
02572 if(rt_g.NMG_debug&DEBUG_FCUT)
02573 bu_log( "\tangle for eu x%x (vu=x%x, #%d) is %g\n",
02574 eu, rs->vu[i], i, angle );
02575
02576
02577 if( angle > vu_angle )
02578 {
02579 if(rt_g.NMG_debug&DEBUG_FCUT)
02580 bu_log( "\t\tabove is the new best VU\n" );
02581 vu_angle = angle;
02582
02583 vu_best = rs->vu[i];
02584 *index1 = i;
02585 }
02586 }
02587
02588 if( vu_best )
02589 {
02590 vu1 = vu_best;
02591 lcut->vu1 = vu1;
02592 }
02593
02594 if(rt_g.NMG_debug&DEBUG_FCUT)
02595 bu_log( "\tfind_loop_to_cut: selecting VU1 x%x\n", vu1 );
02596 }
02597 }
02598
02599 if(rt_g.NMG_debug&DEBUG_FCUT)
02600 bu_log( "\tfind_loop_to_cut: returning %d cuts (index1=%d, index2=%d)\n",
02601 BU_PTBL_END( cuts ), *index1, *index2 );
02602
02603 return( cuts );
02604 }
02605
02606 static fastf_t
02607 nmg_eu_angle(struct edgeuse *eu, struct vertex *vp)
02608 {
02609 struct faceuse *fu;
02610 struct vertex_g *vg1,*vg2;
02611 vect_t norm;
02612 vect_t x_dir;
02613 vect_t y_dir;
02614 vect_t eu_dir;
02615 fastf_t angle;
02616
02617 NMG_CK_EDGEUSE( eu );
02618 NMG_CK_VERTEX( vp );
02619
02620 fu = nmg_find_fu_of_eu( eu );
02621 NMG_CK_FACEUSE( fu );
02622 NMG_GET_FU_NORMAL( norm, fu );
02623
02624 vg1 = eu->vu_p->v_p->vg_p;
02625 vg2 = eu->eumate_p->vu_p->v_p->vg_p;
02626
02627 VSUB2( x_dir, vg1->coord, vp->vg_p->coord );
02628 VUNITIZE( x_dir );
02629 VCROSS( y_dir, norm, x_dir );
02630 VUNITIZE( y_dir );
02631
02632 VSUB2( eu_dir, vg2->coord, vg1->coord );
02633 angle = atan2( VDOT( eu_dir, y_dir ), VDOT( eu_dir, x_dir ) );
02634
02635 return( angle );
02636 }
02637
02638 static int
02639 find_best_vu(int start, int end, struct vertex *other_vp, struct nmg_ray_state *rs)
02640 {
02641 struct edgeuse *eu;
02642 struct vertexuse *best_vu;
02643 struct loopuse *best_lu;
02644 fastf_t best_angle;
02645 int best_index;
02646 int other_is_in_best = -42;
02647 int class;
02648 int i;
02649
02650 if(rt_g.NMG_debug&DEBUG_FCUT)
02651 bu_log( "find_best_vu: start=%d, end=%d, other_vp=x%x, rs=x%x\n",
02652 start,end,other_vp, rs );
02653
02654 NMG_CK_VERTEX( other_vp );
02655 NMG_CK_RAYSTATE(rs);
02656
02657 if( start == end-1 )
02658 {
02659 if(rt_g.NMG_debug&DEBUG_FCUT)
02660 bu_log( "\tfind_best_vu returning %d\n", start );
02661
02662 return( start );
02663 }
02664
02665 best_vu = rs->vu[start];
02666 best_lu = nmg_find_lu_of_vu( best_vu );
02667 best_index = start;
02668 eu = best_vu->up.eu_p;
02669 best_angle = nmg_eu_angle( eu, other_vp );
02670
02671 if( BU_LIST_FIRST_MAGIC( &best_lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
02672 {
02673 other_is_in_best = 0;
02674 }
02675 else if( nmg_loop_is_a_crack( best_lu ) )
02676 {
02677 other_is_in_best = 0;
02678 }
02679 else
02680 {
02681 class = nmg_class_pt_lu_except( other_vp->vg_p->coord, best_lu, (struct edge *)NULL, rs->tol );
02682
02683 if( (class == NMG_CLASS_AinB && best_lu->orientation == OT_SAME) ||
02684 (class == NMG_CLASS_AoutB && best_lu->orientation == OT_OPPOSITE) )
02685 other_is_in_best = 1;
02686 else if( class == NMG_CLASS_AonBshared )
02687 {
02688 bu_log( "find_best_vu: There is a loop to cut, lu=x%x\n", best_lu );
02689 rt_bomb( "find_best_vu: There is a loop to cut" );
02690 }
02691 else
02692 other_is_in_best = 0;
02693 }
02694
02695 if(rt_g.NMG_debug&DEBUG_FCUT)
02696 bu_log( "\tfind_best_vu: first choice is index=%d, vu=x%x, lu=x%x, other_is_in_best=%d\n",
02697 best_index, best_vu, best_lu, other_is_in_best );
02698
02699 for( i=start+1 ; i<end ; i++ )
02700 {
02701 struct loopuse *lu;
02702
02703 lu = nmg_find_lu_of_vu( rs->vu[i] );
02704 if( lu != best_lu )
02705 {
02706 class = nmg_classify_lu_lu( lu, best_lu, rs->tol );
02707 if(rt_g.NMG_debug&DEBUG_FCUT)
02708 {
02709 bu_log( "lu x%x is %s\n", lu , nmg_orientation( lu->orientation ) );
02710 bu_log( "best_lu x%x is %s\n", best_lu , nmg_orientation( best_lu->orientation ) );
02711 bu_log( "lu x%x is %s w.r.t lu x%x\n",
02712 lu, nmg_class_name( class ), best_lu );
02713 }
02714
02715 if( other_is_in_best )
02716 {
02717 if( class == NMG_CLASS_AinB || (class == NMG_CLASS_AonBshared && lu->orientation == OT_SAME) )
02718 {
02719
02720 best_vu = rs->vu[i];
02721 best_lu = lu;
02722 best_index = i;
02723
02724 if(rt_g.NMG_debug&DEBUG_FCUT)
02725 bu_log( "\tfind_best_vu: better choice (inside) - index=%d, vu=x%x, lu=x%x, other_is_in_best=%d\n",
02726 best_index, best_vu, best_lu, other_is_in_best );
02727
02728 }
02729 }
02730 else
02731 {
02732 if( class == NMG_CLASS_AoutB || (class == NMG_CLASS_AonBshared && lu->orientation == OT_OPPOSITE) )
02733 {
02734 best_vu = rs->vu[i];
02735 best_lu = lu;
02736 best_index = i;
02737
02738
02739 if( BU_LIST_FIRST_MAGIC( &best_lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
02740 {
02741 other_is_in_best = 0;
02742 }
02743 else if( nmg_loop_is_a_crack( best_lu ) )
02744 {
02745 other_is_in_best = 0;
02746 }
02747 else
02748 {
02749 class = nmg_class_pt_lu_except( other_vp->vg_p->coord,
02750 best_lu, (struct edge *)NULL, rs->tol );
02751
02752 if( (class == NMG_CLASS_AinB && best_lu->orientation == OT_SAME) ||
02753 (class == NMG_CLASS_AoutB && best_lu->orientation == OT_OPPOSITE) )
02754 other_is_in_best = 1;
02755 else if( class == NMG_CLASS_AonBshared )
02756 {
02757 bu_log( "find_best_vu: There is a loop to cut, lu=x%x\n",
02758 best_lu );
02759 rt_bomb( "find_best_vu: There is a loop to cut" );
02760 }
02761 else
02762 other_is_in_best = 0;
02763 }
02764 if(rt_g.NMG_debug&DEBUG_FCUT)
02765 bu_log( "\tfind_best_vu: better choice (outside) - index=%d, vu=x%x, lu=x%x, other_is_in_best=%d\n",
02766 best_index, best_vu, best_lu, other_is_in_best );
02767 }
02768 }
02769 }
02770 else
02771 {
02772 struct edgeuse *eu;
02773 fastf_t angle;
02774
02775
02776 eu = rs->vu[i]->up.eu_p;
02777 NMG_CK_EDGEUSE( eu );
02778 angle = nmg_eu_angle( eu, other_vp );
02779
02780 if(rt_g.NMG_debug&DEBUG_FCUT)
02781 bu_log( "best_angle = %f, eu=x%x, eu_angle=%f\n",
02782 best_angle, eu, angle );
02783 if( angle > best_angle )
02784 {
02785 best_angle = angle;
02786 best_vu = rs->vu[i];
02787 best_lu = nmg_find_lu_of_vu( best_vu );
02788 best_index = i;
02789 }
02790 }
02791 }
02792
02793 return( best_index );
02794 }
02795
02796 HIDDEN void
02797 nmg_fcut_face(struct nmg_ray_state *rs)
02798 {
02799 register int cur;
02800 struct vertexuse *vu1,*vu2;
02801 struct loopuse *new_lu;
02802 struct edgeuse *new_eu1;
02803 struct edgeuse *old_eu;
02804 struct vertex *prev_v;
02805 struct bu_ptbl *cuts;
02806 int prior_start;
02807 int cut_no;
02808
02809 NMG_CK_RAYSTATE(rs);
02810 BN_CK_TOL(rs->tol);
02811
02812 if(rt_g.NMG_debug&DEBUG_FCUT)
02813 bu_log("nmg_face_combine()\n");
02814
02815 if(rs->eg_p) NMG_CK_EDGE_G_LSEG(rs->eg_p);
02816
02817 #if PLOT_BOTH_FACES
02818 nmg_2face_plot( rs->fu1, rs->fu2 );
02819 #else
02820 nmg_face_plot( rs->fu1 );
02821 nmg_face_plot( rs->fu2 );
02822 #endif
02823
02824 if(rt_g.NMG_debug&DEBUG_FCUT)
02825 {
02826 bu_log( "rs->fu1 = x%x\n", rs->fu1 );
02827 bu_log( "rs->fu2 = x%x\n", rs->fu2 );
02828 nmg_pr_fu_briefly( rs->fu1, "" );
02829 bu_log( "%d vertices on intersect line\n", rs->nvu );
02830 for( cur=0 ; cur<rs->nvu ; cur++ )
02831 bu_log( "\tvu=x%x, v=x%x, lu=x%x\n", rs->vu[cur], rs->vu[cur]->v_p, nmg_find_lu_of_vu( rs->vu[cur] ) );
02832 }
02833
02834
02835 if( rs->nvu < 2 )
02836 return;
02837
02838 prev_v = (struct vertex *)NULL;
02839 prior_start = 0;
02840 while( 1 )
02841 {
02842 struct edgeuse *eu_tmp;
02843 struct loopuse *lu1 = (struct loopuse *)NULL;
02844 struct loopuse *lu2 = (struct loopuse *)NULL;
02845 point_t mid_pt;
02846 int class;
02847 int orient1 = 0;
02848 int orient2 = 0;
02849 int prior_end;
02850 int next_start,next_end;
02851 int i;
02852 int index1,index2;
02853
02854 while( rs->vu[prior_start]->v_p == prev_v )
02855 prior_start++;
02856
02857 vu1 = rs->vu[prior_start];
02858 prior_end = prior_start;
02859
02860 prev_v = vu1->v_p;
02861
02862 while( ++prior_end < rs->nvu && rs->vu[prior_end]->v_p == vu1->v_p );
02863
02864 next_start = prior_end;
02865
02866 if( next_start >= rs->nvu )
02867 break;
02868
02869 vu2 = rs->vu[next_start];
02870 next_end = next_start;
02871 while( ++next_end < rs->nvu && rs->vu[next_end]->v_p == vu2->v_p );
02872
02873 if(rt_g.NMG_debug&DEBUG_FCUT)
02874 {
02875 bu_log( "rs->fu1 = x%x\n", rs->fu1 );
02876 bu_log( "rs->fu2 = x%x\n", rs->fu2 );
02877 bu_log( "prior_start=%d. prior_end=%d, next_start=%d, next_end=%d\n",
02878 prior_start, prior_end, next_start, next_end );
02879 bu_log( "%d vertices on intersect line\n", rs->nvu );
02880 for( cur=0 ; cur<rs->nvu ; cur++ )
02881 bu_log( "\tvu=x%x, v=x%x, lu=x%x\n", rs->vu[cur], rs->vu[cur]->v_p, nmg_find_lu_of_vu( rs->vu[cur] ) );
02882 }
02883
02884
02885 if( nmg_find_eu_in_face( vu1->v_p, vu2->v_p, rs->fu1,
02886 (struct edgeuse *)NULL, 0 ) )
02887 {
02888 if(rt_g.NMG_debug&DEBUG_FCUT)
02889 bu_log( "Already an edge here\n" );
02890 continue;
02891 }
02892
02893 if( nmg_find_eu_in_face( vu1->v_p, vu2->v_p, rs->fu1->fumate_p,
02894 (struct edgeuse *)NULL, 0 ) )
02895 {
02896 if(rt_g.NMG_debug&DEBUG_FCUT)
02897 bu_log( "Already an edge here\n" );
02898 continue;
02899 }
02900
02901
02902
02903
02904
02905 VAVERAGE( mid_pt, vu1->v_p->vg_p->coord, vu2->v_p->vg_p->coord )
02906 class = nmg_class_pt_fu_except( mid_pt, rs->fu1, (struct loopuse *)NULL,
02907 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0, 1, rs->tol );
02908
02909 if(rt_g.NMG_debug&DEBUG_FCUT)
02910 {
02911 bu_log( "vu1=x%x (%g %g %g ), vu2=x%x (%g %g %g)\n",
02912 vu1, V3ARGS( vu1->v_p->vg_p->coord ),
02913 vu2, V3ARGS( vu2->v_p->vg_p->coord ) );
02914 bu_log( "\tmid_pt = (%g %g %g)\n", V3ARGS( mid_pt ) );
02915 bu_log( "class for mid point is %s\n", nmg_class_name(class) );
02916 }
02917
02918 if( class == NMG_CLASS_AoutB )
02919 continue;
02920
02921
02922
02923
02924 class = nmg_class_pt_fu_except( mid_pt, rs->fu2, (struct loopuse *)NULL,
02925 (void (*)())NULL, (void (*)())NULL, (char *)NULL, 0, 0, rs->tol );
02926
02927 if( class == NMG_CLASS_AoutB )
02928 continue;
02929
02930
02931
02932 old_eu = nmg_findeu( vu1->v_p, vu2->v_p, (struct shell *)NULL,
02933 (struct edgeuse *)NULL, 0);
02934
02935
02936 cuts = find_loop_to_cut( &index1, &index2, prior_start, prior_end,
02937 next_start, next_end, mid_pt, rs );
02938 if( cuts == (struct bu_ptbl *)NULL )
02939 #if 0
02940 {
02941 vu1 = rs->vu[index1];
02942 vu2 = rs->vu[index2];
02943 lu1 = nmg_find_lu_of_vu( vu1 );
02944 lu2 = nmg_find_lu_of_vu( vu2 );
02945 orient1 = lu1->orientation;
02946 orient2 = lu2->orientation;
02947
02948 }
02949 else
02950 #endif
02951 {
02952 index1 = find_best_vu( prior_start, prior_end, vu2->v_p, rs );
02953 index2 = find_best_vu( next_start, next_end, vu1->v_p, rs );
02954 vu1 = rs->vu[index1];
02955 vu2 = rs->vu[index2];
02956 lu1 = nmg_find_lu_of_vu( vu1 );
02957 lu2 = nmg_find_lu_of_vu( vu2 );
02958 orient1 = lu1->orientation;
02959 orient2 = lu2->orientation;
02960 }
02961
02962 if( cuts )
02963 {
02964 for( cut_no=0 ; cut_no<BU_PTBL_END( cuts ) ; cut_no++ )
02965 {
02966 struct loop_cuts *lcut;
02967
02968 if(rt_g.NMG_debug&DEBUG_FCUT)
02969 bu_log( "\tcut loop (#%d of %d)\n", cut_no, BU_PTBL_END( cuts ) );
02970
02971 lcut = (struct loop_cuts *)BU_PTBL_GET( cuts, cut_no );
02972
02973 vu1 = lcut->vu1;
02974 vu2 = lcut->vu2;
02975 lu1 = lcut->lu;
02976
02977 new_lu = nmg_cut_loop( vu1, vu2 );
02978 new_eu1 = BU_LIST_LAST( edgeuse, &new_lu->down_hd );
02979
02980 NMG_CK_EDGEUSE( new_eu1 );
02981
02982
02983 new_eu1->e_p->is_real = 1;
02984
02985 nmg_loop_g( lu1->l_p, rs->tol );
02986 nmg_loop_g( new_lu->l_p, rs->tol );
02987
02988 nmg_lu_reorient( lu1 );
02989 nmg_lu_reorient( new_lu );
02990
02991 if(rt_g.NMG_debug&DEBUG_FCUT)
02992 {
02993 bu_log( "\t\t new_eu = x%x\n", new_eu1 );
02994 nmg_pr_fu_briefly( rs->fu1, "" );
02995 }
02996 #if 0
02997
02998 nmg_edge_geom_isect_line( new_eu1, rs, "CUTJOIN, new edge after loop cut" );
02999 #endif
03000 if( old_eu ) nmg_radial_join_eu( old_eu, new_eu1, rs->tol );
03001
03002
03003
03004
03005
03006 eu_tmp = vu1->up.eu_p;
03007 eu_tmp = BU_LIST_PPREV_CIRC( edgeuse, &eu_tmp->l );
03008 if( eu_tmp->vu_p->v_p != vu2->v_p )
03009 {
03010 bu_log( "nmg_fcut_face: eu (x%x) has wrong vertex (x%x) should be (x%x)\n", eu_tmp, eu_tmp->vu_p->v_p, vu2->v_p );
03011 rt_bomb( "nmg_fcut_face: eu has wrong vertex" );
03012 }
03013
03014 rs->vu[prior_end-1-cut_no] = eu_tmp->vu_p;
03015 }
03016 bu_ptbl_free( cuts);
03017 bu_free( (char *)cuts, "cuts" );
03018
03019 continue;
03020 }
03021
03022 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_VERTEXUSE_MAGIC &&
03023 BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC )
03024
03025 {
03026 struct vertexuse *new_vu2;
03027
03028 new_vu2 = nmg_join_2singvu_loops( vu1, vu2 );
03029 new_eu1 = new_vu2->up.eu_p;
03030 NMG_CK_EDGEUSE( new_eu1 );
03031
03032
03033 new_eu1->e_p->is_real = 1;
03034
03035 nmg_loop_g( lu1->l_p, rs->tol );
03036 lu1->orientation = OT_SAME;
03037 lu1->lumate_p->orientation = OT_SAME;
03038
03039 if(rt_g.NMG_debug&DEBUG_FCUT)
03040 {
03041 bu_log( "\tjoin 2 singvu loops\n" );
03042 nmg_pr_fu_briefly( rs->fu1, "" );
03043 }
03044 #if 0
03045
03046 nmg_edge_geom_isect_line( new_eu1, rs, "CUTJOIN, new edge after loop cut" );
03047 #endif
03048 if( old_eu ) nmg_radial_join_eu( old_eu, new_eu1, rs->tol );
03049
03050
03051
03052 for( i=next_start ; i<next_end ; i++ )
03053 {
03054 if( rs->vu[i] == vu2 )
03055 {
03056 rs->vu[i] = new_vu2;
03057 break;
03058 }
03059 }
03060
03061 continue;
03062 }
03063
03064 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_VERTEXUSE_MAGIC &&
03065 BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_EDGEUSE_MAGIC )
03066 {
03067 struct vertexuse *new_vu1;
03068
03069 new_vu1 = nmg_join_singvu_loop( vu2, vu1 );
03070 new_eu1 = new_vu1->up.eu_p;
03071 NMG_CK_EDGEUSE( new_eu1 );
03072
03073
03074 new_eu1->e_p->is_real = 1;
03075
03076 nmg_loop_g( lu2->l_p, rs->tol );
03077 lu2->orientation = orient2;
03078 lu2->lumate_p->orientation = orient2;
03079
03080 if(rt_g.NMG_debug&DEBUG_FCUT)
03081 {
03082 bu_log( "\tjoin loops vu1 (x%x) is sing vu loop\n", vu1 );
03083 nmg_pr_fu_briefly( rs->fu1, "" );
03084 }
03085 #if 0
03086
03087 nmg_edge_geom_isect_line( new_eu1, rs, "CUTJOIN, new edge after loop cut" );
03088
03089 #endif
03090 if( old_eu ) nmg_radial_join_eu( old_eu, new_eu1, rs->tol );
03091
03092
03093
03094
03095
03096 eu_tmp = new_vu1->up.eu_p;
03097 eu_tmp = BU_LIST_PPREV_CIRC( edgeuse, &eu_tmp->l );
03098 if( eu_tmp->vu_p->v_p != vu2->v_p )
03099 {
03100 bu_log( "nmg_fcut_face: eu (x%x) has wrong vertex (x%x) should be (x%x)\n", eu_tmp, eu_tmp->vu_p->v_p, vu2->v_p );
03101 rt_bomb( "nmg_fcut_face: eu has wrong vertex" );
03102 }
03103
03104 rs->vu[prior_end-1] = eu_tmp->vu_p;
03105 continue;
03106 }
03107
03108 if( BU_LIST_FIRST_MAGIC( &lu1->down_hd ) == NMG_EDGEUSE_MAGIC &&
03109 BU_LIST_FIRST_MAGIC( &lu2->down_hd ) == NMG_VERTEXUSE_MAGIC )
03110 {
03111 struct vertexuse *new_vu2;
03112
03113 new_vu2 = nmg_join_singvu_loop( vu1, vu2 );
03114 new_eu1 = new_vu2->up.eu_p;
03115 NMG_CK_EDGEUSE( new_eu1 );
03116
03117
03118 new_eu1->e_p->is_real = 1;
03119
03120 nmg_loop_g( lu1->l_p, rs->tol );
03121 lu1->orientation = orient1;
03122 lu1->lumate_p->orientation = orient1;
03123
03124 if(rt_g.NMG_debug&DEBUG_FCUT)
03125 {
03126 bu_log( "\tjoin loops vu2 (x%x) is sing vu loop\n", vu2 );
03127 nmg_pr_fu_briefly( rs->fu1, "" );
03128 }
03129 #if 0
03130
03131 nmg_edge_geom_isect_line( new_eu1, rs, "CUTJOIN, new edge after loop cut" );
03132 #endif
03133
03134 if( old_eu ) nmg_radial_join_eu( old_eu, new_eu1, rs->tol );
03135
03136
03137
03138 for( i=next_start ; i<next_end ; i++ )
03139 {
03140 if( rs->vu[i] == vu2 )
03141 {
03142 rs->vu[i] = new_vu2;
03143 break;
03144 }
03145 }
03146
03147 continue;
03148 }
03149
03150 if( lu1 != lu2 )
03151 {
03152 struct vertexuse *new_vu2;
03153
03154 new_vu2 = nmg_join_2loops( vu1, vu2 );
03155 new_eu1 = new_vu2->up.eu_p;
03156 NMG_CK_EDGEUSE( new_eu1 );
03157
03158
03159 new_eu1->e_p->is_real = 1;
03160
03161 nmg_loop_g( lu1->l_p, rs->tol );
03162
03163 if(rt_g.NMG_debug&DEBUG_FCUT)
03164 {
03165 bu_log( "\t join 2 loops\n" );
03166 bu_log( "\t\tvu2 (x%x) replaced with new_vu2 x%x\n", vu2, new_vu2 );
03167 nmg_pr_fu_briefly( rs->fu1, "" );
03168 }
03169
03170 #if 0
03171
03172 nmg_edge_geom_isect_line( new_eu1, rs, "CUTJOIN, new edge after loop cut" );
03173 #endif
03174
03175 if( old_eu ) nmg_radial_join_eu( old_eu, new_eu1, rs->tol );
03176
03177
03178
03179
03180 rs->vu[prior_end - 1] = new_vu2;
03181
03182 continue;
03183 }
03184
03185 bu_log( "ERROR in face cutter: something should have been cut!!\n" );
03186 bu_log( "vu1=x%x, vu2=x%x\n", vu1, vu2 );
03187 nmg_pr_fu_briefly( rs->fu1, "" );
03188 rt_bomb( "ERROR: face cutter didn't cut anything" );
03189 }
03190
03191 if(rt_g.NMG_debug&DEBUG_FCUT)
03192 nmg_pr_fu_briefly( rs->fu1, "" );
03193 }
03194
03195 HIDDEN void
03196 nmg_face_combine_jra(struct nmg_ray_state *rs1, fastf_t *mag1, struct nmg_ray_state *rs2, fastf_t *mag2)
03197 {
03198 nmg_fcut_face( rs1 );
03199 nmg_fcut_face( rs2 );
03200
03201 }
03202
03203
03204
03205
03206
03207
03208
03209 HIDDEN void
03210 nmg_face_combineX(struct nmg_ray_state *rs1, fastf_t *mag1, struct nmg_ray_state *rs2, fastf_t *mag2)
03211 {
03212 register int cur1, cur2;
03213 register int nxt1, nxt2;
03214
03215 NMG_CK_RAYSTATE(rs1);
03216 NMG_CK_RAYSTATE(rs2);
03217 BN_CK_TOL(rs1->tol);
03218 BN_CK_TOL(rs2->tol);
03219
03220 if(rt_g.NMG_debug&DEBUG_FCUT)
03221 bu_log("nmg_face_combine()\n");
03222
03223 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03224 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03225
03226 #if PLOT_BOTH_FACES
03227 nmg_2face_plot( rs1->fu1, rs1->fu2 );
03228 #else
03229 nmg_face_plot( rs1->fu1 );
03230 nmg_face_plot( rs1->fu2 );
03231 #endif
03232
03233
03234
03235
03236 cur1 = cur2 = 0;
03237 for( ; cur1 < rs1->nvu && cur2 < rs2->nvu; cur1=nxt1, cur2=nxt2 ) {
03238 int old_rs1_state = rs1->state;
03239
03240 if(rt_g.NMG_debug&DEBUG_FCUT)
03241 bu_log("\nnmg_face_combineX() vu block, index1=%d, index2=%d\n", cur1, cur2);
03242
03243 if( mag1[cur1] < mag2[cur2] ) {
03244 if(rt_g.NMG_debug&DEBUG_FCUT)
03245 bu_log("\nnmg_face_combineX() doing index1 block (at end)\n");
03246 nxt1 = nmg_face_next_vu_interval( rs1, cur1, mag1, rs2->state );
03247 nxt2 = cur2;
03248 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03249 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03250 if( !rs2->eg_p ) rs2->eg_p = rs1->eg_p;
03251 } else if( mag1[cur1] > mag2[cur2] ) {
03252 if(rt_g.NMG_debug&DEBUG_FCUT)
03253 bu_log("\nnmg_face_combineX() doing index2 block (at end)\n");
03254 nxt1 = cur1;
03255 nxt2 = nmg_face_next_vu_interval( rs2, cur2, mag2, old_rs1_state );
03256 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03257 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03258 if( !rs1->eg_p ) rs1->eg_p = rs2->eg_p;
03259 } else {
03260 struct vertexuse *vu1;
03261 struct vertexuse *vu2;
03262 vu1 = rs1->vu[cur1];
03263 vu2 = rs2->vu[cur2];
03264 NMG_CK_VERTEXUSE(vu1);
03265 NMG_CK_VERTEXUSE(vu2);
03266 if( vu1->v_p != vu2->v_p ) {
03267 bu_log("cur1=%d, cur2=%d, v1=x%x, v2=x%x\n",
03268 cur1, cur2, vu1->v_p, vu2->v_p);
03269 rt_bomb("nmg_face_combineX: vertex lists scrambled");
03270 }
03271 if(rt_g.NMG_debug&DEBUG_FCUT)
03272 bu_log("\nnmg_face_combineX() doing index1 block\n");
03273 nxt1 = nmg_face_next_vu_interval( rs1, cur1, mag1, rs2->state );
03274 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03275 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03276 if( !rs2->eg_p ) rs2->eg_p = rs1->eg_p;
03277
03278 if(rt_g.NMG_debug&DEBUG_FCUT)
03279 bu_log("\nnmg_face_combineX() doing index2 block\n");
03280 nxt2 = nmg_face_next_vu_interval( rs2, cur2, mag2, old_rs1_state );
03281 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03282 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03283 if( !rs1->eg_p ) rs1->eg_p = rs2->eg_p;
03284 }
03285 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03286 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03287 }
03288
03289
03290
03291
03292
03293 for( ; cur1 < rs1->nvu; cur1 = nxt1 ) {
03294 nxt1 = nmg_face_next_vu_interval( rs1, cur1, mag1, rs2->state );
03295 }
03296 if( !rs2->eg_p ) rs2->eg_p = rs1->eg_p;
03297 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03298 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03299
03300 for( ; cur2 < rs2->nvu; cur2 = nxt2 ) {
03301 nxt2 = nmg_face_next_vu_interval( rs2, cur2, mag2, rs1->state );
03302 }
03303 if( !rs1->eg_p ) rs1->eg_p = rs2->eg_p;
03304 if(rs1->eg_p) NMG_CK_EDGE_G_LSEG(rs1->eg_p);
03305 if(rs2->eg_p) NMG_CK_EDGE_G_LSEG(rs2->eg_p);
03306
03307 if( rs1->state != NMG_STATE_OUT || rs2->state != NMG_STATE_OUT ) {
03308 bu_log("ERROR nmg_face_combine() ended in state '%s'/'%s'?\n",
03309 nmg_state_names[rs1->state],
03310 nmg_state_names[rs2->state] );
03311 bu_log("cur1 = %d of %d, cur2 = %d of %d\n",
03312 cur1, rs1->nvu, cur2, rs2->nvu );
03313
03314 if( RT_G_DEBUG || rt_g.NMG_debug ) {
03315
03316 rt_g.NMG_debug |= DEBUG_VU_SORT|DEBUG_FCUT|DEBUG_PLOTEM;
03317 nmg_pl_comb_fu( 0, 1, rs1->fu1 );
03318 nmg_pl_comb_fu( 0, 2, rs1->fu2 );
03319 }
03320
03321 #if 0
03322 bu_log("nmg_face_combine() bad ending state, pushing on\n");
03323 #else
03324
03325 rt_bomb("nmg_face_combine() bad ending state\n");
03326 #endif
03327 }
03328 }
03329
03330
03331
03332
03333 void
03334 nmg_unlist_v(struct bu_ptbl *b, fastf_t *mag, struct vertex *v)
03335 {
03336 register int i;
03337 struct vertexuse *vu;
03338
03339 BU_CK_PTBL(b);
03340 NMG_CK_VERTEX(v);
03341 for( i=0; i<BU_PTBL_END(b); i++ ) {
03342 vu = (struct vertexuse *)BU_PTBL_GET(b, i);
03343 if( !vu ) continue;
03344 if( vu->v_p == v )
03345 {
03346 BU_PTBL_GET(b, i) = (long *)0;
03347 mag[i] = MAX_FASTF;
03348 }
03349 }
03350 }
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362 int
03363 nmg_onon_fix(struct nmg_ray_state *rs, struct bu_ptbl *b, struct bu_ptbl *ob, fastf_t *mag, fastf_t *omag)
03364
03365
03366
03367
03368
03369 {
03370 int i;
03371 int zapped;
03372 struct vertexuse *vu;
03373 struct vertex *v;
03374 int zot;
03375
03376 NMG_CK_RAYSTATE(rs);
03377 BU_CK_PTBL(b);
03378 BU_CK_PTBL(ob);
03379
03380 zapped = 0;
03381 for( i=0; i<BU_PTBL_END(b); i++ ) {
03382 again:
03383 vu = (struct vertexuse *)BU_PTBL_GET(b, i);
03384 if( !vu ) continue;
03385 NMG_CK_VERTEXUSE(vu);
03386 if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC ) continue;
03387 v = vu->v_p;
03388 NMG_CK_VERTEX(v);
03389 if( (zot = nmg_assess_eu( vu->up.eu_p, 0, rs, i )) < 0 ) {
03390 if(rt_g.NMG_debug&DEBUG_FCUT) {
03391 bu_log("nmg_onon_fix(): vu[%d] zapped (rev)\n", -zot);
03392 }
03393 doit:
03394 vu = (struct vertexuse *)BU_PTBL_GET(b, -zot);
03395 NMG_CK_VERTEXUSE(vu);
03396 v = vu->v_p;
03397
03398 nmg_unlist_v(b, mag, v);
03399 nmg_unlist_v(ob, omag, v);
03400 zapped++;
03401 goto again;
03402 }
03403
03404 if( (zot = nmg_assess_eu( vu->up.eu_p, 1, rs, i )) < 0 ) {
03405 if(rt_g.NMG_debug&DEBUG_FCUT) {
03406 bu_log("nmg_onon_fix(): vu[%d] zapped (forw)\n", -zot);
03407 }
03408 goto doit;
03409 }
03410 }
03411 if( zapped ) {
03412 int removed;
03413
03414
03415
03416
03417 bu_log("nmg_onon_fix(): removing %d dead vertexuses\n", zapped);
03418
03419 removed = 0;
03420 for( i=BU_PTBL_END( b ) ; i>=0 ; i-- )
03421 {
03422 int count=0;
03423 int j,k;
03424
03425 j = i;
03426 while( j>=0 && !BU_PTBL_GET( b, j ) ) --j;
03427 count = i-j;
03428 removed += count;
03429 for( k=j+1; k<BU_PTBL_END(b)-removed ; k++ )
03430 mag[k] = mag[k+count];
03431 }
03432 bu_ptbl_rm(b, 0 );
03433 removed = 0;
03434 for( i=BU_PTBL_END( ob ) ; i>=0 ; i-- )
03435 {
03436 int count=0;
03437 int j,k;
03438
03439 j = i;
03440 while( j>=0 && !BU_PTBL_GET( ob, j ) ) --j;
03441 count = i-j;
03442 removed += count;
03443 for( k=j+1 ; k<BU_PTBL_END(ob)-removed ; k++ )
03444 omag[k] = omag[k+count];
03445 }
03446 bu_ptbl_rm(ob, 0 );
03447 #if 0
03448 rt_bomb("nmg_onon_fix(): check the intersector\n");
03449 #endif
03450 return 1;
03451 }
03452
03453 return 0;
03454 }
03455 #if 0
03456 void
03457 nmg_sort_coincident_vus( tbl, tol )
03458 struct bu_ptbl *tbl;
03459 const struct bn_tol *tol;
03460 {
03461 int curr_vu=0;
03462 int start1,end1;
03463 int start2,end2;
03464 struct vertexuse *vu1;
03465 struct vertexuse *vu2;
03466 struct loopuse **matching_lus;
03467 int match_count=0;
03468
03469 BN_CK_TOL( tol );
03470 BU_CK_PTBL( tbl );
03471
03472 if( BU_PTBL_END( tbl ) < 3 )
03473 return;
03474
03475 matching_lus = (struct loopuse **)bu_calloc( BU_PTBL_END( tbl ),
03476 sizeof( struct loopuse *), "nmg_sort_coincident_vus: matching_lus" );
03477
03478
03479 while( curr_vu < BU_PTBL_END( tbl )-1 )
03480 {
03481 struct loopuse *lu1,*lu2;
03482
03483 vu1 = (struct vertexuse *)BU_PTBL_GET( tbl, curr_vu );
03484 start1 = curr_vu;
03485 end1 = start1;
03486 vu2 = (struct vertexuse *)BU_PTBL_GET( tbl, start1 + 1 );
03487 if( vu1->v-p != vu2->v_p )
03488 {
03489
03490 curr_vu++;
03491 continue;
03492 }
03493 while( vu2->v_p == vu1->v_p )
03494 {
03495 end1++;
03496 vu2 = (struct vertexuse *)BU_PTBL_GET( tbl, end1 + 1 );
03497 }
03498
03499
03500
03501
03502
03503 start2 = end1 + 1;
03504 end2 = start2;
03505 vu1 = (struct vertexuse *)BU_PTBL_GET( tbl, start2 );
03506 vu2 = (struct vertexuse *)BU_PTBL_GET( tbl, start2+1 );
03507 while( vu2->v_p == vu1->v_p )
03508 {
03509 end2++;
03510 vu2 = (struct vertexuse *)BU_PTBL_GET( tbl, end2+1 );
03511 }
03512
03513 match_count = 0;
03514 for( i=start1 ; i<=end1 ; i++ )
03515 {
03516 vu1 = (struct vertexuse *)BU_PTBL_GET( tbl, i );
03517 lu1 = nmg_find_lu_of_vu( vu1 );
03518 if( !lu1 )
03519 continue;
03520
03521
03522 for( j=start1 ; j<= end1 ; j++ )
03523 {
03524 vu2 = (struct vertexuse *)BU_PTBL_GET( tbl, j );
03525 lu2 = nmg_find_lu_of_vu( vu2 );
03526 if( lu2 == lu1 )
03527 {
03528 matching_lus[match_count] = lu1;
03529 match_count++;
03530 }
03531 }
03532 }
03533 }
03534 }
03535
03536 #endif
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549 struct edge_g_lseg *
03550 nmg_face_cutjoin(struct bu_ptbl *b1, struct bu_ptbl *b2, fastf_t *mag1, fastf_t *mag2, struct faceuse *fu1, struct faceuse *fu2, fastf_t *pt, fastf_t *dir, struct edge_g_lseg *eg, const struct bn_tol *tol)
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561 {
03562 struct vertexuse **vu1, **vu2;
03563 int i;
03564 struct nmg_ray_state rs1;
03565 struct nmg_ray_state rs2;
03566
03567 if(rt_g.NMG_debug&DEBUG_FCUT) {
03568 bu_log("\nnmg_face_cutjoin(fu1=x%x, fu2=x%x) eg=x%x START\n", fu1, fu2, eg);
03569 }
03570
03571 BN_CK_TOL(tol);
03572 NMG_CK_FACEUSE(fu1);
03573 NMG_CK_FACEUSE(fu2);
03574
03575
03576 if( rt_g.NMG_debug&DEBUG_FCUT && ( b1->end <= 0 || b2->end <= 0) ) {
03577 bu_log("nmg_face_cutjoin(fu1=x%x, fu2=x%x): WARNING empty list %d %d\n",
03578 fu1, fu2, b1->end, b2->end );
03579 #if 0
03580 return eg;
03581 #endif
03582 }
03583
03584 top:
03585
03586
03587
03588
03589 ptbl_vsort(b1, fu1, fu2, pt, dir, mag1, tol->dist);
03590 ptbl_vsort(b2, fu2, fu1, pt, dir, mag2, tol->dist);
03591
03592 vu1 = (struct vertexuse **)b1->buffer;
03593 vu2 = (struct vertexuse **)b2->buffer;
03594
03595
03596 if(rt_g.NMG_debug&DEBUG_FCUT) {
03597 bu_log("Ray vu intersection list:\n");
03598 for( i=0; i < b1->end; i++ ) {
03599 bu_log(" %d %e ", i, mag1[i] );
03600 nmg_pr_vu_briefly( vu1[i], (char *)0 );
03601 }
03602 for( i=0; i < b2->end; i++ ) {
03603 bu_log(" %d %e ", i, mag2[i] );
03604 nmg_pr_vu_briefly( vu2[i], (char *)0 );
03605 }
03606 }
03607
03608
03609 if( nmg_ck_vu_ptbl( b1, fu1 ) || nmg_ck_vu_ptbl( b2, fu2 ) ) goto top;
03610
03611 #if 0
03612
03613
03614 {
03615 i = b1->end-1;
03616 if( b2->end-1 < i ) i = b2->end-1;
03617 for( ; i >= 0; i-- ) {
03618 NMG_CK_VERTEXUSE(vu1[i]);
03619 NMG_CK_VERTEXUSE(vu2[i]);
03620 if( vu1[i]->v_p == vu2[i]->v_p ) continue;
03621 bu_log("Index %d mis-match, x%x != x%x\n",
03622 i, vu1[i]->v_p, vu2[i]->v_p );
03623 }
03624 }
03625 #endif
03626
03627
03628
03629 if(rt_g.NMG_debug&DEBUG_FCUT) {
03630 int found1=(-1),found2=(-1);
03631 int tmp_found;
03632 struct faceuse *fu;
03633 struct vertexuse *vu;
03634
03635
03636 for( i=0 ; i<BU_PTBL_END( b1 ) ; i++ )
03637 {
03638 tmp_found = 0;
03639 vu = (struct vertexuse *)BU_PTBL_GET( b1 , i );
03640 fu = nmg_find_fu_of_vu(vu);
03641 if( fu == fu1 )
03642 tmp_found = 1;
03643 if( found1 == (-1) )
03644 found1 = tmp_found;
03645 else if( tmp_found != found1 )
03646 {
03647 bu_log ("nmg_face_cutjoin: Intersection list is screwy for face 1\n" );
03648 break;
03649 }
03650 }
03651
03652
03653 for( i=0 ; i<BU_PTBL_END( b2 ) ; i++ )
03654 {
03655 tmp_found = 0;
03656 vu = (struct vertexuse *)BU_PTBL_GET( b2 , i );
03657 fu = nmg_find_fu_of_vu(vu);
03658 if( fu == fu2 )
03659 tmp_found = 1;
03660 if( found2 == (-1) )
03661 found2 = tmp_found;
03662 else if( tmp_found != found2 )
03663 {
03664 bu_log ("nmg_face_cutjoin: Intersection list is screwy for face 2\n" );
03665 break;
03666 }
03667 }
03668 if( !found1 )
03669 bu_log( "nmg_face_cutjoin: intersection list for face 1 doesn't contain vertexuses from face 1!!!\n" );
03670 if( !found2 )
03671 bu_log( "nmg_face_cutjoin: intersection list for face 2 doesn't contain vertexuses from face 2!!!\n" );
03672 }
03673
03674 nmg_face_rs_init( &rs1, b1, fu1, fu2, pt, dir, eg, tol );
03675 nmg_face_rs_init( &rs2, b2, fu2, fu1, pt, dir, eg, tol );
03676 #if 0
03677
03678 if( nmg_onon_fix( &rs1, b1, b2, mag1, mag2 ) || nmg_onon_fix( &rs2, b2, b1, mag2, mag1 ) ) goto top;
03679 #endif
03680
03681 #if 0
03682 nmg_face_combineX( &rs1, mag1, &rs2, mag2 );
03683 #else
03684 nmg_face_combine_jra( &rs1, mag1, &rs2, mag2 );
03685 #endif
03686
03687
03688
03689
03690
03691
03692 if( (i = nmg_mesh_two_faces( fu1, fu2, tol )) ) {
03693 if(rt_g.NMG_debug&DEBUG_FCUT)
03694 bu_log("nmg_face_cutjoin() meshed %d edges\n", i);
03695 }
03696 if(rt_g.NMG_debug&DEBUG_FCUT) {
03697 bu_log("nmg_face_cutjoin(fu1=x%x, fu2=x%x) eg=x%x END\n", fu1, fu2, rs1.eg_p);
03698 }
03699 if( eg && !rs1.eg_p ) rt_bomb("nmg_face_cutjoin() lost edge_g_lseg?\n");
03700 if( eg && eg != rs1.eg_p ) bu_log("nmg_face_cutjoin() changed from eg=x%x to rs1.eg_p=x%x\n", eg, rs1.eg_p);
03701 return rs1.eg_p;
03702 }
03703
03704 void
03705 nmg_fcut_face_2d(struct bu_ptbl *vu_list, fastf_t *mag, struct faceuse *fu1, struct faceuse *fu2, struct bn_tol *tol)
03706 {
03707 struct nmg_ray_state rs;
03708 point_t pt;
03709 vect_t dir;
03710 struct edge_g_lseg *eg;
03711
03712 NMG_CK_FACEUSE( fu1 );
03713 NMG_CK_FACEUSE( fu2 );
03714 BN_CK_TOL( tol );
03715 BU_CK_PTBL( vu_list );
03716
03717 VSETALL( pt, 0.0 );
03718 VSET( dir, 1.0, 0.0 ,0.0 );
03719 eg = (struct edge_g_lseg *)NULL;
03720
03721 nmg_face_rs_init( &rs, vu_list, fu1, fu2, pt, dir, eg, tol );
03722
03723 nmg_fcut_face( &rs );
03724 }
03725
03726
03727
03728
03729
03730
03731 struct state_transitions {
03732 int assessment;
03733 int new_state;
03734 int action;
03735 };
03736
03737 static const struct state_transitions nmg_state_is_out[17] = {
03738 { NMG_LEFT_LEFT, NMG_STATE_OUT, NMG_ACTION_NONE },
03739 { NMG_LEFT_RIGHT, NMG_STATE_IN, NMG_ACTION_VFY_EXT },
03740 { NMG_LEFT_ON_FORW, NMG_STATE_ON_L, NMG_ACTION_VFY_EXT },
03741 { NMG_LEFT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03742 { NMG_RIGHT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03743 { NMG_RIGHT_RIGHT, NMG_STATE_OUT, NMG_ACTION_NONE },
03744 { NMG_RIGHT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03745 { NMG_RIGHT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03746 { NMG_ON_FORW_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03747 { NMG_ON_FORW_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03748 { NMG_ON_FORW_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03749 { NMG_ON_FORW_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03750 { NMG_ON_REV_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03751 { NMG_ON_REV_RIGHT, NMG_STATE_ON_R, NMG_ACTION_VFY_EXT },
03752 { NMG_ON_REV_ON_FORW, NMG_STATE_ON_N, NMG_ACTION_NONE },
03753 { NMG_ON_REV_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03754 { NMG_LONE, NMG_STATE_OUT, NMG_ACTION_NONE }
03755 };
03756
03757 static const struct state_transitions nmg_state_is_on_L[17] = {
03758 { NMG_LEFT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03759 { NMG_LEFT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03760 { NMG_LEFT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03761 { NMG_LEFT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03762 { NMG_RIGHT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03763 { NMG_RIGHT_RIGHT, NMG_STATE_ON_L, NMG_ACTION_NONE },
03764 { NMG_RIGHT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03765 { NMG_RIGHT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03766 { NMG_ON_FORW_LEFT, NMG_STATE_OUT, NMG_ACTION_NONE },
03767 { NMG_ON_FORW_RIGHT, NMG_STATE_IN, NMG_ACTION_NONE },
03768 { NMG_ON_FORW_ON_FORW, NMG_STATE_ON_L, NMG_ACTION_NONE },
03769 { NMG_ON_FORW_ON_REV, NMG_STATE_IN, NMG_ACTION_NONE },
03770 { NMG_ON_REV_LEFT, NMG_STATE_ON_N, NMG_ACTION_VFY_MULTI },
03771 { NMG_ON_REV_RIGHT, NMG_STATE_ON_B, NMG_ACTION_VFY_EXT },
03772 { NMG_ON_REV_ON_FORW, NMG_STATE_ON_L, NMG_ACTION_VFY_MULTI },
03773 { NMG_ON_REV_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03774 { NMG_LONE, NMG_STATE_ON_L, NMG_ACTION_LONE_V_ESPLIT }
03775 };
03776
03777 static const struct state_transitions nmg_state_is_on_R[17] = {
03778 { NMG_LEFT_LEFT, NMG_STATE_ON_R, NMG_ACTION_NONE },
03779 { NMG_LEFT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03780 { NMG_LEFT_ON_FORW, NMG_STATE_ON_B, NMG_ACTION_NONE },
03781 { NMG_LEFT_ON_REV, NMG_STATE_IN, NMG_ACTION_NONE },
03782 { NMG_RIGHT_LEFT, NMG_STATE_ON_N, NMG_ACTION_VFY_MULTI },
03783 { NMG_RIGHT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03784 { NMG_RIGHT_ON_FORW, NMG_STATE_ON_N, NMG_ACTION_VFY_MULTI },
03785 { NMG_RIGHT_ON_REV, NMG_STATE_OUT, NMG_ACTION_NONE },
03786 { NMG_ON_FORW_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03787 { NMG_ON_FORW_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03788 { NMG_ON_FORW_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03789 { NMG_ON_FORW_ON_REV, NMG_STATE_IN, NMG_ACTION_NONE },
03790 { NMG_ON_REV_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03791 { NMG_ON_REV_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03792 { NMG_ON_REV_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03793 { NMG_ON_REV_ON_REV, NMG_STATE_ON_R, NMG_ACTION_NONE },
03794 { NMG_LONE, NMG_STATE_ON_R, NMG_ACTION_LONE_V_ESPLIT }
03795 };
03796
03797 static const struct state_transitions nmg_state_is_on_B[17] = {
03798 { NMG_LEFT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03799 { NMG_LEFT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03800 { NMG_LEFT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03801 { NMG_LEFT_ON_REV, NMG_STATE_IN, NMG_ACTION_VFY_MULTI },
03802 { NMG_RIGHT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03803 { NMG_RIGHT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03804 { NMG_RIGHT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03805 { NMG_RIGHT_ON_REV, NMG_STATE_ON_L, NMG_ACTION_NONE },
03806 { NMG_ON_FORW_LEFT, NMG_STATE_ON_R, NMG_ACTION_NONE },
03807 { NMG_ON_FORW_RIGHT, NMG_STATE_IN, NMG_ACTION_VFY_MULTI },
03808 { NMG_ON_FORW_ON_FORW, NMG_STATE_ON_B, NMG_ACTION_VFY_MULTI },
03809 { NMG_ON_FORW_ON_REV, NMG_STATE_IN, NMG_ACTION_NONE },
03810 { NMG_ON_REV_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03811 { NMG_ON_REV_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03812 { NMG_ON_REV_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03813 { NMG_ON_REV_ON_REV, NMG_STATE_ON_B, NMG_ACTION_VFY_MULTI },
03814 { NMG_LONE, NMG_STATE_ON_B, NMG_ACTION_LONE_V_ESPLIT }
03815 };
03816
03817 static const struct state_transitions nmg_state_is_on_N[17] = {
03818 { NMG_LEFT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03819 { NMG_LEFT_RIGHT, NMG_STATE_OUT, NMG_ACTION_VFY_MULTI },
03820 { NMG_LEFT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03821 { NMG_LEFT_ON_REV, NMG_STATE_ON_L, NMG_ACTION_VFY_MULTI },
03822 { NMG_RIGHT_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03823 { NMG_RIGHT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03824 { NMG_RIGHT_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03825 { NMG_RIGHT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03826 { NMG_ON_FORW_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03827 { NMG_ON_FORW_RIGHT, NMG_STATE_ON_R, NMG_ACTION_VFY_MULTI },
03828 { NMG_ON_FORW_ON_FORW, NMG_STATE_ON_N, NMG_ACTION_VFY_MULTI },
03829 { NMG_ON_FORW_ON_REV, NMG_STATE_OUT, NMG_ACTION_NONE },
03830 { NMG_ON_REV_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03831 { NMG_ON_REV_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03832 { NMG_ON_REV_ON_FORW, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03833 { NMG_ON_REV_ON_REV, NMG_STATE_ON_N, NMG_ACTION_VFY_MULTI },
03834 { NMG_LONE, NMG_STATE_ON_N, NMG_ACTION_LONE_V_ESPLIT }
03835 };
03836
03837 static const struct state_transitions nmg_state_is_in[17] = {
03838 { NMG_LEFT_LEFT, NMG_STATE_IN, NMG_ACTION_CUTJOIN },
03839 { NMG_LEFT_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03840 { NMG_LEFT_ON_FORW, NMG_STATE_ON_R, NMG_ACTION_CUTJOIN },
03841 { NMG_LEFT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03842 { NMG_RIGHT_LEFT, NMG_STATE_OUT, NMG_ACTION_CUTJOIN },
03843 { NMG_RIGHT_RIGHT, NMG_STATE_IN, NMG_ACTION_CUTJOIN },
03844 { NMG_RIGHT_ON_FORW, NMG_STATE_ON_L, NMG_ACTION_CUTJOIN },
03845 { NMG_RIGHT_ON_REV, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03846 { NMG_ON_FORW_LEFT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03847 { NMG_ON_FORW_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03848 { NMG_ON_FORW_ON_FORW, NMG_STATE_IN, NMG_ACTION_NONE },
03849 { NMG_ON_FORW_ON_REV, NMG_STATE_OUT, NMG_ACTION_NONE },
03850 { NMG_ON_REV_LEFT, NMG_STATE_ON_R, NMG_ACTION_CUTJOIN },
03851 { NMG_ON_REV_RIGHT, NMG_STATE_ERROR, NMG_ACTION_ERROR },
03852 { NMG_ON_REV_ON_FORW, NMG_STATE_ON_B, NMG_ACTION_CUTJOIN },
03853 { NMG_ON_REV_ON_REV, NMG_STATE_IN, NMG_ACTION_NONE },
03854 { NMG_LONE, NMG_STATE_IN, NMG_ACTION_LONE_V_JAUNT }
03855 };
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869 int
03870 nmg_insert_vu_if_on_edge(struct vertexuse *vu1, struct vertexuse *vu2, struct edgeuse *new_eu, struct bn_tol *tol)
03871
03872
03873
03874
03875 {
03876 struct edgeuse *eu_from;
03877 struct edgeuse *eu_to;
03878 vect_t eu_vect;
03879 vect_t vect_to_loop;
03880 fastf_t eu_len_sq;
03881 fastf_t dist_to_loop_sq;
03882
03883 NMG_CK_VERTEXUSE( vu1 );
03884 if( *vu1->up.magic_p != NMG_LOOPUSE_MAGIC )
03885 rt_bomb( "nmg_insert_vu_if_on_edge: vu1 is not from a loop of a single vertex" );
03886
03887 NMG_CK_VERTEXUSE( vu2 );
03888 if( *vu2->up.magic_p != NMG_EDGEUSE_MAGIC )
03889 rt_bomb( "nmg_insert_vu_if_on_edge: vu2 is not from an edgeuse" );
03890
03891 BN_CK_TOL( tol );
03892
03893 if(rt_g.NMG_debug&DEBUG_FCUT)
03894 bu_log( "nmg_insert_vu_if_on_edge: vu1=x%x, vu2=x%x\n" , vu1 , vu2 );
03895
03896 eu_from = BU_LIST_PNEXT_CIRC( edgeuse , vu2->up.eu_p );
03897 eu_to = BU_LIST_PPREV_CIRC( edgeuse , vu2->up.eu_p );
03898 if( bn_3pts_collinear( vu1->v_p->vg_p->coord , vu2->v_p->vg_p->coord , eu_from->vu_p->v_p->vg_p->coord , tol ))
03899 {
03900 if(rt_g.NMG_debug&DEBUG_FCUT)
03901 bu_log( "\t points are collinear with vu2's eu ( %g , %g , %g ) -> ( %g , %g , %g )\n",
03902 V3ARGS( vu2->v_p->vg_p->coord ),
03903 V3ARGS( eu_from->vu_p->v_p->vg_p->coord ) );
03904 VSUB2( eu_vect , eu_from->vu_p->v_p->vg_p->coord , vu2->v_p->vg_p->coord );
03905 VSUB2( vect_to_loop , vu1->v_p->vg_p->coord , vu2->v_p->vg_p->coord );
03906 if( VDOT( eu_vect , vect_to_loop ) > 0.0 )
03907 {
03908 eu_len_sq = MAGSQ( eu_vect );
03909 dist_to_loop_sq = MAGSQ( vect_to_loop );
03910 if( dist_to_loop_sq < eu_len_sq )
03911 {
03912 if(rt_g.NMG_debug&DEBUG_FCUT)
03913 bu_log( "\tvu1 is on vu2's eu, creating new edge (MAGSQ=%g, tol->dist_sq=%g)\n" , dist_to_loop_sq , tol->dist_sq );
03914 (void) nmg_ebreaker( vu1->v_p , vu2->up.eu_p, tol );
03915 nmg_klu( vu1->up.lu_p );
03916 return( 1 );
03917 }
03918 }
03919 }
03920 if( bn_3pts_collinear( vu1->v_p->vg_p->coord , vu2->v_p->vg_p->coord , eu_to->vu_p->v_p->vg_p->coord , tol ))
03921 {
03922 if(rt_g.NMG_debug&DEBUG_FCUT)
03923 bu_log( "\t points are collinear with eu that ends at vu2 ( %g , %g , %g ) -> ( %g , %g , %g )\n",
03924 V3ARGS( eu_to->vu_p->v_p->vg_p->coord ),
03925 V3ARGS( vu2->v_p->vg_p->coord ) );
03926 VSUB2( eu_vect , vu2->v_p->vg_p->coord , eu_to->vu_p->v_p->vg_p->coord );
03927 VSUB2( vect_to_loop , vu1->v_p->vg_p->coord , eu_to->vu_p->v_p->vg_p->coord );
03928 if( VDOT( eu_vect , vect_to_loop ) > 0.0 )
03929 {
03930 eu_len_sq = MAGSQ( eu_vect );
03931 dist_to_loop_sq = MAGSQ( vect_to_loop );
03932 if( dist_to_loop_sq < eu_len_sq )
03933 {
03934
03935 if(rt_g.NMG_debug&DEBUG_FCUT)
03936 bu_log( "\tvu1 is on eu that ends at vu2, creating new edge (MAGSQ=%g, tol->dist_sq=%g)\n" , dist_to_loop_sq , tol->dist_sq );
03937 (void) nmg_ebreaker( vu1->v_p , eu_to, tol );
03938 nmg_klu( vu1->up.lu_p );
03939 return( 1 );
03940 }
03941 }
03942 }
03943 return( 0 );
03944 }
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962 int
03963 nmg_face_state_transition(struct nmg_ray_state *rs, int pos, int multi, int other_rs_state)
03964 {
03965 int assessment;
03966 int old_state;
03967 int new_state;
03968 const struct state_transitions *stp;
03969 struct vertexuse *vu;
03970 struct vertexuse *prev_vu = (struct vertexuse *)NULL;
03971 struct loopuse *lu;
03972 struct loopuse *prev_lu;
03973 struct faceuse *fu;
03974 struct edgeuse *eu;
03975 struct edgeuse *first_new_eu;
03976 struct edgeuse *second_new_eu;
03977 struct edgeuse *old_eu;
03978 int e_assessment;
03979 int action;
03980 int e_pos;
03981
03982 NMG_CK_RAYSTATE(rs);
03983 vu = rs->vu[pos];
03984 NMG_CK_VERTEXUSE(vu);
03985 BN_CK_TOL(rs->tol);
03986 if(rs->eg_p) NMG_CK_EDGE_G_LSEG(rs->eg_p);
03987
03988 if(rt_g.NMG_debug&DEBUG_FCUT) {
03989 bu_log("nmg_face_state_transition(vu x%x, pos=%d) START\n",
03990 vu, pos);
03991 bu_log("Plotting this loopuse, before action:\n");
03992 nmg_pr_lu_briefly(nmg_find_lu_of_vu(vu), (char *)0);
03993 nmg_plot_lu_ray(nmg_find_lu_of_vu(vu),
03994 rs->vu[0], rs->vu[rs->nvu-1], rs->left );
03995 }
03996
03997 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
03998 nmg_vfu( &rs->fu1->s_p->fu_hd, rs->fu1->s_p );
03999 nmg_vfu( &rs->fu2->s_p->fu_hd, rs->fu2->s_p );
04000 nmg_fu_touchingloops(rs->fu1);
04001 nmg_fu_touchingloops(rs->fu2);
04002 }
04003
04004 assessment = nmg_assess_vu( rs, pos );
04005 old_state = rs->state;
04006 switch( old_state ) {
04007 default:
04008 case NMG_STATE_ERROR:
04009 rt_bomb("nmg_face_state_transition: was in ERROR state\n");
04010 case NMG_STATE_OUT:
04011 stp = &nmg_state_is_out[assessment];
04012 break;
04013 case NMG_STATE_ON_L:
04014 stp = &nmg_state_is_on_L[assessment];
04015 break;
04016 case NMG_STATE_ON_R:
04017 stp = &nmg_state_is_on_R[assessment];
04018 break;
04019 case NMG_STATE_ON_B:
04020 stp = &nmg_state_is_on_B[assessment];
04021 break;
04022 case NMG_STATE_ON_N:
04023 stp = &nmg_state_is_on_N[assessment];
04024 break;
04025 case NMG_STATE_IN:
04026 stp = &nmg_state_is_in[assessment];
04027 break;
04028 }
04029
04030 if( assessment != stp->assessment ) {
04031 bu_log("assessment=%d, stp->assessment=%d, error\n", assessment, stp->assessment);
04032 rt_bomb("nmg_face_state_transition() bad table\n");
04033 }
04034 action = stp->action;
04035 new_state = stp->new_state;
04036 rs->last_action = action;
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046 if( other_rs_state == NMG_STATE_OUT && action != NMG_ACTION_ERROR &&
04047 action != NMG_ACTION_NONE ) {
04048 action = NMG_ACTION_NONE_OPTIM;
04049 }
04050
04051 if(rt_g.NMG_debug&DEBUG_FCUT) {
04052 bu_log("nmg_face_state_transition(vu x%x, pos=%d)\n\told=%s, assessed=%s, new=%s, action=%s\n",
04053 vu, pos,
04054 nmg_state_names[old_state], nmg_v_assessment_names[assessment],
04055 nmg_state_names[new_state], action_names[action] );
04056 }
04057
04058
04059
04060
04061
04062 if( NMG_V_ASSESSMENT_PREV(assessment) == NMG_E_ASSESSMENT_ON_REV ) {
04063 eu = nmg_find_eu_of_vu(vu);
04064 eu = BU_LIST_PPREV_CIRC( edgeuse, eu );
04065 NMG_CK_EDGEUSE(eu);
04066 if( !rs->eg_p || eu->g.lseg_p != rs->eg_p ) {
04067 if( rs->eg_p )
04068 NMG_CK_EDGE_G_LSEG(rs->eg_p)
04069 nmg_edge_geom_isect_line( eu, rs, "force ON_REV to line" );
04070 }
04071 }
04072 if( NMG_V_ASSESSMENT_NEXT(assessment) == NMG_E_ASSESSMENT_ON_FORW ) {
04073 eu = nmg_find_eu_of_vu(vu);
04074 NMG_CK_EDGEUSE(eu);
04075 if( !rs->eg_p || eu->g.lseg_p != rs->eg_p ) {
04076 if( rs->eg_p )
04077 NMG_CK_EDGE_G_LSEG(rs->eg_p)
04078 nmg_edge_geom_isect_line( eu, rs, "force ON_FORW to line" );
04079 }
04080 }
04081
04082 switch( action ) {
04083 default:
04084 case NMG_ACTION_ERROR:
04085 bomb:
04086 {
04087 struct bu_vls str;
04088
04089 bu_log("nmg_face_state_transition: got action=ERROR\n");
04090 bu_vls_init(&str);
04091 bu_vls_printf(&str,"nmg_face_state_transition(vu x%lx, pos=%d)\n\told=%s, assessed=%s, new=%s, action=%s\n",
04092 (long)vu, pos,
04093 nmg_state_names[old_state], nmg_v_assessment_names[assessment],
04094 nmg_state_names[new_state], action_names[action] );
04095 if( RT_G_DEBUG || rt_g.NMG_debug ) {
04096
04097 lu = nmg_find_lu_of_vu( vu );
04098 NMG_CK_LOOPUSE(lu);
04099
04100 bu_log("Loop with the offending vertex\n");
04101 nmg_pr_lu_briefly(lu, (char *)0);
04102 #if 0
04103 if(rt_g.NMG_debug&DEBUG_FCUT) {
04104 bu_log("The whole face\n");
04105 nmg_pr_fu(lu->up.fu_p, (char *)0);
04106 }
04107 #endif
04108
04109
04110 #if 0
04111 rt_g.NMG_debug |= DEBUG_FCUT|DEBUG_PLOTEM;
04112 nmg_pl_comb_fu( 0, 1, lu->up.fu_p );
04113 nmg_plot_lu_ray(lu, rs->vu[0], rs->vu[rs->nvu-1], rs->left );
04114 {
04115 FILE *fp = fopen("error.pl", "w");
04116 nmg_pl_m(fp, nmg_find_model((long *)lu));
04117 fclose(fp);
04118 bu_log("wrote error.pl\n");
04119 }
04120
04121 nmg_stash_model_to_file( "error.g", nmg_find_model((long*)lu), "nmg_fcut.c error dump" );
04122 #endif
04123 }
04124
04125 rt_bomb(bu_vls_addr(&str));
04126 }
04127 case NMG_ACTION_NONE:
04128 case NMG_ACTION_NONE_OPTIM:
04129 if( *(vu->up.magic_p) != NMG_LOOPUSE_MAGIC ) break;
04130 lu = vu->up.lu_p;
04131 if( old_state != NMG_STATE_OUT && lu->orientation == OT_BOOLPLACE ) {
04132
04133
04134
04135 lu->orientation = lu->lumate_p->orientation = OT_UNSPEC;
04136 }
04137 break;
04138 case NMG_ACTION_VFY_EXT:
04139
04140 lu = nmg_find_lu_of_vu( vu );
04141 NMG_CK_LOOPUSE(lu);
04142 switch( lu->orientation ) {
04143 case OT_SAME:
04144 break;
04145 default:
04146 bu_log("nmg_face_state_transition: VFY_EXT got orientation=%s\n",
04147 nmg_orientation(lu->orientation) );
04148 break;
04149 }
04150 break;
04151 case NMG_ACTION_VFY_MULTI:
04152
04153
04154
04155
04156 if( multi ) break;
04157 bu_log("nmg_face_state_transition: VFY_MULTI had only 1 vertex\n");
04158 goto bomb;
04159 case NMG_ACTION_LONE_V_ESPLIT:
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171 lu = nmg_find_lu_of_vu( vu );
04172 NMG_CK_LOOPUSE(lu);
04173 for( e_pos = pos-1; e_pos >= 0; e_pos-- ) {
04174 prev_vu = rs->vu[e_pos];
04175 NMG_CK_VERTEXUSE(prev_vu);
04176 prev_lu = nmg_find_lu_of_vu( prev_vu );
04177
04178 if( *prev_vu->up.magic_p == NMG_EDGEUSE_MAGIC )
04179 break;
04180
04181 #if 0
04182 bu_log("prev_vu->up is %s\n", bu_identify_magic(*prev_vu->up.magic_p) );
04183 nmg_pr_vu(prev_vu, "prev ");
04184 nmg_pr_vu(rs->vu[e_pos], "cur ");
04185 #endif
04186 }
04187 if( e_pos < 0 ) rt_bomb("nmg_face_state_transition: LONE_V_ESPLIT can't find start of edge!\n");
04188 eu = prev_vu->up.eu_p;
04189 NMG_CK_EDGEUSE(eu);
04190 e_assessment = nmg_assess_eu( eu, 1, rs, e_pos );
04191 if( e_assessment == NMG_E_ASSESSMENT_ON_FORW ) {
04192
04193 } else {
04194 e_assessment = nmg_assess_eu( eu, 0, rs, e_pos );
04195 if( e_assessment == NMG_E_ASSESSMENT_ON_REV ) {
04196
04197 eu = BU_LIST_PPREV_CIRC( edgeuse, eu );
04198 } else {
04199
04200 bu_log("LONE_V_ESPLIT: rev e_assessment = %s\n", nmg_e_assessment_names[e_assessment]);
04201 rt_bomb("nmg_face_state_transition: LONE_V_ESPLIT could not find ON edge to split\n");
04202 }
04203 }
04204
04205 if( vu->v_p == eu->vu_p->v_p ) {
04206
04207 rs->vu[pos] = eu->vu_p;
04208 } else if( vu->v_p == eu->eumate_p->vu_p->v_p ) {
04209
04210 rs->vu[pos] = BU_LIST_PNEXT_CIRC(edgeuse, eu)->vu_p;
04211 } else {
04212
04213 nmg_edge_geom_isect_line( eu, rs, "LONE_V_ESPLIT, before edge split" );
04214 rs->vu[pos] = nmg_ebreaker( vu->v_p, eu, rs->tol )->vu_p;
04215 }
04216
04217 nmg_klu(lu);
04218 if(rt_g.NMG_debug&DEBUG_FCUT) {
04219 bu_log("After LONE_V_ESPLIT, the final loop:\n");
04220 lu = nmg_find_lu_of_vu(rs->vu[pos]);
04221 NMG_CK_LOOPUSE(lu);
04222 nmg_pr_lu(lu, " ");
04223 nmg_plot_lu_ray(lu, rs->vu[0], rs->vu[rs->nvu-1], rs->left );
04224 }
04225 break;
04226 case NMG_ACTION_LONE_V_JAUNT:
04227
04228
04229
04230
04231
04232
04233 prev_vu = rs->vu[pos-1];
04234 NMG_CK_VERTEXUSE(prev_vu);
04235
04236 if( *prev_vu->up.magic_p == NMG_LOOPUSE_MAGIC ) {
04237
04238 rs->vu[pos] = nmg_join_2singvu_loops( prev_vu, vu );
04239
04240 lu = nmg_find_lu_of_vu(rs->vu[pos]);
04241 NMG_CK_LOOPUSE(lu);
04242
04243 nmg_set_lu_orientation( lu, old_state==NMG_STATE_IN );
04244 } else {
04245 rs->vu[pos] = nmg_join_singvu_loop( prev_vu, vu );
04246 }
04247
04248
04249 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, rs->vu[pos]->up.eu_p);
04250 nmg_edge_geom_isect_line( first_new_eu, rs, "LONE_V_JAUNT, new edge" );
04251
04252
04253
04254
04255 nmg_loop_g(nmg_find_lu_of_vu(rs->vu[pos])->l_p, rs->tol);
04256
04257 if(rt_g.NMG_debug&DEBUG_FCUT) {
04258 bu_log("After LONE_V_JAUNT, the final loop:\n");
04259 nmg_pr_lu_briefly(nmg_find_lu_of_vu(rs->vu[pos]), (char *)0);
04260 nmg_plot_lu_ray(nmg_find_lu_of_vu(rs->vu[pos]),
04261 rs->vu[0], rs->vu[rs->nvu-1], rs->left );
04262 }
04263 break;
04264 case NMG_ACTION_CUTJOIN:
04265
04266
04267
04268
04269
04270
04271
04272
04273 lu = nmg_find_lu_of_vu( vu );
04274 NMG_CK_LOOPUSE(lu);
04275 fu = lu->up.fu_p;
04276 NMG_CK_FACEUSE(fu);
04277 prev_vu = rs->vu[pos-1];
04278 NMG_CK_VERTEXUSE(prev_vu);
04279 prev_lu = nmg_find_lu_of_vu( prev_vu );
04280 NMG_CK_LOOPUSE(prev_lu);
04281
04282
04283 old_eu = nmg_findeu(prev_vu->v_p, vu->v_p, (struct shell *)NULL,
04284 (struct edgeuse *)NULL, 0);
04285
04286 if( lu->l_p == prev_lu->l_p ) {
04287 int is_crack;
04288
04289
04290 is_crack = nmg_loop_is_a_crack(lu);
04291 if(rt_g.NMG_debug&DEBUG_FCUT)
04292 bu_log("Calling nmg_cut_loop(prev_vu=x%x, vu=x%x) is_crack=%d, old_eu=x%x\n", prev_vu, vu, is_crack, old_eu);
04293 if( prev_vu->v_p == vu->v_p ) {
04294
04295 lu = nmg_split_lu_at_vu( prev_lu, prev_vu );
04296 } else {
04297 lu = nmg_cut_loop( prev_vu, vu );
04298
04299
04300
04301
04302 first_new_eu = BU_LIST_PPREV_CIRC( edgeuse, &prev_vu->up.eu_p->l );
04303 second_new_eu = BU_LIST_PPREV_CIRC( edgeuse, &vu->up.eu_p->l );
04304 NMG_CK_EDGEUSE(first_new_eu);
04305 NMG_CK_EDGEUSE(second_new_eu);
04306 if( first_new_eu->vu_p->v_p != vu->v_p || first_new_eu->eumate_p->vu_p->v_p != prev_vu->v_p ) {
04307 nmg_pr_vu_briefly(prev_vu, 0);
04308 nmg_pr_vu_briefly(vu, 0);
04309 nmg_pr_eu_endpoints(first_new_eu, 0);
04310 nmg_pr_eu_endpoints(second_new_eu, 0);
04311 if(old_eu) nmg_pr_eu_endpoints(old_eu, 0);
04312 rt_bomb("nmg_face_state_transition() cut loop bafflement\n");
04313 }
04314
04315 nmg_edge_geom_isect_line( first_new_eu, rs, "CUTJOIN, new edge after loop cut" );
04316 if( old_eu ) nmg_radial_join_eu( old_eu, first_new_eu, rs->tol );
04317 }
04318
04319 nmg_loop_g( lu->l_p, rs->tol );
04320 nmg_loop_g( prev_lu->l_p, rs->tol );
04321
04322 nmg_lu_reorient( lu );
04323 nmg_lu_reorient( prev_lu );
04324
04325 if(rt_g.NMG_debug&DEBUG_FCUT) {
04326 bu_log("After CUT, the final loop:\n");
04327 nmg_pr_lu_briefly(nmg_find_lu_of_vu(rs->vu[pos]), (char *)0);
04328 nmg_plot_lu_ray(nmg_find_lu_of_vu(rs->vu[pos]),
04329 rs->vu[0], rs->vu[rs->nvu-1], rs->left );
04330 }
04331 break;
04332 }
04333
04334
04335
04336
04337
04338
04339 if(rt_g.NMG_debug&DEBUG_FCUT) {
04340 bu_log("nmg_face_state_transition() joining 2 loops, prev_vu=x%x, vu=x%x, old_eu=x%x\n",
04341 prev_vu, vu, old_eu);
04342 }
04343
04344 if( *prev_vu->up.magic_p == NMG_LOOPUSE_MAGIC ||
04345 *vu->up.magic_p == NMG_LOOPUSE_MAGIC ) {
04346
04347
04348
04349
04350
04351
04352
04353 if( *prev_vu->up.magic_p == NMG_LOOPUSE_MAGIC &&
04354 *vu->up.magic_p != NMG_LOOPUSE_MAGIC ) {
04355 if(rt_g.NMG_debug&DEBUG_FCUT)
04356 bu_log( "\tprev_vu is a vertex loop\n" );
04357
04358
04359 rs->vu[pos-1] = nmg_join_singvu_loop( vu, prev_vu );
04360 } else if( *vu->up.magic_p == NMG_LOOPUSE_MAGIC &&
04361 *prev_vu->up.magic_p != NMG_LOOPUSE_MAGIC ) {
04362 if(rt_g.NMG_debug&DEBUG_FCUT)
04363 bu_log( "\tvu is a vertex loop\n" );
04364
04365
04366 rs->vu[pos] = nmg_join_singvu_loop( prev_vu, vu );
04367 } else {
04368
04369 if(rt_g.NMG_debug&DEBUG_FCUT)
04370 bu_log( "\tprev_vu and vu are vertex loops\n" );
04371 vu = rs->vu[pos] = nmg_join_2singvu_loops( prev_vu, vu );
04372
04373 lu = nmg_find_lu_of_vu(vu);
04374 NMG_CK_LOOPUSE(lu);
04375 nmg_set_lu_orientation( lu, old_state==NMG_STATE_IN );
04376 }
04377 } else {
04378 rs->vu[pos] = nmg_join_2loops( prev_vu, vu );
04379 }
04380
04381
04382
04383
04384 vu = rs->vu[pos];
04385 lu = nmg_find_lu_of_vu(vu);
04386 NMG_CK_LOOPUSE(lu);
04387 prev_vu = rs->vu[pos-1];
04388 eu = prev_vu->up.eu_p;
04389 NMG_CK_EDGEUSE(eu);
04390 first_new_eu = BU_LIST_PPREV_CIRC(edgeuse, rs->vu[pos]->up.eu_p);
04391 NMG_CK_EDGEUSE(first_new_eu);
04392 if( eu == first_new_eu ) {
04393 nmg_edge_geom_isect_line( first_new_eu, rs, "CUTJOIN new edge" );
04394 if( old_eu ) nmg_radial_join_eu( old_eu, eu, rs->tol );
04395 }
04396
04397
04398 nmg_loop_g(lu->l_p, rs->tol);
04399
04400 if(rt_g.NMG_debug&DEBUG_FCUT) {
04401 bu_log("After JOIN, the final loop:\n");
04402 nmg_pr_lu_briefly(lu, (char *)0);
04403 nmg_plot_lu_ray( lu, rs->vu[0], rs->vu[rs->nvu-1], rs->left );
04404 }
04405 break;
04406 }
04407
04408 rs->state = new_state;
04409
04410 if( rt_g.NMG_debug & DEBUG_VERIFY ) {
04411
04412 nmg_vfu( &rs->fu1->s_p->fu_hd, rs->fu1->s_p );
04413 nmg_vfu( &rs->fu2->s_p->fu_hd, rs->fu2->s_p );
04414 nmg_fu_touchingloops(rs->fu1);
04415 nmg_fu_touchingloops(rs->fu2);
04416 }
04417
04418 if(rt_g.NMG_debug&DEBUG_FCUT) {
04419 bu_log("nmg_face_state_transition(vu x%x, pos=%d) END\n",
04420 rs->vu[pos], pos);
04421 }
04422 if(rs->eg_p) NMG_CK_EDGE_G_LSEG(rs->eg_p);
04423 return 0;
04424 }
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435