00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "common.h"
00037
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <math.h>
00041
00042 #include "machine.h"
00043 #include "vmath.h"
00044 #include "nmg.h"
00045 #include "raytrace.h"
00046 #include "plot3.h"
00047
00048
00049
00050
00051
00052
00053
00054 struct ve_dist {
00055 struct bu_list l;
00056 long *magic_p;
00057 double dist;
00058 struct vertex *v1;
00059 struct vertex *v2;
00060 int status;
00061 };
00062 #define NMG_VE_DIST_MAGIC 0x102938
00063 #define NMG_CK_VED(_p) NMG_CKMAG(_p, NMG_VE_DIST_MAGIC, "vertex/edge_dist")
00064
00065
00066
00067
00068
00069 struct edge_info {
00070 struct bu_list l;
00071 struct ve_dist *ved_p;
00072 struct edgeuse *eu_p;
00073 int class;
00074 };
00075 #define NMG_EDGE_INFO_MAGIC 0xe100
00076 #define NMG_CK_EI(_p) NMG_CKMAG(_p, NMG_EDGE_INFO_MAGIC, "edge_info")
00077
00078 struct fpi {
00079 long magic;
00080 const struct bn_tol *tol;
00081 const struct faceuse *fu_p;
00082 struct bu_list ve_dh;
00083 plane_t norm;
00084 point_t pt;
00085 void (*eu_func)();
00086 void (*vu_func)();
00087 const char *priv;
00088 int hits;
00089 };
00090 #define NMG_FPI_MAGIC 12345678
00091 #define NMG_CK_FPI(_fpi) \
00092 NMG_CKMAG(_fpi, NMG_FPI_MAGIC, "fu_pt_info") ; \
00093 BN_CK_TOL( _fpi->tol ); \
00094 BU_CK_LIST_HEAD(&_fpi->ve_dh)
00095
00096 #define NMG_FPI_TOUCHED 27
00097 #define NMG_FPI_MISSED 32768
00098
00099 #ifdef USE_PROTOTYPES
00100 static int nmg_class_pt_vu(struct fpi *fpi, struct vertexuse *vu);
00101
00102 static struct edge_info *nmg_class_pt_eu(struct fpi *fpi, struct edgeuse *eu, struct edge_info *edge_list, const int in_or_out_only);
00103 static int compute_loop_class(struct fpi *fpi, const struct loopuse *lu,struct edge_info *edge_list);
00104 static int nmg_class_pt_lu(struct loopuse *lu, struct fpi *fpi, const int in_or_out_only);
00105 int nmg_class_pt_fu_except(const point_t pt, const struct faceuse *fu, const struct loopuse *ignore_lu, void (*eu_func)(), void (*vu_func)(), const char *priv, const int call_on_hits, const int in_or_out_only, const struct bn_tol *tol);
00106 #endif
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 int
00139 bn_distsq_pt3_lseg3(fastf_t *dist, const fastf_t *a, const fastf_t *b, const fastf_t *p, const struct bn_tol *tol)
00140 {
00141 vect_t PtoA;
00142 vect_t PtoB;
00143 vect_t AtoB;
00144 fastf_t P_A_sq;
00145 fastf_t P_B_sq;
00146 fastf_t B_A_sq;
00147 fastf_t t;
00148 fastf_t dot;
00149
00150 BN_CK_TOL(tol);
00151 #if 0
00152 if( RT_G_DEBUG & DEBUG_MATH ) {
00153 bu_log("bn_distsq_pt3_lseg3() a=(%g,%g,%g) b=(%g,%g,%g)\n\tp=(%g,%g,%g), tol->dist=%g sq=%g\n",
00154 V3ARGS(a),
00155 V3ARGS(b),
00156 V3ARGS(p),
00157 tol->dist, tol->dist_sq );
00158 }
00159 #endif
00160
00161
00162 VSUB2(PtoA, p, a);
00163 if( (P_A_sq = MAGSQ(PtoA)) < tol->dist_sq ) {
00164
00165 *dist = 0.0;
00166 return 1;
00167 }
00168
00169
00170 VSUB2(PtoB, p, b);
00171 if( (P_B_sq = MAGSQ(PtoB)) < tol->dist_sq ) {
00172
00173 *dist = 0.0;
00174 return 2;
00175 }
00176
00177 VSUB2(AtoB, b, a);
00178 B_A_sq = MAGSQ(AtoB);
00179
00180
00181
00182
00183 dot = VDOT(PtoA, AtoB);
00184 t = dot * dot / B_A_sq;
00185
00186 if( dot < 0.0 && t > tol->dist_sq ) {
00187
00188 *dist = P_A_sq;
00189 return 3;
00190 }
00191 if( t < B_A_sq - tol->dist_sq ) {
00192
00193 register fastf_t dsq;
00194
00195
00196 if( (dsq = P_A_sq - t ) <= tol->dist_sq ) {
00197
00198 *dist = 0.0;
00199 return 0;
00200 }
00201
00202
00203 *dist = dsq;
00204 return 5;
00205 }
00206
00207
00208 *dist = P_B_sq;
00209 return 4;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 static int
00219 nmg_class_pt_vu(struct fpi *fpi, struct vertexuse *vu)
00220 {
00221 vect_t delta;
00222 struct ve_dist *ved;
00223
00224 NMG_CK_VERTEXUSE(vu);
00225
00226
00227 for (BU_LIST_FOR(ved, ve_dist, &fpi->ve_dh)){
00228 NMG_CK_VED(ved);
00229 if (ved->magic_p == &vu->v_p->magic) {
00230 goto found;
00231 }
00232 }
00233
00234
00235
00236
00237
00238 VSUB2(delta, vu->v_p->vg_p->coord, fpi->pt);
00239
00240 ved = (struct ve_dist *) bu_malloc(sizeof(struct ve_dist), "ve_dist structure");
00241 ved->magic_p = &vu->v_p->magic;
00242 ved->dist = MAGNITUDE(delta);
00243 if (ved->dist < fpi->tol->dist_sq ) {
00244 ved->status = NMG_FPI_TOUCHED;
00245 if (fpi->hits == NMG_FPI_PERGEOM)
00246 fpi->vu_func(vu, fpi->pt, fpi->priv);
00247 }
00248 else ved->status = NMG_FPI_MISSED;
00249
00250 ved->v1 = ved->v2 = vu->v_p;
00251
00252 BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC);
00253 BU_LIST_APPEND(&fpi->ve_dh, &ved->l);
00254 found:
00255
00256 if (fpi->vu_func &&
00257 ved->status == NMG_FPI_TOUCHED &&
00258 fpi->hits == NMG_FPI_PERUSE)
00259 fpi->vu_func(vu, fpi->pt, fpi->priv);
00260
00261 return ved->status;
00262 }
00263
00264 #if 0
00265 static void
00266 pl_pt_e(fpi, ei)
00267 struct fpi *fpi;
00268 struct edge_info *ei;
00269 {
00270 FILE *fd;
00271 char name[25];
00272 long *b;
00273 point_t pca;
00274 fastf_t dist;
00275 static int plot_file_number=0;
00276 struct bn_tol tmp_tol;
00277
00278 NMG_CK_FPI(fpi);
00279 NMG_CK_FACEUSE(fpi->fu_p);
00280 NMG_CK_EI(ei);
00281
00282 sprintf(name, "pt_e%02d.pl", plot_file_number++);
00283 if ((fd=fopen(name, "w")) == (FILE *)NULL) {
00284 perror(name);
00285 bu_bomb("unable to open file for writing");
00286 }
00287
00288 bu_log("\toverlay %s\n", name);
00289 b = (long *)bu_calloc( fpi->fu_p->s_p->r_p->m_p->maxindex,
00290 sizeof(long), "bit vec"),
00291
00292 pl_erase(fd);
00293 pd_3space(fd,
00294 fpi->fu_p->f_p->min_pt[0]-1.0,
00295 fpi->fu_p->f_p->min_pt[1]-1.0,
00296 fpi->fu_p->f_p->min_pt[2]-1.0,
00297 fpi->fu_p->f_p->max_pt[0]+1.0,
00298 fpi->fu_p->f_p->max_pt[1]+1.0,
00299 fpi->fu_p->f_p->max_pt[2]+1.0);
00300
00301 nmg_pl_eu(fd, ei->eu_p, b, 255, 255, 255);
00302
00303 tmp_tol.magic = BN_TOL_MAGIC;
00304 tmp_tol.dist = 0.005;
00305 tmp_tol.dist_sq = tmp_tol.dist * tmp_tol.dist;
00306 tmp_tol.perp = 1e-6;
00307 tmp_tol.para = 1 - tmp_tol.perp;
00308
00309 (void)bn_dist_pt3_lseg3( &dist, pca, ei->eu_p->vu_p->v_p->vg_p->coord,
00310 ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord, fpi->pt, &tmp_tol );
00311 pl_color(fd, 255, 255, 50);
00312 pdv_3line(fd, pca, fpi->pt);
00313
00314 bu_free((char *)b, "bit vec");
00315 fclose(fd);
00316 }
00317 #endif
00318 static int
00319 Quadrant(fastf_t x, fastf_t y)
00320 {
00321 if( x >= 0.0 )
00322 {
00323 if( y >= 0.0 )
00324 return( 1 );
00325 else
00326 return( 4 );
00327 }
00328 else
00329 {
00330 if( y >= 0.0 )
00331 return( 2 );
00332 else
00333 return( 3 );
00334 }
00335 }
00336
00337 int
00338 nmg_eu_is_part_of_crack(const struct edgeuse *eu)
00339 {
00340 struct loopuse *lu;
00341 struct edgeuse *eu_test;
00342
00343 NMG_CK_EDGEUSE( eu );
00344
00345
00346 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC )
00347 return( 0 );
00348
00349 lu = eu->up.lu_p;
00350 NMG_CK_LOOPUSE( lu );
00351
00352 for( BU_LIST_FOR( eu_test, edgeuse, &lu->down_hd ) )
00353 {
00354 if( eu_test == eu )
00355 continue;
00356
00357 if( eu_test->vu_p->v_p == eu->eumate_p->vu_p->v_p &&
00358 eu_test->eumate_p->vu_p->v_p == eu->vu_p->v_p )
00359 return( 1 );
00360 }
00361
00362 return( 0 );
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 int
00382 nmg_class_pt_euvu(const fastf_t *pt, struct edgeuse *eu_in, const struct bn_tol *tol)
00383 {
00384 struct loopuse *lu;
00385 struct edgeuse *prev_eu;
00386 struct edgeuse *eu;
00387 struct vertex *v0,*v1,*v2;
00388 vect_t left;
00389 vect_t eu_dir;
00390 vect_t other_eudir;
00391 vect_t pt_dir;
00392 fastf_t xo,yo;
00393 fastf_t xpt,ypt;
00394 fastf_t len;
00395 int quado,quadpt;
00396 int class = NMG_CLASS_Unknown;
00397 int eu_is_crack=0;
00398 int prev_eu_is_crack=0;
00399
00400 NMG_CK_EDGEUSE( eu_in );
00401 BN_CK_TOL( tol );
00402
00403 eu = eu_in;
00404
00405 if(rt_g.NMG_debug & DEBUG_PT_FU )
00406 bu_log( "nmg_class_pt_euvu( (%g %g %g), eu=x%x )\n", V3ARGS( pt ), eu );
00407
00408 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC )
00409 {
00410 bu_log( "nmg_class_pt_euvu() called with eu (x%x) that isn't part of a loop\n", eu );
00411 rt_bomb( "nmg_class_pt_euvu() called with eu that isn't part of a loop" );
00412 }
00413 lu = eu->up.lu_p;
00414 NMG_CK_LOOPUSE( lu );
00415
00416 eu_is_crack = nmg_eu_is_part_of_crack( eu );
00417
00418 prev_eu = BU_LIST_PPREV_CIRC( edgeuse, &eu->l );
00419
00420 prev_eu_is_crack = nmg_eu_is_part_of_crack( prev_eu );
00421
00422
00423 if( eu_is_crack && prev_eu_is_crack )
00424 return( NMG_CLASS_Unknown );
00425
00426 if( eu_is_crack )
00427 {
00428 struct edgeuse *eu_test;
00429 int done=0;
00430
00431 if(rt_g.NMG_debug & DEBUG_PT_FU )
00432 bu_log( "nmg_class_pt_euvu: eu x%x is a crack\n", eu );
00433
00434
00435 eu_test = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
00436 while( !done )
00437 {
00438 while( eu_test->vu_p->v_p != eu->vu_p->v_p && eu_test != eu )
00439 eu_test = BU_LIST_PNEXT_CIRC( edgeuse, &eu_test->l );
00440
00441 if( eu_test == eu )
00442 done = 1;
00443
00444 if( !nmg_eu_is_part_of_crack( eu_test ) )
00445 done = 1;
00446
00447 if( !done )
00448 eu_test = BU_LIST_PNEXT_CIRC( edgeuse, &eu_test->l );
00449 }
00450
00451 if( eu_test == eu )
00452 return( NMG_CLASS_Unknown );
00453 else
00454 eu = eu_test;
00455
00456 if(rt_g.NMG_debug & DEBUG_PT_FU )
00457 bu_log( "\tUsing eu x%x instead\n", eu );
00458 }
00459
00460 if( prev_eu_is_crack )
00461 {
00462 struct edgeuse *eu_test;
00463 int done=0;
00464
00465 if(rt_g.NMG_debug & DEBUG_PT_FU )
00466 bu_log( "nmg_class_pt_euvu: prev_eu (x%x) is a crack\n" );
00467
00468
00469 eu_test = BU_LIST_PPREV_CIRC( edgeuse, &prev_eu->l );
00470 while( !done )
00471 {
00472 while( eu_test->eumate_p->vu_p->v_p != eu->vu_p->v_p && eu_test != prev_eu )
00473 eu_test = BU_LIST_PPREV_CIRC( edgeuse, &eu_test->l );
00474
00475 if( eu_test == prev_eu )
00476 done = 1;
00477
00478 if( !nmg_eu_is_part_of_crack( eu_test ) )
00479 done = 1;
00480
00481 if( !done )
00482 eu_test = BU_LIST_PPREV_CIRC( edgeuse, &eu_test->l );
00483 }
00484
00485 if( eu_test == prev_eu )
00486 return( NMG_CLASS_Unknown );
00487 else
00488 prev_eu = eu_test;
00489
00490 if(rt_g.NMG_debug & DEBUG_PT_FU )
00491 bu_log( "\tUsing prev_eu x%x instead\n", prev_eu );
00492 }
00493
00494
00495 if( nmg_find_eu_leftvec( left, eu ) )
00496 {
00497 bu_log( "nmg_class_pt_euvu: nmg_find_eu_leftvec() for eu=x%x failed!\n",eu );
00498 rt_bomb( "nmg_class_pt_euvu: nmg_find_eu_leftvec() failed!" );
00499 }
00500
00501 if(rt_g.NMG_debug & DEBUG_PT_FU )
00502 bu_log( "\tprev_eu = x%x, left = (%g %g %g)\n", prev_eu, V3ARGS( left ) );
00503
00504
00505 v0 = eu->vu_p->v_p;
00506 NMG_CK_VERTEX( v0 );
00507
00508
00509 v1 = eu->eumate_p->vu_p->v_p;
00510 NMG_CK_VERTEX( v1 );
00511
00512
00513 v2 = prev_eu->vu_p->v_p;
00514 NMG_CK_VERTEX( v2 );
00515
00516 if(rt_g.NMG_debug & DEBUG_PT_FU )
00517 bu_log( "\tv0=x%x, v1=x%x, v2=x%x\n", v0, v1, v2 );
00518
00519
00520 VSUB2( eu_dir, v1->vg_p->coord, v0->vg_p->coord );
00521
00522
00523 VSUB2( other_eudir, v2->vg_p->coord, v0->vg_p->coord );
00524
00525 if(rt_g.NMG_debug & DEBUG_PT_FU )
00526 bu_log( "\teu_dir=(%g %g %g), other_eudir=(%x %x %x)\n",V3ARGS( eu_dir ), V3ARGS( other_eudir ) );
00527
00528
00529 xo = VDOT( eu_dir, other_eudir );
00530 yo = VDOT( left, other_eudir );
00531
00532
00533 quado = Quadrant( xo, yo );
00534
00535 if(rt_g.NMG_debug & DEBUG_PT_FU )
00536 bu_log( "\txo=%g, yo=%g, qudarant=%d\n", xo,yo,quado );
00537
00538
00539 VSUB2( pt_dir, pt, v0->vg_p->coord );
00540
00541 if(rt_g.NMG_debug & DEBUG_PT_FU )
00542 bu_log( "\tpt_dir=( %g %g %g )\n", V3ARGS( pt_dir ) );
00543
00544
00545 xpt = VDOT( eu_dir, pt_dir );
00546 ypt = VDOT( left, pt_dir );
00547
00548
00549 quadpt = Quadrant( xpt, ypt );
00550
00551 if(rt_g.NMG_debug & DEBUG_PT_FU )
00552 bu_log( "\txpt=%g, ypt=%g, qudarant=%d\n", xpt,ypt,quadpt );
00553
00554
00555 if( quadpt < quado )
00556 return( NMG_CLASS_AinB );
00557
00558 if( quadpt > quado )
00559 return( NMG_CLASS_AoutB );
00560
00561
00562 len = sqrt( xo*xo + yo*yo );
00563 xo = xo/len;
00564 yo = yo/len;
00565
00566 len = sqrt( xpt*xpt + ypt*ypt );
00567 xpt = xpt/len;
00568 ypt = ypt/len;
00569
00570 if(rt_g.NMG_debug & DEBUG_PT_FU )
00571 bu_log( "\tNormalized xo,yo=(%g %g), xpt,ypt=( %g %g )\n", xo,yo,xpt,ypt );
00572
00573 switch( quadpt )
00574 {
00575 case 1:
00576 if( xpt >= xo && ypt <= yo )
00577 class = NMG_CLASS_AinB;
00578 else
00579 class = NMG_CLASS_AoutB;
00580 break;
00581 case 2:
00582 if( xpt >= xo && ypt >= yo )
00583 class = NMG_CLASS_AinB;
00584 else
00585 class = NMG_CLASS_AoutB;
00586 break;
00587 case 3:
00588 if( xpt <= xo && ypt >= yo )
00589 class = NMG_CLASS_AinB;
00590 else
00591 class = NMG_CLASS_AoutB;
00592 break;
00593 case 4:
00594 if( xpt <= xo && ypt <= yo )
00595 class = NMG_CLASS_AinB;
00596 else
00597 class = NMG_CLASS_AoutB;
00598 break;
00599 default:
00600 bu_log( "This can't happen (illegal quadrant %d)\n", quadpt );
00601 rt_bomb( "This can't happen (illegal quadrant)\n" );
00602 break;
00603 }
00604 if(rt_g.NMG_debug & DEBUG_PT_FU )
00605 bu_log( "returning %s\n", nmg_class_name( class ) );
00606
00607 return( class );
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617 static struct edge_info *
00618 nmg_class_pt_eu(struct fpi *fpi, struct edgeuse *eu, struct edge_info *edge_list, const int in_or_out_only)
00619 {
00620 struct bn_tol tmp_tol;
00621 struct edgeuse *next_eu;
00622 struct ve_dist *ved, *ed;
00623 struct edge_info *ei_p;
00624 struct edge_info *ei;
00625 pointp_t eu_pt;
00626 vect_t left;
00627 vect_t v_to_pt;
00628 int found_data = 0;
00629
00630 NMG_CK_FPI(fpi);
00631 BN_CK_TOL(fpi->tol);
00632
00633 if (rt_g.NMG_debug & DEBUG_PT_FU) {
00634 bu_log("pt (%g %g %g) vs_edge (%g %g %g) (%g %g %g) (eu=x%x)\n",
00635 V3ARGS(fpi->pt),
00636 V3ARGS(eu->vu_p->v_p->vg_p->coord),
00637 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord), eu);
00638 }
00639 #if 0
00640
00641 for (BU_LIST_FOR(ed, ve_dist, &fpi->ve_dh)) {
00642 NMG_CK_VED(ed);
00643 if (ed->magic_p == &eu->e_p->magic) {
00644
00645
00646
00647 if (rt_g.NMG_debug & DEBUG_PT_FU)
00648 bu_log ("pt previously classified WRT Edge\n");
00649
00650 ved = ed;
00651 found_data = 1;
00652 goto found;
00653 }
00654
00655 if (ed->dist <= fpi->tol->dist_sq &&
00656 (ed->magic_p == &eu->vu_p->v_p->magic ||
00657 ed->magic_p == &eu->eumate_p->vu_p->v_p->magic) ) {
00658
00659
00660
00661 if (rt_g.NMG_debug & DEBUG_PT_FU) {
00662 register struct vertex *v_p =
00663 (struct vertex *)ed->magic_p;
00664 bu_log ("vertex (%g %g %g) of edge previously touched\n",
00665 V3ARGS(v_p->vg_p->coord));
00666 }
00667 ved = ed;
00668 found_data = 1;
00669 goto found;
00670 }
00671 }
00672 #endif
00673
00674
00675
00676
00677 tmp_tol = (*fpi->tol);
00678 if( in_or_out_only )
00679 {
00680 tmp_tol.dist = 0.0;
00681 tmp_tol.dist_sq = 0.0;
00682 }
00683
00684 ved = (struct ve_dist *)bu_malloc(sizeof(struct ve_dist), "ve_dist structure");
00685 ved->magic_p = &eu->e_p->magic;
00686 ved->status = bn_distsq_pt3_lseg3(&ved->dist,
00687 eu->vu_p->v_p->vg_p->coord,
00688 eu->eumate_p->vu_p->v_p->vg_p->coord,
00689 fpi->pt,
00690 &tmp_tol);
00691 ved->v1 = eu->vu_p->v_p;
00692 ved->v2 = eu->eumate_p->vu_p->v_p;
00693 BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC);
00694 BU_LIST_APPEND(&fpi->ve_dh, &ved->l);
00695 eu_pt = ved->v1->vg_p->coord;
00696
00697 if (rt_g.NMG_debug & DEBUG_PT_FU )
00698 {
00699 bu_log( "nmg_class_pt_eu: status for eu x%x (%g %g %g)<->(%g %g %g) vs pt (%g %g %g) is %d\n",
00700 eu, V3ARGS( eu->vu_p->v_p->vg_p->coord ),
00701 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ),
00702 V3ARGS( fpi->pt ), ved->status );
00703 bu_log( "\tdist = %g\n", ved->dist );
00704 }
00705
00706
00707
00708
00709
00710
00711 ei = (struct edge_info *)bu_malloc(sizeof(struct edge_info), "struct edge_info");
00712 ei->ved_p = ved;
00713 ei->eu_p = eu;
00714 BU_LIST_MAGIC_SET(&ei->l, NMG_EDGE_INFO_MAGIC);
00715
00716
00717
00718 switch (ved->status) {
00719 case 0:
00720 ei->class = NMG_CLASS_AonBshared;
00721 if (fpi->eu_func &&
00722 (fpi->hits == NMG_FPI_PERUSE ||
00723 (fpi->hits == NMG_FPI_PERGEOM && !found_data) ) ) {
00724 fpi->eu_func(eu, fpi->pt, fpi->priv);
00725 }
00726 break;
00727 case 1:
00728 ei->class = NMG_CLASS_AonBshared;
00729
00730
00731
00732
00733 ed = (struct ve_dist *)bu_malloc(sizeof(struct ve_dist), "ve_dist structure");
00734 ed->magic_p = &ved->v1->magic;
00735 ed->status = ved->status;
00736 ed->v1 = ed->v2 = ved->v1;
00737
00738 BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC);
00739 BU_LIST_APPEND(&fpi->ve_dh, &ed->l);
00740
00741 if (fpi->vu_func &&
00742 (fpi->hits == NMG_FPI_PERUSE ||
00743 (fpi->hits == NMG_FPI_PERGEOM && !found_data) ) ) {
00744 fpi->vu_func(eu->vu_p, fpi->pt, fpi->priv);
00745 }
00746
00747 break;
00748 case 2:
00749 ei->class = NMG_CLASS_AonBshared;
00750
00751
00752
00753
00754 ed = (struct ve_dist *)bu_malloc(sizeof(struct ve_dist), "ve_dist structure");
00755 ed->magic_p = &ved->v2->magic;
00756 ed->status = ved->status;
00757 ed->v1 = ed->v2 = ved->v2;
00758
00759 BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC);
00760 BU_LIST_APPEND(&fpi->ve_dh, &ed->l);
00761 if (fpi->vu_func &&
00762 (fpi->hits == NMG_FPI_PERUSE ||
00763 (fpi->hits == NMG_FPI_PERGEOM && !found_data) ) ) {
00764 fpi->vu_func(eu->eumate_p->vu_p, fpi->pt, fpi->priv);
00765 }
00766 break;
00767
00768 case 3:
00769 ei->class = nmg_class_pt_euvu( fpi->pt, eu, fpi->tol );
00770 if( ei->class == NMG_CLASS_Unknown )
00771 ei->ved_p->dist = MAX_FASTF;
00772 break;
00773 case 4:
00774 next_eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l);
00775 ei->class = nmg_class_pt_euvu( fpi->pt, next_eu, fpi->tol );
00776 if( ei->class == NMG_CLASS_Unknown )
00777 ei->ved_p->dist = MAX_FASTF;
00778 break;
00779
00780 case 5:
00781 if (nmg_find_eu_left_non_unit( left, eu ))
00782 rt_bomb("can't find left vector\n");
00783
00784
00785
00786 VSUB2(v_to_pt, fpi->pt, eu_pt);
00787 if (VDOT(v_to_pt, left) >= 0.0)
00788 ei->class = NMG_CLASS_AinB;
00789 else
00790 ei->class = NMG_CLASS_AoutB;
00791 break;
00792 default:
00793 bu_log("%s:%d status = %d\n", __FILE__, __LINE__, ved->status);
00794 rt_bomb("Why did this happen?");
00795 break;
00796 }
00797
00798
00799 if (rt_g.NMG_debug & DEBUG_PT_FU) {
00800 bu_log("pt @ dist %g from edge classed %s vs edge\n",
00801 ei->ved_p->dist, nmg_class_name(ei->class));
00802
00803 }
00804
00805
00806 for (BU_LIST_FOR(ei_p, edge_info, &edge_list->l)) {
00807
00808
00809
00810
00811 if (ved->dist < ei_p->ved_p->dist ||
00812 (ved->dist == ei_p->ved_p->dist &&
00813 ei_p->ved_p->magic_p == ved->magic_p) )
00814 break;
00815 }
00816
00817 BU_LIST_INSERT(&ei_p->l, &ei->l);
00818 return ei;
00819 }
00820
00821
00822
00823
00824
00825
00826
00827 HIDDEN void make_near_list( struct edge_info *edge_list, struct bu_list *near1)
00828 {
00829 struct edge_info *ei;
00830 struct edge_info *ei_p;
00831 struct edge_info *tmp;
00832 double dist;
00833
00834 BU_CK_LIST_HEAD(&edge_list->l);
00835 BU_CK_LIST_HEAD(near1);
00836
00837
00838 ei = BU_LIST_FIRST( edge_info, &edge_list->l);
00839 while( BU_LIST_NOT_HEAD( &ei->l, &edge_list->l)) {
00840 NMG_CK_EI(ei);
00841 ei_p = BU_LIST_FIRST( edge_info, &edge_list->l);
00842 while( BU_LIST_NOT_HEAD( &ei_p->l, &edge_list->l)) {
00843 NMG_CK_EI(ei_p);
00844 NMG_CK_VED(ei_p->ved_p);
00845
00846
00847
00848
00849 if (ei_p->ved_p->magic_p == ei->ved_p->magic_p &&
00850 ei_p->eu_p->eumate_p->vu_p->v_p == ei->eu_p->vu_p->v_p &&
00851 ei_p->eu_p->vu_p->v_p == ei->eu_p->eumate_p->vu_p->v_p ) {
00852 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
00853 bu_log("tossing edgeuse pair:\n");
00854 bu_log("(%g %g %g) -> (%g %g %g)\n",
00855 V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
00856 V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
00857 bu_log("(%g %g %g) -> (%g %g %g)\n",
00858 V3ARGS(ei_p->eu_p->vu_p->v_p->vg_p->coord),
00859 V3ARGS(ei_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
00860 }
00861
00862 tmp = ei_p;
00863 ei_p = BU_LIST_PLAST(edge_info, &ei_p->l);
00864 BU_LIST_DEQUEUE(&tmp->l);
00865 bu_free((char *)tmp, "edge info struct");
00866 tmp = ei;
00867 ei = BU_LIST_PLAST(edge_info, &ei->l);
00868 BU_LIST_DEQUEUE(&tmp->l);
00869 bu_free((char *)tmp, "edge info struct");
00870 break;
00871 }
00872 ei_p = BU_LIST_PNEXT( edge_info, &ei_p->l );
00873 }
00874 ei = BU_LIST_PNEXT( edge_info, &ei->l );
00875 }
00876
00877 if( BU_LIST_IS_EMPTY( &edge_list->l ) )
00878 return;
00879
00880 ei = BU_LIST_FIRST(edge_info, &edge_list->l);
00881 NMG_CK_EI(ei);
00882 NMG_CK_VED(ei->ved_p);
00883 dist = ei->ved_p->dist;
00884
00885
00886 for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) {
00887 NMG_CK_EI(ei);
00888 NMG_CK_VED(ei->ved_p);
00889 if (ei->ved_p->dist == dist) {
00890 ei_p = BU_LIST_PLAST(edge_info, &ei->l);
00891 BU_LIST_DEQUEUE(&ei->l);
00892 BU_LIST_APPEND(near1, &ei->l);
00893 ei = ei_p;
00894 }
00895 }
00896
00897 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
00898 bu_log("dist %g near list\n", dist);
00899 for (BU_LIST_FOR(ei, edge_info, near1)) {
00900 bu_log("\t(%g %g %g) -> (%g %g %g)\n",
00901 V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
00902 V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
00903 bu_log("\tdist:%g class:%s status:%d\n\t\tv1(%g %g %g) v2(%g %g %g)\n",
00904 ei->ved_p->dist, nmg_class_name(ei->class),
00905 ei->ved_p->status,
00906 V3ARGS(ei->ved_p->v1->vg_p->coord),
00907 V3ARGS(ei->ved_p->v2->vg_p->coord));
00908 bu_log( "\tei->ved_p->magic_p=x%x, ei->eu_p->vu_p=x%x, ei->eu_p->eumate_p->vu_p=x%x\n",
00909 ei->ved_p->magic_p, ei->eu_p->vu_p, ei->eu_p->eumate_p->vu_p );
00910 }
00911 }
00912 }
00913
00914
00915
00916
00917
00918 static void
00919 pl_pt_lu(struct fpi *fpi, const struct loopuse *lu, struct edge_info *ei)
00920 {
00921 FILE *fd;
00922 char name[25];
00923 long *b;
00924 static int plot_file_number=0;
00925 int i;
00926 point_t p1, p2;
00927 point_t pca;
00928 fastf_t dist;
00929 struct bn_tol tmp_tol;
00930
00931 NMG_CK_FPI(fpi);
00932 NMG_CK_FACEUSE(fpi->fu_p);
00933 NMG_CK_LOOPUSE(lu);
00934 NMG_CK_EI(ei);
00935
00936 sprintf(name, "pt_lu%02d.pl", plot_file_number++);
00937 if ((fd=fopen(name, "w")) == (FILE *)NULL) {
00938 perror(name);
00939 bu_bomb("unable to open file for writing");
00940 }
00941
00942 bu_log("\toverlay %s\n", name);
00943 b = (long *)bu_calloc( fpi->fu_p->s_p->r_p->m_p->maxindex,
00944 sizeof(long), "bit vec"),
00945
00946 pl_erase(fd);
00947 pd_3space(fd,
00948 fpi->fu_p->f_p->min_pt[0]-1.0,
00949 fpi->fu_p->f_p->min_pt[1]-1.0,
00950 fpi->fu_p->f_p->min_pt[2]-1.0,
00951 fpi->fu_p->f_p->max_pt[0]+1.0,
00952 fpi->fu_p->f_p->max_pt[1]+1.0,
00953 fpi->fu_p->f_p->max_pt[2]+1.0);
00954
00955 nmg_pl_lu(fd, lu, b, 255, 255, 255);
00956
00957 tmp_tol.magic = BN_TOL_MAGIC;
00958 tmp_tol.dist = 0.005;
00959 tmp_tol.dist_sq = tmp_tol.dist * tmp_tol.dist;
00960 tmp_tol.perp = 1e-6;
00961 tmp_tol.para = 1 - tmp_tol.perp;
00962
00963 (void)bn_dist_pt3_lseg3( &dist, pca, ei->eu_p->vu_p->v_p->vg_p->coord,
00964 ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord, fpi->pt, &tmp_tol );
00965
00966 pl_color(fd, 255, 255, 50);
00967 pdv_3line(fd, pca, fpi->pt);
00968
00969 pl_color(fd, 255, 64, 255);
00970
00971
00972 for (i=0 ; i < 3 ; i++) {
00973 VMOVE(p1, fpi->pt);
00974 p1[i] -= 1.0;
00975 VMOVE(p2, fpi->pt);
00976 p2[i] += 1.0;
00977 pdv_3line(fd, p1, p2);
00978 }
00979
00980 bu_free((char *)b, "bit vec");
00981 fclose(fd);
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 static int
00996 compute_loop_class(struct fpi *fpi,
00997 const struct loopuse *lu,
00998 struct edge_info *edge_list)
00999 {
01000 struct edge_info *ei;
01001 struct edge_info *ei_vdot_max;
01002 struct bu_list near1;
01003 int lu_class = NMG_CLASS_Unknown;
01004
01005 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01006 bu_log("compute_loop_class()\n");
01007 for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) {
01008 bu_log("dist:%g class:%s status:%d\n\tv1(%g %g %g) v2(%g %g %g)\n",
01009 ei->ved_p->dist, nmg_class_name(ei->class),
01010 ei->ved_p->status,
01011 V3ARGS(ei->ved_p->v1->vg_p->coord),
01012 V3ARGS(ei->ved_p->v2->vg_p->coord));
01013 }
01014 }
01015
01016 BU_CK_LIST_HEAD(&edge_list->l);
01017 BU_LIST_INIT(&near1);
01018
01019
01020
01021
01022 while (BU_LIST_IS_EMPTY(&near1) && BU_LIST_NON_EMPTY(&edge_list->l)) {
01023 make_near_list(edge_list, &near1);
01024 }
01025
01026 if (BU_LIST_IS_EMPTY(&near1)) {
01027
01028
01029 if (lu->orientation == OT_SAME) {
01030 lu_class = NMG_CLASS_AoutB;
01031 } else if (lu->orientation == OT_OPPOSITE) {
01032 lu_class = NMG_CLASS_AinB;
01033 } else
01034 rt_bomb("bad lu orientation\n");
01035
01036 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01037 bu_log("list was empty, so class is %s\n",
01038 nmg_class_name(lu_class));
01039 }
01040 goto departure;
01041 }
01042
01043
01044 ei_vdot_max = (struct edge_info *)NULL;
01045
01046 for (BU_LIST_FOR(ei, edge_info, &near1)) {
01047 NMG_CK_EI(ei);
01048 NMG_CK_VED(ei->ved_p);
01049 switch (ei->ved_p->status) {
01050 case 0:
01051 case 1:
01052 case 2:
01053 lu_class = NMG_CLASS_AonBshared;
01054 if (rt_g.NMG_debug & DEBUG_PT_FU )
01055 pl_pt_lu(fpi, lu, ei);
01056 goto departure;
01057 case 3:
01058 case 4:
01059 case 5:
01060 lu_class = ei->class;
01061 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01062 bu_log("found status 5 edge, loop class is %s\n",
01063 nmg_class_name(lu_class));
01064 }
01065 if (rt_g.NMG_debug & DEBUG_PT_FU )
01066 pl_pt_lu(fpi, lu, ei);
01067 goto departure;
01068 default:
01069 bu_log("%s:%d status = %d\n",
01070 __FILE__, __LINE__, ei->ved_p->status);
01071 rt_bomb("Why did this happen?");
01072 break;
01073 }
01074 }
01075 if (ei_vdot_max) {
01076 if (rt_g.NMG_debug & DEBUG_PT_FU)
01077 pl_pt_lu(fpi, lu, ei_vdot_max);
01078 } else {
01079 bu_log("%s:%d ei_vdot_max not set\n",
01080 __FILE__, __LINE__);
01081 rt_bomb("How does this happen?\n");
01082 }
01083 departure:
01084
01085
01086
01087
01088 while (BU_LIST_WHILE(ei, edge_info, &near1)) {
01089 BU_LIST_DEQUEUE( &ei->l );
01090 bu_free( (char *)ei, "edge_info struct");
01091 }
01092
01093 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01094 bu_log("compute_loop_class() returns %s\n",
01095 nmg_class_name(lu_class));
01096 }
01097
01098 return lu_class;
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 static int
01138 nmg_class_pt_lu(struct loopuse *lu, struct fpi *fpi, const int in_or_out_only)
01139 {
01140 int lu_class = NMG_CLASS_Unknown;
01141
01142 NMG_CK_FPI(fpi);
01143 NMG_CK_LOOPUSE(lu);
01144 NMG_CK_LOOP(lu->l_p);
01145 NMG_CK_LOOP_G(lu->l_p->lg_p);
01146
01147
01148 if (!V3PT_IN_RPP( fpi->pt, lu->l_p->lg_p->min_pt, lu->l_p->lg_p->max_pt)) {
01149
01150
01151 if (rt_g.NMG_debug & DEBUG_PT_FU )
01152 {
01153 bu_log("nmg_class_pt_lu( pt(%g %g %g) outside loop RPP\n",
01154 V3ARGS(fpi->pt));
01155 bu_log( " lu RPP: ( %g %g %g ) <-> ( %g %g %g )\n",
01156 V3ARGS(lu->l_p->lg_p->min_pt), V3ARGS( lu->l_p->lg_p->max_pt) );
01157 }
01158
01159 if (lu->orientation == OT_SAME)
01160 return NMG_CLASS_AoutB;
01161 else if (lu->orientation == OT_OPPOSITE)
01162 return NMG_CLASS_AinB;
01163 else if (lu->orientation == OT_UNSPEC)
01164 return NMG_CLASS_Unknown;
01165
01166 }
01167
01168 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
01169 register struct edgeuse *eu;
01170 struct edge_info edge_list;
01171 struct edge_info *ei;
01172 int is_crack;
01173
01174 is_crack = nmg_loop_is_a_crack(lu);
01175 if( lu->orientation == OT_OPPOSITE && is_crack ) {
01176
01177
01178
01179
01180 lu_class = NMG_CLASS_AinB;
01181 if (rt_g.NMG_debug & DEBUG_PT_FU )
01182 bu_log("nmg_class_pt_lu() ignoring OT_OPPOSITE crack loop\n");
01183 goto out;
01184 }
01185
01186 BU_LIST_INIT(&edge_list.l);
01187
01188 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
01189 ei = nmg_class_pt_eu(fpi, eu, &edge_list, in_or_out_only);
01190 NMG_CK_EI(ei);
01191 NMG_CK_VED(ei->ved_p);
01192 if ( !in_or_out_only && ei->ved_p->dist < fpi->tol->dist_sq) {
01193 lu_class = NMG_CLASS_AinB;
01194 break;
01195 }
01196 }
01197
01198 if (lu_class == NMG_CLASS_Unknown) {
01199
01200 if( is_crack ) {
01201
01202 lu_class = NMG_CLASS_AoutB;
01203 } else {
01204 lu_class = compute_loop_class(fpi, lu, &edge_list);
01205 }
01206 } else {
01207
01208 if (rt_g.NMG_debug & DEBUG_PT_FU )
01209 bu_log("loop class already known (pt must touch edge)\n");
01210 }
01211
01212
01213 while ( BU_LIST_WHILE(ei, edge_info, &edge_list.l) ) {
01214 BU_LIST_DEQUEUE( &ei->l );
01215 bu_free( (char *)ei, "edge info struct");
01216 }
01217 } else if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
01218 register struct vertexuse *vu;
01219 int v_class;
01220
01221 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01222 v_class = nmg_class_pt_vu(fpi, vu);
01223
01224 switch (lu->orientation) {
01225 case OT_BOOLPLACE:
01226 case OT_SAME:
01227 if (v_class == NMG_FPI_TOUCHED)
01228 lu_class = NMG_CLASS_AinB;
01229 else
01230 lu_class = NMG_CLASS_AoutB;
01231 break;
01232 case OT_OPPOSITE:
01233
01234 lu_class = NMG_CLASS_AinB;
01235 break;
01236 case OT_UNSPEC:
01237 lu_class = NMG_CLASS_Unknown;
01238 break;
01239 default:
01240 bu_log("nmg_class_pt_lu() hit %s loop at vu=x%x\n",
01241 nmg_orientation(lu->orientation), vu);
01242 rt_bomb("nmg_class_pt_lu() Loop orientation error\n");
01243 break;
01244 }
01245 } else {
01246 bu_log("%s:%d bad child of loopuse\n", __FILE__, __LINE__);
01247 rt_bomb("nmg_class_pt_lu() crash and burn\n");
01248 }
01249
01250
01251 out:
01252 if (rt_g.NMG_debug & DEBUG_PT_FU )
01253 bu_log("nmg_class_pt_lu() pt classed %s vs loop\n", nmg_class_name(lu_class));
01254
01255 return lu_class;
01256 }
01257
01258
01259 static void
01260 plot_parity_error(const struct faceuse *fu, const fastf_t *pt)
01261 {
01262 long *b;
01263 FILE *fp;
01264 point_t p1, p2;
01265 int i;
01266
01267 NMG_CK_FACEUSE(fu);
01268
01269 if (!(fp=fopen("pt_fu_parity_error.pl", "w")) )
01270 rt_bomb("error opening pt_fu_parity_error.pl\n");
01271
01272
01273 bu_log("overlay pt_fu_parity_error.pl\n");
01274
01275 b = (long *)bu_calloc( fu->s_p->r_p->m_p->maxindex,
01276 sizeof(long), "bit vec"),
01277
01278
01279 pl_erase(fp);
01280 pd_3space(fp,
01281 fu->f_p->min_pt[0]-1.0,
01282 fu->f_p->min_pt[1]-1.0,
01283 fu->f_p->min_pt[2]-1.0,
01284 fu->f_p->max_pt[0]+1.0,
01285 fu->f_p->max_pt[1]+1.0,
01286 fu->f_p->max_pt[2]+1.0);
01287
01288 nmg_pl_fu(fp, fu, b, 200, 200, 200);
01289
01290
01291
01292 for (i=0 ; i < 3 ; i++) {
01293 VMOVE(p1, pt);
01294 p1[i] -= 1.0;
01295 VMOVE(p2, pt);
01296 p2[i] += 1.0;
01297 pdv_3line(fp, p1, p2);
01298 }
01299
01300 bu_free((char *)b, "plot table");
01301 fclose(fp);
01302
01303 }
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 int
01336 nmg_class_pt_fu_except(const fastf_t *pt, const struct faceuse *fu, const struct loopuse *ignore_lu, void (*eu_func) (), void (*vu_func) (), const char *priv, const int call_on_hits, const int in_or_out_only, const struct bn_tol *tol)
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 {
01347 struct fpi fpi;
01348 struct loopuse *lu;
01349 int ot_same_in = 0;
01350 int ot_opposite_out = 0;
01351 int ot_same[4];
01352 int ot_opposite[4];
01353 int lu_class;
01354 int fu_class = NMG_CLASS_Unknown;
01355 double dist;
01356 struct ve_dist *ved_p;
01357 int i;
01358
01359 if (rt_g.NMG_debug & DEBUG_PT_FU )
01360 bu_log("nmg_class_pt_fu_except( pt=(%g %g %g), fu=x%x )\n", V3ARGS(pt), fu);
01361
01362 if(fu->orientation != OT_SAME) rt_bomb("nmg_class_pt_fu_except() not OT_SAME\n");
01363
01364 NMG_CK_FACEUSE(fu);
01365 NMG_CK_FACE(fu->f_p);
01366 NMG_CK_FACE_G_PLANE(fu->f_p->g.plane_p);
01367 if(ignore_lu) NMG_CK_LOOPUSE(ignore_lu);
01368 BN_CK_TOL(tol);
01369
01370
01371 NMG_GET_FU_PLANE( fpi.norm, fu );
01372 if( (dist=fabs(DIST_PT_PLANE( pt, fpi.norm ))) > tol->dist ) {
01373 bu_log("nmg_class_pt_fu_except() ERROR, point (%g,%g,%g)\nnot on face %g %g %g %g,\ndist=%g\n",
01374 V3ARGS(pt), V4ARGS(fpi.norm), dist );
01375 }
01376
01377 if( !V3PT_IN_RPP( pt, fu->f_p->min_pt, fu->f_p->max_pt ) ) {
01378
01379
01380
01381 if (rt_g.NMG_debug & DEBUG_PT_FU )
01382 bu_log("nmg_class_pt_fu_except( (%g %g %g) ouside face RPP\n",
01383 V3ARGS(pt));
01384
01385 return NMG_CLASS_AoutB;
01386 }
01387
01388 for( i=0; i<4; i++ ) {
01389 ot_same[i] = ot_opposite[i] = 0;
01390 }
01391
01392 fpi.fu_p = fu;
01393 fpi.tol = tol;
01394 BU_LIST_INIT(&fpi.ve_dh);
01395 VMOVE(fpi.pt, pt);
01396 fpi.eu_func = eu_func;
01397 fpi.vu_func = vu_func;
01398 fpi.priv = priv;
01399 fpi.hits = call_on_hits;
01400 fpi.magic = NMG_FPI_MAGIC;
01401
01402 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
01403 if( ignore_lu && (ignore_lu==lu || ignore_lu==lu->lumate_p) )
01404 continue;
01405
01406
01407 if( lu->orientation != OT_SAME && lu->orientation != OT_OPPOSITE )
01408 continue;
01409
01410 lu_class = nmg_class_pt_lu(lu, &fpi, in_or_out_only);
01411 if (rt_g.NMG_debug & DEBUG_PT_FU )
01412 bu_log("loop %s says pt is %s\n",
01413 nmg_orientation(lu->orientation),
01414 nmg_class_name(lu_class) );
01415
01416 if( lu_class < 0 || lu_class > 3 ) {
01417 bu_log("nmg_class_pt_fu_except() lu_class=%s %d\n",
01418 nmg_class_name(lu_class), lu_class);
01419 rt_bomb("nmg_class_pt_fu_except() bad lu_class\n");
01420 }
01421
01422 if (lu->orientation == OT_OPPOSITE) {
01423 ot_opposite[lu_class]++;
01424 if( lu_class == NMG_CLASS_AoutB )
01425 ot_opposite_out++;
01426 } else if (lu->orientation == OT_SAME ) {
01427 ot_same[lu_class]++;
01428 if (lu_class == NMG_CLASS_AinB ||
01429 lu_class == NMG_CLASS_AonBshared)
01430 ot_same_in++;
01431 }
01432 }
01433
01434 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01435 bu_log("loops ot_same_in:%d ot_opposite_out:%d\n",
01436 ot_same_in, ot_opposite_out);
01437 bu_log("loops in/onS/onA/out ot_same=%d/%d/%d/%d ot_opp=%d/%d/%d/%d\n",
01438 ot_same[0], ot_same[1], ot_same[2], ot_same[3],
01439 ot_opposite[0], ot_opposite[1], ot_opposite[2], ot_opposite[3] );
01440 }
01441
01442 if (ot_same_in == ot_opposite_out) {
01443
01444 fu_class = NMG_CLASS_AoutB;
01445 } else if (ot_same_in > ot_opposite_out) {
01446
01447 fu_class = NMG_CLASS_AinB;
01448 } else {
01449
01450 bu_log("loops in/onS/onA/out ot_same=%d/%d/%d/%d ot_opp=%d/%d/%d/%d\n",
01451 ot_same[0], ot_same[1], ot_same[2], ot_same[3],
01452 ot_opposite[0], ot_opposite[1], ot_opposite[2], ot_opposite[3] );
01453 bu_log("nmg_class_pt_fu_except(%g %g %g)\nParity error @ %s:%d ot_same_in:%d ot_opposite_out:%d\n",
01454 V3ARGS(pt), __FILE__, __LINE__,
01455 ot_same_in, ot_opposite_out);
01456 bu_log( "fu=x%x\n", fu );
01457 nmg_pr_fu_briefly( fu, "" );
01458
01459 plot_parity_error(fu, pt);
01460
01461 #if 0
01462
01463 rt_g.NMG_debug |= DEBUG_PT_FU;
01464 for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
01465 if( ignore_lu && (ignore_lu==lu || ignore_lu==lu->lumate_p) )
01466 continue;
01467
01468
01469 if( lu->orientation != OT_SAME && lu->orientation != OT_OPPOSITE )
01470 continue;
01471
01472 lu_class = nmg_class_pt_lu(lu, &fpi, in_or_out_only);
01473 }
01474 #endif
01475 rt_bomb("nmg_class_pt_fu_except() loop classification parity error\n");
01476 }
01477
01478 while (BU_LIST_WHILE(ved_p, ve_dist, &fpi.ve_dh)) {
01479 BU_LIST_DEQUEUE( &ved_p->l );
01480 bu_free( (char *)ved_p, "ve_dist struct");
01481 }
01482
01483
01484 if (rt_g.NMG_debug & DEBUG_PT_FU )
01485 bu_log("nmg_class_pt_fu_except() returns %s\n",
01486 nmg_class_name(fu_class));
01487
01488 return fu_class;
01489 }
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501 int
01502 nmg_class_pt_lu_except(fastf_t *pt, const struct loopuse *lu, const struct edge *e_p, const struct bn_tol *tol)
01503 {
01504 register struct edgeuse *eu;
01505 struct edge_info edge_list;
01506 struct edge_info *ei;
01507 struct fpi fpi;
01508 int lu_class = NMG_CLASS_Unknown;
01509 struct ve_dist *ved_p;
01510 double dist;
01511
01512 if (rt_g.NMG_debug & DEBUG_PT_FU ) {
01513 bu_log("nmg_class_pt_lu_except( (%g %g %g) ", V3ARGS(pt), e_p);
01514 if (e_p)
01515 bu_log(" e_p=(%g %g %g) <-> (%g %g %g) )\n",
01516 V3ARGS(e_p->eu_p->vu_p->v_p->vg_p->coord),
01517 V3ARGS(e_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord) );
01518 else
01519 bu_log(" e_p=(NULL) )\n");
01520 }
01521
01522 NMG_CK_LOOPUSE(lu);
01523
01524 if (e_p) NMG_CK_EDGE(e_p);
01525
01526 NMG_CK_FACEUSE(lu->up.fu_p);
01527
01528
01529 NMG_GET_FU_PLANE( fpi.norm, lu->up.fu_p );
01530 if( (dist=fabs(DIST_PT_PLANE( pt, fpi.norm ))) > tol->dist ) {
01531 bu_log("nmg_class_pt_lu_except() ERROR, point (%g,%g,%g)\nnot on face %g %g %g %g,\ndist=%g\n",
01532 V3ARGS(pt), V4ARGS(fpi.norm), dist );
01533 }
01534
01535
01536 if (!V3PT_IN_RPP( pt, lu->l_p->lg_p->min_pt, lu->l_p->lg_p->max_pt)) {
01537
01538
01539 if (rt_g.NMG_debug & DEBUG_PT_FU )
01540 bu_log("nmg_class_pt_lu_except( pt(%g %g %g) outside loop RPP\n",
01541 V3ARGS(pt));
01542
01543 if (lu->orientation == OT_SAME) return NMG_CLASS_AoutB;
01544 else if (lu->orientation == OT_OPPOSITE) return NMG_CLASS_AinB;
01545 else {
01546 bu_log("What kind of loop is this anyway? %s?\n",
01547 nmg_orientation(lu->orientation) );
01548 rt_bomb("");
01549 }
01550 }
01551
01552 if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC) {
01553 bu_log("%s:%d Improper use of nmg_class_pt_lu_except(pt(%g %g %g), vu)\n",
01554 __FILE__, __LINE__, V3ARGS(pt));
01555 rt_bomb("giving up\n");
01556 }
01557
01558 BU_LIST_INIT(&edge_list.l);
01559 fpi.fu_p = lu->up.fu_p;
01560
01561 fpi.tol = tol;
01562 BU_LIST_INIT(&fpi.ve_dh);
01563 VMOVE(fpi.pt, pt);
01564 fpi.eu_func = (void (*)())NULL;
01565 fpi.vu_func = (void (*)())NULL;
01566 fpi.priv = (char *)NULL;
01567 fpi.hits = 0;
01568 fpi.magic = NMG_FPI_MAGIC;
01569
01570 for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
01571 if (eu->e_p == e_p) {
01572 if (rt_g.NMG_debug & DEBUG_PT_FU )
01573 bu_log("skipping edguse (%g %g %g) -> (%g %g %g) on \"except\" edge\n",
01574 V3ARGS(eu->vu_p->v_p->vg_p->coord),
01575 V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord) );
01576
01577 continue;
01578 }
01579
01580 ei = nmg_class_pt_eu(&fpi, eu, &edge_list, 0);
01581 NMG_CK_EI(ei);
01582 NMG_CK_VED(ei->ved_p);
01583 if (ei->ved_p->dist < tol->dist_sq) {
01584 lu_class = NMG_CLASS_AonBshared;
01585 break;
01586 }
01587 }
01588 if (lu_class == NMG_CLASS_Unknown)
01589 lu_class = compute_loop_class(&fpi, lu, &edge_list);
01590 else if (rt_g.NMG_debug & DEBUG_PT_FU )
01591 bu_log("loop class already known (pt must touch edge)\n");
01592
01593
01594 while ( BU_LIST_WHILE(ei, edge_info, &edge_list.l) ) {
01595 BU_LIST_DEQUEUE( &ei->l );
01596 bu_free( (char *)ei, "edge info struct");
01597 }
01598
01599 while (BU_LIST_WHILE(ved_p, ve_dist, &fpi.ve_dh)) {
01600 BU_LIST_DEQUEUE( &ved_p->l );
01601 bu_free( (char *)ved_p, "ve_dist struct");
01602 }
01603
01604 if (rt_g.NMG_debug & DEBUG_PT_FU )
01605 bu_log("nmg_class_pt_lu_except() returns %s\n",
01606 nmg_class_name(lu_class));
01607
01608 return lu_class;
01609 }
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619