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