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
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 #ifndef lint
00158 static const char RCSepa[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_epa.c,v 14.12 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00159 #endif
00160
00161 #include "common.h"
00162
00163 #include <stddef.h>
00164 #include <stdio.h>
00165 #ifdef HAVE_STRING_H
00166 # include <string.h>
00167 #else
00168 # include <strings.h>
00169 #endif
00170 #include <math.h>
00171
00172 #include "machine.h"
00173 #include "vmath.h"
00174 #include "db.h"
00175 #include "nmg.h"
00176 #include "raytrace.h"
00177 #include "rtgeom.h"
00178 #include "./debug.h"
00179
00180 struct epa_specific {
00181 point_t epa_V;
00182 vect_t epa_Hunit;
00183 vect_t epa_Aunit;
00184 vect_t epa_Bunit;
00185 fastf_t epa_h;
00186 fastf_t epa_inv_r1sq;
00187 fastf_t epa_inv_r2sq;
00188 mat_t epa_SoR;
00189 mat_t epa_invRoS;
00190 };
00191
00192 const struct bu_structparse rt_epa_parse[] = {
00193 { "%f", 3, "V", bu_offsetof(struct rt_epa_internal, epa_V[X]), BU_STRUCTPARSE_FUNC_NULL },
00194 { "%f", 3, "H", bu_offsetof(struct rt_epa_internal, epa_H[X]), BU_STRUCTPARSE_FUNC_NULL },
00195 { "%f", 3, "A", bu_offsetof(struct rt_epa_internal, epa_Au[X]), BU_STRUCTPARSE_FUNC_NULL },
00196 { "%f", 1, "r_1", bu_offsetof(struct rt_epa_internal, epa_r1), BU_STRUCTPARSE_FUNC_NULL },
00197 { "%f", 1, "r_2", bu_offsetof(struct rt_epa_internal, epa_r2), BU_STRUCTPARSE_FUNC_NULL },
00198 { {'\0','\0','\0','\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL }
00199 };
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int
00217 rt_epa_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00218 {
00219 struct rt_epa_internal *xip;
00220 register struct epa_specific *epa;
00221 #ifndef NO_MAGIC_CHECKING
00222 const struct bn_tol *tol = &rtip->rti_tol;
00223 #endif
00224 LOCAL fastf_t magsq_h;
00225 LOCAL fastf_t mag_a, mag_h;
00226 LOCAL fastf_t f, r1, r2;
00227 LOCAL mat_t R;
00228 LOCAL mat_t Rinv;
00229 LOCAL mat_t S;
00230
00231 #ifndef NO_MAGIC_CHECKING
00232 RT_CK_DB_INTERNAL(ip);
00233 BN_CK_TOL(tol);
00234 #endif
00235 xip = (struct rt_epa_internal *)ip->idb_ptr;
00236 RT_EPA_CK_MAGIC(xip);
00237
00238
00239 mag_a = sqrt( MAGSQ( xip->epa_Au ) );
00240 mag_h = sqrt( magsq_h = MAGSQ( xip->epa_H ) );
00241 r1 = xip->epa_r1;
00242 r2 = xip->epa_r2;
00243
00244 if( NEAR_ZERO(mag_h, RT_LEN_TOL)
00245 || !NEAR_ZERO(mag_a - 1.0, RT_LEN_TOL)
00246 || r1 < 0.0 || r2 < 0.0 ) {
00247 return(1);
00248 }
00249
00250
00251 f = VDOT( xip->epa_Au, xip->epa_H ) / mag_h;
00252 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00253 return(1);
00254 }
00255
00256
00257
00258
00259 stp->st_id = ID_EPA;
00260 stp->st_meth = &rt_functab[ID_EPA];
00261
00262 BU_GETSTRUCT( epa, epa_specific );
00263 stp->st_specific = (genptr_t)epa;
00264
00265 epa->epa_h = mag_h;
00266 epa->epa_inv_r1sq = 1 / (r1 * r1);
00267 epa->epa_inv_r2sq = 1 / (r2 * r2);
00268
00269
00270 VMOVE( epa->epa_Hunit, xip->epa_H );
00271 VUNITIZE( epa->epa_Hunit );
00272 VMOVE( epa->epa_Aunit, xip->epa_Au );
00273 VCROSS( epa->epa_Bunit, epa->epa_Aunit, epa->epa_Hunit );
00274
00275 VMOVE( epa->epa_V, xip->epa_V );
00276
00277
00278 MAT_IDN( R );
00279 VREVERSE( &R[0], epa->epa_Bunit );
00280 VMOVE( &R[4], epa->epa_Aunit );
00281 VREVERSE( &R[8], epa->epa_Hunit );
00282 bn_mat_trn( Rinv, R );
00283
00284
00285 MAT_IDN( S );
00286 S[ 0] = 1.0/r2;
00287 S[ 5] = 1.0/r1;
00288 S[10] = 1.0/mag_h;
00289
00290
00291 bn_mat_mul( epa->epa_SoR, S, R );
00292 bn_mat_mul( epa->epa_invRoS, Rinv, S );
00293
00294
00295
00296 VJOIN1( stp->st_center, epa->epa_V, mag_h / 2.0, epa->epa_Hunit );
00297
00298 stp->st_bradius = sqrt(0.25*magsq_h + r2*r2 + r1*r1);
00299
00300 stp->st_aradius = stp->st_bradius;
00301
00302
00303 stp->st_min[X] = stp->st_center[X] - stp->st_bradius;
00304 stp->st_max[X] = stp->st_center[X] + stp->st_bradius;
00305 stp->st_min[Y] = stp->st_center[Y] - stp->st_bradius;
00306 stp->st_max[Y] = stp->st_center[Y] + stp->st_bradius;
00307 stp->st_min[Z] = stp->st_center[Z] - stp->st_bradius;
00308 stp->st_max[Z] = stp->st_center[Z] + stp->st_bradius;
00309
00310 return(0);
00311 }
00312
00313
00314
00315
00316 void
00317 rt_epa_print(register const struct soltab *stp)
00318 {
00319 register const struct epa_specific *epa =
00320 (struct epa_specific *)stp->st_specific;
00321
00322 VPRINT("V", epa->epa_V);
00323 VPRINT("Hunit", epa->epa_Hunit);
00324 VPRINT("Aunit", epa->epa_Aunit);
00325 VPRINT("Bunit", epa->epa_Bunit);
00326 bn_mat_print("S o R", epa->epa_SoR );
00327 bn_mat_print("invR o S", epa->epa_invRoS );
00328 }
00329
00330
00331 #define EPA_NORM_BODY (1)
00332 #define EPA_NORM_TOP (2)
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 int
00346 rt_epa_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00347 {
00348 register struct epa_specific *epa =
00349 (struct epa_specific *)stp->st_specific;
00350 LOCAL vect_t dprime;
00351 LOCAL vect_t pprime;
00352 LOCAL fastf_t k1, k2;
00353 LOCAL vect_t xlated;
00354 LOCAL struct hit hits[3];
00355 register struct hit *hitp;
00356
00357 hitp = &hits[0];
00358
00359
00360 MAT4X3VEC( dprime, epa->epa_SoR, rp->r_dir );
00361 VSUB2( xlated, rp->r_pt, epa->epa_V );
00362 MAT4X3VEC( pprime, epa->epa_SoR, xlated );
00363
00364
00365 {
00366 FAST fastf_t a, b, c;
00367 FAST fastf_t disc;
00368
00369 a = dprime[X] * dprime[X] + dprime[Y] * dprime[Y];
00370 b = 2*(dprime[X] * pprime[X] + dprime[Y] * pprime[Y])
00371 - dprime[Z];
00372 c = pprime[X] * pprime[X]
00373 + pprime[Y] * pprime[Y] - pprime[Z] - 1.0;
00374 if ( !NEAR_ZERO(a, RT_PCOEF_TOL) ) {
00375 disc = b*b - 4 * a * c;
00376 if (disc <= 0)
00377 goto check_plates;
00378 disc = sqrt(disc);
00379
00380 k1 = (-b + disc) / (2.0 * a);
00381 k2 = (-b - disc) / (2.0 * a);
00382
00383
00384
00385
00386
00387 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00388 if( hitp->hit_vpriv[Z] <= 0.0 ) {
00389 hitp->hit_magic = RT_HIT_MAGIC;
00390 hitp->hit_dist = k1;
00391 hitp->hit_surfno = EPA_NORM_BODY;
00392 hitp++;
00393 }
00394
00395 VJOIN1( hitp->hit_vpriv, pprime, k2, dprime );
00396 if( hitp->hit_vpriv[Z] <= 0.0 ) {
00397 hitp->hit_magic = RT_HIT_MAGIC;
00398 hitp->hit_dist = k2;
00399 hitp->hit_surfno = EPA_NORM_BODY;
00400 hitp++;
00401 }
00402 } else if ( !NEAR_ZERO(b, RT_PCOEF_TOL) ) {
00403 k1 = -c/b;
00404 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00405 if( hitp->hit_vpriv[Z] <= 0.0 ) {
00406 hitp->hit_magic = RT_HIT_MAGIC;
00407 hitp->hit_dist = k1;
00408 hitp->hit_surfno = EPA_NORM_BODY;
00409 hitp++;
00410 }
00411 }
00412 }
00413
00414
00415
00416
00417
00418 check_plates:
00419
00420 if( hitp == &hits[1] && !NEAR_ZERO(dprime[Z], SMALL) ) {
00421
00422 k1 = -pprime[Z] / dprime[Z];
00423
00424 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00425 if( hitp->hit_vpriv[X] * hitp->hit_vpriv[X] +
00426 hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y] <= 1.0 ) {
00427 hitp->hit_magic = RT_HIT_MAGIC;
00428 hitp->hit_dist = k1;
00429 hitp->hit_surfno = EPA_NORM_TOP;
00430 hitp++;
00431 }
00432 }
00433
00434 if( hitp != &hits[2] )
00435 return(0);
00436
00437 if( hits[0].hit_dist < hits[1].hit_dist ) {
00438
00439 register struct seg *segp;
00440
00441 RT_GET_SEG(segp, ap->a_resource);
00442 segp->seg_stp = stp;
00443 segp->seg_in = hits[0];
00444 segp->seg_out = hits[1];
00445 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00446 } else {
00447
00448 register struct seg *segp;
00449
00450 RT_GET_SEG(segp, ap->a_resource);
00451 segp->seg_stp = stp;
00452 segp->seg_in = hits[1];
00453 segp->seg_out = hits[0];
00454 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00455 }
00456 return(2);
00457 }
00458
00459 #define RT_EPA_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
00460
00461
00462
00463
00464
00465
00466 void
00467 rt_epa_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00468
00469
00470
00471
00472
00473 {
00474 rt_vstub( stp, rp, segp, n, ap );
00475 }
00476
00477
00478
00479
00480
00481
00482 void
00483 rt_epa_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00484 {
00485 fastf_t scale;
00486 vect_t can_normal;
00487 register struct epa_specific *epa =
00488 (struct epa_specific *)stp->st_specific;
00489
00490 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00491 switch( hitp->hit_surfno ) {
00492 case EPA_NORM_BODY:
00493 VSET( can_normal,
00494 hitp->hit_vpriv[X],
00495 hitp->hit_vpriv[Y],
00496 -0.5 );
00497 MAT4X3VEC( hitp->hit_normal, epa->epa_invRoS, can_normal );
00498 scale = 1.0 / MAGNITUDE( hitp->hit_normal );
00499 VSCALE( hitp->hit_normal, hitp->hit_normal, scale );
00500
00501
00502 hitp->hit_vpriv[X] = scale;
00503 break;
00504 case EPA_NORM_TOP:
00505 VREVERSE( hitp->hit_normal, epa->epa_Hunit );
00506 break;
00507 default:
00508 bu_log("rt_epa_norm: surfno=%d bad\n", hitp->hit_surfno);
00509 break;
00510 }
00511 }
00512
00513
00514
00515
00516
00517
00518 void
00519 rt_epa_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00520 {
00521 fastf_t a, b, c, scale;
00522 mat_t M1, M2;
00523 register struct epa_specific *epa =
00524 (struct epa_specific *)stp->st_specific;
00525 vect_t u, v;
00526 vect_t vec1, vec2;
00527 vect_t tmp;
00528
00529 switch( hitp->hit_surfno ) {
00530 case EPA_NORM_BODY:
00531
00532
00533
00534
00535 bn_vec_ortho( u, hitp->hit_normal );
00536 VCROSS( v, hitp->hit_normal, u );
00537
00538
00539 scale = - hitp->hit_vpriv[X];
00540
00541 MAT_IDN( M1 );
00542 M1[10] = 0;
00543
00544 bn_mat_mul( M2, epa->epa_invRoS, M1);
00545 bn_mat_mul( M1, M2, epa->epa_SoR );
00546
00547
00548 MAT4X3VEC( tmp, M1, u );
00549 a = VDOT(u, tmp) * scale;
00550 b = VDOT(v, tmp) * scale;
00551 MAT4X3VEC( tmp, M1, v );
00552 c = VDOT(v, tmp) * scale;
00553
00554 eigen2x2( &cvp->crv_c1, &cvp->crv_c2, vec1, vec2, a, b, c );
00555 VCOMB2( cvp->crv_pdir, vec1[X], u, vec1[Y], v );
00556 VUNITIZE( cvp->crv_pdir );
00557 break;
00558 case EPA_NORM_TOP:
00559 cvp->crv_c1 = cvp->crv_c2 = 0;
00560
00561 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00562 break;
00563 }
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 void
00575 rt_epa_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00576 {
00577 register struct epa_specific *epa =
00578 (struct epa_specific *)stp->st_specific;
00579 LOCAL vect_t work;
00580 LOCAL vect_t pprime;
00581 FAST fastf_t len;
00582
00583
00584
00585
00586
00587 VSUB2( work, hitp->hit_point, epa->epa_V );
00588 MAT4X3VEC( pprime, epa->epa_SoR, work );
00589
00590 switch( hitp->hit_surfno ) {
00591 case EPA_NORM_BODY:
00592
00593 if (pprime[Z] == -1.0) {
00594 uvp->uv_u = 0;
00595 } else {
00596 len = sqrt(pprime[X]*pprime[X] + pprime[Y]*pprime[Y]);
00597 uvp->uv_u = acos(pprime[X]/len) * bn_inv2pi;
00598 }
00599 uvp->uv_v = -pprime[Z];
00600 break;
00601 case EPA_NORM_TOP:
00602
00603 len = sqrt(pprime[X]*pprime[X] + pprime[Y]*pprime[Y]);
00604 uvp->uv_u = acos(pprime[X]/len) * bn_inv2pi;
00605 uvp->uv_v = 1.0 - len;
00606 break;
00607 }
00608
00609 if( pprime[Y] < 0 )
00610 uvp->uv_u = 1.0 - uvp->uv_u;
00611
00612
00613 uvp->uv_du = uvp->uv_dv = 0;
00614 }
00615
00616
00617
00618
00619 void
00620 rt_epa_free(register struct soltab *stp)
00621 {
00622 register struct epa_specific *epa =
00623 (struct epa_specific *)stp->st_specific;
00624
00625
00626 bu_free( (char *)epa, "epa_specific" );
00627 }
00628
00629
00630
00631
00632 int
00633 rt_epa_class(void)
00634 {
00635 return(0);
00636 }
00637
00638
00639
00640
00641 int
00642 rt_epa_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00643 {
00644 fastf_t dtol, f, mag_a, mag_h, ntol, r1, r2;
00645 fastf_t **ellipses, theta_new, theta_prev, rt_ell_ang(fastf_t *p1, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol);
00646 int *pts_dbl, i, j, nseg;
00647 int jj, na, nb, nell, recalc_b;
00648 LOCAL mat_t R;
00649 LOCAL mat_t invR;
00650 LOCAL struct rt_epa_internal *xip;
00651 point_t p1;
00652 struct rt_pt_node *pos_a, *pos_b, *pts_a, *pts_b, *rt_ptalloc(void);
00653 vect_t A, Au, B, Bu, Hu, V, Work;
00654
00655 #ifndef NO_MAGIC_CHECKING
00656 RT_CK_DB_INTERNAL(ip);
00657 #endif
00658
00659 xip = (struct rt_epa_internal *)ip->idb_ptr;
00660 RT_EPA_CK_MAGIC(xip);
00661
00662
00663
00664
00665
00666
00667 mag_a = MAGSQ( xip->epa_Au );
00668 mag_h = MAGNITUDE( xip->epa_H );
00669 r1 = xip->epa_r1;
00670 r2 = xip->epa_r2;
00671
00672 if( NEAR_ZERO(mag_h, RT_LEN_TOL)
00673 || !NEAR_ZERO(mag_a - 1.0, RT_LEN_TOL)
00674 || r1 <= 0.0 || r2 <= 0.0 ) {
00675 return(-2);
00676 }
00677
00678
00679 f = VDOT( xip->epa_Au, xip->epa_H ) / mag_h;
00680 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00681 return(-2);
00682 }
00683
00684
00685 VMOVE( Hu, xip->epa_H );
00686 VUNITIZE( Hu );
00687 VMOVE( Au, xip->epa_Au );
00688 VCROSS( Bu, Au, Hu );
00689
00690
00691 MAT_IDN( R );
00692 VREVERSE( &R[0], Bu );
00693 VMOVE( &R[4], Au );
00694 VREVERSE( &R[8], Hu );
00695 bn_mat_trn( invR, R );
00696
00697
00698
00699
00700 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 )
00701 dtol = 0.0;
00702 else
00703
00704 dtol = ttol->rel * 2 * r2;
00705 if( ttol->abs <= 0.0 ) {
00706 if( dtol <= 0.0 )
00707
00708 dtol = 2 * 0.10 * r2;
00709 else
00710
00711 ;
00712 } else {
00713
00714 if( ttol->rel <= 0.0 || dtol > ttol->abs )
00715 dtol = ttol->abs;
00716 }
00717
00718
00719 if( ttol->norm > 0.0 )
00720 ntol = ttol->norm;
00721 else
00722
00723 ntol = bn_pi;
00724
00725
00726
00727
00728
00729
00730 pts_b = rt_ptalloc();
00731 pts_b->next = rt_ptalloc();
00732 pts_b->next->next = NULL;
00733 VSET( pts_b->p, 0, 0, -mag_h);
00734 VSET( pts_b->next->p, 0, r2, 0);
00735
00736 nb = 2;
00737
00738 nb += rt_mk_parabola( pts_b, r2, mag_h, dtol, ntol );
00739 nell = nb - 1;
00740
00741
00742
00743
00744 pts_a = rt_ptalloc();
00745 VMOVE(pts_a->p, pts_b->p);
00746 pts_a->next = NULL;
00747 pos_b = pts_b->next;
00748 pos_a = pts_a;
00749 while (pos_b) {
00750
00751 pos_a->next = rt_ptalloc();
00752 pos_a = pos_a->next;
00753 pos_a->p[Z] = pos_b->p[Z];
00754
00755 pos_a->p[Y] = r1*sqrt( pos_a->p[Z] / mag_h + 1 );
00756 pos_a->p[X] = 0;
00757 pos_b = pos_b->next;
00758 }
00759 pos_a->next = NULL;
00760
00761
00762 recalc_b = 0;
00763 na = 0;
00764 pos_a = pts_a;
00765 while (pos_a->next) {
00766 na = rt_mk_parabola( pos_a, r1, mag_h, dtol, ntol );
00767 if (na != 0) {
00768 recalc_b = 1;
00769 nell += na;
00770 }
00771 pos_a = pos_a->next;
00772 }
00773
00774 if ( recalc_b ) {
00775
00776 pos_b = pts_b;
00777 while ( pos_b ) {
00778 struct rt_pt_node *next;
00779
00780
00781 next = pos_b->next;
00782 bu_free( (char *)pos_b, "rt_pt_node" );
00783 pos_b = next;
00784 }
00785
00786
00787
00788 pts_b = rt_ptalloc();
00789 pts_b->p[Z] = pts_a->p[Z];
00790 pts_b->next = NULL;
00791 pos_a = pts_a->next;
00792 pos_b = pts_b;
00793 while (pos_a) {
00794
00795 pos_b->next = rt_ptalloc();
00796 pos_b = pos_b->next;
00797 pos_b->p[Z] = pos_a->p[Z];
00798
00799 pos_b->p[Y] = r2*sqrt( pos_b->p[Z] / mag_h + 1 );
00800 pos_b->p[X] = 0;
00801 pos_a = pos_a->next;
00802 }
00803 pos_b->next = NULL;
00804 }
00805
00806
00807 ellipses = (fastf_t **)bu_malloc( nell * sizeof(fastf_t *), "fastf_t ell[]");
00808
00809 pts_dbl = (int *)bu_malloc( nell * sizeof(int), "dbl ints" );
00810
00811
00812 i = 0;
00813 nseg = 0;
00814 theta_prev = bn_twopi;
00815 pos_a = pts_a->next;
00816 pos_b = pts_b->next;
00817 while (pos_a) {
00818 VSCALE( A, Au, pos_a->p[Y] );
00819 VSCALE( B, Bu, pos_b->p[Y] );
00820 VJOIN1( V, xip->epa_V, -pos_a->p[Z], Hu );
00821
00822 VSET( p1, 0., pos_b->p[Y], 0. );
00823 theta_new = rt_ell_ang(p1, pos_a->p[Y], pos_b->p[Y], dtol, ntol);
00824 if (nseg == 0) {
00825 nseg = (int)(bn_twopi / theta_new) + 1;
00826 pts_dbl[i] = 0;
00827 } else if (theta_new < theta_prev) {
00828 nseg *= 2;
00829 pts_dbl[i] = 1;
00830 } else
00831 pts_dbl[i] = 0;
00832 theta_prev = theta_new;
00833
00834 ellipses[i] = (fastf_t *)bu_malloc(3*(nseg+1)*sizeof(fastf_t),
00835 "pts ell");
00836 rt_ell( ellipses[i], V, A, B, nseg );
00837
00838 i++;
00839 pos_a = pos_a->next;
00840 pos_b = pos_b->next;
00841 }
00842
00843 RT_ADD_VLIST( vhead,
00844 &ellipses[nell-1][(nseg-1)*ELEMENTS_PER_VECT],
00845 BN_VLIST_LINE_MOVE );
00846 for( i = 0; i < nseg; i++ ) {
00847 RT_ADD_VLIST( vhead,
00848 &ellipses[nell-1][i*ELEMENTS_PER_VECT],
00849 BN_VLIST_LINE_DRAW );
00850 }
00851
00852
00853 for (i = nell-2; i >= 0; i--) {
00854 int bottom, top;
00855
00856 top = i + 1;
00857 bottom = i;
00858 if (pts_dbl[top])
00859 nseg /= 2;
00860
00861
00862 RT_ADD_VLIST( vhead,
00863 &ellipses[bottom][(nseg-1)*ELEMENTS_PER_VECT],
00864 BN_VLIST_LINE_MOVE );
00865 for( j = 0; j < nseg; j++ ) {
00866 RT_ADD_VLIST( vhead,
00867 &ellipses[bottom][j*ELEMENTS_PER_VECT],
00868 BN_VLIST_LINE_DRAW );
00869 }
00870
00871
00872 for (j = 0; j < nseg; j++) {
00873 if (pts_dbl[top])
00874 jj = j + j;
00875 else
00876 jj = j;
00877 RT_ADD_VLIST( vhead,
00878 &ellipses[bottom][j*ELEMENTS_PER_VECT],
00879 BN_VLIST_LINE_MOVE );
00880 RT_ADD_VLIST( vhead,
00881 &ellipses[top][jj*ELEMENTS_PER_VECT],
00882 BN_VLIST_LINE_DRAW );
00883 }
00884 }
00885
00886 VADD2( Work, xip->epa_V, xip->epa_H );
00887 for (i = 0; i < nseg; i++) {
00888
00889 RT_ADD_VLIST( vhead, Work, BN_VLIST_LINE_MOVE );
00890 RT_ADD_VLIST( vhead,
00891 &ellipses[0][i*ELEMENTS_PER_VECT],
00892 BN_VLIST_LINE_DRAW );
00893 }
00894
00895
00896 for (i = 0; i < nell; i++) {
00897 bu_free( (char *)ellipses[i], "pts ell");
00898 }
00899 bu_free( (char *)ellipses, "fastf_t ell[]");
00900 bu_free( (char *)pts_dbl, "dbl ints" );
00901
00902 return(0);
00903 }
00904
00905 #define ELLOUT(n) ov+(n-1)*3
00906
00907 void
00908 rt_ell_norms(register fastf_t *ov, fastf_t *A, fastf_t *B, fastf_t *h_vec, fastf_t t, int sides)
00909 {
00910 fastf_t ang, theta, x, y, sqrt_1mt;
00911 int n;
00912 vect_t partial_t, partial_ang;
00913
00914 sqrt_1mt = sqrt( 1.0 - t );
00915 if( sqrt_1mt < SMALL_FASTF )
00916 rt_bomb( "rt_epa_tess: rt_ell_norms: sqrt( 1.0 -t ) is zero\n" );
00917 theta = 2 * bn_pi / sides;
00918 ang = 0.;
00919
00920 for (n = 1; n <= sides; n++, ang += theta) {
00921 x = cos( ang );
00922 y = sin( ang );
00923 VJOIN2( partial_t, h_vec, -x/(2.0*sqrt_1mt), A, -y/(2.0*sqrt_1mt), B );
00924 VBLEND2( partial_ang, x*sqrt_1mt, B, -y*sqrt_1mt, A );
00925 VCROSS( ELLOUT(n), partial_t, partial_ang );
00926 VUNITIZE( ELLOUT(n) );
00927 }
00928 VMOVE(ELLOUT(n), ELLOUT(1));
00929 }
00930
00931
00932
00933
00934
00935
00936
00937 void
00938 rt_ell(register fastf_t *ov, register const fastf_t *V, const fastf_t *A, const fastf_t *B, int sides)
00939 {
00940 fastf_t ang, theta, x, y;
00941 int n;
00942
00943 theta = 2 * bn_pi / sides;
00944 ang = 0.;
00945
00946 for (n = 1; n <= sides; n++, ang += theta) {
00947 x = cos( ang );
00948 y = sin( ang );
00949 VJOIN2( ELLOUT(n), V, x, A, y, B );
00950 }
00951 VMOVE(ELLOUT(n), ELLOUT(1));
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 fastf_t
00962 rt_ell_ang(fastf_t *p1, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
00963 {
00964 fastf_t dist, intr, m, theta0, theta1;
00965 point_t mpt, p0;
00966 vect_t norm_line, norm_ell;
00967
00968 VSET( p0, a, 0., 0. );
00969
00970 m = ( p1[Y] - p0[Y] ) / ( p1[X] - p0[X] );
00971 intr = p0[Y] - m * p0[X];
00972
00973 mpt[X] = a / sqrt( b*b / (m*m*a*a) + 1 );
00974 mpt[Y] = b * sqrt( 1 - mpt[X] * mpt[X] / (a*a) );
00975 mpt[Z] = 0;
00976
00977 dist = fabs( m * mpt[X] - mpt[Y] + intr ) / sqrt( m * m + 1 );
00978
00979 VSET( norm_line, m, -1., 0.);
00980 VSET( norm_ell, b * b * p0[X], a * a * p0[Y], 0. );
00981 VUNITIZE( norm_line );
00982 VUNITIZE( norm_ell );
00983 theta0 = fabs( acos( VDOT( norm_line, norm_ell )));
00984 VSET( norm_ell, b * b * p1[X], a * a * p1[Y], 0. );
00985 VUNITIZE( norm_ell );
00986 theta1 = fabs( acos( VDOT( norm_line, norm_ell )));
00987
00988 if ( dist > dtol || theta0 > ntol || theta1 > ntol ) {
00989
00990 return( rt_ell_ang( mpt, a, b, dtol, ntol ) );
00991 } else
00992 return( acos( VDOT(p0, p1)
00993 / ( MAGNITUDE(p0) * MAGNITUDE(p1) ) ));
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003 int
01004 rt_epa_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01005 {
01006 fastf_t dtol, f, mag_a, mag_h, ntol, r1, r2;
01007 fastf_t **ellipses, **normals, theta_new, theta_prev;
01008 int *pts_dbl, face, i, j, nseg;
01009 int *segs_per_ell;
01010 int jj, na, nb, nell, recalc_b;
01011 LOCAL mat_t R;
01012 LOCAL mat_t invR;
01013 LOCAL struct rt_epa_internal *xip;
01014 point_t p1;
01015 struct rt_pt_node *pos_a, *pos_b, *pts_a, *pts_b, *rt_ptalloc(void);
01016 struct shell *s;
01017 struct faceuse **outfaceuses = NULL;
01018 struct vertex *vertp[3];
01019 struct vertex ***vells = (struct vertex ***)NULL;
01020 vect_t A, Au, B, Bu, Hu, V;
01021 vect_t apex_norm,rev_norm;
01022 vect_t A_orig,B_orig;
01023 struct vertex *apex_v;
01024 struct vertexuse *vu;
01025 struct faceuse *fu;
01026
01027 RT_CK_DB_INTERNAL(ip);
01028 xip = (struct rt_epa_internal *)ip->idb_ptr;
01029 RT_EPA_CK_MAGIC(xip);
01030
01031
01032
01033
01034
01035
01036 mag_a = MAGSQ( xip->epa_Au );
01037 mag_h = MAGNITUDE( xip->epa_H );
01038 r1 = xip->epa_r1;
01039 r2 = xip->epa_r2;
01040
01041 if( NEAR_ZERO(mag_h, RT_LEN_TOL)
01042 || !NEAR_ZERO(mag_a - 1.0, RT_LEN_TOL)
01043 || r1 <= 0.0 || r2 <= 0.0 ) {
01044 return(-2);
01045 }
01046
01047
01048 f = VDOT( xip->epa_Au, xip->epa_H ) / mag_h;
01049 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
01050 return(-2);
01051 }
01052
01053
01054 VMOVE( Hu, xip->epa_H );
01055 VUNITIZE( Hu );
01056 VMOVE( Au, xip->epa_Au );
01057 VCROSS( Bu, Au, Hu );
01058
01059 VSCALE( A_orig , Au , xip->epa_r1 );
01060 VSCALE( B_orig , Bu , xip->epa_r2 );
01061
01062
01063 MAT_IDN( R );
01064 VREVERSE( &R[0], Bu );
01065 VMOVE( &R[4], Au );
01066 VREVERSE( &R[8], Hu );
01067 bn_mat_trn( invR, R );
01068
01069
01070
01071
01072 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 )
01073 dtol = 0.0;
01074 else
01075
01076 dtol = ttol->rel * 2 * r2;
01077 if( ttol->abs <= 0.0 ) {
01078 if( dtol <= 0.0 )
01079
01080 dtol = 2 * 0.10 * r2;
01081 else
01082
01083 ;
01084 } else {
01085
01086 if( ttol->rel <= 0.0 || dtol > ttol->abs )
01087 dtol = ttol->abs;
01088 }
01089
01090
01091 if( ttol->norm > 0.0 )
01092 ntol = ttol->norm;
01093 else
01094
01095 ntol = bn_pi;
01096
01097
01098
01099
01100
01101
01102 pts_b = rt_ptalloc();
01103 pts_b->next = rt_ptalloc();
01104 pts_b->next->next = NULL;
01105 VSET( pts_b->p, 0, 0, -mag_h);
01106 VSET( pts_b->next->p, 0, r2, 0);
01107
01108 nb = 2;
01109
01110 nb += rt_mk_parabola( pts_b, r2, mag_h, dtol, ntol );
01111 nell = nb - 1;
01112
01113
01114
01115
01116 pts_a = rt_ptalloc();
01117 VMOVE(pts_a->p, pts_b->p);
01118 pts_a->next = NULL;
01119 pos_b = pts_b->next;
01120 pos_a = pts_a;
01121 while (pos_b) {
01122
01123 pos_a->next = rt_ptalloc();
01124 pos_a = pos_a->next;
01125 pos_a->p[Z] = pos_b->p[Z];
01126
01127 pos_a->p[Y] = r1*sqrt( pos_a->p[Z] / mag_h + 1 );
01128 pos_a->p[X] = 0;
01129 pos_b = pos_b->next;
01130 }
01131 pos_a->next = NULL;
01132
01133
01134 recalc_b = 0;
01135 na = 0;
01136 pos_a = pts_a;
01137 while (pos_a->next) {
01138 na = rt_mk_parabola( pos_a, r1, mag_h, dtol, ntol );
01139 if (na != 0) {
01140 recalc_b = 1;
01141 nell += na;
01142 }
01143 pos_a = pos_a->next;
01144 }
01145
01146 if ( recalc_b ) {
01147
01148 pos_b = pts_b;
01149 while ( pos_b ) {
01150 struct rt_pt_node *tmp;
01151
01152 tmp = pos_b->next;
01153 bu_free( (char *)pos_b, "rt_pt_node" );
01154 pos_b = tmp;
01155 }
01156
01157
01158
01159 pts_b = rt_ptalloc();
01160 pts_b->p[Z] = pts_a->p[Z];
01161 pts_b->next = NULL;
01162 pos_a = pts_a->next;
01163 pos_b = pts_b;
01164 while (pos_a) {
01165
01166 pos_b->next = rt_ptalloc();
01167 pos_b = pos_b->next;
01168 pos_b->p[Z] = pos_a->p[Z];
01169
01170 pos_b->p[Y] = r2*sqrt( pos_b->p[Z] / mag_h + 1 );
01171 pos_b->p[X] = 0;
01172 pos_a = pos_a->next;
01173 }
01174 pos_b->next = NULL;
01175 }
01176
01177
01178 ellipses = (fastf_t **)bu_malloc( nell * sizeof(fastf_t *), "fastf_t ell[]");
01179
01180 pts_dbl = (int *)bu_malloc( nell * sizeof(int), "dbl ints" );
01181
01182
01183
01184 segs_per_ell = (int *)bu_calloc( nell , sizeof( int ) , "rt_epa_tess: segs_per_ell" );
01185
01186
01187 normals = (fastf_t **)bu_malloc( nell * sizeof(fastf_t *), "fastf_t normals[]");
01188
01189
01190 i = 0;
01191 nseg = 0;
01192 theta_prev = bn_twopi;
01193 pos_a = pts_a->next;
01194 pos_b = pts_b->next;
01195 while (pos_a) {
01196 fastf_t t;
01197
01198 t = (-pos_a->p[Z] / mag_h);
01199 VSCALE( A, Au, pos_a->p[Y] );
01200 VSCALE( B, Bu, pos_b->p[Y] );
01201 VJOIN1( V, xip->epa_V, -pos_a->p[Z], Hu );
01202
01203 VSET( p1, 0., pos_b->p[Y], 0. );
01204 theta_new = rt_ell_ang(p1, pos_a->p[Y], pos_b->p[Y], dtol, ntol);
01205 if (nseg == 0) {
01206 nseg = (int)(bn_twopi / theta_new) + 1;
01207 pts_dbl[i] = 0;
01208
01209 face = nseg*(1 + 3*((1 << (nell-1)) - 1));
01210
01211 outfaceuses = (struct faceuse **)
01212 bu_malloc( (face+1) * sizeof(struct faceuse *), "faceuse []" );
01213 } else if (theta_new < theta_prev) {
01214 nseg *= 2;
01215 pts_dbl[i] = 1;
01216 } else {
01217 pts_dbl[i] = 0;
01218 }
01219 theta_prev = theta_new;
01220
01221 ellipses[i] = (fastf_t *)bu_malloc(3*(nseg+1)*sizeof(fastf_t),
01222 "pts ell");
01223 segs_per_ell[i] = nseg;
01224 normals[i] = (fastf_t *)bu_malloc(3*(nseg+1)*sizeof(fastf_t), "rt_epa_tess_ normals" );
01225 rt_ell( ellipses[i], V, A, B, nseg );
01226 rt_ell_norms( normals[i], A_orig, B_orig, xip->epa_H, t, nseg );
01227
01228 i++;
01229 pos_a = pos_a->next;
01230 pos_b = pos_b->next;
01231 }
01232
01233
01234
01235
01236
01237 *r = nmg_mrsv( m );
01238 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
01239
01240
01241 vells = (struct vertex ***)
01242 bu_malloc(nell*sizeof(struct vertex **), "vertex [][]");
01243 j = nseg;
01244 for (i = nell-1; i >= 0; i--) {
01245 vells[i] = (struct vertex **)
01246 bu_malloc(j*sizeof(struct vertex *), "vertex []");
01247 if (i && pts_dbl[i])
01248 j /= 2;
01249 }
01250
01251
01252 for (i = 0; i < nseg; i++)
01253 vells[nell-1][i] = (struct vertex *)0;
01254 face = 0;
01255 if ( (outfaceuses[face++] = nmg_cface(s, vells[nell-1], nseg)) == 0) {
01256 bu_log("rt_epa_tess() failure, top face\n");
01257 goto fail;
01258 }
01259 for (i = 0; i < nseg; i++) {
01260 NMG_CK_VERTEX( vells[nell-1][i] );
01261 nmg_vertex_gv( vells[nell-1][i], &ellipses[nell-1][3*i] );
01262 }
01263
01264
01265 (void)nmg_mark_edges_real( &outfaceuses[0]->l.magic );
01266
01267
01268 for (i = nell-2; i >= 0; i--) {
01269 int bottom, top;
01270
01271 top = i + 1;
01272 bottom = i;
01273 if (pts_dbl[top])
01274 nseg /= 2;
01275 vertp[0] = (struct vertex *)0;
01276
01277
01278 for (j = 0; j < nseg; j++) {
01279 jj = j + j;
01280
01281 if (pts_dbl[top]) {
01282
01283 vertp[1] = vells[top][jj+1];
01284 vertp[2] = vells[top][jj];
01285 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01286 bu_log("rt_epa_tess() failure\n");
01287 goto fail;
01288 }
01289 if (j == 0)
01290 vells[bottom][j] = vertp[0];
01291
01292
01293 vertp[2] = vertp[1];
01294 if (j == nseg-1)
01295 vertp[1] = vells[bottom][0];
01296 else
01297 vertp[1] = (struct vertex *)0;
01298 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01299 bu_log("rt_epa_tess() failure\n");
01300 goto fail;
01301 }
01302 if (j != nseg-1)
01303 vells[bottom][j+1] = vertp[1];
01304
01305
01306 vertp[0] = vertp[1];
01307 if (j == nseg-1)
01308 vertp[1] = vells[top][0];
01309 else
01310 vertp[1] = vells[top][jj+2];
01311 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01312 bu_log("rt_epa_tess() failure\n");
01313 goto fail;
01314 }
01315 } else {
01316
01317 if (j == nseg-1)
01318 vertp[1] = vells[top][0];
01319 else
01320 vertp[1] = vells[top][j+1];
01321 vertp[2] = vells[top][j];
01322 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01323 bu_log("rt_epa_tess() failure\n");
01324 goto fail;
01325 }
01326 if (j == 0)
01327 vells[bottom][j] = vertp[0];
01328
01329
01330 vertp[2] = vertp[0];
01331 if (j == nseg-1)
01332 vertp[0] = vells[bottom][0];
01333 else
01334 vertp[0] = (struct vertex *)0;
01335 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01336 bu_log("rt_epa_tess() failure\n");
01337 goto fail;
01338 }
01339 if (j != nseg-1)
01340 vells[bottom][j+1] = vertp[0];
01341 }
01342 }
01343
01344
01345 for (j = 0; j < nseg; j++) {
01346 NMG_CK_VERTEX( vells[bottom][j] );
01347 nmg_vertex_gv( vells[bottom][j],
01348 &ellipses[bottom][3*j] );
01349 }
01350 }
01351
01352
01353 VADD2(V, xip->epa_V, xip->epa_H);
01354 vertp[0] = (struct vertex *)0;
01355 vertp[1] = vells[0][1];
01356 vertp[2] = vells[0][0];
01357 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01358 bu_log("rt_epa_tess() failure\n");
01359 goto fail;
01360 }
01361
01362 NMG_CK_VERTEX(vertp[0]);
01363 nmg_vertex_gv( vertp[0], (fastf_t *)V );
01364 apex_v = vertp[0];
01365
01366 for (i = 1; i < nseg; i++) {
01367 vertp[2] = vertp[1];
01368 if (i == nseg-1)
01369 vertp[1] = vells[0][0];
01370 else
01371 vertp[1] = vells[0][i+1];
01372 if ( (outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
01373 bu_log("rt_epa_tess() failure\n");
01374 goto fail;
01375 }
01376 }
01377
01378
01379 for (i=0 ; i < face ; i++) {
01380 if( nmg_fu_planeeqn( outfaceuses[i], tol ) < 0 )
01381 goto fail;
01382 }
01383
01384
01385 for( i=0 ; i<nell ; i++ )
01386 {
01387 for( j=0 ; j<segs_per_ell[i] ; j++ )
01388 {
01389 VREVERSE( rev_norm , &normals[i][j*3] );
01390 for( BU_LIST_FOR( vu , vertexuse , &vells[i][j]->vu_hd ) )
01391 {
01392
01393 fu = nmg_find_fu_of_vu( vu );
01394 NMG_CK_FACEUSE( fu );
01395
01396 if( fu == outfaceuses[0] || fu->fumate_p == outfaceuses[0] )
01397 continue;
01398
01399 if( fu->orientation == OT_SAME )
01400 nmg_vertexuse_nv( vu , &normals[i][j*3] );
01401 else if( fu->orientation == OT_OPPOSITE )
01402 nmg_vertexuse_nv( vu , rev_norm );
01403 }
01404 }
01405 }
01406
01407 VMOVE( apex_norm , xip->epa_H );
01408 VUNITIZE( apex_norm );
01409 VREVERSE( rev_norm , apex_norm );
01410 for( BU_LIST_FOR( vu , vertexuse , &apex_v->vu_hd ) )
01411 {
01412 NMG_CK_VERTEXUSE( vu );
01413 fu = nmg_find_fu_of_vu( vu );
01414 NMG_CK_FACEUSE( fu );
01415 if( fu->orientation == OT_SAME )
01416 nmg_vertexuse_nv( vu , apex_norm );
01417 else if( fu->orientation == OT_OPPOSITE )
01418 nmg_vertexuse_nv( vu , rev_norm );
01419 }
01420
01421
01422 nmg_gluefaces( outfaceuses, face, tol );
01423
01424
01425 nmg_region_a( *r, tol );
01426
01427
01428 nmg_shell_coplanar_face_merge( s, tol, 1 );
01429
01430
01431 bu_free( (char *)outfaceuses, "faceuse []");
01432 for (i = 0; i < nell; i++) {
01433 bu_free( (char *)ellipses[i], "pts ell");
01434 bu_free( (char *)vells[i], "vertex []");
01435 }
01436 bu_free( (char *)ellipses, "fastf_t ell[]");
01437 bu_free( (char *)pts_dbl, "dbl ints" );
01438 bu_free( (char *)vells, "vertex [][]");
01439
01440 return(0);
01441
01442 fail:
01443
01444 bu_free( (char *)outfaceuses, "faceuse []");
01445 for (i = 0; i < nell; i++) {
01446 bu_free( (char *)ellipses[i], "pts ell");
01447 bu_free( (char *)vells[i], "vertex []");
01448 }
01449 bu_free( (char *)ellipses, "fastf_t ell[]");
01450 bu_free( (char *)pts_dbl, "dbl ints" );
01451 bu_free( (char *)vells, "vertex [][]");
01452
01453 return(-1);
01454 }
01455
01456
01457
01458
01459
01460
01461
01462 int
01463 rt_epa_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01464 {
01465 LOCAL struct rt_epa_internal *xip;
01466 union record *rp;
01467
01468 BU_CK_EXTERNAL( ep );
01469 rp = (union record *)ep->ext_buf;
01470
01471 if( rp->u_id != ID_SOLID ) {
01472 bu_log("rt_epa_import: defective record\n");
01473 return(-1);
01474 }
01475
01476 RT_CK_DB_INTERNAL( ip );
01477 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01478 ip->idb_type = ID_EPA;
01479 ip->idb_meth = &rt_functab[ID_EPA];
01480 ip->idb_ptr = bu_malloc( sizeof(struct rt_epa_internal), "rt_epa_internal");
01481 xip = (struct rt_epa_internal *)ip->idb_ptr;
01482 xip->epa_magic = RT_EPA_INTERNAL_MAGIC;
01483
01484
01485 MAT4X3PNT( xip->epa_V, mat, &rp->s.s_values[0*3] );
01486 MAT4X3VEC( xip->epa_H, mat, &rp->s.s_values[1*3] );
01487 MAT4X3VEC( xip->epa_Au, mat, &rp->s.s_values[2*3] );
01488 VUNITIZE( xip->epa_Au );
01489 xip->epa_r1 = rp->s.s_values[3*3] / mat[15];
01490 xip->epa_r2 = rp->s.s_values[3*3+1] / mat[15];
01491
01492 if( xip->epa_r1 < SMALL_FASTF || xip->epa_r2 < SMALL_FASTF )
01493 {
01494 bu_log( "rt_epa_import: r1 or r2 are zero\n" );
01495 bu_free( (char *)ip->idb_ptr , "rt_epa_import: ip->idb_ptr" );
01496 return( -1 );
01497 }
01498
01499 return(0);
01500 }
01501
01502
01503
01504
01505
01506
01507 int
01508 rt_epa_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01509 {
01510 struct rt_epa_internal *xip;
01511 union record *epa;
01512 fastf_t mag_h;
01513
01514 RT_CK_DB_INTERNAL(ip);
01515 if( ip->idb_type != ID_EPA ) return(-1);
01516 xip = (struct rt_epa_internal *)ip->idb_ptr;
01517 RT_EPA_CK_MAGIC(xip);
01518
01519 BU_CK_EXTERNAL(ep);
01520 ep->ext_nbytes = sizeof(union record);
01521 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "epa external");
01522 epa = (union record *)ep->ext_buf;
01523
01524 epa->s.s_id = ID_SOLID;
01525 epa->s.s_type = EPA;
01526
01527 if (!NEAR_ZERO( MAGNITUDE(xip->epa_Au) - 1., RT_LEN_TOL)) {
01528 bu_log("rt_epa_export: Au not a unit vector!\n");
01529 return(-1);
01530 }
01531
01532 mag_h = MAGNITUDE(xip->epa_H);
01533
01534 if ( mag_h < RT_LEN_TOL
01535 || xip->epa_r1 < RT_LEN_TOL
01536 || xip->epa_r2 < RT_LEN_TOL) {
01537 bu_log("rt_epa_export: not all dimensions positive!\n");
01538 return(-1);
01539 }
01540
01541 if ( !NEAR_ZERO( VDOT(xip->epa_Au, xip->epa_H)/mag_h, RT_DOT_TOL) ) {
01542 bu_log("rt_epa_export: Au and H are not perpendicular!\n");
01543 return(-1);
01544 }
01545
01546 if (xip->epa_r2 > xip->epa_r1) {
01547 bu_log("rt_epa_export: semi-minor axis cannot be longer than semi-major axis!\n");
01548 return(-1);
01549 }
01550
01551
01552 VSCALE( &epa->s.s_values[0*3], xip->epa_V, local2mm );
01553 VSCALE( &epa->s.s_values[1*3], xip->epa_H, local2mm );
01554 VMOVE( &epa->s.s_values[2*3], xip->epa_Au );
01555 epa->s.s_values[3*3] = xip->epa_r1 * local2mm;
01556 epa->s.s_values[3*3+1] = xip->epa_r2 * local2mm;
01557
01558 return(0);
01559 }
01560
01561
01562
01563
01564
01565
01566
01567 int
01568 rt_epa_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01569 {
01570 LOCAL struct rt_epa_internal *xip;
01571 fastf_t vec[11];
01572
01573 BU_CK_EXTERNAL( ep );
01574
01575 BU_ASSERT_LONG( ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * 11 );
01576
01577 RT_CK_DB_INTERNAL( ip );
01578 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01579 ip->idb_type = ID_EPA;
01580 ip->idb_meth = &rt_functab[ID_EPA];
01581 ip->idb_ptr = bu_malloc( sizeof(struct rt_epa_internal), "rt_epa_internal");
01582
01583 xip = (struct rt_epa_internal *)ip->idb_ptr;
01584 xip->epa_magic = RT_EPA_INTERNAL_MAGIC;
01585
01586
01587 ntohd( (unsigned char *)vec, ep->ext_buf, 11 );
01588
01589
01590 MAT4X3PNT( xip->epa_V, mat, &vec[0*3] );
01591 MAT4X3VEC( xip->epa_H, mat, &vec[1*3] );
01592 MAT4X3VEC( xip->epa_Au, mat, &vec[2*3] );
01593 VUNITIZE( xip->epa_Au );
01594 xip->epa_r1 = vec[3*3] / mat[15];
01595 xip->epa_r2 = vec[3*3+1] / mat[15];
01596
01597 if( xip->epa_r1 < SMALL_FASTF || xip->epa_r2 < SMALL_FASTF )
01598 {
01599 bu_log( "rt_epa_import: r1 or r2 are zero\n" );
01600 bu_free( (char *)ip->idb_ptr , "rt_epa_import: ip->idb_ptr" );
01601 return( -1 );
01602 }
01603
01604 return(0);
01605 }
01606
01607
01608
01609
01610
01611
01612 int
01613 rt_epa_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01614 {
01615 struct rt_epa_internal *xip;
01616 fastf_t vec[11];
01617 fastf_t mag_h;
01618
01619 RT_CK_DB_INTERNAL(ip);
01620 if( ip->idb_type != ID_EPA ) return(-1);
01621 xip = (struct rt_epa_internal *)ip->idb_ptr;
01622 RT_EPA_CK_MAGIC(xip);
01623
01624 BU_CK_EXTERNAL(ep);
01625 ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * 11;
01626 ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "epa external");
01627
01628 if (!NEAR_ZERO( MAGNITUDE(xip->epa_Au) - 1., RT_LEN_TOL)) {
01629 bu_log("rt_epa_export: Au not a unit vector!\n");
01630 return(-1);
01631 }
01632
01633 mag_h = MAGNITUDE(xip->epa_H);
01634
01635 if ( mag_h < RT_LEN_TOL
01636 || xip->epa_r1 < RT_LEN_TOL
01637 || xip->epa_r2 < RT_LEN_TOL) {
01638 bu_log("rt_epa_export: not all dimensions positive!\n");
01639 return(-1);
01640 }
01641
01642 if ( !NEAR_ZERO( VDOT(xip->epa_Au, xip->epa_H)/mag_h, RT_DOT_TOL) ) {
01643 bu_log("rt_epa_export: Au and H are not perpendicular!\n");
01644 return(-1);
01645 }
01646
01647 if (xip->epa_r2 > xip->epa_r1) {
01648 bu_log("rt_epa_export: semi-minor axis cannot be longer than semi-major axis!\n");
01649 return(-1);
01650 }
01651
01652
01653 VSCALE( &vec[0*3], xip->epa_V, local2mm );
01654 VSCALE( &vec[1*3], xip->epa_H, local2mm );
01655 VMOVE( &vec[2*3], xip->epa_Au );
01656 vec[3*3] = xip->epa_r1 * local2mm;
01657 vec[3*3+1] = xip->epa_r2 * local2mm;
01658
01659
01660 htond( ep->ext_buf, (unsigned char *)vec, 11 );
01661
01662 return(0);
01663 }
01664
01665
01666
01667
01668
01669
01670
01671
01672 int
01673 rt_epa_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01674 {
01675 register struct rt_epa_internal *xip =
01676 (struct rt_epa_internal *)ip->idb_ptr;
01677 char buf[256];
01678
01679 RT_EPA_CK_MAGIC(xip);
01680 bu_vls_strcat( str, "Elliptical Paraboloid (EPA)\n");
01681
01682 sprintf(buf, "\tV (%g, %g, %g)\n",
01683 INTCLAMP(xip->epa_V[X] * mm2local),
01684 INTCLAMP(xip->epa_V[Y] * mm2local),
01685 INTCLAMP(xip->epa_V[Z] * mm2local) );
01686 bu_vls_strcat( str, buf );
01687
01688 sprintf(buf, "\tH (%g, %g, %g) mag=%g\n",
01689 INTCLAMP(xip->epa_H[X] * mm2local),
01690 INTCLAMP(xip->epa_H[Y] * mm2local),
01691 INTCLAMP(xip->epa_H[Z] * mm2local),
01692 INTCLAMP(MAGNITUDE(xip->epa_H) * mm2local) );
01693 bu_vls_strcat( str, buf );
01694
01695 sprintf(buf, "\tA=%g\n", INTCLAMP(xip->epa_r1 * mm2local));
01696 bu_vls_strcat( str, buf );
01697
01698 sprintf(buf, "\tB=%g\n", INTCLAMP(xip->epa_r2 * mm2local));
01699 bu_vls_strcat( str, buf );
01700
01701 return(0);
01702 }
01703
01704
01705
01706
01707
01708
01709 void
01710 rt_epa_ifree(struct rt_db_internal *ip)
01711 {
01712 register struct rt_epa_internal *xip;
01713
01714 RT_CK_DB_INTERNAL(ip);
01715 xip = (struct rt_epa_internal *)ip->idb_ptr;
01716 RT_EPA_CK_MAGIC(xip);
01717 xip->epa_magic = 0;
01718
01719 bu_free( (char *)xip, "epa ifree" );
01720 ip->idb_ptr = GENPTR_NULL;
01721 }
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732