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 #ifndef lint
00043 static const char RCStorus[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_torus.c,v 14.14 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00044 #endif
00045
00046 #include "common.h"
00047
00048 #include <stddef.h>
00049 #include <stdio.h>
00050 #ifdef HAVE_STRING_H
00051 # include <string.h>
00052 #else
00053 # include <strings.h>
00054 #endif
00055 #include <math.h>
00056
00057 #include "machine.h"
00058 #include "vmath.h"
00059 #include "db.h"
00060 #include "nmg.h"
00061 #include "raytrace.h"
00062 #include "rtgeom.h"
00063 #include "./debug.h"
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 const struct bu_structparse rt_tor_parse[] = {
00076 { "%f", 3, "V", bu_offsetof(struct rt_tor_internal, v[X]), BU_STRUCTPARSE_FUNC_NULL },
00077 { "%f", 3, "H", bu_offsetof(struct rt_tor_internal, h[X]), BU_STRUCTPARSE_FUNC_NULL },
00078 { "%f", 1, "r_a", bu_offsetof(struct rt_tor_internal, r_a), BU_STRUCTPARSE_FUNC_NULL },
00079 { "%f", 1, "r_h", bu_offsetof(struct rt_tor_internal, r_h), BU_STRUCTPARSE_FUNC_NULL },
00080 { {'\0','\0','\0','\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL }
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
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 struct tor_specific {
00171 fastf_t tor_alpha;
00172 fastf_t tor_r1;
00173 fastf_t tor_r2;
00174 vect_t tor_V;
00175 vect_t tor_N;
00176 mat_t tor_SoR;
00177 mat_t tor_invR;
00178 };
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 int
00196 rt_tor_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00197 {
00198 register struct tor_specific *tor;
00199 LOCAL mat_t R;
00200 LOCAL vect_t P, w1;
00201 FAST fastf_t f;
00202 struct rt_tor_internal *tip;
00203
00204 tip = (struct rt_tor_internal *)ip->idb_ptr;
00205 RT_TOR_CK_MAGIC(tip);
00206
00207
00208 if( rt_fdiff( tip->r_a, tip->r_b ) != 0 ) {
00209 bu_log("tor(%s): (|A|=%f) != (|B|=%f) \n",
00210 stp->st_name, tip->r_a, tip->r_b );
00211 return(1);
00212 }
00213
00214
00215 f = VDOT( tip->a, tip->b )/(tip->r_a*tip->r_b);
00216
00217 if( ! NEAR_ZERO(f, rtip->rti_tol.dist) ) {
00218 bu_log("tor(%s): A not perpendicular to B, f=%f\n",
00219 stp->st_name, f);
00220 return(1);
00221 }
00222 f = VDOT( tip->b, tip->h )/(tip->r_b);
00223 if( ! NEAR_ZERO(f, rtip->rti_tol.dist) ) {
00224 bu_log("tor(%s): B not perpendicular to H, f=%f\n",
00225 stp->st_name, f);
00226 return(1);
00227 }
00228 f = VDOT( tip->a, tip->h )/(tip->r_a);
00229 if( ! NEAR_ZERO(f, rtip->rti_tol.dist) ) {
00230 bu_log("tor(%s): A not perpendicular to H, f=%f\n",
00231 stp->st_name, f);
00232 return(1);
00233 }
00234
00235
00236 if( 0.0 >= tip->r_h || tip->r_h > tip->r_a ) {
00237 bu_log("r1 = %f, r2 = %f\n", tip->r_a, tip->r_h );
00238 bu_log("tor(%s): 0 < r2 <= r1 is not true\n", stp->st_name);
00239 return(1);
00240 }
00241
00242
00243 BU_GETSTRUCT( tor, tor_specific );
00244 stp->st_specific = (genptr_t)tor;
00245
00246 tor->tor_r1 = tip->r_a;
00247 tor->tor_r2 = tip->r_h;
00248
00249 VMOVE( tor->tor_V, tip->v );
00250 tor->tor_alpha = tip->r_h/tor->tor_r1;
00251
00252
00253 VMOVE( tor->tor_N, tip->h );
00254
00255 MAT_IDN( R );
00256 VSCALE( &R[0], tip->a, 1.0/tip->r_a );
00257 VSCALE( &R[4], tip->b, 1.0/tip->r_b );
00258 VMOVE( &R[8], tor->tor_N );
00259 bn_mat_inv( tor->tor_invR, R );
00260
00261
00262 MAT_COPY( tor->tor_SoR, R );
00263 tor->tor_SoR[15] *= tor->tor_r1;
00264
00265 VMOVE( stp->st_center, tor->tor_V );
00266 stp->st_aradius = stp->st_bradius = tor->tor_r1 + tip->r_h;
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 VSET( P, 1.0, 0, 0 );
00278 VCROSS( w1, tor->tor_N, P );
00279 f = tor->tor_r2 + tor->tor_r1 * MAGNITUDE(w1);
00280 VSCALE( w1, P, f );
00281 f = fabs( w1[X] );
00282 stp->st_min[X] = tor->tor_V[X] - f;
00283 stp->st_max[X] = tor->tor_V[X] + f;
00284
00285
00286 VSET( P, 0, 1.0, 0 );
00287 VCROSS( w1, tor->tor_N, P );
00288 f = tor->tor_r2 + tor->tor_r1 * MAGNITUDE(w1);
00289 VSCALE( w1, P, f );
00290 f = fabs( w1[Y] );
00291 stp->st_min[Y] = tor->tor_V[Y] - f;
00292 stp->st_max[Y] = tor->tor_V[Y] + f;
00293
00294
00295 VSET( P, 0, 0, 1.0 );
00296 VCROSS( w1, tor->tor_N, P );
00297 f = tor->tor_r2 + tor->tor_r1 * MAGNITUDE(w1);
00298 VSCALE( w1, P, f );
00299 f = fabs( w1[Z] );
00300 stp->st_min[Z] = tor->tor_V[Z] - f;
00301 stp->st_max[Z] = tor->tor_V[Z] + f;
00302
00303 return(0);
00304 }
00305
00306
00307
00308
00309 void
00310 rt_tor_print(register const struct soltab *stp)
00311 {
00312 register const struct tor_specific *tor =
00313 (struct tor_specific *)stp->st_specific;
00314
00315 bu_log("r2/r1 (alpha) = %f\n", tor->tor_alpha);
00316 bu_log("r1 = %f\n", tor->tor_r1);
00317 bu_log("r2 = %f\n", tor->tor_r2);
00318 VPRINT("V", tor->tor_V);
00319 VPRINT("N", tor->tor_N);
00320 bn_mat_print("S o R", tor->tor_SoR );
00321 bn_mat_print("invR", tor->tor_invR );
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 int
00357 rt_tor_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00358 {
00359 register struct tor_specific *tor =
00360 (struct tor_specific *)stp->st_specific;
00361 register struct seg *segp;
00362 LOCAL vect_t dprime;
00363 LOCAL vect_t pprime;
00364 LOCAL vect_t work;
00365 LOCAL bn_poly_t C;
00366 LOCAL bn_complex_t val[4];
00367 LOCAL double k[4];
00368 register int i;
00369 LOCAL int j;
00370 LOCAL bn_poly_t A, Asqr;
00371 LOCAL bn_poly_t X2_Y2;
00372 LOCAL vect_t cor_pprime;
00373 LOCAL fastf_t cor_proj;
00374
00375
00376 MAT4X3VEC( dprime, tor->tor_SoR, rp->r_dir );
00377 VUNITIZE( dprime );
00378
00379 VSUB2( work, rp->r_pt, tor->tor_V );
00380 MAT4X3VEC( pprime, tor->tor_SoR, work );
00381
00382
00383
00384
00385
00386
00387
00388
00389 cor_proj = VDOT( pprime, dprime );
00390 VSCALE( cor_pprime, dprime, cor_proj );
00391 VSUB2( cor_pprime, pprime, cor_pprime );
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 X2_Y2.dgr = 2;
00410 X2_Y2.cf[0] = dprime[X] * dprime[X] + dprime[Y] * dprime[Y];
00411 X2_Y2.cf[1] = 2.0 * (dprime[X] * cor_pprime[X] +
00412 dprime[Y] * cor_pprime[Y]);
00413 X2_Y2.cf[2] = cor_pprime[X] * cor_pprime[X] +
00414 cor_pprime[Y] * cor_pprime[Y];
00415
00416
00417 A.dgr = 2;
00418 A.cf[0] = X2_Y2.cf[0] + dprime[Z] * dprime[Z];
00419 A.cf[1] = X2_Y2.cf[1] + 2.0 * dprime[Z] * cor_pprime[Z];
00420 A.cf[2] = X2_Y2.cf[2] + cor_pprime[Z] * cor_pprime[Z] +
00421 1.0 - tor->tor_alpha * tor->tor_alpha;
00422
00423
00424
00425 Asqr.dgr = 4;
00426 Asqr.cf[0] = A.cf[0] * A.cf[0];
00427 Asqr.cf[1] = A.cf[0] * A.cf[1] + A.cf[1] * A.cf[0];
00428 Asqr.cf[2] = A.cf[0] * A.cf[2] + A.cf[1] * A.cf[1] + A.cf[2] * A.cf[0];
00429 Asqr.cf[3] = A.cf[1] * A.cf[2] + A.cf[2] * A.cf[1];
00430 Asqr.cf[4] = A.cf[2] * A.cf[2];
00431
00432
00433
00434
00435 C.dgr = 4;
00436 C.cf[0] = Asqr.cf[0];
00437 C.cf[1] = Asqr.cf[1];
00438 C.cf[2] = Asqr.cf[2] - X2_Y2.cf[0] * 4.0;
00439 C.cf[3] = Asqr.cf[3] - X2_Y2.cf[1] * 4.0;
00440 C.cf[4] = Asqr.cf[4] - X2_Y2.cf[2] * 4.0;
00441
00442
00443
00444
00445 if ( (i = rt_poly_roots( &C, val, stp->st_dp->d_namep )) != 4 ){
00446 if( i > 0 ) {
00447 bu_log("tor: rt_poly_roots() 4!=%d\n", i);
00448 bn_pr_roots( stp->st_name, val, i );
00449 } else if (i < 0) {
00450 static int reported=0;
00451 bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
00452 if (!reported) {
00453 VPRINT("while shooting from:\t", rp->r_pt);
00454 VPRINT("while shooting at:\t", rp->r_dir);
00455 bu_log("Additional torus convergence failure details will be suppressed.\n");
00456 reported=1;
00457 }
00458 }
00459 return(0);
00460 }
00461
00462
00463
00464
00465
00466
00467
00468 for ( j=0, i=0; j < 4; j++ ){
00469 if( NEAR_ZERO( val[j].im, ap->a_rt_i->rti_tol.dist ) )
00470 k[i++] = val[j].re;
00471 }
00472
00473
00474 for( j = 0; j < i; ++j )
00475 k[j] -= cor_proj;
00476
00477
00478 switch( i ) {
00479 case 0:
00480 return(0);
00481
00482 default:
00483 bu_log("rt_tor_shot: reduced 4 to %d roots\n",i);
00484 bn_pr_roots( stp->st_name, val, 4 );
00485 return(0);
00486
00487 case 2:
00488 {
00489
00490 FAST fastf_t u;
00491 if( (u=k[0]) < k[1] ) {
00492
00493 k[0] = k[1];
00494 k[1] = u;
00495 }
00496 }
00497 break;
00498 case 4:
00499 {
00500 register short n;
00501 register short lim;
00502
00503
00504 for( lim = i-1; lim > 0; lim-- ) {
00505 for( n = 0; n < lim; n++ ) {
00506 FAST fastf_t u;
00507 if( (u=k[n]) < k[n+1] ) {
00508
00509 k[n] = k[n+1];
00510 k[n+1] = u;
00511 }
00512 }
00513 }
00514 }
00515 break;
00516 }
00517
00518
00519
00520 RT_GET_SEG(segp, ap->a_resource);
00521 segp->seg_stp = stp;
00522 segp->seg_in.hit_dist = k[1]*tor->tor_r1;
00523 segp->seg_out.hit_dist = k[0]*tor->tor_r1;
00524 segp->seg_in.hit_surfno = segp->seg_out.hit_surfno = 0;
00525
00526 VJOIN1( segp->seg_in.hit_vpriv, pprime, k[1], dprime );
00527 VJOIN1( segp->seg_out.hit_vpriv, pprime, k[0], dprime );
00528 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00529
00530 if( i == 2 )
00531 return(2);
00532
00533
00534
00535 RT_GET_SEG(segp, ap->a_resource);
00536 segp->seg_stp = stp;
00537 segp->seg_in.hit_dist = k[3]*tor->tor_r1;
00538 segp->seg_out.hit_dist = k[2]*tor->tor_r1;
00539 segp->seg_in.hit_surfno = segp->seg_out.hit_surfno = 1;
00540 VJOIN1( segp->seg_in.hit_vpriv, pprime, k[3], dprime );
00541 VJOIN1( segp->seg_out.hit_vpriv, pprime, k[2], dprime );
00542 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00543 return(4);
00544 }
00545
00546 #define SEG_MISS(SEG) (SEG).seg_stp=(struct soltab *) 0;
00547
00548
00549
00550
00551
00552 void
00553 rt_tor_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00554
00555
00556
00557
00558
00559 {
00560 register int i;
00561 register struct tor_specific *tor;
00562 LOCAL vect_t dprime;
00563 LOCAL vect_t pprime;
00564 LOCAL vect_t work;
00565 LOCAL bn_poly_t *C;
00566 LOCAL bn_complex_t (*val)[4];
00567 LOCAL int num_roots;
00568 LOCAL int num_zero;
00569 LOCAL bn_poly_t A, Asqr;
00570 LOCAL bn_poly_t X2_Y2;
00571 LOCAL vect_t cor_pprime;
00572 LOCAL fastf_t *cor_proj;
00573
00574
00575 C = (bn_poly_t *)bu_malloc(n * sizeof(bn_poly_t), "tor bn_poly_t");
00576 val = (bn_complex_t (*)[4])bu_malloc(n * sizeof(bn_complex_t) * 4,
00577 "tor bn_complex_t");
00578 cor_proj = (fastf_t *)bu_malloc(n * sizeof(fastf_t), "tor proj");
00579
00580
00581 # include "noalias.h"
00582 for(i = 0; i < n; i++) segp[i].seg_stp = stp[i];
00583
00584
00585 # include "noalias.h"
00586 for(i = 0; i < n; i++){
00587 if( segp[i].seg_stp == 0) continue;
00588 tor = (struct tor_specific *)stp[i]->st_specific;
00589
00590
00591 MAT4X3VEC( dprime, tor->tor_SoR, rp[i]->r_dir );
00592 VUNITIZE( dprime );
00593
00594
00595 VMOVE( segp[i].seg_in.hit_normal, dprime );
00596
00597 VSUB2( work, rp[i]->r_pt, tor->tor_V );
00598 MAT4X3VEC( pprime, tor->tor_SoR, work );
00599
00600
00601 VMOVE( segp[i].seg_out.hit_normal, pprime );
00602
00603
00604
00605
00606
00607
00608
00609
00610 cor_proj[i] = VDOT( pprime, dprime );
00611 VSCALE( cor_pprime, dprime, cor_proj[i] );
00612 VSUB2( cor_pprime, pprime, cor_pprime );
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 X2_Y2.dgr = 2;
00631 X2_Y2.cf[0] = dprime[X] * dprime[X] + dprime[Y] * dprime[Y];
00632 X2_Y2.cf[1] = 2.0 * (dprime[X] * cor_pprime[X] +
00633 dprime[Y] * cor_pprime[Y]);
00634 X2_Y2.cf[2] = cor_pprime[X] * cor_pprime[X] +
00635 cor_pprime[Y] * cor_pprime[Y];
00636
00637
00638 A.dgr = 2;
00639 A.cf[0] = X2_Y2.cf[0] + dprime[Z] * dprime[Z];
00640 A.cf[1] = X2_Y2.cf[1] + 2.0 * dprime[Z] * cor_pprime[Z];
00641 A.cf[2] = X2_Y2.cf[2] + cor_pprime[Z] * cor_pprime[Z] +
00642 1.0 - tor->tor_alpha * tor->tor_alpha;
00643
00644
00645
00646 Asqr.dgr = 4;
00647 Asqr.cf[0] = A.cf[0] * A.cf[0];
00648 Asqr.cf[1] = A.cf[0] * A.cf[1] +
00649 A.cf[1] * A.cf[0];
00650 Asqr.cf[2] = A.cf[0] * A.cf[2] +
00651 A.cf[1] * A.cf[1] +
00652 A.cf[2] * A.cf[0];
00653 Asqr.cf[3] = A.cf[1] * A.cf[2] +
00654 A.cf[2] * A.cf[1];
00655 Asqr.cf[4] = A.cf[2] * A.cf[2];
00656
00657
00658 X2_Y2.cf[0] *= 4.0;
00659 X2_Y2.cf[1] *= 4.0;
00660 X2_Y2.cf[2] *= 4.0;
00661
00662
00663
00664 C[i].dgr = 4;
00665 C[i].cf[0] = Asqr.cf[0];
00666 C[i].cf[1] = Asqr.cf[1];
00667 C[i].cf[2] = Asqr.cf[2] - X2_Y2.cf[0];
00668 C[i].cf[3] = Asqr.cf[3] - X2_Y2.cf[1];
00669 C[i].cf[4] = Asqr.cf[4] - X2_Y2.cf[2];
00670 }
00671
00672
00673 for(i = 0; i < n; i++){
00674 if( segp[i].seg_stp == 0) continue;
00675
00676
00677
00678
00679 if ( (num_roots = rt_poly_roots( &(C[i]), &(val[i][0]), (*stp)->st_dp->d_namep )) != 4 ){
00680 if( num_roots > 0 ) {
00681 bu_log("tor: rt_poly_roots() 4!=%d\n", num_roots);
00682 bn_pr_roots( "tor", val[i], num_roots );
00683 } else if (num_roots < 0) {
00684 static int reported=0;
00685 bu_log("The root solver failed to converge on a solution for %s\n", stp[i]->st_dp->d_namep);
00686 if (!reported) {
00687 VPRINT("while shooting from:\t", rp[i]->r_pt);
00688 VPRINT("while shooting at:\t", rp[i]->r_dir);
00689 bu_log("Additional torus convergence failure details will be suppressed.\n");
00690 reported=1;
00691 }
00692 }
00693 SEG_MISS(segp[i]);
00694 }
00695 }
00696
00697
00698 # include "noalias.h"
00699 for(i = 0; i < n; i++){
00700 if( segp[i].seg_stp == 0) continue;
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 num_zero = 0;
00711 if( NEAR_ZERO( val[i][0].im, ap->a_rt_i->rti_tol.dist ) )
00712 C[i].cf[num_zero++] = val[i][0].re - cor_proj[i];
00713 if( NEAR_ZERO( val[i][1].im, ap->a_rt_i->rti_tol.dist ) ) {
00714 C[i].cf[num_zero++] = val[i][1].re - cor_proj[i];
00715 }
00716 if( NEAR_ZERO( val[i][2].im, ap->a_rt_i->rti_tol.dist ) ) {
00717 C[i].cf[num_zero++] = val[i][2].re - cor_proj[i];
00718 }
00719 if( NEAR_ZERO( val[i][3].im, ap->a_rt_i->rti_tol.dist ) ) {
00720 C[i].cf[num_zero++] = val[i][3].re - cor_proj[i];
00721 }
00722 C[i].dgr = num_zero;
00723
00724
00725 if( num_zero == 0 ) {
00726 SEG_MISS(segp[i]);
00727 }
00728 else if( num_zero != 2 && num_zero != 4 ) {
00729 #if 0
00730 bu_log("rt_tor_shot: reduced 4 to %d roots\n",i);
00731 bn_pr_roots( stp->st_name, val, 4 );
00732 #endif
00733 SEG_MISS(segp[i]);
00734 }
00735 }
00736
00737
00738 # include "noalias.h"
00739 for(i = 0; i < n; i++){
00740 if( segp[i].seg_stp == 0) continue;
00741 if( C[i].dgr != 2 ) continue;
00742
00743 tor = (struct tor_specific *)stp[i]->st_specific;
00744
00745
00746
00747 if (C[i].cf[1] < C[i].cf[0]) {
00748
00749 segp[i].seg_in.hit_dist = C[i].cf[1]*tor->tor_r1;
00750 segp[i].seg_out.hit_dist = C[i].cf[0]*tor->tor_r1;
00751
00752 VJOIN1( segp[i].seg_in.hit_vpriv,
00753 segp[i].seg_out.hit_normal,
00754 C[i].cf[1], segp[i].seg_in.hit_normal );
00755 VJOIN1( segp[i].seg_out.hit_vpriv,
00756 segp[i].seg_out.hit_normal,
00757 C[i].cf[0], segp[i].seg_in.hit_normal );
00758 } else {
00759
00760 segp[i].seg_in.hit_dist = C[i].cf[0]*tor->tor_r1;
00761 segp[i].seg_out.hit_dist = C[i].cf[1]*tor->tor_r1;
00762
00763 VJOIN1( segp[i].seg_in.hit_vpriv,
00764 segp[i].seg_out.hit_normal,
00765 C[i].cf[0], segp[i].seg_in.hit_normal );
00766 VJOIN1( segp[i].seg_out.hit_vpriv,
00767 segp[i].seg_out.hit_normal,
00768 C[i].cf[1], segp[i].seg_in.hit_normal );
00769 }
00770 }
00771
00772
00773 for(i = 0; i < n; i++){
00774
00775 if( segp[i].seg_stp == 0) continue;
00776 if( C[i].dgr != 4 ) continue;
00777
00778 tor = (struct tor_specific *)stp[i]->st_specific;
00779
00780
00781 rt_pt_sort( C[i].cf, 4 );
00782
00783
00784
00785 VMOVE( dprime, segp[i].seg_in.hit_normal );
00786
00787 VMOVE( pprime, segp[i].seg_out.hit_normal );
00788
00789
00790 segp[i].seg_in.hit_dist = C[i].cf[1]*tor->tor_r1;
00791 segp[i].seg_out.hit_dist = C[i].cf[0]*tor->tor_r1;
00792
00793 VJOIN1(segp[i].seg_in.hit_vpriv, pprime, C[i].cf[1], dprime );
00794 VJOIN1(segp[i].seg_out.hit_vpriv, pprime, C[i].cf[0], dprime);
00795
00796 #if 0
00797
00798
00799
00800 GET_SEG(seg2p, resp);
00801 segp[i].seg_next = seg2p;
00802 seg2p->seg_stp = stp[i];
00803 seg2p->seg_in.hit_dist = C[i].cf[3]*tor->tor_r1;
00804 seg2p->seg_out.hit_dist = C[i].cf[2]*tor->tor_r1;
00805 VJOIN1( seg2p->seg_in.hit_vpriv, pprime, C[i].cf[3], dprime );
00806 VJOIN1(seg2p->seg_out.hit_vpriv, pprime, C[i].cf[2], dprime );
00807 #endif
00808 }
00809
00810
00811 bu_free( (char *)C, "tor C");
00812 bu_free( (char *)val, "tor val");
00813 bu_free( (char *)cor_proj, "tor cor_proj");
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 void
00844 rt_tor_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00845 {
00846 register struct tor_specific *tor =
00847 (struct tor_specific *)stp->st_specific;
00848 FAST fastf_t w;
00849 LOCAL vect_t work;
00850
00851 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00852 w = hitp->hit_vpriv[X]*hitp->hit_vpriv[X] +
00853 hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y] +
00854 hitp->hit_vpriv[Z]*hitp->hit_vpriv[Z] +
00855 1.0 - tor->tor_alpha*tor->tor_alpha;
00856 VSET( work,
00857 ( w - 2.0 ) * hitp->hit_vpriv[X],
00858 ( w - 2.0 ) * hitp->hit_vpriv[Y],
00859 w * hitp->hit_vpriv[Z] );
00860 VUNITIZE( work );
00861
00862 MAT3X3VEC( hitp->hit_normal, tor->tor_invR, work );
00863 }
00864
00865
00866
00867
00868
00869
00870 void
00871 rt_tor_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00872 {
00873 register struct tor_specific *tor =
00874 (struct tor_specific *)stp->st_specific;
00875 vect_t w4, w5;
00876 fastf_t nx, ny, nz, x1, y1, z1;
00877 fastf_t d;
00878
00879 nx = tor->tor_N[X];
00880 ny = tor->tor_N[Y];
00881 nz = tor->tor_N[Z];
00882
00883
00884 VSUB2( w4, hitp->hit_point, tor->tor_V );
00885
00886 if( !NEAR_ZERO(nz, 0.00001) ) {
00887 z1 = w4[Z]*nx*nx + w4[Z]*ny*ny - w4[X]*nx*nz - w4[Y]*ny*nz;
00888 x1 = (nx*(z1-w4[Z])/nz) + w4[X];
00889 y1 = (ny*(z1-w4[Z])/nz) + w4[Y];
00890 } else if( !NEAR_ZERO(ny, 0.00001) ) {
00891 y1 = w4[Y]*nx*nx + w4[Y]*nz*nz - w4[X]*nx*ny - w4[Z]*ny*nz;
00892 x1 = (nx*(y1-w4[Y])/ny) + w4[X];
00893 z1 = (nz*(y1-w4[Y])/ny) + w4[Z];
00894 } else {
00895 x1 = w4[X]*ny*ny + w4[X]*nz*nz - w4[Y]*nx*ny - w4[Z]*nz*nx;
00896 y1 = (ny*(x1-w4[X])/nx) + w4[Y];
00897 z1 = (nz*(x1-w4[X])/nx) + w4[Z];
00898 }
00899 d = sqrt(x1*x1 + y1*y1 + z1*z1);
00900
00901 cvp->crv_c1 = (tor->tor_r1 - d) / (d * tor->tor_r2);
00902 cvp->crv_c2 = -1.0 / tor->tor_r2;
00903
00904 w4[X] = x1 / d;
00905 w4[Y] = y1 / d;
00906 w4[Z] = z1 / d;
00907 VCROSS( w5, tor->tor_N, w4 );
00908 VCROSS( cvp->crv_pdir, w5, hitp->hit_normal );
00909 VUNITIZE( cvp->crv_pdir );
00910 }
00911
00912
00913
00914
00915 void
00916 rt_tor_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00917 {
00918 register struct tor_specific *tor =
00919 (struct tor_specific *) stp -> st_specific;
00920 LOCAL vect_t work;
00921 LOCAL vect_t pprime;
00922 LOCAL vect_t pprime2;
00923 LOCAL fastf_t costheta;
00924
00925 VSUB2(work, hitp -> hit_point, tor -> tor_V);
00926 MAT4X3VEC(pprime, tor -> tor_SoR, work);
00927
00928
00929
00930 uvp -> uv_u = atan2(pprime[Y], pprime[X]) * bn_inv2pi + 0.5;
00931
00932 VSET(work, pprime[X], pprime[Y], 0.0);
00933 VUNITIZE(work);
00934 VSUB2(pprime2, pprime, work);
00935 VUNITIZE(pprime2);
00936 costheta = VDOT(pprime2, work);
00937 uvp -> uv_v = atan2(pprime2[Z], costheta) * bn_inv2pi + 0.5;
00938 }
00939
00940
00941
00942
00943 void
00944 rt_tor_free(struct soltab *stp)
00945 {
00946 register struct tor_specific *tor =
00947 (struct tor_specific *)stp->st_specific;
00948
00949 bu_free( (char *)tor, "tor_specific");
00950 }
00951
00952 int
00953 rt_tor_class(void)
00954 {
00955 return(0);
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 int
00982 rt_num_circular_segments(double maxerr, double radius)
00983 {
00984 register fastf_t cos_half_theta;
00985 register fastf_t half_theta;
00986 int n;
00987
00988 if( radius <= 0.0 || maxerr <= 0.0 || maxerr >= radius ) {
00989
00990 return(6);
00991 }
00992 cos_half_theta = 1.0 - maxerr / radius;
00993
00994
00995
00996 if( cos_half_theta <= 0.0 || cos_half_theta >= 1.0 ) {
00997
00998 return(6);
00999 }
01000 half_theta = acos( cos_half_theta );
01001 if( half_theta < SMALL ) {
01002
01003
01004
01005 return( 360*10 );
01006 }
01007 n = bn_pi / half_theta + 0.99;
01008
01009
01010 if( n <= 6 ) return(6);
01011 if( n >= 360*10 ) return( 360*10 );
01012 return(n);
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 int
01024 rt_tor_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01025 {
01026 fastf_t alpha;
01027 fastf_t beta;
01028 fastf_t cos_alpha, sin_alpha;
01029 fastf_t cos_beta, sin_beta;
01030 fastf_t dist_to_rim;
01031 struct rt_tor_internal *tip;
01032 int w;
01033 int nw = 8;
01034 int len;
01035 int nlen = 16;
01036 fastf_t *pts;
01037 vect_t G;
01038 vect_t radius;
01039 vect_t edge;
01040 fastf_t rel;
01041
01042 RT_CK_DB_INTERNAL(ip);
01043 tip = (struct rt_tor_internal *)ip->idb_ptr;
01044 RT_TOR_CK_MAGIC(tip);
01045
01046 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 ) {
01047 rel = 0.0;
01048 } else {
01049
01050
01051
01052 rel = ttol->rel * 2 * (tip->r_a+tip->r_h);
01053 }
01054
01055 if( ttol->abs <= 0.0 ) {
01056
01057 if( rel <= 0.0 ) {
01058
01059 nw = 8;
01060 nlen = 16;
01061 } else {
01062
01063 nlen = rt_num_circular_segments( rel, tip->r_a );
01064 nw = rt_num_circular_segments( rel, tip->r_h );
01065 }
01066 } else {
01067
01068 if( rel <= 0.0 || rel > ttol->abs)
01069 rel = ttol->abs;
01070 nlen = rt_num_circular_segments( rel, tip->r_a );
01071 nw = rt_num_circular_segments( rel, tip->r_h );
01072 }
01073
01074
01075
01076
01077
01078
01079
01080
01081 if( ttol->norm > 0.0 ) {
01082 register int nseg;
01083 nseg = (bn_pi / ttol->norm) + 0.99;
01084 if( nseg > nlen ) nlen = nseg;
01085 if( nseg > nw ) nw = nseg;
01086 }
01087
01088
01089 dist_to_rim = tip->r_h/tip->r_a;
01090 pts = (fastf_t *)bu_malloc( nw * nlen * sizeof(point_t),
01091 "rt_tor_plot pts[]" );
01092
01093 #define TOR_PT(www,lll) ((((www)%nw)*nlen)+((lll)%nlen))
01094 #define TOR_PTA(ww,ll) (&pts[TOR_PT(ww,ll)*3])
01095 #define TOR_NORM_A(ww,ll) (&norms[TOR_PT(ww,ll)*3])
01096
01097 for( len = 0; len < nlen; len++ ) {
01098 beta = bn_twopi * len / nlen;
01099 cos_beta = cos(beta);
01100 sin_beta = sin(beta);
01101
01102 VCOMB2( radius, cos_beta, tip->a, sin_beta, tip->b );
01103
01104 VSCALE( G, radius, dist_to_rim );
01105 for( w = 0; w < nw; w++ ) {
01106 alpha = bn_twopi * w / nw;
01107 cos_alpha = cos(alpha);
01108 sin_alpha = sin(alpha);
01109 VCOMB2( edge, cos_alpha, G, sin_alpha*tip->r_h, tip->h );
01110 VADD3( TOR_PTA(w,len), tip->v, edge, radius );
01111 }
01112 }
01113
01114
01115 for( w = 0; w < nw; w++ ) {
01116 len = nlen-1;
01117 RT_ADD_VLIST( vhead, TOR_PTA(w,len), BN_VLIST_LINE_MOVE );
01118 for( len = 0; len < nlen; len++ ) {
01119 RT_ADD_VLIST( vhead, TOR_PTA(w,len), BN_VLIST_LINE_DRAW );
01120 }
01121 }
01122
01123 for( len = 0; len < nlen; len++ ) {
01124 w = nw-1;
01125 RT_ADD_VLIST( vhead, TOR_PTA(w,len), BN_VLIST_LINE_MOVE );
01126 for( w = 0; w < nw; w++ ) {
01127 RT_ADD_VLIST( vhead, TOR_PTA(w,len), BN_VLIST_LINE_DRAW );
01128 }
01129 }
01130
01131 bu_free( (char *)pts, "rt_tor_plot pts[]" );
01132 return(0);
01133 }
01134
01135
01136
01137
01138 int
01139 rt_tor_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01140 {
01141 fastf_t alpha;
01142 fastf_t beta;
01143 fastf_t cos_alpha, sin_alpha;
01144 fastf_t cos_beta, sin_beta;
01145 fastf_t dist_to_rim;
01146 struct rt_tor_internal *tip;
01147 int w;
01148 int nw = 6;
01149 int len;
01150 int nlen = 6;
01151 fastf_t *pts;
01152 vect_t G;
01153 vect_t radius;
01154 vect_t edge;
01155 struct shell *s;
01156 struct vertex **verts;
01157 struct faceuse **faces;
01158 fastf_t *norms;
01159 struct vertex **vertp[4];
01160 int nfaces;
01161 int i;
01162 fastf_t rel;
01163
01164 RT_CK_DB_INTERNAL(ip);
01165 tip = (struct rt_tor_internal *)ip->idb_ptr;
01166 RT_TOR_CK_MAGIC(tip);
01167
01168 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 ) {
01169 rel = 0.0;
01170 } else {
01171
01172
01173
01174 rel = ttol->rel * 2 * (tip->r_a+tip->r_h);
01175 }
01176
01177 if( ttol->abs <= 0.0 ) {
01178
01179 if( rel <= 0.0 ) {
01180
01181 nw = 8;
01182 nlen = 16;
01183 } else {
01184
01185 nlen = rt_num_circular_segments( rel, tip->r_a );
01186 nw = rt_num_circular_segments( rel, tip->r_h );
01187 }
01188 } else {
01189
01190 if( rel <= 0.0 || rel > ttol->abs)
01191 rel = ttol->abs;
01192 nlen = rt_num_circular_segments( rel, tip->r_a );
01193 nw = rt_num_circular_segments( rel, tip->r_h );
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203 if( ttol->norm > 0.0 ) {
01204 register int nseg;
01205 nseg = (bn_pi / ttol->norm) + 0.99;
01206 if( nseg > nlen ) nlen = nseg;
01207 if( nseg > nw ) nw = nseg;
01208 }
01209
01210
01211 dist_to_rim = tip->r_h/tip->r_a;
01212 pts = (fastf_t *)bu_malloc( nw * nlen * sizeof(point_t),
01213 "rt_tor_tess pts[]" );
01214 norms = (fastf_t *)bu_malloc( nw * nlen * sizeof( vect_t ) , "rt_tor_tess: norms[]" );
01215
01216 for( len = 0; len < nlen; len++ ) {
01217 beta = bn_twopi * len / nlen;
01218 cos_beta = cos(beta);
01219 sin_beta = sin(beta);
01220
01221 VCOMB2( radius, cos_beta, tip->a, sin_beta, tip->b );
01222
01223 VSCALE( G, radius, dist_to_rim );
01224 for( w = 0; w < nw; w++ ) {
01225 alpha = bn_twopi * w / nw;
01226 cos_alpha = cos(alpha);
01227 sin_alpha = sin(alpha);
01228 VCOMB2( edge, cos_alpha, G, sin_alpha*tip->r_h, tip->h );
01229 VADD3( TOR_PTA(w,len), tip->v, edge, radius );
01230
01231 VMOVE( TOR_NORM_A(w,len) , edge );
01232 VUNITIZE( TOR_NORM_A(w,len) );
01233 }
01234 }
01235
01236 *r = nmg_mrsv( m );
01237 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
01238
01239 verts = (struct vertex **)bu_calloc( nw*nlen, sizeof(struct vertex *),
01240 "rt_tor_tess *verts[]" );
01241 faces = (struct faceuse **)bu_calloc( nw*nlen, sizeof(struct faceuse *),
01242 "rt_tor_tess *faces[]" );
01243
01244
01245
01246 nfaces = 0;
01247 for( w = 0; w < nw; w++ ) {
01248 for( len = 0; len < nlen; len++ ) {
01249 vertp[0] = &verts[ TOR_PT(w+0,len+0) ];
01250 vertp[1] = &verts[ TOR_PT(w+0,len+1) ];
01251 vertp[2] = &verts[ TOR_PT(w+1,len+1) ];
01252 vertp[3] = &verts[ TOR_PT(w+1,len+0) ];
01253 if( (faces[nfaces++] = nmg_cmface( s, vertp, 4 )) == (struct faceuse *)0 ) {
01254 bu_log("rt_tor_tess() nmg_cmface failed, w=%d/%d, len=%d/%d\n",
01255 w, nw, len, nlen );
01256 nfaces--;
01257 }
01258 }
01259 }
01260
01261
01262 for( w = 0; w < nw; w++ ) {
01263 for( len = 0; len < nlen; len++ ) {
01264 nmg_vertex_gv( verts[TOR_PT(w,len)], TOR_PTA(w,len) );
01265 }
01266 }
01267
01268
01269 for( i=0; i < nfaces; i++ ) {
01270 if( nmg_fu_planeeqn( faces[i], tol ) < 0 )
01271 return -1;
01272 }
01273
01274
01275 for( w=0 ; w<nw ; w++ )
01276 {
01277 for( len=0 ; len<nlen ; len++ )
01278 {
01279 struct vertexuse *vu;
01280 vect_t rev_norm;
01281
01282 VREVERSE( rev_norm , TOR_NORM_A(w,len) );
01283
01284 for( BU_LIST_FOR( vu , vertexuse , &verts[TOR_PT(w,len)]->vu_hd ) )
01285 {
01286 struct faceuse *fu;
01287
01288 NMG_CK_VERTEXUSE( vu );
01289
01290 fu = nmg_find_fu_of_vu( vu );
01291 NMG_CK_FACEUSE( fu );
01292
01293 if( fu->orientation == OT_SAME )
01294 nmg_vertexuse_nv( vu , TOR_NORM_A(w,len) );
01295 else if( fu->orientation == OT_OPPOSITE )
01296 nmg_vertexuse_nv( vu , rev_norm );
01297 }
01298 }
01299 }
01300
01301
01302 nmg_region_a( *r, tol );
01303
01304 bu_free( (char *)pts, "rt_tor_tess pts[]" );
01305 bu_free( (char *)verts, "rt_tor_tess *verts[]" );
01306 bu_free( (char *)faces, "rt_tor_tess *faces[]" );
01307 bu_free( (char *)norms , "rt_tor_tess norms[]" );
01308 return(0);
01309 }
01310
01311
01312
01313
01314
01315
01316
01317
01318 int
01319 rt_tor_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01320 {
01321 struct rt_tor_internal *tip;
01322 union record *rp;
01323 LOCAL fastf_t vec[3*4];
01324 vect_t axb;
01325 register fastf_t f;
01326
01327 BU_CK_EXTERNAL( ep );
01328 rp = (union record *)ep->ext_buf;
01329
01330 if( rp->u_id != ID_SOLID ) {
01331 bu_log("rt_tor_import: defective record\n");
01332 return(-1);
01333 }
01334
01335 RT_CK_DB_INTERNAL( ip );
01336 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01337 ip->idb_type = ID_TOR;
01338 ip->idb_meth = &rt_functab[ID_TOR];
01339 ip->idb_ptr = bu_malloc(sizeof(struct rt_tor_internal), "rt_tor_internal");
01340 tip = (struct rt_tor_internal *)ip->idb_ptr;
01341 tip->magic = RT_TOR_INTERNAL_MAGIC;
01342
01343
01344 rt_fastf_float( vec, rp->s.s_values, 4 );
01345
01346
01347 MAT4X3PNT( tip->v, mat, &vec[0*3] );
01348 MAT4X3VEC( tip->h, mat, &vec[1*3] );
01349 MAT4X3VEC( tip->a, mat, &vec[2*3] );
01350 MAT4X3VEC( tip->b, mat, &vec[3*3] );
01351
01352
01353 tip->r_a = MAGNITUDE(tip->a);
01354 tip->r_b = MAGNITUDE(tip->b);
01355 tip->r_h = MAGNITUDE(tip->h);
01356 if( tip->r_a < SMALL || tip->r_b < SMALL || tip->r_h < SMALL ) {
01357 bu_log("rt_tor_import: zero length A, B, or H vector\n");
01358 return(-1);
01359 }
01360
01361 f = 1.0/tip->r_h;
01362 VSCALE( tip->h, tip->h, f );
01363
01364
01365
01366 VCROSS( axb, tip->a, tip->b );
01367 if( VDOT( axb, tip->h ) < 0 ) {
01368 VREVERSE( tip->h, tip->h );
01369 }
01370
01371 return(0);
01372 }
01373
01374
01375
01376
01377 int
01378 rt_tor_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01379 {
01380 double vec[2*3+2];
01381 struct rt_tor_internal *tip;
01382
01383 RT_CK_DB_INTERNAL( ip );
01384 if (ip->idb_type != ID_TOR) return -1;
01385 tip = (struct rt_tor_internal *)ip->idb_ptr;
01386 RT_TOR_CK_MAGIC(tip);
01387
01388 BU_CK_EXTERNAL(ep);
01389 ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * (2*3+2);
01390 ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "tor external");
01391
01392
01393 VSCALE( &vec[0*3], tip->v, local2mm );
01394 VMOVE( &vec[1*3], tip->h);
01395 vec[2*3+0] = tip->r_a*local2mm;
01396 vec[2*3+1] = tip->r_h*local2mm;
01397
01398
01399 htond( ep->ext_buf, (unsigned char *)vec, 2*3+2);
01400
01401 return 0;
01402 }
01403
01404
01405
01406
01407
01408 int
01409 rt_tor_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01410 {
01411 struct rt_tor_internal *tip;
01412 union record *rec;
01413 vect_t norm;
01414 vect_t cross1, cross2;
01415 fastf_t r1, r2;
01416 fastf_t r3, r4;
01417 double m2;
01418
01419 RT_CK_DB_INTERNAL(ip);
01420 if( ip->idb_type != ID_TOR ) return(-1);
01421 tip = (struct rt_tor_internal *)ip->idb_ptr;
01422 RT_TOR_CK_MAGIC(tip);
01423
01424 BU_CK_EXTERNAL(ep);
01425 ep->ext_nbytes = sizeof(union record);
01426 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "tor external");
01427 rec = (union record *)ep->ext_buf;
01428
01429 rec->s.s_id = ID_SOLID;
01430 rec->s.s_type = TOR;
01431
01432 r1 = tip->r_a;
01433 r2 = tip->r_h;
01434
01435
01436 if( r2 <= 0.0 ) {
01437 bu_log("rt_tor_export: illegal r2=%.12e <= 0\n", r2);
01438 return(-1);
01439 }
01440 if( r2 > r1 ) {
01441 bu_log("rt_tor_export: illegal r2=%.12e > r1=%.12e\n",
01442 r2, r1);
01443 return(-1);
01444 }
01445
01446 r1 *= local2mm;
01447 r2 *= local2mm;
01448 VSCALE( &rec->s.s_values[0*3], tip->v, local2mm );
01449
01450 VMOVE( norm, tip->h );
01451 m2 = MAGNITUDE( norm );
01452 if( m2 <= SQRT_SMALL_FASTF ) {
01453 bu_log("rt_tor_export: normal magnitude is zero!\n");
01454 return(-1);
01455 }
01456 m2 = 1.0/m2;
01457 VSCALE( norm, norm, m2 );
01458 VSCALE( &rec->s.s_values[1*3], norm, r2 );
01459
01460
01461
01462 bn_vec_ortho( cross1, norm );
01463 VCROSS( cross2, norm, cross1 );
01464 VUNITIZE( cross2 );
01465
01466
01467 VSCALE( &rec->s.s_values[2*3], cross1, r1 );
01468 VSCALE( &rec->s.s_values[3*3], cross2, r1 );
01469
01470
01471
01472
01473
01474 r3=r1-r2;
01475 r4=r1+r2;
01476
01477
01478 VSCALE( &rec->s.s_values[4*3], cross1, r3 );
01479 VSCALE( &rec->s.s_values[5*3], cross2, r3 );
01480
01481
01482 VSCALE( &rec->s.s_values[6*3], cross1, r4 );
01483 VSCALE( &rec->s.s_values[7*3], cross2, r4 );
01484
01485 return(0);
01486 }
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 int
01503 rt_tor_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01504 {
01505 struct rt_tor_internal *tip;
01506 LOCAL struct rec {
01507 double v[3];
01508 double h[3];
01509 double ra;
01510 double rh;
01511 } rec;
01512
01513
01514 BU_CK_EXTERNAL( ep );
01515 BU_ASSERT_LONG( ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * (2*3+2) );
01516
01517 RT_CK_DB_INTERNAL( ip );
01518
01519 if (bn_mat_is_non_unif(mat)) {
01520 bu_log("------------------ WARNING ----------------\nNon-uniform matrix transform on torus. Ignored\n");
01521 }
01522
01523
01524 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01525 ip->idb_type = ID_TOR;
01526 ip->idb_meth = &rt_functab[ID_TOR];
01527 ip->idb_ptr = bu_malloc( sizeof(struct rt_tor_internal), "rt_tor_internal");
01528 tip = (struct rt_tor_internal *)ip->idb_ptr;
01529
01530 tip->magic = RT_TOR_INTERNAL_MAGIC;
01531
01532 ntohd( (unsigned char *)&rec, ep->ext_buf, 2*3+2);
01533
01534
01535 MAT4X3PNT( tip->v, mat, rec.v );
01536 MAT4X3VEC( tip->h, mat, rec.h );
01537 VUNITIZE( tip->h );
01538
01539 tip->r_a = rec.ra / mat[15];
01540 tip->r_h = rec.rh / mat[15];
01541
01542
01543 tip->r_b = tip->r_a;
01544
01545
01546 bn_vec_ortho( tip->a, tip->h );
01547 VCROSS( tip->b, tip->h, tip->a);
01548
01549 VSCALE(tip->a, tip->a, tip->r_a);
01550 VSCALE(tip->b, tip->b, tip->r_b);
01551 return 0;
01552 }
01553
01554
01555
01556
01557
01558
01559
01560 int
01561 rt_tor_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01562 {
01563 register struct rt_tor_internal *tip =
01564 (struct rt_tor_internal *)ip->idb_ptr;
01565 double r3, r4;
01566
01567 RT_TOR_CK_MAGIC(tip);
01568 bu_vls_strcat( str, "torus (TOR)\n");
01569
01570 bu_vls_printf( str, "\tV (%g, %g, %g), r1=%g (A), r2=%g (H)\n",
01571 INTCLAMP(tip->v[X] * mm2local),
01572 INTCLAMP(tip->v[Y] * mm2local),
01573 INTCLAMP(tip->v[Z] * mm2local),
01574 INTCLAMP(tip->r_a * mm2local),
01575 INTCLAMP(tip->r_h * mm2local) );
01576
01577 bu_vls_printf( str, "\tN=(%g, %g, %g)\n",
01578 INTCLAMP(tip->h[X] * mm2local),
01579 INTCLAMP(tip->h[Y] * mm2local),
01580 INTCLAMP(tip->h[Z] * mm2local) );
01581
01582 if( !verbose ) return(0);
01583
01584 bu_vls_printf( str, "\tA=(%g, %g, %g)\n",
01585 INTCLAMP(tip->a[X] * mm2local / tip->r_a),
01586 INTCLAMP(tip->a[Y] * mm2local / tip->r_a),
01587 INTCLAMP(tip->a[Z] * mm2local / tip->r_a) );
01588
01589 bu_vls_printf( str, "\tB=(%g, %g, %g)\n",
01590 INTCLAMP(tip->b[X] * mm2local / tip->r_b),
01591 INTCLAMP(tip->b[Y] * mm2local / tip->r_b),
01592 INTCLAMP(tip->b[Z] * mm2local / tip->r_b) );
01593
01594 r3 = tip->r_a - tip->r_h;
01595 bu_vls_printf( str, "\tvector to inner edge = (%g, %g, %g)\n",
01596 INTCLAMP(tip->a[X] * mm2local / tip->r_a * r3),
01597 INTCLAMP(tip->a[Y] * mm2local / tip->r_a * r3),
01598 INTCLAMP(tip->a[Z] * mm2local / tip->r_a * r3) );
01599
01600 r4 = tip->r_a + tip->r_h;
01601 bu_vls_printf( str, "\tvector to outer edge = (%g, %g, %g)\n",
01602 INTCLAMP(tip->a[X] * mm2local / tip->r_a * r4),
01603 INTCLAMP(tip->a[Y] * mm2local / tip->r_a * r4),
01604 INTCLAMP(tip->a[Z] * mm2local / tip->r_a * r4) );
01605
01606 return(0);
01607 }
01608
01609
01610
01611
01612
01613
01614 void
01615 rt_tor_ifree(struct rt_db_internal *ip)
01616 {
01617 register struct rt_tor_internal *tip;
01618
01619 RT_CK_DB_INTERNAL(ip);
01620 tip = (struct rt_tor_internal *)ip->idb_ptr;
01621 RT_TOR_CK_MAGIC(tip);
01622
01623 bu_free( (char *)tip, "rt_tor_internal" );
01624 ip->idb_ptr = GENPTR_NULL;
01625 }
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635