00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef lint
00042 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nmg_misc.c,v 14.15 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00043 #endif
00044
00045 #include "common.h"
00046
00047
00048 #include <math.h>
00049 #include <stdio.h>
00050 #ifdef HAVE_STRING_H
00051 #include <string.h>
00052 #else
00053 #include <strings.h>
00054 #endif
00055 #include "machine.h"
00056 #include "vmath.h"
00057 #include "nmg.h"
00058 #include "raytrace.h"
00059 #include "nurb.h"
00060 #include "rtgeom.h"
00061
00062 #include "db.h"
00063
00064
00065
00066
00067 int
00068 nmg_snurb_calc_lu_uv_orient(const struct loopuse *lu)
00069 {
00070 struct edgeuse *eu;
00071 int edge_count=0;
00072 int edge_no;
00073 vect_t area;
00074 point_t *pts;
00075
00076 NMG_CK_LOOPUSE( lu );
00077
00078 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00079 rt_bomb( "nmg_snurb_calc_lu_uv_orient: LU has no edges\n" );
00080
00081 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
00082 rt_bomb( "nmg_snurb_calc_lu_uv_orient: LU is not part of a faceuse\n" );
00083
00084 NMG_CK_FACEUSE( lu->up.fu_p );
00085 NMG_CK_FACE( lu->up.fu_p->f_p );
00086
00087 if( *lu->up.fu_p->f_p->g.magic_p != NMG_FACE_G_SNURB_MAGIC )
00088 rt_bomb( "nmg_snurb_calc_lu_uv_orient: LU is not part of a SNURB face\n" );
00089
00090
00091 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
00092 {
00093 struct edge_g_cnurb *eg;
00094
00095 NMG_CK_EDGEUSE( eu );
00096
00097 if( *eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC )
00098 rt_bomb( "nmg_snurb_calc_lu_uv_orient: EU on NURB face does not have edge_g_cnurb geometry\n" );
00099
00100 eg = eu->g.cnurb_p;
00101 NMG_CK_EDGE_G_CNURB( eg );
00102
00103 if( eg->order <= 0 )
00104 edge_count++;
00105 else
00106 edge_count += 5;
00107 }
00108
00109
00110 pts = (point_t *)bu_calloc( edge_count, sizeof( point_t ), "Orient_nurb_face_loops: pts" );
00111
00112
00113 edge_no = 0;
00114 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
00115 {
00116 struct edge_g_cnurb *eg;
00117 struct vertexuse *vu;
00118 struct vertexuse_a_cnurb *vg1;
00119
00120 eg = eu->g.cnurb_p;
00121
00122 if( eg->order <= 0 )
00123 {
00124 vu = eu->vu_p;
00125 NMG_CK_VERTEXUSE( vu );
00126 if( *vu->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
00127 rt_bomb( "Orient_nurb_face_loops: vertexuse in face_g_snurb faceuse doesn't have edge_g_cnurb attribute\n" );
00128 vg1 = vu->a.cnurb_p;
00129 VMOVE( pts[edge_no], vg1->param )
00130 edge_no++;
00131 }
00132 else
00133 {
00134 fastf_t t1,t2;
00135 hpoint_t crv_pt;
00136 int coords;
00137 int i;
00138
00139 t1 = eg->k.knots[0];
00140 t2 = eg->k.knots[eg->k.k_size-1];
00141 coords = RT_NURB_EXTRACT_COORDS( eg->pt_type );
00142
00143 for( i=0 ; i<5 ; i++ )
00144 {
00145 fastf_t t;
00146
00147 t = t1 + (t2 - t1)*0.2*(fastf_t)i;
00148
00149 VSETALLN( crv_pt, 0.0, coords )
00150 rt_nurb_c_eval( eg, t, crv_pt );
00151 if( RT_NURB_IS_PT_RATIONAL( eg->pt_type ) )
00152 VSCALE( pts[edge_no], crv_pt, crv_pt[coords-1] )
00153 else
00154 VMOVE( pts[edge_no], crv_pt )
00155 edge_no++;
00156 }
00157 }
00158 }
00159
00160
00161 for( edge_no=1 ; edge_no<edge_count ; edge_no++ )
00162 {
00163 VSUB2( pts[edge_no], pts[edge_no], pts[0] )
00164 pts[edge_no][Z] = 0.0;
00165 }
00166 VSETALL( pts[0], 0.0 )
00167
00168
00169 VSETALL( area, 0.0 );
00170 for( edge_no=1 ; edge_no<edge_count-1 ; edge_no++ )
00171 {
00172 vect_t cross;
00173
00174 VCROSS( cross, pts[edge_no], pts[edge_no+1] );
00175 VADD2( area, area, cross );
00176 }
00177
00178 bu_free( (char *)pts, "nmg_snurb_calc_lu_uv_orient: pts" );
00179
00180 if( area[Z] > 0.0 )
00181 return( OT_SAME );
00182 if( area[Z] < 0.0 )
00183 return( OT_OPPOSITE );
00184
00185 return( OT_NONE );
00186 }
00187
00188 void
00189 nmg_snurb_fu_eval(const struct faceuse *fu, const fastf_t u, const fastf_t v, fastf_t *pt_on_srf)
00190 {
00191 struct face *f;
00192 hpoint_t tmp_pt;
00193
00194 NMG_CK_FACEUSE( fu );
00195
00196 f = fu->f_p;
00197 NMG_CK_FACE( f );
00198 if( !f->g.magic_p )
00199 {
00200 bu_log( "nmg_snurb_fu_get_norm: face has no geometry (x%x)\n", f );
00201 rt_bomb( "nmg_snurb_fu_get_norm: bad face\n" );
00202 }
00203 if( *f->g.magic_p != NMG_FACE_G_SNURB_MAGIC )
00204 {
00205 bu_log( "nmg_snurb_fu_get_norm: face is not a NURB face (x%x)\n", f );
00206 rt_bomb( "nmg_snurb_fu_get_norm: bad face\n" );
00207 }
00208
00209 VSETALLN( tmp_pt, 0.0, 4 );
00210 rt_nurb_s_eval( f->g.snurb_p, u, v, tmp_pt );
00211
00212 if( RT_NURB_IS_PT_RATIONAL(f->g.snurb_p->pt_type) )
00213 {
00214 double f;
00215
00216 f = 1.0 / tmp_pt[3];
00217 VSCALE( pt_on_srf, tmp_pt, f );
00218 }
00219 else
00220 VMOVE( pt_on_srf, tmp_pt )
00221 }
00222
00223 void
00224 nmg_snurb_fu_get_norm(const struct faceuse *fu, const fastf_t u, const fastf_t v, fastf_t *norm)
00225 {
00226 struct face *f;
00227
00228 NMG_CK_FACEUSE( fu );
00229
00230 f = fu->f_p;
00231 NMG_CK_FACE( f );
00232 if( !f->g.magic_p )
00233 {
00234 bu_log( "nmg_snurb_fu_get_norm: face has no geometry (x%x)\n", f );
00235 rt_bomb( "nmg_snurb_fu_get_norm: bad face\n" );
00236 }
00237 if( *f->g.magic_p != NMG_FACE_G_SNURB_MAGIC )
00238 {
00239 bu_log( "nmg_snurb_fu_get_norm: face is not a NURB face (x%x)\n", f );
00240 rt_bomb( "nmg_snurb_fu_get_norm: bad face\n" );
00241 }
00242
00243 rt_nurb_s_norm( f->g.snurb_p, u, v, norm );
00244
00245 if( (fu->orientation != OT_SAME) != (f->flip != 0 ) )
00246 VREVERSE( norm, norm )
00247 }
00248
00249 void
00250 nmg_snurb_fu_get_norm_at_vu(const struct faceuse *fu, const struct vertexuse *vu, fastf_t *norm)
00251 {
00252 struct vertexuse_a_cnurb *va;
00253
00254 NMG_CK_FACEUSE( fu );
00255 NMG_CK_VERTEXUSE( vu );
00256
00257 if( !vu->a.magic_p )
00258 {
00259 bu_log( "nmg_snurb_fu_get_norm_at_vu: vertexuse does not have an attribute (x%x)\n", vu );
00260 rt_bomb( "nmg_snurb_fu_get_norm_at_vu: bad VU\n" );
00261 }
00262
00263 if( *vu->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
00264 {
00265 bu_log( "nmg_snurb_fu_get_norm_at_vu: vertexuse does not have a cnurb attribute (x%x)\n", vu );
00266 rt_bomb( "nmg_snurb_fu_get_norm_at_vu: bad VU\n" );
00267 }
00268
00269 va = vu->a.cnurb_p;
00270 NMG_CK_VERTEXUSE_A_CNURB( va );
00271
00272 nmg_snurb_fu_get_norm( fu, va->param[0], va->param[1], norm );
00273
00274 }
00275
00276 void
00277 nmg_find_zero_length_edges(const struct model *m)
00278 {
00279 struct bu_ptbl eu_tab;
00280 struct edgeuse *eu;
00281 int i;
00282
00283 bu_ptbl_init( &eu_tab, 64, " &eu_tab");
00284
00285 nmg_edgeuse_tabulate( &eu_tab, &m->magic );
00286
00287 for( i=0 ; i<BU_PTBL_END( &eu_tab ) ; i++ )
00288 {
00289 struct loopuse *lu;
00290
00291 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tab, i );
00292 NMG_CK_EDGEUSE( eu );
00293
00294 if( eu->vu_p->v_p != eu->eumate_p->vu_p->v_p )
00295 continue;
00296
00297
00298
00299 bu_log( "Edgeuse x%x (vp %x to vp %x)\n" , eu, eu->vu_p->v_p, eu->eumate_p->vu_p->v_p );
00300 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC )
00301 {
00302 bu_log( "\tThis is a wire edge\n" );
00303 continue;
00304 }
00305
00306 lu = eu->up.lu_p;
00307
00308 nmg_pr_lu_briefly( lu, "" );
00309 }
00310
00311 bu_ptbl_free( &eu_tab);
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 struct face *
00325 nmg_find_top_face_in_dir(const struct shell *s, int dir, long int *flags)
00326 {
00327 fastf_t extreme_value=(-MAX_FASTF);
00328 fastf_t extreme_slope=(-MAX_FASTF);
00329 vect_t edge;
00330 vect_t normal;
00331 struct face *f_top=(struct face *)NULL;
00332 struct edge *e_top=(struct edge *)NULL;
00333 struct vertex *vp_top=(struct vertex *)NULL;
00334 struct loopuse *lu;
00335 struct faceuse *fu;
00336 struct edgeuse *eu,*eu1;
00337 struct vertexuse *vu;
00338 struct vertex *v1,*v2;
00339 int bottommost=0;
00340
00341 if( rt_g.NMG_debug & DEBUG_BASIC )
00342 bu_log( "nmg_find_top_face_in_dir( s = x%x , dir=%d , flags = x%x )\n" , s, dir , flags );
00343
00344 NMG_CK_SHELL( s );
00345
00346 if( dir < X || dir > Z )
00347 {
00348 bu_log( "nmg_find_top_face_in_dir: illegal direction: %d\n", dir );
00349 return( (struct face *)NULL );
00350 }
00351
00352 #if 0
00353 if( dir < 0 )
00354 {
00355 bottommost = 1;
00356 dir = (-dir);
00357 extreme_value = MAX_FASTF;
00358 extreme_slope = MAX_FASTF;
00359 }
00360 #endif
00361
00362 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
00363 {
00364 NMG_CK_FACEUSE( fu );
00365
00366
00367 if( NMG_INDEX_TEST( flags , fu->f_p ) )
00368 continue;
00369 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
00370 {
00371 NMG_CK_LOOPUSE( lu );
00372 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_EDGEUSE_MAGIC )
00373 {
00374 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
00375 {
00376 NMG_CK_EDGEUSE( eu );
00377 if( bottommost )
00378 {
00379 if( eu->vu_p->v_p->vg_p->coord[dir] < extreme_value )
00380 {
00381 extreme_value = eu->vu_p->v_p->vg_p->coord[dir];
00382 vp_top = eu->vu_p->v_p;
00383 }
00384 }
00385 else
00386 {
00387 if( eu->vu_p->v_p->vg_p->coord[dir] > extreme_value )
00388 {
00389 extreme_value = eu->vu_p->v_p->vg_p->coord[dir];
00390 vp_top = eu->vu_p->v_p;
00391 }
00392 }
00393 }
00394 }
00395 }
00396 }
00397 if( vp_top == (struct vertex *)NULL )
00398 {
00399 bu_log( "Find_top_face_in_dir: Could not find extreme vertex" );
00400 return( (struct face *)NULL );
00401 }
00402
00403 if( rt_g.NMG_debug & DEBUG_BASIC )
00404 bu_log( "top vertex is x%x at ( %g %g %g )\n",
00405 vp_top, V3ARGS( vp_top->vg_p->coord ) );
00406
00407
00408 for( BU_LIST_FOR( vu , vertexuse , &vp_top->vu_hd ) )
00409 {
00410 struct vertexuse *vu1;
00411
00412 NMG_CK_VERTEXUSE( vu );
00413
00414
00415 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
00416 continue;
00417
00418 eu = vu->up.eu_p;
00419 NMG_CK_EDGEUSE( eu );
00420
00421 if( rt_g.NMG_debug & DEBUG_BASIC )
00422 {
00423 bu_log( "Checking edge (%g %g %g)<->(%g %g %g)\n",
00424 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
00425 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
00426 }
00427
00428
00429 if( *eu->up.magic_p != NMG_LOOPUSE_MAGIC )
00430 continue;
00431
00432
00433 if( *eu->up.lu_p->up.magic_p != NMG_FACEUSE_MAGIC )
00434 continue;
00435
00436
00437 if( NMG_INDEX_TEST( flags , eu->up.lu_p->up.fu_p->f_p ) )
00438 continue;
00439
00440
00441 if( nmg_find_s_of_eu( eu ) != s )
00442 continue;
00443
00444
00445 if( eu->eumate_p->vu_p->v_p == vp_top )
00446 continue;
00447
00448
00449 vu1 = eu->eumate_p->vu_p;
00450 NMG_CK_VERTEXUSE( vu1 );
00451
00452
00453 VSUB2( edge , vu1->v_p->vg_p->coord , vu->v_p->vg_p->coord );
00454 VUNITIZE( edge );
00455
00456 if( rt_g.NMG_debug & DEBUG_BASIC )
00457 {
00458 bu_log( "Checking edge (%g %g %g)<->(%g %g %g)\n",
00459 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
00460 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
00461 bu_log( "\tedge direction = (%g %g %g)\n", V3ARGS( edge ) );
00462 bu_log( "\t\textreme slope = %g\n", extreme_slope );
00463 }
00464
00465
00466 if( bottommost )
00467 {
00468 if( edge[dir] < extreme_slope )
00469 {
00470 extreme_slope = edge[dir];
00471 e_top = eu->e_p;
00472 }
00473 }
00474 else
00475 {
00476 if( edge[dir] > extreme_slope )
00477 {
00478 if( rt_g.NMG_debug & DEBUG_BASIC )
00479 bu_log( "New top edge!\n" );
00480 extreme_slope = edge[dir];
00481 e_top = eu->e_p;
00482 }
00483 }
00484 }
00485 if( e_top == (struct edge *)NULL )
00486 {
00487 bu_log( "Fix_normals: Could not find uppermost edge" );
00488 return( (struct face *)NULL );
00489 }
00490
00491 eu = e_top->eu_p;
00492
00493 #if 0
00494
00495 if( eu->eumate_p == eu->radial_p )
00496 return( (struct face *)NULL );
00497 #endif
00498 v1 = eu->vu_p->v_p;
00499 NMG_CK_VERTEX( v1 );
00500 v2 = eu->eumate_p->vu_p->v_p;
00501 NMG_CK_VERTEX( v2 );
00502
00503 if( rt_g.NMG_debug & DEBUG_BASIC )
00504 bu_log( "top EU is x%x (%g %g %g) <-> (%g %g %g)\n",
00505 eu, V3ARGS( v1->vg_p->coord ),
00506 V3ARGS( v2->vg_p->coord ) );
00507
00508
00509
00510 if( bottommost )
00511 extreme_slope = MAX_FASTF;
00512 else
00513 extreme_slope = (-MAX_FASTF);
00514
00515 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
00516 {
00517 vect_t left;
00518 vect_t edge_dir;
00519
00520 NMG_CK_VERTEXUSE( vu );
00521 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
00522 continue;
00523
00524 eu1 = vu->up.eu_p;
00525 NMG_CK_EDGEUSE( eu1 );
00526
00527
00528 if( *eu1->up.magic_p != NMG_LOOPUSE_MAGIC )
00529 continue;
00530
00531
00532 if( eu1->eumate_p->vu_p->v_p != v2 )
00533 continue;
00534
00535 lu = eu1->up.lu_p;
00536 NMG_CK_LOOPUSE( lu );
00537 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
00538 continue;
00539
00540
00541 fu = lu->up.fu_p;
00542 NMG_CK_FACEUSE( fu );
00543
00544
00545 if( fu->s_p != s || NMG_INDEX_TEST( flags, fu->f_p ) )
00546 continue;
00547
00548
00549 if( rt_g.NMG_debug & DEBUG_BASIC )
00550 bu_log( "test EU is x%x (%g %g %g) <-> (%g %g %g)\n",
00551 eu, V3ARGS( eu->vu_p->v_p->vg_p->coord ),
00552 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
00553
00554 VSUB2( edge_dir , eu1->eumate_p->vu_p->v_p->vg_p->coord , eu1->vu_p->v_p->vg_p->coord );
00555
00556 if( rt_g.NMG_debug & DEBUG_BASIC )
00557 bu_log( "edge_dir is ( %g %g %g )\n", V3ARGS( edge_dir ) );
00558
00559
00560 if( *fu->f_p->g.magic_p == NMG_FACE_G_PLANE_MAGIC )
00561 NMG_GET_FU_NORMAL( normal, fu )
00562 else if( *fu->f_p->g.magic_p == NMG_FACE_G_SNURB_MAGIC )
00563 nmg_snurb_fu_get_norm_at_vu( fu, eu1->vu_p, normal );
00564
00565 if( rt_g.NMG_debug & DEBUG_BASIC )
00566 bu_log( "fu normal is ( %g %g %g )\n" , V3ARGS( normal ) );
00567
00568
00569 VCROSS( left , normal , edge_dir );
00570
00571
00572 VUNITIZE( left );
00573 if( rt_g.NMG_debug & DEBUG_BASIC )
00574 {
00575 bu_log( "left vector is ( %g %g %g )\n", V3ARGS( left ) );
00576 bu_log( "\textreme slope in %d direction is %g\n", dir, extreme_slope );
00577 }
00578
00579
00580 if( bottommost )
00581 {
00582 if( left[dir] < extreme_slope )
00583 {
00584 extreme_slope = left[dir];
00585 f_top = fu->f_p;
00586 }
00587 }
00588 else
00589 {
00590 if( left[dir] > extreme_slope )
00591 {
00592 if( rt_g.NMG_debug & DEBUG_BASIC )
00593 bu_log( "new f_top\n" );
00594 extreme_slope = left[dir];
00595 f_top = fu->f_p;
00596 }
00597 }
00598 }
00599
00600 if( f_top == (struct face *)NULL )
00601 {
00602 bu_log( "Nmg_find_top_face_in_dir: Could not find uppermost face" );
00603 return( (struct face *)NULL );
00604 }
00605
00606 if( rt_g.NMG_debug & DEBUG_BASIC )
00607 bu_log( "nmg_find_top_face_in_dir: top face = x%x, dir = %d, top vertex = x%x ( %g %g %g )\n",
00608 f_top, dir, vp_top, V3ARGS( vp_top->vg_p->coord ) );
00609
00610 return( f_top );
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 struct face *
00627 nmg_find_top_face(const struct shell *s, int *dir, long int *flags)
00628 {
00629 struct face *top_face;
00630
00631 for( *dir=X ; *dir<=Z ; (*dir)++ )
00632 if( (top_face=nmg_find_top_face_in_dir( s, *dir, flags )) != (struct face *)NULL )
00633 return( top_face );
00634
00635
00636 bu_log( "Nmg_find_top_face: Cannot find a top face\n" );
00637 *dir = (-32000);
00638 return( (struct face *)NULL );
00639
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 struct top_face
00654 {
00655 struct shell *s;
00656 struct face *f;
00657 int dir;
00658 vect_t normal;
00659 };
00660
00661 static void
00662 nmg_assoc_void_shells(const struct nmgregion *r, struct bu_ptbl *shells, const struct bn_tol *ttol)
00663 {
00664 struct shell *outer_shell,*void_s,*s;
00665 struct faceuse *fu;
00666 struct loopuse *lu;
00667 struct edgeuse *eu;
00668 long *flags;
00669 struct top_face *top_faces;
00670 int total_shells=0;
00671 int i;
00672 int dir;
00673
00674 NMG_CK_REGION( r );
00675 BU_CK_PTBL( shells );
00676 BN_CK_TOL( ttol );
00677
00678 outer_shell = (struct shell *)BU_PTBL_GET( shells , 0 );
00679 NMG_CK_SHELL( outer_shell );
00680
00681
00682 for( BU_LIST_FOR( s , shell , &r->s_hd ) )
00683 total_shells++;
00684
00685
00686 top_faces = (struct top_face *)bu_calloc( total_shells , sizeof( struct top_face ) , "nmg_assoc_void_shells: top_faces" );
00687
00688
00689 flags = (long *)bu_calloc( r->m_p->maxindex , sizeof( long ) , "nmg_find_outer_and_void_shells: flags" );
00690
00691 top_faces[0].s = outer_shell;
00692 top_faces[0].f = nmg_find_top_face( outer_shell, &dir , flags );
00693 top_faces[0].dir = dir;
00694 fu = top_faces[0].f->fu_p;
00695 if( fu->orientation != OT_SAME )
00696 fu = fu->fumate_p;
00697 NMG_GET_FU_NORMAL( top_faces[0].normal , fu );
00698
00699
00700 i = 0;
00701 for( BU_LIST_FOR( s , shell , &r->s_hd ) )
00702 {
00703 if( s == outer_shell )
00704 continue;
00705
00706 top_faces[++i].s = s;
00707 top_faces[i].f = nmg_find_top_face( s, &dir , flags );
00708 top_faces[i].dir = dir;
00709 if( top_faces[i].f == (struct face *)NULL )
00710 bu_log( "WARNING: nmg_assoc_void_shells() could not find top face for shell x%x\n", s );
00711 else
00712 {
00713 fu = top_faces[i].f->fu_p;
00714 if( fu->orientation != OT_SAME )
00715 fu = fu->fumate_p;
00716 NMG_GET_FU_NORMAL( top_faces[i].normal , fu );
00717 }
00718 }
00719
00720
00721 for( BU_LIST_FOR( void_s , shell , &r->s_hd ) )
00722 {
00723 struct face *void_f;
00724 int wrong_void=0;
00725 vect_t normal;
00726
00727 if( void_s == outer_shell )
00728 continue;
00729
00730 NMG_CK_SHELL( void_s );
00731
00732 void_f = (struct face *)NULL;
00733 for( i=0 ; i<total_shells ; i++ )
00734 {
00735 if( top_faces[i].s == void_s )
00736 {
00737 void_f = top_faces[i].f;
00738 dir = top_faces[i].dir;
00739 VMOVE( normal , top_faces[i].normal );
00740 break;
00741 }
00742 }
00743 if( void_f == (struct face *)NULL )
00744 rt_bomb( "nmg_assoc_void_shells: no top face for a shell\n" );
00745
00746 if( normal[dir] < 0.0)
00747 {
00748
00749 struct face *int_f;
00750 struct shell *test_s;
00751 int breakout=0;
00752 int not_in_this_shell=0;
00753
00754
00755
00756 if( !V3RPP1_IN_RPP2( void_s->sa_p->min_pt , void_s->sa_p->max_pt , outer_shell->sa_p->min_pt , outer_shell->sa_p->max_pt ) )
00757 {
00758 continue;
00759 }
00760
00761 for( BU_LIST_FOR( fu , faceuse , &void_s->fu_hd ) )
00762 {
00763 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
00764 {
00765 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00766 continue;
00767 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
00768 {
00769 int class;
00770
00771 class = nmg_class_pt_s( eu->vu_p->v_p->vg_p->coord , outer_shell, 0 , ttol );
00772
00773 if( class == NMG_CLASS_AoutB )
00774 {
00775 breakout = 1;
00776 not_in_this_shell = 1;
00777 break;
00778 }
00779 }
00780 if( breakout )
00781 break;
00782 }
00783 if( breakout )
00784 break;
00785 }
00786
00787 if( not_in_this_shell )
00788 continue;
00789
00790 int_f = (struct face *)NULL;
00791 for( i=0 ; i<total_shells ; i++ )
00792 {
00793 if( top_faces[i].s == void_s )
00794 {
00795 int_f = top_faces[i].f;
00796 break;
00797 }
00798 }
00799 if( int_f == (struct face *)NULL )
00800 rt_bomb( "nmg_assoc_void_shells: no top face for a shell\n" );
00801
00802
00803 for( BU_LIST_FOR( test_s , shell , &r->s_hd ) )
00804 {
00805 vect_t test_norm;
00806 struct face *test_f;
00807 int test_dir = 0;
00808
00809
00810 if( test_s == void_s || test_s == outer_shell )
00811 continue;
00812
00813
00814 test_f = (struct face *)NULL;
00815 for( i=0 ; i<total_shells ; i++ )
00816 {
00817 if( top_faces[i].s == test_s )
00818 {
00819 test_f = top_faces[i].f;
00820 test_dir = top_faces[i].dir;
00821 VMOVE( test_norm , top_faces[i].normal );
00822 break;
00823 }
00824 }
00825 if( test_f == (struct face *)NULL )
00826 rt_bomb( "nmg_assoc_void_shells: no top face for a shell\n" );
00827
00828
00829 if( test_norm[test_dir] < 0.0)
00830 continue;
00831
00832
00833 if( !V3RPP1_IN_RPP2( void_s->sa_p->min_pt , void_s->sa_p->max_pt , test_s->sa_p->min_pt , test_s->sa_p->max_pt ) )
00834 continue;
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 }
00847 if( wrong_void )
00848 {
00849 continue;
00850 }
00851
00852
00853
00854 bu_ptbl_ins( shells , (long *)void_s );
00855 }
00856 }
00857 bu_free( (char *)flags , "nmg_assoc_void_shells: flags" );
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 int
00870 nmg_find_outer_and_void_shells(struct nmgregion *r, struct bu_ptbl ***shells, const struct bn_tol *tol)
00871 {
00872 struct bu_ptbl *outer_shells;
00873 struct shell *s;
00874 int i;
00875 int total_shells=0;
00876 int outer_shell_count;
00877 int re_bound=0;
00878 int dir;
00879 long *flags;
00880
00881 NMG_CK_REGION( r );
00882 BN_CK_TOL( tol );
00883
00884
00885 outer_shells = (struct bu_ptbl *)bu_malloc( sizeof( struct bu_ptbl ) , "nmg_find_outer_and_void_shells: outer_shells" );
00886 bu_ptbl_init( outer_shells , 64, " outer_shells ");
00887 for (BU_LIST_FOR(s, shell, &r->s_hd))
00888 {
00889 NMG_CK_SHELL( s );
00890 bu_ptbl_ins( outer_shells , (long *)s );
00891 }
00892 for( i=0 ; i<BU_PTBL_END( outer_shells ) ; i++ )
00893 {
00894 s = (struct shell *)BU_PTBL_GET( outer_shells , i );
00895 if( nmg_decompose_shell( s , tol ) > 1 )
00896 re_bound = 1;
00897 }
00898 bu_ptbl_reset( outer_shells );
00899
00900 if( re_bound )
00901 nmg_region_a( r , tol );
00902
00903 for (BU_LIST_FOR(s, shell, &r->s_hd))
00904 total_shells++;
00905
00906 flags = (long *)bu_calloc( r->m_p->maxindex , sizeof( long ) , "nmg_find_outer_and_void_shells: flags" );
00907
00908 for( BU_LIST_FOR( s , shell , &r->s_hd ) )
00909 {
00910 struct face *f;
00911 struct faceuse *fu;
00912 vect_t normal;
00913
00914 f = (struct face *)NULL;
00915 for( dir = X ; dir <= Z ; dir++ ) {
00916 if( (f = nmg_find_top_face_in_dir( s, dir , flags )) == (struct face *)NULL )
00917 continue;
00918
00919 fu = f->fu_p;
00920 if( fu->orientation != OT_SAME )
00921 fu = fu->fumate_p;
00922 if( fu->orientation != OT_SAME )
00923 rt_bomb( "nmg_find_outer_and_void_shells: Neither faceuse nor mate have OT_SAME orient\n" );
00924
00925 NMG_GET_FU_NORMAL( normal , fu );
00926 if( normal[dir] >= 0.0) {
00927 bu_ptbl_ins( outer_shells , (long *)s );
00928 break;
00929 }
00930 }
00931
00932 if( f == (struct face *)NULL ) {
00933 bu_bomb( "nmg_find_outer_and_void_shells: cannot find top face in a shell\n" );
00934 }
00935 }
00936
00937
00938 outer_shell_count = BU_PTBL_END( outer_shells );
00939
00940 *shells = (struct bu_ptbl **)bu_calloc( BU_PTBL_END( outer_shells ) , sizeof( struct bu_ptbl *) ,
00941 "nmg_find_outer_and_void_shells: shells" );
00942 for( i=0 ; i<BU_PTBL_END( outer_shells ) ; i++ )
00943 {
00944 (*shells)[i] = (struct bu_ptbl *)bu_malloc( sizeof( struct bu_ptbl ) ,
00945 "nmg_find_outer_and_void_shells: shells[]" );
00946
00947 bu_ptbl_init( (*shells)[i] , 64, "(*shells)[i]");
00948 BU_CK_PTBL( (*shells)[i] );
00949 bu_ptbl_ins( (*shells)[i] , BU_PTBL_GET( outer_shells , i ) );
00950 if( outer_shell_count != total_shells )
00951 nmg_assoc_void_shells( r , (*shells)[i] , tol );
00952 }
00953
00954 bu_free( (char *)flags , "nmg_find_outer_and_void_shells: flags" );
00955 bu_ptbl_free( outer_shells );
00956 return( outer_shell_count );
00957 }
00958
00959
00960
00961
00962
00963
00964 int
00965 nmg_mark_edges_real(const long int *magic_p)
00966 {
00967 struct bu_ptbl edges;
00968 int i,count;
00969
00970 nmg_edge_tabulate( &edges , magic_p );
00971
00972 count = BU_PTBL_END( &edges );
00973 for( i=0 ; i<count ; i++ )
00974 {
00975 struct edge *e;
00976
00977 e = (struct edge *)BU_PTBL_GET( &edges , i );
00978 NMG_CK_EDGE( e );
00979
00980 e->is_real = 1;
00981 }
00982
00983 bu_ptbl_free( &edges );
00984
00985 return( count );
00986 }
00987
00988
00989
00990
00991
00992
00993 void
00994 nmg_tabulate_face_g_verts(struct bu_ptbl *tab, const struct face_g_plane *fg)
00995 {
00996 struct face *f;
00997
00998 NMG_CK_FACE_G_PLANE( fg );
00999
01000 bu_ptbl_init( tab, 64, " tab");
01001
01002
01003 for( BU_LIST_FOR( f , face , &fg->f_hd ) )
01004 {
01005 struct faceuse *fu;
01006 struct loopuse *lu;
01007
01008 NMG_CK_FACE( f );
01009
01010
01011 fu = f->fu_p;
01012 NMG_CK_FACEUSE( fu );
01013
01014
01015 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
01016 {
01017 NMG_CK_LOOPUSE( lu );
01018
01019
01020 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
01021 {
01022 struct vertexuse *vu;
01023 struct vertex *v;
01024
01025 vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
01026 NMG_CK_VERTEXUSE( vu );
01027 v = vu->v_p;
01028 NMG_CK_VERTEX( v );
01029
01030
01031 bu_ptbl_ins_unique( tab , (long *)v );
01032 }
01033 else
01034 {
01035 struct edgeuse *eu;
01036
01037
01038 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
01039 {
01040 struct vertexuse *vu;
01041 struct vertex *v;
01042
01043 NMG_CK_EDGEUSE( eu );
01044 vu = eu->vu_p;
01045 NMG_CK_VERTEXUSE( vu );
01046 v = vu->v_p;
01047 NMG_CK_VERTEX( v );
01048
01049
01050 bu_ptbl_ins_unique( tab , (long *)v );
01051 }
01052 }
01053 }
01054 }
01055 }
01056
01057
01058
01059
01060
01061
01062
01063 void
01064 nmg_isect_shell_self(struct shell *s, const struct bn_tol *tol)
01065 {
01066 struct model *m;
01067 struct nmgregion *r;
01068 struct shell *s_fu;
01069 struct faceuse *fu;
01070 struct bu_ptbl fus;
01071 int fu_no;
01072 int fu2_no;
01073
01074 NMG_CK_SHELL( s );
01075 BN_CK_TOL( tol );
01076
01077 m = nmg_find_model( &s->l.magic );
01078 NMG_CK_MODEL( m );
01079
01080 nmg_vmodel( m );
01081
01082 r = s->r_p;
01083 NMG_CK_REGION( r );
01084
01085 s_fu = nmg_msv( r );
01086 NMG_CK_SHELL( s_fu );
01087
01088 bu_ptbl_init( &fus , 64, " &fus ");
01089
01090 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
01091 {
01092 NMG_CK_FACEUSE( fu );
01093
01094 if( fu->orientation == OT_SAME )
01095 bu_ptbl_ins( &fus , (long *)fu );
01096 }
01097
01098
01099 for( fu_no=0 ; fu_no < BU_PTBL_END( &fus ) ; fu_no ++ )
01100 {
01101 struct faceuse *fu2;
01102
01103 fu = (struct faceuse *)BU_PTBL_GET( &fus , fu_no );
01104
01105 NMG_CK_FACEUSE( fu );
01106
01107
01108 nmg_mv_fu_between_shells( s_fu, s, fu );
01109
01110
01111
01112
01113 for( fu2_no=fu_no+1 ; fu2_no < BU_PTBL_END( &fus ) ; fu2_no++ )
01114 {
01115 struct face *f,*f2;
01116
01117 fu2 = (struct faceuse *)BU_PTBL_GET( &fus , fu2_no );
01118
01119 if( rt_g.NMG_debug & DEBUG_BASIC )
01120 bu_log( "nmg_extrude_cleanup: fu=x%x, fu2=x%x\n" , fu , fu2 );
01121
01122
01123 if( fu2->orientation != OT_SAME || nmg_faces_are_radial( fu , fu2 ) )
01124 continue;
01125
01126 f = fu->f_p;
01127 f2 = fu2->f_p;
01128
01129
01130 if( !V3RPP_OVERLAP( f->min_pt , f->max_pt , f2->min_pt , f2->max_pt ) )
01131 continue;
01132
01133 if( rt_g.NMG_debug & DEBUG_BASIC )
01134 bu_log( "nmg_extrude_cleanup: calling nmg_isect_two_generic_faces( fu=x%x , fu2=x%x )\n" , fu , fu2 );
01135
01136 nmg_isect_two_generic_faces( fu , fu2 , tol );
01137 }
01138
01139 while( BU_LIST_NON_EMPTY( &s_fu->fu_hd ) )
01140 {
01141 struct faceuse *fu_tmp;
01142
01143 fu_tmp = BU_LIST_FIRST( faceuse , &s_fu->fu_hd );
01144 NMG_CK_FACEUSE( fu_tmp );
01145
01146 if( rt_g.NMG_debug & DEBUG_BASIC )
01147 bu_log( "nmg_extrude_cleanup: moving fu x%x back\n" , fu_tmp );
01148
01149 nmg_mv_fu_between_shells( s, s_fu, fu_tmp );
01150 }
01151 }
01152
01153
01154 nmg_ks( s_fu );
01155
01156 bu_ptbl_free( &fus);
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 struct edgeuse *
01172 nmg_next_radial_eu(const struct edgeuse *eu, const struct shell *s, const int wires)
01173 {
01174 struct edgeuse *ret_eu;
01175
01176 NMG_CK_EDGEUSE( eu );
01177 if( s )
01178 NMG_CK_SHELL( s );
01179
01180 if( s && nmg_find_s_of_eu( eu ) != s )
01181 rt_bomb( "nmg_find_radial_eu: eu is not in specified shell\n" );
01182
01183 if( !wires && !nmg_find_fu_of_eu( eu ) )
01184 rt_bomb( "nmg_find_radial_eu: wire edges not specified, but eu is a wire!!\n" );
01185
01186 ret_eu = eu->eumate_p->radial_p;
01187 while(
01188 (!wires & (nmg_find_fu_of_eu(ret_eu) == (struct faceuse *)NULL))
01189 ||
01190 ( (s != (struct shell *)NULL) &&
01191 nmg_find_s_of_eu(ret_eu) != s )
01192 )
01193 ret_eu = ret_eu->eumate_p->radial_p;
01194
01195 return( ret_eu );
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 struct edgeuse *
01212 nmg_prev_radial_eu(const struct edgeuse *eu, const struct shell *s, const int wires)
01213 {
01214 struct edgeuse *ret_eu;
01215
01216 NMG_CK_EDGEUSE( eu );
01217 if( s )
01218 NMG_CK_SHELL( s );
01219
01220 if( s && nmg_find_s_of_eu( eu ) != s )
01221 rt_bomb( "nmg_find_radial_eu: eu is not in specified shell\n" );
01222
01223 if( !wires && !nmg_find_fu_of_eu( eu ) )
01224 rt_bomb( "nmg_find_radial_eu: wire edges not specified, but eu is a wire!!\n" );
01225
01226 ret_eu = eu->radial_p->eumate_p;
01227 while( ( !wires & (nmg_find_fu_of_eu( ret_eu ) == (struct faceuse *)NULL)) ||
01228 ( (s != (struct shell *)NULL) && nmg_find_s_of_eu( ret_eu ) != s ) )
01229 ret_eu = ret_eu->radial_p->eumate_p;
01230
01231 return( ret_eu );
01232 }
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 int
01244 nmg_radial_face_count(const struct edgeuse *eu, const struct shell *s)
01245 {
01246 int face_count=1;
01247 struct edgeuse *eu1;
01248
01249 NMG_CK_EDGEUSE( eu );
01250 if( s )
01251 NMG_CK_SHELL( s );
01252
01253
01254 eu1 = eu->eumate_p->radial_p;
01255 while( eu1 != eu && eu1 != eu->eumate_p )
01256 {
01257
01258 if( (!s || nmg_find_s_of_eu( eu1 ) == s) &&
01259 nmg_find_fu_of_eu( eu1 ) != (struct faceuse *)NULL )
01260 face_count++;
01261 eu1 = eu1->eumate_p->radial_p;
01262 }
01263
01264 return( face_count );
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 int
01278 nmg_check_closed_shell(const struct shell *s, const struct bn_tol *tol)
01279 {
01280 struct faceuse *fu;
01281
01282 NMG_CK_SHELL( s );
01283 BN_CK_TOL( tol );
01284
01285 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
01286 {
01287 struct loopuse *lu;
01288
01289 NMG_CK_FACEUSE( fu );
01290
01291 if( fu->orientation != OT_SAME )
01292 continue;
01293
01294 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
01295 {
01296 struct edgeuse *eu;
01297
01298 NMG_CK_LOOPUSE( lu );
01299
01300 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01301 continue;
01302
01303 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
01304 {
01305 struct edgeuse *next_eu;
01306
01307 next_eu = nmg_next_radial_eu( eu, s , 0 );
01308 if( next_eu == eu || next_eu == eu->eumate_p )
01309 return( 1 );
01310 }
01311 }
01312 }
01313
01314 return( 0 );
01315 }
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 int
01326 nmg_move_lu_between_fus(struct faceuse *dest, struct faceuse *src, struct loopuse *lu)
01327 {
01328 struct loopuse *lumate;
01329 int src_is_empty;
01330
01331 NMG_CK_FACEUSE( dest );
01332 NMG_CK_FACEUSE( dest->fumate_p );
01333 NMG_CK_FACEUSE( src );
01334 NMG_CK_FACEUSE( src->fumate_p );
01335 NMG_CK_LOOPUSE( lu );
01336
01337 if( rt_g.NMG_debug & DEBUG_BASIC )
01338 bu_log( "nmg_move_lu_between_fus( dest=x%x, src=x%x, lu=x%x)\n", dest, src, lu );
01339
01340 if( lu->up.fu_p != src )
01341 {
01342 bu_log( "nmg_move_lu_between_fus( dest=x%x, src=x%x, lu=x%x)\n", dest, src, lu );
01343 rt_bomb( "\tlu is not in src faceuse\n" );
01344 }
01345
01346 if( dest == src )
01347 return( 0 );
01348
01349 lumate = lu->lumate_p;
01350 NMG_CK_LOOPUSE( lumate );
01351
01352
01353 BU_LIST_DEQUEUE( &lu->l );
01354 src_is_empty = BU_LIST_IS_EMPTY( &src->lu_hd );
01355
01356
01357 BU_LIST_DEQUEUE( &lumate->l );
01358 if( src_is_empty != BU_LIST_IS_EMPTY( &src->fumate_p->lu_hd ) )
01359 {
01360 bu_log( "nmg_move_lu_between_fus( dest=x%x, src=x%x, lu=x%x)\n", dest, src, lu );
01361 if( src_is_empty )
01362 rt_bomb( "\tsrc faceuse contains only lu, but src->fumate_p has more!!\n" );
01363 rt_bomb( "\tsrc->fumate_p faceuse contains only lu->lumate_p, but src has more!!\n" );
01364 }
01365
01366
01367 BU_LIST_INSERT( &dest->lu_hd, &lu->l );
01368
01369
01370 BU_LIST_INSERT( &dest->fumate_p->lu_hd, &lumate->l );
01371
01372
01373 lu->up.fu_p = dest;
01374 lumate->up.fu_p = dest->fumate_p;
01375
01376 return( src_is_empty );
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 void
01388 nmg_loop_plane_newell(const struct loopuse *lu, fastf_t *pl)
01389 {
01390 struct edgeuse *eu;
01391 double hmin,hmax;
01392 double pl_tmp[3];
01393
01394 NMG_CK_LOOPUSE( lu );
01395
01396 VSETALL( pl, 0.0 );
01397 pl[H] = 0.0;
01398
01399 VSETALL( pl_tmp, 0.0 );
01400
01401
01402 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01403 return;
01404
01405
01406 if( nmg_loop_is_a_crack( lu ) )
01407 return;
01408
01409 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01410 return;
01411
01412 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
01413 {
01414 struct edgeuse *eu_next;
01415 struct vertex_g *vg;
01416 struct vertex_g *vg_next;
01417
01418 vg = eu->vu_p->v_p->vg_p;
01419 eu_next = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
01420 vg_next = eu_next->vu_p->v_p->vg_p;
01421
01422 pl_tmp[X] += ( vg->coord[Y] - vg_next->coord[Y]) * ( vg->coord[Z] + vg_next->coord[Z] );
01423 pl_tmp[Y] += ( vg->coord[Z] - vg_next->coord[Z]) * ( vg->coord[X] + vg_next->coord[X] );
01424 pl_tmp[Z] += ( vg->coord[X] - vg_next->coord[X]) * ( vg->coord[Y] + vg_next->coord[Y] );
01425 }
01426
01427 VUNITIZE( pl_tmp );
01428 VMOVE( pl, pl_tmp );
01429
01430 hmin = MAX_FASTF;
01431 hmax = (-hmin);
01432
01433 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
01434 {
01435 struct vertex_g *vg;
01436 fastf_t htest;
01437
01438 vg = eu->vu_p->v_p->vg_p;
01439 htest = VDOT( vg->coord, pl );
01440 if( htest > hmax )
01441 hmax = htest;
01442 if( htest < hmin )
01443 hmin = htest;
01444 }
01445
01446 pl[H] = (hmax + hmin)/2.0;
01447
01448 if( lu->orientation == OT_OPPOSITE )
01449 HREVERSE( pl, pl );
01450 }
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 fastf_t
01465 nmg_loop_plane_area(const struct loopuse *lu, fastf_t *pl)
01466 {
01467 fastf_t area;
01468 fastf_t vect_mag;
01469 fastf_t vect_mag_inv;
01470 fastf_t pt_dot_plane=0.0;
01471 fastf_t pt_count=0.0;
01472 plane_t plane;
01473 struct edgeuse *eu;
01474 vect_t trans;
01475
01476 NMG_CK_LOOPUSE( lu );
01477
01478
01479 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01480 return( (fastf_t)(-1.0) );
01481
01482
01483 if( nmg_loop_is_a_crack( lu ) )
01484 return( (fastf_t)(-1.0) );
01485
01486
01487
01488
01489
01490
01491 eu = BU_LIST_FIRST( edgeuse , &lu->down_hd );
01492 NMG_CK_VERTEXUSE( eu->vu_p );
01493 NMG_CK_VERTEX( eu->vu_p->v_p );
01494 NMG_CK_VERTEX_G( eu->vu_p->v_p->vg_p );
01495 VMOVE( trans , eu->vu_p->v_p->vg_p->coord );
01496
01497 VSET( plane , 0.0 , 0.0 , 0.0 );
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
01509 {
01510 struct edgeuse *next_eu;
01511 struct vertex *vp,*next_vp;
01512 vect_t cross;
01513 point_t p1,p2;
01514
01515 vp = eu->vu_p->v_p;
01516
01517 next_eu = BU_LIST_PNEXT_CIRC( edgeuse , &eu->l );
01518 NMG_CK_EDGEUSE( next_eu );
01519 NMG_CK_VERTEXUSE( next_eu->vu_p );
01520
01521 next_vp = next_eu->vu_p->v_p;
01522 NMG_CK_VERTEX( next_vp );
01523 NMG_CK_VERTEX_G( next_vp->vg_p );
01524
01525 VSUB2( p1 , vp->vg_p->coord , trans );
01526 VSUB2( p2 , next_vp->vg_p->coord , trans );
01527 VCROSS( cross , p1 , p2 );
01528 VADD2( plane , plane , cross );
01529 }
01530
01531 vect_mag = MAGNITUDE( plane );
01532
01533
01534 if( vect_mag < SMALL_FASTF )
01535 return( (fastf_t)(-1.0) );
01536
01537 area = 0.5 * vect_mag;
01538 vect_mag_inv = 1.0/vect_mag;
01539
01540 VSCALE( plane , plane , vect_mag_inv );
01541
01542
01543 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
01544 {
01545 pt_dot_plane += VDOT( plane , eu->vu_p->v_p->vg_p->coord );
01546 pt_count++;
01547 }
01548
01549
01550 if( pt_count < 3 )
01551 return( (fastf_t)(-1.0) );
01552
01553 plane[3] = pt_dot_plane/pt_count;
01554 HMOVE( pl , plane );
01555
01556 return( area );
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 int
01578 nmg_calc_face_plane(struct faceuse *fu_in, fastf_t *pl)
01579 {
01580 struct faceuse *fu;
01581 struct bu_ptbl verts;
01582 plane_t old_pl;
01583 struct face *f;
01584 struct face_g_plane *fg;
01585 struct loopuse *lu;
01586 mat_t matrix;
01587 mat_t inverse;
01588 fastf_t det;
01589 double one_over_vertex_count;
01590 vect_t vsum;
01591 fastf_t min_dist=MAX_FASTF;
01592 fastf_t max_dist=(-MAX_FASTF);
01593 int i;
01594 int got_dir=0;
01595 int failed=0;
01596 int loop_count=0;
01597
01598 fu = fu_in;
01599 NMG_CK_FACEUSE( fu );
01600
01601
01602 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
01603 {
01604 if( !got_dir && BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_EDGEUSE_MAGIC )
01605 {
01606
01607 nmg_loop_plane_newell( lu , old_pl );
01608 if( old_pl[X] != 0.0 || old_pl[Y] != 0.0 || old_pl[Z] != 0.0 )
01609 got_dir = 1;
01610 }
01611
01612 loop_count++;
01613 }
01614
01615 if( !got_dir )
01616 return( 1 );
01617
01618 f = fu->f_p;
01619 NMG_CK_FACE( f );
01620 fg = f->g.plane_p;
01621 if( fg )
01622 {
01623 struct face *f1;
01624
01625 NMG_CK_FACE_G_PLANE( fg );
01626
01627
01628 loop_count = 0;
01629 for( BU_LIST_FOR( f1 , face, &fg->f_hd ) )
01630 {
01631 for( BU_LIST_FOR( lu, loopuse, &f1->fu_p->lu_hd ) )
01632 loop_count++;
01633 }
01634
01635
01636 if( loop_count < 2 )
01637 {
01638 HMOVE( pl, old_pl );
01639 return( 0 );
01640 }
01641
01642 nmg_tabulate_face_g_verts( &verts , fg );
01643 }
01644 else
01645 {
01646
01647 if( loop_count < 2 )
01648 {
01649 HMOVE( pl, old_pl );
01650 return( 0 );
01651 }
01652
01653 nmg_vertex_tabulate( &verts , &fu->l.magic );
01654 }
01655
01656
01657
01658
01659 if( fu->orientation != OT_UNSPEC )
01660 {
01661 if( fu->orientation != OT_SAME )
01662 fu = fu->fumate_p;
01663 if( fu->orientation != OT_SAME )
01664 {
01665 bu_log( "nmg_calc_face_plane: fu x%x has no OT_SAME use\n" , fu );
01666 bu_ptbl_free( &verts );
01667 return( 1 );
01668 }
01669 }
01670
01671
01672 MAT_ZERO( matrix );
01673 VSET( vsum , 0.0 , 0.0 , 0.0 );
01674
01675 one_over_vertex_count = 1.0/(double)(BU_PTBL_END( &verts ));
01676
01677 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
01678 {
01679 struct vertex *v;
01680 struct vertex_g *vg;
01681
01682 v = (struct vertex *)BU_PTBL_GET( &verts , i );
01683 vg = v->vg_p;
01684
01685 matrix[0] += vg->coord[X] * vg->coord[X];
01686 matrix[1] += vg->coord[X] * vg->coord[Y];
01687 matrix[2] += vg->coord[X] * vg->coord[Z];
01688 matrix[5] += vg->coord[Y] * vg->coord[Y];
01689 matrix[6] += vg->coord[Y] * vg->coord[Z];
01690 matrix[10] += vg->coord[Z] * vg->coord[Z];
01691
01692 vsum[X] += vg->coord[X];
01693 vsum[Y] += vg->coord[Y];
01694 vsum[Z] += vg->coord[Z];
01695 }
01696 matrix[4] = matrix[1];
01697 matrix[8] = matrix[2];
01698 matrix[9] = matrix[6];
01699 matrix[15] = 1.0;
01700
01701
01702
01703 det = bn_mat_determinant( matrix );
01704
01705 if( !NEAR_ZERO( det , SMALL_FASTF ) )
01706 {
01707 fastf_t inv_len_pl;
01708
01709
01710 bn_mat_inv( inverse , matrix );
01711
01712
01713 MAT4X3PNT( pl , inverse , vsum );
01714
01715
01716 inv_len_pl = 1.0/(MAGNITUDE( pl ));
01717 HSCALE( pl , pl , inv_len_pl );
01718
01719
01720 VSCALE( vsum, vsum, one_over_vertex_count );
01721
01722
01723 pl[H] = VDOT( pl , vsum );
01724
01725
01726 if( VDOT( pl , old_pl ) < 0.0 )
01727 HREVERSE( pl , pl );
01728 }
01729 else
01730 {
01731 struct vertex *v,*v0;
01732 int x_same=1;
01733 int y_same=1;
01734 int z_same=1;
01735
01736
01737
01738
01739 v0 = (struct vertex *)BU_PTBL_GET( &verts , 0 );
01740 for( i=1 ; i<BU_PTBL_END( &verts ) ; i++ )
01741 {
01742 v = (struct vertex *)BU_PTBL_GET( &verts , i );
01743
01744 if( v->vg_p->coord[X] != v0->vg_p->coord[X] )
01745 x_same = 0;
01746 if( v->vg_p->coord[Y] != v0->vg_p->coord[Y] )
01747 y_same = 0;
01748 if( v->vg_p->coord[Z] != v0->vg_p->coord[Z] )
01749 z_same = 0;
01750
01751 if( !x_same && !y_same && !z_same )
01752 break;
01753 }
01754
01755 if( x_same )
01756 {
01757 VSET( pl , 1.0 , 0.0 , 0.0 );
01758 }
01759 else if( y_same )
01760 {
01761 VSET( pl , 0.0 , 1.0 , 0.0 );
01762 }
01763 else if( z_same )
01764 {
01765 VSET( pl , 0.0 , 0.0 , 1.0 );
01766 }
01767
01768 if( x_same || y_same || z_same )
01769 {
01770
01771 VSCALE( vsum, vsum, one_over_vertex_count );
01772
01773
01774 pl[H] = VDOT( pl , vsum );
01775
01776
01777 if( VDOT( pl , old_pl ) < 0.0 )
01778 HREVERSE( pl , pl );
01779 }
01780 else
01781 {
01782 bu_log( "nmg_calc_face_plane: Cannot calculate plane for fu x%x\n" , fu );
01783 nmg_pr_fu_briefly( fu , (char *)NULL );
01784 bu_log( "%d verts\n" , BU_PTBL_END( &verts ) );
01785 failed = 1;
01786 }
01787 }
01788
01789
01790 for( i=0 ; i<BU_PTBL_END( &verts ) ; i++ )
01791 {
01792 struct vertex *v;
01793 struct vertex_g *vg;
01794 fastf_t dist;
01795
01796 v = (struct vertex *)BU_PTBL_GET( &verts, i );
01797 vg = v->vg_p;
01798
01799 dist = DIST_PT_PLANE( vg->coord, pl );
01800 if( dist > max_dist )
01801 max_dist = dist;
01802 if( dist < min_dist )
01803 min_dist = dist;
01804 }
01805
01806 pl[H] += (max_dist + min_dist)/2.0;
01807
01808 bu_ptbl_free( &verts );
01809 return( failed );
01810 }
01811
01812
01813
01814
01815
01816
01817
01818 int
01819 nmg_calc_face_g(struct faceuse *fu)
01820 {
01821 plane_t pl;
01822 int ret_val;
01823
01824 ret_val = nmg_calc_face_plane( fu, pl );
01825
01826 if( !ret_val )
01827 nmg_face_g( fu, pl );
01828
01829 return( ret_val );
01830 }
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842 fastf_t
01843 nmg_faceuse_area(const struct faceuse *fu)
01844 {
01845 struct loopuse *lu;
01846 plane_t plane;
01847 fastf_t area=0.0;
01848 fastf_t tmp_area;
01849
01850 NMG_CK_FACEUSE( fu );
01851
01852 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
01853 {
01854 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
01855 continue;
01856
01857 tmp_area = nmg_loop_plane_area( lu , plane );
01858 if( tmp_area < 0.0 )
01859 continue;
01860
01861 if( lu->orientation == OT_SAME )
01862 area += tmp_area;
01863 else if( lu->orientation == OT_OPPOSITE )
01864 area -= tmp_area;
01865 else
01866 {
01867 bu_log( "nmg_faceuse_area: Cannot calculate area (lu with %s orientation)\n",
01868 nmg_orientation( lu->orientation ) );
01869 return( (fastf_t)-1.0 );
01870 }
01871 }
01872
01873 return( area );
01874 }
01875
01876 fastf_t
01877 nmg_shell_area(const struct shell *s)
01878 {
01879 fastf_t area=0.0;
01880 fastf_t tmp_area;
01881 struct faceuse *fu;
01882
01883 NMG_CK_SHELL( s );
01884
01885 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
01886 {
01887 if( fu->orientation != OT_SAME )
01888 continue;
01889
01890 tmp_area = nmg_faceuse_area( fu );
01891 if( tmp_area < 0.0 )
01892 continue;
01893
01894 area += tmp_area;
01895 }
01896
01897 return( area );
01898 }
01899
01900 fastf_t
01901 nmg_region_area(const struct nmgregion *r)
01902 {
01903 struct shell *s;
01904 fastf_t area=0.0;
01905
01906 NMG_CK_REGION( r );
01907
01908 for( BU_LIST_FOR( s , shell , &r->s_hd ) )
01909 area += nmg_shell_area( s );
01910
01911 return( area );
01912 }
01913
01914 fastf_t
01915 nmg_model_area(const struct model *m)
01916 {
01917 struct nmgregion *r;
01918 fastf_t area=0.0;
01919
01920 NMG_CK_MODEL( m );
01921
01922 for( BU_LIST_FOR( r , nmgregion , &m->r_hd ) )
01923 area += nmg_region_area( r );
01924
01925 return( area );
01926 }
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948 int
01949 rt_dist_line3_line3(fastf_t *dist, const fastf_t *p1, const fastf_t *d1, const fastf_t *p2, const fastf_t *d2, const struct bn_tol *tol)
01950 {
01951 fastf_t d1_d2;
01952 point_t a1,a2;
01953 vect_t a1_to_a2;
01954 vect_t p2_to_p1;
01955 fastf_t min_dist;
01956 fastf_t tol_dist_sq;
01957 fastf_t tol_dist;
01958
01959 BN_CK_TOL( tol );
01960
01961 if( tol->dist > 0.0 )
01962 tol_dist = tol->dist;
01963 else
01964 tol_dist = 0.005;
01965
01966 if( tol->dist_sq > 0.0 )
01967 tol_dist_sq = tol->dist_sq;
01968 else
01969 tol_dist_sq = tol_dist * tol_dist;
01970
01971 if( !NEAR_ZERO( MAGSQ( d1 ) - 1.0 , tol_dist_sq ) )
01972 {
01973 bu_log( "rt_dist_line3_line3: non-unit length direction vector ( %f %f %f )\n" , V3ARGS( d1 ) );
01974 rt_bomb( "rt_dist_line3_line3\n" );
01975 }
01976
01977 if( !NEAR_ZERO( MAGSQ( d2 ) - 1.0 , tol_dist_sq ) )
01978 {
01979 bu_log( "rt_dist_line3_line3: non-unit length direction vector ( %f %f %f )\n" , V3ARGS( d2 ) );
01980 rt_bomb( "rt_dist_line3_line3\n" );
01981 }
01982
01983 d1_d2 = VDOT( d1 , d2 );
01984
01985 if( BN_VECT_ARE_PARALLEL( d1_d2 , tol ) )
01986 {
01987 if( bn_dist_line3_pt3( p1 , d1 , p2 ) > tol_dist )
01988 return( -2 );
01989 else
01990 return( -1 );
01991 }
01992
01993 VSUB2( p2_to_p1 , p1 , p2 );
01994 dist[0] = (d1_d2 * VDOT( p2_to_p1 , d2 ) - VDOT( p2_to_p1 , d1 ))/(1.0 - d1_d2 * d1_d2 );
01995 dist[1] = dist[0] * d1_d2 + VDOT( p2_to_p1 , d2 );
01996
01997 VJOIN1( a1 , p1 , dist[0] , d1 );
01998 VJOIN1( a2 , p2 , dist[1] , d2 );
01999
02000 VSUB2( a1_to_a2 , a2 , a1 );
02001 min_dist = MAGNITUDE( a1_to_a2 );
02002 if( min_dist < tol_dist )
02003 return( 0 );
02004 else
02005 return( 1 );
02006 }
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032 int
02033 rt_dist_line3_lseg3(fastf_t *dist, const fastf_t *p, const fastf_t *d, const fastf_t *a, const fastf_t *b, const struct bn_tol *tol)
02034 {
02035 vect_t a_to_b;
02036 vect_t a_dir;
02037 fastf_t len_ab;
02038 int outside_segment;
02039 int ret;
02040
02041 BN_CK_TOL( tol );
02042
02043 VSUB2( a_to_b , b , a );
02044 len_ab = MAGNITUDE( a_to_b );
02045 VSCALE( a_dir , a_to_b , (1.0/len_ab) );
02046
02047 ret = rt_dist_line3_line3( dist , p , d , a , a_dir , tol );
02048
02049 if( ret < 0 )
02050 {
02051 vect_t to_a,to_b;
02052 fastf_t dist_to_a,dist_to_b;
02053
02054 VSUB2( to_a , a , p );
02055 VSUB2( to_b , b , p );
02056 dist_to_a = VDOT( to_a , d );
02057 dist_to_b = VDOT( to_b , d );
02058
02059 if( dist_to_a <= dist_to_b )
02060 {
02061 dist[0] = dist_to_a;
02062 dist[1] = 0.0;
02063 }
02064 else
02065 {
02066 dist[0] = dist_to_b;
02067 dist[1] = 1.0;
02068 }
02069 return( ret );
02070 }
02071
02072 if( dist[1] >= (-tol->dist) && dist[1] <= len_ab + tol->dist )
02073 {
02074
02075 outside_segment = 0;
02076 dist[1] = dist[1]/len_ab;
02077 if( dist[1] < 0.0 )
02078 dist[1] = 0.0;
02079 if( dist[1] > 1.0 )
02080 dist[1] = 1.0;
02081 }
02082 else
02083 {
02084 outside_segment = 1;
02085 dist[1] = dist[1]/len_ab;
02086 }
02087
02088 return( 2*ret + outside_segment );
02089 }
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 void
02105 nmg_purge_unwanted_intersection_points(struct bu_ptbl *vert_list, fastf_t *mag_list, const struct faceuse *fu, const struct bn_tol *tol)
02106 {
02107 int i;
02108 int j;
02109 struct vertexuse *vu;
02110 struct loopuse *lu;
02111 const struct loop_g *lg;
02112 const struct loopuse *fu2lu;
02113 const struct loop_g *fu2lg = (const struct loop_g *)NULL;
02114 int overlap = 0;
02115
02116 NMG_CK_FACEUSE(fu);
02117 BN_CK_TOL(tol);
02118
02119 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02120 {
02121 bu_log("nmg_purge_unwanted_intersection_points(0x%08x, 0x%08x)\n", vert_list, fu);
02122 bu_log("\t%d vertexuses in list\n", vert_list->end );
02123 }
02124
02125 for (i=0 ; i < vert_list->end ; i++) {
02126 vu = (struct vertexuse *)vert_list->buffer[i];
02127 if( vu->l.magic != NMG_VERTEXUSE_MAGIC )
02128 {
02129
02130
02131 for (j=i ; j < vert_list->end ; j++)
02132 {
02133 vert_list->buffer[j] = vert_list->buffer[j+1];
02134 mag_list[j] = mag_list[j+1];
02135 }
02136
02137 --(vert_list->end);
02138 vert_list->buffer[vert_list->end] = (long *)NULL;
02139 mag_list[vert_list->end] = MAX_FASTF;
02140 --i;
02141 continue;
02142 }
02143 NMG_CK_VERTEXUSE(vu);
02144 lu = nmg_find_lu_of_vu( vu );
02145 NMG_CK_LOOPUSE(lu);
02146 lg = lu->l_p->lg_p;
02147 NMG_CK_LOOP_G(lg);
02148
02149 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02150 bu_log("vu[%d]: 0x%08x (%g %g %g) lu: 0x%08x %s\n",
02151 i, vu, V3ARGS(vu->v_p->vg_p->coord),
02152 lu, nmg_orientation(lu->orientation) );
02153 bu_log("\tlu BBox: (%g %g %g) (%g %g %g)\n",
02154 V3ARGS(lg->min_pt), V3ARGS(lg->max_pt) );
02155 }
02156 if (lu->up.fu_p->f_p == fu->f_p)
02157 bu_log("I'm checking against my own face?\n");
02158
02159
02160
02161
02162
02163 overlap = 0;
02164 for (BU_LIST_FOR(fu2lu, loopuse, &fu->lu_hd )){
02165 NMG_CK_LOOPUSE(fu2lu);
02166 NMG_CK_LOOP(fu2lu->l_p);
02167
02168 switch(fu2lu->orientation) {
02169 case OT_BOOLPLACE:
02170
02171
02172
02173 continue;
02174 case OT_UNSPEC:
02175
02176
02177
02178
02179
02180 if( BU_LIST_FIRST_MAGIC(&fu2lu->down_hd) != NMG_VERTEXUSE_MAGIC )
02181 bu_log("nmg_purge_unwanted_intersection_points() non self-loop OT_UNSPEC vertexuse in fu2?\n");
02182 break;
02183 case OT_SAME:
02184 case OT_OPPOSITE:
02185 break;
02186 default:
02187 bu_log("nmg_purge_unwanted_intersection_points encountered %s loop in fu2\n",
02188 nmg_orientation(fu2lu->orientation));
02189
02190 break;
02191 }
02192
02193 fu2lg = fu2lu->l_p->lg_p;
02194 NMG_CK_LOOP_G(fu2lg);
02195
02196 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02197 bu_log("\tfu2lu BBox: (%g %g %g) (%g %g %g) %s\n",
02198 V3ARGS(fu2lg->min_pt), V3ARGS(fu2lg->max_pt),
02199 nmg_orientation(fu2lu->orientation) );
02200 }
02201
02202 if (V3RPP_OVERLAP_TOL(fu2lg->min_pt, fu2lg->max_pt,
02203 lg->min_pt, lg->max_pt, tol)) {
02204 overlap = 1;
02205 break;
02206 }
02207 }
02208 if (!overlap) {
02209
02210 if (rt_g.NMG_debug & DEBUG_POLYSECT) {
02211 bu_log("nmg_purge_unwanted_intersection_points This little bugger slipped in somehow. Deleting it from the list.\n");
02212 nmg_pr_vu_briefly(vu, (char *)NULL);
02213 }
02214 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_VERTEXUSE_MAGIC &&
02215 lu->orientation == OT_UNSPEC ) {
02216
02217 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02218 bu_log("nmg_purge_unwanted_intersection_points() remarking as OT_BOOLPLACE\n");
02219 lu->orientation =
02220 lu->lumate_p->orientation = OT_BOOLPLACE;
02221 }
02222
02223
02224 for (j=i ; j < vert_list->end ; j++)
02225 {
02226 vert_list->buffer[j] = vert_list->buffer[j+1];
02227 mag_list[j] = mag_list[j+1];
02228 }
02229
02230 --(vert_list->end);
02231 vert_list->buffer[vert_list->end] = (long *)NULL;
02232 mag_list[vert_list->end] = MAX_FASTF;
02233 --i;
02234 }
02235 }
02236 if (rt_g.NMG_debug & DEBUG_POLYSECT)
02237 bu_log("\tAt end of nmg_purge_unwanted_intersection_points, %d vertexuses in list\n",
02238 vert_list->end );
02239 }
02240
02241
02242
02243
02244
02245
02246
02247
02248 int
02249 nmg_in_or_ref(struct vertexuse *vu, struct bu_ptbl *b)
02250 {
02251 union {
02252 struct vertexuse **vu;
02253 long **magic_p;
02254 } p;
02255 int i;
02256
02257 p.magic_p = b->buffer;
02258 for (i=0 ; i < b->end ; ++i) {
02259 if (p.vu[i] && *p.magic_p[i] == NMG_VERTEXUSE_MAGIC &&
02260 (p.vu[i] == vu || p.vu[i]->v_p == vu->v_p))
02261 return(1);
02262 }
02263 return(0);
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278 void
02279 nmg_rebound(struct model *m, const struct bn_tol *tol)
02280 {
02281 struct nmgregion *r;
02282 struct shell *s;
02283 struct faceuse *fu;
02284 struct face *f;
02285 struct loopuse *lu;
02286 struct loop *l;
02287 register int *flags;
02288
02289 NMG_CK_MODEL(m);
02290 BN_CK_TOL(tol);
02291
02292 flags = (int *)bu_calloc( m->maxindex*2, sizeof(int), "rebound flags[]" );
02293
02294 for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) ) {
02295 NMG_CK_REGION(r);
02296 for( BU_LIST_FOR( s, shell, &r->s_hd ) ) {
02297 NMG_CK_SHELL(s);
02298
02299
02300 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
02301 NMG_CK_FACEUSE(fu);
02302
02303 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) {
02304 NMG_CK_LOOPUSE(lu);
02305 l = lu->l_p;
02306 NMG_CK_LOOP(l);
02307 if( NMG_INDEX_FIRST_TIME(flags,l) )
02308 nmg_loop_g(l, tol);
02309 }
02310 }
02311
02312 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) {
02313 NMG_CK_FACEUSE(fu);
02314 f = fu->f_p;
02315 NMG_CK_FACE(f);
02316
02317
02318 if( NMG_INDEX_FIRST_TIME(flags,f) )
02319 nmg_face_bb( f, tol );
02320 }
02321
02322
02323 for( BU_LIST_FOR( lu, loopuse, &s->lu_hd ) ) {
02324 NMG_CK_LOOPUSE(lu);
02325 l = lu->l_p;
02326 NMG_CK_LOOP(l);
02327 if( NMG_INDEX_FIRST_TIME(flags,l) )
02328 nmg_loop_g(l, tol);
02329 }
02330
02331
02332
02333
02334
02335 if( NMG_INDEX_FIRST_TIME(flags,s) )
02336 nmg_shell_a( s, tol );
02337 }
02338
02339
02340 nmg_region_a( r, tol );
02341 }
02342
02343 bu_free( (char *)flags, "rebound flags[]" );
02344 }
02345
02346
02347
02348
02349 void
02350 nmg_count_shell_kids(const struct model *m, long unsigned int *total_faces, long unsigned int *total_wires, long unsigned int *total_points)
02351 {
02352 short *tbl;
02353
02354 const struct nmgregion *r;
02355 const struct shell *s;
02356 const struct faceuse *fu;
02357 const struct loopuse *lu;
02358 const struct edgeuse *eu;
02359
02360 NMG_CK_MODEL(m);
02361
02362 tbl = (short *)bu_calloc(m->maxindex+1, sizeof(char),
02363 "face/wire/point counted table");
02364
02365 *total_faces = *total_wires = *total_points = 0;
02366 for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
02367 for (BU_LIST_FOR(s, shell, &r->s_hd)) {
02368 if (s->vu_p) {
02369 total_points++;
02370 continue;
02371 }
02372 for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
02373 if (NMG_INDEX_TEST_AND_SET(tbl, fu->f_p))
02374 (*total_faces)++;
02375 }
02376 for (BU_LIST_FOR(lu, loopuse, &s->lu_hd)) {
02377 if (NMG_INDEX_TEST_AND_SET(tbl, lu->l_p))
02378 (*total_wires)++;
02379 }
02380 for (BU_LIST_FOR(eu, edgeuse, &s->eu_hd)) {
02381 if (NMG_INDEX_TEST_AND_SET(tbl, eu->e_p))
02382 (*total_wires)++;
02383 }
02384 }
02385 }
02386
02387 bu_free((char *)tbl, "face/wire/point counted table");
02388 }
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403 static void
02404 order_tbl(struct bu_ptbl *tbl, int start_index, int **index, int tbl_size, int *loop_size)
02405 {
02406 int i,j,k;
02407 int found;
02408 struct edgeuse *eu,*eu1;
02409 struct vertex *start_v;
02410
02411
02412 if( *index == NULL )
02413 (*index) = (int *)bu_calloc( tbl_size , sizeof( int ) , "Table index" );
02414
02415 for( i=0 ; i<tbl_size ; i++ )
02416 (*index)[i] = (-1);
02417
02418
02419 (*index)[0] = start_index;
02420 *loop_size = 1;
02421 eu = (struct edgeuse *)BU_PTBL_GET( tbl , start_index );
02422 start_v = eu->vu_p->v_p;
02423 i = 0;
02424 found = 1;
02425 while( eu->eumate_p->vu_p->v_p != start_v && found )
02426 {
02427 found = 0;
02428
02429
02430 for( j=0 ; j<tbl_size ; j++ )
02431 {
02432 int already_used = 0;
02433
02434 eu1 = (struct edgeuse *)BU_PTBL_GET( tbl , j );
02435
02436
02437 for( k=0 ; k<(*loop_size) ; k++ )
02438 {
02439 if( eu1 == (struct edgeuse *)BU_PTBL_GET( tbl, (*index)[k] ) )
02440 {
02441 already_used = 1;
02442 break;
02443 }
02444 }
02445 if( already_used )
02446 continue;
02447 if( eu1->vu_p->v_p == eu->eumate_p->vu_p->v_p )
02448 {
02449
02450 found = 1;
02451 (*index)[++i] = j;
02452 (*loop_size)++;
02453 eu = eu1;
02454 break;
02455 }
02456 }
02457 }
02458 }
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472 void
02473 nmg_close_shell(struct shell *s, const struct bn_tol *tol)
02474 {
02475 struct bu_ptbl eu_tbl;
02476 struct bu_ptbl vert_tbl;
02477 int *index;
02478 int loop_size;
02479 struct faceuse *fu;
02480 struct loopuse *lu;
02481 struct edgeuse *eu;
02482 int start_loop;
02483 int i;
02484 int found;
02485
02486 if( rt_g.NMG_debug & DEBUG_BASIC )
02487 bu_log( "nmg_close_shell: s = x%x\n" , s );
02488
02489 NMG_CK_SHELL( s );
02490 BN_CK_TOL( tol );
02491
02492 index = NULL;
02493
02494
02495 (void)bu_ptbl_init( &eu_tbl , 64, " &eu_tbl ");
02496
02497
02498 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
02499 {
02500 NMG_CK_FACEUSE( fu );
02501
02502 if( fu->orientation == OT_SAME )
02503 {
02504
02505 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
02506 {
02507 NMG_CK_LOOPUSE( lu );
02508
02509 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) ==
02510 NMG_VERTEXUSE_MAGIC )
02511 continue;
02512
02513
02514 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
02515 {
02516 NMG_CK_EDGEUSE( eu );
02517
02518 if( eu->radial_p == eu->eumate_p )
02519 (void)bu_ptbl_ins( &eu_tbl , (long *) eu->eumate_p );
02520 }
02521 }
02522 }
02523 }
02524
02525
02526 if( BU_PTBL_END( &eu_tbl ) == 0 )
02527 {
02528 bu_ptbl_free( &eu_tbl );
02529 return;
02530 }
02531
02532
02533 (void)bu_ptbl_init( &vert_tbl , 64, " &vert_tbl ");
02534
02535 while( BU_PTBL_END( &eu_tbl ) )
02536 {
02537 int give_up_on_face=0;
02538
02539
02540 start_loop = -1;
02541 loop_size = 0;
02542 while( loop_size < 2 )
02543 {
02544 if( ++start_loop > BU_PTBL_END( &eu_tbl ) - 3 )
02545 break;
02546 order_tbl( &eu_tbl, start_loop , &index , BU_PTBL_END( &eu_tbl ) , &loop_size );
02547 }
02548
02549
02550 while( loop_size > 3 )
02551 {
02552 struct edgeuse *eu1, *eu2=NULL, *eu_new = NULL;
02553 struct edgeuse **eu_used;
02554 int edges_used=0;
02555 int found_face=0;
02556 int start_index,end_index;
02557 int coplanar;
02558 plane_t pl1,pl2;
02559 point_t pt[3];
02560
02561
02562
02563 start_index = 0;
02564 end_index = start_index + 3;
02565
02566 for( i=start_index ; i<end_index ; i++ )
02567 {
02568 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02569 VMOVE( pt[i-start_index] , eu->vu_p->v_p->vg_p->coord );
02570 }
02571 while( bn_mk_plane_3pts( pl1 , pt[0] , pt[1] , pt[2] , tol ) && end_index<loop_size )
02572 {
02573 start_index++;
02574 end_index++;
02575 for( i=start_index ; i<end_index ; i++ )
02576 {
02577 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02578 VMOVE( pt[i-start_index] , eu->vu_p->v_p->vg_p->coord );
02579 }
02580 }
02581 if( end_index == loop_size )
02582 {
02583 if( BU_PTBL_END( &eu_tbl ) > loop_size )
02584 {
02585 int old_loop_size=loop_size;
02586
02587 loop_size = 0;
02588 while( loop_size < 3 )
02589 {
02590 found = 1;
02591 for( start_loop=index[0]+1 ; start_loop < BU_PTBL_END( &eu_tbl )-3 ; start_loop++ )
02592 {
02593 found = 0;
02594 for( i=0 ; i<old_loop_size ; i++ )
02595 {
02596 if( index[i] == start_loop )
02597 {
02598 found = 1;
02599 break;
02600 }
02601 }
02602 if( !found )
02603 break;
02604 }
02605 if( found )
02606 {
02607
02608 bu_log( "nmg_close_shell: cannot make any planes from loop, old_loop_size = %d\n", old_loop_size );
02609 for( i=0 ; i<old_loop_size ; i++ )
02610 {
02611 eu= (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02612 bu_log( "(%g %g %g) <-> (%g %g %g)\n",
02613 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
02614 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
02615 }
02616 bu_bomb( "nmg_close_shell: cannot make any planes from loop\n" );
02617 }
02618 order_tbl( &eu_tbl, start_loop , &index , BU_PTBL_END( &eu_tbl ) , &loop_size );
02619 }
02620 }
02621 }
02622
02623
02624 coplanar = 1;
02625 while( end_index < loop_size && coplanar )
02626 {
02627 end_index +=3;
02628 if( end_index > loop_size )
02629 end_index = loop_size;
02630 start_index = end_index - 3;
02631
02632 for( i=start_index ; i<end_index ; i++ )
02633 {
02634 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02635 VMOVE( pt[i-start_index] , eu->vu_p->v_p->vg_p->coord );
02636 }
02637
02638
02639
02640 if( !bn_mk_plane_3pts( pl2 , pt[0] , pt[1] , pt[2] , tol ) )
02641 {
02642 if( (i=bn_coplanar( pl1 , pl2 , tol )) < 1 )
02643 coplanar = 0;
02644 }
02645 }
02646
02647 if( coplanar )
02648 {
02649 struct edgeuse *eu_tmp;
02650
02651
02652 bu_ptbl_reset( &vert_tbl );
02653 for( i=0 ; i<loop_size ; i++ )
02654 {
02655 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02656 bu_ptbl_ins( &vert_tbl , (long *)&eu->vu_p->v_p );
02657 }
02658
02659
02660 fu = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR(&vert_tbl) , loop_size );
02661
02662
02663 if( nmg_loop_plane_area( BU_LIST_FIRST( loopuse , &fu->lu_hd ) , pl2 ) < 0.0 )
02664 {
02665 bu_log( "Failed planeeq\n" );
02666 nmg_kfu( fu );
02667 }
02668 else
02669 {
02670 nmg_face_g( fu , pl2 );
02671
02672
02673 nmg_face_bb( fu->f_p , tol );
02674 }
02675
02676
02677 eu_used = (struct edgeuse **)bu_calloc( loop_size , sizeof( struct edguse *) , "edges used list" );
02678 for( i=0 ; i<loop_size ; i++ )
02679 eu_used[i] = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02680
02681 for( i=0 ; i<loop_size ; i++ )
02682 bu_ptbl_rm( &eu_tbl , (long *)eu_used[i] );
02683
02684 bu_free( (char *)eu_used , "edge used list" );
02685
02686
02687 eu_tmp = nmg_find_e( (*(struct vertex **)BU_PTBL_GET( &vert_tbl, 0 )), (*(struct vertex **)BU_PTBL_GET( &vert_tbl, loop_size-1 )), (struct shell *)NULL, (struct edge *)NULL );
02688 if( eu_tmp )
02689 {
02690 if( eu_tmp->radial_p != eu_tmp->eumate_p )
02691 {
02692 for( i=0 ; i<BU_PTBL_END( &eu_tbl ) ; i++ )
02693 {
02694 struct edgeuse *eu2;
02695
02696 eu2 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl, i );
02697 if( EDGESADJ( eu2, eu_tmp ) )
02698 {
02699 bu_ptbl_rm( &eu_tbl , (long *)eu2 );
02700 break;
02701 }
02702 }
02703 }
02704 }
02705
02706
02707 found_face = 1;
02708 give_up_on_face = 1;
02709 }
02710
02711
02712 start_index = -1;
02713 end_index = -1;
02714 while( !found_face )
02715 {
02716
02717 (void)bu_ptbl_reset( &vert_tbl );
02718
02719 if( end_index == 0 )
02720 {
02721 give_up_on_face = 1;
02722 break;
02723 }
02724 start_index++;
02725 end_index = start_index + 1;
02726 if( end_index == loop_size )
02727 end_index = 0;
02728
02729
02730 eu1 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[start_index] );
02731 bu_ptbl_ins( &vert_tbl , (long *)&eu1->vu_p->v_p );
02732
02733 eu2 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[end_index] );
02734 bu_ptbl_ins( &vert_tbl , (long *)&eu2->vu_p->v_p );
02735
02736 edges_used = 2;
02737
02738 while( bn_3pts_collinear(
02739 eu1->vu_p->v_p->vg_p->coord,
02740 eu2->vu_p->v_p->vg_p->coord,
02741 eu2->eumate_p->vu_p->v_p->vg_p->coord,
02742 tol ) && edges_used < loop_size )
02743 {
02744
02745 end_index++;
02746 if( end_index == loop_size )
02747 end_index = 0;
02748 eu1 = eu2;
02749 eu2 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[end_index]);
02750 bu_ptbl_ins( &vert_tbl , (long *)&eu2->vu_p->v_p );
02751 edges_used++;
02752 }
02753
02754 found_face = 1;
02755 #if 0
02756
02757 vfirst = (*(struct vertex **)BU_PTBL_GET( &vert_tbl, 0 ));
02758 vlast = (*(struct vertex **)BU_PTBL_GET( &vert_tbl, edges_used-1 ));
02759 eu_tmp = nmg_find_e( vfirst, vlast, (struct shell *)NULL, (struct edge *)NULL );
02760 if( eu_tmp )
02761 {
02762 if( eu_tmp->radial_p != eu_tmp->eumate_p )
02763 found_face = 0;
02764 }
02765 #endif
02766
02767 }
02768
02769 if( give_up_on_face )
02770 {
02771 loop_size = 0;
02772 start_loop = -1;
02773 break;
02774 }
02775
02776
02777 bu_ptbl_ins( &vert_tbl , (long *)&eu2->eumate_p->vu_p->v_p );
02778
02779
02780 eu_used = (struct edgeuse **)bu_calloc( edges_used , sizeof( struct edguse *) , "edges used list" );
02781 for( i=0 ; i<edges_used ; i++ )
02782 eu_used[i] = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02783
02784
02785 fu = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR(&vert_tbl) , edges_used+1 );
02786
02787 for( i=0 ; i<edges_used ; i++ )
02788 bu_ptbl_rm( &eu_tbl , (long *)eu_used[i] );
02789
02790 if( nmg_loop_plane_area( BU_LIST_FIRST( loopuse , &fu->lu_hd ) , pl2 ) < 0.0 )
02791 {
02792 bu_log( "Failed planeeq\n" );
02793 nmg_kfu( fu );
02794 }
02795 else
02796 {
02797 nmg_face_g( fu , pl2 );
02798
02799
02800 found = 0;
02801 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
02802 {
02803 NMG_CK_LOOPUSE( lu );
02804 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) ==
02805 NMG_VERTEXUSE_MAGIC )
02806 continue;
02807 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
02808 {
02809 NMG_CK_EDGEUSE( eu );
02810 if( eu->vu_p->v_p == (*(struct vertex **)BU_PTBL_GET( &vert_tbl , 0 ))
02811 && eu->eumate_p->vu_p->v_p == (*(struct vertex **)BU_PTBL_GET( &vert_tbl , edges_used) ) )
02812 {
02813 eu_new = eu;
02814 found = 1;
02815 break;
02816 }
02817 else if( eu->vu_p->v_p == (*(struct vertex **)BU_PTBL_GET( &vert_tbl , edges_used))
02818 && eu->eumate_p->vu_p->v_p == (*(struct vertex **)BU_PTBL_GET( &vert_tbl , 0 ) ) )
02819 {
02820 eu_new = eu->eumate_p;
02821 found = 1;
02822 break;
02823 }
02824
02825 }
02826 if( found )
02827 break;
02828 }
02829
02830 if( eu_new->radial_p == eu_new->eumate_p )
02831 bu_ptbl_ins( &eu_tbl , (long *)eu_new );
02832 else
02833 {
02834 struct edgeuse *eu_tmp;
02835
02836
02837 for( i=0 ; i<BU_PTBL_END( &eu_tbl ) ; i++ )
02838 {
02839 eu_tmp = (struct edgeuse *)BU_PTBL_GET( &eu_tbl, i );
02840 if( eu_tmp->vu_p->v_p == eu_new->vu_p->v_p &&
02841 eu_tmp->eumate_p->vu_p->v_p == eu_new->eumate_p->vu_p->v_p )
02842 {
02843 bu_ptbl_rm( &eu_tbl , (long *)eu_tmp );
02844 break;
02845 }
02846 }
02847 }
02848 }
02849
02850 bu_free( (char *)eu_used , "edge used list" );
02851
02852
02853 loop_size = 0;
02854 start_loop = -1;
02855 while( loop_size < 3 && start_loop < BU_PTBL_END( &eu_tbl )-3 )
02856 order_tbl( &eu_tbl, ++start_loop , &index , BU_PTBL_END( &eu_tbl ) , &loop_size );
02857 }
02858
02859 if( give_up_on_face )
02860 continue;
02861
02862 if( loop_size == 2 )
02863 {
02864 bu_ptbl_reset( &vert_tbl );
02865 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[0] );
02866 (void)bu_ptbl_ins( &vert_tbl , (long *)&eu->vu_p->v_p);
02867 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[1] );
02868 (void)bu_ptbl_ins( &vert_tbl , (long *)&eu->vu_p->v_p);
02869 (void)bu_ptbl_ins( &vert_tbl , (long *)&eu->eumate_p->vu_p->v_p);
02870 if( !bn_3pts_collinear(
02871 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 0 )))->vg_p->coord,
02872 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 1 )))->vg_p->coord,
02873 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 2 )))->vg_p->coord,
02874 tol ) )
02875 {
02876 fu = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR(&vert_tbl) , 3 );
02877 if( nmg_calc_face_g( fu ) )
02878 {
02879 bu_log( "Failed planeeq\n" );
02880 nmg_kfu( fu );
02881 }
02882 }
02883 else
02884 bu_log( "Not makeing face, edges are collinear!\n" );
02885
02886 loop_size = 0;
02887 continue;
02888 }
02889 else if( loop_size < 2 )
02890 {
02891 loop_size = 0;
02892 continue;
02893 }
02894
02895
02896 bu_ptbl_reset( &vert_tbl );
02897 for( i=0 ; i<3 ; i++ )
02898 {
02899 eu = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[i] );
02900 (void)bu_ptbl_ins( &vert_tbl , (long *)&eu->vu_p->v_p);
02901 }
02902
02903 if( !bn_3pts_collinear(
02904 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 0 )))->vg_p->coord,
02905 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 1 )))->vg_p->coord,
02906 ((*(struct vertex **)BU_PTBL_GET( &vert_tbl , 2 )))->vg_p->coord,
02907 tol ) )
02908 {
02909
02910
02911 fu = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR(&vert_tbl) , 3 );
02912 if( nmg_calc_face_g( fu ) )
02913 bu_log( "Failed planeeq\n" );
02914
02915 }
02916 else
02917 bu_log( "Not makeing face, edges are collinear!\n" );
02918
02919
02920 {
02921 struct edgeuse *eu1,*eu2,*eu3;
02922
02923 eu1 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[0] );
02924 eu2 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[1] );
02925 eu3 = (struct edgeuse *)BU_PTBL_GET( &eu_tbl , index[2] );
02926 bu_ptbl_rm( &eu_tbl , (long *)eu1 );
02927 bu_ptbl_rm( &eu_tbl , (long *)eu2 );
02928 bu_ptbl_rm( &eu_tbl , (long *)eu3 );
02929 }
02930 }
02931
02932
02933 bu_free( (char *)index , "index" );
02934 bu_ptbl_free( &eu_tbl );
02935 bu_ptbl_free( &vert_tbl );
02936
02937 }
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955 struct shell *
02956 nmg_dup_shell(struct shell *s, long int ***trans_tbl, const struct bn_tol *tol)
02957 {
02958
02959 struct model *m;
02960 struct shell *new_s;
02961 struct faceuse *fu;
02962 struct loopuse *lu,*new_lu;
02963 struct edgeuse *eu;
02964 struct faceuse *new_fu;
02965 struct bu_ptbl faces;
02966 int tbl_size;
02967
02968 if( rt_g.NMG_debug & DEBUG_BASIC)
02969 bu_log( "nmg_dup_shell( s = x%x , trans_tbl = x%x )\n" , s , trans_tbl );
02970
02971 NMG_CK_SHELL( s );
02972 BN_CK_TOL( tol );
02973
02974 m = nmg_find_model( (long *)s );
02975
02976
02977 tbl_size = m->maxindex * 3;
02978 (*trans_tbl) = (long **)bu_calloc(tbl_size, sizeof(long *),
02979 "nmg_dup_shell trans_tbl" );
02980
02981 bu_ptbl_init( &faces , 64, " &faces ");
02982
02983 new_s = nmg_msv( s->r_p );
02984 if( s->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
02985 NMG_INDEX_ASSIGN( (*trans_tbl) , s , (long *)new_s );
02986 if( new_s->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
02987 NMG_INDEX_ASSIGN( (*trans_tbl) , new_s , (long *)s );
02988
02989
02990 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
02991 {
02992 NMG_CK_FACEUSE( fu );
02993 if( fu->orientation == OT_SAME )
02994 {
02995 new_fu = (struct faceuse *)NULL;
02996 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
02997 {
02998 NMG_CK_LOOPUSE( lu );
02999 if( new_fu )
03000 {
03001 new_lu = nmg_dup_loop( lu , &new_fu->l.magic , (*trans_tbl) );
03002 if( lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03003 NMG_INDEX_ASSIGN( (*trans_tbl) , lu , (long *)new_lu );
03004 if( new_lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03005 NMG_INDEX_ASSIGN( (*trans_tbl) , new_lu , (long *)lu );
03006 }
03007 else
03008 {
03009 new_lu = nmg_dup_loop( lu , &new_s->l.magic , (*trans_tbl) );
03010 if( new_lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03011 NMG_INDEX_ASSIGN( (*trans_tbl) , lu , (long *)new_lu );
03012 if( lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03013 NMG_INDEX_ASSIGN( (*trans_tbl) , new_lu , (long *)lu );
03014 new_fu = nmg_mf( new_lu );
03015 if( lu->orientation == OT_OPPOSITE )
03016 {
03017
03018 new_lu->orientation = OT_OPPOSITE;
03019 new_lu->lumate_p->orientation = OT_OPPOSITE;
03020 }
03021 if( fu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03022 NMG_INDEX_ASSIGN( (*trans_tbl) , fu , (long *)new_fu );
03023 if( new_fu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03024 NMG_INDEX_ASSIGN( (*trans_tbl) , new_fu , (long *)fu );
03025 if( fu->fumate_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03026 NMG_INDEX_ASSIGN( (*trans_tbl) , fu->fumate_p , (long *)new_fu->fumate_p );
03027 if( new_fu->fumate_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03028 NMG_INDEX_ASSIGN( (*trans_tbl) , new_fu->fumate_p , (long *)fu->fumate_p );
03029 if( fu->f_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03030 NMG_INDEX_ASSIGN( (*trans_tbl) , fu->f_p , (long *)new_fu->f_p );
03031 if( new_fu->f_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03032 NMG_INDEX_ASSIGN( (*trans_tbl) , new_fu->f_p , (long *)fu->f_p );
03033 }
03034 }
03035 if (fu->f_p->g.plane_p)
03036 {
03037 #if 1
03038
03039 plane_t n;
03040 NMG_GET_FU_PLANE( n, fu );
03041 nmg_face_g(new_fu, n);
03042 #else
03043
03044 nmg_jfg( fu, new_fu );
03045 #endif
03046
03047
03048 if( fu->f_p->g.plane_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03049 NMG_INDEX_ASSIGN( (*trans_tbl) , fu->f_p->g.plane_p , (long *)new_fu->f_p->g.plane_p );
03050 if( new_fu->f_p->g.plane_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03051 NMG_INDEX_ASSIGN( (*trans_tbl) , new_fu->f_p->g.plane_p , (long *)fu->f_p->g.plane_p );
03052 }
03053 new_fu->orientation = fu->orientation;
03054 new_fu->fumate_p->orientation = fu->fumate_p->orientation;
03055 bu_ptbl_ins( &faces , (long *)new_fu );
03056 }
03057 }
03058
03059
03060 nmg_gluefaces( (struct faceuse **)BU_PTBL_BASEADDR( &faces) , BU_PTBL_END( &faces ), tol );
03061 bu_ptbl_free( &faces );
03062
03063
03064 for( BU_LIST_FOR( lu , loopuse , &s->lu_hd ) )
03065 {
03066 NMG_CK_LOOPUSE( lu );
03067 new_lu = nmg_dup_loop( lu , &new_s->l.magic , (*trans_tbl) );
03068 if( lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03069 NMG_INDEX_ASSIGN( (*trans_tbl) , lu , (long *)new_lu );
03070 if( new_lu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03071 NMG_INDEX_ASSIGN( (*trans_tbl) , new_lu , (long *)lu );
03072 }
03073
03074
03075 for( BU_LIST_FOR( eu , edgeuse , &s->eu_hd ) )
03076 {
03077 struct vertex *old_v1,*old_v2,*new_v1,*new_v2;
03078 struct edgeuse *new_eu;
03079
03080 NMG_CK_EDGEUSE( eu );
03081 NMG_CK_VERTEXUSE( eu->vu_p );
03082 NMG_CK_VERTEX( eu->vu_p->v_p );
03083 NMG_CK_EDGEUSE( eu->eumate_p );
03084 NMG_CK_VERTEXUSE( eu->eumate_p->vu_p );
03085 NMG_CK_VERTEX( eu->eumate_p->vu_p->v_p );
03086
03087 old_v1 = eu->vu_p->v_p;
03088 new_v1 = NMG_INDEX_GETP(vertex, (*trans_tbl), old_v1);
03089 old_v2 = eu->eumate_p->vu_p->v_p;
03090 new_v2 = NMG_INDEX_GETP(vertex, (*trans_tbl), old_v2);
03091
03092
03093 new_eu = nmg_me( new_v1 , new_v2 , new_s );
03094 if( eu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03095 NMG_INDEX_ASSIGN( (*trans_tbl) , eu , (long *)new_eu );
03096 if( new_eu->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03097 NMG_INDEX_ASSIGN( (*trans_tbl) , new_eu , (long *)eu );
03098
03099 new_v1 = new_eu->vu_p->v_p;
03100 if( old_v1->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03101 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v1 , (long *)new_v1 );
03102 if( new_v1->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03103 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v1 , (long *)old_v1 );
03104 if( !new_v1->vg_p )
03105 {
03106 nmg_vertex_gv( new_v1 , old_v1->vg_p->coord );
03107 if( old_v1->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03108 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v1->vg_p , (long *)new_v1->vg_p );
03109 if( new_v1->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03110 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v1->vg_p , (long *)old_v1->vg_p );
03111 }
03112
03113 new_v2 = new_eu->eumate_p->vu_p->v_p;
03114 if( old_v2->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03115 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v2 , (long *)new_v2 );
03116 if( new_v2->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03117 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v2 , (long *)old_v2 );
03118 if( !new_v2->vg_p )
03119 {
03120 nmg_vertex_gv( new_v2 , old_v2->vg_p->coord );
03121 if( old_v2->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03122 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v2->vg_p , (long *)new_v2->vg_p );
03123 if( new_v2->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03124 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v2->vg_p , (long *)old_v2->vg_p );
03125 }
03126
03127 }
03128
03129 #if 0
03130
03131
03132
03133
03134 if( s->vu_p )
03135 {
03136 old_vu = s->vu_p;
03137 NMG_CK_VERTEXUSE( old_vu );
03138 old_v = old_vu->v_p;
03139 NMG_CK_VERTEX( old_v );
03140 new_v = NMG_INDEX_GETP(vertex, (*trans_tbl), old_v);
03141 if( new_v )
03142 {
03143
03144 if( new_s->vu_p )
03145 (void )nmg_kvu( new_s->vu_p );
03146 new_s->vu_p = nmg_mvu( new_v , (long *)new_s , m );
03147 }
03148 else
03149 {
03150
03151 new_s->vu_p = nmg_mvvu( (long *)new_s , m );
03152 new_v = new_s->vu_p->v_p;
03153
03154
03155 if( old_v->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03156 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v , (long *)new_v );
03157 if( new_v->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03158 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v , (long *)old_v );
03159
03160
03161 nmg_vertex_gv( new_v , old_v->vg_p->coord );
03162 if( old_v->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03163 NMG_INDEX_ASSIGN( (*trans_tbl) , old_v->vg_p , (long *)new_v->vg_p );
03164 if( new_v->vg_p->index >= tbl_size ) rt_bomb( "nmg_dup_shell: trans table exceeded\n" );
03165 NMG_INDEX_ASSIGN( (*trans_tbl) , new_v->vg_p , (long *)old_v->vg_p );
03166 }
03167 }
03168 #endif
03169
03170 return( new_s );
03171 }
03172
03173
03174
03175 #define NMG_PUSH( _ptr , _stack ) bu_ptbl_ins( _stack , (long *) _ptr );
03176
03177 struct edgeuse
03178 *nmg_pop_eu(struct bu_ptbl *stack)
03179 {
03180 struct edgeuse *eu;
03181
03182
03183 if( BU_PTBL_END( stack ) == 0 )
03184 return( (struct edgeuse *)NULL );
03185
03186
03187 eu = (struct edgeuse *)BU_PTBL_GET( stack , BU_PTBL_END( stack )-1 );
03188
03189
03190 bu_ptbl_rm( stack , (long *)eu );
03191
03192 return( eu );
03193 }
03194
03195 void
03196 nmg_reverse_radials(struct faceuse *fu, const struct bn_tol *tol)
03197 {
03198 struct loopuse *lu;
03199
03200 if( rt_g.NMG_debug & DEBUG_BASIC )
03201 bu_log( "nmg_reverse_radials( fu = x%x )\n" , fu );
03202
03203 NMG_CK_FACEUSE( fu );
03204 BN_CK_TOL( tol );
03205
03206 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
03207 {
03208 struct edgeuse *eu;
03209 struct edgeuse *eu_radial;
03210 struct edgeuse *eumate;
03211 struct edgeuse *eumate_radial;
03212
03213 NMG_CK_LOOPUSE( lu );
03214
03215 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03216 continue;
03217
03218 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03219 {
03220 eu_radial = eu->radial_p;
03221 eumate = eu->eumate_p;
03222 eumate_radial = eumate->radial_p;
03223
03224
03225 if( eu_radial == eumate )
03226 continue;
03227
03228
03229
03230
03231
03232
03233 eu_radial->radial_p = eumate;
03234 eu->radial_p = eumate_radial;
03235 eumate_radial->radial_p = eu;
03236 eumate->radial_p = eu_radial;
03237 }
03238 }
03239 }
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249 void
03250 nmg_reverse_face_and_radials(struct faceuse *fu, const struct bn_tol *tol)
03251 {
03252 struct loopuse *lu;
03253
03254 if( rt_g.NMG_debug & DEBUG_BASIC )
03255 bu_log( "nmg_reverse_face_and_radials( fu = x%x )\n" , fu );
03256
03257 NMG_CK_FACEUSE( fu );
03258 BN_CK_TOL( tol );
03259
03260
03261 nmg_reverse_face( fu );
03262
03263 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
03264 {
03265 struct edgeuse *eu;
03266 struct edgeuse *eu_radial;
03267 struct edgeuse *eumate;
03268 struct edgeuse *eumate_radial;
03269
03270 NMG_CK_LOOPUSE( lu );
03271
03272 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03273 continue;
03274
03275 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03276 {
03277 eu_radial = eu->radial_p;
03278 eumate = eu->eumate_p;
03279 eumate_radial = eumate->radial_p;
03280
03281
03282 if( eu_radial == eumate )
03283 continue;
03284
03285
03286
03287
03288
03289
03290 eu_radial->radial_p = eumate;
03291 eu->radial_p = eumate_radial;
03292 eumate_radial->radial_p = eu;
03293 eumate->radial_p = eu_radial;
03294 }
03295 }
03296 }
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311 int
03312 nmg_shell_is_void(const struct shell *s)
03313 {
03314 struct model *m;
03315 struct face *f;
03316 struct faceuse *fu;
03317 vect_t normal;
03318 int dir;
03319 long *flags;
03320
03321 NMG_CK_SHELL( s );
03322
03323 m = nmg_find_model( &s->l.magic );
03324 NMG_CK_MODEL( m );
03325
03326 flags = (long *)bu_calloc( m->maxindex , sizeof( long ) , "nmg_shell_is_void: flags " );
03327
03328 f = nmg_find_top_face( s, &dir , flags );
03329
03330 bu_free( (char *)flags , "nmg_shell_is_void: flags" );
03331
03332 if( f == (struct face *)NULL )
03333 return( -1 );
03334
03335 NMG_CK_FACE( f );
03336 NMG_CK_FACE_G_PLANE( f->g.plane_p );
03337 fu = f->fu_p;
03338 NMG_CK_FACEUSE( fu );
03339
03340 if( fu->orientation != OT_SAME )
03341 fu = fu->fumate_p;
03342 if( fu->orientation != OT_SAME )
03343 return( -1 );
03344
03345 NMG_GET_FU_NORMAL( normal , fu );
03346
03347 if( normal[dir] == 0.0 )
03348 return( -1 );
03349 if( normal[dir] < 0.0)
03350 return( 1 );
03351 else
03352 return( 0 );
03353 }
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365 void
03366 nmg_propagate_normals(struct faceuse *fu_in, long int *flags, const struct bn_tol *tol)
03367 {
03368 struct bu_ptbl stack;
03369 struct loopuse *lu;
03370 struct edgeuse *eu,*eu1;
03371 struct faceuse *fu;
03372
03373 if( rt_g.NMG_debug & DEBUG_BASIC )
03374 bu_log( "nmg_propagate_normals( fu_in = x%x , flags = x%x )\n" , fu_in , flags );
03375
03376 NMG_CK_FACEUSE( fu_in );
03377 BN_CK_TOL( tol );
03378
03379 fu = fu_in;
03380 if( fu->orientation != OT_SAME )
03381 fu = fu->fumate_p;
03382 if( fu->orientation != OT_SAME )
03383 {
03384 bu_log( "nmg_propagate_normals: Could not find OT_SAME orientation of faceuse x%x\n" , fu_in );
03385 return;
03386 }
03387
03388
03389 NMG_INDEX_SET( flags , fu->f_p );
03390
03391
03392 bu_ptbl_init( &stack , 64, " &stack ");
03393
03394
03395 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
03396 {
03397 NMG_CK_LOOPUSE( lu );
03398 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03399 continue;
03400 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
03401 {
03402
03403 if( eu->radial_p->eumate_p != eu )
03404 NMG_PUSH( eu , &stack );
03405 }
03406 }
03407
03408
03409
03410
03411 while( (eu1 = nmg_pop_eu( &stack )) != (struct edgeuse *)NULL )
03412 {
03413
03414
03415
03416 NMG_CK_EDGEUSE( eu1 );
03417
03418 eu = eu1->radial_p;
03419 NMG_CK_EDGEUSE( eu );
03420
03421
03422 fu = nmg_find_fu_of_eu( eu );
03423 if( !fu )
03424 continue;
03425
03426 NMG_CK_FACEUSE( fu );
03427
03428
03429 if( NMG_INDEX_TEST_AND_SET( flags , fu->f_p ) )
03430 {
03431 if( rt_g.NMG_debug & DEBUG_BASIC )
03432 bu_log( "nmg_propagate_normals: checking fu x%x, eu = x%x, eu1 = x%x\n" , fu, eu, eu1 );
03433
03434 if( fu->orientation == OT_SAME )
03435 {
03436 if( eu1->vu_p->v_p == eu->vu_p->v_p &&
03437 eu1->eumate_p->vu_p->v_p == eu->eumate_p->vu_p->v_p )
03438 {
03439
03440
03441
03442 nmg_reverse_face_and_radials( fu , tol );
03443 }
03444
03445 }
03446 else if( fu->orientation == OT_OPPOSITE )
03447 {
03448 if( eu1->vu_p->v_p == eu->vu_p->v_p &&
03449 eu1->eumate_p->vu_p->v_p == eu->eumate_p->vu_p->v_p )
03450 {
03451
03452 nmg_reverse_radials( fu , tol );
03453 }
03454 else
03455 {
03456
03457 nmg_reverse_face( fu );
03458 }
03459 }
03460 else
03461 {
03462 bu_log( "nmg_propagate_normals: found an unoriented face!!!!\n" );
03463 nmg_pr_fu_briefly( fu, "" );
03464 rt_bomb( "nmg_propagate_normals: found an unoriented face!!!!\n" );
03465 }
03466
03467
03468 if( fu->orientation != OT_SAME )
03469 fu = fu->fumate_p;
03470
03471
03472 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
03473 {
03474 NMG_CK_LOOPUSE( lu );
03475 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03476 continue;
03477 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
03478 {
03479
03480 if( eu->radial_p->eumate_p != eu )
03481 NMG_PUSH( eu , &stack );
03482 }
03483 }
03484 }
03485 }
03486
03487
03488 bu_ptbl_free( &stack );
03489 }
03490
03491
03492
03493
03494
03495
03496
03497 static void
03498 nmg_disconnect_shells(struct nmgregion *r)
03499 {
03500 struct shell *s1;
03501 struct bu_ptbl edges;
03502 int count=0;
03503 int i;
03504
03505 NMG_CK_REGION( r );
03506
03507
03508 for( BU_LIST_FOR( s1, shell, &r->s_hd ) )
03509 count++;
03510
03511
03512 if( count < 2 )
03513 return;
03514
03515
03516 nmg_edge_tabulate( &edges, &r->l.magic );
03517
03518
03519 for( i=0 ; i<BU_PTBL_END( &edges ) ; i++ )
03520 {
03521 struct edge *e;
03522 struct edgeuse *eu;
03523 struct edgeuse *eu1;
03524 struct shell *needs_disconnect=(struct shell *)NULL;
03525
03526 e = (struct edge *)BU_PTBL_GET( &edges, i );
03527 NMG_CK_EDGE( e );
03528
03529
03530 eu = e->eu_p;
03531 s1 = nmg_find_s_of_eu( eu );
03532
03533
03534 eu1 = eu->eumate_p->radial_p;
03535 while( eu1 != eu && eu1 != eu->eumate_p )
03536 {
03537 struct shell *s2;
03538
03539 if( (s2 = nmg_find_s_of_eu( eu1 )) != s1 )
03540 {
03541 needs_disconnect = s2;
03542 break;
03543 }
03544 eu1 = eu1->eumate_p->radial_p;
03545 }
03546
03547 while( needs_disconnect )
03548 {
03549 struct edgeuse *eu2;
03550 struct edgeuse *start_eu;
03551 struct edgeuse *last;
03552 int last_orientation;
03553
03554
03555 start_eu = eu1->radial_p;
03556 nmg_unglueedge( eu1 );
03557 last = eu1;
03558 last_orientation = (nmg_find_fu_of_eu( eu1 ))->orientation;
03559
03560
03561 while( nmg_find_s_of_eu( start_eu ) == needs_disconnect )
03562 start_eu = start_eu->eumate_p->radial_p;
03563 eu2 = start_eu;
03564 do
03565 {
03566 struct edgeuse *next_eu;
03567 struct faceuse *fu2;
03568
03569
03570 next_eu = eu2->eumate_p->radial_p;
03571 if( nmg_find_s_of_eu( eu2 ) == needs_disconnect )
03572 {
03573
03574
03575 nmg_unglueedge( eu2 );
03576 fu2 = nmg_find_fu_of_eu( eu2 );
03577
03578
03579 if( fu2->orientation == last_orientation)
03580 {
03581 nmg_je( last, eu2 );
03582 last = eu2->eumate_p;
03583 last_orientation = fu2->fumate_p->orientation;
03584 }
03585 else
03586 {
03587 nmg_je( last, eu2->eumate_p );
03588 last_orientation = fu2->orientation;
03589 last = eu2;
03590 }
03591 }
03592 eu2 = next_eu;
03593 } while( eu2 != start_eu && eu2->eumate_p != start_eu );
03594
03595
03596 eu1 = eu->eumate_p->radial_p;
03597 needs_disconnect = (struct shell *)NULL;
03598 while( eu1 != eu && eu1 != eu->eumate_p )
03599 {
03600 struct shell *s2;
03601
03602 if( (s2 = nmg_find_s_of_eu( eu1 )) != s1 )
03603 {
03604 needs_disconnect = s2;
03605 break;
03606 }
03607 eu1 = eu1->eumate_p->radial_p;
03608 }
03609 }
03610
03611 }
03612 }
03613
03614
03615
03616
03617
03618
03619
03620 void
03621 nmg_connect_same_fu_orients(struct shell *s)
03622 {
03623 struct faceuse *fu;
03624
03625 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
03626 {
03627 struct loopuse *lu;
03628
03629 if( fu->orientation != OT_SAME )
03630 continue;
03631
03632 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
03633 {
03634 struct edgeuse *eu;
03635
03636 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
03637 continue;
03638
03639 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03640 {
03641 struct faceuse *fu2;
03642 struct faceuse *fu3;
03643 struct edgeuse *eu2;
03644
03645 eu2 = eu->radial_p;
03646
03647 if( eu2 == eu->eumate_p )
03648 continue;
03649
03650 fu2 = nmg_find_fu_of_eu( eu2 );
03651 if( fu2->orientation == OT_SAME )
03652 continue;
03653
03654 fu3 = nmg_find_fu_of_eu( eu->eumate_p->radial_p );
03655 if( fu3->orientation == OT_OPPOSITE )
03656 continue;
03657 }
03658 }
03659 }
03660 }
03661
03662
03663
03664
03665
03666
03667
03668 void
03669 nmg_fix_decomposed_shell_normals(struct shell *s, const struct bn_tol *tol)
03670 {
03671 struct model *m;
03672 struct face *f_top;
03673 struct faceuse *fu;
03674 vect_t normal;
03675 int dir;
03676 int missed_faces;
03677 long *flags;
03678
03679 NMG_CK_SHELL( s );
03680 BN_CK_TOL( tol );
03681
03682 m = s->r_p->m_p;
03683 flags = (long *)bu_calloc( m->maxindex , sizeof( long ) , "nmg_fix_decomposed_shell_normals: flags" );
03684
03685 missed:
03686
03687 f_top = nmg_find_top_face( s, &dir , flags );
03688 if( f_top == (struct face *)NULL )
03689 {
03690 bu_log( "nmg_fix_decomposed_shell_normals: Could not get a top face from nmg_find_top_face()\n" );
03691 bu_log( "\tWARNING: continuing without fixing normals!!!!\n" );
03692 bu_free( (char *)flags, "nmg_fix_decomposed_shell_normals: flags" );
03693 return;
03694 }
03695 if( *f_top->g.magic_p != NMG_FACE_G_PLANE_MAGIC )
03696 {
03697 NMG_INDEX_SET( flags, f_top );
03698 goto missed;
03699 }
03700
03701 if( NMG_INDEX_TEST( flags, f_top ) )
03702 bu_log(" nmg_find_top_face returned a flagged face %x\n" , f_top );
03703
03704 NMG_CK_FACE( f_top );
03705 fu = f_top->fu_p;
03706 NMG_CK_FACEUSE( fu );
03707 if( fu->orientation != OT_SAME )
03708 fu = fu->fumate_p;
03709 if( fu->orientation != OT_SAME )
03710 {
03711 bu_log( "nmg_fix_decomposed_shell_normals: no OT_SAME use of top face\n" );
03712 bu_free( (char *)flags , "nmg_fix_decomposed_shell_normals: flags" );
03713 return;
03714 }
03715 NMG_GET_FU_NORMAL( normal , fu );
03716
03717 if( rt_g.NMG_debug & DEBUG_BASIC )
03718 {
03719 bu_log( "\tnmg_fix_decomposed_shell_normals: top face is x%x in %d direction, OT_SAME use is x%x\n", f_top, dir, fu );
03720 bu_log( "\toutward normal = ( %g %g %g )\n" , V3ARGS( normal ) );
03721 }
03722
03723
03724
03725 if( normal[dir] < 0.0 )
03726 {
03727 if( rt_g.NMG_debug & DEBUG_BASIC )
03728 bu_log( "nmg_fix_decomposed_shell_normals: reversing fu x%x\n" , fu );
03729
03730 nmg_reverse_face_and_radials( fu, tol );
03731 }
03732
03733
03734 fu = f_top->fu_p;
03735 if( fu->orientation != OT_SAME )
03736 fu = fu->fumate_p;
03737
03738 NMG_CK_FACEUSE( fu );
03739
03740
03741
03742
03743
03744 nmg_propagate_normals( fu , flags , tol );
03745
03746 if( rt_g.NMG_debug & DEBUG_BASIC )
03747 {
03748 vect_t new_norm;
03749
03750 NMG_GET_FU_NORMAL( new_norm , fu );
03751 bu_log( "nmg_fix_decomposed_shell_normals: After propagation top faceuse normal is ( %g %g %g )\n",
03752 V3ARGS( new_norm ) );
03753 }
03754
03755
03756 missed_faces = 0;
03757 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
03758 {
03759 NMG_CK_FACEUSE( fu );
03760 if( fu->orientation == OT_SAME )
03761 {
03762 if( !NMG_INDEX_TEST( flags , fu->f_p ) )
03763 missed_faces++;
03764 }
03765 }
03766
03767 if( missed_faces )
03768 {
03769 bu_log( "nmg_fix_decomposed_shell_normals: missed %d faces in shell x%x (was it decomposed?)\n",
03770 missed_faces, s );
03771 rt_bomb( "nmg_fix_decomposed_shell_normals: missed faces in shell (was it decomposed?)\n" );
03772 }
03773
03774 bu_free( (char *)flags, "flags" );
03775 }
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789 struct model *
03790 nmg_mk_model_from_region(struct nmgregion *r, int reindex)
03791 {
03792 struct model *m;
03793 struct bu_ptbl tbl;
03794 int i;
03795 int other_uses=0;
03796
03797 NMG_CK_REGION( r );
03798
03799
03800
03801 nmg_vertex_tabulate( &tbl, &r->l.magic );
03802
03803 for( i=0 ; i<BU_PTBL_END( &tbl ) ; i++ )
03804 {
03805 struct vertex *v;
03806 struct vertexuse *vu;
03807
03808 v = (struct vertex *)BU_PTBL_GET( &tbl, i );
03809 NMG_CK_VERTEX( v );
03810
03811 for( BU_LIST_FOR( vu, vertexuse, &v->vu_hd ) )
03812 {
03813 if( (nmg_find_s_of_vu( vu ))->r_p != r )
03814 {
03815 bu_log( "vertexuse x%x (v=x%x) at (%g %g %g) has use in another region\n",
03816 vu, v, V3ARGS( v->vg_p->coord ) );
03817 other_uses++;
03818 }
03819 }
03820 }
03821 bu_ptbl_free( &tbl );
03822
03823 nmg_edge_tabulate( &tbl, &r->l.magic );
03824 for( i=0 ; i<BU_PTBL_END( &tbl ) ; i++ )
03825 {
03826 struct edge *e;
03827 struct edgeuse *eu;
03828 struct edgeuse *eu1;
03829
03830 e = (struct edge *)BU_PTBL_GET( &tbl, i );
03831 NMG_CK_EDGE( e );
03832
03833 eu = e->eu_p;
03834 NMG_CK_EDGEUSE( eu );
03835
03836 eu1 = eu->radial_p->eumate_p;
03837 while( eu1 != eu )
03838 {
03839 if( (nmg_find_s_of_eu( eu1 ))->r_p != r )
03840 {
03841 bu_log( "edgeuse x%x (e=x%x) at (%g %g %g)<->(%g %g %g0 has use in another region\n",
03842 eu, e, V3ARGS( eu->vu_p->v_p->vg_p->coord ), V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
03843 other_uses++;
03844 }
03845 eu1 = eu1->radial_p->eumate_p;
03846 }
03847 }
03848 bu_ptbl_free( &tbl );
03849
03850 if( other_uses )
03851 {
03852 return( (struct model *)NULL );
03853 }
03854
03855 m = nmg_mm();
03856
03857 BU_LIST_DEQUEUE( &r->l );
03858
03859 BU_LIST_INSERT( &m->r_hd, &r->l );
03860
03861 r->m_p = m;
03862
03863 if( reindex )
03864 nmg_m_reindex( m , 0 );
03865 else
03866 m->maxindex = nmg_find_max_index( m ) + 1;
03867
03868 return( m );
03869 }
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884 void
03885 nmg_fix_normals(struct shell *s_orig, const struct bn_tol *tol)
03886 {
03887 struct model *tmp_m;
03888 struct model *m;
03889 struct shell *dup_s;
03890 struct shell *s1;
03891 struct nmgregion *tmp_r;
03892 struct faceuse *fu;
03893 struct bu_ptbl reverse;
03894 int shell_count;
03895 long **trans_tbl;
03896
03897 if( rt_g.NMG_debug & DEBUG_BASIC )
03898 bu_log( "nmg_fix_normals( s = x%x )\n" , s_orig );
03899
03900 NMG_CK_SHELL( s_orig );
03901 BN_CK_TOL( tol );
03902
03903
03904
03905
03906 for( BU_LIST_FOR( fu, faceuse, &s_orig->fu_hd ) )
03907 {
03908 struct face *f;
03909
03910 NMG_CK_FACEUSE( fu );
03911
03912 if( fu->orientation != OT_SAME )
03913 continue;
03914
03915 f = fu->f_p;
03916
03917 if( !f->g.magic_p )
03918 {
03919 bu_log( "nmg_fix_normals failed, found a face with no geometry (x%x)\n", f );
03920 return;
03921 }
03922
03923 if( *f->g.magic_p != NMG_FACE_G_PLANE_MAGIC )
03924 {
03925 bu_log( "nmg_fix_normals: non-planar face found (x%x)\n", f );
03926 bu_log( " cannot fix normals\n" );
03927 return;
03928 }
03929 }
03930
03931 m = s_orig->r_p->m_p;
03932
03933
03934 tmp_r = nmg_mrsv( m );
03935
03936
03937 (void)nmg_ks( BU_LIST_FIRST( shell, &tmp_r->s_hd ) );
03938
03939
03940 dup_s = nmg_dup_shell( s_orig, &trans_tbl, tol );
03941
03942
03943 nmg_mv_shell_to_region( dup_s, tmp_r );
03944
03945
03946 tmp_m = nmg_mk_model_from_region( tmp_r, 0 );
03947 nmg_rebound( tmp_m, tol );
03948
03949
03950 shell_count = nmg_decompose_shell( dup_s, tol );
03951
03952 if( shell_count == 1 )
03953 {
03954
03955 (void)nmg_km( tmp_m );
03956 bu_free( (char *)trans_tbl, "translate table" );
03957 nmg_connect_same_fu_orients( s_orig );
03958 nmg_fix_decomposed_shell_normals( s_orig, tol );
03959 return;
03960 }
03961
03962
03963 nmg_disconnect_shells( tmp_r );
03964
03965
03966 for( BU_LIST_FOR( s1, shell, &tmp_r->s_hd ) )
03967 nmg_connect_same_fu_orients( s1 );
03968
03969
03970
03971
03972
03973 for( BU_LIST_FOR( s1, shell, &tmp_r->s_hd ) )
03974 nmg_fix_decomposed_shell_normals( s1, tol );
03975
03976
03977 bu_ptbl_init( &reverse, 8, "Ptbl for nmg_fix_normals" );
03978
03979
03980 for( BU_LIST_FOR( s1, shell, &tmp_r->s_hd ) )
03981 {
03982 struct shell *s2;
03983 int inner_count=0;
03984
03985 for( BU_LIST_FOR( s2, shell, &tmp_r->s_hd ) )
03986 {
03987 int class;
03988
03989 if( s1 == s2 )
03990 continue;
03991
03992 class = nmg_classify_s_vs_s( s1, s2, tol );
03993 if( class == NMG_CLASS_AinB )
03994 inner_count++;
03995 else if( class == NMG_CLASS_Unknown )
03996 {
03997 bu_log( "nmg_fix_normals: nmg_classify_s_vs_s() failed for shells x%x and x%x\n", s1, s2 );
03998 bu_log( " Continueing anyway (shell is likely to have incorrectly oriented normals)\n" );
03999 }
04000 }
04001
04002 if( inner_count % 2 )
04003 {
04004
04005 bu_ptbl_ins( &reverse, (long *)s1 );
04006 }
04007 }
04008
04009
04010 nmg_connect_same_fu_orients( s_orig );
04011
04012 for( BU_LIST_FOR( s1, shell, &tmp_r->s_hd ) )
04013 {
04014 int reversed;
04015
04016 if( bu_ptbl_locate( &reverse, (long *)s1 ) == (-1 ))
04017 reversed = 0;
04018 else
04019 reversed = 1;
04020
04021 for( BU_LIST_FOR( fu, faceuse, &s1->fu_hd ) )
04022 {
04023 struct faceuse *fu_in_s;
04024 vect_t normal;
04025 vect_t normal_in_s;
04026
04027 if( fu->orientation != OT_SAME )
04028 continue;
04029
04030 fu_in_s = NMG_INDEX_GETP( faceuse, trans_tbl, fu );
04031 if( !fu_in_s )
04032 {
04033 bu_log( "fu x%x does not have corrrespondence in original shell\n", fu );
04034 nmg_pr_fu_briefly( fu, "" );
04035 continue;
04036 }
04037 if( fu_in_s->orientation != OT_SAME )
04038 fu_in_s = fu_in_s->fumate_p;
04039
04040 NMG_GET_FU_NORMAL( normal, fu );
04041 if( reversed )
04042 VREVERSE( normal, normal )
04043
04044 NMG_GET_FU_NORMAL( normal_in_s, fu_in_s );
04045
04046 if( VDOT( normal, normal_in_s ) < 0.0 )
04047 {
04048 nmg_reverse_face_and_radials( fu_in_s, tol );
04049 }
04050 }
04051 }
04052
04053 bu_ptbl_free( &reverse );
04054 bu_free( (char *)trans_tbl, "translation table" );
04055
04056 nmg_km( tmp_m );
04057 }
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 int
04074 nmg_break_long_edges(struct shell *s, const struct bn_tol *tol)
04075 {
04076 struct faceuse *fu;
04077 struct loopuse *lu;
04078 struct edgeuse *eu;
04079 int split_count=0;
04080
04081 if( rt_g.NMG_debug & DEBUG_BASIC )
04082 bu_log( "nmg_break_long_edges( s = x%x )\n" , s );
04083
04084 NMG_CK_SHELL( s );
04085 BN_CK_TOL( tol );
04086
04087
04088 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
04089 {
04090 NMG_CK_FACEUSE( fu );
04091
04092 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04093 {
04094 NMG_CK_LOOPUSE( lu );
04095
04096
04097 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
04098 continue;
04099
04100 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
04101 {
04102 struct vertexuse *vu;
04103
04104 NMG_CK_EDGEUSE( eu );
04105
04106
04107 for( BU_LIST_FOR( vu , vertexuse , &eu->vu_p->v_p->vu_hd ) )
04108 {
04109 struct edgeuse *eu1;
04110
04111 NMG_CK_VERTEXUSE( vu );
04112
04113
04114 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
04115 continue;
04116
04117 eu1 = vu->up.eu_p;
04118
04119
04120 if( eu1 == eu )
04121 continue;
04122
04123
04124 if( eu1->eumate_p->vu_p->v_p == eu->eumate_p->vu_p->v_p )
04125 continue;
04126
04127
04128 eu1 = eu1->eumate_p;
04129
04130
04131 if( bn_3pts_collinear( eu->vu_p->v_p->vg_p->coord ,
04132 eu->eumate_p->vu_p->v_p->vg_p->coord ,
04133 eu1->vu_p->v_p->vg_p->coord , tol ) )
04134 {
04135
04136
04137 vect_t v0,v1;
04138
04139 VSUB2( v0 , eu->eumate_p->vu_p->v_p->vg_p->coord , eu->vu_p->v_p->vg_p->coord );
04140 VSUB2( v1 , eu1->eumate_p->vu_p->v_p->vg_p->coord , eu1->vu_p->v_p->vg_p->coord );
04141
04142 if (MAGSQ( v0 ) > MAGSQ( v1 ) && VDOT( v0 , v1 ) < 0.0 )
04143 {
04144 if( rt_g.NMG_debug & DEBUG_BASIC )
04145 {
04146 bu_log( "Breaking edge from ( %f %f %f ) to ( %f %f %f ) at ( %f %f %f )\n",
04147 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
04148 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ),
04149 V3ARGS( eu1->vu_p->v_p->vg_p->coord ) );
04150 }
04151 (void) nmg_ebreak(eu1->vu_p->v_p, eu);
04152 split_count++;
04153 }
04154 else if( rt_g.NMG_debug & DEBUG_BASIC )
04155 {
04156 bu_log( "Not splitting collinear edges x%x and x%x:\n", eu , eu1 );
04157 bu_log( "\t( %f %f %f ) -> ( %f %f %f )\n",
04158 V3ARGS( eu->vu_p->v_p->vg_p->coord ),
04159 V3ARGS( eu->eumate_p->vu_p->v_p->vg_p->coord ) );
04160 bu_log( "\t( %f %f %f ) -> ( %f %f %f )\n",
04161 V3ARGS( eu1->vu_p->v_p->vg_p->coord ),
04162 V3ARGS( eu1->eumate_p->vu_p->v_p->vg_p->coord ) );
04163 }
04164 }
04165 }
04166 }
04167 }
04168 }
04169 return( split_count );
04170 }
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180 struct faceuse *
04181 nmg_mk_new_face_from_loop(struct loopuse *lu)
04182 {
04183 struct shell *s;
04184 struct faceuse *fu;
04185 struct loopuse *lu1;
04186 struct loopuse *lu_mate;
04187 int ot_same_loops=0;
04188
04189 if( rt_g.NMG_debug & DEBUG_BASIC )
04190 bu_log( "nmg_mk_new_face_from_loop( lu = x%x )\n" , lu );
04191
04192 NMG_CK_LOOPUSE( lu );
04193
04194 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
04195 {
04196 bu_log( "nmg_mk_new_face_from_loop: loopuse is not in a faceuse\n" );
04197 return( (struct faceuse *)NULL );
04198 }
04199
04200 fu = lu->up.fu_p;
04201 NMG_CK_FACEUSE( fu );
04202
04203 s = fu->s_p;
04204 NMG_CK_SHELL( s );
04205
04206
04207 for( BU_LIST_FOR( lu1 , loopuse , &fu->lu_hd ) )
04208 {
04209 NMG_CK_LOOPUSE( lu1 );
04210 if( lu1->orientation == OT_SAME )
04211 ot_same_loops++;
04212 }
04213
04214 if( ot_same_loops == 1 && lu->orientation == OT_SAME )
04215 {
04216 bu_log( "nmg_mk_new_face_from_loop: cannot remove only exterior loop from faceuse\n" );
04217 return( (struct faceuse *)NULL );
04218 }
04219
04220 lu_mate = lu->lumate_p;
04221
04222
04223 BU_LIST_DEQUEUE( &lu->l );
04224
04225
04226 BU_LIST_DEQUEUE( &lu_mate->l );
04227
04228
04229
04230
04231
04232 BU_LIST_INSERT( &s->lu_hd , &lu_mate->l );
04233 BU_LIST_INSERT( &s->lu_hd , &lu->l );
04234
04235
04236 lu->up.s_p = s;
04237 lu_mate->up.s_p = s;
04238
04239
04240 return( nmg_mf( lu ) );
04241 }
04242
04243
04244 struct nmg_split_loops_state
04245 {
04246 long *flags;
04247 const struct bn_tol *tol;
04248 int split;
04249 };
04250
04251 void
04252 nmg_split_loops_handler(long int *fu_p, genptr_t sl_state, int after)
04253 {
04254 struct faceuse *fu;
04255 struct nmg_split_loops_state *state;
04256 struct loopuse *lu;
04257 const struct bn_tol *tol;
04258 int otsame_loops=0;
04259 int otopp_loops=0;
04260
04261 fu = (struct faceuse *)fu_p;
04262 NMG_CK_FACEUSE( fu );
04263
04264 state = (struct nmg_split_loops_state *)sl_state;
04265 tol = state->tol;
04266
04267 if( fu->orientation != OT_SAME )
04268 return;
04269
04270 if( !NMG_INDEX_TEST_AND_SET( state->flags , fu ) ) return;
04271
04272 NMG_INDEX_SET( state->flags , fu->fumate_p );
04273
04274 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04275 {
04276 NMG_CK_LOOPUSE( lu );
04277
04278 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04279 continue;
04280
04281 if( lu->orientation == OT_SAME )
04282 otsame_loops++;
04283 else if( lu->orientation == OT_OPPOSITE )
04284 otopp_loops++;
04285 else
04286 {
04287 bu_log( "nmg_split_loops_into_faces: facuse (x%x) with %s loopuse (x%x)\n",
04288 fu , nmg_orientation( lu->orientation ) , lu );
04289 return;
04290 }
04291 }
04292
04293
04294 if( otsame_loops == 1 )
04295 return;
04296
04297 if( otopp_loops && otsame_loops )
04298 {
04299 struct bu_ptbl inside_loops;
04300
04301 bu_ptbl_init( &inside_loops , 64, " &inside_loops ");
04302
04303 lu = BU_LIST_FIRST( loopuse , &fu->lu_hd );
04304 while( BU_LIST_NOT_HEAD( lu , &fu->lu_hd ) )
04305 {
04306 struct faceuse *new_fu;
04307 struct loopuse *lu_next;
04308 struct loopuse *lu1;
04309 plane_t plane;
04310 int index;
04311
04312 lu_next = BU_LIST_PNEXT( loopuse , &lu->l );
04313
04314 if( otsame_loops == 1 )
04315 {
04316
04317 bu_ptbl_free( &inside_loops );
04318 return;
04319 }
04320
04321 if( lu->orientation != OT_SAME )
04322 {
04323 lu = lu_next;
04324 continue;
04325 }
04326
04327
04328 for( BU_LIST_FOR( lu1 , loopuse , &fu->lu_hd ) )
04329 {
04330 struct loopuse *lu2;
04331 int hole_in_lu=1;
04332
04333 if( lu1 == lu )
04334 continue;
04335
04336
04337 if( lu1->orientation != OT_OPPOSITE )
04338 continue;
04339
04340
04341 if( nmg_classify_lu_lu( lu1 , lu , tol ) != NMG_CLASS_AinB )
04342 continue;
04343
04344
04345
04346
04347
04348
04349
04350 for( BU_LIST_FOR( lu2 , loopuse , &fu->lu_hd ) )
04351 {
04352
04353 if( lu2 == lu || lu2 == lu1 )
04354 continue;
04355
04356 if( lu2->orientation != OT_SAME )
04357 continue;
04358
04359 if( nmg_classify_lu_lu( lu2 , lu , tol ) == NMG_CLASS_AinB )
04360 {
04361
04362 if( nmg_classify_lu_lu( lu1 , lu2 , tol ) == NMG_CLASS_AinB )
04363 {
04364
04365
04366
04367 hole_in_lu = 0;;
04368 break;
04369 }
04370 }
04371 }
04372
04373 if( hole_in_lu )
04374 bu_ptbl_ins( &inside_loops , (long *)lu1 );
04375 }
04376
04377 NMG_GET_FU_PLANE( plane , fu );
04378
04379 new_fu = nmg_mk_new_face_from_loop( lu );
04380 nmg_face_g( new_fu , plane );
04381
04382 for( index=0 ; index<BU_PTBL_END( &inside_loops ) ; index++ )
04383 {
04384 lu1 = (struct loopuse *)BU_PTBL_GET( &inside_loops , index );
04385 nmg_move_lu_between_fus( new_fu , fu , lu1 );
04386 otopp_loops--;
04387 }
04388 nmg_face_bb( new_fu->f_p, tol );
04389 bu_ptbl_reset( &inside_loops );
04390 otsame_loops--;
04391 lu = lu_next;
04392 }
04393 bu_ptbl_free( &inside_loops );
04394 }
04395 else if( otsame_loops )
04396 {
04397
04398 int first=1;
04399 struct faceuse *new_fu;
04400
04401 lu = BU_LIST_FIRST( loopuse , &fu->lu_hd );
04402 while( BU_LIST_NOT_HEAD( lu , &fu->lu_hd ) )
04403 {
04404 struct loopuse *next_lu;
04405
04406 next_lu = BU_LIST_PNEXT( loopuse , &lu->l );
04407
04408 if( first )
04409 first = 0;
04410 else
04411 {
04412 plane_t plane;
04413
04414 if( lu->orientation == OT_SAME )
04415 {
04416 NMG_GET_FU_PLANE( plane , fu );
04417 }
04418 else
04419 {
04420 NMG_GET_FU_PLANE( plane , fu->fumate_p );
04421 }
04422 new_fu = nmg_mk_new_face_from_loop( lu );
04423 nmg_face_g( new_fu , plane );
04424 nmg_face_bb( new_fu->f_p, tol );
04425 }
04426
04427 lu = next_lu;
04428 }
04429 }
04430 else
04431 {
04432
04433 bu_log( "nmg_split_loops_into_faces: fu (x%x) has only OT_OPPOSITE loopuses, ignored\n" , fu );
04434 }
04435 }
04436
04437
04438
04439
04440
04441
04442
04443
04444 int
04445 nmg_split_loops_into_faces(long int *magic_p, const struct bn_tol *tol)
04446 {
04447 struct model *m;
04448 struct nmg_split_loops_state sl_state;
04449 int count;
04450 static const struct nmg_visit_handlers htab = {NULL, NULL, NULL, NULL, NULL,
04451 NULL, NULL, NULL, NULL, nmg_split_loops_handler,
04452 NULL, NULL, NULL, NULL, NULL,
04453 NULL, NULL, NULL, NULL, NULL,
04454 NULL, NULL, NULL, NULL, NULL};
04455
04456
04457 if( rt_g.NMG_debug & DEBUG_BASIC )
04458 bu_log( "nmg_split_loops_into_faces( magic_p = x%x )\n" , magic_p );
04459
04460 BN_CK_TOL( tol );
04461
04462 m = nmg_find_model( magic_p );
04463 NMG_CK_MODEL( m );
04464
04465 BN_CK_TOL( tol );
04466
04467 sl_state.split = 0;
04468 sl_state.flags = (long *)bu_calloc( m->maxindex*2 , sizeof( long ) , "nmg_split_loops_into_faces: flags" );
04469 sl_state.tol = tol;
04470
04471 nmg_visit( magic_p , &htab , (genptr_t)&sl_state );
04472
04473 count = sl_state.split;
04474
04475 bu_free( (char *)sl_state.flags , "nmg_split_loops_into_faces: flags" );
04476
04477 return( count );
04478 }
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491 int
04492 nmg_decompose_shell(struct shell *s, const struct bn_tol *tol)
04493 {
04494 int missed_faces;
04495 int no_of_shells=1;
04496 int shell_no=1;
04497 int i,j;
04498 struct model *m;
04499 struct nmgregion *r;
04500 struct shell *new_s;
04501 struct faceuse *fu;
04502 struct loopuse *lu;
04503 struct edgeuse *eu;
04504 struct edgeuse *eu1;
04505 struct faceuse *missed_fu = NULL;
04506 struct bu_ptbl stack;
04507 struct bu_ptbl shared_edges;
04508 long *flags;
04509
04510 if( rt_g.NMG_debug & DEBUG_BASIC )
04511 bu_log( "nmg_decompose_shell( s = x%x ) START\n" , s );
04512
04513 NMG_CK_SHELL( s );
04514
04515 BN_CK_TOL( tol );
04516
04517
04518 r = s->r_p;
04519 NMG_CK_REGION( r );
04520 m = r->m_p;
04521 NMG_CK_MODEL( m );
04522 flags = (long *)bu_calloc( m->maxindex*2 , sizeof( long ) , "nmg_decompose_shell: flags" );
04523
04524 bu_ptbl_init( &stack , 64, " &stack ");
04525 bu_ptbl_init( &shared_edges , 64, " &shared_edges ");
04526
04527
04528 (void)nmg_split_loops_into_faces( &s->l.magic , tol );
04529
04530
04531 fu = BU_LIST_FIRST( faceuse , &s->fu_hd );
04532 NMG_CK_FACEUSE( fu );
04533 if( fu->orientation != OT_SAME )
04534 fu = fu->fumate_p;
04535 if( fu->orientation != OT_SAME )
04536 rt_bomb( "First face in shell has no OT_SAME uses!!!!\n" );
04537
04538
04539 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04540 {
04541 NMG_CK_LOOPUSE( lu );
04542 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04543 continue;
04544
04545 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
04546 {
04547
04548 if( nmg_radial_face_count( eu , s ) > 2 )
04549 bu_ptbl_ins_unique( &shared_edges , (long *)eu );
04550 else
04551 bu_ptbl_ins_unique( &stack , (long *)eu );
04552 }
04553 }
04554
04555
04556 NMG_INDEX_ASSIGN( flags , fu , shell_no );
04557 NMG_INDEX_ASSIGN( flags , fu->fumate_p , shell_no );
04558
04559
04560 while( (eu1 = nmg_pop_eu( &stack )) != (struct edgeuse *)NULL )
04561 {
04562 NMG_CK_EDGEUSE( eu1 );
04563
04564
04565 eu = eu1->radial_p;
04566 NMG_CK_EDGEUSE( eu );
04567
04568
04569 while( nmg_find_s_of_eu( eu ) != s && eu != eu1 && eu != eu1->eumate_p )
04570 eu = eu->eumate_p->radial_p;
04571
04572 if( eu == eu1 || eu == eu1->eumate_p )
04573 continue;
04574
04575 fu = nmg_find_fu_of_eu( eu );
04576 NMG_CK_FACEUSE( fu );
04577
04578 if( fu->orientation != OT_SAME )
04579 fu = fu->fumate_p;
04580
04581
04582 if( !NMG_INDEX_TEST( flags , fu ) )
04583 {
04584
04585 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04586 {
04587 NMG_CK_LOOPUSE( lu );
04588
04589 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04590 continue;
04591
04592 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
04593 {
04594
04595 if( nmg_radial_face_count( eu , s ) > 2 )
04596 bu_ptbl_ins_unique( &shared_edges , (long *)eu );
04597 else
04598 bu_ptbl_ins_unique( &stack , (long *)eu );
04599 }
04600 }
04601
04602 NMG_INDEX_ASSIGN( flags , fu , shell_no );
04603 NMG_INDEX_ASSIGN( flags , fu->fumate_p , shell_no );
04604 }
04605 }
04606
04607
04608 missed_faces = 0;
04609 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
04610 {
04611 NMG_CK_FACEUSE( fu );
04612 if( fu->orientation == OT_SAME )
04613 {
04614 if( !NMG_INDEX_TEST( flags , fu ) )
04615 {
04616 missed_faces++;
04617 missed_fu = fu;
04618 }
04619 }
04620 }
04621
04622 if( !missed_faces )
04623 {
04624 bu_free( (char *)flags , "nmg_decompose_shell: flags " );
04625 bu_ptbl_free( &stack );
04626 bu_ptbl_free( &shared_edges );
04627 return( no_of_shells );
04628 }
04629
04630 while( missed_faces )
04631 {
04632 struct edgeuse *unassigned_eu = NULL;
04633 int *shells_at_edge;
04634 int new_shell_no=0;
04635
04636 bu_ptbl_reset( &stack );
04637
04638
04639 shells_at_edge = (int *)bu_calloc( no_of_shells+1 , sizeof( int ) , "nmg_decompose_shell: shells_at_edge" );
04640
04641 for( i=0 ; i<BU_PTBL_END( &shared_edges ) ; i++ )
04642 {
04643 int faces_at_edge=0;
04644 int k;
04645
04646
04647
04648
04649
04650
04651
04652 for( k=0 ; k<=no_of_shells ; k++ )
04653 shells_at_edge[k] = 0;
04654
04655 unassigned_eu = NULL;
04656
04657 eu = (struct edgeuse *)BU_PTBL_GET( &shared_edges , i );
04658 NMG_CK_EDGEUSE( eu );
04659
04660 eu1 = eu;
04661 do
04662 {
04663 struct faceuse *fu_of_eu;
04664
04665 fu_of_eu = nmg_find_fu_of_eu( eu1 );
04666
04667 faces_at_edge++;
04668 if( !NMG_INDEX_TEST( flags , fu_of_eu ) )
04669 unassigned_eu = eu1;
04670 shells_at_edge[ NMG_INDEX_GET( flags , fu_of_eu ) ]++;
04671
04672 eu1 = nmg_next_radial_eu( eu1 , s , 0 );
04673 }
04674 while( eu1 != eu );
04675
04676 if( shells_at_edge[0] == 1 && unassigned_eu )
04677 {
04678
04679
04680
04681 for( j=1 ; j<=no_of_shells ; j++ )
04682 {
04683 if( shells_at_edge[j] == 1 )
04684 {
04685
04686 new_shell_no = j;
04687 break;
04688 }
04689 }
04690 }
04691 else if( shells_at_edge[0] == 0 )
04692 {
04693
04694
04695
04696 bu_ptbl_rm( &shared_edges , (long *)eu );
04697 }
04698 if( new_shell_no )
04699 break;
04700 }
04701
04702 if( !new_shell_no )
04703 {
04704
04705
04706
04707
04708 for( i=0 ; i<BU_PTBL_END( &shared_edges ) ; i++ )
04709 {
04710 struct faceuse *fu_of_eu1;
04711 int found_missed_face=0;
04712
04713 eu = (struct edgeuse *)BU_PTBL_GET( &shared_edges , i );
04714 NMG_CK_EDGEUSE( eu );
04715
04716 eu1 = eu;
04717 do
04718 {
04719
04720 fu_of_eu1 = nmg_find_fu_of_eu( eu1 );
04721 NMG_CK_FACEUSE( fu_of_eu1 );
04722 if( !NMG_INDEX_TEST( flags , fu_of_eu1 ) )
04723 {
04724 struct edgeuse *eu2;
04725 struct faceuse *fu_of_eu2;
04726
04727
04728
04729
04730 eu2 = nmg_prev_radial_eu( eu1 , s , 0 );
04731 fu_of_eu2 = nmg_find_fu_of_eu( eu2 );
04732 NMG_CK_FACEUSE( fu_of_eu2 );
04733 if( NMG_INDEX_TEST( flags , fu_of_eu2 ) )
04734 {
04735
04736
04737
04738 if( fu_of_eu2->orientation ==
04739 fu_of_eu1->orientation )
04740 {
04741
04742
04743
04744
04745 missed_fu = fu_of_eu1;
04746 found_missed_face = 1;
04747 }
04748 }
04749 if( found_missed_face )
04750 break;
04751
04752 eu2 = nmg_next_radial_eu( eu1 , s , 0 );
04753 fu_of_eu2 = nmg_find_fu_of_eu( eu2 );
04754 NMG_CK_FACEUSE( fu_of_eu2 );
04755 if( NMG_INDEX_TEST( flags , fu_of_eu2 ) )
04756 {
04757
04758
04759
04760 if( fu_of_eu2->orientation ==
04761 fu_of_eu1->orientation )
04762 {
04763
04764
04765
04766
04767 missed_fu = fu_of_eu1;
04768 found_missed_face = 1;
04769 }
04770 }
04771
04772 }
04773 if( found_missed_face )
04774 break;
04775 eu1 = nmg_next_radial_eu( eu1 , s , 0 );
04776 }
04777 while( eu1 != eu );
04778
04779 if( found_missed_face )
04780 break;
04781 }
04782 }
04783
04784 bu_free( (char *)shells_at_edge , "nmg_decompose_shell: shells_at_edge" );
04785
04786
04787 if( new_shell_no )
04788 {
04789 shell_no = new_shell_no;
04790 fu = nmg_find_fu_of_eu( unassigned_eu );
04791 }
04792 else
04793 {
04794 shell_no = (++no_of_shells);
04795 NMG_CK_FACEUSE( missed_fu );
04796 fu = missed_fu;
04797 }
04798
04799 if( fu->orientation != OT_SAME )
04800 fu = fu->fumate_p;
04801
04802 if( !NMG_INDEX_TEST( flags , fu ) )
04803 {
04804
04805
04806
04807 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04808 {
04809 NMG_CK_LOOPUSE( lu );
04810
04811 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04812 continue;
04813
04814 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
04815 {
04816
04817 if( nmg_radial_face_count( eu , s ) > 2 )
04818 bu_ptbl_ins_unique( &shared_edges , (long *)eu );
04819 else
04820 bu_ptbl_ins_unique( &stack , (long *)eu );
04821 }
04822 }
04823
04824
04825 NMG_INDEX_ASSIGN( flags , fu , shell_no );
04826 NMG_INDEX_ASSIGN( flags , fu->fumate_p , shell_no );
04827
04828 }
04829 else
04830 rt_bomb( "nmg_decompose_shell: Missed face wasn't missed???\n" );
04831
04832
04833 while( (eu1 = nmg_pop_eu( &stack )) != (struct edgeuse *)NULL )
04834 {
04835 NMG_CK_EDGEUSE( eu1 );
04836
04837
04838 eu = eu1->radial_p;
04839 NMG_CK_EDGEUSE( eu );
04840
04841
04842 while( nmg_find_s_of_eu( eu ) != s && eu != eu1 && eu != eu1->eumate_p )
04843 eu = eu->eumate_p->radial_p;
04844
04845 if( eu == eu1 || eu == eu1->eumate_p )
04846 continue;
04847
04848 fu = nmg_find_fu_of_eu( eu );
04849 NMG_CK_FACEUSE( fu );
04850
04851
04852 if( !NMG_INDEX_TEST( flags , fu ) )
04853 {
04854
04855 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
04856 {
04857 NMG_CK_LOOPUSE( lu );
04858 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
04859 continue;
04860 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
04861 {
04862
04863 if( nmg_radial_face_count( eu , s ) > 2 )
04864 bu_ptbl_ins_unique( &shared_edges , (long *)eu );
04865 else
04866 bu_ptbl_ins_unique( &stack , (long *)eu );
04867 }
04868 }
04869
04870
04871 NMG_INDEX_ASSIGN( flags , fu , shell_no );
04872 NMG_INDEX_ASSIGN( flags , fu->fumate_p , shell_no );
04873
04874 }
04875 }
04876
04877
04878 missed_faces = 0;
04879 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
04880 {
04881 NMG_CK_FACEUSE( fu );
04882 if( fu->orientation == OT_SAME )
04883 {
04884 if( !NMG_INDEX_TEST( flags , fu ) )
04885 {
04886 missed_faces++;
04887 missed_fu = fu;
04888 }
04889 }
04890 }
04891 }
04892
04893
04894 for( shell_no=2 ; shell_no<=no_of_shells ; shell_no++ )
04895 {
04896 struct bu_ptbl faces;
04897
04898 bu_ptbl_init( &faces, 64, "Faces ptbl for nmg_decompose_shell" );
04899
04900
04901 new_s = nmg_msv( r );
04902 (void)nmg_kvu( new_s->vu_p );
04903
04904
04905 fu = BU_LIST_FIRST( faceuse , &s->fu_hd );
04906 while( BU_LIST_NOT_HEAD( fu , &s->fu_hd ) )
04907 {
04908 struct faceuse *next_fu;
04909
04910 next_fu = BU_LIST_NEXT( faceuse , &fu->l );
04911 while( BU_LIST_NOT_HEAD( next_fu , &s->fu_hd ) && next_fu->orientation != OT_SAME )
04912 next_fu = BU_LIST_NEXT( faceuse , &next_fu->l );
04913
04914 if( fu->orientation != OT_SAME )
04915 {
04916 fu = next_fu;
04917 continue;
04918 }
04919
04920 if( NMG_INDEX_GET( flags , fu ) == shell_no )
04921 {
04922 nmg_mv_fu_between_shells( new_s , s , fu );
04923 bu_ptbl_ins( &faces, (long *)fu );
04924 }
04925
04926 fu = next_fu;
04927 }
04928
04929 nmg_gluefaces( (struct faceuse **)BU_PTBL_BASEADDR( &faces ), BU_PTBL_END( &faces ), tol );
04930 bu_ptbl_free( &faces );
04931 nmg_shell_a( new_s, tol );
04932 }
04933 bu_free( (char *)flags , "nmg_decompose_shell: flags " );
04934 bu_ptbl_free( &stack );
04935 bu_ptbl_free( &shared_edges );
04936
04937 nmg_rebound( m ,tol );
04938
04939 if( rt_g.NMG_debug & DEBUG_BASIC )
04940 bu_log( "nmg_decompose_shell END (%d shells)\n" , no_of_shells );
04941
04942 return( no_of_shells );
04943 }
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953 void
04954 nmg_stash_model_to_file(const char *filename, const struct model *m, const char *title)
04955 {
04956 struct rt_wdb *fp;
04957 struct rt_db_internal intern;
04958 struct bu_external ext;
04959 int ret;
04960 int flags;
04961 char *name="error.s";
04962
04963 bu_log("nmg_stash_model_to_file('%s', x%x, %s)\n", filename, m, title);
04964
04965 NMG_CK_MODEL(m);
04966 nmg_vmodel(m);
04967
04968 if( (fp = wdb_fopen(filename)) == NULL ) {
04969 perror(filename);
04970 return;
04971 }
04972
04973 RT_INIT_DB_INTERNAL(&intern);
04974 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
04975 intern.idb_type = ID_NMG;
04976 intern.idb_meth = &rt_functab[ID_NMG];
04977 intern.idb_ptr = (genptr_t)m;
04978
04979 if( fp->dbip->dbi_version <= 4 ) {
04980 BU_INIT_EXTERNAL( &ext );
04981 ret = intern.idb_meth->ft_export( &ext, &intern, 1.0, fp->dbip, &rt_uniresource );
04982 if( ret < 0 ) {
04983 bu_log("rt_db_put_internal(%s): solid export failure\n",
04984 name);
04985 ret = -1;
04986 goto out;
04987 }
04988 db_wrap_v4_external( &ext, name );
04989 } else {
04990 if( rt_db_cvt_to_external5( &ext, name, &intern, 1.0, fp->dbip, &rt_uniresource, intern.idb_major_type ) < 0 ) {
04991 bu_log("wdb_export(%s): solid export failure\n",
04992 name );
04993 ret = -2;
04994 goto out;
04995 }
04996 }
04997 BU_CK_EXTERNAL( &ext );
04998
04999 flags = db_flags_internal( &intern );
05000 ret = wdb_export_external( fp, &ext, name, flags, intern.idb_type );
05001 out:
05002 bu_free_external( &ext );
05003 wdb_close( fp );
05004
05005 bu_log("nmg_stash_model_to_file(): wrote error.s to '%s'\n",
05006 filename);
05007 }
05008
05009
05010 struct nmg_unbreak_state
05011 {
05012 long *flags;
05013 int unbroken;
05014 };
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028 void
05029 nmg_unbreak_handler(long int *eup, genptr_t state, int after)
05030 {
05031 struct edgeuse *eu1,*eu2;
05032 struct edge *e;
05033 struct edge_g_lseg *eg;
05034 struct nmg_unbreak_state *ub_state;
05035 struct vertex *vb;
05036 int ret;
05037
05038 eu1 = (struct edgeuse *)eup;
05039 NMG_CK_EDGEUSE( eu1 );
05040
05041 ub_state = (struct nmg_unbreak_state *)state;
05042
05043
05044
05045
05046
05047
05048
05049 if( !NMG_INDEX_TEST_AND_SET( ub_state->flags , eu1 ) ) return;
05050
05051 e = eu1->e_p;
05052 NMG_CK_EDGE( e );
05053
05054 eg = eu1->g.lseg_p;
05055 if( !eg ) {
05056 bu_log( "nmg_unbreak_handler: no geomtry for edge x%x\n" , e );
05057 return;
05058 }
05059 NMG_CK_EDGE_G_EITHER(eg);
05060
05061
05062
05063 if( bu_list_len( &eg->eu_hd2 ) < 2*2 ) {
05064
05065 return;
05066 }
05067
05068
05069 eu2 = BU_LIST_PNEXT_CIRC( edgeuse , eu1 );
05070 NMG_CK_EDGEUSE( eu2 );
05071 if( eu2->g.lseg_p != eg )
05072 {
05073
05074
05075
05076
05077
05078 return;
05079 }
05080 vb = eu2->vu_p->v_p;
05081 NMG_CK_VERTEX(vb);
05082
05083
05084
05085
05086
05087
05088
05089
05090
05091 ret = nmg_unbreak_edge( eu1 );
05092 if( ret != 0 ) return;
05093
05094
05095 ub_state->unbroken++;
05096 }
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106 int
05107 nmg_unbreak_region_edges(long int *magic_p)
05108 {
05109 struct model *m;
05110 struct nmg_unbreak_state ub_state;
05111 int count;
05112 static const struct nmg_visit_handlers htab = {NULL, NULL, NULL, NULL, NULL,
05113 NULL, NULL, NULL, NULL, NULL,
05114 NULL, NULL, NULL, NULL, NULL,
05115 NULL, NULL, nmg_unbreak_handler, NULL, NULL,
05116 NULL, NULL, NULL, NULL, NULL};
05117
05118
05119 if( rt_g.NMG_debug & DEBUG_BASIC )
05120 bu_log( "nmg_unbreak_region_edges( magic_p = x%x )\n" , magic_p );
05121
05122 m = nmg_find_model( magic_p );
05123 NMG_CK_MODEL( m );
05124
05125 ub_state.unbroken = 0;
05126 ub_state.flags = (long *)bu_calloc( m->maxindex*2 , sizeof( long ) , "nmg_unbreak_region_edges: flags" );
05127
05128 nmg_visit( magic_p , &htab , (genptr_t)&ub_state );
05129
05130 count = ub_state.unbroken;
05131
05132 bu_free( (char *)ub_state.flags , "nmg_unbreak_region_edges: flags" );
05133
05134 return( count );
05135 }
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165 int
05166 rt_dist_pt3_line3(fastf_t *dist, fastf_t *pca, const fastf_t *a, const fastf_t *dir, const fastf_t *p, const struct bn_tol *tol)
05167 {
05168 vect_t AtoP;
05169 vect_t unit_dir;
05170 fastf_t A_P_sq;
05171 fastf_t t;
05172 fastf_t dsq;
05173
05174 if( rt_g.NMG_debug & DEBUG_BASIC )
05175 bu_log( "rt_dist_pt3_line3( a=( %f %f %f ), dir=( %f %f %f ), p=( %f %f %f )\n" ,
05176 V3ARGS( a ) , V3ARGS( dir ) , V3ARGS( p ) );
05177
05178 BN_CK_TOL(tol);
05179
05180
05181 VSUB2(AtoP, p, a);
05182 if( (A_P_sq = MAGSQ(AtoP)) < tol->dist_sq ) {
05183
05184 VMOVE( pca, a );
05185 *dist = 0.0;
05186 return( 0 );
05187 }
05188
05189 VMOVE( unit_dir , dir );
05190 VUNITIZE( unit_dir );
05191
05192
05193
05194
05195 t = VDOT(AtoP, unit_dir);
05196
05197 VJOIN1( pca , a , t , unit_dir );
05198 if( (dsq = A_P_sq - t*t) < tol->dist_sq )
05199 {
05200
05201 *dist = 0.0;
05202 return( 1 );
05203 }
05204 else
05205 {
05206
05207 *dist = sqrt( dsq );
05208 return( 2 );
05209 }
05210 }
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223 int
05224 nmg_mv_shell_to_region(struct shell *s, struct nmgregion *r)
05225 {
05226 int ret_val;
05227
05228 if( rt_g.NMG_debug & DEBUG_BASIC )
05229 bu_log( "nmg_mv_shell_to_region( s=x%x , r=x%x )\n" , s , r );
05230
05231 NMG_CK_SHELL( s );
05232 NMG_CK_REGION( r );
05233
05234 if( s->r_p == r )
05235 {
05236 bu_log( "nmg_mv_shell_to_region: Attempt to move shell to region it is already in\n" );
05237 return( 0 );
05238 }
05239
05240 if( nmg_find_model( &s->l.magic ) != nmg_find_model( &r->l.magic ) )
05241 rt_bomb( "nmg_mv_shell_to_region: Cannot move shell to a different model\n" );
05242
05243 BU_LIST_DEQUEUE( &s->l );
05244 if( BU_LIST_IS_EMPTY( &s->r_p->s_hd ) )
05245 ret_val = 1;
05246 else
05247 ret_val = 0;
05248
05249 BU_LIST_APPEND( &r->s_hd , &s->l );
05250
05251 s->r_p = r;
05252
05253 return( ret_val );
05254 }
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267 int
05268 nmg_find_isect_faces(const struct vertex *new_v, struct bu_ptbl *faces, int *free_edges, const struct bn_tol *tol)
05269 {
05270 struct faceuse *fu;
05271 struct face_g_plane *fg;
05272 struct vertexuse *vu;
05273 int i;
05274 int unique;
05275
05276 if( rt_g.NMG_debug & DEBUG_BASIC )
05277 bu_log( "nmg_find_isect_faces( new_v=x%x , faces=x%x )\n" , new_v , faces );
05278
05279 NMG_CK_VERTEX( new_v );
05280 BN_CK_TOL( tol );
05281 BU_CK_PTBL( faces );
05282
05283
05284 for( BU_LIST_FOR( vu , vertexuse , &new_v->vu_hd ) )
05285 {
05286 NMG_CK_VERTEXUSE( vu );
05287 fu = nmg_find_fu_of_vu( vu );
05288 if( fu->orientation != OT_SAME )
05289 continue;;
05290
05291 NMG_CK_FACEUSE( fu );
05292 fg = fu->f_p->g.plane_p;
05293
05294
05295 unique = 1;
05296 for( i=0 ; i<BU_PTBL_END( faces ) ; i++ )
05297 {
05298 struct face *fp;
05299
05300 fp = (struct face *)BU_PTBL_GET( faces , i );
05301 if( fp->g.plane_p == fg || bn_coplanar( fg->N , fp->g.plane_p->N , tol ) > 0 )
05302 {
05303 unique = 0;
05304 break;
05305 }
05306 }
05307
05308
05309 if( unique )
05310 {
05311 struct edgeuse *eu1;
05312
05313 bu_ptbl_ins( faces , (long *)fu->f_p );
05314
05315
05316 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
05317 continue;
05318
05319 eu1 = vu->up.eu_p;
05320 if( eu1->eumate_p == eu1->radial_p )
05321 (*free_edges)++;
05322 else
05323 {
05324 eu1 = BU_LIST_PPREV_CIRC( edgeuse , eu1 );
05325 if( eu1->eumate_p == eu1->radial_p )
05326 (*free_edges)++;
05327 }
05328 }
05329 }
05330 return( BU_PTBL_END( faces ) );
05331 }
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345 int
05346 nmg_simple_vertex_solve(struct vertex *new_v, const struct bu_ptbl *faces, const struct bn_tol *tol)
05347 {
05348 struct vertex_g *vg;
05349 int failed=0;
05350
05351 if( rt_g.NMG_debug & DEBUG_BASIC )
05352 {
05353 struct face *f;
05354 struct faceuse *fu;
05355 plane_t pl;
05356 int i;
05357
05358 bu_log( "nmg_simple_vertex_solve( new_v=x%x , %d faces )\n" , new_v , BU_PTBL_END( faces ));
05359
05360 for( i=0 ; i<BU_PTBL_END( faces ) ; i++ )
05361 {
05362 f = (struct face *)BU_PTBL_GET( faces, i );
05363 fu = f->fu_p;
05364 if( fu->orientation != OT_SAME )
05365 fu = fu->fumate_p;
05366 if( fu->orientation != OT_SAME )
05367 bu_log( "\tface (x%x) has no OT_SAME use\n", f );
05368 NMG_GET_FU_PLANE( pl, fu );
05369 bu_log( "\t#%d: %g %g %g %g\n", i, V4ARGS( pl ) );
05370 }
05371 }
05372
05373 NMG_CK_VERTEX( new_v );
05374 BU_CK_PTBL( faces );
05375 BN_CK_TOL( tol );
05376
05377 vg = new_v->vg_p;
05378 NMG_CK_VERTEX_G( vg );
05379
05380 switch( BU_PTBL_END( faces ) )
05381 {
05382 struct face *fp1,*fp2,*fp3;
05383 plane_t pl1;
05384 fastf_t vert_move_len;
05385 fastf_t pl_dot;
05386
05387 case 0:
05388 bu_log( "nmg_simple_vertex_solve: vertex not in any face planes!!!\n" );
05389 failed = 1;
05390 break;
05391
05392 case 1:
05393 fp1 = (struct face *)BU_PTBL_GET( faces , 0 );
05394 vert_move_len = DIST_PT_PLANE( vg->coord , fp1->g.plane_p->N );
05395 VJOIN1( vg->coord , vg->coord , -vert_move_len , fp1->g.plane_p->N );
05396 break;
05397
05398 case 2:
05399 fp1 = (struct face *)BU_PTBL_GET( faces , 0 );
05400 fp2 = (struct face *)BU_PTBL_GET( faces , 1 );
05401
05402 pl_dot = VDOT( fp1->g.plane_p->N, fp2->g.plane_p->N );
05403 if( NEAR_ZERO( pl_dot - 1.0 , tol->perp ) || NEAR_ZERO( pl_dot + 1.0, tol->perp) )
05404 {
05405 vect_t move_vect;
05406
05407
05408 vert_move_len = (DIST_PT_PLANE( vg->coord , fp1->g.plane_p->N )
05409 + DIST_PT_PLANE( vg->coord , fp2->g.plane_p->N ))/2.0;
05410 VADD2( move_vect, fp1->g.plane_p->N, fp2->g.plane_p->N );
05411 VUNITIZE( move_vect );
05412 VJOIN1( vg->coord, vg->coord, -vert_move_len, move_vect );
05413 }
05414 else
05415 {
05416
05417
05418 VCROSS( pl1 , fp1->g.plane_p->N , fp2->g.plane_p->N );
05419
05420 VUNITIZE( pl1 );
05421 pl1[3] = VDOT( vg->coord , pl1 );
05422 if( bn_mkpoint_3planes( vg->coord , fp1->g.plane_p->N , fp2->g.plane_p->N , pl1 ) )
05423 {
05424 bu_log( "nmg_simple_vertex_solve: Cannot find new coords for two planes\n" );
05425 bu_log( "\tplanes are ( %f %f %f %f ) and ( %f %f %f %f )\n",
05426 V4ARGS( fp1->g.plane_p->N ) ,
05427 V4ARGS( fp2->g.plane_p->N ) );
05428 bu_log( "\tcalculated third plane is ( %f %f %f %f )\n" , V4ARGS( pl1 ) );
05429 failed = 1;
05430 break;
05431 }
05432 }
05433 break;
05434
05435 case 3:
05436 fp1 = (struct face *)BU_PTBL_GET( faces , 0 );
05437 fp2 = (struct face *)BU_PTBL_GET( faces , 1 );
05438 fp3 = (struct face *)BU_PTBL_GET( faces , 2 );
05439 if( bn_mkpoint_3planes( vg->coord , fp1->g.plane_p->N , fp2->g.plane_p->N , fp3->g.plane_p->N ) )
05440 {
05441 bu_log( "nmg_simple_vertex_solve: failed for 3 planes:\n" );
05442 bu_log( "\t( %f %f %f %f )\n" , V4ARGS( fp1->g.plane_p->N ) );
05443 bu_log( "\t( %f %f %f %f )\n" , V4ARGS( fp2->g.plane_p->N ) );
05444 bu_log( "\t( %f %f %f %f )\n" , V4ARGS( fp3->g.plane_p->N ) );
05445 failed = 1;
05446 break;
05447 }
05448 break;
05449 default:
05450 failed = 1;
05451 bu_log( "nmg_simple_vertex_solve: Called for a complex vertex\n" );
05452 break;
05453 }
05454
05455 if( failed )
05456 bu_log( "nmg_simple_vertex_solve: Failed to determine new coordinates for vertex at ( %f %f %f )\n",
05457 V3ARGS( new_v->vg_p->coord ) );
05458 else if( rt_g.NMG_debug & DEBUG_BASIC )
05459 bu_log( "nmg_simple_vertex_solve: new coords = ( %f %f %f )\n",
05460 V3ARGS( new_v->vg_p->coord ) );
05461
05462 return( failed );
05463 }
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474 int
05475 nmg_ck_vert_on_fus(const struct vertex *v, const struct bn_tol *tol)
05476 {
05477 struct vertexuse *vu;
05478 fastf_t max_dist=0.0;
05479 int ret_val=0;
05480
05481 NMG_CK_VERTEX( v );
05482 BN_CK_TOL( tol );
05483
05484 NMG_CK_VERTEX_G( v->vg_p );
05485
05486 for( BU_LIST_FOR( vu , vertexuse , &v->vu_hd ) )
05487 {
05488 struct faceuse *fu;
05489 fastf_t dist;
05490
05491 fu = nmg_find_fu_of_vu( vu );
05492 if( !fu )
05493 continue;
05494
05495 NMG_CK_FACEUSE( fu );
05496 NMG_CK_FACE( fu->f_p );
05497 NMG_CK_FACE_G_PLANE( fu->f_p->g.plane_p );
05498 dist = DIST_PT_PLANE( v->vg_p->coord , fu->f_p->g.plane_p->N );
05499 dist = (dist < 0.0 ? (-dist) : dist);
05500 if( dist > tol->dist )
05501 {
05502 ret_val = 1;
05503
05504 if( dist > max_dist )
05505 max_dist = dist;
05506
05507 bu_log( "nmg_ck_vert_on_fus: v=x%x vu=x%x ( %f %f %f ) is %g from\n\tfaceuse x%x f x%x\n" , v , vu , V3ARGS( v->vg_p->coord ) , dist , fu , fu->f_p );
05508 }
05509 }
05510
05511 if( ret_val )
05512 bu_log( "nmg_ck_vert_on_fus: v=x%x ( %f %f %f ) max distance of %g from faceuses\n" , v , V3ARGS( v->vg_p->coord ) , max_dist );
05513
05514 return( ret_val );
05515 }
05516
05517
05518
05519
05520
05521 struct intersect_fus
05522 {
05523 struct faceuse *fu[2];
05524 struct edgeuse *eu;
05525 point_t start;
05526 vect_t dir;
05527 point_t pt;
05528 int got_pt;
05529 int free_edge;
05530 struct vertex *vp;
05531 };
05532
05533
05534
05535
05536
05537
05538 static void
05539 nmg_pr_inter(const struct vertex *new_v, const struct bu_ptbl *int_faces)
05540 {
05541 int i;
05542 struct bn_tol tol;
05543
05544 NMG_CK_VERTEX( new_v );
05545 BU_CK_PTBL( int_faces );
05546
05547 tol.magic = BN_TOL_MAGIC;
05548 tol.dist = 0.005;
05549 tol.dist_sq = tol.dist * tol.dist;
05550 tol.perp = 1e-6;
05551 tol.para = 1 - tol.perp;
05552
05553 bu_log( "\nint_faces at vertex x%x ( %f %f %f )\n" , new_v , V3ARGS( new_v->vg_p->coord ) );
05554 for( i=0 ; i<BU_PTBL_END( int_faces ) ; i++ )
05555 {
05556 struct intersect_fus *i_fus;
05557 struct face *fp1,*fp2;
05558 plane_t pl;
05559
05560 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , i );
05561
05562 bu_log( "edge number %d, x%x\n" , i , i_fus );
05563 if( i_fus->fu[0] )
05564 fp1 = i_fus->fu[0]->f_p;
05565 else
05566 fp1 = NULL;
05567 if( i_fus->fu[1] )
05568 {
05569 fp2 = i_fus->fu[1]->f_p;
05570 NMG_GET_FU_PLANE( pl , i_fus->fu[1] );
05571 }
05572 else
05573 fp2 = NULL;
05574
05575 if( i_fus->fu[1] )
05576 bu_log( "\tfu1 = x%x (face=x%x), fu2 = x%x (face=x%x) ( %f %f %f %f )\n" , i_fus->fu[0] , fp1 , i_fus->fu[1] , fp2 , V4ARGS( pl ) );
05577 else
05578 bu_log( "\tfu1 = x%x (face=x%x), fu2 = x%x (face=x%x)\n" , i_fus->fu[0] , fp1 , i_fus->fu[1] , fp2 );
05579
05580 if( i_fus->eu == NULL )
05581 bu_log( "\teu = NULL\n" );
05582 else if( i_fus->eu->vu_p == NULL )
05583 bu_log( "\teu = x%x , vu_p = NULL\n" , i_fus->eu );
05584 else
05585 {
05586 struct faceuse *fu;
05587
05588 bu_log( "\teu = x%x, from x%x ( %f %f %f ) to x%x ( %f %f %f )\n" , i_fus->eu,
05589 i_fus->eu->vu_p->v_p , V3ARGS( i_fus->eu->vu_p->v_p->vg_p->coord ),
05590 i_fus->eu->eumate_p->vu_p->v_p , V3ARGS( i_fus->eu->eumate_p->vu_p->v_p->vg_p->coord ) );
05591 if( i_fus->fu[0] )
05592 {
05593 fu = nmg_find_fu_of_eu( i_fus->eu );
05594 if( fu != i_fus->fu[0] )
05595 bu_log( "****ERROR**** eu is not in fu1 it's in x%x\n" , fu );
05596 }
05597 else
05598 {
05599 fu = nmg_find_fu_of_eu( i_fus->eu );
05600 if( fu != i_fus->fu[1] )
05601 bu_log( "****ERROR**** eu is not in fu2, it's in x%x\n" , fu );
05602 }
05603 #if 0
05604
05605 if( !bn_pt3_pt3_equal( i_fus->eu->vu_p->v_p->vg_p->coord, i_fus->eu->eumate_p->vu_p->v_p, &tol ) )
05606 nmg_pr_fu_around_eu( i_fus->eu , &tol );
05607 #endif
05608 }
05609
05610 bu_log( "\tstart = ( %f %f %f ) , dir = ( %f %f %f )\n" , V3ARGS( i_fus->start ) , V3ARGS( i_fus->dir ) );
05611 bu_log( "\tpt = ( %f %f %f )\n" , V3ARGS( i_fus->pt ) );
05612 bu_log( "\tfree_edge = %d\n" , i_fus->free_edge );
05613 if( i_fus->eu && i_fus->eu->vu_p )
05614 {
05615 if( i_fus->eu->eumate_p != i_fus->eu->radial_p &&
05616 i_fus->free_edge )
05617 bu_log( "****ERROR**** this is NOT a free edge\n" );
05618 if( i_fus->eu->eumate_p == i_fus->eu->radial_p &&
05619 !i_fus->free_edge )
05620 bu_log( "****ERROR**** This is a free edge\n" );
05621 }
05622 if( i_fus->vp )
05623 bu_log( "\tvp = x%x ( %f %f %f )\n" , i_fus->vp , V3ARGS( i_fus->vp->vg_p->coord ) );
05624 else
05625 bu_log( "\tvp = NULL\n" );
05626 }
05627 }
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639 static int
05640 nmg_get_edge_lines(struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
05641 {
05642 struct vertex_g *vg;
05643 struct vertexuse *vu;
05644 struct edgeuse *eu,*eu1;
05645 struct faceuse *fu;
05646 struct model *m;
05647 struct nmgregion *r;
05648 struct bn_tol tol_tmp;
05649 int done=0;
05650 int edge_no;
05651
05652 NMG_CK_VERTEX( new_v );
05653 vg = new_v->vg_p;
05654 NMG_CK_VERTEX_G( vg );
05655 BN_CK_TOL( tol );
05656 BU_CK_PTBL( int_faces );
05657
05658 if( rt_g.NMG_debug & DEBUG_BASIC )
05659 bu_log( "nmg_get_edge_lines( new_v=x%x , int_faces=x%x )\n" , new_v , int_faces );
05660
05661
05662 tol_tmp.magic = BN_TOL_MAGIC;
05663 tol_tmp.dist = 0.0;
05664 tol_tmp.dist_sq = 0.0;
05665 tol_tmp.perp = 0.0;
05666 tol_tmp.para = 1.0;
05667
05668 m = nmg_find_model( &new_v->magic );
05669 NMG_CK_MODEL( m );
05670 r = BU_LIST_FIRST( nmgregion , &m->r_hd );
05671 NMG_CK_REGION( r );
05672 NMG_CK_REGION_A( r->ra_p );
05673
05674
05675 eu1 = (struct edgeuse *)NULL;
05676 for( BU_LIST_FOR( vu , vertexuse , &new_v->vu_hd ) )
05677 {
05678 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
05679 continue;
05680
05681 eu = vu->up.eu_p->eumate_p;
05682 fu = nmg_find_fu_of_eu( eu );
05683 if( !fu )
05684 continue;
05685
05686 if( fu->orientation != OT_SAME )
05687 continue;
05688
05689 if( eu->eumate_p == eu->radial_p )
05690 {
05691
05692 plane_t pl;
05693 struct intersect_fus *i_fus;
05694
05695
05696 i_fus = (struct intersect_fus *)bu_malloc( sizeof( struct intersect_fus ) , "nmg_get_edge_lines: i_fus" );
05697 i_fus->fu[0] = NULL;
05698 i_fus->fu[1] = fu;
05699 i_fus->eu = eu;
05700 i_fus->vp = (struct vertex *)NULL;
05701 VSET( i_fus->pt , 0.0 , 0.0 , 0.0 );
05702 i_fus->got_pt = 0;
05703 i_fus->free_edge = 1;
05704 eu1 = BU_LIST_PNEXT_CIRC( edgeuse , &eu->l );
05705
05706 VSUB2( i_fus->dir , eu->vu_p->v_p->vg_p->coord , eu->eumate_p->vu_p->v_p->vg_p->coord );
05707 VUNITIZE( i_fus->dir );
05708 NMG_GET_FU_PLANE( pl , fu );
05709 VJOIN1( i_fus->start , vg->coord , (-DIST_PT_PLANE( vg->coord , pl )) , pl );
05710
05711
05712 bu_ptbl_ins( int_faces , (long *)i_fus );
05713
05714 break;
05715 }
05716 }
05717
05718 if( !eu1 )
05719 {
05720 int found_start=0;
05721
05722
05723 for( BU_LIST_FOR( vu , vertexuse , &new_v->vu_hd ) )
05724 {
05725 NMG_CK_VERTEXUSE( vu );
05726 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
05727 continue;
05728
05729 eu1 = vu->up.eu_p;
05730
05731 fu = nmg_find_fu_of_eu( eu1 );
05732 NMG_CK_FACEUSE( fu );
05733
05734 if( fu->orientation == OT_SAME )
05735 {
05736 found_start = 1;
05737 break;
05738 }
05739 }
05740 if( !found_start )
05741 {
05742 bu_log( "Cannot find edgeuse in OT_SAME faceuse starting at ( %f %f %f )\n",
05743 V3ARGS( new_v->vg_p->coord ) );
05744 return( 1 );
05745 }
05746 }
05747
05748 eu = eu1;
05749
05750
05751 while( !done )
05752 {
05753 fastf_t dist;
05754 point_t start;
05755 vect_t dir;
05756 vect_t eu_dir;
05757 int ret_val;
05758 struct intersect_fus *i_fus;
05759 struct faceuse *fu1,*fu2;
05760
05761 NMG_CK_EDGEUSE( eu );
05762
05763 if( eu->vu_p->v_p != new_v )
05764 {
05765
05766
05767
05768
05769 bu_log( "nmg_get_edge_lines: Bad solid!!!\n" );
05770 for( edge_no=0 ; edge_no<BU_PTBL_END( int_faces ) ; edge_no++ )
05771 {
05772 struct intersect_fus *i_fus;
05773
05774 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
05775
05776 bu_free( (char *)i_fus , "nmg_get_edge_lines: i_fus" );
05777 }
05778 return( 1 );
05779 }
05780
05781
05782 VSUB2( eu_dir , eu->eumate_p->vu_p->v_p->vg_p->coord , eu->vu_p->v_p->vg_p->coord );
05783
05784
05785 fu1 = nmg_find_fu_of_eu( eu );
05786 fu2 = nmg_find_fu_of_eu( eu->radial_p );
05787
05788
05789 i_fus = (struct intersect_fus *)bu_malloc( sizeof( struct intersect_fus ) , "nmg_inside_vert: intersection list" );
05790 i_fus->fu[0] = fu1;
05791 if( eu->radial_p == eu->eumate_p )
05792 {
05793 i_fus->fu[1] = (struct faceuse *)NULL;
05794 i_fus->free_edge = 1;
05795 done = 1;
05796 }
05797 else
05798 {
05799 i_fus->fu[1] = fu2;
05800 i_fus->free_edge = 0;
05801 }
05802 i_fus->eu = eu;
05803 i_fus->vp = (struct vertex *)NULL;
05804 VSET( i_fus->pt , 0.0 , 0.0 , 0.0 );
05805 i_fus->got_pt = 0;
05806 VSET( i_fus->start , 0.0 , 0.0 , 0.0 );
05807 VSET( i_fus->dir , 0.0 , 0.0 , 0.0 );
05808
05809
05810 if( fu1->f_p != fu2->f_p )
05811 {
05812
05813
05814
05815 ret_val = bn_isect_2planes( start, dir,
05816 fu1->f_p->g.plane_p->N,
05817 fu2->f_p->g.plane_p->N,
05818 new_v->vg_p->coord,
05819 &tol_tmp );
05820 if( ret_val )
05821 {
05822
05823 bu_log( "nmg_inside_vert: Cannot find new edge between two planes\n" );
05824 bu_log( "return from bn_isect_2planes is %d\n" , ret_val );
05825 bu_log( "\tplanes are ( %f %f %f %f ) and ( %f %f %f %f )\n" ,
05826 V4ARGS( fu1->f_p->g.plane_p->N ),
05827 V4ARGS( fu2->f_p->g.plane_p->N ) );
05828 bu_log( "\tfus x%x and x%x, faces x%x and x%x\n" ,
05829 fu1, fu2, fu1->f_p, fu2->f_p );
05830 nmg_pr_fu_briefly( fu1 , "fu1: " );
05831 nmg_pr_fu_briefly( fu2 , "fu2: " );
05832 rt_bomb( "Can't find plane intersection\n" );
05833 }
05834
05835 (void)rt_dist_pt3_line3( &dist , start , start , dir , new_v->vg_p->coord , tol );
05836
05837
05838 if( VDOT( eu_dir , dir ) < 0.0 )
05839 VREVERSE( dir , dir );
05840 VMOVE( i_fus->start , start );
05841 VMOVE( i_fus->dir , dir );
05842 }
05843 else if( i_fus->free_edge )
05844 {
05845 plane_t pl;
05846
05847
05848
05849
05850
05851 NMG_GET_FU_PLANE( pl , fu1 );
05852
05853 VMOVE( i_fus->dir , eu_dir );
05854 VUNITIZE( i_fus->dir );
05855
05856 VJOIN1( i_fus->start , vg->coord , (-DIST_PT_PLANE( vg->coord , pl )) , pl );
05857
05858 }
05859
05860
05861 bu_ptbl_ins( int_faces , (long *)i_fus );
05862
05863 if( !done )
05864 {
05865
05866 eu = eu->radial_p;
05867 eu = BU_LIST_PNEXT_CIRC( edgeuse , eu );
05868 if( eu == eu1 )
05869 done = 1;
05870 }
05871 }
05872 if( rt_g.NMG_debug & DEBUG_BASIC )
05873 {
05874 bu_log( "After getting edge lines:\n" );
05875 nmg_pr_inter( new_v , int_faces );
05876 }
05877
05878 return( 0 );
05879 }
05880
05881
05882
05883
05884
05885
05886
05887 static int
05888 nmg_get_max_edge_inters(const struct vertex *new_v, struct bu_ptbl *int_faces, const struct bu_ptbl *faces, const struct bn_tol *tol)
05889 {
05890 struct model *m;
05891 struct nmgregion *r;
05892 int edge_no;
05893
05894 if( rt_g.NMG_debug & DEBUG_BASIC )
05895 bu_log( "nmg_get_max_edge_inters( new_v = x%x , %d intersect_fus structs , %d faces )\n" , new_v , BU_PTBL_END( int_faces ) , BU_PTBL_END( faces ) );
05896
05897 NMG_CK_VERTEX( new_v );
05898 BN_CK_TOL( tol );
05899 BU_CK_PTBL( int_faces );
05900
05901 m = nmg_find_model( &new_v->magic );
05902 NMG_CK_MODEL( m );
05903 r = BU_LIST_FIRST( nmgregion , &m->r_hd );
05904 NMG_CK_REGION( r );
05905 NMG_CK_REGION_A( r->ra_p );
05906
05907
05908 for( edge_no=0 ; edge_no<BU_PTBL_END( int_faces ) ; edge_no++ )
05909 {
05910 struct intersect_fus *edge_fus,*other_fus;
05911 fastf_t max_dist,dist[2];
05912 int next_edge_no,prev_edge_no;
05913 int other_index;
05914
05915 edge_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
05916
05917
05918 if( edge_fus->fu[0] && edge_fus->fu[1] &&
05919 edge_fus->fu[0]->f_p == edge_fus->fu[1]->f_p )
05920 continue;
05921
05922
05923
05924
05925 max_dist = (-MAX_FASTF);
05926
05927
05928 next_edge_no = edge_no + 1;
05929 if( next_edge_no == BU_PTBL_END( int_faces ) )
05930 next_edge_no = 0;
05931
05932 other_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
05933
05934
05935 while( other_fus->fu[0] == other_fus->fu[1] && other_fus != edge_fus )
05936 {
05937 next_edge_no++;
05938 if( next_edge_no == BU_PTBL_END( int_faces ) )
05939 next_edge_no = 0;
05940
05941 other_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
05942
05943 }
05944
05945
05946 if( other_fus != edge_fus )
05947 {
05948 if( !rt_dist_line3_line3( dist , edge_fus->start , edge_fus->dir , other_fus->start , other_fus->dir , tol ) )
05949 {
05950 if( rt_g.NMG_debug & DEBUG_BASIC )
05951 bu_log( "Edge #%d intersects edge #%d at dist = %f\n" , edge_no , next_edge_no , dist[0] );
05952 if( NEAR_ZERO( dist[0] , tol->dist ) )
05953 dist[0] = 0.0;
05954 if( dist[0] > max_dist )
05955 max_dist = dist[0];
05956 }
05957 }
05958
05959
05960 prev_edge_no = edge_no - 1;
05961 if( prev_edge_no < 0 )
05962 prev_edge_no = BU_PTBL_END( int_faces ) - 1;
05963
05964 other_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , prev_edge_no );
05965
05966 while( other_fus->fu[0] == other_fus->fu[1] && other_fus != edge_fus )
05967 {
05968 prev_edge_no--;
05969 if( prev_edge_no < 0 )
05970 prev_edge_no = BU_PTBL_END( int_faces ) - 1;
05971
05972 other_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , prev_edge_no );
05973 }
05974
05975 if( other_fus != edge_fus )
05976 {
05977 if( rt_dist_line3_line3( dist , edge_fus->start , edge_fus->dir , other_fus->start , other_fus->dir , tol ) >= 0 )
05978 {
05979 if( rt_g.NMG_debug & DEBUG_BASIC )
05980 bu_log( "Edge #%d intersects edge #%d at dist = %f\n" , edge_no , prev_edge_no , dist[0] );
05981 if( NEAR_ZERO( dist[0] , tol->dist ) )
05982 dist[0] = 0.0;
05983 if( dist[0] > max_dist )
05984 max_dist = dist[0];
05985 }
05986 }
05987
05988 if( max_dist < 0.0 )
05989 {
05990
05991 for( other_index=0 ; other_index<BU_PTBL_END( int_faces ) ; other_index ++ )
05992 {
05993 struct face *f;
05994
05995 if( other_index == edge_no )
05996 continue;
05997
05998 other_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , other_index );
05999
06000 if( !other_fus->fu[0] )
06001 continue;
06002
06003 NMG_CK_FACEUSE( other_fus->fu[0] );
06004 f = other_fus->fu[0]->f_p;
06005
06006 if( edge_fus->fu[0] && f == edge_fus->fu[0]->f_p )
06007 continue;
06008
06009 if( edge_fus->fu[1] && f == edge_fus->fu[1]->f_p )
06010 continue;
06011
06012
06013 if( NEAR_ZERO( VDOT( f->g.plane_p->N , edge_fus->dir ) , tol->perp ) )
06014 continue;
06015
06016 if( bn_isect_line3_plane( &dist[0] , edge_fus->start , edge_fus->dir , f->g.plane_p->N , tol ) > 1 )
06017 continue;
06018
06019 if( rt_g.NMG_debug & DEBUG_BASIC )
06020 bu_log( "Edge #%d intersects fu[0] from edge #%d at dist = %f\n" , edge_no , other_index , dist[0] );
06021
06022 if( NEAR_ZERO( dist[0] , tol->dist ) )
06023 dist[0] = 0.0;
06024
06025 if( dist[0] > max_dist )
06026 max_dist = dist[0];
06027 }
06028 }
06029
06030
06031 if( max_dist > (-MAX_FASTF) )
06032 {
06033 VJOIN1( edge_fus->pt , edge_fus->start , max_dist , edge_fus->dir );
06034 edge_fus->got_pt = 1;
06035 }
06036 }
06037
06038
06039 for( edge_no=0 ; edge_no < BU_PTBL_END( int_faces ) ; edge_no++ )
06040 {
06041 struct intersect_fus *edge_fus;
06042
06043 edge_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06044 if( !edge_fus->got_pt )
06045 VMOVE( edge_fus->pt , edge_fus->start )
06046 }
06047
06048 if( rt_g.NMG_debug & DEBUG_BASIC )
06049 {
06050 bu_log( "After nmg_get_max_edge_inters:\n" );
06051 nmg_pr_inter( new_v , int_faces );
06052 }
06053
06054 return( 0 );
06055 }
06056
06057
06058
06059
06060
06061
06062
06063
06064 static void
06065 nmg_fuse_inters(struct intersect_fus *i_fus, struct intersect_fus *j_fus, struct bu_ptbl *int_faces, const struct bn_tol *tol)
06066 {
06067 struct edgeuse *radial_eu;
06068 struct edgeuse *prev_eu;
06069
06070 BU_CK_PTBL( int_faces );
06071 BN_CK_TOL( tol );
06072
06073 if( rt_g.NMG_debug & DEBUG_BASIC )
06074 bu_log( "nmg_fuse_inters: i_fus=x%x, j_fus=x%x, %d edges\n" , i_fus, j_fus, BU_PTBL_END( int_faces ) );
06075
06076
06077 radial_eu = j_fus->eu->radial_p;
06078
06079
06080 prev_eu = BU_LIST_PPREV_CIRC( edgeuse , &j_fus->eu->l );
06081
06082 if( EDGESADJ( prev_eu , j_fus->eu ) )
06083 {
06084 nmg_keu( prev_eu );
06085 nmg_keu( j_fus->eu );
06086 }
06087 else
06088 bu_log( "nmg_fuse_inter_verts: ERROR: can't find adjacent edges to kill\n" );
06089
06090
06091 i_fus->fu[1] = j_fus->fu[1];
06092
06093
06094
06095
06096 if( i_fus->fu[0] && j_fus->fu[1] )
06097 {
06098 if( rt_g.NMG_debug & DEBUG_BASIC )
06099 {
06100 bu_log( "radial join of eu's x%x and x%x\n" , i_fus->eu , radial_eu );
06101 bu_log( "\tx%x to x%x and x%x to x%x\n" ,
06102 i_fus->eu->vu_p->v_p, i_fus->eu->eumate_p->vu_p->v_p,
06103 radial_eu->vu_p->v_p, radial_eu->eumate_p->vu_p->v_p );
06104 }
06105 nmg_radial_join_eu( i_fus->eu , radial_eu , tol );
06106 }
06107
06108
06109 if( !i_fus->fu[0] )
06110 i_fus->eu = radial_eu;
06111 NMG_CK_EDGEUSE( i_fus->eu );
06112
06113
06114
06115
06116 if( j_fus->free_edge )
06117 i_fus->free_edge = 1;
06118
06119 bu_ptbl_rm( int_faces , (long *)j_fus );
06120 bu_free( (char *)j_fus , "nmg_split_edges_at_pts: j_fus " );
06121
06122 }
06123
06124
06125
06126
06127
06128
06129
06130
06131
06132 static void
06133 nmg_split_edges_at_pts(const struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
06134 {
06135 int edge_no;
06136
06137 if( rt_g.NMG_debug & DEBUG_BASIC )
06138 bu_log( "nmg_split_edges_at_pts( new_v = x%x , %d intersect_fus structs)\n" , new_v , BU_PTBL_END( int_faces ) );
06139
06140 BN_CK_TOL( tol );
06141 BU_CK_PTBL( int_faces );
06142 NMG_CK_VERTEX( new_v );
06143
06144
06145 for( edge_no=0 ; edge_no < BU_PTBL_END( int_faces ) ; edge_no++ )
06146 {
06147 struct intersect_fus *i_fus;
06148 struct edgeuse *new_eu;
06149
06150 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06151
06152
06153 if( i_fus->fu[0] && i_fus->fu[1] && i_fus->fu[0]->f_p == i_fus->fu[1]->f_p )
06154 continue;
06155
06156 if( bn_pt3_pt3_equal( new_v->vg_p->coord , i_fus->pt , tol ) )
06157 {
06158
06159 i_fus->vp = (struct vertex *)NULL;
06160 VMOVE( i_fus->pt , new_v->vg_p->coord );
06161 VMOVE( i_fus->start , new_v->vg_p->coord );
06162 VSUB2( i_fus->dir , i_fus->eu->eumate_p->vu_p->v_p->vg_p->coord , i_fus->eu->vu_p->v_p->vg_p->coord );
06163 VUNITIZE( i_fus->dir );
06164 continue;
06165 }
06166 new_eu = nmg_esplit( i_fus->vp , i_fus->eu, 0 );
06167 i_fus->vp = new_eu->vu_p->v_p;
06168
06169
06170 if( i_fus->free_edge && !i_fus->fu[0] )
06171 i_fus->eu = new_eu;
06172
06173
06174 if( i_fus && !i_fus->vp->vg_p )
06175 nmg_vertex_gv( i_fus->vp , i_fus->pt );
06176 }
06177 if( rt_g.NMG_debug & DEBUG_BASIC )
06178 {
06179 bu_log( "After splitting edges:\n" );
06180 nmg_pr_inter( new_v , int_faces );
06181 }
06182
06183
06184 edge_no = 0;
06185 while( edge_no < BU_PTBL_END( int_faces ) )
06186 {
06187 int next_edge_no;
06188 struct intersect_fus *i_fus,*j_fus;
06189
06190 next_edge_no = edge_no + 1;
06191 if( next_edge_no == BU_PTBL_END( int_faces ) )
06192 next_edge_no = 0;
06193
06194 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06195 j_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
06196
06197
06198 while( j_fus->fu[0] && j_fus->fu[1] &&
06199 j_fus->fu[0]->f_p == j_fus->fu[1]->f_p &&
06200 j_fus != i_fus )
06201 {
06202
06203 if( i_fus->free_edge && j_fus->free_edge )
06204 break;
06205
06206
06207 if( !i_fus->vp )
06208 break;
06209
06210
06211
06212
06213
06214 (void) nmg_esplit( i_fus->vp , j_fus->eu, 0 );
06215
06216
06217 nmg_fuse_inters( i_fus , j_fus , int_faces , tol );
06218
06219
06220 if( next_edge_no == BU_PTBL_END( int_faces ) )
06221 next_edge_no = 0;
06222
06223 j_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
06224
06225 }
06226 edge_no++;
06227 }
06228 if( rt_g.NMG_debug & DEBUG_BASIC )
06229 {
06230 bu_log( "After loops of same face\n" );
06231 nmg_pr_inter( new_v , int_faces );
06232 }
06233 }
06234
06235
06236
06237
06238
06239
06240 static void
06241 nmg_remove_short_eus_inter(struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
06242 {
06243 int edge_no;
06244 struct vertexuse *vu;
06245
06246 NMG_CK_VERTEX( new_v );
06247 BU_CK_PTBL( int_faces );
06248 BN_CK_TOL( tol );
06249
06250 if( rt_g.NMG_debug & DEBUG_BASIC )
06251 bu_log( "nmg_remove_short_eus: new_v=x%x ( %f %f %f ), %d edges\n" , new_v, V3ARGS( new_v->vg_p->coord ), BU_PTBL_END( int_faces ) );
06252
06253
06254
06255
06256 for( edge_no=0 ; edge_no<BU_PTBL_END( int_faces ) ; edge_no++ )
06257 {
06258 struct intersect_fus *edge_fus;
06259
06260 edge_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06261
06262 if( !edge_fus->vp )
06263 continue;
06264
06265 if( !bn_pt3_pt3_equal( new_v->vg_p->coord , edge_fus->vp->vg_p->coord , tol ) )
06266 continue;
06267
06268 nmg_jv( new_v , edge_fus->vp );
06269 edge_fus->vp = new_v;
06270 }
06271
06272
06273 vu = BU_LIST_FIRST( vertexuse , &new_v->vu_hd );
06274 while( BU_LIST_NOT_HEAD( vu , &new_v->vu_hd ) )
06275 {
06276 struct vertexuse *vu_next;
06277 struct faceuse *fu;
06278 struct loopuse *lu;
06279 struct faceuse *bad_fu=(struct faceuse *)NULL;
06280 int bad_loop=0;
06281
06282 NMG_CK_VERTEXUSE( vu );
06283
06284 vu_next = BU_LIST_PNEXT( vertexuse , &vu->l );
06285
06286 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
06287 {
06288 vu = vu_next;
06289 continue;
06290 }
06291
06292 fu = nmg_find_fu_of_vu( vu );
06293 NMG_CK_FACEUSE( fu );
06294
06295
06296 lu = BU_LIST_FIRST( loopuse , &fu->lu_hd );
06297 while( BU_LIST_NOT_HEAD( lu , &fu->lu_hd ) )
06298 {
06299 struct loopuse *lu_next;
06300 struct edgeuse *eu;
06301
06302 NMG_CK_LOOPUSE( lu );
06303
06304 lu_next = BU_LIST_PNEXT( loopuse , &lu->l );
06305
06306 eu = BU_LIST_FIRST( edgeuse , &lu->down_hd );
06307 while( BU_LIST_NOT_HEAD( eu , &lu->down_hd ) )
06308 {
06309 struct edgeuse *eu_next;
06310
06311 NMG_CK_EDGEUSE( eu );
06312
06313 eu_next = BU_LIST_PNEXT( edgeuse , &eu->l );
06314
06315
06316 if( eu->vu_p->v_p == eu->eumate_p->vu_p->v_p )
06317 {
06318 while( (vu_next == eu->vu_p || vu_next == eu->eumate_p->vu_p ) &&
06319 BU_LIST_NOT_HEAD( vu_next , &new_v->vu_hd ) )
06320 vu_next = BU_LIST_PNEXT( vertexuse , &vu_next->l );
06321 while( (eu_next == eu || eu_next == eu->eumate_p) &&
06322 BU_LIST_NOT_HEAD( eu_next , &lu->down_hd ) )
06323 eu_next = BU_LIST_PNEXT( edgeuse , &eu_next->l );
06324
06325 if( rt_g.NMG_debug & DEBUG_BASIC )
06326 bu_log( "\tkilling eu x%x (x%x)\n" , eu , eu->eumate_p );
06327
06328 bad_loop = nmg_keu( eu );
06329 }
06330
06331 else if( bn_pt3_pt3_equal( eu->vu_p->v_p->vg_p->coord , eu->eumate_p->vu_p->v_p->vg_p->coord , tol ) )
06332 {
06333 struct edgeuse *prev_eu;
06334
06335 prev_eu = BU_LIST_PPREV_CIRC( edgeuse , &eu->l );
06336 NMG_CK_EDGEUSE( prev_eu );
06337
06338 prev_eu->eumate_p->vu_p->v_p = eu->eumate_p->vu_p->v_p;
06339
06340 while( (vu_next == eu->vu_p || vu_next == eu->eumate_p->vu_p ) &&
06341 BU_LIST_NOT_HEAD( vu_next , &new_v->vu_hd ) )
06342 vu_next = BU_LIST_PNEXT( vertexuse , &vu_next->l );
06343 while( (eu_next == eu || eu_next == eu->eumate_p) &&
06344 BU_LIST_NOT_HEAD( eu_next , &lu->down_hd ) )
06345 eu_next = BU_LIST_PNEXT( edgeuse , &eu_next->l );
06346
06347 if( rt_g.NMG_debug & DEBUG_BASIC )
06348 bu_log( "\tkilling eu x%x (x%x)\n" , eu , eu->eumate_p );
06349
06350 bad_loop = nmg_keu( eu );
06351 }
06352
06353 if( bad_loop )
06354 {
06355
06356 while( (lu_next == lu || lu_next == lu->lumate_p) &&
06357 BU_LIST_NOT_HEAD( lu_next , &fu->lu_hd ) )
06358 lu_next = BU_LIST_PNEXT( loopuse , &lu_next->l );
06359
06360 bad_fu = nmg_find_fu_of_lu( lu );
06361 if( !nmg_klu( lu ) )
06362 bad_fu = (struct faceuse *)NULL;
06363
06364 break;
06365 }
06366
06367 eu = eu_next;
06368 }
06369 if( bad_fu )
06370 {
06371
06372 if( nmg_kfu( bad_fu ) )
06373 {
06374
06375 bu_log( "nmg_remove_short_eus_inter: nmg_kfu emptied shell!!!\n" );
06376 break;
06377 }
06378 }
06379 lu = lu_next;
06380 }
06381
06382 vu = vu_next;
06383 }
06384 }
06385
06386
06387
06388
06389
06390
06391 static void
06392 nmg_simplify_inter(const struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
06393 {
06394 int edge_no=0;
06395 int next_edge_no;
06396
06397 if( rt_g.NMG_debug & DEBUG_BASIC )
06398 bu_log( "nmg_simplify_inter( new_v=x%x ( %f %f %f ), int_faces=x%x)\n",
06399 new_v, V3ARGS( new_v->vg_p->coord ) , int_faces );
06400
06401 NMG_CK_VERTEX( new_v );
06402 BU_CK_PTBL( int_faces );
06403 BN_CK_TOL( tol );
06404
06405 while( BU_PTBL_END( int_faces ) > 1 && edge_no < BU_PTBL_END( int_faces ) )
06406 {
06407 struct intersect_fus *i_fus;
06408 struct intersect_fus *j_fus;
06409
06410
06411 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06412 next_edge_no = edge_no+1;
06413 if( next_edge_no == BU_PTBL_END( int_faces ) )
06414 next_edge_no = 0;
06415 j_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
06416
06417
06418 if( (i_fus->free_edge || j_fus->free_edge) && next_edge_no == 0 )
06419 {
06420 edge_no++;
06421 continue;
06422 }
06423
06424
06425 if( i_fus->free_edge && j_fus->free_edge )
06426 {
06427 edge_no++;
06428 continue;
06429 }
06430
06431
06432 if( i_fus->vp == NULL || j_fus->vp == NULL ||
06433 i_fus->eu == NULL || j_fus->eu == NULL )
06434 {
06435 edge_no++;
06436 continue;
06437 }
06438
06439
06440 if( i_fus->vp == new_v || j_fus->vp == new_v )
06441 {
06442 edge_no++;
06443 continue;
06444 }
06445
06446 NMG_CK_VERTEX( i_fus->vp );
06447 NMG_CK_VERTEX( j_fus->vp );
06448 NMG_CK_EDGEUSE( i_fus->eu );
06449 NMG_CK_EDGEUSE( j_fus->eu );
06450
06451
06452
06453
06454 if( i_fus->vp == j_fus->vp )
06455 {
06456 nmg_fuse_inters( i_fus , j_fus , int_faces , tol );
06457 continue;
06458 }
06459 else if( bn_pt3_pt3_equal( i_fus->vp->vg_p->coord , j_fus->vp->vg_p->coord , tol ) )
06460 {
06461 nmg_jv( i_fus->vp , j_fus->vp );
06462 nmg_fuse_inters( i_fus , j_fus , int_faces , tol );
06463 continue;
06464 }
06465 else if( bn_3pts_collinear( i_fus->vp->vg_p->coord , j_fus->vp->vg_p->coord , new_v->vg_p->coord , tol ) )
06466 {
06467 fastf_t i_dist,j_dist;
06468 vect_t i_dist_to_new_v,j_dist_to_new_v;
06469
06470
06471
06472
06473
06474 VSUB2( i_dist_to_new_v , new_v->vg_p->coord , i_fus->vp->vg_p->coord );
06475 VSUB2( j_dist_to_new_v , new_v->vg_p->coord , j_fus->vp->vg_p->coord );
06476
06477 if( VDOT( i_dist_to_new_v , j_dist_to_new_v ) < 0.0 )
06478 {
06479
06480 edge_no++;
06481 continue;
06482 }
06483
06484 i_dist = MAGSQ( i_dist_to_new_v );
06485 j_dist = MAGSQ( j_dist_to_new_v );
06486
06487 if( i_dist < tol->dist_sq || j_dist < tol->dist_sq )
06488 rt_bomb( "nmg_simplify_inter: vertex within tolerance of new_v\n" );
06489
06490 if( rt_g.NMG_debug & DEBUG_BASIC )
06491 bu_log( "\tCollinear vertices x%x, x%x, and x%x\n",
06492 new_v , i_fus->vp , j_fus->vp );
06493
06494 if( i_dist > j_dist && j_dist > tol->dist_sq )
06495 {
06496
06497
06498
06499
06500 if( rt_g.NMG_debug & DEBUG_BASIC )
06501 bu_log( "\tSplitting i_fus->eu x%x at vertex x%x\n" , i_fus->eu , j_fus->vp );
06502
06503 (void)nmg_esplit( j_fus->vp , i_fus->eu, 0 );
06504 i_fus->vp = j_fus->vp;
06505 nmg_fuse_inters( i_fus , j_fus , int_faces , tol );
06506
06507 continue;
06508 }
06509 else if( j_dist > i_dist && i_dist > tol->dist_sq )
06510 {
06511
06512
06513
06514
06515 if( rt_g.NMG_debug & DEBUG_BASIC )
06516 bu_log( "\tSplitting j_fus->eu x%x at vertex x%x\n" , j_fus->eu , i_fus->vp );
06517
06518 (void)nmg_esplit( i_fus->vp , j_fus->eu, 0 );
06519 nmg_fuse_inters( i_fus , j_fus , int_faces , tol );
06520 continue;
06521 }
06522 }
06523 edge_no++;
06524 }
06525 if( rt_g.NMG_debug & DEBUG_BASIC )
06526 {
06527 bu_log( "\nAfter nmg_simplify_inter:\n" );
06528 nmg_pr_inter( new_v , int_faces );
06529 }
06530 }
06531
06532
06533
06534
06535
06536
06537
06538
06539
06540
06541 void
06542 nmg_make_faces_at_vert(struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
06543 {
06544 struct loopuse *old_lu;
06545 int edge_no=0,next_edge_no;
06546
06547 if( rt_g.NMG_debug & DEBUG_BASIC )
06548 bu_log( "nmg_make_faces_at_vert( x%x , %d intersect_fus structs)\n" , new_v , BU_PTBL_END( int_faces ) );
06549
06550 NMG_CK_VERTEX( new_v );
06551 BU_CK_PTBL( int_faces );
06552 BN_CK_TOL( tol );
06553
06554 if( BU_PTBL_END( int_faces ) == 1 )
06555 {
06556 struct intersect_fus *i_fus;
06557
06558
06559
06560
06561 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , 0 );
06562 if( i_fus->vp )
06563 {
06564 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , 0 );
06565
06566 VMOVE( new_v->vg_p->coord , i_fus->vp->vg_p->coord );
06567 nmg_jv( new_v , i_fus->vp );
06568 }
06569 return;
06570 }
06571
06572 if( BU_PTBL_END( int_faces ) == 2 )
06573 {
06574 struct intersect_fus *i_fus,*j_fus;
06575 point_t center_pt;
06576
06577
06578
06579
06580 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , 0 );
06581 j_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , 1 );
06582
06583 if( i_fus->vp && j_fus->vp && !i_fus->free_edge && !j_fus->free_edge )
06584 {
06585 VCOMB2( center_pt , 0.5 , i_fus->vp->vg_p->coord , 0.5 , j_fus->vp->vg_p->coord );
06586 VMOVE( new_v->vg_p->coord , center_pt );
06587 }
06588 return;
06589 }
06590
06591
06592
06593
06594
06595
06596
06597 while( edge_no < BU_PTBL_END( int_faces ) )
06598 {
06599 struct intersect_fus *i_fus;
06600 struct intersect_fus *j_fus;
06601 struct vertexuse *vu1,*vu2;
06602 struct edgeuse *eu;
06603 struct loopuse *lu;
06604 struct loopuse *new_lu;
06605 struct faceuse *new_fu;
06606 struct faceuse *fu;
06607
06608
06609 i_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
06610 next_edge_no = edge_no+1;
06611 if( next_edge_no == BU_PTBL_END( int_faces ) )
06612 next_edge_no = 0;
06613 j_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
06614
06615
06616 if( (i_fus->free_edge || j_fus->free_edge) && next_edge_no == 0 )
06617 {
06618 edge_no++;
06619 continue;
06620 }
06621
06622
06623 if( i_fus->vp == j_fus->vp )
06624 {
06625 edge_no++;
06626 continue;
06627 }
06628
06629
06630 if( i_fus->vp == NULL || j_fus->vp == NULL || i_fus->eu == NULL || j_fus->eu == NULL )
06631 {
06632 edge_no++;
06633 continue;
06634 }
06635
06636
06637 if( i_fus->vp == new_v || j_fus->vp == new_v )
06638 {
06639 edge_no++;
06640 continue;
06641 }
06642
06643 NMG_CK_VERTEX( i_fus->vp );
06644 NMG_CK_VERTEX( j_fus->vp );
06645 NMG_CK_EDGEUSE( i_fus->eu );
06646 NMG_CK_EDGEUSE( j_fus->eu );
06647
06648
06649 if( bn_3pts_collinear( i_fus->vp->vg_p->coord , j_fus->vp->vg_p->coord , new_v->vg_p->coord , tol ) )
06650 {
06651 edge_no++;
06652 continue;
06653 }
06654
06655
06656
06657
06658 old_lu = j_fus->eu->up.lu_p;
06659 vu1 = (struct vertexuse *)NULL;
06660 vu2 = (struct vertexuse *)NULL;
06661 for( BU_LIST_FOR( eu , edgeuse , &old_lu->down_hd ) )
06662 {
06663 if( eu->vu_p->v_p == i_fus->vp )
06664 vu1 = eu->vu_p;
06665 else if( eu->vu_p->v_p == j_fus->vp )
06666 vu2 = eu->vu_p;
06667 }
06668
06669 if( vu1 == NULL || vu2 == NULL )
06670 {
06671 bu_log( "nmg_make_faces_at_vert: ERROR: Can't find loop containing vertices x%x and x%x\n" , i_fus->vp, j_fus->vp );
06672 bu_log( "\t( %f %f %f ) and ( %f %f %f )\n" , V3ARGS( i_fus->vp->vg_p->coord ) , V3ARGS( j_fus->vp->vg_p->coord ) );
06673 edge_no++;
06674 continue;
06675 }
06676
06677
06678
06679
06680 eu = vu1->up.eu_p;
06681 if( eu->eumate_p->vu_p == vu2 )
06682 {
06683 edge_no++;
06684 continue;
06685 }
06686 eu = vu2->up.eu_p;
06687 if( eu->eumate_p->vu_p == vu1 )
06688 {
06689 edge_no++;
06690 continue;
06691 }
06692
06693
06694 new_lu = nmg_cut_loop( vu1 , vu2 );
06695
06696
06697
06698
06699
06700 new_lu->orientation = OT_SAME;
06701 new_lu->lumate_p->orientation = OT_SAME;
06702 old_lu->orientation = OT_SAME;
06703 old_lu->lumate_p->orientation = OT_SAME;
06704
06705
06706
06707
06708 lu = NULL;
06709
06710
06711 for( BU_LIST_FOR( eu , edgeuse , &old_lu->down_hd ) )
06712 {
06713 if( eu->vu_p->v_p == new_v )
06714 {
06715 lu = old_lu;
06716 break;
06717 }
06718 }
06719
06720
06721 if( lu == NULL )
06722 {
06723 for( BU_LIST_FOR( eu , edgeuse , &new_lu->down_hd ) )
06724 {
06725 if( eu->vu_p->v_p == new_v )
06726 {
06727 lu = old_lu;
06728 break;
06729 }
06730 }
06731 }
06732
06733 if( lu == NULL )
06734 {
06735 fu = old_lu->up.fu_p;
06736 bu_log( "nmg_make_faces_at_vert: can't find loop for new face\n" );
06737 bu_log( "vu1 = x%x (x%x) vu2 = x%x (x%x)\n" , vu1 , vu1->v_p , vu2 , vu2->v_p );
06738 bu_log( "new_v = x%x\n" , new_v );
06739 bu_log( "old_lu = x%x , new_lu = x%x\n" , old_lu , new_lu );
06740 nmg_pr_fu_briefly( fu , (char *)NULL );
06741 rt_bomb( "nmg_make_faces_at_vert: can't find loop for new face\n" );
06742 }
06743
06744
06745 new_fu = nmg_mk_new_face_from_loop( lu );
06746
06747
06748 j_fus->fu[0] = new_fu;
06749 i_fus->fu[1] = new_fu;
06750
06751 NMG_CK_FACEUSE( new_fu );
06752
06753
06754 if( nmg_calc_face_g( new_fu ) )
06755 {
06756 bu_log( "nmg_make_faces_at_vert: Failed to calculate plane eqn for face:\n " );
06757 bu_log( "\tnew_v is x%x at ( %f %f %f )\n" , new_v , V3ARGS( new_v->vg_p->coord ) );
06758 if( bn_3pts_collinear( new_v->vg_p->coord,
06759 vu1->v_p->vg_p->coord, vu2->v_p->vg_p->coord,
06760 tol ) )
06761 bu_log( "\tPoints are collinear\n" );
06762 nmg_pr_fu_briefly( new_fu , " " );
06763 }
06764 nmg_face_bb( new_fu->f_p , tol );
06765
06766 edge_no++;
06767 }
06768 }
06769
06770
06771
06772
06773
06774
06775
06776 void
06777 nmg_kill_cracks_at_vertex(const struct vertex *vp)
06778 {
06779 struct bu_ptbl fus_at_vert;
06780 struct vertexuse *vu;
06781 struct faceuse *fu;
06782 int fu_no;
06783
06784 if( rt_g.NMG_debug & DEBUG_BASIC )
06785 bu_log( "nmg_kill_cracks_at_vertex( vp=x%x )\n" , vp );
06786
06787 NMG_CK_VERTEX( vp );
06788
06789
06790 bu_ptbl_init( &fus_at_vert , 64, " &fus_at_vert ");
06791
06792 for( BU_LIST_FOR( vu , vertexuse , &vp->vu_hd ) )
06793 {
06794 NMG_CK_VERTEXUSE( vu );
06795
06796 fu = nmg_find_fu_of_vu( vu );
06797 if( !fu )
06798 continue;
06799
06800 NMG_CK_FACEUSE( fu );
06801 bu_ptbl_ins_unique( &fus_at_vert , (long *)fu );
06802 }
06803
06804
06805 for( fu_no=0 ; fu_no<BU_PTBL_END( &fus_at_vert ) ; fu_no++ )
06806 {
06807 struct loopuse *lu;
06808 int bad_face=0;
06809
06810 fu = (struct faceuse *)BU_PTBL_GET( &fus_at_vert , fu_no );
06811 NMG_CK_FACEUSE( fu );
06812
06813 lu = BU_LIST_FIRST( loopuse , &fu->lu_hd );
06814 while( BU_LIST_NOT_HEAD( lu , &fu->lu_hd ) )
06815 {
06816 struct loopuse *lu_next;
06817 struct edgeuse *eu;
06818 int bad_loop=0;
06819
06820 NMG_CK_LOOPUSE( lu );
06821
06822 lu_next = BU_LIST_NEXT( loopuse , &lu->l );
06823
06824 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
06825 {
06826 lu = lu_next;
06827 continue;
06828 }
06829
06830 eu = BU_LIST_FIRST( edgeuse , &lu->down_hd );
06831 while( BU_LIST_NOT_HEAD( eu , &lu->down_hd ) )
06832 {
06833 struct edgeuse *eu_prev;
06834 struct edgeuse *eu_next;
06835
06836 NMG_CK_EDGEUSE( eu );
06837
06838 eu_next = BU_LIST_NEXT( edgeuse , &eu->l );
06839 eu_prev = BU_LIST_PPREV_CIRC( edgeuse , &eu->l );
06840 NMG_CK_EDGEUSE( eu_prev );
06841
06842
06843 if( EDGESADJ( eu , eu_prev ) )
06844 {
06845
06846 if( nmg_keu( eu ) )
06847 {
06848
06849 bu_log( "ERROR: nmg_kill_cracks_at_vert: bad loopuse x%x\n" , lu );
06850 bad_loop = 1;
06851 break;
06852 }
06853 if( nmg_keu( eu_prev ) )
06854 {
06855 bad_loop = 1;
06856 break;
06857 }
06858 }
06859 eu = eu_next;
06860 }
06861 if( bad_loop )
06862 {
06863 if( nmg_klu( lu ) )
06864 {
06865 bad_face = 1;
06866 break;
06867 }
06868 }
06869 lu = lu_next;
06870 }
06871 if( bad_face )
06872 {
06873 if( nmg_kfu( fu ) )
06874 bu_log( "ERROR:nmg_kill_cracks_at_vert: bad shell!!!\n" );
06875 }
06876 }
06877 bu_ptbl_free( &fus_at_vert );
06878 }
06879
06880
06881
06882
06883
06884
06885
06886
06887
06888
06889 static fastf_t
06890 nmg_dist_to_cross(const struct intersect_fus *i_fus, const struct intersect_fus *j_fus, fastf_t *new_pt, const struct bn_tol *tol)
06891 {
06892 plane_t pl;
06893 struct edgeuse *i_next_eu,*j_next_eu;
06894 struct vertex *i_end,*j_end;
06895 struct vertex *i_start,*j_start;
06896 point_t i_end_pt,j_end_pt;
06897 vect_t i_dir,j_dir;
06898 fastf_t dist[2];
06899
06900 BN_CK_TOL( tol );
06901
06902 if( i_fus->fu[1] )
06903 NMG_GET_FU_PLANE( pl , i_fus->fu[1] )
06904
06905
06906 if( !i_fus->fu[0] )
06907 i_next_eu = BU_LIST_PPREV_CIRC( edgeuse , &i_fus->eu->l );
06908 else
06909 i_next_eu = BU_LIST_PNEXT_CIRC( edgeuse , &i_fus->eu->l );
06910
06911 if( !j_fus->fu[0] )
06912 j_next_eu = BU_LIST_PPREV_CIRC( edgeuse , &j_fus->eu->l );
06913 else
06914 j_next_eu = BU_LIST_PNEXT_CIRC( edgeuse , &j_fus->eu->l );
06915
06916 NMG_CK_EDGEUSE( i_next_eu );
06917 NMG_CK_EDGEUSE( j_next_eu );
06918
06919
06920 i_end = i_next_eu->eumate_p->vu_p->v_p;
06921 j_end = j_next_eu->eumate_p->vu_p->v_p;
06922
06923 NMG_CK_VERTEX( i_end );
06924 NMG_CK_VERTEX( j_end );
06925
06926
06927
06928
06929 if( i_fus->fu[1] )
06930 {
06931 VJOIN1( i_end_pt , i_end->vg_p->coord , -(DIST_PT_PLANE( i_end->vg_p->coord , pl )) , pl )
06932 VJOIN1( j_end_pt , j_end->vg_p->coord , -(DIST_PT_PLANE( j_end->vg_p->coord , pl )) , pl )
06933 }
06934 else
06935 {
06936 VMOVE( i_end_pt , i_end->vg_p->coord )
06937 VMOVE( j_end_pt , j_end->vg_p->coord )
06938 }
06939
06940
06941 i_start = i_next_eu->vu_p->v_p;
06942 j_start = j_next_eu->vu_p->v_p;
06943
06944 NMG_CK_VERTEX( i_start );
06945 NMG_CK_VERTEX( j_start );
06946
06947
06948 VSUB2( i_dir , i_end_pt , i_start->vg_p->coord );
06949 VSUB2( j_dir , j_end_pt , j_start->vg_p->coord );
06950
06951 if( rt_g.NMG_debug & DEBUG_BASIC )
06952 {
06953 bu_log( "nmg_dist_to_cross: checking edges x%x and x%x:\n" , i_fus , j_fus );
06954 bu_log( "\t( %f %f %f ) <-> ( %f %f %f )\n", V3ARGS( i_start->vg_p->coord ), V3ARGS( i_end_pt ) );
06955 bu_log( "\t( %f %f %f ) <-> ( %f %f %f )\n", V3ARGS( j_start->vg_p->coord ), V3ARGS( j_end_pt ) );
06956 }
06957
06958 if( i_fus->free_edge && j_fus->free_edge )
06959 {
06960 fastf_t max_dist0;
06961 fastf_t max_dist1;
06962 int ret_val;
06963
06964 if( rt_g.NMG_debug & DEBUG_BASIC )
06965 bu_log( "\tBoth are free edges\n" );
06966
06967 max_dist0 = MAGNITUDE( i_dir );
06968 VSCALE( i_dir , i_dir , (1.0/max_dist0) )
06969 max_dist1 = MAGNITUDE( j_dir );
06970 VSCALE( j_dir , j_dir , (1.0/max_dist1) )
06971
06972
06973 if( (ret_val=rt_dist_line3_line3( dist , i_start->vg_p->coord , i_dir ,
06974 j_start->vg_p->coord , j_dir , tol )) >= 0 )
06975 {
06976 if( rt_g.NMG_debug & DEBUG_BASIC )
06977 {
06978 bu_log( "max_dists = %f , %f\n" , max_dist0,max_dist1 );
06979 bu_log( "dist = %f , %f\n" , dist[0] , dist[1] );
06980 }
06981
06982
06983
06984
06985 if( dist[0] >= 0.0 && dist[0] <= max_dist0 &&
06986 dist[1] >= 0.0 && dist[1] <= max_dist1 )
06987 {
06988 plane_t pl1,pl2,pl3;
06989
06990 if( rt_g.NMG_debug & DEBUG_BASIC )
06991 {
06992 point_t tmp_pt;
06993
06994 bu_log( "\t\tintersection!!\n" );
06995 VJOIN1( tmp_pt , i_start->vg_p->coord , dist[0] , i_dir );
06996 bu_log( "\t\t\t( %f %f %f )\n" , V3ARGS( tmp_pt ) );
06997 VJOIN1( tmp_pt , j_start->vg_p->coord , dist[1] , j_dir );
06998 bu_log( "\t\t\t( %f %f %f )\n" , V3ARGS( tmp_pt ) );
06999 }
07000
07001
07002 NMG_GET_FU_PLANE( pl1 , j_fus->fu[1] );
07003 NMG_GET_FU_PLANE( pl2 , i_fus->fu[0] );
07004 VCROSS( pl3 , pl1 , pl2 );
07005 pl3[3] = VDOT( pl3 , i_fus->vp->vg_p->coord );
07006 bn_mkpoint_3planes( new_pt , pl1 , pl2 , pl3 );
07007
07008 return( dist[0] );
07009 }
07010 else
07011 return( (fastf_t)(-1.0) );
07012 }
07013 else
07014 {
07015 if( rt_g.NMG_debug & DEBUG_BASIC )
07016 bu_log( "ret_val = %d\n" , ret_val );
07017
07018 return( (fastf_t)(-1.0) );
07019 }
07020 }
07021 else
07022 {
07023
07024 if( bn_isect_lseg3_lseg3( dist , i_start->vg_p->coord , i_dir ,
07025 j_start->vg_p->coord , j_dir , tol ) == 1 )
07026 {
07027 fastf_t len0;
07028
07029 len0 = MAGNITUDE( i_dir );
07030
07031
07032 if( dist[0] == 0.0 )
07033 VMOVE( new_pt , i_start->vg_p->coord )
07034 else if( dist[0] == 1.0 )
07035 VMOVE( new_pt , i_end_pt )
07036 else if( dist[1] == 0.0 )
07037 VMOVE( new_pt , j_start->vg_p->coord )
07038 else if( dist[1] == 1.0 )
07039 VMOVE( new_pt , j_end_pt )
07040 else
07041 VJOIN1( new_pt , i_start->vg_p->coord , dist[0] , i_dir )
07042
07043 if( rt_g.NMG_debug & DEBUG_BASIC )
07044 bu_log( "\tdist=%f, new_pt=( %f %f %f )\n" , dist[0] , V3ARGS( new_pt ) );
07045
07046 return( dist[0]*len0 );
07047 }
07048 else
07049 return( (fastf_t)(-1.0) );
07050 }
07051 }
07052
07053
07054
07055
07056
07057
07058
07059
07060
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076 static void
07077 nmg_fix_crossed_loops(struct vertex *new_v, struct bu_ptbl *int_faces, const struct bn_tol *tol)
07078 {
07079 int edge_no;
07080
07081 if( rt_g.NMG_debug & DEBUG_BASIC )
07082 bu_log( "nmg_fix_crossed_loops( new_v=x%x ( %f %f %f ), %d edges)\n", new_v , V3ARGS( new_v->vg_p->coord ) , BU_PTBL_END( int_faces ) );
07083
07084 NMG_CK_VERTEX( new_v );
07085 BU_CK_PTBL( int_faces );
07086 BN_CK_TOL( tol );
07087
07088
07089 if( BU_PTBL_END( int_faces ) > 2 )
07090 {
07091 for( edge_no=0 ; edge_no<BU_PTBL_END( int_faces ) ; edge_no++ )
07092 {
07093 int next_edge_no,prev_edge_no;
07094 struct intersect_fus *edge_fus;
07095 struct intersect_fus *next_fus,*prev_fus;
07096 fastf_t dist1,dist2;
07097 point_t pt1,pt2;
07098
07099 edge_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
07100
07101 if( !edge_fus->vp )
07102 continue;
07103
07104
07105 next_edge_no = edge_no + 1;
07106 if( next_edge_no == BU_PTBL_END( int_faces ) )
07107 next_edge_no = 0;
07108
07109 next_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
07110
07111
07112 if( next_fus->vp && (!edge_fus->free_edge || !next_fus->free_edge) )
07113 dist1 = nmg_dist_to_cross( edge_fus , next_fus , pt1 , tol );
07114 else
07115 dist1 = (-1.0);
07116
07117
07118 prev_edge_no = edge_no - 1;
07119 if( prev_edge_no < 0 )
07120 prev_edge_no = BU_PTBL_END( int_faces ) - 1;
07121
07122 prev_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , prev_edge_no );
07123
07124
07125 if( prev_fus->vp && (!edge_fus->free_edge || !prev_fus->free_edge) )
07126 dist2 = nmg_dist_to_cross( edge_fus , prev_fus , pt2 , tol );
07127 else
07128 dist2 = (-1.0);
07129
07130
07131 if( dist1 < tol->dist || dist2 < tol->dist )
07132 continue;
07133
07134 if( rt_g.NMG_debug & DEBUG_BASIC )
07135 {
07136 bu_log( "fus=x%x, prev=x%x, next=x%x, dist1=%f, dist2=%f\n",
07137 edge_fus,next_fus,prev_fus,dist1,dist2 );
07138 bu_log( "\t( %f %f %f ), ( %f %f %f )\n" , V3ARGS( pt1 ) , V3ARGS( pt2 ) );
07139 }
07140
07141
07142 if( bn_pt3_pt3_equal( pt1 , pt2 , tol ) )
07143 {
07144 if( rt_g.NMG_debug & DEBUG_BASIC )
07145 bu_log( "\tMerging all three points to pt1\n" );
07146
07147 VMOVE( edge_fus->vp->vg_p->coord , pt1 );
07148 VMOVE( edge_fus->pt , pt1 );
07149 VMOVE( next_fus->vp->vg_p->coord , pt1 );
07150 VMOVE( next_fus->pt , pt1 );
07151 VMOVE( prev_fus->vp->vg_p->coord , pt1 );
07152 VMOVE( prev_fus->pt , pt1 );
07153 }
07154 else if( dist1 > dist2 )
07155 {
07156
07157 if( rt_g.NMG_debug & DEBUG_BASIC )
07158 bu_log( "\tMerging edge and next to pt1, moving prev to pt2\n");
07159 VMOVE( edge_fus->vp->vg_p->coord , pt1 );
07160 VMOVE( edge_fus->pt , pt1 );
07161 VMOVE( next_fus->vp->vg_p->coord , pt1 );
07162 VMOVE( next_fus->pt , pt1 );
07163
07164 VMOVE( prev_fus->vp->vg_p->coord , pt2 );
07165 VMOVE( prev_fus->pt , pt2 );
07166 }
07167 else
07168 {
07169
07170 if( rt_g.NMG_debug & DEBUG_BASIC )
07171 bu_log( "\tMerging edge and prev to pt2, moving next to pt1\n" );
07172 VMOVE( edge_fus->vp->vg_p->coord , pt2 );
07173 VMOVE( edge_fus->pt , pt2 );
07174 VMOVE( prev_fus->vp->vg_p->coord , pt2 );
07175 VMOVE( prev_fus->pt , pt2 );
07176
07177 VMOVE( next_fus->vp->vg_p->coord , pt1 );
07178 VMOVE( next_fus->pt , pt1 );
07179 }
07180 }
07181 }
07182
07183 if( rt_g.NMG_debug & DEBUG_BASIC )
07184 {
07185 bu_log( "After fixing edges that intersect two edges:\n" );
07186 nmg_pr_inter( new_v , int_faces );
07187 }
07188
07189
07190 for( edge_no=0 ; edge_no<BU_PTBL_END( int_faces ) ; edge_no++ )
07191 {
07192 int next_edge_no;
07193 struct intersect_fus *edge_fus;
07194 struct intersect_fus *next_fus;
07195 point_t pt;
07196 fastf_t dist;
07197
07198 edge_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , edge_no );
07199
07200 if( !edge_fus->vp )
07201 continue;
07202
07203
07204 next_edge_no = edge_no + 1;
07205 if( next_edge_no == BU_PTBL_END( int_faces ) )
07206 next_edge_no = 0;
07207
07208 next_fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , next_edge_no );
07209
07210 if( !next_fus->vp )
07211 continue;
07212
07213
07214 dist = nmg_dist_to_cross( edge_fus , next_fus , pt , tol );
07215
07216 if( dist > tol->dist )
07217 {
07218
07219 if( rt_g.NMG_debug & DEBUG_BASIC )
07220 {
07221 bu_log( "edge x%x intersect next edge x%x\n" , edge_fus , next_fus );
07222 bu_log( "\tdist=%f, ( %f %f %f )\n" , dist , V3ARGS( pt ) );
07223 }
07224 if( edge_fus->free_edge && next_fus->free_edge )
07225 {
07226
07227 VMOVE( edge_fus->vp->vg_p->coord , pt );
07228 VMOVE( edge_fus->pt , pt );
07229 VMOVE( next_fus->vp->vg_p->coord , pt );
07230 VMOVE( next_fus->pt , pt );
07231 VMOVE( new_v->vg_p->coord , pt );
07232 }
07233 else
07234 {
07235
07236 VMOVE( edge_fus->vp->vg_p->coord , pt );
07237 VMOVE( edge_fus->pt , pt );
07238 VMOVE( next_fus->vp->vg_p->coord , pt );
07239 VMOVE( next_fus->pt , pt );
07240 }
07241 }
07242 }
07243 if( rt_g.NMG_debug & DEBUG_BASIC )
07244 {
07245 bu_log( "After nmg_fix_crossed_loops:\n" );
07246 nmg_pr_inter( new_v , int_faces );
07247 }
07248 }
07249
07250
07251
07252
07253
07254 static int
07255 nmg_calc_new_v(struct vertex *new_v, const struct bu_ptbl *int_faces, const struct bn_tol *tol)
07256 {
07257 plane_t *planes;
07258 int pl_count;
07259 int i;
07260
07261 NMG_CK_VERTEX( new_v );
07262 BU_CK_PTBL( int_faces );
07263 BN_CK_TOL( tol );
07264
07265 if( rt_g.NMG_debug & DEBUG_BASIC )
07266 bu_log( "nmg_calc_new_v: (%f %f %f) , %d faces\n" , V3ARGS( new_v->vg_p->coord ) , BU_PTBL_END( int_faces ) );
07267
07268
07269 i = BU_PTBL_END( int_faces );
07270 if( i < 3 )
07271 i = 3;
07272 planes = (plane_t *)bu_calloc( i , sizeof( plane_t ) , "nmg_calc_new_v: planes" );
07273
07274 pl_count = 0;
07275
07276 for( i=0 ; i<BU_PTBL_END( int_faces ) ; i++ )
07277 {
07278 struct intersect_fus *fus;
07279 plane_t pl;
07280 int j;
07281 int unique=1;
07282
07283 fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , i );
07284
07285 if( !fus->fu[0] )
07286 continue;
07287
07288 NMG_CK_FACEUSE( fus->fu[0] );
07289 NMG_GET_FU_PLANE( pl , fus->fu[0] );
07290
07291 for( j=0 ; j<pl_count ; j++ )
07292 {
07293 if( bn_coplanar( planes[j] , pl , tol ) > 0 )
07294 {
07295 unique = 0;
07296 break;
07297 }
07298 }
07299
07300 if( !unique )
07301 continue;
07302
07303 VMOVE( planes[pl_count] , pl );
07304 planes[pl_count][H] = pl[H];
07305 pl_count++;
07306 }
07307
07308 if( pl_count > 2 )
07309 {
07310 if( bn_isect_planes( new_v->vg_p->coord , (const plane_t *)planes , pl_count ) )
07311 {
07312 bu_log( "nmg_cacl_new_v: Cannot solve for new geometry at ( %f %f %f )\n",
07313 V3ARGS( new_v->vg_p->coord ) );
07314 bu_free( (char *)planes , "nmg_calc_new_v: planes" );
07315 return( 1 );
07316 }
07317 }
07318 else if( pl_count == 1 )
07319 {
07320 fastf_t vert_move_len;
07321
07322
07323 vert_move_len = DIST_PT_PLANE( new_v->vg_p->coord , planes[0] );
07324 VJOIN1( new_v->vg_p->coord , new_v->vg_p->coord , -vert_move_len , planes[0] );
07325 }
07326 else if( pl_count == 2 )
07327 {
07328 VCROSS( planes[2] , planes[0] , planes[1] );
07329 planes[2][H] = VDOT( new_v->vg_p->coord , planes[2] );
07330 pl_count = 3;
07331 if( bn_mkpoint_3planes( new_v->vg_p->coord , planes[0] , planes[1] , planes[2] ) )
07332 {
07333 bu_log( "nmg_cacl_new_v: 3 planes do not intersect at a point\n" );
07334 bu_free( (char *)planes , "nmg_calc_new_v: planes" );
07335 return( 1 );
07336 }
07337 }
07338 else
07339 {
07340 bu_log( "nmg_calc_new_v: No face planes at vertex x%x (%f %f %f)\n",
07341 new_v , V3ARGS( new_v->vg_p->coord ) );
07342 bu_free( (char *)planes , "nmg_calc_new_v: planes" );
07343 return( 1 );
07344 }
07345
07346 if( rt_g.NMG_debug & DEBUG_BASIC )
07347 bu_log( "\tnew_v = ( %f %f %f )\n" , V3ARGS( new_v->vg_p->coord ) );
07348
07349 bu_free( (char *)planes , "nmg_calc_new_v: planes" );
07350
07351 for( i=0 ; i<BU_PTBL_END( int_faces ) ; i++ )
07352 {
07353 struct intersect_fus *fus;
07354 fastf_t dist;
07355
07356 fus = (struct intersect_fus *)BU_PTBL_GET( int_faces , i );
07357
07358 (void) rt_dist_pt3_line3( &dist , fus->start , fus->start , fus->dir , new_v->vg_p->coord , tol );
07359 }
07360
07361 if( rt_g.NMG_debug & DEBUG_BASIC )
07362 {
07363 bu_log( "After nmg_calc_new_v:\n" );
07364 nmg_pr_inter( new_v , int_faces );
07365 }
07366
07367 return( 0 );
07368 }
07369
07370
07371
07372
07373
07374
07375
07376
07377
07378
07379
07380
07381
07382
07383
07384
07385
07386
07387 int
07388 nmg_complex_vertex_solve(struct vertex *new_v, const struct bu_ptbl *faces, const int free_edges, const int approximate, const struct bn_tol *tol)
07389 {
07390 struct faceuse *fu;
07391 struct face *fp1;
07392 struct bu_ptbl int_faces;
07393 int i;
07394
07395
07396
07397
07398
07399 if( rt_g.NMG_debug & DEBUG_BASIC )
07400 bu_log( "nmg_complex_vertex_solve( new_v = x%x , %d faces )\n" , new_v , BU_PTBL_END( faces ) );
07401
07402 NMG_CK_VERTEX( new_v );
07403 BU_CK_PTBL( faces );
07404 BN_CK_TOL( tol );
07405
07406 if( approximate )
07407 {
07408 plane_t *planes;
07409 int plane_count;
07410
07411 plane_count = BU_PTBL_END( faces );
07412
07413 planes = (plane_t *)bu_calloc( plane_count+free_edges , sizeof( plane_t ) , "nmg_complex_vertex_solve: planes" );
07414
07415
07416 for( i=0 ; i<BU_PTBL_END( faces ) ; i++ )
07417 {
07418 fp1 = (struct face *)BU_PTBL_GET( faces , i );
07419 fu = fp1->fu_p;
07420 NMG_GET_FU_PLANE( planes[i] , fu );
07421
07422 if( rt_g.NMG_debug & DEBUG_BASIC )
07423 bu_log( "\t plane #%d: %g %g %g %g\n", i, V4ARGS( planes[i] ) );
07424 }
07425
07426 if( rt_g.NMG_debug & DEBUG_BASIC )
07427 {
07428 int j;
07429
07430 for( i=0 ; i<BU_PTBL_END( faces ); i++ )
07431 {
07432 fastf_t dot;
07433
07434 dot = VDOT( planes[i], new_v->vg_p->coord );
07435 bu_log( "\tVDOT( #%d, new_v ) - dist = %g\n", i, dot-planes[i][3] );
07436
07437 for( j=0 ; j<BU_PTBL_END( faces ) ; j++ )
07438 {
07439 dot = VDOT( planes[i], planes[j] );
07440 bu_log( "\tVDOT( #%d, #%d ) = %g\n",i,j, dot );
07441 }
07442 }
07443 }
07444
07445 if( free_edges )
07446 {
07447 int free_edge_count=0;
07448 struct vertexuse *vu;
07449 struct faceuse *fu_free=(struct faceuse *)NULL;
07450 struct edgeuse *eu_free=(struct edgeuse *)NULL;
07451
07452 plane_count = BU_PTBL_END( faces );
07453
07454 for( BU_LIST_FOR( vu, vertexuse, &new_v->vu_hd ) )
07455 {
07456 struct edgeuse *eu;
07457
07458 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
07459 continue;
07460
07461 eu = vu->up.eu_p;
07462
07463 if( eu->radial_p == eu->eumate_p )
07464 {
07465 vect_t fu_norm;
07466
07467
07468 eu_free = eu;
07469 fu_free = nmg_find_fu_of_eu( eu_free );
07470 free_edge_count++;
07471
07472 NMG_GET_FU_NORMAL( fu_norm, fu_free );
07473
07474 VCROSS( planes[plane_count], fu_norm, eu_free->g.lseg_p->e_dir );
07475 VUNITIZE( planes[plane_count] );
07476
07477 planes[plane_count][3] = VDOT( planes[plane_count], new_v->vg_p->coord );
07478
07479 if( rt_g.NMG_debug & DEBUG_BASIC )
07480 bu_log( "\t added plane #%d: %g %g %g %g\n", plane_count, V4ARGS( planes[plane_count] ) );
07481
07482 plane_count++;
07483
07484 if( free_edge_count == free_edges )
07485 break;
07486 }
07487 }
07488 }
07489
07490 if( bn_isect_planes( new_v->vg_p->coord , (const plane_t *)planes , plane_count ) )
07491 {
07492 bu_log( "nmg_complex_vertex_solve: Could not calculate new geometry at ( %f %f %f )\n",
07493 V3ARGS( new_v->vg_p->coord ) );
07494 bu_free( (char *) planes , "nmg_complex_vertex_solve: planes" );
07495 return( 1 );
07496 }
07497 bu_free( (char *) planes , "nmg_complex_vertex_solve: planes" );
07498
07499 if( rt_g.NMG_debug & DEBUG_BASIC )
07500 bu_log( "nmg_complex_vertex_solve: new coords = ( %f %f %f )\n",
07501 V3ARGS( new_v->vg_p->coord ) );
07502 return( 0 );
07503 }
07504
07505 bu_ptbl_init( &int_faces , 64, " &int_faces ");
07506
07507
07508
07509
07510 if( nmg_get_edge_lines( new_v , &int_faces , tol ) )
07511 {
07512 bu_ptbl_free( &int_faces );
07513 return( 1 );
07514 }
07515
07516
07517 if( nmg_calc_new_v( new_v , &int_faces , tol ) )
07518 {
07519 bu_ptbl_free( &int_faces );
07520 return( 1 );
07521 }
07522
07523
07524
07525
07526
07527
07528 if (nmg_get_max_edge_inters( new_v , &int_faces , faces , tol ) )
07529 {
07530 bu_ptbl_free( &int_faces );
07531 return( 1 );
07532 }
07533
07534
07535 nmg_split_edges_at_pts( new_v , &int_faces , tol );
07536
07537
07538 nmg_fix_crossed_loops( new_v , &int_faces , tol );
07539
07540 nmg_remove_short_eus_inter( new_v , &int_faces , tol );
07541
07542 nmg_simplify_inter( new_v , &int_faces , tol );
07543
07544
07545 nmg_make_faces_at_vert( new_v , &int_faces , tol );
07546
07547
07548 nmg_kill_cracks_at_vertex( new_v );
07549
07550
07551 for( i=0 ; i<BU_PTBL_END( &int_faces ) ; i++ )
07552 {
07553 struct intersect_fus *i_fus;
07554
07555 i_fus = (struct intersect_fus *)BU_PTBL_GET( &int_faces , i );
07556 bu_free( (char *)i_fus , "nmg_complex_vertex_solve: intersect_fus struct\n" );
07557 }
07558 bu_ptbl_free( &int_faces );
07559
07560 if( rt_g.NMG_debug & DEBUG_BASIC )
07561 bu_log( "nmg_co,mplex_vertex_solve: new coords = ( %f %f %f )\n",
07562 V3ARGS( new_v->vg_p->coord ) );
07563
07564 return( 0 );
07565 }
07566
07567
07568
07569
07570
07571
07572
07573
07574
07575
07576 int
07577 nmg_bad_face_normals(const struct shell *s, const struct bn_tol *tol)
07578 {
07579 struct faceuse *fu;
07580 struct loopuse *lu;
07581 vect_t old_normal;
07582 plane_t new_plane;
07583
07584 NMG_CK_SHELL( s );
07585 BN_CK_TOL( tol );
07586
07587 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
07588 {
07589 fastf_t area = -1;
07590
07591 NMG_CK_FACEUSE( fu );
07592
07593
07594 if( fu->orientation != OT_SAME )
07595 continue;
07596
07597
07598 NMG_GET_FU_NORMAL( old_normal , fu );
07599
07600 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
07601 {
07602 NMG_CK_LOOPUSE( lu );
07603
07604 if( lu->orientation != OT_SAME && lu->orientation != OT_OPPOSITE )
07605 continue;
07606
07607 if( (area = nmg_loop_plane_area( lu , new_plane )) > 0.0 )
07608 {
07609 if( lu->orientation != OT_SAME )
07610 VREVERSE( new_plane , new_plane )
07611 break;
07612 }
07613 }
07614
07615 if( area > 0.0 )
07616 {
07617 if( VDOT( old_normal , new_plane ) < 0.0 )
07618 return( 1 );
07619 }
07620 }
07621 return( 0 );
07622 }
07623
07624
07625
07626
07627
07628
07629
07630
07631
07632
07633
07634 int
07635 nmg_faces_are_radial(const struct faceuse *fu1, const struct faceuse *fu2)
07636 {
07637 struct edgeuse *eu,*eu_tmp;
07638 struct loopuse *lu;
07639
07640 NMG_CK_FACEUSE( fu1 );
07641 NMG_CK_FACEUSE( fu2 );
07642
07643
07644 for( BU_LIST_FOR( lu , loopuse , &fu1->lu_hd ) )
07645 {
07646 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
07647 continue;
07648
07649
07650 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
07651 {
07652
07653 eu_tmp = eu->eumate_p->radial_p;
07654 while( eu_tmp != eu && eu_tmp != eu->eumate_p )
07655 {
07656 struct faceuse *fu_tmp;
07657
07658
07659 fu_tmp = nmg_find_fu_of_eu( eu_tmp );
07660
07661
07662 if( fu_tmp == fu2 || fu_tmp == fu2->fumate_p )
07663 return( 1 );
07664
07665
07666 eu_tmp = eu_tmp->eumate_p->radial_p;
07667 }
07668 }
07669 }
07670
07671 return( 0 );
07672 }
07673
07674
07675
07676
07677
07678
07679
07680
07681
07682
07683
07684
07685
07686
07687
07688
07689 int
07690 nmg_move_edge_thru_pt(struct edgeuse *mv_eu, const fastf_t *pt, const struct bn_tol *tol)
07691 {
07692 struct faceuse *fu,*fu1;
07693 struct edgeuse *eu,*eu1;
07694 struct edge_g_lseg *eg;
07695 struct vertex *v1,*v2;
07696 struct model *m;
07697 vect_t e_dir;
07698 struct bu_ptbl tmp_faces[2];
07699 struct bu_ptbl faces;
07700 int count;
07701 long *flags;
07702
07703 if( rt_g.NMG_debug & DEBUG_BASIC )
07704 bu_log( "nmg_move_edge_thru_pt( mv_eu=x%x , pt=( %f %f %f) )\n" , mv_eu , V3ARGS( pt ) );
07705
07706 NMG_CK_EDGEUSE( mv_eu );
07707 BN_CK_TOL( tol );
07708
07709 m = nmg_find_model( &mv_eu->l.magic );
07710 NMG_CK_MODEL( m );
07711
07712
07713 v1 = mv_eu->vu_p->v_p;
07714 NMG_CK_VERTEX( v1 );
07715 v2 = mv_eu->eumate_p->vu_p->v_p;
07716 NMG_CK_VERTEX( v2 );
07717
07718 eg = mv_eu->g.lseg_p;
07719
07720
07721 if( v1 != v2 )
07722 {
07723 if( eg )
07724 {
07725 NMG_CK_EDGE_G_LSEG(eg);
07726 VMOVE( e_dir , eg->e_dir );
07727 if( mv_eu->orientation == OT_OPPOSITE )
07728 {
07729 VREVERSE( e_dir , e_dir );
07730 }
07731 }
07732 else
07733 {
07734 nmg_edge_g( mv_eu );
07735 eg = mv_eu->g.lseg_p;
07736 VMOVE( e_dir , eg->e_dir );
07737 }
07738 VUNITIZE( e_dir );
07739 }
07740
07741 eu = mv_eu;
07742 fu1 = nmg_find_fu_of_eu( eu );
07743
07744 if( fu1 == NULL )
07745 {
07746 vect_t to_pt;
07747 vect_t move_v;
07748 fastf_t edir_comp;
07749 point_t new_loc;
07750
07751
07752
07753
07754 VSUB2( to_pt , pt , v1->vg_p->coord );
07755 edir_comp = VDOT( to_pt , e_dir );
07756 VJOIN1( move_v , to_pt , -edir_comp , e_dir );
07757
07758
07759 VADD2( new_loc , v1->vg_p->coord , move_v );
07760 nmg_vertex_gv( v1 , new_loc );
07761
07762 if( v2 != v1 )
07763 {
07764 VADD2( new_loc , v2->vg_p->coord , move_v );
07765 nmg_vertex_gv( v2 , new_loc );
07766 }
07767
07768
07769 if( !eg )
07770 nmg_edge_g( eu );
07771 else
07772 VMOVE( eg->e_pt , new_loc )
07773
07774 if( *eu->up.magic_p == NMG_LOOPUSE_MAGIC )
07775 {
07776 struct edgeuse *tmp_eu;
07777
07778
07779
07780
07781
07782 tmp_eu = BU_LIST_PNEXT_CIRC( edgeuse , &eu->l );
07783 NMG_CK_EDGEUSE( tmp_eu );
07784 if( *tmp_eu->g.magic_p == NMG_EDGE_G_LSEG_MAGIC )
07785 {
07786 VMOVE( tmp_eu->g.lseg_p->e_pt , tmp_eu->vu_p->v_p->vg_p->coord )
07787 VSUB2( tmp_eu->g.lseg_p->e_dir, tmp_eu->eumate_p->vu_p->v_p->vg_p->coord, tmp_eu->g.lseg_p->e_pt)
07788 }
07789 tmp_eu = BU_LIST_PPREV_CIRC( edgeuse , &eu->l );
07790 NMG_CK_EDGEUSE( tmp_eu );
07791 if( *tmp_eu->g.magic_p == NMG_EDGE_G_LSEG_MAGIC )
07792 {
07793 VMOVE( tmp_eu->g.lseg_p->e_pt , tmp_eu->vu_p->v_p->vg_p->coord )
07794 VSUB2( tmp_eu->g.lseg_p->e_dir, tmp_eu->eumate_p->vu_p->v_p->vg_p->coord, tmp_eu->g.lseg_p->e_pt)
07795 }
07796 }
07797
07798 return( 0 );
07799 }
07800
07801
07802 if( mv_eu->radial_p->eumate_p != mv_eu->eumate_p->radial_p && mv_eu->radial_p != mv_eu->eumate_p )
07803 {
07804 bu_log( "Cannot handle edges with more than two radial faces\n" );
07805 return( 1 );
07806 }
07807
07808 bu_ptbl_init( &tmp_faces[0] , 64, " &tmp_faces[0] ");
07809 bu_ptbl_init( &tmp_faces[1] , 64, " &tmp_faces[1] ");
07810
07811
07812 if( nmg_find_isect_faces( v1 , &tmp_faces[0] , &count , tol ) > 3 ||
07813 nmg_find_isect_faces( v2 , &tmp_faces[1] , &count , tol ) > 3 )
07814 {
07815 bu_log( "nmg_move_edge_thru_pt: cannot handle complex vertices yet\n" );
07816 bu_ptbl_free( &tmp_faces[0] );
07817 bu_ptbl_free( &tmp_faces[1] );
07818 return( 1 );
07819 }
07820
07821
07822 if( eg )
07823 {
07824 VMOVE( eg->e_pt , pt );
07825 }
07826
07827
07828 fu = fu1;
07829 do
07830 {
07831 struct edgeuse *eu_next;
07832 plane_t plane;
07833 int cross_direction;
07834 vect_t norm;
07835 int done;
07836
07837 NMG_CK_EDGEUSE( eu );
07838 NMG_CK_FACEUSE( fu );
07839
07840 if( fu->orientation == OT_SAME )
07841 NMG_GET_FU_NORMAL( norm , fu )
07842 else
07843 NMG_GET_FU_NORMAL( norm , fu->fumate_p )
07844
07845
07846
07847
07848
07849
07850 eu_next = eu;
07851 done = 0;
07852 while( !done )
07853 {
07854 vect_t to_anchor;
07855 vect_t next_dir;
07856 vect_t cross;
07857 struct vertex *anchor_v;
07858 fastf_t mag;
07859
07860
07861 eu_next = BU_LIST_PNEXT_CIRC( edgeuse , &eu_next->l );
07862
07863
07864 if( eu_next == eu )
07865 {
07866 bu_log( "nmg_move_edge_thru_pt: cannot calculate new plane eqn\n" );
07867 return( 1 );
07868 }
07869
07870
07871 anchor_v = eu_next->eumate_p->vu_p->v_p;
07872
07873 VSUB2( next_dir , anchor_v->vg_p->coord , eu_next->vu_p->v_p->vg_p->coord );
07874 VCROSS( cross , e_dir , next_dir );
07875 if( VDOT( cross , norm ) < 0.0 )
07876 cross_direction = 1;
07877 else
07878 cross_direction = 0;
07879
07880
07881 VSUB2( to_anchor , anchor_v->vg_p->coord , pt );
07882 if( cross_direction )
07883 {
07884 VCROSS( plane , to_anchor , e_dir );
07885 }
07886 else
07887 {
07888 VCROSS( plane , e_dir , to_anchor );
07889 }
07890
07891 mag = MAGNITUDE( plane );
07892 if( mag > SQRT_SMALL_FASTF )
07893 {
07894
07895 mag = 1.0/mag;
07896 VSCALE( plane , plane , mag );
07897 plane[3] = VDOT( plane , pt );
07898
07899
07900 if( fu->orientation == OT_SAME )
07901 nmg_face_g( fu , plane );
07902 else
07903 nmg_face_g( fu->fumate_p , plane );
07904 done = 1;
07905 }
07906 }
07907
07908
07909 eu = eu->eumate_p->radial_p;
07910 fu = nmg_find_fu_of_eu( eu );
07911 }
07912 while( fu != fu1 && fu != fu1->fumate_p );
07913
07914
07915
07916
07917
07918 flags = (long *)bu_calloc( m->maxindex , sizeof( long ) , "nmg_move_edge_thru_pt: flags" );
07919 bu_ptbl_init( &faces , 64, " &faces ");
07920
07921 eu1 = mv_eu;
07922 fu1 = nmg_find_fu_of_eu( eu1 );
07923 fu = fu1;
07924 do
07925 {
07926 struct loopuse *lu;
07927
07928 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
07929 {
07930 struct edgeuse *eu;
07931
07932 NMG_CK_LOOPUSE( lu );
07933
07934 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
07935 {
07936 struct vertexuse *vu;
07937 vu = BU_LIST_FIRST( vertexuse , &lu->down_hd );
07938 if( NMG_INDEX_TEST_AND_SET( flags , vu->v_p ) )
07939 {
07940 bu_ptbl_reset( &faces );
07941
07942
07943 if( nmg_find_isect_faces( vu->v_p , &faces , &count , tol ) > 3 )
07944 {
07945 bu_log( "mg_move_edge_thru_pt: Cannot handle complex vertices\n" );
07946 bu_ptbl_free( &faces );
07947 bu_free( (char *)flags , "mg_move_edge_thru_pt: flags" );
07948 return( 1 );
07949 }
07950
07951 if( nmg_simple_vertex_solve( vu->v_p , &faces, tol ) )
07952 {
07953
07954 bu_log( "nmg_move_edge_thru_pt: Could not solve simple vertex\n" );
07955 bu_ptbl_free( &faces );
07956 bu_free( (char *)flags , "mg_move_edge_thru_pt: flags" );
07957 return( 1 );
07958 }
07959 }
07960 continue;
07961 }
07962
07963 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
07964 {
07965 struct vertexuse *vu;
07966
07967 vu = eu->vu_p;
07968 if( NMG_INDEX_TEST_AND_SET( flags , vu->v_p ) )
07969 {
07970
07971 bu_ptbl_reset( &faces );
07972
07973
07974 if( nmg_find_isect_faces( vu->v_p , &faces , &count , tol ) > 3 )
07975 {
07976 bu_log( "mg_move_edge_thru_pt: Cannot handle complex vertices\n" );
07977 bu_ptbl_free( &faces );
07978 bu_free( (char *)flags , "mg_move_edge_thru_pt: flags" );
07979 return( 1 );
07980 }
07981
07982 if( BU_PTBL_END( &faces ) == 1 &&
07983 (mv_eu->vu_p->v_p == vu->v_p ||
07984 mv_eu->eumate_p->vu_p->v_p == vu->v_p) )
07985 {
07986 vect_t to_pt;
07987 vect_t mv_vect;
07988 vect_t eu_dir;
07989
07990
07991
07992
07993 VSUB2( eu_dir, eu->eumate_p->vu_p->v_p->vg_p->coord, vu->v_p->vg_p->coord );
07994 VUNITIZE( eu_dir );
07995 VSUB2( to_pt, pt , vu->v_p->vg_p->coord );
07996 VJOIN1( mv_vect, to_pt, -VDOT( e_dir, to_pt ), e_dir );
07997 VADD2( vu->v_p->vg_p->coord, vu->v_p->vg_p->coord, mv_vect);
07998 }
07999 else
08000 {
08001 if( nmg_simple_vertex_solve( vu->v_p , &faces, tol ) )
08002 {
08003
08004 bu_log( "nmg_move_edge_thru_pt: Could not solve simple vertex\n" );
08005 bu_ptbl_free( &faces );
08006 bu_free( (char *)flags , "mg_move_edge_thru_pt: flags" );
08007 return( 1 );
08008 }
08009 }
08010
08011
08012 if( eu->e_p != mv_eu->e_p )
08013 {
08014 if( !eu->g.magic_p )
08015 nmg_edge_g( eu );
08016 else
08017 {
08018 VMOVE( eu->g.lseg_p->e_pt, vu->v_p->vg_p->coord );
08019 VSUB2( eu->g.lseg_p->e_dir,
08020 eu->eumate_p->vu_p->v_p->vg_p->coord,
08021 vu->v_p->vg_p->coord );
08022 }
08023 }
08024 }
08025 }
08026 }
08027
08028
08029 eu1 = eu1->eumate_p->radial_p;
08030 fu = nmg_find_fu_of_eu( eu1 );
08031 }
08032 while( fu != fu1 && fu != fu1->fumate_p );
08033
08034 bu_free( (char *)flags , "mg_move_edge_thru_pt: flags" );
08035 bu_ptbl_free( &faces );
08036
08037 return( 0 );
08038 }
08039
08040
08041
08042
08043
08044
08045 void
08046 nmg_vlist_to_wire_edges(struct shell *s, const struct bu_list *vhead)
08047 {
08048 const struct bn_vlist *vp;
08049 struct edgeuse *eu;
08050 struct vertex *v1,*v2;
08051 point_t pt1,pt2;
08052
08053 NMG_CK_SHELL( s );
08054 NMG_CK_LIST( vhead );
08055
08056 v1 = (struct vertex *)NULL;
08057 v2 = (struct vertex *)NULL;
08058
08059 vp = BU_LIST_FIRST( bn_vlist , vhead );
08060 if( vp->nused < 2 )
08061 return;
08062
08063 for( BU_LIST_FOR( vp , bn_vlist , vhead ) )
08064 {
08065 register int i;
08066 register int nused = vp->nused;
08067 vect_t edge_vec;
08068
08069 for( i=0 ; i<nused ; i++ )
08070 {
08071 switch( vp->cmd[i] )
08072 {
08073 case BN_VLIST_LINE_MOVE:
08074 case BN_VLIST_POLY_MOVE:
08075 v1 = (struct vertex *)NULL;
08076 v2 = (struct vertex *)NULL;
08077 VMOVE( pt2 , vp->pt[i] );
08078 break;
08079 case BN_VLIST_LINE_DRAW:
08080 case BN_VLIST_POLY_DRAW:
08081 VSUB2( edge_vec , pt2 , vp->pt[i] );
08082 if( VNEAR_ZERO( edge_vec , SMALL_FASTF ) )
08083 break;
08084 VMOVE( pt1 , pt2 );
08085 v1 = v2;
08086 VMOVE( pt2 , vp->pt[i] );
08087 v2 = (struct vertex *)NULL;
08088 eu = nmg_me( v1 , v2 , s );
08089 v1 = eu->vu_p->v_p;
08090 v2 = eu->eumate_p->vu_p->v_p;
08091 nmg_vertex_gv( v2 , pt2 );
08092 if( !v1->vg_p )
08093 nmg_vertex_gv( v1 , pt1 );
08094 nmg_edge_g( eu );
08095 break;
08096 case BN_VLIST_POLY_START:
08097 case BN_VLIST_POLY_END:
08098 break;
08099 }
08100 }
08101 }
08102 }
08103
08104 void
08105 nmg_follow_free_edges_to_vertex(const struct vertex *vpa, const struct vertex *vpb, struct bu_ptbl *bad_verts, const struct shell *s, const struct edgeuse *eu, struct bu_ptbl *verts, int *found)
08106 {
08107 struct vertexuse *vu;
08108
08109 BU_CK_PTBL( bad_verts );
08110 NMG_CK_EDGEUSE( eu );
08111 NMG_CK_VERTEX( vpa );
08112 NMG_CK_VERTEX( vpb );
08113 if( s )
08114 NMG_CK_SHELL( s );
08115
08116 NMG_CK_VERTEX( eu->eumate_p->vu_p->v_p );
08117
08118 if( rt_g.NMG_debug & DEBUG_BASIC )
08119 {
08120 bu_log( "nmg_follow_free_edges_to_vertex( vpa=x%x, vpb=x%x s=x%x, eu=x%x, found=%d )\n",
08121 vpa,vpb,s,eu,*found );
08122 }
08123
08124 for( BU_LIST_FOR( vu , vertexuse , &eu->eumate_p->vu_p->v_p->vu_hd ) )
08125 {
08126 struct edgeuse *eu1;
08127
08128 NMG_CK_VERTEXUSE( vu );
08129
08130 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
08131 continue;
08132
08133 if( s && (nmg_find_s_of_vu( vu ) != s ) )
08134 continue;
08135
08136 eu1 = vu->up.eu_p;
08137
08138 NMG_CK_EDGEUSE( eu1 );
08139
08140 if( rt_g.NMG_debug & DEBUG_BASIC )
08141 bu_log( "\tchecking eu x%x: x%x ( %f %f %f )\n\t\tto x%x ( %f %f %f )\n", eu1,
08142 eu1->vu_p->v_p, V3ARGS( eu1->vu_p->v_p->vg_p->coord ),
08143 eu1->eumate_p->vu_p->v_p, V3ARGS( eu1->eumate_p->vu_p->v_p->vg_p->coord ) );
08144
08145
08146 if( eu1->eumate_p != eu1->radial_p )
08147 {
08148 if( rt_g.NMG_debug & DEBUG_BASIC )
08149 bu_log( "\t\tnot a dangling edge\n" );
08150 continue;
08151 }
08152
08153
08154 if( eu1 == eu->eumate_p )
08155 {
08156 if( rt_g.NMG_debug & DEBUG_BASIC )
08157 bu_log( "\t\tback the way we came\n" );
08158 continue;
08159 }
08160
08161 if( eu1->eumate_p->vu_p->v_p == vpb )
08162 {
08163
08164 if( rt_g.NMG_debug & DEBUG_BASIC )
08165 bu_log( "\t\tfound goal\n" );
08166 bu_ptbl_ins( verts , (long *)vu->v_p );
08167 bu_ptbl_ins( verts , (long *)vpb );
08168 *found = 1;
08169 }
08170 else if( eu1->eumate_p->vu_p->v_p == vpa )
08171 {
08172
08173 if( rt_g.NMG_debug & DEBUG_BASIC )
08174 bu_log( "\t\tback at start\n" );
08175 continue;
08176 }
08177 else if( bu_ptbl_locate( bad_verts , (long *)eu1->eumate_p->vu_p->v_p ) != (-1))
08178 {
08179
08180 if( rt_g.NMG_debug & DEBUG_BASIC )
08181 bu_log( "\t\tA bad vertex\n" );
08182 continue;
08183 }
08184 else if( bu_ptbl_locate( verts , (long *)eu1->eumate_p->vu_p->v_p ) != (-1))
08185 {
08186
08187 if( rt_g.NMG_debug & DEBUG_BASIC )
08188 bu_log( "a loop\n" );
08189 continue;
08190 }
08191 else
08192 {
08193 if( rt_g.NMG_debug & DEBUG_BASIC )
08194 bu_log( "\t\tinserting vertex x%x\n" , vu->v_p );
08195 bu_ptbl_ins( verts , (long *)vu->v_p );
08196 if( rt_g.NMG_debug & DEBUG_BASIC )
08197 bu_log( "\t\tCalling follow edges\n" );
08198 nmg_follow_free_edges_to_vertex( vpa , vpb , bad_verts , s , eu1 , verts , found );
08199 if( *found < 0 )
08200 {
08201 if( rt_g.NMG_debug & DEBUG_BASIC )
08202 {
08203 bu_log( "\t\treturn is %d\n" , *found );
08204 bu_log( "\t\t\tremove vertex x%x\n" , vu->v_p );
08205 }
08206 bu_ptbl_rm( verts , (long *)vu->v_p );
08207 *found = 0;
08208 }
08209 }
08210 if( *found )
08211 return;
08212 }
08213
08214 *found = (-1);
08215 }
08216
08217 static struct bu_ptbl *
08218 nmg_find_path(const struct vertex *vpa, const struct vertex *vpb, struct bu_ptbl *bad_verts, const struct shell *s)
08219 {
08220 int done;
08221 static struct bu_ptbl verts;
08222 struct vertexuse *vua;
08223
08224
08225 BU_CK_PTBL( bad_verts );
08226 NMG_CK_VERTEX( vpa );
08227 NMG_CK_VERTEX( vpb );
08228
08229 if( rt_g.NMG_debug & DEBUG_BASIC )
08230 {
08231 int i;
08232
08233 bu_log( "nmg_find_path( vpa=x%x ( %f %f %f ), vpb=x%x ( %f %f %f )\n",
08234 vpa, V3ARGS( vpa->vg_p->coord ), vpb, V3ARGS( vpb->vg_p->coord ) );
08235 bu_log( "\t%d vertices to avoid\n" , BU_PTBL_END( bad_verts ) );
08236 for( i=0 ; i<BU_PTBL_END( bad_verts ) ; i++ )
08237 {
08238 struct vertex *vpbad;
08239
08240 vpbad = (struct vertex *)BU_PTBL_GET( bad_verts , i );
08241 bu_log( "\tx%x ( %f %f %f )\n" , vpbad , V3ARGS( vpbad->vg_p->coord ) );
08242 }
08243 }
08244
08245 bu_ptbl_init( &verts , 64, " &verts ");
08246 bu_ptbl_ins( &verts , (long *)vpa );
08247
08248 for( BU_LIST_FOR( vua , vertexuse , &vpa->vu_hd ) )
08249 {
08250 struct edgeuse *eua;
08251
08252 NMG_CK_VERTEXUSE( vua );
08253
08254 if( *vua->up.magic_p != NMG_EDGEUSE_MAGIC )
08255 continue;
08256
08257 if( s && (nmg_find_s_of_vu( vua ) != s) )
08258 continue;
08259
08260 eua = vua->up.eu_p;
08261
08262 NMG_CK_EDGEUSE( eua );
08263
08264 if( rt_g.NMG_debug & DEBUG_BASIC )
08265 bu_log( "\tchecking eu x%x: x%x ( %f %f %f )\n\t\tto x%x ( %f %f %f )\n", eua,
08266 eua->vu_p->v_p, V3ARGS( eua->vu_p->v_p->vg_p->coord ),
08267 eua->eumate_p->vu_p->v_p, V3ARGS( eua->eumate_p->vu_p->v_p->vg_p->coord ) );
08268
08269 if( eua->eumate_p != eua->radial_p )
08270 {
08271 if( rt_g.NMG_debug & DEBUG_BASIC )
08272 bu_log( "\t\tback the way we came!\n" );
08273 continue;
08274 }
08275
08276 if( bu_ptbl_locate( bad_verts , (long *)eua->eumate_p->vu_p->v_p ) != (-1) )
08277 {
08278 if( rt_g.NMG_debug & DEBUG_BASIC )
08279 bu_log( "\t\tOne of the bad vertices!!\n" );
08280 continue;
08281 }
08282
08283 if( eua->eumate_p->vu_p->v_p == vpb )
08284 {
08285 if( rt_g.NMG_debug & DEBUG_BASIC )
08286 bu_log( "\t\tfound goal!!\n" );
08287 bu_ptbl_ins( &verts , (long *)vpb );
08288 return( &verts );
08289 }
08290
08291 done = 0;
08292 if( rt_g.NMG_debug & DEBUG_BASIC )
08293 bu_log( "\tCall follow edges\n" );
08294 nmg_follow_free_edges_to_vertex( vpa, vpb, bad_verts, s, eua, &verts, &done );
08295
08296 if( done == 1 )
08297 break;
08298
08299 bu_ptbl_reset( &verts );
08300 bu_ptbl_ins( &verts , (long *)vpa );
08301 }
08302
08303 if( done != 1 )
08304 bu_ptbl_init( &verts , 64, " &verts ");
08305
08306 return( &verts );
08307 }
08308
08309 void
08310 nmg_glue_face_in_shell(const struct faceuse *fu, struct shell *s, const struct bn_tol *tol)
08311 {
08312 struct loopuse *lu;
08313
08314 NMG_CK_FACEUSE( fu );
08315 NMG_CK_SHELL( s );
08316 BN_CK_TOL( tol );
08317
08318 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
08319 {
08320 struct edgeuse *eu;
08321
08322 NMG_CK_LOOPUSE( lu );
08323 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
08324 continue;
08325
08326 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
08327 {
08328 struct edgeuse *eu1;
08329
08330 NMG_CK_EDGEUSE( eu );
08331
08332 eu1 = nmg_findeu( eu->vu_p->v_p, eu->eumate_p->vu_p->v_p, s, eu, 1 );
08333 if( eu1 )
08334 {
08335 NMG_CK_EDGEUSE( eu1 );
08336 nmg_radial_join_eu( eu1, eu, tol );
08337 }
08338 }
08339 }
08340 }
08341
08342 #if 0
08343 static int
08344 nmg_vert_is_normalward( v, vbase, norm )
08345 struct vertex *v;
08346 struct vertex *vbase;
08347 vect_t norm;
08348 {
08349 vect_t to_v;
08350
08351 NMG_CK_VERTEX( v );
08352 NMG_CK_VERTEX( vbase );
08353
08354 VSUB2( to_v, v->vg_p->coord, vbase->vg_p->coord );
08355 if( VDOT( to_v, norm ) > 0.0 )
08356 return( 1 );
08357 else
08358 return( 0 );
08359 }
08360
08361
08362
08363 static void
08364 Join_eus( v1, v2, v3, tol )
08365 struct vertex *v1,*v2,*v3;
08366 const struct bn_tol *tol;
08367 {
08368 struct edgeuse *eu1;
08369 struct edgeuse *eu2;
08370
08371 if( rt_g.NMG_debug & DEBUG_BASIC )
08372 {
08373 bu_log( "Join_eus:\n" );
08374 bu_log( "\tv1 = x%x ( %g %g %g )\n", v1, V3ARGS( v1->vg_p->coord ) );
08375 bu_log( "\tv2 = x%x ( %g %g %g )\n", v2, V3ARGS( v2->vg_p->coord ) );
08376 bu_log( "\tv3 = x%x ( %g %g %g )\n", v3, V3ARGS( v3->vg_p->coord ) );
08377 }
08378
08379 eu1 = nmg_find_e( v1, v2, (struct shell *)NULL, (struct edge *)NULL );
08380 if( !eu1 )
08381 {
08382 if( rt_g.NMG_debug & DEBUG_BASIC )
08383 bu_log( "\tNo edge found from v1 to v2\n" );
08384 }
08385 else
08386 {
08387 NMG_CK_EDGEUSE( eu1 );
08388
08389 eu2 = nmg_find_e( v1, v2, (struct shell *)NULL, eu1->e_p );
08390 while( eu2 )
08391 {
08392 NMG_CK_EDGEUSE( eu2 );
08393
08394 if( rt_g.NMG_debug & DEBUG_BASIC )
08395 bu_log( "Joining eus x%x and x%x\n" , eu1, eu2 );
08396 nmg_radial_join_eu( eu1, eu2, tol );
08397
08398 eu2 = nmg_find_e( v1, v2, (struct shell *)NULL, eu1->e_p );
08399 }
08400 }
08401
08402 eu1 = nmg_find_e( v2, v3, (struct shell *)NULL, (struct edge *)NULL );
08403 if( !eu1 )
08404 {
08405 if( rt_g.NMG_debug & DEBUG_BASIC )
08406 bu_log( "\tNo edge found from v2 to v3\n" );
08407 }
08408 else
08409 {
08410 NMG_CK_EDGEUSE( eu1 );
08411
08412 eu2 = nmg_find_e( v2, v3, (struct shell *)NULL, eu1->e_p );
08413 while( eu2 )
08414 {
08415 NMG_CK_EDGEUSE( eu2 );
08416 if( rt_g.NMG_debug & DEBUG_BASIC )
08417 bu_log( "Joining eus x%x and x%x\n" , eu1, eu2 );
08418 nmg_radial_join_eu( eu1, eu2, tol );
08419
08420 eu2 = nmg_find_e( v2, v3, (struct shell *)NULL, eu1->e_p );
08421 }
08422 }
08423 }
08424 #endif
08425
08426 static int
08427 nmg_make_connect_faces(struct shell *dst, struct vertex *vpa, struct vertex *vpb, struct bu_ptbl *verts, const struct bn_tol *tol)
08428 {
08429 int done=0;
08430 int i,j;
08431 int verts_in_face=0;
08432 struct vertex *face_verts[20];
08433 struct vertex *v;
08434 int max_vert_no=19;
08435 int made_face;
08436 int faces_made=0;
08437 fastf_t dist_to_a_sq,dist_to_b_sq;
08438 vect_t to_vpa,to_vpb;
08439
08440 if( rt_g.NMG_debug & DEBUG_BASIC )
08441 {
08442 bu_log( "nmg_make_connect_faces( dst=x%x, vpa=x%x ( %f %f %f ), vpb=x%x ( %f %f %f )\n",
08443 dst, vpa, V3ARGS( vpa->vg_p->coord ), vpb, V3ARGS( vpb->vg_p->coord ) );
08444 for( i=0 ; i<BU_PTBL_END( verts ) ; i++ )
08445 {
08446 struct vertex *v;
08447
08448 v = (struct vertex *)BU_PTBL_GET( verts , i );
08449 bu_log( "\tx%x ( %f %f %f )\n" , v , V3ARGS( v->vg_p->coord ) );
08450 }
08451 }
08452
08453 NMG_CK_SHELL( dst );
08454 NMG_CK_VERTEX( vpa );
08455 NMG_CK_VERTEX( vpb );
08456 BU_CK_PTBL( verts );
08457 BN_CK_TOL( tol );
08458
08459 if( BU_PTBL_END( verts ) < 1 )
08460 {
08461 bu_log( "nmg_make_connect_faces: no list of vertices from other shell\n" );
08462 return( 0 );
08463 }
08464 if( BU_PTBL_END( verts ) == 1 )
08465 {
08466 face_verts[0] = vpb;
08467 face_verts[1] = vpa;
08468 face_verts[2] = (struct vertex *)BU_PTBL_GET( verts , 0 );
08469 i = 0;
08470 }
08471 else
08472 {
08473
08474 face_verts[0] = vpa;
08475 face_verts[1] = (struct vertex *)BU_PTBL_GET( verts , 0 );
08476 face_verts[2] = (struct vertex *)BU_PTBL_GET( verts , 1 );
08477 i = 1;
08478 }
08479 v = face_verts[2];
08480 verts_in_face = 3;
08481
08482 VSUB2( to_vpa , vpa->vg_p->coord , v->vg_p->coord );
08483 VSUB2( to_vpb , vpb->vg_p->coord , v->vg_p->coord );
08484
08485 dist_to_a_sq = MAGSQ( to_vpa );
08486 dist_to_b_sq = MAGSQ( to_vpb );
08487
08488 while( 1 )
08489 {
08490 struct faceuse *new_fu;
08491 struct loopuse *lu;
08492 plane_t pl;
08493 fastf_t area;
08494 int still_collinear=0;
08495
08496 made_face = 0;
08497
08498
08499 while( bn_3pts_collinear( face_verts[0]->vg_p->coord,
08500 face_verts[1]->vg_p->coord,
08501 face_verts[verts_in_face - 1]->vg_p->coord, tol) )
08502 {
08503 if( verts_in_face >= max_vert_no )
08504 {
08505 still_collinear = 1;
08506 break;
08507 }
08508
08509 if( i+1 >= BU_PTBL_END( verts ) )
08510 {
08511 still_collinear = 1;
08512 break;
08513 }
08514 i++;
08515 face_verts[verts_in_face] = (struct vertex *)BU_PTBL_GET( verts , i );
08516 verts_in_face++;
08517 }
08518
08519 if( !still_collinear )
08520 {
08521
08522
08523 if( rt_g.NMG_debug & DEBUG_BASIC )
08524 {
08525 int debug_int;
08526
08527 bu_log( "make face:\n" );
08528 for( debug_int=0 ; debug_int<verts_in_face ; debug_int++ )
08529 bu_log( "\tx%x ( %f %f %f )\n" , face_verts[debug_int],
08530 V3ARGS( face_verts[debug_int]->vg_p->coord ) );
08531 }
08532
08533 new_fu = nmg_cface( dst , face_verts , verts_in_face );
08534 lu = BU_LIST_FIRST( loopuse , &new_fu->lu_hd );
08535 area = nmg_loop_plane_area( lu , pl );
08536
08537 if( area <= 0.0 )
08538 {
08539 bu_log( "Bad lu:\n" );
08540 nmg_pr_lu_briefly( lu, " " );
08541 nmg_kfu( new_fu );
08542 rt_bomb( "nmg_make_connect_faces: Failed to calculate plane eqn\n" );
08543 }
08544 else
08545 {
08546 made_face = 1;
08547 faces_made++;
08548
08549 nmg_face_g( new_fu , pl );
08550 nmg_loop_g( lu->l_p, tol );
08551
08552
08553 nmg_glue_face_in_shell( new_fu , dst , tol );
08554 }
08555 }
08556 else
08557 made_face = 0;
08558
08559
08560
08561
08562
08563 if( dist_to_b_sq <= dist_to_a_sq && face_verts[0] == vpa )
08564 {
08565 face_verts[0] = vpb;
08566 face_verts[1] = vpa;
08567 face_verts[2] = v;
08568 verts_in_face = 3;
08569 }
08570 else
08571 {
08572
08573 i++;
08574
08575 if( i < BU_PTBL_END( verts ) )
08576 {
08577 v = (struct vertex *)BU_PTBL_GET( verts , i );
08578 NMG_CK_VERTEX( v );
08579
08580 VSUB2( to_vpa , vpa->vg_p->coord , v->vg_p->coord );
08581 VSUB2( to_vpb , vpb->vg_p->coord , v->vg_p->coord );
08582
08583 dist_to_a_sq = MAGSQ( to_vpa );
08584 dist_to_b_sq = MAGSQ( to_vpb );
08585 face_verts[1] = face_verts[verts_in_face-1];
08586 face_verts[2] = v;
08587 verts_in_face = 3;
08588 }
08589 else if( face_verts[0] == vpa )
08590 {
08591 if( done )
08592 break;
08593
08594
08595 face_verts[0] = vpb;
08596 face_verts[1] = vpa;
08597 face_verts[2] = face_verts[verts_in_face-1];
08598 verts_in_face = 3;
08599 done = 1;
08600 }
08601 else
08602 break;
08603 }
08604
08605 }
08606
08607 if( !made_face )
08608 {
08609 int found;
08610
08611 if( !faces_made )
08612 {
08613
08614
08615
08616 found = 0;
08617 for( i=0 ; i<verts_in_face ; i++ )
08618 {
08619 if( face_verts[i] == vpa )
08620 {
08621 found = 1;
08622 break;
08623 }
08624 }
08625 if( !found )
08626 {
08627 if( verts_in_face < 19 )
08628 {
08629 face_verts[verts_in_face] = vpa;
08630 verts_in_face++;
08631 }
08632 }
08633
08634
08635 found = 0;
08636 for( i=0 ; i<verts_in_face ; i++ )
08637 {
08638 if( face_verts[i] == vpb )
08639 {
08640 found = 1;
08641 break;
08642 }
08643 }
08644 if( !found )
08645 {
08646 if( verts_in_face < 19 )
08647 {
08648 face_verts[verts_in_face] = vpb;
08649 verts_in_face++;
08650 }
08651 }
08652
08653
08654 for( j=0 ; j<BU_PTBL_END( verts ) ; j++ )
08655 {
08656 struct vertex *v_tmp;
08657
08658 v_tmp = (struct vertex *)BU_PTBL_GET( verts, j );
08659 found = 0;
08660 for( i=0 ; i<verts_in_face ; i++ )
08661 {
08662 if( face_verts[i] == v_tmp )
08663 {
08664 found = 1;
08665 break;
08666 }
08667 }
08668 if( !found )
08669 {
08670 if( verts_in_face < 19 )
08671 {
08672 face_verts[verts_in_face] = v_tmp;
08673 verts_in_face++;
08674 }
08675 }
08676 }
08677 }
08678 #if 1
08679 return( 1 );
08680 #else
08681 if( rt_g.NMG_debug & DEBUG_BASIC )
08682 {
08683 bu_log( "nmg_make_connect_faces: Looking for edges to split verts in face = %d\n", verts_in_face );
08684 for( i=0 ; i<verts_in_face ; i++ )
08685 bu_log( "\t x%x ( %g %g %g )\n", face_verts[i], V3ARGS( face_verts[i]->vg_p->coord ) );
08686 }
08687
08688 for( i=0 ; i<verts_in_face-2 ; i++ )
08689 {
08690 for( j=i+1 ; j<verts_in_face-1 ; j++ )
08691 {
08692 for( k=j+1 ; k<verts_in_face ; k++ )
08693 {
08694 struct edgeuse *eu;
08695
08696 if( rt_g.NMG_debug & DEBUG_BASIC )
08697 {
08698 bu_log( "Checking collinearity of:\n" );
08699 bu_log( "\t x%x ( %g %g %g )\n", face_verts[i], V3ARGS( face_verts[i]->vg_p->coord ) );
08700 bu_log( "\t x%x ( %g %g %g )\n", face_verts[j], V3ARGS( face_verts[j]->vg_p->coord ) );
08701 bu_log( "\t x%x ( %g %g %g )\n", face_verts[k], V3ARGS( face_verts[k]->vg_p->coord ) );
08702 }
08703
08704 if( !bn_3pts_collinear( face_verts[i]->vg_p->coord,
08705 face_verts[j]->vg_p->coord,
08706 face_verts[k]->vg_p->coord, tol ) )
08707 continue;
08708 if( rt_g.NMG_debug & DEBUG_BASIC )
08709 bu_log( "\t They are collinear\n" );
08710
08711 if( (eu = nmg_findeu( face_verts[i], face_verts[j], (struct shell *)NULL,
08712 (struct edgeuse *)NULL, 0 ) ) )
08713 {
08714 if( rt_g.NMG_debug & DEBUG_BASIC )
08715 bu_log( "\tFound eu between x%x and x%x\n", face_verts[i], face_verts[j] );
08716
08717 if( !bn_dist_pt3_lseg3( &dist, pca,
08718 face_verts[i]->vg_p->coord,
08719 face_verts[j]->vg_p->coord,
08720 face_verts[k]->vg_p->coord, tol ) )
08721 {
08722 new_eu = nmg_esplit( face_verts[k], eu, 1 );
08723 Join_eus( face_verts[i], face_verts[k], face_verts[j], tol );
08724 }
08725 else if( rt_g.NMG_debug & DEBUG_BASIC )
08726 bu_log( "\t\tvertex x%x is outside eu\n" , face_verts[k] );
08727 }
08728 if( (eu = nmg_findeu( face_verts[i], face_verts[k], (struct shell *)NULL,
08729 (struct edgeuse *)NULL, 0 ) ) )
08730 {
08731 if( rt_g.NMG_debug & DEBUG_BASIC )
08732 bu_log( "\tFound eu between x%x and x%x\n", face_verts[i], face_verts[k] );
08733
08734 if( !bn_dist_pt3_lseg3( &dist, pca,
08735 face_verts[i]->vg_p->coord,
08736 face_verts[k]->vg_p->coord,
08737 face_verts[j]->vg_p->coord, tol ) )
08738 {
08739 new_eu = nmg_esplit( face_verts[j], eu, 1 );
08740 Join_eus( face_verts[i], face_verts[j], face_verts[k], tol );
08741 }
08742 else if( rt_g.NMG_debug & DEBUG_BASIC )
08743 bu_log( "\t\tvertex x%x is outside eu\n" , face_verts[j] );
08744 }
08745 if( (eu = nmg_findeu( face_verts[j], face_verts[k], (struct shell *)NULL,
08746 (struct edgeuse *)NULL, 0 ) ) )
08747 {
08748 if( rt_g.NMG_debug & DEBUG_BASIC )
08749 bu_log( "\tFound eu between x%x and x%x\n", face_verts[j], face_verts[k] );
08750
08751 if( !bn_dist_pt3_lseg3( &dist, pca,
08752 face_verts[j]->vg_p->coord,
08753 face_verts[k]->vg_p->coord,
08754 face_verts[i]->vg_p->coord, tol ) )
08755 {
08756 new_eu = nmg_esplit( face_verts[i], eu, 1 );
08757 Join_eus( face_verts[j], face_verts[i], face_verts[k], tol );
08758 }
08759 else if( rt_g.NMG_debug & DEBUG_BASIC )
08760 bu_log( "\t\tvertex x%x is outside eu\n" , face_verts[i] );
08761 }
08762 }
08763 }
08764 }
08765 #endif
08766 }
08767 return( 0 );
08768 }
08769
08770
08771
08772
08773
08774
08775
08776
08777
08778
08779
08780
08781
08782
08783
08784
08785 struct dangle
08786 {
08787 struct vertex *va,*vb;
08788 struct vertex *v1,*v2;
08789 struct bu_ptbl bad_verts;
08790
08791 int needs_edge_breaking;
08792 };
08793
08794 int
08795 nmg_open_shells_connect(struct shell *dst, struct shell *src, const long int **copy_tbl, const struct bn_tol *tol)
08796 {
08797 struct faceuse *fu;
08798 struct loopuse *lu;
08799 struct edgeuse *eu;
08800 struct bu_ptbl faces;
08801 struct bu_ptbl dangles;
08802 int open_src,open_dst;
08803 int i,j,k;
08804
08805 if( rt_g.NMG_debug & DEBUG_BASIC )
08806 bu_log( "nmg_open_shells_connect( dst=x%x , src=x%x , copy_tbl=x%x)\n" , dst , src , copy_tbl );
08807
08808 NMG_CK_SHELL( dst );
08809 NMG_CK_SHELL( src );
08810 BN_CK_TOL( tol );
08811
08812 open_src = nmg_check_closed_shell( src , tol );
08813 open_dst = nmg_check_closed_shell( dst , tol );
08814
08815 if( !open_dst && !open_src )
08816 {
08817
08818 nmg_js( dst, src, tol );
08819 return( 0 );
08820 }
08821
08822 if( !open_dst )
08823 {
08824 bu_log( "nmg_open_shells_connect: destination shell is closed!\n" );
08825 return( 1 );
08826 }
08827
08828 if( !open_src )
08829 {
08830 bu_log( "nmg_open_shells_connect: source shell is closed!\n" );
08831 return( 1 );
08832 }
08833
08834 bu_ptbl_init( &dangles , 64, " &dangles ");
08835
08836
08837 for( BU_LIST_FOR( fu , faceuse , &dst->fu_hd ) )
08838 {
08839 NMG_CK_FACEUSE( fu );
08840 if( fu->orientation != OT_SAME )
08841 continue;
08842 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
08843 {
08844 NMG_CK_LOOPUSE( lu );
08845 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) == NMG_VERTEXUSE_MAGIC )
08846 continue;
08847
08848 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
08849 {
08850 NMG_CK_EDGEUSE( eu );
08851 if( eu->eumate_p == eu->radial_p )
08852 {
08853 struct dangle *dang;
08854 struct vertexuse *test_vu;
08855 struct vertex *vpbad1,*vpbada;
08856
08857
08858 dang = (struct dangle *)bu_malloc( sizeof( struct dangle ) ,
08859 "nmg_open_shells_connect: dang" );
08860
08861 dang->needs_edge_breaking = 0;
08862 dang->va = eu->vu_p->v_p;
08863 NMG_CK_VERTEX( dang->va );
08864 dang->v1 = NMG_INDEX_GETP(vertex, copy_tbl, dang->va );
08865 NMG_CK_VERTEX( dang->v1 );
08866 dang->vb = eu->eumate_p->vu_p->v_p;
08867 NMG_CK_VERTEX( dang->vb );
08868 dang->v2 = NMG_INDEX_GETP(vertex, copy_tbl, dang->vb );
08869 NMG_CK_VERTEX( dang->v2 );
08870
08871 bu_ptbl_init( &dang->bad_verts , 64, " &dang->bad_verts ");
08872
08873
08874
08875
08876
08877
08878 for( BU_LIST_FOR( test_vu , vertexuse , &dang->va->vu_hd ) )
08879 {
08880 struct edgeuse *test_eu;
08881
08882 if( *test_vu->up.magic_p != NMG_EDGEUSE_MAGIC )
08883 continue;
08884
08885 test_eu = test_vu->up.eu_p;
08886 if( test_eu == eu )
08887 continue;
08888
08889 if( test_eu->eumate_p->vu_p->v_p == dang->vb )
08890 continue;
08891
08892 if( test_eu->eumate_p == test_eu->radial_p )
08893 {
08894
08895
08896
08897
08898 vpbada = test_eu->eumate_p->vu_p->v_p;
08899 vpbad1 = NMG_INDEX_GETP( vertex , copy_tbl , vpbada );
08900 if( vpbad1 )
08901 bu_ptbl_ins( &dang->bad_verts , (long *)vpbad1 );
08902 }
08903 }
08904
08905 for( BU_LIST_FOR( test_vu , vertexuse , &dang->vb->vu_hd ) )
08906 {
08907 struct edgeuse *test_eu;
08908
08909 if( *test_vu->up.magic_p != NMG_EDGEUSE_MAGIC )
08910 continue;
08911
08912 test_eu = test_vu->up.eu_p;
08913 if( test_eu == eu->eumate_p )
08914 continue;
08915
08916
08917 if( test_eu->eumate_p->vu_p->v_p == dang->va )
08918 continue;
08919
08920 if( test_eu->eumate_p == test_eu->radial_p )
08921 {
08922
08923
08924
08925
08926 vpbada = test_eu->eumate_p->vu_p->v_p;
08927 vpbad1 = NMG_INDEX_GETP( vertex , copy_tbl , vpbada );
08928 if( vpbad1 )
08929 bu_ptbl_ins( &dang->bad_verts , (long *)vpbad1 );
08930 }
08931 }
08932 bu_ptbl_ins( &dangles , (long *)dang );
08933 }
08934 }
08935 }
08936 }
08937
08938
08939 for( i=0 ; i<BU_PTBL_END( &dangles ) ; i++ )
08940 {
08941 struct dangle *dang;
08942 struct bu_ptbl *verts;
08943
08944 dang = (struct dangle *)BU_PTBL_GET( &dangles , i );
08945
08946
08947 verts = nmg_find_path( dang->v1 , dang->v2 , &dang->bad_verts , src );
08948
08949
08950 if( BU_PTBL_END( verts ) > 1 )
08951 dang->needs_edge_breaking = nmg_make_connect_faces( dst , dang->va , dang->vb , verts , tol );
08952 else
08953 {
08954 bu_log( "nmg_open_shells_connect: unable to make connecting face\n" );
08955 bu_log( "\tfor edge from x%x ( %f %f %f )\n\t\tto x%x ( %f %f %f )\n",
08956 dang->va, V3ARGS( dang->va->vg_p->coord ),
08957 dang->vb, V3ARGS( dang->vb->vg_p->coord ) );
08958 }
08959
08960 bu_ptbl_free( verts );
08961 bu_ptbl_free( &dang->bad_verts );
08962 }
08963
08964 while( BU_PTBL_END( &dangles ) )
08965 {
08966 struct vertex *verts[4];
08967 struct dangle *dang;
08968 struct edgeuse *eu;
08969 fastf_t dist;
08970 point_t pca;
08971 int done;
08972
08973 dang = (struct dangle *)BU_PTBL_GET( &dangles , BU_PTBL_END( &dangles )-1 );
08974 if( dang->needs_edge_breaking )
08975 {
08976
08977 dang = (struct dangle *)BU_PTBL_GET( &dangles, BU_PTBL_END( &dangles ) - 1 );
08978 verts[0] = dang->va;
08979 verts[1] = dang->vb;
08980 verts[2] = dang->v1;
08981 verts[3] = dang->v2;
08982
08983 for( i=0 ; i<3 ; i++ )
08984 {
08985 for( j=i+1 ; j<4 ; j++ )
08986 {
08987 eu = nmg_findeu( verts[i], verts[j],
08988 0, 0, 1 );
08989 if( !eu )
08990 continue;
08991
08992 for( k=0 ; k<4 ; k++ )
08993 {
08994 if( k == i || k == j )
08995 continue;
08996 if( bn_dist_pt3_lseg3( &dist, pca,
08997 verts[i]->vg_p->coord,
08998 verts[j]->vg_p->coord,
08999 verts[k]->vg_p->coord, tol ) )
09000 continue;
09001
09002 (void)nmg_esplit( verts[k], eu, 1 );
09003 }
09004 }
09005 }
09006 done = 0;
09007 while( !done )
09008 {
09009 done = 1;
09010 for( i=0 ; i<3 ; i++ )
09011 {
09012 for( j=i+1 ; j<4 ; j++ )
09013 {
09014 struct edgeuse *eu2;
09015
09016 eu = nmg_findeu( verts[i], verts[j], 0, 0, 1 );
09017 if( !eu )
09018 continue;
09019
09020 eu2 = nmg_findeu( verts[i], verts[j], 0, eu, 1 );
09021 if( !eu2 )
09022 continue;
09023
09024 if( eu2->vu_p->v_p == eu->vu_p->v_p )
09025 eu2 = eu2->eumate_p;
09026 nmg_je( eu, eu2 );
09027 done = 0;
09028 }
09029 }
09030 }
09031 }
09032 bu_ptbl_rm( &dangles , (long *)dang );
09033 bu_free( (char *)dang , "nmg_open_shells_connect: dang" );
09034 }
09035
09036 bu_ptbl_free( &dangles);
09037 nmg_js( dst , src , tol );
09038
09039
09040 bu_ptbl_init( &faces , 64, " &faces ");
09041 for( BU_LIST_FOR( fu , faceuse , &dst->fu_hd ) )
09042 {
09043 NMG_CK_FACEUSE( fu );
09044 if( fu->orientation == OT_SAME )
09045 bu_ptbl_ins( &faces , (long *)fu );
09046 }
09047 nmg_gluefaces( (struct faceuse **)BU_PTBL_BASEADDR( &faces) , BU_PTBL_END( &faces ), tol );
09048 bu_ptbl_free( &faces );
09049
09050 return( 0 );
09051 }
09052
09053
09054
09055
09056
09057
09058
09059
09060
09061
09062
09063
09064
09065
09066
09067 int
09068 nmg_in_vert(struct vertex *new_v, const int approximate, const struct bn_tol *tol)
09069 {
09070 struct bu_ptbl faces;
09071 int failed=0;
09072 int free_edges=0;
09073 int face_count;
09074
09075 if( rt_g.NMG_debug & DEBUG_BASIC )
09076 bu_log( "nmg_in_vert( new_v=x%x at ( %f %f %f) )\n" , new_v , V3ARGS( new_v->vg_p->coord ) );
09077
09078 NMG_CK_VERTEX( new_v );
09079 BN_CK_TOL( tol );
09080
09081 bu_ptbl_init( &faces , 64, " &faces ");
09082
09083
09084 face_count = nmg_find_isect_faces( new_v , &faces , &free_edges , tol );
09085
09086 if( rt_g.NMG_debug & DEBUG_BASIC )
09087 bu_log( "\tnmg_in_vert: found %d faces at new_v, %d free_edges\n",
09088 face_count, free_edges );
09089
09090 if( (face_count < 4 && !free_edges) || face_count < 3 )
09091 {
09092 if( nmg_simple_vertex_solve( new_v , &faces, tol ) )
09093 {
09094 failed = 1;
09095 bu_log( "Could not solve simple vertex\n" );
09096 }
09097 }
09098 else
09099 {
09100 if( nmg_complex_vertex_solve( new_v , &faces , free_edges , approximate , tol ) )
09101 {
09102 failed = 1;
09103 bu_log( "Could not solve complex vertex\n" );
09104 }
09105 }
09106
09107
09108 bu_ptbl_free( &faces );
09109
09110 return( failed );
09111 }
09112
09113
09114
09115
09116
09117
09118
09119
09120 void
09121 nmg_mirror_model(struct model *m)
09122 {
09123 struct bu_ptbl vertices;
09124 struct nmgregion *r;
09125 int i;
09126 long *flags;
09127
09128 NMG_CK_MODEL( m );
09129
09130
09131 nmg_vertex_tabulate( &vertices , &m->magic );
09132
09133 for( i=0 ; i<BU_PTBL_END( &vertices ) ; i++ )
09134 {
09135 struct vertex *v;
09136
09137 v = (struct vertex *)BU_PTBL_GET( &vertices , i );
09138 NMG_CK_VERTEX( v );
09139
09140 v->vg_p->coord[Y] = (-v->vg_p->coord[Y]);
09141 }
09142 (void)bu_ptbl_free( &vertices );
09143
09144
09145 flags = (long *)bu_calloc( m->maxindex , sizeof( long ) , "nmg_mirror_model: flags" );
09146 for( BU_LIST_FOR( r , nmgregion , &m->r_hd ) )
09147 {
09148 struct shell *s;
09149
09150 for( BU_LIST_FOR( s , shell , &r->s_hd ) )
09151 {
09152 struct faceuse *fu;
09153
09154 for( BU_LIST_FOR( fu , faceuse , &s->fu_hd ) )
09155 {
09156 int orientation;
09157
09158 if( NMG_INDEX_TEST_AND_SET( flags , fu ) )
09159 {
09160
09161 orientation = fu->orientation;
09162 fu->orientation = fu->fumate_p->orientation;
09163 fu->fumate_p->orientation = orientation;
09164 NMG_INDEX_SET( flags , fu->fumate_p );
09165
09166 if( NMG_INDEX_TEST_AND_SET( flags , fu->f_p->g.plane_p ) )
09167 {
09168
09169 fu->f_p->g.plane_p->N[Y] = (-fu->f_p->g.plane_p->N[Y]);
09170 }
09171 }
09172 }
09173 }
09174 }
09175
09176 bu_free( (char *)flags , "nmg_mirror_model: flags " );
09177 }
09178
09179 int
09180 nmg_kill_cracks(struct shell *s)
09181 {
09182 struct faceuse *fu;
09183 struct faceuse *fu_next;
09184 int empty_shell=0;
09185
09186 if( rt_g.NMG_debug & DEBUG_BASIC )
09187 bu_log( "nmg_kill_cracks( s=%x )\n" , s );
09188
09189 NMG_CK_SHELL( s );
09190 #if 1
09191
09192
09193
09194
09195
09196
09197 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
09198 {
09199 struct loopuse *lu;
09200 NMG_CK_FACEUSE( fu );
09201
09202 if( fu->orientation != OT_SAME )
09203 continue;
09204
09205 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
09206 {
09207 struct edgeuse *eu;
09208
09209 NMG_CK_LOOPUSE( lu );
09210
09211 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
09212 continue;
09213 again:
09214 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
09215 {
09216 struct edgeuse *eu2;
09217
09218 NMG_CK_EDGEUSE( eu );
09219
09220 for( BU_LIST_FOR( eu2, edgeuse, &lu->down_hd ) )
09221 {
09222 struct loopuse *new_lu1;
09223 struct loopuse *new_lu2;
09224
09225 if( eu == eu2 )
09226 continue;
09227
09228
09229 if( eu->e_p != eu2->e_p )
09230 continue;
09231
09232 if( eu2 == BU_LIST_PNEXT_CIRC( edgeuse, &eu->l ) )
09233 {
09234
09235 continue;
09236 }
09237 if( eu2 == BU_LIST_PPREV_CIRC( edgeuse, &eu->l ) )
09238 {
09239
09240 continue;
09241 }
09242
09243 if( eu->vu_p->v_p == eu2->vu_p->v_p )
09244 {
09245
09246 continue;
09247 }
09248
09249 if( eu->eumate_p->vu_p->v_p != eu2->vu_p->v_p )
09250 {
09251
09252 bu_log( "nmg_kill_cracks: found a strange crack at eu1=x%x, eu2=x%x\n", eu, eu2 );
09253 nmg_pr_lu_briefly( lu, "" );
09254 rt_bomb( "nmg_kill_cracks: found a strange crack\n" );
09255 }
09256
09257 new_lu1 = nmg_split_lu_at_vu( lu, eu->vu_p );
09258 new_lu2 = nmg_split_lu_at_vu( new_lu1, eu2->vu_p );
09259
09260 nmg_klu( new_lu2 );
09261
09262 nmg_lu_reorient( lu );
09263 nmg_lu_reorient( new_lu1 );
09264
09265 goto again;
09266 }
09267 }
09268 }
09269 }
09270 #endif
09271 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
09272 while( BU_LIST_NOT_HEAD( fu, &s->fu_hd ) )
09273 {
09274 struct loopuse *lu;
09275 struct loopuse *lu_next;
09276 int empty_face=0;
09277
09278 NMG_CK_FACEUSE( fu );
09279
09280 fu_next = BU_LIST_PNEXT( faceuse, &fu->l );
09281 while( BU_LIST_NOT_HEAD( fu_next, &s->fu_hd )
09282 && fu_next == fu->fumate_p )
09283 fu_next = BU_LIST_PNEXT( faceuse, &fu_next->l );
09284
09285 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
09286 while( BU_LIST_NOT_HEAD( lu, &fu->lu_hd ) )
09287 {
09288 struct edgeuse *eu;
09289 struct edgeuse *eu_next;
09290 int empty_loop=0;
09291
09292 NMG_CK_LOOPUSE( lu );
09293
09294 lu_next = BU_LIST_PNEXT( loopuse, &lu->l );
09295
09296 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
09297 {
09298 lu = lu_next;
09299 continue;
09300 }
09301
09302 crack_top:
09303 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
09304 {
09305 NMG_CK_EDGEUSE( eu );
09306
09307 eu_next = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
09308 NMG_CK_EDGEUSE( eu_next );
09309
09310 if( eu->vu_p->v_p != eu_next->eumate_p->vu_p->v_p )
09311 continue;
09312
09313 if( nmg_keu( eu ) )
09314 empty_loop = 1;
09315 else if( nmg_keu( eu_next ) )
09316 empty_loop = 1;
09317
09318 if( empty_loop )
09319 break;
09320
09321 goto crack_top;
09322 }
09323 if( empty_loop )
09324 {
09325 if( nmg_klu( lu ) )
09326 {
09327 empty_face = 1;
09328 break;
09329 }
09330 }
09331 lu = lu_next;
09332 }
09333 if( empty_face )
09334 {
09335 if( nmg_kfu( fu ) )
09336 {
09337 empty_shell = 1;
09338 break;
09339 }
09340 }
09341 fu = fu_next;
09342 }
09343
09344 if( empty_shell )
09345 {
09346 if( rt_g.NMG_debug & DEBUG_BASIC )
09347 bu_log( "nmg_kill_cracks: ret = %d\n" , empty_shell );
09348 return( empty_shell );
09349 }
09350
09351
09352 if( rt_g.NMG_debug & DEBUG_BASIC )
09353 bu_log( "nmg_kill_cracks: ret = %d\n" , empty_shell );
09354
09355 return( empty_shell );
09356 }
09357
09358 int
09359 nmg_kill_zero_length_edgeuses(struct model *m)
09360 {
09361 struct nmgregion *r;
09362 int empty_model=0;
09363
09364 if( rt_g.NMG_debug & DEBUG_BASIC )
09365 bu_log( "nmg_kill_zero_length_edgeuses( m=%x )\n", m );
09366
09367 NMG_CK_MODEL( m );
09368
09369 r = BU_LIST_FIRST( nmgregion, &m->r_hd );
09370 while( BU_LIST_NOT_HEAD( r, &m->r_hd ) )
09371 {
09372 struct nmgregion *next_r;
09373 struct shell *s;
09374 int empty_region=0;
09375
09376 NMG_CK_REGION( r );
09377
09378 next_r = BU_LIST_PNEXT( nmgregion, &r->l );
09379
09380 s = BU_LIST_FIRST( shell, &r->s_hd );
09381 while( BU_LIST_NOT_HEAD( s, &r->s_hd ) )
09382 {
09383 struct shell *next_s;
09384 struct faceuse *fu;
09385 int empty_shell=0;
09386
09387 NMG_CK_SHELL( s );
09388
09389 next_s = BU_LIST_PNEXT( shell, &s->l );
09390
09391 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
09392 while( BU_LIST_NOT_HEAD( fu, &s->fu_hd ) )
09393 {
09394 struct loopuse *lu;
09395 struct faceuse *next_fu;
09396 int empty_fu=0;
09397
09398 NMG_CK_FACEUSE( fu );
09399
09400 next_fu = BU_LIST_PNEXT( faceuse, &fu->l );
09401 if( next_fu == fu->fumate_p )
09402 next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l );
09403
09404 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
09405 while( BU_LIST_NOT_HEAD( lu, &fu->lu_hd ) )
09406 {
09407 struct edgeuse *eu;
09408 struct loopuse *next_lu;
09409 int empty_loop=0;
09410
09411 NMG_CK_LOOPUSE( lu );
09412
09413 next_lu = BU_LIST_PNEXT( loopuse, &lu->l );
09414
09415 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
09416 {
09417 lu = next_lu;
09418 continue;
09419 }
09420
09421 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
09422 while( BU_LIST_NOT_HEAD( eu, &lu->down_hd ) )
09423 {
09424 struct edgeuse *next_eu;
09425 struct edgeuse *next_eu_circ;
09426
09427 NMG_CK_EDGEUSE( eu );
09428
09429 next_eu = BU_LIST_PNEXT( edgeuse, &eu->l );
09430 next_eu_circ = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
09431
09432 if( eu->vu_p->v_p == next_eu_circ->vu_p->v_p )
09433 {
09434
09435 if( nmg_keu( eu ) )
09436 empty_loop = 1;
09437 }
09438 eu = next_eu;
09439 }
09440 if( empty_loop )
09441 {
09442 if( nmg_klu( lu ) )
09443 empty_fu = 1;
09444 }
09445 lu = next_lu;
09446 }
09447 if( empty_fu )
09448 {
09449 if( nmg_kfu( fu ) )
09450 empty_shell = 1;
09451 }
09452 fu = next_fu;
09453 }
09454 if( empty_shell )
09455 {
09456 if( nmg_ks( s ) )
09457 empty_region = 1;
09458 }
09459 s = next_s;
09460 }
09461 if( empty_region )
09462 {
09463 if( nmg_kr( r ) )
09464 empty_model = 1;
09465 }
09466 r = next_r;
09467 }
09468
09469 if( empty_model )
09470 return( 1 );
09471 else
09472 return( 0 );
09473 }
09474
09475
09476
09477
09478
09479
09480
09481 void
09482 nmg_make_faces_within_tol(struct shell *s, const struct bn_tol *tol)
09483 {
09484 struct bu_ptbl faceuses;
09485 struct faceuse *fu;
09486 int i;
09487
09488 NMG_CK_SHELL( s );
09489 BN_CK_TOL( tol );
09490
09491 bu_ptbl_init( &faceuses, 64, " &faceuses");
09492
09493 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
09494 {
09495 NMG_CK_FACEUSE( fu );
09496
09497 if( fu->orientation != OT_SAME )
09498 continue;
09499
09500 bu_ptbl_ins( &faceuses, (long *)fu );
09501 }
09502
09503 for (i = 0; i < BU_PTBL_END( &faceuses ); i++)
09504 {
09505 fu = (struct faceuse *)BU_PTBL_GET( &faceuses, i );
09506
09507
09508 if( nmg_ck_fu_verts( fu, fu->f_p, tol ) )
09509 {
09510 plane_t pl;
09511
09512
09513 nmg_triangulate_fu( fu, tol );
09514
09515
09516 (void)nmg_split_loops_into_faces( &fu->l.magic, tol );
09517
09518 if( nmg_calc_face_plane( fu, pl ) )
09519 {
09520 bu_log( "nmg_make_faces_within_tol(): nmg_calc_face_plane() failed\n" );
09521 rt_bomb( "nmg_make_faces_within_tol(): nmg_calc_face_plane() failed" );
09522 }
09523 nmg_face_new_g( fu, pl );
09524 }
09525 }
09526
09527 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
09528 {
09529 plane_t pl;
09530
09531 if( fu->orientation != OT_SAME )
09532 continue;
09533
09534 if( bu_ptbl_locate( &faceuses, (long *)fu ) != (-1) )
09535 continue;
09536
09537 if( nmg_calc_face_plane( fu, pl ) )
09538 {
09539 bu_log( "nmg_make_faces_within_tol(): nmg_calc_face_plane() failed\n" );
09540 rt_bomb( "nmg_make_faces_within_tol(): nmg_calc_face_plane() failed" );
09541 }
09542
09543 nmg_face_new_g( fu, pl );
09544 }
09545
09546 bu_ptbl_free( &faceuses);
09547 }
09548
09549 void
09550 nmg_intersect_loops_self(struct shell *s, const struct bn_tol *tol)
09551 {
09552 struct faceuse *fu;
09553 struct bu_ptbl edgeuses;
09554
09555 NMG_CK_SHELL( s );
09556 BN_CK_TOL( tol );
09557
09558 bu_ptbl_init( &edgeuses, 64, " &edgeuses");
09559
09560 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
09561 {
09562 struct loopuse *lu;
09563
09564 NMG_CK_FACEUSE( fu );
09565
09566 if( fu->orientation != OT_SAME )
09567 continue;
09568
09569 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
09570 {
09571 struct edgeuse *eu;
09572 int i,j;
09573
09574 NMG_CK_LOOPUSE( lu );
09575
09576 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
09577 continue;
09578 top:
09579 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
09580 bu_ptbl_ins( &edgeuses, (long *)eu );
09581
09582 for( i=0 ; i<BU_PTBL_END( &edgeuses ); i++ )
09583 {
09584 vect_t eu_dir;
09585
09586 eu = (struct edgeuse *)BU_PTBL_GET( &edgeuses, i );
09587 VSUB2( eu_dir, eu->eumate_p->vu_p->v_p->vg_p->coord, eu->vu_p->v_p->vg_p->coord );
09588
09589 for( j=i+1 ; j<BU_PTBL_END( &edgeuses ) ; j++ )
09590 {
09591 struct edgeuse *eu2;
09592 struct edgeuse *new_eu=(struct edgeuse *)NULL;
09593 struct vertex *v;
09594 vect_t eu2_dir;
09595 point_t int_pt;
09596 fastf_t dist[2];
09597 int code;
09598
09599 eu2 = (struct edgeuse *)BU_PTBL_GET( &edgeuses, j );
09600 VSUB2( eu2_dir, eu2->eumate_p->vu_p->v_p->vg_p->coord, eu2->vu_p->v_p->vg_p->coord );
09601
09602 code = bn_isect_lseg3_lseg3( dist, eu->vu_p->v_p->vg_p->coord, eu_dir,
09603 eu2->vu_p->v_p->vg_p->coord, eu2_dir, tol );
09604
09605 if( code < 0 )
09606 continue;
09607
09608 if( code == 0 )
09609 {
09610 if( dist[0] > 0.0 && dist[0] != 1.0 )
09611 {
09612 VJOIN1( int_pt, eu->vu_p->v_p->vg_p->coord, dist[0], eu_dir );
09613 v = (struct vertex *)NULL;
09614 new_eu = nmg_ebreaker( v, eu, tol );
09615 nmg_vertex_gv( new_eu->vu_p->v_p, int_pt );
09616 }
09617 if( dist[1] > 0.0 && dist[1] != 1.0 )
09618 {
09619 VJOIN1( int_pt, eu->vu_p->v_p->vg_p->coord, dist[1], eu_dir );
09620 v = (struct vertex *)NULL;
09621 new_eu = nmg_ebreaker( v, eu, tol );
09622 nmg_vertex_gv( new_eu->vu_p->v_p, int_pt );
09623 }
09624 }
09625 else
09626 {
09627 if( dist[0] != 0.0 && dist[0] != 1.0 )
09628 {
09629 VJOIN1( int_pt, eu->vu_p->v_p->vg_p->coord, dist[0], eu_dir );
09630 v = (struct vertex *)NULL;
09631 new_eu = nmg_ebreaker( v, eu, tol );
09632 nmg_vertex_gv( new_eu->vu_p->v_p, int_pt );
09633 }
09634 if( dist[1] != 0.0 && dist[1] != 1.0 )
09635 {
09636 VJOIN1( int_pt, eu2->vu_p->v_p->vg_p->coord, dist[1], eu2_dir );
09637 v = (struct vertex *)NULL;
09638 new_eu = nmg_ebreaker( v, eu2, tol );
09639 nmg_vertex_gv( new_eu->vu_p->v_p, int_pt );
09640 }
09641
09642 }
09643 if( new_eu )
09644 {
09645 bu_ptbl_reset( &edgeuses);
09646 goto top;
09647 }
09648 }
09649 }
09650
09651 bu_ptbl_reset( &edgeuses);
09652 }
09653 }
09654
09655 bu_ptbl_free( &edgeuses);
09656 }
09657
09658
09659
09660
09661
09662
09663
09664
09665
09666
09667
09668 struct edge_g_cnurb *
09669 rt_join_cnurbs(struct bu_list *crv_head)
09670 {
09671 struct edge_g_cnurb *crv,*next_crv;
09672 struct edge_g_cnurb *new_crv=(struct edge_g_cnurb *)NULL;
09673 fastf_t knot_delta=0.0;
09674 fastf_t last_knot=0.0;
09675 int ncoords;
09676 int knot_index=(-1);
09677 int max_order=0;
09678 int ctl_points=1;
09679 int ctl_index=(-1);
09680 int knot_length=0;
09681 int pt_type=0;
09682 int curve_count=0;
09683 int i,j;
09684
09685 BU_CK_LIST_HEAD( crv_head );
09686
09687
09688
09689
09690 for( BU_LIST_FOR( crv, edge_g_cnurb, crv_head ) )
09691 {
09692 curve_count++;
09693 rt_nurb_c_print( crv);
09694 if( crv->order > max_order )
09695 max_order = crv->order;
09696
09697 i = 0;
09698 while( crv->k.knots[++i] == crv->k.knots[0] );
09699 if( i != crv->order )
09700 {
09701 bu_log( "Curve does not have multiplicity equal to order at start:\n" );
09702 rt_nurb_c_print( crv);
09703 return( new_crv );
09704 }
09705
09706 i = crv->k.k_size - 1;
09707 while( crv->k.knots[--i] == crv->k.knots[crv->k.k_size - 1] );
09708 if( crv->k.k_size - i - 1 != crv->order )
09709 {
09710 bu_log( "Curve does not have multiplicity equal to order at end:\n" );
09711 rt_nurb_c_print( crv);
09712 return( new_crv );
09713 }
09714
09715 if( pt_type == 0 )
09716 pt_type = crv->pt_type;
09717 else
09718 {
09719 if( crv->pt_type != pt_type )
09720 {
09721 bu_log( "rt_join_cnurbs: curves are not the same pt_type (%d vs %d)\n",
09722 pt_type, crv->pt_type );
09723 return( new_crv );
09724 }
09725 }
09726 }
09727
09728
09729 if( curve_count < 2 )
09730 {
09731 crv = BU_LIST_FIRST( edge_g_cnurb, crv_head );
09732 BU_LIST_DEQUEUE( &crv->l );
09733 return( crv );
09734 }
09735
09736
09737 for( BU_LIST_FOR( crv, edge_g_cnurb, crv_head ) )
09738 {
09739 if( crv->order == max_order )
09740 continue;
09741
09742
09743
09744 rt_bomb( "rt_join_cnurbs: Need to raise order of curve\n" );
09745 }
09746
09747
09748 crv = BU_LIST_FIRST( edge_g_cnurb, crv_head );
09749 ncoords = RT_NURB_EXTRACT_COORDS( crv->pt_type );
09750 next_crv = BU_LIST_NEXT( edge_g_cnurb, &crv->l );
09751 while( BU_LIST_NOT_HEAD( &next_crv->l, crv_head ) )
09752 {
09753 int endpoints_equal;
09754
09755 endpoints_equal = 1;
09756
09757 for( i=0 ; i<ncoords ; i++ )
09758 {
09759
09760
09761
09762 if( crv->ctl_points[(crv->c_size-1)*ncoords+i] == next_crv->ctl_points[i] )
09763 continue;
09764 else
09765 {
09766 endpoints_equal = 0;
09767 break;
09768 }
09769 }
09770 if( endpoints_equal )
09771 {
09772
09773 crv = next_crv;
09774 next_crv = BU_LIST_NEXT( edge_g_cnurb, &crv->l );
09775 continue;
09776 }
09777
09778 bu_log( "rt_join_cnurbs: Curve endpoints do not match:\n" );
09779 rt_nurb_c_print( crv );
09780 rt_nurb_c_print( next_crv );
09781 return( new_crv );
09782 }
09783
09784
09785 crv = BU_LIST_FIRST( edge_g_cnurb, crv_head );
09786 knot_length = crv->order;
09787 for( BU_LIST_FOR( crv, edge_g_cnurb, crv_head ) )
09788 {
09789 ctl_points += (crv->c_size - 1);
09790 knot_length += (crv->k.k_size - crv->order - 1);
09791
09792 }
09793 knot_length++;
09794
09795 new_crv = rt_nurb_new_cnurb( max_order, knot_length, ctl_points, pt_type );
09796
09797 crv = BU_LIST_FIRST( edge_g_cnurb, crv_head );
09798
09799
09800 for( i=0 ; i<crv->order ; i++ )
09801 new_crv->k.knots[++knot_index] = crv->k.knots[i];
09802
09803
09804 for( j=0 ; j<ncoords ; j++ )
09805 new_crv->ctl_points[j] = crv->ctl_points[j];
09806
09807 ctl_index = 0;
09808 knot_delta = new_crv->k.knots[knot_index];
09809
09810
09811 for( BU_LIST_FOR( crv, edge_g_cnurb, crv_head ) )
09812 {
09813
09814 for( i=crv->order ; i<crv->k.k_size-crv->order ; i++ )
09815 {
09816 new_crv->k.knots[++knot_index] = crv->k.knots[i] + knot_delta;
09817 }
09818
09819
09820 for( i=0 ; i<crv->order-1 ; i++ )
09821 new_crv->k.knots[++knot_index] = crv->k.knots[crv->k.k_size-1] + knot_delta;
09822
09823 knot_delta += crv->k.knots[crv->k.k_size-1];
09824 last_knot = new_crv->k.knots[knot_index];
09825
09826
09827 for( i=1 ; i<crv->c_size ; i++ )
09828 {
09829 ctl_index++;
09830 VMOVEN( &new_crv->ctl_points[ctl_index*ncoords], &crv->ctl_points[i*ncoords], ncoords );
09831 }
09832 }
09833 new_crv->k.knots[++knot_index] = last_knot;
09834
09835 return( new_crv );
09836 }
09837
09838
09839
09840
09841
09842
09843
09844
09845
09846
09847
09848
09849 struct edge_g_cnurb *
09850 rt_arc2d_to_cnurb(fastf_t *i_center, fastf_t *i_start, fastf_t *i_end, int point_type, const struct bn_tol *tol)
09851 {
09852 struct edge_g_cnurb *crv;
09853 struct bu_list crv_head;
09854 point_t center;
09855 point_t start;
09856 point_t end;
09857 double angle;
09858 double angles[3];
09859 double radius;
09860 double tmp_radius;
09861 vect_t v1, v2;
09862 vect_t ref1, ref2;
09863 vect_t norm;
09864 point_t start1;
09865 point_t end1;
09866 int nsegs;
09867 int pt_type;
09868 int ncoords = 0;
09869 int i;
09870
09871 BN_CK_TOL( tol );
09872
09873 VMOVE( start, i_start )
09874 VMOVE( center, i_center )
09875 VMOVE( end, i_end )
09876 switch( point_type )
09877 {
09878 case RT_NURB_PT_XY:
09879 case RT_NURB_PT_UV:
09880 ncoords = 3;
09881 start[Z] = 0.0;
09882 center[Z] = 0.0;
09883 end[Z] = 0.0;
09884 break;
09885 case RT_NURB_PT_XYZ:
09886 case RT_NURB_PT_DATA:
09887 case RT_NURB_PT_PROJ:
09888 ncoords = 4;
09889 break;
09890 }
09891
09892 if( point_type == RT_NURB_PT_XYZ )
09893 {
09894
09895 if( center[Z] - start[Z] > tol->dist )
09896 {
09897 bu_log( "rt_arc2d_to_cnurb: center and start points not at same Z value (%g vs %g)\n",
09898 center[Z], start[Z] );
09899 return( (struct edge_g_cnurb *)NULL );
09900 }
09901
09902 if( end[Z] - start[Z] > tol->dist )
09903 {
09904 bu_log( "rt_arc2d_to_cnurb: end and start points not at same Z value (%g vs %g)\n",
09905 end[Z], start[Z] );
09906 return( (struct edge_g_cnurb *)NULL );
09907 }
09908
09909 if( end[Z] - center[Z] > tol->dist )
09910 {
09911 bu_log( "rt_arc2d_to_cnurb: end and center points not at same Z value (%g vs %g)\n",
09912 end[Z], center[Z] );
09913 return( (struct edge_g_cnurb *)NULL );
09914 }
09915 }
09916
09917
09918 pt_type = RT_NURB_MAKE_PT_TYPE( ncoords, point_type, RT_NURB_PT_RATIONAL );
09919
09920
09921 if( ncoords == 4 )
09922 {
09923 VSUB2( v1, start, center );
09924 radius = MAGNITUDE( v1 );
09925 VSUB2( v2, end, center );
09926 tmp_radius = MAGNITUDE( v2 );
09927 }
09928 else
09929 {
09930 radius = sqrt( (start[X] - center[X])*(start[X] - center[X]) +
09931 (start[Y] - center[Y])*(start[Y] - center[Y]) );
09932 tmp_radius = sqrt( (end[X] - center[X])*(end[X] - center[X]) +
09933 (end[Y] - center[Y])*(end[Y] - center[Y]) );
09934 }
09935
09936
09937 if( !NEAR_ZERO( radius - tmp_radius, tol->dist ) )
09938 {
09939 bu_log( "rt_arc2d_to_cnurb: distances from center to start and center to end are different\n" );
09940 bu_log( " (%g and %g)\n", radius, tmp_radius );
09941 return( (struct edge_g_cnurb *)NULL );
09942 }
09943
09944
09945 VSET( norm, 0.0, 0.0, 1.0 );
09946 VMOVE( ref1, v1 );
09947 VSCALE( ref1, ref1, 1.0/radius );
09948 VCROSS( ref2, norm, ref1 );
09949
09950
09951 angle = atan2( VDOT( v2, ref2 ), VDOT( v2, ref1 ) );
09952 if( angle <= 0.0 )
09953 angle += 2.0*bn_pi;
09954
09955 if( angle < 150.0*bn_pi/180.0 )
09956 {
09957 fastf_t dist1, dist2;
09958 vect_t t1, t2;
09959 int ret_val;
09960
09961
09962 VMOVE( t1, ref2 );
09963 if( VDOT( t1, v2 ) > 0.0 )
09964 VREVERSE( t1, t1 );
09965 VCROSS( t2, v2, norm );
09966 VUNITIZE( t2 );
09967 if( VDOT( t2, v1 ) > 0.0 )
09968 VREVERSE( t2, t2 );
09969 if( (ret_val=bn_isect_line3_line3( &dist1, &dist2, start, t1, end, t2, tol )) < 1 )
09970 {
09971 bu_log( "rt_arc2d_to_cnurb: Cannot calculate second control point\n" );
09972 bu_log( " bn_isect_line3_line3 returns %d\n" , ret_val );
09973 return( (struct edge_g_cnurb *)NULL );
09974 }
09975
09976
09977 crv = rt_nurb_new_cnurb( 3, 6, 3, pt_type );
09978
09979
09980 for( i=0 ; i<3 ; i++ )
09981 crv->k.knots[i] = 0.0;
09982 for( i=3 ; i<6 ; i++ )
09983 crv->k.knots[i] = 1.0;
09984
09985
09986 VMOVEN( crv->ctl_points, start, ncoords-1 )
09987 VMOVEN( &crv->ctl_points[8], end, ncoords-1 )
09988
09989
09990 crv->ctl_points[ncoords-1] = 1.0;
09991 crv->ctl_points[3*ncoords-1] = 1.0;
09992
09993
09994 VJOIN1N( &crv->ctl_points[ncoords], start, dist1, t1, ncoords-1 )
09995
09996
09997 crv->ctl_points[2*ncoords-1] = cos( angle/2.0 );
09998
09999
10000 VSCALEN( &crv->ctl_points[ncoords], &crv->ctl_points[ncoords], crv->ctl_points[2*ncoords-1], ncoords-1 )
10001
10002 return( crv );
10003 }
10004
10005
10006
10007
10008
10009 if( angle < 1.5*bn_pi )
10010 {
10011
10012 nsegs = 2;
10013 angles[0] = angle/2.0;
10014 angles[1] = angle;
10015 }
10016 else
10017 {
10018
10019 nsegs = 3;
10020 angles[0] = angle/3.0;
10021 angles[1] = 2.0*angles[0];
10022 angles[2] = angle;
10023 }
10024
10025
10026 BU_LIST_INIT( &crv_head );
10027
10028
10029 VMOVE( end1, start );
10030 for( i=0 ; i<nsegs ; i++ )
10031 {
10032 VMOVE( start1, end1 );
10033 if( i == nsegs-1 )
10034 VMOVE( end1, end )
10035 else
10036 VJOIN2( end1, center, radius*cos( angles[i] ), ref1, radius*sin( angles[i] ), ref2 )
10037
10038 crv = rt_arc2d_to_cnurb( center, start1, end1, point_type, tol );
10039 BU_LIST_INSERT( &crv_head, &crv->l );
10040 }
10041
10042
10043 crv = rt_join_cnurbs( &crv_head );
10044
10045 return( crv );
10046 }
10047
10048 int
10049 nmg_break_edge_at_verts(struct edge *e, struct bu_ptbl *verts, const struct bn_tol *tol)
10050 {
10051 int break_count=0;
10052 int j;
10053 struct vertex *va,*vb;
10054 struct bu_ptbl edges;
10055
10056 BN_CK_TOL( tol );
10057 NMG_CK_EDGE( e );
10058 BU_CK_PTBL( verts );
10059
10060 bu_ptbl_init( &edges, 64, " &edges");
10061 bu_ptbl_ins( &edges, (long *)e );
10062
10063 start:
10064
10065 while( BU_PTBL_END( &edges ) )
10066 {
10067 struct edge *e1;
10068 struct edgeuse *eu;
10069
10070 e1 = (struct edge *)BU_PTBL_GET( &edges, BU_PTBL_END( &edges )-1 );
10071 NMG_CK_EDGE( e1 );
10072 eu = e1->eu_p;
10073 NMG_CK_EDGEUSE( eu );
10074
10075 va = eu->vu_p->v_p;
10076 NMG_CK_VERTEX( va );
10077 vb = eu->eumate_p->vu_p->v_p;
10078 NMG_CK_VERTEX( vb );
10079
10080 for( j=0 ; j<BU_PTBL_END( verts ) ; j++ )
10081 {
10082 struct edgeuse *eu_new;
10083 struct vertex *v;
10084 fastf_t dist;
10085 point_t pca;
10086
10087 v = (struct vertex *)BU_PTBL_GET( verts, j );
10088 NMG_CK_VERTEX( v );
10089
10090 if( v == va || v == vb )
10091 continue;
10092
10093 if( bn_dist_pt3_lseg3( &dist, pca, va->vg_p->coord, vb->vg_p->coord, v->vg_p->coord, tol ) )
10094 continue;
10095
10096 eu_new = nmg_esplit( v, eu, 1 );
10097 break_count++;
10098
10099 bu_ptbl_rm( &edges, (long *)e1 );
10100 bu_ptbl_ins( &edges, (long *)eu->e_p );
10101 bu_ptbl_ins( &edges, (long *)eu_new->e_p );
10102
10103 goto start;
10104 }
10105 bu_ptbl_rm( &edges, (long *)e1 );
10106 }
10107 bu_ptbl_free( &edges);
10108 return( break_count );
10109 }
10110
10111 int
10112 nmg_break_edges(long int *magic_p, const struct bn_tol *tol)
10113 {
10114 struct bu_ptbl edges;
10115 struct bu_ptbl verts;
10116 int i;
10117 int break_count=0;
10118
10119 BN_CK_TOL( tol );
10120
10121 nmg_edge_tabulate( &edges, magic_p );
10122 nmg_vertex_tabulate( &verts, magic_p );
10123
10124 for( i=0 ; i<BU_PTBL_END( &edges ); i++ )
10125 {
10126 struct edge *e;
10127 int edge_break_count=0;
10128
10129 e = (struct edge *)BU_PTBL_GET( &edges, i );
10130 NMG_CK_EDGE( e );
10131 edge_break_count = nmg_break_edge_at_verts( e, &verts, tol );
10132 break_count += edge_break_count;
10133 }
10134 bu_ptbl_free( &edges);
10135 bu_ptbl_free( &verts);
10136
10137 return( break_count );
10138 }
10139
10140
10141 static int
10142 Shell_is_arb(struct shell *s, struct bu_ptbl *tab)
10143 {
10144 struct faceuse *fu;
10145 struct face *f;
10146 int four_verts=0;
10147 int three_verts=0;
10148 int face_count=0;
10149 int loop_count;
10150
10151 NMG_CK_SHELL( s );
10152
10153 nmg_vertex_tabulate( tab, &s->l.magic );
10154
10155 if( BU_PTBL_END( tab ) > 8 || BU_PTBL_END( tab ) < 4 )
10156 goto not_arb;
10157
10158 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
10159 {
10160 struct loopuse *lu;
10161 vect_t fu_norm;
10162
10163 NMG_CK_FACEUSE( fu );
10164
10165 if( fu->orientation != OT_SAME )
10166 continue;
10167
10168 f = fu->f_p;
10169 NMG_CK_FACE( f );
10170
10171 if( *f->g.magic_p != NMG_FACE_G_PLANE_MAGIC )
10172 goto not_arb;
10173
10174 NMG_GET_FU_NORMAL( fu_norm, fu );
10175
10176 loop_count = 0;
10177 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
10178 {
10179 struct edgeuse *eu;
10180
10181 NMG_CK_LOOPUSE( lu );
10182
10183 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
10184 goto not_arb;
10185
10186 loop_count++;
10187
10188
10189 if( loop_count > 1 )
10190 goto not_arb;
10191
10192 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10193 {
10194 struct edgeuse *eu_radial;
10195 struct faceuse *fu_radial;
10196 struct face *f_radial;
10197 vect_t norm_radial;
10198 vect_t eu_dir;
10199 vect_t cross;
10200 fastf_t dot;
10201
10202 NMG_CK_EDGEUSE( eu );
10203
10204 eu_radial = nmg_next_radial_eu( eu, s, 0 );
10205
10206
10207 if( eu_radial == eu || eu_radial == eu->eumate_p )
10208 goto not_arb;
10209
10210 fu_radial = nmg_find_fu_of_eu( eu_radial );
10211 NMG_CK_FACEUSE( fu_radial );
10212
10213 if( fu_radial->orientation != OT_SAME )
10214 fu_radial = fu_radial->fumate_p;
10215
10216 f_radial = fu_radial->f_p;
10217 NMG_CK_FACE( f_radial );
10218
10219
10220 if( *f_radial->g.magic_p != NMG_FACE_G_PLANE_MAGIC )
10221 goto not_arb;
10222
10223
10224
10225
10226
10227 NMG_GET_FU_NORMAL( norm_radial, fu_radial );
10228
10229 dot = VDOT( norm_radial, fu_norm );
10230
10231 if( !NEAR_ZERO( dot - 1.0, 0.00001 ) )
10232 {
10233
10234 VCROSS( cross, fu_norm, norm_radial );
10235
10236 if( eu->orientation == OT_NONE )
10237 {
10238 VSUB2( eu_dir, eu->vu_p->v_p->vg_p->coord, eu->eumate_p->vu_p->v_p->vg_p->coord )
10239 if( eu->orientation != OT_SAME )
10240 VREVERSE( eu_dir, eu_dir )
10241 }
10242 else
10243 VMOVE( eu_dir, eu->g.lseg_p->e_dir )
10244
10245 if( eu->orientation == OT_SAME || eu->orientation == OT_NONE )
10246 {
10247 if( VDOT( cross, eu_dir ) < 0.0 )
10248 goto not_arb;
10249 }
10250 else
10251 {
10252 if( VDOT( cross, eu_dir ) > 0.0 )
10253 goto not_arb;
10254 }
10255 }
10256 }
10257 }
10258 }
10259
10260
10261 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
10262 {
10263 struct loopuse *lu;
10264 int vert_count=0;
10265
10266 if( fu->orientation != OT_SAME )
10267 continue;
10268
10269 face_count++;
10270 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
10271 {
10272 struct edgeuse *eu;
10273
10274 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10275 vert_count++;
10276 }
10277
10278 if( vert_count == 3 )
10279 three_verts++;
10280 else if( vert_count == 4 )
10281 four_verts++;
10282 }
10283
10284
10285 if( face_count != three_verts + four_verts )
10286 goto not_arb;
10287
10288
10289 switch( BU_PTBL_END( tab ) )
10290 {
10291 case 4:
10292 if( three_verts != 4 || four_verts != 0 )
10293 goto not_arb;
10294 break;
10295 case 5:
10296 if( four_verts != 1 || three_verts != 4 )
10297 goto not_arb;
10298 break;
10299 case 6:
10300 if( three_verts != 2 || four_verts != 3 )
10301 goto not_arb;
10302 break;
10303 case 7:
10304 if( four_verts != 4 || three_verts != 2 )
10305 goto not_arb;
10306 break;
10307 case 8:
10308 if( four_verts != 6 || three_verts != 0 )
10309 goto not_arb;
10310 break;
10311 }
10312
10313 return( BU_PTBL_END( tab ) );
10314
10315
10316 not_arb:
10317 bu_ptbl_free( tab);
10318 return( 0 );
10319 }
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333 int
10334 nmg_to_arb( const struct model *m, struct rt_arb_internal *arb_int )
10335 {
10336 struct nmgregion *r;
10337 struct shell *s;
10338 struct faceuse *fu;
10339 struct loopuse *lu;
10340 struct edgeuse *eu;
10341 struct vertex *v;
10342 struct edgeuse *eu_start;
10343 struct faceuse *fu1;
10344 struct bu_ptbl tab;
10345 int face_verts;
10346 int i,j;
10347 int found;
10348 int ret_val = 0;
10349
10350 NMG_CK_MODEL( m );
10351
10352 r = BU_LIST_FIRST( nmgregion, &m->r_hd );
10353
10354
10355 if( BU_LIST_NEXT_NOT_HEAD( &r->l, &m->r_hd ) )
10356 return( 0 );
10357
10358 s = BU_LIST_FIRST( shell, &r->s_hd );
10359 NMG_CK_SHELL( s );
10360
10361
10362 if( BU_LIST_NEXT_NOT_HEAD( &s->l, &r->s_hd ) )
10363 return( 0 );
10364
10365 switch( Shell_is_arb( s, &tab ) )
10366 {
10367 case 0:
10368 ret_val = 0;
10369 break;
10370 case 4:
10371 v = (struct vertex *)BU_PTBL_GET( &tab, 0 );
10372 NMG_CK_VERTEX( v );
10373 VMOVE( arb_int->pt[0], v->vg_p->coord );
10374 v = (struct vertex *)BU_PTBL_GET( &tab, 1 );
10375 NMG_CK_VERTEX( v );
10376 VMOVE( arb_int->pt[1], v->vg_p->coord );
10377 v = (struct vertex *)BU_PTBL_GET( &tab, 2 );
10378 NMG_CK_VERTEX( v );
10379 VMOVE( arb_int->pt[2], v->vg_p->coord );
10380 VMOVE( arb_int->pt[3], v->vg_p->coord );
10381 v = (struct vertex *)BU_PTBL_GET( &tab, 3 );
10382 NMG_CK_VERTEX( v );
10383 VMOVE( arb_int->pt[4], v->vg_p->coord );
10384 VMOVE( arb_int->pt[5], v->vg_p->coord );
10385 VMOVE( arb_int->pt[6], v->vg_p->coord );
10386 VMOVE( arb_int->pt[7], v->vg_p->coord );
10387
10388 bu_ptbl_free( &tab);
10389 ret_val = 1;
10390 break;
10391 case 5:
10392 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
10393 face_verts = 0;
10394 while( face_verts != 4 )
10395 {
10396 face_verts = 0;
10397 fu = BU_LIST_PNEXT_CIRC( faceuse, &fu->l );
10398 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10399 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10400 face_verts++;
10401 }
10402 NMG_CK_FACEUSE( fu );
10403 if( fu->orientation != OT_SAME )
10404 fu = fu->fumate_p;
10405 NMG_CK_FACEUSE( fu );
10406
10407 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10408 j = 0;
10409 eu_start = BU_LIST_FIRST( edgeuse, &lu->down_hd );
10410 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10411 {
10412 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10413 j++;
10414 }
10415
10416 eu = eu_start->radial_p;
10417 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10418 eu = eu->eumate_p;
10419 for( i=0 ; i<4 ; i++ )
10420 {
10421 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10422 j++;
10423 }
10424
10425 bu_ptbl_free( &tab);
10426 ret_val = 1;
10427 break;
10428 case 6:
10429 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
10430 face_verts = 0;
10431 while( face_verts != 3 )
10432 {
10433 face_verts = 0;
10434 fu = BU_LIST_PNEXT_CIRC( faceuse, &fu->l );
10435 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10436 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10437 face_verts++;
10438 }
10439 NMG_CK_FACEUSE( fu );
10440 if( fu->orientation != OT_SAME )
10441 fu = fu->fumate_p;
10442 NMG_CK_FACEUSE( fu );
10443
10444 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10445
10446 eu_start = BU_LIST_FIRST( edgeuse, &lu->down_hd );
10447 eu = eu_start;
10448 VMOVE( arb_int->pt[1], eu->vu_p->v_p->vg_p->coord );
10449 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10450 VMOVE( arb_int->pt[0], eu->vu_p->v_p->vg_p->coord );
10451 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10452 VMOVE( arb_int->pt[4], eu->vu_p->v_p->vg_p->coord );
10453 VMOVE( arb_int->pt[5], eu->vu_p->v_p->vg_p->coord );
10454
10455 eu = eu_start->radial_p;
10456 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10457 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10458 eu = eu->radial_p->eumate_p;
10459 VMOVE( arb_int->pt[2], eu->vu_p->v_p->vg_p->coord );
10460 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10461 VMOVE( arb_int->pt[3], eu->vu_p->v_p->vg_p->coord );
10462 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10463 VMOVE( arb_int->pt[6], eu->vu_p->v_p->vg_p->coord );
10464 VMOVE( arb_int->pt[7], eu->vu_p->v_p->vg_p->coord );
10465
10466 bu_ptbl_free( &tab);
10467 ret_val = 1;
10468 break;
10469 case 7:
10470 found = 0;
10471 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
10472 while( !found )
10473 {
10474 int verts4=0,verts3=0;
10475
10476 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10477 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10478 {
10479 struct loopuse *lu1;
10480 struct edgeuse *eu1;
10481 int vert_count=0;
10482
10483 fu1 = nmg_find_fu_of_eu( eu->radial_p );
10484 lu1 = BU_LIST_FIRST( loopuse, &fu1->lu_hd );
10485 for( BU_LIST_FOR( eu1, edgeuse, &lu1->down_hd ) )
10486 vert_count++;
10487
10488 if( vert_count == 4 )
10489 verts4++;
10490 else if( vert_count == 3 )
10491 verts3++;
10492 }
10493
10494 if( verts4 == 2 && verts3 == 2 )
10495 found = 1;
10496 }
10497 if( fu->orientation != OT_SAME )
10498 fu = fu->fumate_p;
10499 NMG_CK_FACEUSE( fu );
10500
10501 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10502 j = 0;
10503 eu_start = BU_LIST_FIRST( edgeuse, &lu->down_hd );
10504 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10505 {
10506 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10507 j++;
10508 }
10509
10510 eu = eu_start->radial_p;
10511 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10512 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10513 eu = eu->radial_p->eumate_p;
10514 fu1 = nmg_find_fu_of_eu( eu );
10515 if( nmg_faces_are_radial( fu, fu1 ) )
10516 {
10517 eu = eu_start->radial_p;
10518 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10519 eu = eu->radial_p->eumate_p;
10520 }
10521 for( i=0 ; i<4 ; i++ )
10522 {
10523 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10524 j++;
10525 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10526 }
10527
10528 bu_ptbl_free( &tab);
10529 ret_val = 1;
10530 break;
10531 case 8:
10532 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
10533 NMG_CK_FACEUSE( fu );
10534 if( fu->orientation != OT_SAME )
10535 fu = fu->fumate_p;
10536 NMG_CK_FACEUSE( fu );
10537
10538 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
10539 j = 0;
10540 eu_start = BU_LIST_FIRST( edgeuse, &lu->down_hd );
10541 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10542 {
10543 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10544 j++;
10545 }
10546
10547 eu = eu_start->radial_p;
10548 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10549 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10550 eu = eu->radial_p->eumate_p;
10551 for( i=0 ; i<4 ; i++ )
10552 {
10553 VMOVE( arb_int->pt[j], eu->vu_p->v_p->vg_p->coord )
10554 j++;
10555 eu = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
10556 }
10557
10558 bu_ptbl_free( &tab);
10559 ret_val = 1;
10560 break;
10561 default:
10562 rt_bomb( "Shell_is_arb screwed up" );
10563 break;
10564 }
10565 if( ret_val )
10566 arb_int->magic = RT_ARB_INTERNAL_MAGIC;
10567 return( ret_val );
10568 }
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584 int
10585 nmg_to_tgc(
10586 const struct model *m,
10587 struct rt_tgc_internal *tgc_int,
10588 const struct bn_tol *tol )
10589 {
10590 struct nmgregion *r;
10591 struct shell *s;
10592 struct faceuse *fu;
10593 struct loopuse *lu;
10594 struct edgeuse *eu;
10595 struct faceuse *fu_base=(struct faceuse *)NULL;
10596 struct faceuse *fu_top=(struct faceuse *)NULL;
10597 int three_vert_faces=0;
10598 int four_vert_faces=0;
10599 int many_vert_faces=0;
10600 int base_vert_count=0;
10601 int top_vert_count=0;
10602 point_t sum;
10603 fastf_t vert_count=0.0;
10604 fastf_t one_over_vert_count;
10605 point_t base_center;
10606 fastf_t min_base_r_sq;
10607 fastf_t max_base_r_sq;
10608 fastf_t sum_base_r_sq;
10609 fastf_t ave_base_r_sq;
10610 fastf_t base_r;
10611 point_t top_center;
10612 fastf_t min_top_r_sq;
10613 fastf_t max_top_r_sq;
10614 fastf_t sum_top_r_sq;
10615 fastf_t ave_top_r_sq;
10616 fastf_t top_r;
10617 plane_t top_pl;
10618 plane_t base_pl;
10619 vect_t plv_1,plv_2;
10620
10621 NMG_CK_MODEL( m );
10622
10623 BN_CK_TOL( tol );
10624
10625 r = BU_LIST_FIRST( nmgregion, &m->r_hd );
10626
10627
10628 if( BU_LIST_NEXT_NOT_HEAD( &r->l, &m->r_hd ) )
10629 return( 0 );
10630
10631 s = BU_LIST_FIRST( shell, &r->s_hd );
10632 NMG_CK_SHELL( s );
10633
10634
10635 if( BU_LIST_NEXT_NOT_HEAD( &s->l, &r->s_hd ) )
10636 return( 0 );
10637
10638 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
10639 {
10640 int lu_count=0;
10641
10642 NMG_CK_FACEUSE( fu );
10643 if( fu->orientation != OT_SAME )
10644 continue;
10645
10646 vert_count = 0.0;
10647
10648 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
10649 {
10650
10651 NMG_CK_LOOPUSE( lu );
10652
10653 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
10654 return( 0 );
10655
10656 lu_count++;
10657 if( lu_count > 1 )
10658 return( 0 );
10659
10660 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10661 vert_count++;
10662 }
10663
10664 if( vert_count < 3 )
10665 return( 0 );
10666
10667 if( vert_count == 4 )
10668 four_vert_faces++;
10669 else if( vert_count ==3 )
10670 three_vert_faces++;
10671 else
10672 {
10673 many_vert_faces++;
10674 if( many_vert_faces > 2 )
10675 return( 0 );
10676
10677 if( many_vert_faces == 1 )
10678 {
10679 fu_base = fu;
10680 base_vert_count = vert_count;
10681 NMG_GET_FU_PLANE( base_pl, fu_base );
10682 }
10683 else if( many_vert_faces == 2 )
10684 {
10685 fu_top = fu;
10686 top_vert_count = vert_count;
10687 NMG_GET_FU_PLANE( top_pl, fu_top );
10688 }
10689 }
10690 }
10691
10692
10693
10694 if( three_vert_faces%2 )
10695 return( 0 );
10696
10697
10698 if( base_vert_count != top_vert_count )
10699 return( 0 );
10700
10701
10702 if( (base_vert_count != four_vert_faces) &&
10703 (base_vert_count*2 != three_vert_faces ) )
10704 return( 0 );
10705
10706 if( !NEAR_ZERO( 1.0 + VDOT( top_pl, base_pl ), tol->perp ) )
10707 return( 0 );
10708
10709
10710
10711
10712
10713 vert_count = 0.0;
10714 VSETALL( sum, 0.0 );
10715 lu = BU_LIST_FIRST( loopuse, &fu_base->lu_hd );
10716 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10717 {
10718 struct vertex_g *vg;
10719
10720 NMG_CK_EDGEUSE( eu );
10721
10722 NMG_CK_VERTEXUSE( eu->vu_p );
10723 NMG_CK_VERTEX( eu->vu_p->v_p );
10724 vg = eu->vu_p->v_p->vg_p;
10725 NMG_CK_VERTEX_G( vg );
10726
10727 VADD2( sum, sum, vg->coord );
10728 vert_count++;
10729 }
10730
10731 one_over_vert_count = 1.0/vert_count;
10732 VSCALE( base_center, sum, one_over_vert_count );
10733
10734
10735 min_base_r_sq = MAX_FASTF;
10736 max_base_r_sq = (-min_base_r_sq);
10737 sum_base_r_sq = 0.0;
10738 lu = BU_LIST_FIRST( loopuse, &fu_base->lu_hd );
10739 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10740 {
10741 struct vertex_g *vg;
10742 vect_t rad_vect;
10743 fastf_t r_sq;
10744
10745 vg = eu->vu_p->v_p->vg_p;
10746
10747 VSUB2( rad_vect, vg->coord, base_center );
10748 r_sq = MAGSQ( rad_vect );
10749 if( r_sq > max_base_r_sq )
10750 max_base_r_sq = r_sq;
10751 if( r_sq < min_base_r_sq )
10752 min_base_r_sq = r_sq;
10753
10754 sum_base_r_sq += r_sq;
10755 }
10756
10757 ave_base_r_sq = sum_base_r_sq/vert_count;
10758
10759 base_r = sqrt( max_base_r_sq );
10760
10761 if( !NEAR_ZERO( (max_base_r_sq - ave_base_r_sq)/ave_base_r_sq, 0.001 ) ||
10762 !NEAR_ZERO( (min_base_r_sq - ave_base_r_sq)/ave_base_r_sq, 0.001 ) )
10763 return( 0 );
10764
10765 VSETALL( sum, 0.0 );
10766 lu = BU_LIST_FIRST( loopuse, &fu_top->lu_hd );
10767 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10768 {
10769 struct vertex_g *vg;
10770
10771 NMG_CK_EDGEUSE( eu );
10772
10773 NMG_CK_VERTEXUSE( eu->vu_p );
10774 NMG_CK_VERTEX( eu->vu_p->v_p );
10775 vg = eu->vu_p->v_p->vg_p;
10776 NMG_CK_VERTEX_G( vg );
10777
10778 VADD2( sum, sum, vg->coord );
10779 }
10780
10781 VSCALE( top_center, sum, one_over_vert_count );
10782
10783
10784 min_top_r_sq = MAX_FASTF;
10785 max_top_r_sq = (-min_top_r_sq);
10786 sum_top_r_sq = 0.0;
10787 lu = BU_LIST_FIRST( loopuse, &fu_top->lu_hd );
10788 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
10789 {
10790 struct vertex_g *vg;
10791 vect_t rad_vect;
10792 fastf_t r_sq;
10793
10794 vg = eu->vu_p->v_p->vg_p;
10795
10796 VSUB2( rad_vect, vg->coord, top_center );
10797 r_sq = MAGSQ( rad_vect );
10798 if( r_sq > max_top_r_sq )
10799 max_top_r_sq = r_sq;
10800 if( r_sq < min_top_r_sq )
10801 min_top_r_sq = r_sq;
10802
10803 sum_top_r_sq += r_sq;
10804 }
10805
10806 ave_top_r_sq = sum_top_r_sq/vert_count;
10807 top_r = sqrt( max_top_r_sq );
10808
10809 if( !NEAR_ZERO( (max_top_r_sq - ave_top_r_sq)/ave_top_r_sq, 0.001 ) ||
10810 !NEAR_ZERO( (min_top_r_sq - ave_top_r_sq)/ave_top_r_sq, 0.001 ) )
10811 return( 0 );
10812
10813
10814 VMOVE( tgc_int->v, base_center );
10815 VSUB2( tgc_int->h, top_center, base_center );
10816
10817 bn_vec_perp( plv_1, top_pl );
10818 VCROSS( plv_2, top_pl, plv_1 );
10819 VUNITIZE( plv_1 );
10820 VUNITIZE( plv_2 );
10821 VSCALE( tgc_int->a, plv_1, base_r );
10822 VSCALE( tgc_int->b, plv_2, base_r );
10823 VSCALE( tgc_int->c, plv_1, top_r );
10824 VSCALE( tgc_int->d, plv_2, top_r );
10825
10826 tgc_int->magic = RT_TGC_INTERNAL_MAGIC;
10827
10828 return( 1 );
10829 }
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840 int
10841 nmg_lu_is_convex(struct loopuse *lu, const struct bn_tol *tol)
10842 {
10843 struct edgeuse *eu1,*eu2,*eu3,*eu_start;
10844
10845 NMG_CK_LOOPUSE( lu );
10846 BN_CK_TOL( tol );
10847
10848 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
10849 return( 1 );
10850
10851 if( !lu->l_p->lg_p )
10852 nmg_loop_g( lu->l_p, tol );
10853
10854 eu1 = BU_LIST_FIRST( edgeuse, &lu->down_hd );
10855 eu_start = eu1;
10856 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
10857 eu3 = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
10858
10859 if( eu1->vu_p->v_p == eu3->eumate_p->vu_p->v_p )
10860 return( 1 );
10861
10862 while( eu3 != eu_start )
10863 {
10864 int class;
10865 struct vertex_g *vg1,*vg3;
10866 point_t mid_pt;
10867
10868 vg1 = eu1->vu_p->v_p->vg_p;
10869 NMG_CK_VERTEX_G( vg1 );
10870
10871 vg3 = eu3->vu_p->v_p->vg_p;
10872 NMG_CK_VERTEX_G( vg3 );
10873
10874 VBLEND2( mid_pt, 0.5, vg1->coord, 0.5, vg3->coord );
10875
10876 class = nmg_class_pt_lu_except( mid_pt, lu, NULL, tol );
10877
10878 if( (class == NMG_CLASS_AoutB && lu->orientation == OT_SAME) ||
10879 (class == NMG_CLASS_AinB && lu->orientation == OT_OPPOSITE) )
10880 return( 0 );
10881 else
10882 {
10883 eu1 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
10884 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
10885 eu3 = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
10886 }
10887 }
10888
10889 return( 1 );
10890 }
10891
10892
10893
10894
10895
10896
10897 int
10898 nmg_to_poly(const struct model *m, struct rt_pg_internal *poly_int, const struct bn_tol *tol)
10899 {
10900 struct nmgregion *r;
10901 struct shell *s;
10902 struct faceuse *fu;
10903 struct loopuse *lu;
10904 struct edgeuse *eu;
10905 struct model *dup_m;
10906 struct nmgregion *dup_r;
10907 struct shell *dup_s;
10908 int max_count;
10909 int count_npts;
10910 int face_count=0;
10911 #if 0
10912 struct rt_pg_face_internal *_poly;
10913 #endif
10914
10915 NMG_CK_MODEL( m );
10916
10917 BN_CK_TOL( tol );
10918
10919 for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )
10920 {
10921 for( BU_LIST_FOR( s, shell, &r->s_hd ) )
10922 {
10923 if( nmg_check_closed_shell( s, tol ) )
10924 return( 0 );
10925 }
10926 }
10927
10928 dup_m = nmg_mm();
10929 dup_r = nmg_mrsv( dup_m );
10930 dup_s = BU_LIST_FIRST( shell, &dup_r->s_hd );
10931
10932 for( BU_LIST_FOR( r, nmgregion, &m->r_hd ) )
10933 {
10934 for( BU_LIST_FOR( s, shell, &r->s_hd ) )
10935 {
10936 for( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
10937 {
10938 if( fu->orientation != OT_SAME )
10939 continue;
10940 (void)nmg_dup_face( fu, dup_s );
10941 }
10942 }
10943 }
10944
10945 for( BU_LIST_FOR( dup_r, nmgregion, &dup_m->r_hd ) )
10946 {
10947 for( BU_LIST_FOR( dup_s, shell, &dup_r->s_hd ) )
10948 {
10949 for( BU_LIST_FOR( fu , faceuse , &dup_s->fu_hd ) )
10950 {
10951 NMG_CK_FACEUSE( fu );
10952
10953
10954 if( fu->orientation != OT_SAME )
10955 continue;
10956
10957
10958 max_count = 0;
10959 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
10960 {
10961 NMG_CK_LOOPUSE( lu );
10962 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
10963 continue;
10964
10965 if( lu->orientation != OT_SAME )
10966 {
10967
10968 max_count = 6;
10969 break;
10970 }
10971
10972 count_npts = 0;
10973 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
10974 count_npts++;
10975
10976 if( count_npts > 5 )
10977 {
10978 max_count = count_npts;
10979 break;
10980 }
10981 if( !nmg_lu_is_convex( lu, tol ) )
10982 {
10983
10984 max_count = 6;
10985 break;
10986 }
10987 }
10988
10989
10990 if( max_count > 5 )
10991 {
10992 if( rt_g.NMG_debug & DEBUG_BASIC )
10993 bu_log( "write_shell_as_polysolid: triangulating fu x%x\n", fu );
10994 nmg_triangulate_fu( fu, tol );
10995 }
10996
10997 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
10998 {
10999 NMG_CK_LOOPUSE( lu );
11000 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
11001 continue;
11002
11003 face_count++;
11004 }
11005 }
11006 }
11007 }
11008 poly_int->npoly = face_count;
11009 poly_int->poly = (struct rt_pg_face_internal *)bu_calloc( face_count,
11010 sizeof( struct rt_pg_face_internal ), "nmg_to_poly: poly" );
11011
11012 face_count = 0;
11013 for( BU_LIST_FOR( dup_r, nmgregion, &dup_m->r_hd ) )
11014 {
11015 for( BU_LIST_FOR( dup_s, shell, &dup_r->s_hd ) )
11016 {
11017 for( BU_LIST_FOR( fu , faceuse , &dup_s->fu_hd ) )
11018 {
11019 vect_t norm;
11020
11021 NMG_CK_FACEUSE( fu );
11022
11023
11024 if( fu->orientation != OT_SAME )
11025 continue;
11026
11027 NMG_GET_FU_NORMAL( norm, fu );
11028
11029 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
11030 {
11031 int pt_no=0;
11032
11033 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
11034 continue;
11035
11036
11037 count_npts = 0;
11038 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
11039 count_npts++;
11040
11041 poly_int->poly[face_count].npts = count_npts;
11042 poly_int->poly[face_count].verts = (fastf_t *) bu_calloc( 3*count_npts, sizeof( fastf_t ), "nmg_to_poly: verts" );
11043 poly_int->poly[face_count].norms = (fastf_t *) bu_calloc( 3*count_npts, sizeof( fastf_t ), "nmg_to_poly: norms" );
11044
11045 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
11046 {
11047 struct vertex_g *vg;
11048
11049 vg = eu->vu_p->v_p->vg_p;
11050 NMG_CK_VERTEX_G( vg );
11051
11052 VMOVE( &(poly_int->poly[face_count].verts[pt_no*3]), vg->coord );
11053 VMOVE( &(poly_int->poly[face_count].norms[pt_no*3]), norm );
11054
11055 pt_no++;
11056 }
11057 face_count++;
11058 }
11059 }
11060 }
11061 }
11062
11063 poly_int->magic = RT_PG_INTERNAL_MAGIC;
11064 nmg_km( dup_m );
11065
11066 return( 1 );
11067 }
11068
11069 int
11070 nmg_simplify_shell_edges(struct shell *s, const struct bn_tol *tol)
11071 {
11072 struct faceuse *fu;
11073 int count=0;
11074
11075 NMG_CK_SHELL( s );
11076 BN_CK_TOL( tol );
11077
11078 fu = BU_LIST_FIRST( faceuse, &s->fu_hd );
11079 while( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) )
11080 {
11081 struct faceuse *fu_next;
11082 struct loopuse *lu;
11083 int empty_fu=0;
11084
11085 NMG_CK_FACEUSE( fu );
11086
11087 fu_next = BU_LIST_PNEXT( faceuse, &fu->l );
11088
11089 if( fu->orientation != OT_SAME )
11090 {
11091 fu = fu_next;
11092 continue;
11093 }
11094
11095 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
11096
11097 while( BU_LIST_NOT_HEAD( &lu->l, &fu->lu_hd ) )
11098 {
11099 struct loopuse *lu_next;
11100 struct edge *ep1,*ep2;
11101 struct edgeuse *eu;
11102 struct edgeuse *eu_next;
11103 vect_t dir_eu;
11104 vect_t dir_next;
11105
11106 NMG_CK_LOOPUSE( lu );
11107
11108 lu_next = BU_LIST_PNEXT( loopuse, &lu->l );
11109
11110 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
11111 {
11112 lu = lu_next;
11113 continue;
11114 }
11115
11116 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd );
11117 while( BU_LIST_NOT_HEAD( &eu->l, &lu->down_hd ) )
11118 {
11119 struct vertex *v1,*v2,*v3;
11120 struct vertex_g *vg1,*vg2,*vg3;
11121 struct vertexuse *vu;
11122 struct vertexuse *next_vu;
11123 struct edgeuse *eu_tmp;
11124 point_t pca;
11125 fastf_t dist;
11126 int skip;
11127 int empty_lu=0;
11128
11129 v1 = eu->vu_p->v_p;
11130 ep1 = eu->e_p;
11131 eu_next = BU_LIST_PNEXT_CIRC( edgeuse, &eu->l );
11132 ep2 = eu_next->e_p;
11133 v2 = eu_next->vu_p->v_p;
11134
11135 if( v1 == v2 )
11136 {
11137
11138 eu = BU_LIST_PNEXT( edgeuse, &eu->l );
11139 continue;
11140 }
11141
11142
11143
11144 skip = 0;
11145 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
11146 {
11147 if( nmg_find_s_of_vu( vu ) != s )
11148 {
11149 skip = 1;
11150 break;
11151 }
11152 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11153 continue;
11154
11155 if( vu->up.eu_p->e_p != ep1 &&
11156 vu->up.eu_p->e_p != ep2 )
11157 {
11158 skip = 1;
11159 break;
11160 }
11161 }
11162
11163 if( skip )
11164 {
11165
11166 eu = BU_LIST_PNEXT( edgeuse, &eu->l );
11167 continue;
11168 }
11169
11170 vg2 = v2->vg_p;
11171
11172 v1 = eu->vu_p->v_p;
11173 vg1 = v1->vg_p;
11174 v3 = eu_next->eumate_p->vu_p->v_p;
11175 vg3 = v3->vg_p;
11176
11177 VSUB2( dir_eu, vg2->coord, vg1->coord );
11178 VSUB2( dir_next, vg3->coord, vg2->coord );
11179
11180 skip = 1;
11181 if( rt_dist_pt3_line3( &dist, pca, vg1->coord, dir_eu, vg3->coord, tol ) < 2 )
11182 skip = 0;
11183 else if( rt_dist_pt3_line3( &dist, pca, vg2->coord, dir_next, vg1->coord, tol ) < 2 )
11184 skip = 0;
11185
11186 if( skip )
11187 {
11188
11189 eu = BU_LIST_PNEXT( edgeuse, &eu->l );
11190 continue;
11191 }
11192
11193 count++;
11194
11195 eu_tmp = eu_next->radial_p;
11196 while( eu_tmp != eu_next->eumate_p )
11197 {
11198 nmg_keu( eu_tmp );
11199 eu_tmp = eu_next->radial_p;
11200 }
11201 nmg_keu( eu_next );
11202
11203
11204 vu = BU_LIST_FIRST( vertexuse, &v2->vu_hd );
11205 while( BU_LIST_NOT_HEAD( &vu->l, &v2->vu_hd ) )
11206 {
11207 NMG_CK_VERTEXUSE( vu );
11208 next_vu = BU_LIST_PNEXT( vertexuse, &vu->l );
11209 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11210 {
11211 vu = next_vu;
11212 continue;
11213 }
11214
11215 eu_tmp = vu->up.eu_p;
11216 NMG_CK_EDGEUSE( eu );
11217
11218 if( eu->e_p != ep1 )
11219 {
11220 vu = next_vu;
11221 continue;
11222 }
11223
11224 nmg_movevu( eu_tmp->vu_p, v3 );
11225
11226 vu = next_vu;
11227 continue;
11228 }
11229
11230 if( BU_LIST_IS_EMPTY( &lu->down_hd ) )
11231 {
11232 empty_lu = 1;
11233 empty_fu = nmg_klu( lu );
11234 }
11235 if( empty_lu )
11236 break;
11237
11238 }
11239
11240 if( empty_fu )
11241 break;
11242 lu = lu_next;
11243 }
11244 if( empty_fu )
11245 {
11246 if( fu_next == fu->fumate_p )
11247 fu_next = BU_LIST_NEXT( faceuse, &fu_next->l );
11248 (void)nmg_kfu( fu );
11249 }
11250 fu = fu_next;
11251 }
11252 return( count );
11253 }
11254
11255 #define EDGE_COLLAPSE_DEBUG 0
11256
11257 int
11258 nmg_select_collapse(const fastf_t max_dist1, const fastf_t max_dot1, const int flip1, const fastf_t max_dist2, const fastf_t max_dot2, const int flip2, const fastf_t max_dot, const fastf_t tol_dist)
11259 {
11260 unsigned int ret;
11261
11262 ret = 1 | 2;
11263
11264 if( flip1 )
11265 ret = ret & ~1;
11266
11267 if( flip2 )
11268 ret = ret & ~2;
11269
11270 if( max_dist1 > tol_dist )
11271 ret = ret & ~1;
11272
11273 if( max_dist2 > tol_dist )
11274 ret = ret & ~2;
11275
11276 if( max_dot1 > max_dot )
11277 ret = ret & ~1;
11278
11279 if( max_dot2 > max_dot )
11280 ret = ret & ~2;
11281
11282 if( ret == (1 | 2) )
11283 {
11284 if( max_dot1 < max_dot2 )
11285 ret = 1;
11286 else
11287 ret = 2;
11288 }
11289
11290 #if EDGE_COLLAPSE_DEBUG
11291 bu_log( "\nmax_dot=%g, tol_coll=%g\n", max_dot, tol_dist );
11292 bu_log( "max_dist1, max_dot1, flip1: %g %g %d\n", max_dist1, max_dot1, flip1 );
11293 bu_log( "max_dist2, max_dot2, flip2: %g %g %d\n", max_dist2, max_dot2, flip2 );
11294 bu_log( "choice = %d\n", ret );
11295 #endif
11296
11297 return( ret );
11298 }
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312 int
11313 nmg_edge_collapse(struct model *m, const struct bn_tol *tol, const fastf_t tol_coll, const fastf_t min_angle)
11314 {
11315 fastf_t max_dot;
11316 struct bu_ptbl edge_table;
11317 long edge_no=0;
11318 long count=0;
11319 long sub_count=1;
11320 int choice;
11321 int i;
11322
11323 NMG_CK_MODEL( m );
11324 BN_CK_TOL( tol );
11325
11326 max_dot = cos( min_angle * bn_pi / 180.0 );
11327
11328
11329 (void)nmg_split_loops_into_faces( &m->magic, tol );
11330
11331 nmg_edge_tabulate( &edge_table, &m->magic );
11332
11333 while( sub_count )
11334 {
11335 sub_count = 0;
11336 for( edge_no=0 ; edge_no < BU_PTBL_END( &edge_table ) ; edge_no++ )
11337 {
11338 int done=0;
11339 struct edge *e;
11340 struct edgeuse *eu, *eu2, *eu3;
11341 struct faceuse *fu, *fu2;
11342 struct vertex *v1, *v2;
11343 struct vertexuse *vu;
11344 int real_count1, real_count2;
11345 vect_t edge_dir;
11346 fastf_t max_dist1, max_dist2;
11347 fastf_t max_dot1, max_dot2;
11348 int flip1, flip2;
11349 int no_collapse;
11350 int free_edge;
11351
11352 max_dist1 = -1.0;
11353 max_dist2 = -1.0;
11354 max_dot1 = -1.0;
11355 max_dot2 = -1.0;
11356
11357 e = (struct edge *)BU_PTBL_GET( &edge_table, edge_no );
11358 if( !e )
11359 continue;
11360 if( e->magic != NMG_EDGE_MAGIC )
11361 continue;
11362
11363 NMG_CK_EDGE( e );
11364 eu = e->eu_p;
11365 NMG_CK_EDGEUSE( eu );
11366
11367 v1 = eu->vu_p->v_p;
11368 NMG_CK_VERTEX( v1 );
11369 v2 = eu->eumate_p->vu_p->v_p;
11370 NMG_CK_VERTEX( v2 );
11371
11372
11373 free_edge = 0;
11374 eu2 = eu;
11375 do
11376 {
11377 eu3 = eu2;
11378 do {
11379 if( eu3->radial_p->eumate_p == eu3 )
11380 {
11381 free_edge = 1;
11382 break;
11383 }
11384 eu3 = BU_LIST_PNEXT_CIRC( edgeuse, &eu3->l );
11385
11386 } while ( eu3 != eu2 );
11387 if( free_edge )
11388 break;
11389
11390 eu2 = eu2->radial_p->eumate_p;
11391 } while( eu2 != eu );
11392
11393 if( free_edge )
11394 {
11395 #if EDGE_COLLAPSE_DEBUG
11396 bu_log( "Not collapsing free edge at (%g %g %g)<->(%g %g %g)\n",
11397 V3ARGS( v1->vg_p->coord ), V3ARGS( v2->vg_p->coord ) );
11398 #endif
11399 continue;
11400 }
11401
11402
11403 #if EDGE_COLLAPSE_DEBUG
11404 bu_log( "Consider collapsing e x%x (%g %g %g)<->(%g %g %g)\n", e, V3ARGS( v1->vg_p->coord ), V3ARGS( v2->vg_p->coord ) );
11405 #endif
11406
11407
11408 real_count1 = 0;
11409
11410 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
11411 {
11412 struct edgeuse *eu1;
11413
11414 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11415 continue;
11416
11417 eu1 = vu->up.eu_p;
11418
11419 fu = nmg_find_fu_of_eu( eu1 );
11420 if( fu->orientation != OT_SAME )
11421 continue;
11422
11423 if( eu1->e_p->is_real )
11424 real_count1++;
11425 }
11426
11427 if( real_count1 > 2 )
11428 {
11429 #if EDGE_COLLAPSE_DEBUG
11430 bu_log( "\t%d real edges at v1\n", real_count1 );
11431 #endif
11432 continue;
11433 }
11434
11435 real_count2 = 0;
11436
11437 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
11438 {
11439 struct edgeuse *eu1;
11440
11441 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11442 continue;
11443
11444 eu1 = vu->up.eu_p;
11445
11446 fu = nmg_find_fu_of_eu( eu1 );
11447 if( fu->orientation != OT_SAME )
11448 continue;
11449
11450 if( eu1->e_p->is_real )
11451 real_count2++;
11452 }
11453
11454 if( real_count2 > 2 )
11455 {
11456 #if EDGE_COLLAPSE_DEBUG
11457 bu_log( "\t%d real edges at v1\n", real_count1 );
11458 #endif
11459 continue;
11460 }
11461
11462
11463 if( (real_count1 || real_count2) && !e->is_real )
11464 {
11465 #if EDGE_COLLAPSE_DEBUG
11466 bu_log( "\tthis edge is not real\n" );
11467 #endif
11468 continue;
11469 }
11470 #if EDGE_COLLAPSE_DEBUG
11471 bu_log( "\tpassed real edges test\n" );
11472 #endif
11473
11474 VSUB2( edge_dir, v2->vg_p->coord, v1->vg_p->coord )
11475 VUNITIZE( edge_dir )
11476
11477 fu = nmg_find_fu_of_eu( eu );
11478 NMG_CK_FACEUSE( fu );
11479 if( fu->orientation != OT_SAME )
11480 fu = fu->fumate_p;
11481 if( fu->orientation != OT_SAME )
11482 {
11483 bu_log( "nmg_edge_collapse: fu (x%x) has no OT_SAME use!!!\n", fu );
11484 continue;
11485 }
11486 eu2 = eu->radial_p;
11487 NMG_CK_EDGEUSE( eu2 );
11488 fu2 = nmg_find_fu_of_eu( eu2 );
11489 NMG_CK_FACEUSE( fu2 );
11490 if( fu2->orientation != OT_SAME )
11491 fu2 = fu2->fumate_p;
11492 if( fu2->orientation != OT_SAME )
11493 {
11494 bu_log( "nmg_edge_collapse: fu2 (x%x) has no OT_SAME use!!!\n", fu2 );
11495 continue;
11496 }
11497
11498 #if EDGE_COLLAPSE_DEBUG
11499 bu_log( "\tCheck moving v1 to v2\n" );
11500 #endif
11501
11502 flip1 = 0;
11503 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
11504 {
11505 struct edgeuse *eu1, *eu2;
11506 vect_t vec1, vec2, vec3;
11507 vect_t norma;
11508 struct vertex_g *vg1, *vg2;
11509 plane_t normb;
11510 fastf_t dist;
11511 fastf_t dot1;
11512
11513 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11514 continue;
11515
11516 eu1 = vu->up.eu_p;
11517 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
11518
11519 if( eu2->eumate_p->vu_p->v_p == v2 )
11520 continue;
11521
11522 if( eu2->vu_p->v_p == v2 )
11523 continue;
11524
11525 vg1 = eu2->vu_p->v_p->vg_p;
11526 vg2 = eu2->eumate_p->vu_p->v_p->vg_p;
11527
11528 VSUB2( vec1, v1->vg_p->coord, vg1->coord )
11529 VSUB2( vec2, vg2->coord, vg1->coord )
11530 VCROSS( norma, vec1, vec2 )
11531 #if EDGE_COLLAPSE_DEBUG
11532 bu_log( "\t\toriginal tri (%g %g %g) (%g %g %g) (%g %g %g)\n",
11533 V3ARGS( v1->vg_p->coord ),
11534 V3ARGS( vg1->coord ),
11535 V3ARGS( vg2->coord ) );
11536 #endif
11537 VSUB2( vec1, v2->vg_p->coord, vg1->coord )
11538 VCROSS( normb, vec1, vec2 )
11539 VSUB2( vec3, v2->vg_p->coord, vg2->coord )
11540 VUNITIZE( vec1 );
11541 VUNITIZE( vec2 );
11542 VUNITIZE( vec3 );
11543
11544 dot1 = VDOT( vec1, vec2 );
11545 if( dot1 > max_dot1 )
11546 max_dot1 = dot1;
11547 dot1 = VDOT( vec1, vec3 );
11548 if( dot1 > max_dot1 )
11549 max_dot1 = dot1;
11550 dot1 = -VDOT( vec2, vec3 );
11551 if( dot1 > max_dot1 )
11552 max_dot1 = dot1;
11553 #if EDGE_COLLAPSE_DEBUG
11554 bu_log( "\t\tnew tri (%g %g %g) (%g %g %g) (%g %g %g)\n",
11555 V3ARGS( v2->vg_p->coord ),
11556 V3ARGS( vg1->coord ),
11557 V3ARGS( vg2->coord ) );
11558 #endif
11559 fu = nmg_find_fu_of_eu( eu1 );
11560 if( fu->orientation == OT_SAME )
11561 {
11562 VUNITIZE( normb )
11563 normb[3] = VDOT( normb, v2->vg_p->coord );
11564
11565 dist = fabs( DIST_PT_PLANE( v1->vg_p->coord, normb ) );
11566 #if EDGE_COLLAPSE_DEBUG
11567 bu_log( "\t\t\tdist = %g\n", dist );
11568 #endif
11569 if( dist > max_dist1 )
11570 max_dist1 = dist;
11571 }
11572 #if EDGE_COLLAPSE_DEBUG
11573 else
11574 bu_log( "\t\t\tfu->orientation = %s\n", nmg_orientation( fu->orientation ) );
11575 #endif
11576
11577 if( VDOT( norma, normb ) <= 0.0 )
11578 {
11579
11580 flip1 = 1;
11581 #if EDGE_COLLAPSE_DEBUG
11582 bu_log( "\t\t\tflip1 = 1\n" );
11583 #endif
11584 break;
11585 }
11586
11587 }
11588
11589
11590 #if EDGE_COLLAPSE_DEBUG
11591 bu_log( "\tCheck moving v2 to v1\n" );
11592 #endif
11593 flip2 = 0;
11594 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
11595 {
11596 struct edgeuse *eu1, *eu2;
11597 vect_t vec1, vec2, vec3;
11598 vect_t norma;
11599 plane_t normb;
11600 struct vertex_g *vg1, *vg2;
11601 fastf_t dist, dot1;
11602
11603 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11604 continue;
11605
11606 eu1 = vu->up.eu_p;
11607 eu2 = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
11608
11609 if( eu2->eumate_p->vu_p->v_p == v1 )
11610 continue;
11611
11612 if( eu2->vu_p->v_p == v1 )
11613 continue;
11614
11615 vg1 = eu2->vu_p->v_p->vg_p;
11616 vg2 = eu2->eumate_p->vu_p->v_p->vg_p;
11617
11618 VSUB2( vec1, v2->vg_p->coord, vg1->coord )
11619 VSUB2( vec2, vg2->coord, vg1->coord )
11620 VCROSS( norma, vec1, vec2 )
11621 #if EDGE_COLLAPSE_DEBUG
11622 bu_log( "\t\toriginal tri (%g %g %g) (%g %g %g) (%g %g %g)\n",
11623 V3ARGS( v2->vg_p->coord ),
11624 V3ARGS( vg1->coord ),
11625 V3ARGS( vg2->coord ) );
11626 #endif
11627
11628 VSUB2( vec1, v1->vg_p->coord, vg1->coord )
11629 VCROSS( normb, vec1, vec2 )
11630 VSUB2( vec3, v1->vg_p->coord, vg2->coord );
11631 VSUB2( vec3, v2->vg_p->coord, vg2->coord )
11632 VUNITIZE( vec1 );
11633 VUNITIZE( vec2 );
11634 VUNITIZE( vec3 );
11635
11636 dot1 = VDOT( vec1, vec2 );
11637 if( dot1 > max_dot2 )
11638 max_dot2 = dot1;
11639 dot1 = VDOT( vec1, vec3 );
11640 if( dot1 > max_dot2 )
11641 max_dot2 = dot1;
11642 dot1 = -VDOT( vec2, vec3 );
11643 if( dot1 > max_dot2 )
11644 max_dot2 = dot1;
11645 #if EDGE_COLLAPSE_DEBUG
11646 bu_log( "\t\tnew tri (%g %g %g) (%g %g %g) (%g %g %g)\n",
11647 V3ARGS( v1->vg_p->coord ),
11648 V3ARGS( vg1->coord ),
11649 V3ARGS( vg2->coord ) );
11650 #endif
11651
11652 fu = nmg_find_fu_of_eu( eu1 );
11653 if( fu->orientation == OT_SAME )
11654 {
11655 VUNITIZE( normb )
11656 normb[3] = VDOT( normb, v1->vg_p->coord );
11657
11658 dist = fabs( DIST_PT_PLANE( v2->vg_p->coord, normb ));
11659 #if EDGE_COLLAPSE_DEBUG
11660 bu_log( "\t\t\tdist = %g\n", dist );
11661 #endif
11662 if( dist > max_dist2 )
11663 max_dist2 = dist;
11664 }
11665 #if EDGE_COLLAPSE_DEBUG
11666 else
11667 bu_log( "\t\t\tfu->orientation = %s\n", nmg_orientation( fu->orientation ) );
11668 #endif
11669
11670 if( VDOT( norma, normb ) <= 0.0 )
11671 {
11672
11673 #if EDGE_COLLAPSE_DEBUG
11674 bu_log( "\t\t\tflip2 = 1\n" );
11675 #endif
11676 flip2 = 1;
11677 break;
11678 }
11679 }
11680 #if EDGE_COLLAPSE_DEBUG
11681 bu_log( "\tmax_dist1=%g, flip1=%d, max_dist2=%g, flip2=%d\n", max_dist1, flip1, max_dist2, flip2 );
11682 #endif
11683
11684 if( max_dist1 < 0.0 )
11685 max_dist1 = MAX_FASTF;
11686 if( max_dist2 < 0.0 )
11687 max_dist2 = MAX_FASTF;
11688 if( ((max_dist1 > tol_coll) || (flip1 > 0) ) &&
11689 ((max_dist2 > tol_coll) || (flip2 > 0) ) )
11690 continue;
11691
11692
11693
11694
11695
11696
11697 no_collapse = 0;
11698 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
11699 {
11700 struct edgeuse *eu1, *eu1a;
11701 struct edgeuse *eu2, *eu2a;
11702 struct vertexuse *vu2;
11703
11704 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11705 continue;
11706
11707 eu1 = vu->up.eu_p;
11708 if( eu1->e_p == e )
11709 continue;
11710
11711 eu1a = BU_LIST_PNEXT_CIRC( edgeuse, &eu1->l );
11712
11713 for( BU_LIST_FOR( vu2, vertexuse, &v2->vu_hd ) )
11714 {
11715 if( *vu2->up.magic_p != NMG_EDGEUSE_MAGIC )
11716 continue;
11717
11718 eu2 = vu2->up.eu_p;
11719 if( eu2->e_p == e )
11720 continue;
11721 if( eu2->e_p == eu1->e_p )
11722 continue;
11723
11724 eu2a = BU_LIST_PNEXT_CIRC( edgeuse, &eu2->l );
11725
11726 if( NMG_ARE_EUS_ADJACENT( eu1a, eu2a ) )
11727 {
11728 no_collapse = 1;
11729 break;
11730 }
11731 }
11732
11733 if( no_collapse )
11734 break;
11735 }
11736
11737 if( no_collapse )
11738 {
11739 #if EDGE_COLLAPSE_DEBUG
11740 bu_log( "\tNot collapsing edge (would create 2D object)\n" );
11741 #endif
11742 continue;
11743 }
11744
11745 choice = nmg_select_collapse( max_dist1, max_dot1, flip1,
11746 max_dist2, max_dot2, flip2,
11747 max_dot, tol_coll );
11748
11749 if( !choice )
11750 continue;
11751 #if EDGE_COLLAPSE_DEBUG
11752 bu_log( "\tCollapsing edge\n" );
11753 #endif
11754
11755 bu_ptbl_zero( &edge_table, (long *)e );
11756
11757 sub_count++;
11758
11759
11760 eu2 = eu->radial_p;
11761 done = 0;
11762 while( !done )
11763 {
11764 struct edgeuse *next;
11765 struct loopuse *lu;
11766 struct faceuse *fu;
11767
11768 next = eu2->eumate_p->radial_p;
11769 if( next == eu2 )
11770 done = 1;
11771
11772 if( *eu2->up.magic_p != NMG_LOOPUSE_MAGIC )
11773 (void)nmg_keu( eu2 );
11774 else
11775 {
11776 lu = eu2->up.lu_p;
11777 if( *lu->up.magic_p != NMG_FACEUSE_MAGIC )
11778 (void)nmg_klu( lu );
11779 else
11780 {
11781 fu = lu->up.fu_p;
11782 if( nmg_klu( lu ) )
11783 nmg_kfu( fu );
11784 }
11785 }
11786 eu2 = next;
11787 }
11788
11789 if( choice == 1 )
11790 {
11791 struct edgeuse *eu1,*eu2;
11792 struct vertexuse *vu2;
11793 #if EDGE_COLLAPSE_DEBUG
11794 bu_log( "\tMoving v1 to v2 (%g %g %g) -> (%g %g %g)\n", V3ARGS( v1->vg_p->coord ), V3ARGS( v2->vg_p->coord ) );
11795 #endif
11796
11797
11798
11799 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
11800 {
11801 struct faceuse *fu;
11802 struct edge_g_lseg *eg;
11803 struct vertex_g *v1a;
11804
11805 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11806 continue;
11807
11808 eu1 = vu->up.eu_p;
11809 fu = nmg_find_fu_of_eu( eu1 );
11810 if( !fu )
11811 continue;
11812
11813 if( fu->orientation != OT_SAME )
11814 continue;
11815
11816 if( !eu1->g.magic_p )
11817 nmg_edge_g( eu1 );
11818 else if( *eu1->g.magic_p != NMG_EDGE_G_LSEG_MAGIC )
11819 continue;
11820
11821 eg = eu1->g.lseg_p;
11822 v1a = eu1->eumate_p->vu_p->v_p->vg_p;
11823 VSUB2( eg->e_dir, v2->vg_p->coord, v1a->coord );
11824 VMOVE( eg->e_pt, v2->vg_p->coord );
11825 }
11826
11827 done = 0;
11828 while( !done )
11829 {
11830 vu = BU_LIST_FIRST( vertexuse, &v1->vu_hd );
11831 if( BU_LIST_LAST( vertexuse, &v1->vu_hd ) == vu )
11832 done = 1;
11833 nmg_movevu( vu, v2 );
11834 }
11835 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
11836 {
11837 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11838 continue;
11839
11840 eu1 = vu->up.eu_p;
11841
11842 vu2 = BU_LIST_NEXT( vertexuse, &vu->l );
11843 while( BU_LIST_NOT_HEAD( &vu2->l, &v2->vu_hd ) )
11844 {
11845 if( *vu2->up.magic_p != NMG_EDGEUSE_MAGIC )
11846 {
11847 vu2 = BU_LIST_NEXT( vertexuse, &vu2->l );
11848 continue;
11849 }
11850 eu2 = vu2->up.eu_p;
11851 if( eu2->eumate_p->vu_p->v_p == eu1->eumate_p->vu_p->v_p &&
11852 eu2->e_p != eu1->e_p )
11853 {
11854 struct edge *e1, *e2;
11855
11856 e1 = eu1->e_p;
11857 e2 = eu2->e_p;
11858
11859 nmg_radial_join_eu_NEW( eu2, eu1, tol );
11860 if( eu1->e_p != e1 )
11861 bu_ptbl_zero( &edge_table, (long *)e1 );
11862 if( eu2->e_p != e2 )
11863 bu_ptbl_zero( &edge_table, (long *)e2 );
11864 }
11865 vu2 = BU_LIST_NEXT( vertexuse, &vu2->l );
11866 }
11867 }
11868 }
11869 else if( choice == 2 )
11870 {
11871 struct edgeuse *eu1,*eu2;
11872 struct vertexuse *vu2;
11873 #if EDGE_COLLAPSE_DEBUG
11874 bu_log( "\tMoving v2 to v1 (%g %g %g) -> (%g %g %g)\n", V3ARGS( v2->vg_p->coord ), V3ARGS( v1->vg_p->coord ) );
11875 #endif
11876
11877
11878 for( BU_LIST_FOR( vu, vertexuse, &v2->vu_hd ) )
11879 {
11880 struct faceuse *fu;
11881 struct edge_g_lseg *eg;
11882 struct vertex_g *v1a;
11883
11884 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11885 continue;
11886
11887 eu1 = vu->up.eu_p;
11888 fu = nmg_find_fu_of_eu( eu1 );
11889 if( !fu )
11890 continue;
11891
11892 if( fu->orientation != OT_SAME )
11893 continue;
11894
11895 if( !eu1->g.magic_p )
11896 nmg_edge_g( eu1 );
11897 else if( *eu1->g.magic_p != NMG_EDGE_G_LSEG_MAGIC )
11898 continue;
11899
11900 eg = eu1->g.lseg_p;
11901 v1a = eu1->eumate_p->vu_p->v_p->vg_p;
11902 VSUB2( eg->e_dir, v1->vg_p->coord, v1a->coord );
11903 VMOVE( eg->e_pt, v1->vg_p->coord );
11904 }
11905
11906 done = 0;
11907 while( !done )
11908 {
11909 vu = BU_LIST_FIRST( vertexuse, &v2->vu_hd );
11910 if( BU_LIST_LAST( vertexuse, &v2->vu_hd ) == vu )
11911 done = 1;
11912 nmg_movevu( vu, v1 );
11913 }
11914 for( BU_LIST_FOR( vu, vertexuse, &v1->vu_hd ) )
11915 {
11916 if( *vu->up.magic_p != NMG_EDGEUSE_MAGIC )
11917 continue;
11918
11919 eu1 = vu->up.eu_p;
11920
11921 vu2 = BU_LIST_NEXT( vertexuse, &vu->l );
11922 while( BU_LIST_NOT_HEAD( &vu2->l, &v1->vu_hd ) )
11923 {
11924 if( *vu2->up.magic_p != NMG_EDGEUSE_MAGIC )
11925 {
11926 vu2 = BU_LIST_NEXT( vertexuse, &vu2->l );
11927 continue;
11928 }
11929 eu2 = vu2->up.eu_p;
11930 if( eu2->eumate_p->vu_p->v_p == eu1->eumate_p->vu_p->v_p &&
11931 eu2->e_p != eu1->e_p )
11932 {
11933 struct edge *e1, *e2;
11934
11935 e1 = eu1->e_p;
11936 e2 = eu2->e_p;
11937 nmg_radial_join_eu_NEW( eu2, eu1, tol );
11938 if( eu1->e_p != e1 )
11939 bu_ptbl_zero( &edge_table, (long *)e1 );
11940 if( eu2->e_p != e2 )
11941 bu_ptbl_zero( &edge_table, (long *)e2 );
11942 }
11943 vu2 = BU_LIST_NEXT( vertexuse, &vu2->l );
11944 }
11945 }
11946 }
11947 else
11948 continue;
11949 }
11950 count += sub_count;
11951 }
11952
11953 if( count )
11954 {
11955
11956
11957 bu_ptbl_reset( &edge_table );
11958 nmg_face_tabulate( &edge_table, &m->magic );
11959
11960 for( i=0 ; i<BU_PTBL_END( &edge_table ) ; i++ )
11961 {
11962 struct face *f;
11963 struct faceuse *fu;
11964
11965 f = (struct face *)BU_PTBL_GET( &edge_table, i );
11966 NMG_CK_FACE( f );
11967 fu = f->fu_p;
11968 if( fu->orientation != OT_SAME )
11969 fu = fu->fumate_p;
11970 if( fu->orientation != OT_SAME )
11971 bu_bomb( "nmg_edge_collapse: Face has no OT_SAME use!!!\n" );
11972
11973 nmg_calc_face_g( fu );
11974 }
11975 }
11976 bu_ptbl_free( &edge_table );
11977 return( count );
11978 }
11979
11980
11981
11982
11983
11984
11985 struct rt_bot_internal *
11986 nmg_bot(struct shell *s, const struct bn_tol *tol)
11987 {
11988 struct rt_bot_internal *bot;
11989 struct bu_ptbl nmg_vertices;
11990 struct bu_ptbl nmg_faces;
11991 int i, face_no;
11992 struct vertex *v;
11993
11994 NMG_CK_SHELL( s );
11995 BN_CK_TOL(tol);
11996
11997
11998 (void)nmg_triangulate_shell(s, tol);
11999
12000
12001 nmg_vertex_tabulate( &nmg_vertices, &s->l.magic );
12002
12003
12004 nmg_face_tabulate( &nmg_faces, &s->l.magic );
12005
12006
12007 bot = (struct rt_bot_internal *)bu_calloc(1, sizeof( struct rt_bot_internal ), "BOT from NMG" );
12008
12009 bot->magic = RT_BOT_INTERNAL_MAGIC;
12010 bot->mode = RT_BOT_SOLID;
12011 bot->orientation = RT_BOT_CCW;
12012 bot->bot_flags = 0;
12013
12014 bot->num_vertices = BU_PTBL_LEN( &nmg_vertices );
12015 bot->num_faces = 0;
12016
12017
12018 for( i=0 ; i<BU_PTBL_LEN( &nmg_faces ); i++ )
12019 {
12020 struct face *f;
12021 struct faceuse *fu;
12022 struct loopuse *lu;
12023
12024 f = (struct face *)BU_PTBL_GET( &nmg_faces, i );
12025 NMG_CK_FACE( f );
12026
12027 fu = f->fu_p;
12028
12029 if( fu->orientation != OT_SAME )
12030 {
12031 fu = fu->fumate_p;
12032 if( fu->orientation != OT_SAME )
12033 {
12034 bu_log( "nmg_bot(): Face has no OT_SAME use!!!!\n" );
12035 bu_free( (char *)bot->vertices, "BOT vertices" );
12036 bu_free( (char *)bot->faces, "BOT faces" );
12037 bu_free( (char *)bot, "BOT" );
12038 return( (struct rt_bot_internal *)NULL );
12039 }
12040 }
12041
12042 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
12043 {
12044 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
12045 continue;
12046 bot->num_faces++;
12047 }
12048 }
12049
12050 bot->faces = (int *)bu_calloc( bot->num_faces * 3, sizeof( int ), "BOT faces" );
12051 bot->vertices = (fastf_t *)bu_calloc( bot->num_vertices * 3, sizeof( fastf_t ), "BOT vertices" );
12052
12053 bot->thickness = (fastf_t *)NULL;
12054 bot->face_mode = (struct bu_bitv *)NULL;
12055
12056
12057 for( i=0 ; i<BU_PTBL_LEN( &nmg_vertices ) ; i++ )
12058 {
12059 struct vertex_g *vg;
12060
12061 v = (struct vertex *)BU_PTBL_GET( &nmg_vertices, i );
12062 NMG_CK_VERTEX( v );
12063
12064 vg = v->vg_p;
12065 NMG_CK_VERTEX_G( vg );
12066
12067 VMOVE( &bot->vertices[i*3], vg->coord );
12068 }
12069
12070
12071 face_no = 0;
12072 for( i=0 ; i<BU_PTBL_LEN( &nmg_faces ); i++ )
12073 {
12074 struct face *f;
12075 struct faceuse *fu;
12076 struct loopuse *lu;
12077
12078 f = (struct face *)BU_PTBL_GET( &nmg_faces, i );
12079 NMG_CK_FACE( f );
12080
12081 fu = f->fu_p;
12082
12083 if( fu->orientation != OT_SAME )
12084 {
12085 fu = fu->fumate_p;
12086 if( fu->orientation != OT_SAME )
12087 {
12088 bu_log( "nmg_bot(): Face has no OT_SAME use!!!!\n" );
12089 bu_free( (char *)bot->vertices, "BOT vertices" );
12090 bu_free( (char *)bot->faces, "BOT faces" );
12091 bu_free( (char *)bot, "BOT" );
12092 return( (struct rt_bot_internal *)NULL );
12093 }
12094 }
12095
12096 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
12097 {
12098 struct edgeuse *eu;
12099 int vertex_no=0;
12100
12101 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
12102 continue;
12103
12104 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
12105 {
12106 struct vertex *v;
12107
12108 if( vertex_no > 2 )
12109 {
12110 bu_log( "nmg_bot(): Face has not been triangulated!!!\n" );
12111 bu_free( (char *)bot->vertices, "BOT vertices" );
12112 bu_free( (char *)bot->faces, "BOT faces" );
12113 bu_free( (char *)bot, "BOT" );
12114 return( (struct rt_bot_internal *)NULL );
12115 }
12116
12117 v = eu->vu_p->v_p;
12118 NMG_CK_VERTEX( v );
12119
12120
12121 bot->faces[ face_no*3 + vertex_no ] = bu_ptbl_locate( &nmg_vertices, (long *)v );
12122
12123 vertex_no++;
12124 }
12125
12126 face_no++;
12127 }
12128 }
12129
12130 bu_ptbl_free( &nmg_vertices );
12131 bu_ptbl_free( &nmg_faces );
12132
12133 return( bot );
12134 }
12135
12136
12137
12138
12139
12140
12141
12142 void
12143 nmg_vlist_to_eu( struct bu_list *vlist, struct shell *s )
12144 {
12145 point_t pt1, pt2;
12146 struct bn_vlist *vp;
12147 struct edgeuse *eu;
12148 struct vertex *v=NULL;
12149 struct vertex *polyStartV=NULL;
12150
12151 for( BU_LIST_FOR( vp, bn_vlist, vlist ) ) {
12152 register int i;
12153 register int nused = vp->nused;
12154 register int *cmd = vp->cmd;
12155 register point_t *pt = vp->pt;
12156 for( i = 0; i < nused; i++,cmd++,pt++ ) {
12157 switch( *cmd ) {
12158 case BN_VLIST_LINE_MOVE:
12159 case BN_VLIST_POLY_MOVE:
12160 VMOVE( pt2, *pt );
12161 v = NULL;
12162 polyStartV = NULL;
12163 break;
12164 case BN_VLIST_LINE_DRAW:
12165 case BN_VLIST_POLY_DRAW:
12166 VMOVE( pt1, pt2 );
12167 VMOVE( pt2, *pt );
12168 eu = nmg_me( v, NULL, s );
12169 if( v == NULL ) {
12170 nmg_vertex_gv( eu->vu_p->v_p, pt1 );
12171 }
12172 nmg_vertex_gv( eu->eumate_p->vu_p->v_p, pt2 );
12173 v = eu->eumate_p->vu_p->v_p;
12174 if( polyStartV == NULL ) polyStartV = eu->vu_p->v_p;
12175 break;
12176 case BN_VLIST_POLY_END:
12177 if( v != NULL && polyStartV != NULL ) {
12178 eu = nmg_me( v, polyStartV, s );
12179 }
12180 break;
12181 case BN_VLIST_POLY_START:
12182 polyStartV = NULL;
12183 v = NULL;
12184 break;
12185 default:
12186 break;
12187 }
12188 }
12189 }
12190 }
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200