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 RCSpg[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_pg.c,v 14.11 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00043 #endif
00044
00045 #include "common.h"
00046
00047
00048
00049 #include <stdio.h>
00050 #include <math.h>
00051 #include "machine.h"
00052 #include "vmath.h"
00053 #include "db.h"
00054 #include "nmg.h"
00055 #include "rtgeom.h"
00056 #include "raytrace.h"
00057 #include "./debug.h"
00058 #include "./plane.h"
00059
00060 #define TRI_NULL ((struct tri_specific *)0)
00061
00062 HIDDEN int rt_pgface(struct soltab *stp, fastf_t *ap, fastf_t *bp, fastf_t *cp, const struct bn_tol *tol);
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 int
00079 rt_pg_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00080 {
00081 struct rt_pg_internal *pgp;
00082 register int i;
00083 int p;
00084
00085 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00086 RT_PG_CK_MAGIC(pgp);
00087
00088 for( p = 0; p < pgp->npoly; p++ ) {
00089 LOCAL vect_t work[3];
00090
00091 VMOVE( work[0], &pgp->poly[p].verts[0*3] );
00092 VMINMAX( stp->st_min, stp->st_max, work[0] );
00093 VMOVE( work[1], &pgp->poly[p].verts[1*3] );
00094 VMINMAX( stp->st_min, stp->st_max, work[1] );
00095
00096 for( i=2; i < pgp->poly[p].npts; i++ ) {
00097 VMOVE( work[2], &pgp->poly[p].verts[i*3] );
00098 VMINMAX( stp->st_min, stp->st_max, work[2] );
00099
00100
00101 (void)rt_pgface( stp,
00102 work[0], work[1], work[2], &rtip->rti_tol );
00103
00104
00105 VMOVE( work[1], work[2] );
00106 }
00107 }
00108 if( stp->st_specific == (genptr_t)0 ) {
00109 bu_log("pg(%s): no faces\n", stp->st_name);
00110 return(-1);
00111 }
00112
00113 {
00114 LOCAL fastf_t dx, dy, dz;
00115 LOCAL fastf_t f;
00116
00117 VADD2SCALE( stp->st_center, stp->st_max, stp->st_min, 0.5 );
00118
00119 dx = (stp->st_max[X] - stp->st_min[X])/2;
00120 f = dx;
00121 dy = (stp->st_max[Y] - stp->st_min[Y])/2;
00122 if( dy > f ) f = dy;
00123 dz = (stp->st_max[Z] - stp->st_min[Z])/2;
00124 if( dz > f ) f = dz;
00125 stp->st_aradius = f;
00126 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00127 }
00128
00129 return(0);
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 HIDDEN int
00144 rt_pgface(struct soltab *stp, fastf_t *ap, fastf_t *bp, fastf_t *cp, const struct bn_tol *tol)
00145 {
00146 register struct tri_specific *trip;
00147 vect_t work;
00148 LOCAL fastf_t m1, m2, m3, m4;
00149
00150 BU_GETSTRUCT( trip, tri_specific );
00151 VMOVE( trip->tri_A, ap );
00152 VSUB2( trip->tri_BA, bp, ap );
00153 VSUB2( trip->tri_CA, cp, ap );
00154 VCROSS( trip->tri_wn, trip->tri_BA, trip->tri_CA );
00155
00156
00157 m1 = MAGNITUDE( trip->tri_BA );
00158 m2 = MAGNITUDE( trip->tri_CA );
00159 VSUB2( work, bp, cp );
00160 m3 = MAGNITUDE( work );
00161 m4 = MAGNITUDE( trip->tri_wn );
00162 if( m1 < tol->dist || m2 < tol->dist ||
00163 m3 < tol->dist || m4 < tol->dist ) {
00164 bu_free( (char *)trip, "getstruct tri_specific");
00165 if( RT_G_DEBUG & DEBUG_ARB8 )
00166 bu_log("pg(%s): degenerate facet\n", stp->st_name);
00167 return(0);
00168 }
00169
00170
00171
00172
00173
00174 VMOVE( trip->tri_N, trip->tri_wn );
00175 VUNITIZE( trip->tri_N );
00176
00177
00178 trip->tri_forw = (struct tri_specific *)stp->st_specific;
00179 stp->st_specific = (genptr_t)trip;
00180 return(3);
00181 }
00182
00183
00184
00185
00186 void
00187 rt_pg_print(register const struct soltab *stp)
00188 {
00189 register const struct tri_specific *trip =
00190 (struct tri_specific *)stp->st_specific;
00191
00192 if( trip == TRI_NULL ) {
00193 bu_log("pg(%s): no faces\n", stp->st_name);
00194 return;
00195 }
00196 do {
00197 VPRINT( "A", trip->tri_A );
00198 VPRINT( "B-A", trip->tri_BA );
00199 VPRINT( "C-A", trip->tri_CA );
00200 VPRINT( "BA x CA", trip->tri_wn );
00201 VPRINT( "Normal", trip->tri_N );
00202 bu_log("\n");
00203 } while( (trip = trip->tri_forw) );
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int
00217 rt_pg_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00218 {
00219 register struct tri_specific *trip =
00220 (struct tri_specific *)stp->st_specific;
00221 #define MAXHITS 128
00222 LOCAL struct hit hits[MAXHITS];
00223 register struct hit *hp;
00224 LOCAL int nhits;
00225
00226 nhits = 0;
00227 hp = &hits[0];
00228
00229
00230 for( ; trip; trip = trip->tri_forw ) {
00231 FAST fastf_t dn;
00232 LOCAL fastf_t abs_dn;
00233 FAST fastf_t k;
00234 LOCAL fastf_t alpha, beta;
00235 LOCAL vect_t wxb;
00236 LOCAL vect_t xp;
00237
00238
00239
00240
00241
00242 dn = VDOT( trip->tri_wn, rp->r_dir );
00243
00244
00245
00246
00247
00248 abs_dn = dn >= 0.0 ? dn : (-dn);
00249 if( abs_dn < SQRT_SMALL_FASTF )
00250 continue;
00251 VSUB2( wxb, trip->tri_A, rp->r_pt );
00252 VCROSS( xp, wxb, rp->r_dir );
00253
00254
00255 alpha = VDOT( trip->tri_CA, xp );
00256 if( dn < 0.0 ) alpha = -alpha;
00257 if( alpha < 0.0 || alpha > abs_dn )
00258 continue;
00259
00260
00261 beta = VDOT( trip->tri_BA, xp );
00262 if( dn > 0.0 ) beta = -beta;
00263 if( beta < 0.0 || beta > abs_dn )
00264 continue;
00265 if( alpha+beta > abs_dn )
00266 continue;
00267 k = VDOT( wxb, trip->tri_wn ) / dn;
00268
00269
00270
00271
00272
00273
00274
00275
00276 VJOIN1( hp->hit_point, rp->r_pt, k, rp->r_dir );
00277
00278
00279 hp->hit_magic = RT_HIT_MAGIC;
00280 hp->hit_dist = k;
00281 VMOVE( hp->hit_normal, trip->tri_N );
00282 if( ++nhits >= MAXHITS ) {
00283 bu_log("rt_pg_shot(%s): too many hits (%d)\n", stp->st_name, nhits);
00284 break;
00285 }
00286 hp++;
00287 }
00288 if( nhits == 0 )
00289 return(0);
00290
00291
00292 rt_hitsort( hits, nhits );
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 {
00305 register int i, j;
00306
00307 for( i=0 ; i<nhits-1 ; i++ )
00308 {
00309 fastf_t dist;
00310
00311 dist = hits[i].hit_dist - hits[i+1].hit_dist;
00312 if( NEAR_ZERO( dist, ap->a_rt_i->rti_tol.dist ) &&
00313 VDOT( hits[i].hit_normal, rp->r_dir ) *
00314 VDOT( hits[i+1].hit_normal, rp->r_dir) > 0)
00315 {
00316 for( j=i ; j<nhits-1 ; j++ )
00317 hits[j] = hits[j+1];
00318 nhits--;
00319 i--;
00320 }
00321 }
00322 }
00323
00324
00325 if( nhits == 1 )
00326 nhits = 0;
00327
00328 if( nhits&1 ) {
00329 register int i;
00330 static int nerrors = 0;
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 if( nerrors++ < 6 ) {
00341 bu_log("rt_pg_shot(%s): WARNING %d hits:\n", stp->st_name, nhits);
00342 bu_log( "\tray start = (%g %g %g) ray dir = (%g %g %g)\n",
00343 V3ARGS( rp->r_pt ), V3ARGS( rp->r_dir ) );
00344 for(i=0; i < nhits; i++ )
00345 {
00346 point_t tmp_pt;
00347
00348 VJOIN1( tmp_pt, rp->r_pt, hits[i].hit_dist, rp->r_dir );
00349 if( VDOT( rp->r_dir, hits[i].hit_normal ) < 0.0 )
00350 bu_log("\tentrance at dist=%f (%g %g %g)\n", hits[i].hit_dist, V3ARGS( tmp_pt ) );
00351 else
00352 bu_log("\texit at dist=%f (%g %g %g)\n", hits[i].hit_dist, V3ARGS( tmp_pt ) );
00353 }
00354 }
00355
00356 if( nhits > 2 )
00357 {
00358 fastf_t dot1,dot2;
00359 int j;
00360
00361
00362
00363
00364 dot2 = 1.0;
00365 i = 0;
00366 while( i<nhits )
00367 {
00368 dot1 = dot2;
00369 dot2 = VDOT( rp->r_dir, hits[i].hit_normal );
00370 if( dot1 > 0.0 && dot2 > 0.0 )
00371 {
00372
00373
00374
00375
00376 for( j=nhits ; j>i ; j-- )
00377 hits[j] = hits[j-1];
00378
00379 VREVERSE( hits[i].hit_normal, hits[i].hit_normal );
00380 dot2 = VDOT( rp->r_dir, hits[i].hit_normal );
00381 nhits++;
00382 bu_log( "\t\tadding fictitious entry at %f (%s)\n", hits[i].hit_dist, stp->st_name );
00383 }
00384 else if( dot1 < 0.0 && dot2 < 0.0 )
00385 {
00386
00387
00388
00389
00390 for( j=nhits ; j>i ; j-- )
00391 hits[j] = hits[j-1];
00392
00393 hits[i] = hits[i-1];
00394 VREVERSE( hits[i].hit_normal, hits[i-1].hit_normal );
00395 dot2 = VDOT( rp->r_dir, hits[i].hit_normal );
00396 nhits++;
00397 bu_log( "\t\tadding fictitious exit at %f (%s)\n", hits[i].hit_dist, stp->st_name );
00398 }
00399 i++;
00400 }
00401
00402 }
00403 else
00404 {
00405 hits[nhits] = hits[nhits-1];
00406 VREVERSE( hits[nhits].hit_normal, hits[nhits-1].hit_normal );
00407 bu_log( "\t\tadding fictitious hit at %f (%s)\n", hits[nhits].hit_dist, stp->st_name );
00408 nhits++;
00409 }
00410 }
00411
00412 if( nhits&1 )
00413 {
00414 if( nhits < MAXHITS )
00415 {
00416 hits[nhits] = hits[nhits-1];
00417 VREVERSE( hits[nhits].hit_normal, hits[nhits-1].hit_normal );
00418 bu_log( "\t\tadding fictitious hit at %f (%s)\n", hits[nhits].hit_dist, stp->st_name );
00419 nhits++;
00420 }
00421 else
00422 nhits--;
00423 }
00424
00425
00426 {
00427 register struct seg *segp;
00428 register int i;
00429 for( i=0; i < nhits; i += 2 ) {
00430 RT_GET_SEG(segp, ap->a_resource);
00431 segp->seg_stp = stp;
00432 segp->seg_in = hits[i];
00433 segp->seg_out = hits[i+1];
00434 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00435 }
00436 }
00437 return(nhits);
00438 }
00439
00440
00441
00442
00443 void
00444 rt_pg_free(struct soltab *stp)
00445 {
00446 register struct tri_specific *trip =
00447 (struct tri_specific *)stp->st_specific;
00448
00449 while( trip != TRI_NULL ) {
00450 register struct tri_specific *nexttri = trip->tri_forw;
00451
00452 bu_free( (char *)trip, "pg tri_specific");
00453 trip = nexttri;
00454 }
00455 }
00456
00457
00458
00459
00460 void
00461 rt_pg_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00462 {
00463
00464 }
00465
00466
00467
00468
00469 void
00470 rt_pg_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00471 {
00472
00473 uvp->uv_u = uvp->uv_v = 0;
00474 uvp->uv_du = uvp->uv_dv = 0;
00475 }
00476
00477
00478
00479
00480 int
00481 rt_pg_class(void)
00482 {
00483 return(0);
00484 }
00485
00486
00487
00488
00489 int
00490 rt_pg_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00491 {
00492 register int i;
00493 register int p;
00494 struct rt_pg_internal *pgp;
00495
00496 RT_CK_DB_INTERNAL(ip);
00497 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00498 RT_PG_CK_MAGIC(pgp);
00499
00500 for( p = 0; p < pgp->npoly; p++ ) {
00501 register struct rt_pg_face_internal *pp;
00502
00503 pp = &pgp->poly[p];
00504 RT_ADD_VLIST( vhead, &pp->verts[3*(pp->npts-1)],
00505 BN_VLIST_LINE_MOVE );
00506 for( i=0; i < pp->npts; i++ ) {
00507 RT_ADD_VLIST( vhead, &pp->verts[3*i],
00508 BN_VLIST_LINE_DRAW );
00509 }
00510 }
00511 return(0);
00512 }
00513
00514
00515
00516
00517
00518
00519 int
00520 rt_pg_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00521 {
00522 register int i;
00523 register int p;
00524 struct rt_pg_internal *pgp;
00525
00526 RT_CK_DB_INTERNAL(ip);
00527 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00528 RT_PG_CK_MAGIC(pgp);
00529
00530 for( p = 0; p < pgp->npoly; p++ ) {
00531 register struct rt_pg_face_internal *pp;
00532 vect_t aa, bb, norm;
00533
00534 pp = &pgp->poly[p];
00535 if (pp->npts < 3)
00536 continue;
00537 VSUB2( aa, &pp->verts[3*(0)], &pp->verts[3*(1)] );
00538 VSUB2( bb, &pp->verts[3*(0)], &pp->verts[3*(2)] );
00539 VCROSS( norm, aa, bb );
00540 VUNITIZE(norm);
00541 RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START);
00542
00543 RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_MOVE);
00544 for (i=0; i < pp->npts-1; i++) {
00545 RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_POLY_DRAW);
00546 }
00547 RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_END);
00548 }
00549 return(0);
00550 }
00551
00552
00553
00554
00555 void
00556 rt_pg_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00557 {
00558 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00559 cvp->crv_c1 = cvp->crv_c2 = 0;
00560 }
00561
00562
00563
00564
00565 int
00566 rt_pg_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00567 {
00568 register int i;
00569 struct shell *s;
00570 struct vertex **verts;
00571 struct vertex ***vertp;
00572 struct faceuse *fu;
00573 register int p;
00574 struct rt_pg_internal *pgp;
00575
00576 RT_CK_DB_INTERNAL(ip);
00577 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00578 RT_PG_CK_MAGIC(pgp);
00579
00580 *r = nmg_mrsv( m );
00581 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
00582
00583 verts = (struct vertex **)bu_malloc(
00584 pgp->max_npts * sizeof(struct vertex *), "pg_tess verts[]");
00585 vertp = (struct vertex ***)bu_malloc(
00586 pgp->max_npts * sizeof(struct vertex **), "pg_tess vertp[]");
00587 for( i=0; i < pgp->max_npts; i++ )
00588 vertp[i] = &verts[i];
00589
00590 for( p = 0; p < pgp->npoly; p++ ) {
00591 register struct rt_pg_face_internal *pp;
00592
00593 pp = &pgp->poly[p];
00594
00595
00596 for( i=0; i < pp->npts; i++ ) {
00597 verts[i] = nmg_find_pt_in_shell( s,
00598 &pp->verts[3*i], tol );
00599 }
00600
00601
00602 if( (fu = nmg_cmface( s, vertp, pp->npts )) == (struct faceuse *)0 ) {
00603 bu_log("rt_pg_tess() nmg_cmface failed, skipping face %d\n",
00604 p);
00605 }
00606
00607
00608 for( i=0; i < pp->npts; i++ ) {
00609 if( verts[i]->vg_p ) continue;
00610 nmg_vertex_gv( verts[i], &pp->verts[3*i] );
00611 }
00612
00613
00614 if( nmg_calc_face_g( fu ) )
00615 {
00616 nmg_pr_fu_briefly( fu, "" );
00617 bu_free( (char *)verts, "pg_tess verts[]" );
00618 bu_free( (char *)vertp, "pg_tess vertp[]" );
00619 return -1;
00620 }
00621 }
00622
00623
00624 nmg_region_a( *r, tol );
00625
00626
00627
00628
00629 nmg_fix_normals( s , tol );
00630 #if 0
00631
00632 (void)nmg_mark_edges_real( &s->l );
00633 #endif
00634 bu_free( (char *)verts, "pg_tess verts[]" );
00635 bu_free( (char *)vertp, "pg_tess vertp[]" );
00636
00637 return(0);
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 int
00648 rt_pg_import(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
00649 {
00650 struct rt_pg_internal *pgp;
00651 union record *rp;
00652 register int i;
00653 int rno;
00654 int p;
00655
00656 BU_CK_EXTERNAL( ep );
00657 rp = (union record *)ep->ext_buf;
00658 if( rp->u_id != ID_P_HEAD ) {
00659 bu_log("rt_pg_import: defective header record\n");
00660 return(-1);
00661 }
00662
00663 RT_CK_DB_INTERNAL( ip );
00664 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00665 ip->idb_type = ID_POLY;
00666 ip->idb_meth = &rt_functab[ID_POLY];
00667 ip->idb_ptr = bu_malloc(sizeof(struct rt_pg_internal), "rt_pg_internal");
00668 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00669 pgp->magic = RT_PG_INTERNAL_MAGIC;
00670
00671 pgp->npoly = (ep->ext_nbytes - sizeof(union record)) /
00672 sizeof(union record);
00673 if( pgp->npoly <= 0 ) {
00674 bu_log("rt_pg_import: polysolid with no polygons!\n");
00675 return -1;
00676 }
00677 if( pgp->npoly )
00678 pgp->poly = (struct rt_pg_face_internal *)bu_malloc(
00679 pgp->npoly * sizeof(struct rt_pg_face_internal), "rt_pg_face_internal");
00680 pgp->max_npts = 0;
00681
00682 for( p=0; p < pgp->npoly; p++ ) {
00683 register struct rt_pg_face_internal *pp;
00684
00685 pp = &pgp->poly[p];
00686 rno = p+1;
00687 if( rp[rno].q.q_id != ID_P_DATA ) {
00688 bu_log("rt_pg_import: defective data record\n");
00689 return -1;
00690 }
00691 pp->npts = rp[rno].q.q_count;
00692 pp->verts = (fastf_t *)bu_malloc(
00693 pp->npts * 3 * sizeof(fastf_t), "pg verts[]" );
00694 pp->norms = (fastf_t *)bu_malloc(
00695 pp->npts * 3 * sizeof(fastf_t), "pg norms[]" );
00696 # include "noalias.h"
00697 for( i=0; i < pp->npts; i++ ) {
00698
00699 MAT4X3PNT( &pp->verts[i*3], mat,
00700 rp[rno].q.q_verts[i] );
00701 MAT4X3VEC( &pp->norms[i*3], mat,
00702 rp[rno].q.q_norms[i] );
00703 }
00704 if( pp->npts > pgp->max_npts ) pgp->max_npts = pp->npts;
00705 }
00706 if( pgp->max_npts < 3 ) {
00707 bu_log("rt_pg_import: polysolid with all polygons of less than %d vertices!\n", pgp->max_npts);
00708
00709 return -1;
00710 }
00711 return( 0 );
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 int
00721 rt_pg_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00722 {
00723 struct rt_pg_internal *pgp;
00724 union record *rec;
00725 register int i;
00726 int rno;
00727 int p;
00728
00729 RT_CK_DB_INTERNAL(ip);
00730 if( ip->idb_type != ID_POLY ) return(-1);
00731 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00732 RT_PG_CK_MAGIC(pgp);
00733
00734 BU_CK_EXTERNAL(ep);
00735 ep->ext_nbytes = (1 + pgp->npoly) * sizeof(union record);
00736 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "pg external");
00737 rec = (union record *)ep->ext_buf;
00738
00739 rec[0].p.p_id = ID_P_HEAD;
00740
00741 for( p=0; p < pgp->npoly; p++ ) {
00742 register struct rt_pg_face_internal *pp;
00743
00744 rno = p+1;
00745 pp = &pgp->poly[p];
00746 if( pp->npts < 3 || pp->npts > 5 ) {
00747 bu_log("rt_pg_export: unable to support npts=%d\n",
00748 pp->npts);
00749 return(-1);
00750 }
00751
00752 rec[rno].q.q_id = ID_P_DATA;
00753 rec[rno].q.q_count = pp->npts;
00754 # include "noalias.h"
00755 for( i=0; i < pp->npts; i++ ) {
00756
00757 VSCALE( rec[rno].q.q_verts[i],
00758 &pp->verts[i*3], local2mm );
00759 VMOVE( rec[rno].q.q_norms[i], &pp->norms[i*3] );
00760 }
00761 }
00762 return(0);
00763 }
00764
00765 int
00766 rt_pg_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
00767 {
00768 bu_log( "As of release 6.0 the polysolid is superceded by the BOT primitive.\n" );
00769 bu_log( "\tTo convert polysolids to BOT primitives, use 'dbupgrade'.\n");
00770
00771 return -1;
00772 }
00773
00774 int
00775 rt_pg_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00776 {
00777 bu_log( "As of release 6.0 the polysolid is superceded by the BOT primitive.\n" );
00778 bu_log( "\tTo convert polysolids to BOT primitives, use 'dbupgrade'.\n" );
00779
00780 return -1;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790 int
00791 rt_pg_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
00792 {
00793 register int j;
00794 register struct rt_pg_internal *pgp =
00795 (struct rt_pg_internal *)ip->idb_ptr;
00796 char buf[256];
00797 int i;
00798
00799 RT_PG_CK_MAGIC(pgp);
00800 bu_vls_strcat( str, "polygon solid with no topology (POLY)\n");
00801
00802 sprintf(buf, "\t%d polygons (faces)\n",
00803 pgp->npoly );
00804 bu_vls_strcat( str, buf );
00805
00806 sprintf(buf, "\tMost complex face has %d vertices\n",
00807 pgp->max_npts );
00808 bu_vls_strcat( str, buf );
00809
00810 if( pgp->npoly )
00811 {
00812 sprintf(buf, "\tFirst vertex (%g, %g, %g)\n",
00813 INTCLAMP(pgp->poly[0].verts[X] * mm2local),
00814 INTCLAMP(pgp->poly[0].verts[Y] * mm2local),
00815 INTCLAMP(pgp->poly[0].verts[Z] * mm2local) );
00816 bu_vls_strcat( str, buf );
00817 }
00818
00819 if( !verbose ) return(0);
00820
00821
00822 for( i=0; i < pgp->npoly; i++ ) {
00823 register fastf_t *v = pgp->poly[i].verts;
00824 register fastf_t *n = pgp->poly[i].norms;
00825
00826 sprintf( buf, "\tPolygon %d: (%d pts)\n",
00827 i, pgp->poly[i].npts );
00828 bu_vls_strcat( str, buf );
00829 for( j=0; j < pgp->poly[i].npts; j++ ) {
00830 sprintf(buf, "\t\tV (%g, %g, %g)\n\t\t N (%g, %g, %g)\n",
00831 INTCLAMP(v[X] * mm2local),
00832 INTCLAMP(v[Y] * mm2local),
00833 INTCLAMP(v[Z] * mm2local),
00834 INTCLAMP(n[X] * mm2local),
00835 INTCLAMP(n[Y] * mm2local),
00836 INTCLAMP(n[Z] * mm2local) );
00837 bu_vls_strcat( str, buf );
00838 v += ELEMENTS_PER_VECT;
00839 n += ELEMENTS_PER_VECT;
00840 }
00841 }
00842
00843 return(0);
00844 }
00845
00846
00847
00848
00849
00850
00851 void
00852 rt_pg_ifree(struct rt_db_internal *ip)
00853 {
00854 register struct rt_pg_internal *pgp;
00855 register int i;
00856
00857 RT_CK_DB_INTERNAL(ip);
00858 pgp = (struct rt_pg_internal *)ip->idb_ptr;
00859 RT_PG_CK_MAGIC(pgp);
00860
00861
00862
00863
00864 for( i=0; i < pgp->npoly; i++ ) {
00865 bu_free( (char *)pgp->poly[i].verts, "pg verts[]");
00866 bu_free( (char *)pgp->poly[i].norms, "pg norms[]");
00867 }
00868 if( pgp->npoly )
00869 bu_free( (char *)pgp->poly, "pg poly[]" );
00870 pgp->magic = 0;
00871 pgp->npoly = 0;
00872 bu_free( (char *)pgp, "pg ifree" );
00873 ip->idb_ptr = GENPTR_NULL;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 int
00889 rt_pg_to_bot( struct rt_db_internal *ip, const struct bn_tol *tol, struct resource *resp )
00890 {
00891 struct rt_pg_internal *ip_pg;
00892 struct rt_bot_internal *ip_bot;
00893 int max_pts;
00894 int max_tri;
00895 int p, i;
00896
00897 RT_CK_DB_INTERNAL(ip);
00898 RT_CK_TOL( tol );
00899 RT_CK_RESOURCE( resp );
00900
00901 if( ip->idb_type != ID_POLY )
00902 {
00903 bu_log( "ERROR: rt_pt_to_bot() called with a non-polysolid!!!\n" );
00904 return -1;
00905 }
00906 ip_pg = (struct rt_pg_internal *)ip->idb_ptr;
00907
00908 RT_PG_CK_MAGIC( ip_pg );
00909
00910 ip_bot = (struct rt_bot_internal *)bu_malloc( sizeof( struct rt_bot_internal ), "BOT internal" );
00911 ip_bot->magic = RT_BOT_INTERNAL_MAGIC;
00912 ip_bot->mode = RT_BOT_SOLID;
00913 ip_bot->orientation = RT_BOT_CCW;
00914 ip_bot->bot_flags = 0;
00915
00916
00917 max_pts = ip_pg->npoly * ip_pg->max_npts;
00918 BU_ASSERT_LONG( max_pts, >, 0 );
00919
00920
00921 max_tri = ip_pg->npoly * 3;
00922 BU_ASSERT_LONG( max_tri, >, 0 );
00923
00924 ip_bot->num_vertices = 0;
00925 ip_bot->num_faces = 0;
00926 ip_bot->thickness = (fastf_t *)NULL;
00927 ip_bot->face_mode = (struct bu_bitv *)NULL;
00928
00929 ip_bot->vertices = (fastf_t *)bu_calloc( max_pts * 3, sizeof( fastf_t ), "BOT vertices" );
00930 ip_bot->faces = (int *)bu_calloc( max_tri * 3, sizeof( int ), "BOT faces" );
00931
00932 for( p=0 ; p<ip_pg->npoly ; p++ )
00933 {
00934 LOCAL vect_t work[3], tmp;
00935 LOCAL struct tri_specific trip;
00936 LOCAL fastf_t m1, m2, m3, m4;
00937 LOCAL int first, v0=0, v2=0;
00938
00939 first = 1;
00940 VMOVE( work[0], &ip_pg->poly[p].verts[0*3] );
00941 VMOVE( work[1], &ip_pg->poly[p].verts[1*3] );
00942
00943 for( i=2; i < ip_pg->poly[p].npts; i++ ) {
00944 VMOVE( work[2], &ip_pg->poly[p].verts[i*3] );
00945
00946 VSUB2( trip.tri_BA, work[1], work[0] );
00947 VSUB2( trip.tri_CA, work[2], work[0] );
00948 VCROSS( trip.tri_wn, trip.tri_BA, trip.tri_CA );
00949
00950
00951 m1 = MAGNITUDE( trip.tri_BA );
00952 m2 = MAGNITUDE( trip.tri_CA );
00953 VSUB2( tmp, work[1], work[2] );
00954 m3 = MAGNITUDE( tmp );
00955 m4 = MAGNITUDE( trip.tri_wn );
00956 if( m1 >= tol->dist && m2 >= tol->dist &&
00957 m3 >= tol->dist && m4 >= tol->dist ) {
00958
00959
00960 if( first ) {
00961 ip_bot->faces[ip_bot->num_faces * 3] = ip_bot->num_vertices;
00962 VMOVE( &ip_bot->vertices[ip_bot->num_vertices * 3], work[0] );
00963 v0 = ip_bot->num_vertices;
00964 ip_bot->num_vertices++;
00965
00966 ip_bot->faces[ip_bot->num_faces * 3 + 1] = ip_bot->num_vertices;
00967 VMOVE( &ip_bot->vertices[ip_bot->num_vertices * 3], work[1] );
00968 ip_bot->num_vertices++;
00969 first = 0;
00970 } else {
00971 ip_bot->faces[ip_bot->num_faces * 3] = v0;
00972 ip_bot->faces[ip_bot->num_faces * 3 + 1] = v2;
00973 }
00974 VMOVE( &ip_bot->vertices[ip_bot->num_vertices * 3], work[2] );
00975 ip_bot->faces[ip_bot->num_faces * 3 + 2] = ip_bot->num_vertices;
00976 v2 = ip_bot->num_vertices;
00977 ip_bot->num_vertices++;
00978
00979 ip_bot->num_faces++;
00980 }
00981
00982
00983 VMOVE( work[1], work[2] );
00984 }
00985 }
00986
00987 (void)rt_bot_vertex_fuse( ip_bot );
00988 (void)rt_bot_condense( ip_bot );
00989
00990 ip_bot->faces = (int *)bu_realloc( ip_bot->faces, ip_bot->num_faces * 3 * sizeof( int ), "BOT faces" );
00991
00992 rt_db_free_internal( ip, resp );
00993
00994 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00995 ip->idb_type = ID_BOT;
00996 ip->idb_meth = &rt_functab[ID_BOT];
00997 ip->idb_ptr = ip_bot;
00998
00999 return 0;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010