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 #ifndef lint
00050 static const char RCStgc[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_tgc.c,v 14.17 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00051 #endif
00052
00053 #include "common.h"
00054
00055 #include <stddef.h>
00056 #include <stdio.h>
00057 #ifdef HAVE_STRING_H
00058 # include <string.h>
00059 #else
00060 # include <strings.h>
00061 #endif
00062 #include <math.h>
00063
00064 #include "machine.h"
00065 #include "vmath.h"
00066 #include "db.h"
00067 #include "nmg.h"
00068 #include "raytrace.h"
00069 #include "rtgeom.h"
00070 #include "./debug.h"
00071 #include "nurb.h"
00072
00073 BU_EXTERN(int rt_rec_prep, (struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip));
00074
00075 struct tgc_specific {
00076 vect_t tgc_V;
00077 fastf_t tgc_sH;
00078 fastf_t tgc_A;
00079 fastf_t tgc_B;
00080 fastf_t tgc_C;
00081 fastf_t tgc_D;
00082 fastf_t tgc_CdAm1;
00083 fastf_t tgc_DdBm1;
00084 fastf_t tgc_AAdCC;
00085 fastf_t tgc_BBdDD;
00086 vect_t tgc_N;
00087 mat_t tgc_ScShR;
00088 mat_t tgc_invRtShSc;
00089 char tgc_AD_CB;
00090 };
00091
00092
00093 static void rt_tgc_rotate(fastf_t *A, fastf_t *B, fastf_t *Hv, fastf_t *Rot, fastf_t *Inv, struct tgc_specific *tgc);
00094 static void rt_tgc_shear(const fastf_t *vect, int axis, fastf_t *Shr, fastf_t *Trn, fastf_t *Inv);
00095 static void rt_tgc_scale(fastf_t a, fastf_t b, fastf_t h, fastf_t *Scl, fastf_t *Inv);
00096 static void nmg_tgc_disk(struct faceuse *fu, fastf_t *rmat, fastf_t height, int flip);
00097 static void nmg_tgc_nurb_cyl(struct faceuse *fu, fastf_t *top_mat, fastf_t *bot_mat);
00098 void rt_pt_sort(register fastf_t *t, int npts);
00099
00100 #define VLARGE 1000000.0
00101 #define ALPHA(x,y,c,d) ( (x)*(x)*(c) + (y)*(y)*(d) )
00102
00103 const struct bu_structparse rt_tgc_parse[] = {
00104 { "%f", 3, "V", bu_offsetof(struct rt_tgc_internal, v[X]), BU_STRUCTPARSE_FUNC_NULL },
00105 { "%f", 3, "H", bu_offsetof(struct rt_tgc_internal, h[X]), BU_STRUCTPARSE_FUNC_NULL },
00106 { "%f", 3, "A", bu_offsetof(struct rt_tgc_internal, a[X]), BU_STRUCTPARSE_FUNC_NULL },
00107 { "%f", 3, "B", bu_offsetof(struct rt_tgc_internal, b[X]), BU_STRUCTPARSE_FUNC_NULL },
00108 { "%f", 3, "C", bu_offsetof(struct rt_tgc_internal, c[X]), BU_STRUCTPARSE_FUNC_NULL },
00109 { "%f", 3, "D", bu_offsetof(struct rt_tgc_internal, d[X]), BU_STRUCTPARSE_FUNC_NULL },
00110 { {'\0','\0','\0','\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL }
00111 };
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 int
00126 rt_tgc_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00127 {
00128 struct rt_tgc_internal *tip;
00129 register struct tgc_specific *tgc;
00130 register fastf_t f;
00131 LOCAL fastf_t prod_ab, prod_cd;
00132 LOCAL fastf_t magsq_a, magsq_b, magsq_c, magsq_d;
00133 LOCAL fastf_t mag_h, mag_a, mag_b, mag_c, mag_d;
00134 LOCAL mat_t Rot, Shr, Scl;
00135 LOCAL mat_t iRot, tShr, iShr, iScl;
00136 LOCAL mat_t tmp;
00137 LOCAL vect_t nH;
00138 LOCAL vect_t work;
00139
00140 tip = (struct rt_tgc_internal *)ip->idb_ptr;
00141 RT_TGC_CK_MAGIC(tip);
00142
00143
00144
00145
00146
00147
00148 if( rt_rec_prep( stp, ip, rtip ) == 0 )
00149 return(0);
00150
00151
00152 mag_h = sqrt( MAGSQ( tip->h ) );
00153 mag_a = sqrt( magsq_a = MAGSQ( tip->a ) );
00154 mag_b = sqrt( magsq_b = MAGSQ( tip->b ) );
00155 mag_c = sqrt( magsq_c = MAGSQ( tip->c ) );
00156 mag_d = sqrt( magsq_d = MAGSQ( tip->d ) );
00157 prod_ab = mag_a * mag_b;
00158 prod_cd = mag_c * mag_d;
00159
00160 if( NEAR_ZERO( mag_h, RT_LEN_TOL ) ) {
00161 bu_log("tgc(%s): zero length H vector\n", stp->st_name );
00162 return(1);
00163 }
00164
00165
00166 if( NEAR_ZERO( mag_a, RT_LEN_TOL ) &&
00167 NEAR_ZERO( mag_c, RT_LEN_TOL ) ) {
00168 bu_log("tgc(%s): vectors A, C zero length\n", stp->st_name );
00169 return (1);
00170 }
00171 if( NEAR_ZERO( mag_b, RT_LEN_TOL ) &&
00172 NEAR_ZERO( mag_d, RT_LEN_TOL ) ) {
00173 bu_log("tgc(%s): vectors B, D zero length\n", stp->st_name );
00174 return (1);
00175 }
00176
00177
00178 if( prod_ab <= SMALL ) {
00179
00180 if( prod_cd <= SMALL ) {
00181 bu_log("tgc(%s): Both ends degenerate\n", stp->st_name);
00182 return(1);
00183 }
00184
00185
00186
00187 VADD2( tip->v, tip->v, tip->h );
00188 VREVERSE( tip->h, tip->h );
00189 #define VEXCHANGE( a, b, tmp ) { VMOVE(tmp,a); VMOVE(a,b); VMOVE(b,tmp); }
00190 VEXCHANGE( tip->a, tip->c, work );
00191 VEXCHANGE( tip->b, tip->d, work );
00192 bu_log("NOTE: tgc(%s): degenerate end exchanged\n", stp->st_name);
00193 }
00194
00195
00196 VCROSS( work, tip->a, tip->b );
00197 f = VDOT( tip->h, work ) / ( prod_ab*mag_h );
00198 if ( NEAR_ZERO(f, RT_DOT_TOL) ) {
00199 bu_log("tgc(%s): H lies in A-B plane\n",stp->st_name);
00200 return(1);
00201 }
00202
00203 if( prod_ab > SMALL ) {
00204
00205 f = VDOT( tip->a, tip->b ) / prod_ab;
00206 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00207 bu_log("tgc(%s): A not perpendicular to B, f=%g\n",
00208 stp->st_name, f);
00209 bu_log("tgc: dot=%g / a*b=%g\n",
00210 VDOT( tip->a, tip->b ), prod_ab );
00211 return(1);
00212 }
00213 }
00214 if( prod_cd > SMALL ) {
00215
00216 f = VDOT( tip->c, tip->d ) / prod_cd;
00217 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00218 bu_log("tgc(%s): C not perpendicular to D, f=%g\n",
00219 stp->st_name, f);
00220 bu_log("tgc: dot=%g / c*d=%g\n",
00221 VDOT( tip->c, tip->d ), prod_cd );
00222 return(1);
00223 }
00224 }
00225
00226 if( mag_a * mag_c > SMALL ) {
00227
00228 f = 1.0 - VDOT( tip->a, tip->c ) / (mag_a * mag_c);
00229 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00230 bu_log("tgc(%s): A not parallel to C, f=%g\n",
00231 stp->st_name, f);
00232 return(1);
00233 }
00234 }
00235
00236 if( mag_b * mag_d > SMALL ) {
00237
00238 f = 1.0 - VDOT( tip->b, tip->d ) / (mag_b * mag_d);
00239 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00240 bu_log("tgc(%s): B not parallel to D, f=%g\n",
00241 stp->st_name, f);
00242 return(1);
00243 }
00244 }
00245
00246
00247 BU_GETSTRUCT( tgc, tgc_specific );
00248 stp->st_specific = (genptr_t)tgc;
00249
00250 VMOVE( tgc->tgc_V, tip->v );
00251 tgc->tgc_A = mag_a;
00252 tgc->tgc_B = mag_b;
00253 tgc->tgc_C = mag_c;
00254 tgc->tgc_D = mag_d;
00255
00256
00257 if( NEAR_ZERO(magsq_c, SMALL) )
00258 tgc->tgc_AAdCC = VLARGE;
00259 else
00260 tgc->tgc_AAdCC = magsq_a / magsq_c;
00261 if( NEAR_ZERO(magsq_d, SMALL) )
00262 tgc->tgc_BBdDD = VLARGE;
00263 else
00264 tgc->tgc_BBdDD = magsq_b / magsq_d;
00265
00266
00267
00268
00269
00270 f = rt_reldiff( (tgc->tgc_A*tgc->tgc_D), (tgc->tgc_C*tgc->tgc_B) );
00271 tgc->tgc_AD_CB = (f < 0.0001);
00272 rt_tgc_rotate( tip->a, tip->b, tip->h, Rot, iRot, tgc );
00273 MAT4X3VEC( nH, Rot, tip->h );
00274 tgc->tgc_sH = nH[Z];
00275
00276 tgc->tgc_CdAm1 = tgc->tgc_C/tgc->tgc_A - 1.0;
00277 tgc->tgc_DdBm1 = tgc->tgc_D/tgc->tgc_B - 1.0;
00278 if( NEAR_ZERO( tgc->tgc_CdAm1, SMALL ) )
00279 tgc->tgc_CdAm1 = 0.0;
00280 if( NEAR_ZERO( tgc->tgc_DdBm1, SMALL ) )
00281 tgc->tgc_DdBm1 = 0.0;
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 rt_tgc_shear( nH, Z, Shr, tShr, iShr );
00292 rt_tgc_scale( tgc->tgc_A, tgc->tgc_B, tgc->tgc_sH, Scl, iScl );
00293
00294 bn_mat_mul( tmp, Shr, Rot );
00295 bn_mat_mul( tgc->tgc_ScShR, Scl, tmp );
00296
00297 bn_mat_mul( tmp, tShr, Scl );
00298 bn_mat_mul( tgc->tgc_invRtShSc, iRot, tmp );
00299
00300
00301 {
00302 LOCAL fastf_t dx, dy, dz;
00303 LOCAL vect_t temp;
00304
00305
00306
00307 VADD2( temp, tgc->tgc_V, tip->a );
00308 VADD2( work, temp, tip->b );
00309 #define TGC_MM(v) VMINMAX( stp->st_min, stp->st_max, v );
00310 TGC_MM( work );
00311 VSUB2( work, temp, tip->b );
00312 TGC_MM( work );
00313
00314 VSUB2( temp, tgc->tgc_V, tip->a );
00315 VADD2( work, temp, tip->b );
00316 TGC_MM( work );
00317 VSUB2( work, temp, tip->b );
00318 TGC_MM( work );
00319
00320 VADD3( temp, tgc->tgc_V, tip->h, tip->c );
00321 VADD2( work, temp, tip->d );
00322 TGC_MM( work );
00323 VSUB2( work, temp, tip->d );
00324 TGC_MM( work );
00325
00326 VADD2( temp, tgc->tgc_V, tip->h );
00327 VSUB2( temp, temp, tip->c );
00328 VADD2( work, temp, tip->d );
00329 TGC_MM( work );
00330 VSUB2( work, temp, tip->d );
00331 TGC_MM( work );
00332
00333 VSET( stp->st_center,
00334 (stp->st_max[X] + stp->st_min[X])/2,
00335 (stp->st_max[Y] + stp->st_min[Y])/2,
00336 (stp->st_max[Z] + stp->st_min[Z])/2 );
00337
00338 dx = (stp->st_max[X] - stp->st_min[X])/2;
00339 f = dx;
00340 dy = (stp->st_max[Y] - stp->st_min[Y])/2;
00341 if( dy > f ) f = dy;
00342 dz = (stp->st_max[Z] - stp->st_min[Z])/2;
00343 if( dz > f ) f = dz;
00344 stp->st_aradius = f;
00345 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00346 }
00347 return (0);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 static void
00372 rt_tgc_rotate(fastf_t *A, fastf_t *B, fastf_t *Hv, fastf_t *Rot, fastf_t *Inv, struct tgc_specific *tgc)
00373 {
00374 LOCAL vect_t uA, uB, uC;
00375 LOCAL fastf_t mag_ha,
00376 mag_hb;
00377
00378
00379 VMOVE( uA, A );
00380 VUNITIZE( uA );
00381 VMOVE( uB, B );
00382 VUNITIZE( uB );
00383
00384
00385 mag_ha = VDOT( Hv, uA );
00386
00387 mag_hb = VDOT( Hv, uB );
00388
00389
00390
00391
00392 VJOIN2( uC, Hv, -mag_ha, uA, -mag_hb, uB );
00393 VUNITIZE( uC );
00394 VMOVE( tgc->tgc_N, uC );
00395
00396 MAT_IDN( Rot );
00397 MAT_IDN( Inv );
00398
00399 Rot[0] = Inv[0] = uA[X];
00400 Rot[1] = Inv[4] = uA[Y];
00401 Rot[2] = Inv[8] = uA[Z];
00402
00403 Rot[4] = Inv[1] = uB[X];
00404 Rot[5] = Inv[5] = uB[Y];
00405 Rot[6] = Inv[9] = uB[Z];
00406
00407 Rot[8] = Inv[2] = uC[X];
00408 Rot[9] = Inv[6] = uC[Y];
00409 Rot[10] = Inv[10] = uC[Z];
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 static void
00426 rt_tgc_shear(const fastf_t *vect, int axis, fastf_t *Shr, fastf_t *Trn, fastf_t *Inv)
00427 {
00428 MAT_IDN( Shr );
00429 MAT_IDN( Trn );
00430 MAT_IDN( Inv );
00431
00432 if( NEAR_ZERO( vect[axis], SMALL_FASTF ) )
00433 rt_bomb("rt_tgc_shear() divide by zero\n");
00434
00435 if ( axis == X ){
00436 Inv[4] = -(Shr[4] = Trn[1] = -vect[Y]/vect[X]);
00437 Inv[8] = -(Shr[8] = Trn[2] = -vect[Z]/vect[X]);
00438 } else if ( axis == Y ){
00439 Inv[1] = -(Shr[1] = Trn[4] = -vect[X]/vect[Y]);
00440 Inv[9] = -(Shr[9] = Trn[6] = -vect[Z]/vect[Y]);
00441 } else if ( axis == Z ){
00442 Inv[2] = -(Shr[2] = Trn[8] = -vect[X]/vect[Z]);
00443 Inv[6] = -(Shr[6] = Trn[9] = -vect[Y]/vect[Z]);
00444 }
00445 }
00446
00447
00448
00449
00450 static void
00451 rt_tgc_scale(fastf_t a, fastf_t b, fastf_t h, fastf_t *Scl, fastf_t *Inv)
00452 {
00453 MAT_IDN( Scl );
00454 MAT_IDN( Inv );
00455 Scl[0] /= a;
00456 Scl[5] /= b;
00457 Scl[10] /= h;
00458 Inv[0] = a;
00459 Inv[5] = b;
00460 Inv[10] = h;
00461 return;
00462 }
00463
00464
00465
00466
00467 void
00468 rt_tgc_print(register const struct soltab *stp)
00469 {
00470 register const struct tgc_specific *tgc =
00471 (struct tgc_specific *)stp->st_specific;
00472
00473 VPRINT( "V", tgc->tgc_V );
00474 bu_log( "mag sheared H = %f\n", tgc->tgc_sH );
00475 bu_log( "mag A = %f\n", tgc->tgc_A );
00476 bu_log( "mag B = %f\n", tgc->tgc_B );
00477 bu_log( "mag C = %f\n", tgc->tgc_C );
00478 bu_log( "mag D = %f\n", tgc->tgc_D );
00479 VPRINT( "Top normal", tgc->tgc_N );
00480
00481 bn_mat_print( "Sc o Sh o R", tgc->tgc_ScShR );
00482 bn_mat_print( "invR o trnSh o Sc", tgc->tgc_invRtShSc );
00483
00484 if( tgc->tgc_AD_CB ) {
00485 bu_log( "A*D == C*B. Equal eccentricities gives quadratic equation.\n");
00486 } else {
00487 bu_log( "A*D != C*B. Quartic equation.\n");
00488 }
00489 bu_log( "(C/A - 1) = %f\n", tgc->tgc_CdAm1 );
00490 bu_log( "(D/B - 1) = %f\n", tgc->tgc_DdBm1 );
00491 bu_log( "(|A|**2)/(|C|**2) = %f\n", tgc->tgc_AAdCC );
00492 bu_log( "(|B|**2)/(|D|**2) = %f\n", tgc->tgc_BBdDD );
00493 }
00494
00495
00496 #define TGC_NORM_BODY (1)
00497 #define TGC_NORM_TOP (2)
00498 #define TGC_NORM_BOT (3)
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 int
00525 rt_tgc_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00526 {
00527 register const struct tgc_specific *tgc =
00528 (struct tgc_specific *)stp->st_specific;
00529 register struct seg *segp;
00530 LOCAL vect_t pprime;
00531 LOCAL vect_t dprime;
00532 LOCAL vect_t work;
00533 LOCAL fastf_t k[6];
00534 LOCAL int hit_type[6];
00535 LOCAL fastf_t t, b, zval, dir;
00536 LOCAL fastf_t t_scale;
00537 LOCAL fastf_t alf1, alf2;
00538 LOCAL int npts;
00539 LOCAL int intersect;
00540 LOCAL vect_t cor_pprime;
00541 LOCAL fastf_t cor_proj = 0;
00542 LOCAL int i;
00543 LOCAL bn_poly_t C;
00544 LOCAL bn_poly_t Xsqr, Ysqr;
00545 LOCAL bn_poly_t R, Rsqr;
00546
00547
00548 MAT4X3VEC( dprime, tgc->tgc_ScShR, rp->r_dir );
00549
00550
00551
00552
00553
00554
00555 t_scale = MAGNITUDE(dprime);
00556 if( NEAR_ZERO( t_scale, SMALL_FASTF ) ) {
00557 bu_log("tgc(%s) dprime=(%g,%g,%g), t_scale=%e, miss.\n",
00558 V3ARGS(dprime), t_scale);
00559 return 0;
00560 }
00561 t_scale = 1/t_scale;
00562 VSCALE( dprime, dprime, t_scale );
00563
00564 if( NEAR_ZERO( dprime[Z], RT_PCOEF_TOL ) ) {
00565 dprime[Z] = 0.0;
00566 }
00567
00568 VSUB2( work, rp->r_pt, tgc->tgc_V );
00569 MAT4X3VEC( pprime, tgc->tgc_ScShR, work );
00570
00571
00572
00573
00574
00575 cor_proj = -VDOT( pprime, dprime );
00576 VJOIN1( cor_pprime, pprime, cor_proj, dprime );
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 for( i=0; i<3; i++ ) {
00588
00589 if( NEAR_ZERO( dprime[i], 1e-10 ) ) dprime[i] = 0;
00590
00591 if( NEAR_ZERO( cor_pprime[i], 1e-20 ) ) cor_pprime[i] = 0;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 Xsqr.dgr = 2;
00617 Xsqr.cf[0] = dprime[X] * dprime[X];
00618 Xsqr.cf[1] = 2.0 * dprime[X] * cor_pprime[X];
00619 Xsqr.cf[2] = cor_pprime[X] * cor_pprime[X];
00620
00621 Ysqr.dgr = 2;
00622 Ysqr.cf[0] = dprime[Y] * dprime[Y];
00623 Ysqr.cf[1] = 2.0 * dprime[Y] * cor_pprime[Y];
00624 Ysqr.cf[2] = cor_pprime[Y] * cor_pprime[Y];
00625
00626 R.dgr = 1;
00627 R.cf[0] = dprime[Z] * tgc->tgc_CdAm1;
00628
00629 R.cf[1] = (cor_pprime[Z] * tgc->tgc_CdAm1) + 1.0;
00630
00631
00632 Rsqr.dgr = 2;
00633 Rsqr.cf[0] = R.cf[0] * R.cf[0];
00634 Rsqr.cf[1] = R.cf[0] * R.cf[1] * 2;
00635 Rsqr.cf[2] = R.cf[1] * R.cf[1];
00636
00637
00638
00639
00640
00641
00642
00643
00644 C.cf[0] = Xsqr.cf[0] + Ysqr.cf[0] - Rsqr.cf[0];
00645 if( tgc->tgc_AD_CB && !NEAR_ZERO( C.cf[0], 1.0e-10 ) ) {
00646 FAST fastf_t roots;
00647
00648
00649
00650
00651
00652 C.dgr = 2;
00653 C.cf[1] = Xsqr.cf[1] + Ysqr.cf[1] - Rsqr.cf[1];
00654 C.cf[2] = Xsqr.cf[2] + Ysqr.cf[2] - Rsqr.cf[2];
00655
00656
00657 if( (roots = C.cf[1]*C.cf[1] - 4 * C.cf[0] * C.cf[2]) < 0 ) {
00658 npts = 0;
00659 } else {
00660 register fastf_t f;
00661 roots = sqrt(roots);
00662 k[0] = (roots - C.cf[1]) * (f = 0.5 / C.cf[0]);
00663 hit_type[0] = TGC_NORM_BODY;
00664 k[1] = (roots + C.cf[1]) * -f;
00665 hit_type[1] = TGC_NORM_BODY;
00666 npts = 2;
00667 }
00668 } else {
00669 LOCAL bn_poly_t Q, Qsqr;
00670 LOCAL bn_complex_t val[4];
00671 register int l;
00672 register int nroots;
00673
00674 Q.dgr = 1;
00675 Q.cf[0] = dprime[Z] * tgc->tgc_DdBm1;
00676
00677 Q.cf[1] = (cor_pprime[Z] * tgc->tgc_DdBm1) + 1.0;
00678
00679
00680 Qsqr.dgr = 2;
00681 Qsqr.cf[0] = Q.cf[0] * Q.cf[0];
00682 Qsqr.cf[1] = Q.cf[0] * Q.cf[1] * 2;
00683 Qsqr.cf[2] = Q.cf[1] * Q.cf[1];
00684
00685
00686
00687
00688
00689
00690
00691
00692 C.dgr = 4;
00693 C.cf[0] = Qsqr.cf[0] * Xsqr.cf[0] +
00694 Rsqr.cf[0] * Ysqr.cf[0] -
00695 (Rsqr.cf[0] * Qsqr.cf[0]);
00696 C.cf[1] = Qsqr.cf[0] * Xsqr.cf[1] + Qsqr.cf[1] * Xsqr.cf[0] +
00697 Rsqr.cf[0] * Ysqr.cf[1] + Rsqr.cf[1] * Ysqr.cf[0] -
00698 (Rsqr.cf[0] * Qsqr.cf[1] + Rsqr.cf[1] * Qsqr.cf[0]);
00699 C.cf[2] = Qsqr.cf[0] * Xsqr.cf[2] + Qsqr.cf[1] * Xsqr.cf[1] +
00700 Qsqr.cf[2] * Xsqr.cf[0] +
00701 Rsqr.cf[0] * Ysqr.cf[2] + Rsqr.cf[1] * Ysqr.cf[1] +
00702 Rsqr.cf[2] * Ysqr.cf[0] -
00703 (Rsqr.cf[0] * Qsqr.cf[2] + Rsqr.cf[1] * Qsqr.cf[1] +
00704 Rsqr.cf[2] * Qsqr.cf[0]);
00705 C.cf[3] = Qsqr.cf[1] * Xsqr.cf[2] + Qsqr.cf[2] * Xsqr.cf[1] +
00706 Rsqr.cf[1] * Ysqr.cf[2] + Rsqr.cf[2] * Ysqr.cf[1] -
00707 (Rsqr.cf[1] * Qsqr.cf[2] + Rsqr.cf[2] * Qsqr.cf[1]);
00708 C.cf[4] = Qsqr.cf[2] * Xsqr.cf[2] +
00709 Rsqr.cf[2] * Ysqr.cf[2] -
00710 (Rsqr.cf[2] * Qsqr.cf[2]);
00711
00712
00713 nroots = rt_poly_roots( &C , val, stp->st_dp->d_namep );
00714
00715
00716
00717
00718
00719
00720
00721 for ( l=0, npts=0; l < nroots; l++ ){
00722 if ( NEAR_ZERO( val[l].im, 1e-10 ) ) {
00723 hit_type[npts] = TGC_NORM_BODY;
00724 k[npts++] = val[l].re;
00725 }
00726 }
00727
00728 if ( npts != 0 && npts != 2 && npts != 4 && npts > 0 ){
00729 bu_log("tgc: reduced %d to %d roots\n",nroots,npts);
00730 bn_pr_roots( stp->st_name, val, nroots );
00731 } else if (nroots < 0) {
00732 static int reported=0;
00733 bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
00734 if (!reported) {
00735 VPRINT("while shooting from:\t", rp->r_pt);
00736 VPRINT("while shooting at:\t", rp->r_dir);
00737 bu_log("Additional truncated general cone convergence failure details will be suppressed.\n");
00738 reported=1;
00739 }
00740 }
00741 }
00742
00743
00744
00745
00746 for( i = 0; i < npts; ++i ) {
00747 k[i] += cor_proj;
00748 }
00749
00750
00751
00752
00753 i = 0;
00754 while( i < npts ) {
00755 zval = k[i]*dprime[Z] + pprime[Z];
00756
00757 if ( zval >= 1.0 || zval <= 0.0 ){
00758 int j;
00759
00760 npts--;
00761 for( j=i ; j<npts ; j++ ) {
00762 hit_type[j] = hit_type[j+1];
00763 k[j] = k[j+1];
00764 }
00765 } else {
00766 i++;
00767 }
00768 }
00769
00770
00771
00772
00773 dir = VDOT( tgc->tgc_N, rp->r_dir );
00774 if( !NEAR_ZERO( dprime[Z], SMALL_FASTF ) && !NEAR_ZERO( dir, RT_DOT_TOL ) ) {
00775 b = ( -pprime[Z] )/dprime[Z];
00776
00777 t = ( 1.0 - pprime[Z] )/dprime[Z];
00778
00779 VJOIN1( work, pprime, b, dprime );
00780
00781
00782 alf1 = work[X]*work[X] + work[Y]*work[Y];
00783
00784 VJOIN1( work, pprime, t, dprime );
00785
00786
00787 alf2 = ALPHA(work[X], work[Y], tgc->tgc_AAdCC,tgc->tgc_BBdDD);
00788
00789 if ( alf1 <= 1.0 ){
00790 hit_type[npts] = TGC_NORM_BOT;
00791 k[npts++] = b;
00792 }
00793 if ( alf2 <= 1.0 ){
00794 hit_type[npts] = TGC_NORM_TOP;
00795 k[npts++] = t;
00796 }
00797 }
00798
00799
00800
00801 {
00802 register fastf_t u;
00803 register short lim, n;
00804 register int type;
00805
00806 for( lim = npts-1; lim > 0; lim-- ) {
00807 for( n = 0; n < lim; n++ ) {
00808 if( (u=k[n]) < k[n+1] ) {
00809
00810 type = hit_type[n];
00811 hit_type[n] = hit_type[n+1];
00812 hit_type[n+1] = type;
00813 k[n] = k[n+1];
00814 k[n+1] = u;
00815 }
00816 }
00817 }
00818 }
00819
00820
00821 if( npts%2 ) {
00822
00823
00824
00825
00826
00827 for( i=npts-1 ; i>0 ; i-- ) {
00828 fastf_t diff;
00829
00830 diff = k[i-1] - k[i];
00831 if( diff < ap->a_rt_i->rti_tol.dist ) {
00832
00833 int j;
00834
00835 npts--;
00836 for( j=i ; j<npts ; j++ ) {
00837 hit_type[j] = hit_type[j+1];
00838 k[j] = k[j+1];
00839 }
00840
00841
00842 break;
00843 }
00844 }
00845 }
00846
00847 if ( npts != 0 && npts != 2 && npts != 4 ){
00848 bu_log("tgc(%s): %d intersects != {0,2,4}\n",
00849 stp->st_name, npts );
00850 bu_log( "\tray: pt = (%g %g %g), dir = (%g %g %g)\n",
00851 V3ARGS( ap->a_ray.r_pt ),
00852 V3ARGS( ap->a_ray.r_dir ) );
00853 for( i=0 ; i<npts ; i++ ) {
00854 bu_log( "\t%g", k[i]*t_scale );
00855 }
00856 bu_log( "\n" );
00857 return(0);
00858 }
00859
00860 intersect = 0;
00861 for( i=npts-1 ; i>0 ; i -= 2 ) {
00862 RT_GET_SEG( segp, ap->a_resource );
00863 segp->seg_stp = stp;
00864
00865 segp->seg_in.hit_dist = k[i] * t_scale;
00866 segp->seg_in.hit_surfno = hit_type[i];
00867 if( segp->seg_in.hit_surfno == TGC_NORM_BODY ) {
00868 VJOIN1( segp->seg_in.hit_vpriv, pprime, k[i], dprime );
00869 } else {
00870 if( dir > 0.0 ) {
00871 segp->seg_in.hit_surfno = TGC_NORM_BOT;
00872 } else {
00873 segp->seg_in.hit_surfno = TGC_NORM_TOP;
00874 }
00875 }
00876
00877 segp->seg_out.hit_dist = k[i-1] * t_scale;
00878 segp->seg_out.hit_surfno = hit_type[i-1];
00879 if( segp->seg_out.hit_surfno == TGC_NORM_BODY ) {
00880 VJOIN1( segp->seg_out.hit_vpriv, pprime, k[i-1], dprime );
00881 } else {
00882 if( dir > 0.0 ) {
00883 segp->seg_out.hit_surfno = TGC_NORM_TOP;
00884 } else {
00885 segp->seg_out.hit_surfno = TGC_NORM_BOT;
00886 }
00887 }
00888 intersect++;
00889 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00890 }
00891
00892 return( intersect );
00893 }
00894
00895 #define RT_TGC_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
00896
00897
00898
00899
00900
00901
00902 void
00903 rt_tgc_vshot(struct soltab **stp, register struct xray **rp, struct seg *segp, int n, struct application *ap)
00904
00905
00906
00907
00908
00909 {
00910 register struct tgc_specific *tgc;
00911 register int ix;
00912 LOCAL vect_t pprime;
00913 LOCAL vect_t dprime;
00914 LOCAL vect_t work;
00915 LOCAL fastf_t k[4], pt[2];
00916 LOCAL fastf_t t, b, zval, dir;
00917 LOCAL fastf_t t_scale = 0;
00918 LOCAL fastf_t alf1, alf2;
00919 LOCAL int npts;
00920 LOCAL int intersect;
00921 LOCAL vect_t cor_pprime;
00922 LOCAL fastf_t cor_proj = 0;
00923 LOCAL int i;
00924 LOCAL bn_poly_t *C;
00925 LOCAL bn_poly_t Xsqr, Ysqr;
00926 LOCAL bn_poly_t R, Rsqr;
00927
00928
00929 C = (bn_poly_t *)bu_malloc(n * sizeof(bn_poly_t), "tor bn_poly_t");
00930
00931
00932 # include "noalias.h"
00933 for(ix = 0; ix < n; ix++) segp[ix].seg_stp = stp[ix];
00934
00935
00936 # include "noalias.h"
00937 for(ix = 0; ix < n; ix++) {
00938
00939 #if !CRAY
00940 if (segp[ix].seg_stp == 0) continue;
00941 #endif
00942
00943 tgc = (struct tgc_specific *)stp[ix]->st_specific;
00944
00945
00946 MAT4X3VEC( dprime, tgc->tgc_ScShR, rp[ix]->r_dir );
00947
00948
00949
00950
00951
00952
00953 t_scale = 1/MAGNITUDE( dprime );
00954 VSCALE( dprime, dprime, t_scale );
00955
00956 if( NEAR_ZERO( dprime[Z], RT_PCOEF_TOL ) )
00957 dprime[Z] = 0.0;
00958
00959
00960 VMOVE( segp[ix].seg_in.hit_normal, dprime );
00961
00962 VSUB2( work, rp[ix]->r_pt, tgc->tgc_V );
00963 MAT4X3VEC( pprime, tgc->tgc_ScShR, work );
00964
00965
00966 VMOVE( segp[ix].seg_out.hit_normal, pprime );
00967
00968
00969
00970
00971
00972 cor_proj = VDOT( pprime, dprime );
00973 VSCALE( cor_pprime, dprime, cor_proj );
00974 VSUB2( cor_pprime, pprime, cor_pprime );
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 Xsqr.dgr = 2;
00999 Xsqr.cf[0] = dprime[X] * dprime[X];
01000 Xsqr.cf[1] = 2.0 * dprime[X] * cor_pprime[X];
01001 Xsqr.cf[2] = cor_pprime[X] * cor_pprime[X];
01002
01003 Ysqr.dgr = 2;
01004 Ysqr.cf[0] = dprime[Y] * dprime[Y];
01005 Ysqr.cf[1] = 2.0 * dprime[Y] * cor_pprime[Y];
01006 Ysqr.cf[2] = cor_pprime[Y] * cor_pprime[Y];
01007
01008 R.dgr = 1;
01009 R.cf[0] = dprime[Z] * tgc->tgc_CdAm1;
01010
01011 R.cf[1] = (cor_pprime[Z] * tgc->tgc_CdAm1) + 1.0;
01012
01013
01014 Rsqr.dgr = 2;
01015 Rsqr.cf[0] = R.cf[0] * R.cf[0];
01016 Rsqr.cf[1] = R.cf[0] * R.cf[1] * 2;
01017 Rsqr.cf[2] = R.cf[1] * R.cf[1];
01018
01019
01020
01021
01022
01023
01024 if ( tgc->tgc_AD_CB ){
01025
01026
01027 C[ix].dgr = 2;
01028 C[ix].cf[0] = Xsqr.cf[0] + Ysqr.cf[0] - Rsqr.cf[0];
01029 C[ix].cf[1] = Xsqr.cf[1] + Ysqr.cf[1] - Rsqr.cf[1];
01030 C[ix].cf[2] = Xsqr.cf[2] + Ysqr.cf[2] - Rsqr.cf[2];
01031 } else {
01032 LOCAL bn_poly_t Q, Qsqr;
01033
01034 Q.dgr = 1;
01035 Q.cf[0] = dprime[Z] * tgc->tgc_DdBm1;
01036
01037 Q.cf[1] = (cor_pprime[Z] * tgc->tgc_DdBm1) + 1.0;
01038
01039
01040 Qsqr.dgr = 2;
01041 Qsqr.cf[0] = Q.cf[0] * Q.cf[0];
01042 Qsqr.cf[1] = Q.cf[0] * Q.cf[1] * 2;
01043 Qsqr.cf[2] = Q.cf[1] * Q.cf[1];
01044
01045
01046 C[ix].dgr = 4;
01047 C[ix].cf[0] = Qsqr.cf[0] * Xsqr.cf[0];
01048 C[ix].cf[1] = Qsqr.cf[0] * Xsqr.cf[1] +
01049 Qsqr.cf[1] * Xsqr.cf[0];
01050 C[ix].cf[2] = Qsqr.cf[0] * Xsqr.cf[2] +
01051 Qsqr.cf[1] * Xsqr.cf[1] +
01052 Qsqr.cf[2] * Xsqr.cf[0];
01053 C[ix].cf[3] = Qsqr.cf[1] * Xsqr.cf[2] +
01054 Qsqr.cf[2] * Xsqr.cf[1];
01055 C[ix].cf[4] = Qsqr.cf[2] * Xsqr.cf[2];
01056
01057
01058
01059 C[ix].cf[0] += Rsqr.cf[0] * Ysqr.cf[0];
01060 C[ix].cf[1] += Rsqr.cf[0] * Ysqr.cf[1] +
01061 Rsqr.cf[1] * Ysqr.cf[0];
01062 C[ix].cf[2] += Rsqr.cf[0] * Ysqr.cf[2] +
01063 Rsqr.cf[1] * Ysqr.cf[1] +
01064 Rsqr.cf[2] * Ysqr.cf[0];
01065 C[ix].cf[3] += Rsqr.cf[1] * Ysqr.cf[2] +
01066 Rsqr.cf[2] * Ysqr.cf[1];
01067 C[ix].cf[4] += Rsqr.cf[2] * Ysqr.cf[2];
01068
01069
01070
01071 C[ix].cf[0] -= Rsqr.cf[0] * Qsqr.cf[0];
01072 C[ix].cf[1] -= Rsqr.cf[0] * Qsqr.cf[1] +
01073 Rsqr.cf[1] * Qsqr.cf[0];
01074 C[ix].cf[2] -= Rsqr.cf[0] * Qsqr.cf[2] +
01075 Rsqr.cf[1] * Qsqr.cf[1] +
01076 Rsqr.cf[2] * Qsqr.cf[0];
01077 C[ix].cf[3] -= Rsqr.cf[1] * Qsqr.cf[2] +
01078 Rsqr.cf[2] * Qsqr.cf[1];
01079 C[ix].cf[4] -= Rsqr.cf[2] * Qsqr.cf[2];
01080 }
01081
01082 }
01083
01084
01085 for(ix = 0; ix < n; ix++){
01086 if (segp[ix].seg_stp == 0) continue;
01087
01088
01089 if ( C[ix].dgr == 2 ){
01090 FAST fastf_t roots;
01091
01092
01093 if( (roots = C[ix].cf[1]*C[ix].cf[1]-4*C[ix].cf[0]*C[ix].cf[2]
01094 ) < 0 ) {
01095 npts = 0;
01096 } else {
01097 roots = sqrt(roots);
01098 k[0] = (roots - C[ix].cf[1]) * 0.5 / C[ix].cf[0];
01099 k[1] = (roots + C[ix].cf[1]) * (-0.5) / C[ix].cf[0];
01100 npts = 2;
01101 }
01102 } else {
01103 LOCAL bn_complex_t val[4];
01104 register int l;
01105 register int nroots;
01106
01107
01108 nroots = rt_poly_roots( &C[ix] , val, (*stp)->st_dp->d_namep );
01109
01110
01111
01112
01113
01114
01115
01116 for ( l=0, npts=0; l < nroots; l++ ){
01117 if ( NEAR_ZERO( val[l].im, 0.0001 ) )
01118 k[npts++] = val[l].re;
01119 }
01120
01121 if ( npts != 0 && npts != 2 && npts != 4 && npts > 0 ){
01122 bu_log("tgc: reduced %d to %d roots\n",nroots,npts);
01123 bn_pr_roots( "tgc", val, nroots );
01124 } else if (nroots < 0) {
01125 static int reported=0;
01126 bu_log("The root solver failed to converge on a solution for %s\n", stp[ix]->st_dp->d_namep);
01127 if (!reported) {
01128 VPRINT("while shooting from:\t", rp[ix]->r_pt);
01129 VPRINT("while shooting at:\t", rp[ix]->r_dir);
01130 bu_log("Additional truncated general cone convergence failure details will be suppressed.\n");
01131 reported=1;
01132 }
01133 }
01134 }
01135
01136
01137
01138
01139 for( i = 0; i < npts; ++i )
01140 k[i] -= cor_proj;
01141
01142 if ( npts != 0 && npts != 2 && npts != 4 ){
01143 bu_log("tgc(%s): %d intersects != {0,2,4}\n",
01144 stp[ix]->st_name, npts );
01145 RT_TGC_SEG_MISS(segp[ix]);
01146 continue;
01147 }
01148
01149
01150 rt_pt_sort( k, npts );
01151
01152
01153
01154
01155
01156
01157 #define OUT 0
01158 #define IN 1
01159
01160
01161
01162
01163
01164
01165 intersect = 0;
01166 tgc = (struct tgc_specific *)stp[ix]->st_specific;
01167 for ( i=0; i < npts; i++ ){
01168
01169
01170 zval = k[i]*segp[ix].seg_in.hit_normal[Z] +
01171 segp[ix].seg_out.hit_normal[Z];
01172
01173 if ( zval < 1.0 && zval > 0.0 ){
01174 if ( ++intersect == 2 ) {
01175 pt[IN] = k[i];
01176 } else
01177 pt[OUT] = k[i];
01178 }
01179 }
01180
01181 C[ix].dgr = intersect;
01182 C[ix].cf[OUT] = pt[OUT];
01183 C[ix].cf[IN] = pt[IN];
01184 }
01185
01186
01187 # include "noalias.h"
01188 for(ix = 0; ix < n; ix++) {
01189 if (segp[ix].seg_stp == 0) continue;
01190
01191 tgc = (struct tgc_specific *)stp[ix]->st_specific;
01192 intersect = C[ix].dgr;
01193 pt[OUT] = C[ix].cf[OUT];
01194 pt[IN] = C[ix].cf[IN];
01195
01196 VMOVE( pprime, segp[ix].seg_out.hit_normal );
01197
01198 VMOVE( dprime, segp[ix].seg_in.hit_normal );
01199
01200 if ( intersect == 2 ){
01201
01202
01203
01204 segp[ix].seg_in.hit_dist = pt[IN] * t_scale;
01205 segp[ix].seg_in.hit_surfno = TGC_NORM_BODY;
01206 VJOIN1( segp[ix].seg_in.hit_vpriv, pprime, pt[IN], dprime );
01207
01208 segp[ix].seg_out.hit_dist = pt[OUT] * t_scale;
01209 segp[ix].seg_out.hit_surfno = TGC_NORM_BODY;
01210 VJOIN1( segp[ix].seg_out.hit_vpriv, pprime, pt[OUT], dprime );
01211 } else if ( intersect == 1 ) {
01212 int nflag;
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 if( dprime[Z] == 0.0 ) {
01224 #if 0
01225 bu_log("tgc: dprime[Z] = 0!\n" );
01226 #endif
01227 RT_TGC_SEG_MISS(segp[ix]);
01228 continue;
01229 }
01230 b = ( -pprime[Z] )/dprime[Z];
01231
01232 t = ( 1.0 - pprime[Z] )/dprime[Z];
01233
01234 VJOIN1( work, pprime, b, dprime );
01235
01236
01237 alf1 = work[X]*work[X] + work[Y]*work[Y];
01238
01239 VJOIN1( work, pprime, t, dprime );
01240
01241 alf2 = ALPHA(work[X], work[Y], tgc->tgc_AAdCC,tgc->tgc_BBdDD);
01242
01243 if ( alf1 <= 1.0 ){
01244 pt[IN] = b;
01245 nflag = TGC_NORM_BOT;
01246 } else if ( alf2 <= 1.0 ){
01247 pt[IN] = t;
01248 nflag = TGC_NORM_TOP;
01249 } else {
01250
01251 #if 0
01252 bu_log("tgc(%s): only 1 intersect\n", stp[ix]->st_name);
01253 #endif
01254 RT_TGC_SEG_MISS(segp[ix]);
01255 continue;
01256 }
01257
01258
01259 if ( pt[OUT] >= pt[IN] ) {
01260 segp[ix].seg_in.hit_dist = pt[IN] * t_scale;
01261 segp[ix].seg_in.hit_surfno = nflag;
01262
01263 segp[ix].seg_out.hit_dist = pt[OUT] * t_scale;
01264 segp[ix].seg_out.hit_surfno = TGC_NORM_BODY;
01265
01266 VJOIN1( segp[ix].seg_out.hit_vpriv, pprime, pt[OUT], dprime );
01267 } else {
01268 segp[ix].seg_in.hit_dist = pt[OUT] * t_scale;
01269
01270 segp[ix].seg_in.hit_surfno = TGC_NORM_BODY;
01271 VJOIN1( segp[ix].seg_in.hit_vpriv, pprime, pt[OUT], dprime );
01272
01273 segp[ix].seg_out.hit_dist = pt[IN] * t_scale;
01274 segp[ix].seg_out.hit_surfno = nflag;
01275 }
01276 } else {
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 if( dprime[Z] == 0.0 ) {
01287 RT_TGC_SEG_MISS(segp[ix]);
01288 continue;
01289 }
01290
01291 dir = VDOT( tgc->tgc_N, rp[ix]->r_dir );
01292 if ( NEAR_ZERO( dir, RT_DOT_TOL ) ) {
01293 RT_TGC_SEG_MISS(segp[ix]);
01294 continue;
01295 }
01296
01297 b = ( -pprime[Z] )/dprime[Z];
01298
01299 t = ( 1.0 - pprime[Z] )/dprime[Z];
01300
01301 VJOIN1( work, pprime, b, dprime );
01302
01303
01304 alf1 = work[X]*work[X] + work[Y]*work[Y];
01305
01306 VJOIN1( work, pprime, t, dprime );
01307
01308 alf2 = ALPHA(work[X], work[Y], tgc->tgc_AAdCC,tgc->tgc_BBdDD);
01309
01310
01311
01312
01313
01314 if ( alf1 > 1.0 || alf2 > 1.0 ) {
01315 RT_TGC_SEG_MISS(segp[ix]);
01316 continue;
01317 }
01318
01319
01320
01321
01322
01323 if ( dir > 0.0 ){
01324 segp[ix].seg_in.hit_dist = b * t_scale;
01325 segp[ix].seg_in.hit_surfno = TGC_NORM_BOT;
01326
01327 segp[ix].seg_out.hit_dist = t * t_scale;
01328 segp[ix].seg_out.hit_surfno = TGC_NORM_TOP;
01329 } else {
01330 segp[ix].seg_in.hit_dist = t * t_scale;
01331 segp[ix].seg_in.hit_surfno = TGC_NORM_TOP;
01332
01333 segp[ix].seg_out.hit_dist = b * t_scale;
01334 segp[ix].seg_out.hit_surfno = TGC_NORM_BOT;
01335 }
01336 }
01337 }
01338 bu_free( (char *)C, "tor bn_poly_t" );
01339 }
01340
01341
01342
01343
01344
01345
01346 void
01347 rt_pt_sort(register fastf_t t[], int npts)
01348 {
01349 FAST fastf_t u;
01350 register short lim, n;
01351
01352 for( lim = npts-1; lim > 0; lim-- ) {
01353 for( n = 0; n < lim; n++ ) {
01354 if( (u=t[n]) < t[n+1] ) {
01355
01356 t[n] = t[n+1];
01357 t[n+1] = u;
01358 }
01359 }
01360 }
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 void
01416 rt_tgc_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
01417 {
01418 register struct tgc_specific *tgc =
01419 (struct tgc_specific *)stp->st_specific;
01420 FAST fastf_t Q;
01421 FAST fastf_t R;
01422 LOCAL vect_t stdnorm;
01423
01424
01425 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
01426
01427
01428 switch( hitp->hit_surfno ) {
01429 case TGC_NORM_TOP:
01430 VMOVE( hitp->hit_normal, tgc->tgc_N );
01431 break;
01432 case TGC_NORM_BOT:
01433 VREVERSE( hitp->hit_normal, tgc->tgc_N );
01434 break;
01435 case TGC_NORM_BODY:
01436
01437 R = 1 + tgc->tgc_CdAm1 * hitp->hit_vpriv[Z];
01438 Q = 1 + tgc->tgc_DdBm1 * hitp->hit_vpriv[Z];
01439 stdnorm[X] = hitp->hit_vpriv[X] * Q * Q;
01440 stdnorm[Y] = hitp->hit_vpriv[Y] * R * R;
01441 stdnorm[Z] = (hitp->hit_vpriv[X]*hitp->hit_vpriv[X] - R*R)
01442 * Q * tgc->tgc_DdBm1
01443 + (hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y] - Q*Q)
01444 * R * tgc->tgc_CdAm1;
01445 MAT4X3VEC( hitp->hit_normal, tgc->tgc_invRtShSc, stdnorm );
01446
01447 VUNITIZE( hitp->hit_normal );
01448 break;
01449 default:
01450 bu_log("rt_tgc_norm: bad surfno=%d\n", hitp->hit_surfno);
01451 break;
01452 }
01453 }
01454
01455
01456
01457
01458 void
01459 rt_tgc_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
01460 {
01461 register struct tgc_specific *tgc =
01462 (struct tgc_specific *)stp->st_specific;
01463 LOCAL vect_t work;
01464 LOCAL vect_t pprime;
01465 FAST fastf_t len;
01466
01467
01468
01469
01470 VSUB2( work, hitp->hit_point, tgc->tgc_V );
01471 MAT4X3VEC( pprime, tgc->tgc_ScShR, work );
01472
01473 switch( hitp->hit_surfno ) {
01474 case TGC_NORM_BODY:
01475
01476 pprime[X] *= tgc->tgc_A / (tgc->tgc_A*( 1.0 - pprime[Z]) + tgc->tgc_C*pprime[Z]);
01477 pprime[Y] *= tgc->tgc_B / (tgc->tgc_B*( 1.0 - pprime[Z]) + tgc->tgc_D*pprime[Z]);
01478 uvp->uv_u = atan2( pprime[Y], pprime[X] ) / bn_twopi + 0.5;
01479 uvp->uv_v = pprime[Z];
01480 break;
01481 case TGC_NORM_TOP:
01482
01483
01484 pprime[X] *= tgc->tgc_A / tgc->tgc_C;
01485 pprime[Y] *= tgc->tgc_B / tgc->tgc_D;
01486 uvp->uv_u = atan2( pprime[Y], pprime[X] ) / bn_twopi + 0.5;
01487 len = sqrt(pprime[X]*pprime[X]+pprime[Y]*pprime[Y]);
01488 uvp->uv_v = len;
01489 break;
01490 case TGC_NORM_BOT:
01491
01492 len = sqrt(pprime[X]*pprime[X]+pprime[Y]*pprime[Y]);
01493 uvp->uv_u = atan2( pprime[Y], pprime[X] ) / bn_twopi + 0.5;
01494 uvp->uv_v = 1 - len;
01495 break;
01496 }
01497
01498 if( uvp->uv_u < 0.0 )
01499 uvp->uv_u = 0.0;
01500 else if( uvp->uv_u > 1.0 )
01501 uvp->uv_u = 1.0;
01502 if( uvp->uv_v < 0.0 )
01503 uvp->uv_v = 0.0;
01504 else if( uvp->uv_v > 1.0 )
01505 uvp->uv_v = 1.0;
01506
01507
01508 uvp->uv_du = uvp->uv_dv = 0;
01509 }
01510
01511
01512
01513
01514
01515 void
01516 rt_tgc_free(struct soltab *stp)
01517 {
01518 register struct tgc_specific *tgc =
01519 (struct tgc_specific *)stp->st_specific;
01520
01521 bu_free( (char *)tgc, "tgc_specific");
01522 }
01523
01524 int
01525 rt_tgc_class(void)
01526 {
01527 return(0);
01528 }
01529
01530
01531
01532
01533
01534
01535
01536
01537 int
01538 rt_tgc_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01539 {
01540 struct rt_tgc_internal *tip;
01541 union record *rp;
01542 LOCAL fastf_t vec[3*6];
01543
01544 BU_CK_EXTERNAL( ep );
01545 rp = (union record *)ep->ext_buf;
01546
01547 if( rp->u_id != ID_SOLID ) {
01548 bu_log("rt_tgc_import: defective record\n");
01549 return(-1);
01550 }
01551
01552 RT_CK_DB_INTERNAL( ip );
01553 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01554 ip->idb_type = ID_TGC;
01555 ip->idb_meth = &rt_functab[ID_TGC];
01556 ip->idb_ptr = bu_malloc( sizeof(struct rt_tgc_internal), "rt_tgc_internal");
01557 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01558 tip->magic = RT_TGC_INTERNAL_MAGIC;
01559
01560
01561 rt_fastf_float( vec, rp->s.s_values, 6 );
01562
01563
01564 MAT4X3PNT( tip->v, mat, &vec[0*3] );
01565 MAT4X3VEC( tip->h, mat, &vec[1*3] );
01566 MAT4X3VEC( tip->a, mat, &vec[2*3] );
01567 MAT4X3VEC( tip->b, mat, &vec[3*3] );
01568 MAT4X3VEC( tip->c, mat, &vec[4*3] );
01569 MAT4X3VEC( tip->d, mat, &vec[5*3] );
01570
01571 return(0);
01572 }
01573
01574
01575
01576
01577 int
01578 rt_tgc_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01579 {
01580 struct rt_tgc_internal *tip;
01581 union record *rec;
01582
01583 RT_CK_DB_INTERNAL(ip);
01584 if( ip->idb_type != ID_TGC && ip->idb_type != ID_REC ) return(-1);
01585 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01586 RT_TGC_CK_MAGIC(tip);
01587
01588 BU_CK_EXTERNAL(ep);
01589 ep->ext_nbytes = sizeof(union record);
01590 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "tgc external");
01591 rec = (union record *)ep->ext_buf;
01592
01593 rec->s.s_id = ID_SOLID;
01594 rec->s.s_type = GENTGC;
01595
01596
01597 VSCALE( &rec->s.s_values[0], tip->v, local2mm );
01598 VSCALE( &rec->s.s_values[3], tip->h, local2mm );
01599 VSCALE( &rec->s.s_values[6], tip->a, local2mm );
01600 VSCALE( &rec->s.s_values[9], tip->b, local2mm );
01601 VSCALE( &rec->s.s_values[12], tip->c, local2mm );
01602 VSCALE( &rec->s.s_values[15], tip->d, local2mm );
01603
01604 return(0);
01605 }
01606
01607
01608
01609
01610
01611
01612
01613 int
01614 rt_tgc_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01615 {
01616 struct rt_tgc_internal *tip;
01617 fastf_t vec[3*6];
01618
01619 BU_CK_EXTERNAL( ep );
01620
01621 BU_ASSERT_LONG( ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * 3*6 );
01622
01623 RT_CK_DB_INTERNAL( ip );
01624 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01625 ip->idb_type = ID_TGC;
01626 ip->idb_meth = &rt_functab[ID_TGC];
01627 ip->idb_ptr = bu_malloc( sizeof(struct rt_tgc_internal), "rt_tgc_internal");
01628
01629 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01630 tip->magic = RT_TGC_INTERNAL_MAGIC;
01631
01632
01633 ntohd( (unsigned char *)vec, ep->ext_buf, 3*6 );
01634
01635
01636 MAT4X3PNT( tip->v, mat, &vec[0*3] );
01637 MAT4X3VEC( tip->h, mat, &vec[1*3] );
01638 MAT4X3VEC( tip->a, mat, &vec[2*3] );
01639 MAT4X3VEC( tip->b, mat, &vec[3*3] );
01640 MAT4X3VEC( tip->c, mat, &vec[4*3] );
01641 MAT4X3VEC( tip->d, mat, &vec[5*3] );
01642
01643 return(0);
01644 }
01645
01646
01647
01648
01649 int
01650 rt_tgc_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01651 {
01652 struct rt_tgc_internal *tip;
01653 fastf_t vec[3*6];
01654
01655 RT_CK_DB_INTERNAL(ip);
01656 if( ip->idb_type != ID_TGC && ip->idb_type != ID_REC ) return(-1);
01657 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01658 RT_TGC_CK_MAGIC(tip);
01659
01660 BU_CK_EXTERNAL(ep);
01661 ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * 3*6;
01662 ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "tgc external");
01663
01664
01665 VSCALE( &vec[0*3], tip->v, local2mm );
01666 VSCALE( &vec[1*3], tip->h, local2mm );
01667 VSCALE( &vec[2*3], tip->a, local2mm );
01668 VSCALE( &vec[3*3], tip->b, local2mm );
01669 VSCALE( &vec[4*3], tip->c, local2mm );
01670 VSCALE( &vec[5*3], tip->d, local2mm );
01671
01672
01673 htond( ep->ext_buf, (unsigned char *)vec, 3*6 );
01674
01675 return(0);
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685 int
01686 rt_tgc_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01687 {
01688 register struct rt_tgc_internal *tip =
01689 (struct rt_tgc_internal *)ip->idb_ptr;
01690 char buf[256];
01691 double angles[5];
01692 vect_t unitv;
01693 fastf_t Hmag;
01694
01695 RT_TGC_CK_MAGIC(tip);
01696 bu_vls_strcat( str, "truncated general cone (TGC)\n");
01697
01698 sprintf(buf, "\tV (%g, %g, %g)\n",
01699 INTCLAMP(tip->v[X] * mm2local),
01700 INTCLAMP(tip->v[Y] * mm2local),
01701 INTCLAMP(tip->v[Z] * mm2local) );
01702 bu_vls_strcat( str, buf );
01703
01704 sprintf(buf, "\tTop (%g, %g, %g)\n",
01705 INTCLAMP((tip->v[X] + tip->h[X]) * mm2local),
01706 INTCLAMP((tip->v[Y] + tip->h[Y]) * mm2local),
01707 INTCLAMP((tip->v[Z] + tip->h[Z]) * mm2local) );
01708 bu_vls_strcat( str, buf );
01709
01710 Hmag = MAGNITUDE(tip->h);
01711 sprintf(buf, "\tH (%g, %g, %g) mag=%g\n",
01712 INTCLAMP(tip->h[X] * mm2local),
01713 INTCLAMP(tip->h[Y] * mm2local),
01714 INTCLAMP(tip->h[Z] * mm2local),
01715 INTCLAMP(Hmag * mm2local) );
01716 bu_vls_strcat( str, buf );
01717 if( Hmag < VDIVIDE_TOL ) {
01718 bu_vls_strcat( str, "H vector is zero!\n");
01719 } else {
01720 register double f = 1/Hmag;
01721 VSCALE( unitv, tip->h, f );
01722 rt_find_fallback_angle( angles, unitv );
01723 rt_pr_fallback_angle( str, "\tH", angles );
01724 }
01725
01726 sprintf(buf, "\tA (%g, %g, %g) mag=%g\n",
01727 INTCLAMP(tip->a[X] * mm2local),
01728 INTCLAMP(tip->a[Y] * mm2local),
01729 INTCLAMP(tip->a[Z] * mm2local),
01730 INTCLAMP(MAGNITUDE(tip->a) * mm2local) );
01731 bu_vls_strcat( str, buf );
01732
01733 sprintf(buf, "\tB (%g, %g, %g) mag=%g\n",
01734 INTCLAMP(tip->b[X] * mm2local),
01735 INTCLAMP(tip->b[Y] * mm2local),
01736 INTCLAMP(tip->b[Z] * mm2local),
01737 INTCLAMP(MAGNITUDE(tip->b) * mm2local) );
01738 bu_vls_strcat( str, buf );
01739
01740 sprintf(buf, "\tC (%g, %g, %g) mag=%g\n",
01741 INTCLAMP(tip->c[X] * mm2local),
01742 INTCLAMP(tip->c[Y] * mm2local),
01743 INTCLAMP(tip->c[Z] * mm2local),
01744 INTCLAMP(MAGNITUDE(tip->c) * mm2local) );
01745 bu_vls_strcat( str, buf );
01746
01747 sprintf(buf, "\tD (%g, %g, %g) mag=%g\n",
01748 INTCLAMP(tip->d[X] * mm2local),
01749 INTCLAMP(tip->d[Y] * mm2local),
01750 INTCLAMP(tip->d[Z] * mm2local),
01751 INTCLAMP(MAGNITUDE(tip->d) * mm2local) );
01752 bu_vls_strcat( str, buf );
01753
01754 VCROSS( unitv, tip->c, tip->d );
01755 VUNITIZE( unitv );
01756 rt_find_fallback_angle( angles, unitv );
01757 rt_pr_fallback_angle( str, "\tAxB", angles );
01758
01759 return(0);
01760 }
01761
01762
01763
01764
01765
01766
01767 void
01768 rt_tgc_ifree(struct rt_db_internal *ip)
01769 {
01770 RT_CK_DB_INTERNAL(ip);
01771 bu_free( ip->idb_ptr, "tgc ifree" );
01772 ip->idb_ptr = GENPTR_NULL;
01773 }
01774
01775
01776
01777
01778 int
01779 rt_tgc_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01780 {
01781 LOCAL struct rt_tgc_internal *tip;
01782 register int i;
01783 LOCAL fastf_t top[16*3];
01784 LOCAL fastf_t bottom[16*3];
01785 LOCAL vect_t work;
01786
01787 RT_CK_DB_INTERNAL(ip);
01788 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01789 RT_TGC_CK_MAGIC(tip);
01790
01791 rt_ell_16pts( bottom, tip->v, tip->a, tip->b );
01792 VADD2( work, tip->v, tip->h );
01793 rt_ell_16pts( top, work, tip->c, tip->d );
01794
01795
01796 RT_ADD_VLIST( vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
01797 for( i=0; i<16; i++ ) {
01798 RT_ADD_VLIST( vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
01799 }
01800
01801
01802 RT_ADD_VLIST( vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
01803 for( i=0; i<16; i++ ) {
01804 RT_ADD_VLIST( vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
01805 }
01806
01807
01808 for( i=0; i<16; i += 4 ) {
01809 RT_ADD_VLIST( vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
01810 RT_ADD_VLIST( vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
01811 }
01812 return(0);
01813 }
01814
01815
01816
01817
01818
01819
01820 void
01821 rt_tgc_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
01822 {
01823 register struct tgc_specific *tgc =
01824 (struct tgc_specific *)stp->st_specific;
01825 fastf_t R, Q, R2, Q2;
01826 mat_t M, dN, mtmp;
01827 vect_t gradf, tmp, u, v;
01828 fastf_t a, b, c, scale;
01829 vect_t vec1, vec2;
01830
01831 if( hitp->hit_surfno != TGC_NORM_BODY ) {
01832
01833 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
01834 cvp->crv_c1 = cvp->crv_c2 = 0;
01835 return;
01836 }
01837
01838 R = 1 + tgc->tgc_CdAm1 * hitp->hit_vpriv[Z];
01839 Q = 1 + tgc->tgc_DdBm1 * hitp->hit_vpriv[Z];
01840 R2 = R*R;
01841 Q2 = Q*Q;
01842
01843
01844
01845
01846
01847
01848 MAT_IDN( dN );
01849 dN[0] = Q2;
01850 dN[2] = dN[8] = 2.0*Q*tgc->tgc_DdBm1 * hitp->hit_vpriv[X];
01851 dN[5] = R2;
01852 dN[6] = dN[9] = 2.0*R*tgc->tgc_CdAm1 * hitp->hit_vpriv[Y];
01853 dN[10] = tgc->tgc_DdBm1*tgc->tgc_DdBm1 * hitp->hit_vpriv[X]*hitp->hit_vpriv[X]
01854 + tgc->tgc_CdAm1*tgc->tgc_CdAm1 * hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y]
01855 - tgc->tgc_DdBm1*tgc->tgc_DdBm1 * R2
01856 - tgc->tgc_CdAm1*tgc->tgc_CdAm1 * Q2
01857 - 4.0*tgc->tgc_CdAm1*tgc->tgc_DdBm1 * R*Q;
01858
01859
01860 bn_mat_mul( mtmp, dN, tgc->tgc_ScShR );
01861 bn_mat_mul( M, tgc->tgc_invRtShSc, mtmp );
01862
01863
01864 gradf[X] = Q2 * hitp->hit_vpriv[X];
01865 gradf[Y] = R2 * hitp->hit_vpriv[Y];
01866 gradf[Z] = (hitp->hit_vpriv[X]*hitp->hit_vpriv[X] - R2) * Q * tgc->tgc_DdBm1 +
01867 (hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y] - Q2) * R * tgc->tgc_CdAm1;
01868 MAT4X3VEC( tmp, tgc->tgc_invRtShSc, gradf );
01869 scale = -1.0 / MAGNITUDE(tmp);
01870
01871
01872
01873
01874
01875
01876 bn_vec_ortho( u, hitp->hit_normal );
01877 VCROSS( v, hitp->hit_normal, u );
01878
01879
01880 MAT4X3VEC( tmp, M, u );
01881 a = VDOT(u, tmp) * scale;
01882 b = VDOT(v, tmp) * scale;
01883 MAT4X3VEC( tmp, M, v );
01884 c = VDOT(v, tmp) * scale;
01885
01886 bn_eigen2x2( &cvp->crv_c1, &cvp->crv_c2, vec1, vec2, a, b, c );
01887 VCOMB2( cvp->crv_pdir, vec1[X], u, vec1[Y], v );
01888 VUNITIZE( cvp->crv_pdir );
01889 }
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901 struct tgc_pts
01902 {
01903 point_t pt;
01904 vect_t tan_axb;
01905 struct vertex *v;
01906 char dont_use;
01907 };
01908
01909 #define MAX_RATIO 10.0
01910
01911
01912 int
01913 rt_tgc_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01914 {
01915 struct shell *s;
01916 struct faceuse *fu,*fu_top,*fu_base;
01917 struct rt_tgc_internal *tip;
01918 fastf_t radius;
01919 fastf_t max_radius,min_radius;
01920 fastf_t h,a,b,c,d;
01921 fastf_t inv_length;
01922 vect_t unit_a,unit_b,unit_c,unit_d;
01923 fastf_t rel,abs,norm;
01924 fastf_t alpha_tol;
01925 fastf_t abs_tol;
01926 int nells;
01927 int nsegs;
01928 vect_t *A;
01929 vect_t *B;
01930 fastf_t *factors;
01931 vect_t vtmp;
01932 vect_t normal;
01933 vect_t rev_norm;
01934 struct tgc_pts **pts;
01935 struct bu_ptbl verts;
01936 struct bu_ptbl faces;
01937 struct vertex **v[3];
01938
01939 int i;
01940
01941 RT_CK_DB_INTERNAL(ip);
01942 tip = (struct rt_tgc_internal *)ip->idb_ptr;
01943 RT_TGC_CK_MAGIC(tip);
01944
01945 if( ttol->abs > 0.0 && ttol->abs < tol->dist )
01946 {
01947 bu_log( "WARNING: tesselation tolerance is %fmm while calculational tolerance is %fmm\n",
01948 ttol->abs , tol->dist );
01949 bu_log( "Cannot tesselate a TGC to finer tolerance than the calculational tolerance\n" );
01950 abs_tol = tol->dist;
01951 } else {
01952 abs_tol = ttol->abs;
01953 }
01954
01955 h = MAGNITUDE( tip->h );
01956 a = MAGNITUDE( tip->a );
01957 if( 2.0*a <= tol->dist )
01958 a = 0.0;
01959 b = MAGNITUDE( tip->b );
01960 if( 2.0*b <= tol->dist )
01961 b = 0.0;
01962 c = MAGNITUDE( tip->c );
01963 if( 2.0*c <= tol->dist )
01964 c = 0.0;
01965 d = MAGNITUDE( tip->d );
01966 if( 2.0*d <= tol->dist )
01967 d = 0.0;
01968
01969 if( a == 0.0 && b == 0.0 && (c == 0.0 || d == 0.0) )
01970 {
01971 bu_log( "Illegal TGC a, b, and c or d less than tolerance\n" );
01972 return( -1);
01973 }
01974 else if( c == 0.0 && d == 0.0 && (a == 0.0 || b == 0.0 ) )
01975 {
01976 bu_log( "Illegal TGC c, d, and a or b less than tolerance\n" );
01977 return( -1 );
01978 }
01979
01980 if( a > 0.0 )
01981 {
01982 inv_length = 1.0/a;
01983 VSCALE( unit_a, tip->a, inv_length );
01984 }
01985 if( b > 0.0 )
01986 {
01987 inv_length = 1.0/b;
01988 VSCALE( unit_b, tip->b, inv_length );
01989 }
01990 if( c > 0.0 )
01991 {
01992 inv_length = 1.0/c;
01993 VSCALE( unit_c, tip->c, inv_length );
01994 }
01995 if( d > 0.0 )
01996 {
01997 inv_length = 1.0/d;
01998 VSCALE( unit_d, tip->d, inv_length );
01999 }
02000
02001
02002 radius = h/2.0;
02003 max_radius = 0.0;
02004 if( a > max_radius )
02005 max_radius = a;
02006 if( b > max_radius )
02007 max_radius = b;
02008 if( c > max_radius )
02009 max_radius = c;
02010 if( d > max_radius )
02011 max_radius = d;
02012
02013 if( max_radius > radius )
02014 radius = max_radius;
02015
02016 min_radius = MAX_FASTF;
02017 if( a < min_radius && a > 0.0 )
02018 min_radius = a;
02019 if( b < min_radius && b > 0.0 )
02020 min_radius = b;
02021 if( c < min_radius && c > 0.0 )
02022 min_radius = c;
02023 if( d < min_radius && d > 0.0 )
02024 min_radius = d;
02025
02026 if( abs_tol <= 0.0 && ttol->rel <= 0.0 && ttol->norm <= 0.0 )
02027 {
02028
02029 if( (radius * 0.2) < max_radius )
02030 alpha_tol = 2.0 * acos( 1.0 - 2.0 * radius * 0.1 / max_radius );
02031 else
02032 alpha_tol = bn_halfpi;
02033 }
02034 else
02035 {
02036 if( abs_tol > 0.0 )
02037 abs = 2.0 * acos( 1.0 - abs_tol/max_radius );
02038 else
02039 abs = bn_halfpi;
02040
02041 if( ttol->rel > 0.0 )
02042 {
02043 if( ttol->rel * 2.0 * radius < max_radius )
02044 rel = 2.0 * acos( 1.0 - ttol->rel * 2.0 * radius/max_radius );
02045 else
02046 rel = bn_halfpi;
02047 }
02048 else
02049 rel = bn_halfpi;
02050
02051 if( ttol->norm > 0.0 )
02052 {
02053 fastf_t norm_top,norm_bot;
02054
02055 if( a<b )
02056 norm_bot = 2.0 * atan( tan( ttol->norm ) * (a/b) );
02057 else
02058 norm_bot = 2.0 * atan( tan( ttol->norm ) * (b/a) );
02059
02060 if( c<d )
02061 norm_top = 2.0 * atan( tan( ttol->norm ) * (c/d) );
02062 else
02063 norm_top = 2.0 * atan( tan( ttol->norm ) * (d/c) );
02064
02065 if( norm_bot < norm_top )
02066 norm = norm_bot;
02067 else
02068 norm = norm_top;
02069 }
02070 else
02071 norm = bn_halfpi;
02072
02073 if( abs < rel )
02074 alpha_tol = abs;
02075 else
02076 alpha_tol = rel;
02077 if( norm < alpha_tol )
02078 alpha_tol = norm;
02079 }
02080
02081
02082 nsegs = (int)(bn_halfpi / alpha_tol + 0.9999);
02083 if( nsegs < 2 )
02084 nsegs = 2;
02085
02086
02087 nsegs *= 4;
02088
02089
02090 {
02091 fastf_t ratios[4],max_ratio;
02092 fastf_t new_ratio = 0;
02093 int which_ratio;
02094 fastf_t len_ha,len_hb;
02095 vect_t ha,hb;
02096 fastf_t ang;
02097 fastf_t sin_ang,cos_ang,cos_m_1_sq, sin_sq;
02098 fastf_t len_A, len_B, len_C, len_D;
02099 int bot_ell=0, top_ell=1;
02100 int reversed=0;
02101
02102 nells = 2;
02103
02104 max_ratio = MAX_RATIO + 1.0;
02105
02106 factors = (fastf_t *)bu_malloc( nells*sizeof( fastf_t ), "factors" );
02107 A = (vect_t *)bu_malloc( nells*sizeof( vect_t ), "A vectors" );
02108 B = (vect_t *)bu_malloc( nells*sizeof( vect_t ), "B vectors" );
02109
02110 factors[bot_ell] = 0.0;
02111 factors[top_ell] = 1.0;
02112 VMOVE( A[bot_ell], tip->a );
02113 VMOVE( A[top_ell], tip->c );
02114 VMOVE( B[bot_ell], tip->b );
02115 VMOVE( B[top_ell], tip->d );
02116
02117
02118 VCROSS( vtmp , A[0] , B[0] );
02119 if( VDOT( vtmp , tip->h ) < 0.0 )
02120 {
02121 VMOVE( A[bot_ell], tip->b );
02122 VMOVE( A[top_ell], tip->d );
02123 VMOVE( B[bot_ell], tip->a );
02124 VMOVE( B[top_ell], tip->c );
02125 reversed = 1;
02126 }
02127 ang = 2.0*bn_pi/((double)nsegs);
02128 sin_ang = sin( ang );
02129 cos_ang = cos( ang );
02130 cos_m_1_sq = (cos_ang - 1.0)*(cos_ang - 1.0);
02131 sin_sq = sin_ang*sin_ang;
02132
02133 VJOIN2( ha, tip->h, 1.0, tip->c, -1.0, tip->a )
02134 VJOIN2( hb, tip->h, 1.0, tip->d, -1.0, tip->b )
02135 len_ha = MAGNITUDE( ha );
02136 len_hb = MAGNITUDE( hb );
02137
02138 while( max_ratio > MAX_RATIO )
02139 {
02140 fastf_t tri_width;
02141
02142 len_A = MAGNITUDE( A[bot_ell] );
02143 if( 2.0*len_A <= tol->dist )
02144 len_A = 0.0;
02145 len_B = MAGNITUDE( B[bot_ell] );
02146 if( 2.0*len_B <= tol->dist )
02147 len_B = 0.0;
02148 len_C = MAGNITUDE( A[top_ell] );
02149 if( 2.0*len_C <= tol->dist )
02150 len_C = 0.0;
02151 len_D = MAGNITUDE( B[top_ell] );
02152 if( 2.0*len_D <= tol->dist )
02153 len_D = 0.0;
02154
02155 if( (len_B > 0.0 && len_D > 0.0) ||
02156 (len_B > 0.0 && (len_D == 0.0 && len_C == 0.0 )) )
02157 {
02158 tri_width = sqrt( cos_m_1_sq*len_A*len_A + sin_sq*len_B*len_B );
02159 ratios[0] = (factors[top_ell] - factors[bot_ell])*len_ha
02160 /tri_width;
02161 }
02162 else
02163 ratios[0] = 0.0;
02164
02165 if( (len_A > 0.0 && len_C > 0.0) ||
02166 ( len_A > 0.0 && (len_C == 0.0 && len_D == 0.0)) )
02167 {
02168 tri_width = sqrt( sin_sq*len_A*len_A + cos_m_1_sq*len_B*len_B );
02169 ratios[1] = (factors[top_ell] - factors[bot_ell])*len_hb
02170 /tri_width;
02171 }
02172 else
02173 ratios[1] = 0.0;
02174
02175 if( (len_D > 0.0 && len_B > 0.0) ||
02176 (len_D > 0.0 && (len_A == 0.0 && len_B == 0.0)) )
02177 {
02178 tri_width = sqrt( cos_m_1_sq*len_C*len_C + sin_sq*len_D*len_D );
02179 ratios[2] = (factors[top_ell] - factors[bot_ell])*len_ha
02180 /tri_width;
02181 }
02182 else
02183 ratios[2] = 0.0;
02184
02185 if( (len_C > 0.0 && len_A > 0.0) ||
02186 (len_C > 0.0 && (len_A == 0.0 && len_B == 0.0)) )
02187 {
02188 tri_width = sqrt( sin_sq*len_C*len_C + cos_m_1_sq*len_D*len_D );
02189 ratios[3] = (factors[top_ell] - factors[bot_ell])*len_hb
02190 /tri_width;
02191 }
02192 else
02193 ratios[3] = 0.0;
02194
02195 which_ratio = -1;
02196 max_ratio = 0.0;
02197
02198 for( i=0 ; i<4 ; i++ )
02199 {
02200 if( ratios[i] > max_ratio )
02201 {
02202 max_ratio = ratios[i];
02203 which_ratio = i;
02204 }
02205 }
02206
02207 if( len_A == 0.0 && len_B == 0.0 && len_C == 0.0 && len_D == 0.0 )
02208 {
02209 if( top_ell == nells - 1 )
02210 {
02211 VMOVE( A[top_ell-1], A[top_ell] )
02212 VMOVE( B[top_ell-1], A[top_ell] )
02213 factors[top_ell-1] = factors[top_ell];
02214 }
02215 else if( bot_ell == 0 )
02216 {
02217 for( i=0 ; i<nells-1 ; i++ )
02218 {
02219 VMOVE( A[i], A[i+1] )
02220 VMOVE( B[i], B[i+1] )
02221 factors[i] = factors[i+1];
02222 }
02223 }
02224
02225 nells -= 1;
02226 break;
02227 }
02228
02229 if( max_ratio <= MAX_RATIO )
02230 break;
02231
02232 if( which_ratio == 0 || which_ratio == 1 )
02233 {
02234 new_ratio = MAX_RATIO/max_ratio;
02235 if( bot_ell == 0 && new_ratio > 0.5 )
02236 new_ratio = 0.5;
02237 }
02238 else if( which_ratio == 2 || which_ratio == 3 )
02239 {
02240 new_ratio = 1.0 - MAX_RATIO/max_ratio;
02241 if( top_ell == nells - 1 && new_ratio < 0.5 )
02242 new_ratio = 0.5;
02243 }
02244 else
02245 {
02246 bu_log( "rt_tgc_tess: Should never get here!!\n" );
02247 rt_bomb( "rt_tgc_tess: Should never get here!!\n" );
02248 }
02249
02250 nells++;
02251 factors = (fastf_t *)bu_realloc( factors, nells*sizeof( fastf_t ), "factors" );
02252 A = (vect_t *)bu_realloc( A, nells*sizeof( vect_t ), "A vectors" );
02253 B = (vect_t *)bu_realloc( B, nells*sizeof( vect_t ), "B vectors" );
02254
02255 for( i=nells-1 ; i>top_ell ; i-- )
02256 {
02257 factors[i] = factors[i-1];
02258 VMOVE( A[i], A[i-1] )
02259 VMOVE( B[i], B[i-1] )
02260 }
02261
02262 factors[top_ell] = factors[bot_ell] +
02263 new_ratio*(factors[top_ell+1] - factors[bot_ell]);
02264
02265 if( reversed )
02266 {
02267 VBLEND2( A[top_ell], (1.0-factors[top_ell]), tip->b, factors[top_ell], tip->d )
02268 VBLEND2( B[top_ell], (1.0-factors[top_ell]), tip->a, factors[top_ell], tip->c )
02269 }
02270 else
02271 {
02272 VBLEND2( A[top_ell], (1.0-factors[top_ell]), tip->a, factors[top_ell], tip->c )
02273 VBLEND2( B[top_ell], (1.0-factors[top_ell]), tip->b, factors[top_ell], tip->d )
02274 }
02275
02276 if( which_ratio == 0 || which_ratio == 1 )
02277 {
02278 top_ell++;
02279 bot_ell++;
02280 }
02281
02282 }
02283
02284 }
02285
02286
02287 pts = (struct tgc_pts **)bu_calloc( nells , sizeof( struct tgc_pts *) , "rt_tgc_tess: pts" );
02288 for( i=0 ; i<nells ; i++ )
02289 pts[i] = (struct tgc_pts *)bu_calloc( nsegs , sizeof( struct tgc_pts ) , "rt_tgc_tess: pts" );
02290
02291
02292 for( i=0 ; i<nells ; i++ )
02293 {
02294 fastf_t h_factor;
02295 int j;
02296
02297 h_factor = factors[i];
02298 for( j=0 ; j<nsegs ; j++ )
02299 {
02300 double alpha;
02301 double sin_alpha,cos_alpha;
02302
02303 alpha = bn_twopi * (double)(2*j+1)/(double)(2*nsegs);
02304 sin_alpha = sin( alpha );
02305 cos_alpha = cos( alpha );
02306
02307
02308 if( i == 0 && a == 0.0 && b == 0.0 )
02309 VMOVE( pts[i][j].pt , tip->v )
02310 else if( i == nells-1 && c == 0.0 && d == 0.0 )
02311 VADD2( pts[i][j].pt, tip->v, tip->h )
02312 else
02313 VJOIN3( pts[i][j].pt , tip->v , h_factor , tip->h , cos_alpha , A[i] , sin_alpha , B[i] )
02314
02315
02316 if( i == 0 && a == 0.0 && b == 0.0 )
02317 VCOMB2( pts[0][j].tan_axb, -sin_alpha, unit_c, cos_alpha, unit_d )
02318 else if( i == nells-1 && c == 0.0 && d == 0.0 )
02319 VCOMB2( pts[i][j].tan_axb, -sin_alpha, unit_a, cos_alpha, unit_b )
02320 else
02321 VCOMB2( pts[i][j].tan_axb , -sin_alpha , A[i] , cos_alpha , B[i] )
02322 }
02323 }
02324
02325
02326 for( i=0 ; i<nells ; i++ )
02327 {
02328 int j;
02329 point_t curr_pt;
02330 vect_t edge_vect;
02331
02332 if( i == 0 && (a == 0.0 || b == 0.0) )
02333 continue;
02334 else if( i == nells-1 && (c == 0.0 || d == 0.0) )
02335 continue;
02336
02337 VMOVE( curr_pt, pts[i][0].pt )
02338 for( j=1 ; j<nsegs ; j++ )
02339 {
02340 fastf_t edge_len_sq;
02341
02342 VSUB2( edge_vect, curr_pt, pts[i][j].pt )
02343 edge_len_sq = MAGSQ( edge_vect );
02344 if(edge_len_sq > tol->dist_sq )
02345 VMOVE( curr_pt, pts[i][j].pt )
02346 else
02347 {
02348
02349 pts[i][j].dont_use = 'n';
02350 }
02351 }
02352 }
02353
02354
02355 *r = nmg_mrsv( m );
02356 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
02357
02358 bu_ptbl_init( &verts , 64, " &verts ");
02359 bu_ptbl_init( &faces , 64, " &faces ");
02360
02361 if( a > 0.0 && b > 0.0 )
02362 {
02363 for( i=nsegs-1 ; i>=0 ; i-- )
02364 {
02365 if( !pts[0][i].dont_use )
02366 bu_ptbl_ins( &verts , (long *)&pts[0][i].v );
02367 }
02368
02369 if( BU_PTBL_END( &verts ) > 2 )
02370 {
02371 fu_base = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR( &verts ), BU_PTBL_END( &verts ) );
02372 bu_ptbl_ins( &faces , (long *)fu_base );
02373 }
02374 else
02375 fu_base = (struct faceuse *)NULL;
02376 }
02377 else
02378 fu_base = (struct faceuse *)NULL;
02379
02380
02381
02382 if( c > 0.0 && d > 0.0 )
02383 {
02384 bu_ptbl_reset( &verts );
02385 for( i=0 ; i<nsegs ; i++ )
02386 {
02387 if( !pts[nells-1][i].dont_use )
02388 bu_ptbl_ins( &verts , (long *)&pts[nells-1][i].v );
02389 }
02390
02391 if( BU_PTBL_END( &verts ) > 2 )
02392 {
02393 fu_top = nmg_cmface( s , (struct vertex ***)BU_PTBL_BASEADDR( &verts ), BU_PTBL_END( &verts ) );
02394 bu_ptbl_ins( &faces , (long *)fu_top );
02395 }
02396 else
02397 fu_top = (struct faceuse *)NULL;
02398 }
02399 else
02400 fu_top = (struct faceuse *)NULL;
02401
02402
02403 bu_ptbl_free( &verts );
02404
02405
02406 for( i=0 ; i<nells-1 ; i++ )
02407 {
02408 int j;
02409 struct vertex **curr_top;
02410 struct vertex **curr_bot;
02411
02412 curr_bot = &pts[i][0].v;
02413 curr_top = &pts[i+1][0].v;
02414 for( j=0 ; j<nsegs ; j++ )
02415 {
02416 int k;
02417
02418 k = j+1;
02419 if( k == nsegs )
02420 k = 0;
02421 if( i != 0 || a > 0.0 || b > 0.0 )
02422 {
02423 if( !pts[i][k].dont_use )
02424 {
02425 v[0] = curr_bot;
02426 v[1] = &pts[i][k].v;
02427 if( i+1 == nells-1 && c == 0.0 && d == 0.0 )
02428 v[2] = &pts[i+1][0].v;
02429 else
02430 v[2] = curr_top;
02431 fu = nmg_cmface( s , v , 3 );
02432 bu_ptbl_ins( &faces , (long *)fu );
02433 curr_bot = &pts[i][k].v;
02434 }
02435 }
02436
02437 if( i != nells-2 || c > 0.0 || d > 0.0 )
02438 {
02439 if( !pts[i+1][k].dont_use )
02440 {
02441 v[0] = &pts[i+1][k].v;
02442 v[1] = curr_top;
02443 if( i == 0 && a == 0.0 && b == 0.0 )
02444 v[2] = &pts[i][0].v;
02445 else
02446 v[2] = curr_bot;
02447 fu = nmg_cmface( s , v , 3 );
02448 bu_ptbl_ins( &faces , (long *)fu );
02449 curr_top = &pts[i+1][k].v;
02450 }
02451 }
02452 }
02453 }
02454
02455
02456 for( i=0 ; i<nells ; i++ )
02457 {
02458 int j;
02459
02460 for( j=0 ; j<nsegs ; j++ )
02461 {
02462 point_t pt_geom;
02463 double alpha;
02464 double sin_alpha,cos_alpha;
02465
02466 alpha = bn_twopi * (double)(2*j+1)/(double)(2*nsegs);
02467 sin_alpha = sin( alpha );
02468 cos_alpha = cos( alpha );
02469
02470
02471 if( i == 0 && a == 0.0 && b == 0.0 )
02472 {
02473 if( j == 0 )
02474 nmg_vertex_gv( pts[0][0].v, tip->v );
02475 }
02476 else if( i == nells-1 && c == 0.0 && d == 0.0 )
02477 {
02478 if( j == 0 )
02479 {
02480 VADD2( pt_geom, tip->v, tip->h );
02481 nmg_vertex_gv( pts[i][0].v , pt_geom );
02482 }
02483 }
02484 else if( pts[i][j].v )
02485 nmg_vertex_gv( pts[i][j].v , pts[i][j].pt );
02486
02487
02488 if( i == 0 && a == 0.0 && b == 0.0 )
02489 VCOMB2( pts[0][j].tan_axb, -sin_alpha, unit_c, cos_alpha, unit_d )
02490 else if( i == nells-1 && c == 0.0 && d == 0.0 )
02491 VCOMB2( pts[i][j].tan_axb, -sin_alpha, unit_a, cos_alpha, unit_b )
02492 else
02493 VCOMB2( pts[i][j].tan_axb , -sin_alpha , A[i] , cos_alpha , B[i] )
02494 }
02495 }
02496
02497
02498 for( i=0 ; i<BU_PTBL_END( &faces ) ; i++ )
02499 {
02500 fu = (struct faceuse *)BU_PTBL_GET( &faces , i );
02501 NMG_CK_FACEUSE( fu );
02502
02503 if( nmg_calc_face_g( fu ) )
02504 {
02505 bu_log( "rt_tess_tgc: failed to calculate plane equation\n" );
02506 nmg_pr_fu_briefly( fu, "" );
02507 return( -1 );
02508 }
02509 }
02510
02511
02512
02513 for( i=0 ; i<nells ; i++ )
02514 {
02515 int j,k;
02516
02517 k = i + 1;
02518 if( k == nells )
02519 k = i - 1;
02520
02521 for( j=0 ; j<nsegs ; j++ )
02522 {
02523 vect_t tan_h;
02524 struct vertexuse *vu;
02525
02526
02527 if( i == nells - 1 )
02528 {
02529 if( c == 0.0 && d == 0.0 )
02530 VSUB2( tan_h , pts[i][0].pt , pts[k][j].pt )
02531 else if( k == 0 && c == 0.0 && d == 0.0 )
02532 VSUB2( tan_h , pts[i][j].pt , pts[k][0].pt )
02533 else
02534 VSUB2( tan_h , pts[i][j].pt , pts[k][j].pt )
02535 }
02536 else if( i == 0 )
02537 {
02538 if( a == 0.0 && b == 0.0 )
02539 VSUB2( tan_h , pts[k][j].pt , pts[i][0].pt )
02540 else if( k == nells-1 && c == 0.0 && d == 0.0 )
02541 VSUB2( tan_h , pts[k][0].pt , pts[i][j].pt )
02542 else
02543 VSUB2( tan_h , pts[k][j].pt , pts[i][j].pt )
02544 }
02545 else if( k == 0 && a == 0.0 && b == 0.0 )
02546 VSUB2( tan_h , pts[k][0].pt , pts[i][j].pt )
02547 else if( k == nells-1 && c == 0.0 && d == 0.0 )
02548 VSUB2( tan_h , pts[k][0].pt , pts[i][j].pt )
02549 else
02550 VSUB2( tan_h , pts[k][j].pt , pts[i][j].pt )
02551
02552 VCROSS( normal , pts[i][j].tan_axb , tan_h );
02553 VUNITIZE( normal );
02554 VREVERSE( rev_norm , normal );
02555
02556 if( !(i == 0 && a == 0.0 && b == 0.0) &&
02557 !(i == nells-1 && c == 0.0 && d == 0.0 ) &&
02558 pts[i][j].v )
02559 {
02560 for( BU_LIST_FOR( vu , vertexuse , &pts[i][j].v->vu_hd ) )
02561 {
02562 NMG_CK_VERTEXUSE( vu );
02563
02564 fu = nmg_find_fu_of_vu( vu );
02565 NMG_CK_FACEUSE( fu );
02566
02567
02568 if( fu == fu_base || fu->fumate_p == fu_base ||
02569 fu == fu_top || fu->fumate_p == fu_top )
02570 continue;
02571
02572 if( fu->orientation == OT_SAME )
02573 nmg_vertexuse_nv( vu , normal );
02574 else if( fu->orientation == OT_OPPOSITE )
02575 nmg_vertexuse_nv( vu , rev_norm );
02576 }
02577 }
02578 }
02579 }
02580
02581
02582 bu_free( (char *)factors, "rt_tgc_tess: factors" );
02583 bu_free( (char *)A , "rt_tgc_tess: A" );
02584 bu_free( (char *)B , "rt_tgc_tess: B" );
02585 for( i=0 ; i<nells ; i++ )
02586 bu_free( (char *)pts[i] , "rt_tgc_tess: pts[i]" );
02587 bu_free( (char *)pts , "rt_tgc_tess: pts" );
02588
02589
02590 for( i=0 ; i<2 ; i++ )
02591 {
02592 struct loopuse *lu;
02593
02594 if( i == 0 )
02595 fu = fu_base;
02596 else
02597 fu = fu_top;
02598
02599 if( fu == (struct faceuse *)NULL )
02600 continue;
02601
02602 NMG_CK_FACEUSE( fu );
02603
02604 for( BU_LIST_FOR( lu , loopuse , &fu->lu_hd ) )
02605 {
02606 struct edgeuse *eu;
02607
02608 NMG_CK_LOOPUSE( lu );
02609
02610 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
02611 continue;
02612
02613 for( BU_LIST_FOR( eu , edgeuse , &lu->down_hd ) )
02614 {
02615 struct edge *e;
02616
02617 NMG_CK_EDGEUSE( eu );
02618 e = eu->e_p;
02619 NMG_CK_EDGE( e );
02620 e->is_real = 1;
02621 }
02622 }
02623 }
02624
02625 nmg_region_a( *r , tol );
02626
02627
02628 nmg_gluefaces( (struct faceuse **)BU_PTBL_BASEADDR( &faces) , BU_PTBL_END( &faces ), tol );
02629 bu_ptbl_free( &faces );
02630
02631 return( 0 );
02632 }
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652 int
02653 rt_tgc_tnurb(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct bn_tol *tol)
02654 {
02655 LOCAL struct rt_tgc_internal *tip;
02656
02657 struct shell *s;
02658 struct vertex *verts[2];
02659 struct vertex **vertp[4];
02660 struct faceuse * top_fu;
02661 struct faceuse * cyl_fu;
02662 struct faceuse * bot_fu;
02663 vect_t uvw;
02664 struct loopuse *lu;
02665 struct edgeuse *eu;
02666 struct edgeuse *top_eu;
02667 struct edgeuse *bot_eu;
02668
02669 mat_t mat;
02670 mat_t imat, omat, top_mat, bot_mat;
02671 vect_t anorm;
02672 vect_t bnorm;
02673 vect_t cnorm;
02674
02675
02676
02677
02678 RT_CK_DB_INTERNAL(ip);
02679 tip = (struct rt_tgc_internal *) ip->idb_ptr;
02680 RT_TGC_CK_MAGIC(tip);
02681
02682
02683
02684 *r = nmg_mrsv( m );
02685 s = BU_LIST_FIRST( shell, &(*r)->s_hd);
02686
02687
02688
02689
02690 MAT_IDN( omat );
02691 MAT_IDN( mat);
02692
02693 omat[0] = MAGNITUDE(tip->c);
02694 omat[5] = MAGNITUDE(tip->d);
02695 omat[3] = tip->v[0] + tip->h[0];
02696 omat[7] = tip->v[1] + tip->h[1];
02697 omat[11] = tip->v[2] + tip->h[2];
02698
02699 bn_mat_mul(imat, mat, omat);
02700
02701 VMOVE(anorm, tip->c);
02702 VMOVE(bnorm, tip->d);
02703 VCROSS(cnorm, tip->c, tip->d);
02704 VUNITIZE(anorm);
02705 VUNITIZE(bnorm);
02706 VUNITIZE(cnorm);
02707
02708 MAT_IDN( omat );
02709
02710 VMOVE( &omat[0], anorm);
02711 VMOVE( &omat[4], bnorm);
02712 VMOVE( &omat[8], cnorm);
02713
02714
02715 bn_mat_mul(top_mat, omat, imat);
02716
02717
02718
02719 verts[0] = verts[1] = NULL;
02720 vertp[0] = &verts[0];
02721 top_fu = nmg_cmface(s, vertp, 1);
02722
02723 lu = BU_LIST_FIRST( loopuse, &top_fu->lu_hd);
02724 NMG_CK_LOOPUSE(lu);
02725 eu= BU_LIST_FIRST( edgeuse, &lu->down_hd);
02726 NMG_CK_EDGEUSE(eu);
02727 top_eu = eu;
02728
02729 VSET( uvw, 0,0,0);
02730 nmg_vertexuse_a_cnurb( eu->vu_p, uvw);
02731 VSET( uvw, 1, 0, 0);
02732 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
02733 eu = BU_LIST_NEXT( edgeuse, &eu->l);
02734
02735
02736 nmg_tgc_disk( top_fu, top_mat, 0.0, 0 );
02737
02738
02739
02740 MAT_IDN( omat );
02741 MAT_IDN( mat);
02742
02743 omat[0] = MAGNITUDE(tip->a);
02744 omat[5] = MAGNITUDE(tip->b);
02745 omat[3] = tip->v[0];
02746 omat[7] = tip->v[1];
02747 omat[11] = tip->v[2];
02748
02749 bn_mat_mul(imat, mat, omat);
02750
02751 VMOVE(anorm, tip->a);
02752 VMOVE(bnorm, tip->b);
02753 VCROSS(cnorm, tip->a, tip->b);
02754 VUNITIZE(anorm);
02755 VUNITIZE(bnorm);
02756 VUNITIZE(cnorm);
02757
02758 MAT_IDN( omat );
02759
02760 VMOVE( &omat[0], anorm);
02761 VMOVE( &omat[4], bnorm);
02762 VMOVE( &omat[8], cnorm);
02763
02764 bn_mat_mul(bot_mat, omat, imat);
02765
02766
02767
02768 vertp[0] = &verts[1];
02769 bot_fu = nmg_cmface(s, vertp, 1);
02770
02771 lu = BU_LIST_FIRST( loopuse, &bot_fu->lu_hd);
02772 NMG_CK_LOOPUSE(lu);
02773 eu= BU_LIST_FIRST( edgeuse, &lu->down_hd);
02774 NMG_CK_EDGEUSE(eu);
02775 bot_eu = eu;
02776
02777 VSET( uvw, 0,0,0);
02778 nmg_vertexuse_a_cnurb( eu->vu_p, uvw);
02779 VSET( uvw, 1, 0, 0);
02780 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
02781
02782
02783 nmg_tgc_disk( bot_fu, bot_mat, 0.0, 1 );
02784
02785
02786
02787 vertp[0] = &verts[0];
02788 vertp[1] = &verts[0];
02789 vertp[2] = &verts[1];
02790 vertp[3] = &verts[1];
02791 cyl_fu = nmg_cmface(s, vertp, 4);
02792
02793 nmg_tgc_nurb_cyl( cyl_fu, top_mat, bot_mat);
02794
02795
02796 lu = BU_LIST_FIRST( loopuse, &cyl_fu->lu_hd);
02797
02798 eu= BU_LIST_FIRST( edgeuse, &lu->down_hd);
02799
02800 nmg_je( top_eu, eu );
02801
02802 eu= BU_LIST_LAST( edgeuse, &lu->down_hd);
02803 eu= BU_LIST_LAST( edgeuse, &eu->l);
02804
02805 nmg_je( bot_eu, eu );
02806 nmg_region_a( *r,tol);
02807
02808 return( 0 );
02809 }
02810
02811
02812 #define RAT .707107
02813
02814 fastf_t nmg_tgc_unitcircle[36] = {
02815 1.0, 0.0, 0.0, 1.0,
02816 RAT, -RAT, 0.0, RAT,
02817 0.0, -1.0, 0.0, 1.0,
02818 -RAT, -RAT, 0.0, RAT,
02819 -1.0, 0.0, 0.0, 1.0,
02820 -RAT, RAT, 0.0, RAT,
02821 0.0, 1.0, 0.0, 1.0,
02822 RAT, RAT, 0.0, RAT,
02823 1.0, 0.0, 0.0, 1.0
02824 };
02825
02826 fastf_t nmg_uv_unitcircle[27] = {
02827 1.0, .5, 1.0,
02828 RAT, RAT, RAT,
02829 .5, 1.0, 1.0,
02830 0.0, RAT, RAT,
02831 0.0, .5, 1.0,
02832 0.0, 0.0, RAT,
02833 .5, 0.0, 1.0,
02834 RAT, 0.0, RAT,
02835 1.0, .5, 1.0
02836 };
02837
02838 static void
02839 nmg_tgc_disk(struct faceuse *fu, fastf_t *rmat, fastf_t height, int flip)
02840 {
02841 struct face_g_snurb * fg;
02842 struct loopuse * lu;
02843 struct edgeuse * eu;
02844 struct edge_g_cnurb * eg;
02845 fastf_t *mptr;
02846 int i;
02847 vect_t vect;
02848 point_t point;
02849
02850 nmg_face_g_snurb( fu,
02851 2, 2,
02852 4, 4,
02853 NULL, NULL,
02854 2, 2,
02855 RT_NURB_MAKE_PT_TYPE(3, 2, 0),
02856 NULL );
02857
02858 fg = fu->f_p->g.snurb_p;
02859
02860
02861 fg->u.knots[0] = 0.0;
02862 fg->u.knots[1] = 0.0;
02863 fg->u.knots[2] = 1.0;
02864 fg->u.knots[3] = 1.0;
02865
02866 fg->v.knots[0] = 0.0;
02867 fg->v.knots[1] = 0.0;
02868 fg->v.knots[2] = 1.0;
02869 fg->v.knots[3] = 1.0;
02870
02871 if(flip)
02872 {
02873 fg->ctl_points[0] = 1.;
02874 fg->ctl_points[1] = -1.;
02875 fg->ctl_points[2] = height;
02876
02877 fg->ctl_points[3] = -1;
02878 fg->ctl_points[4] = -1.;
02879 fg->ctl_points[5] = height;
02880
02881 fg->ctl_points[6] = 1.;
02882 fg->ctl_points[7] = 1.;
02883 fg->ctl_points[8] = height;
02884
02885 fg->ctl_points[9] = -1.;
02886 fg->ctl_points[10] = 1.;
02887 fg->ctl_points[11] = height;
02888 } else
02889 {
02890
02891 fg->ctl_points[0] = -1.;
02892 fg->ctl_points[1] = -1.;
02893 fg->ctl_points[2] = height;
02894
02895 fg->ctl_points[3] = 1;
02896 fg->ctl_points[4] = -1.;
02897 fg->ctl_points[5] = height;
02898
02899 fg->ctl_points[6] = -1.;
02900 fg->ctl_points[7] = 1.;
02901 fg->ctl_points[8] = height;
02902
02903 fg->ctl_points[9] = 1.;
02904 fg->ctl_points[10] = 1.;
02905 fg->ctl_points[11] = height;
02906 }
02907
02908
02909 mptr = fg->ctl_points;
02910
02911 i = fg->s_size[0] * fg->s_size[1];
02912
02913 for( ; i> 0; i--)
02914 {
02915 MAT4X3PNT(vect,rmat,mptr);
02916 mptr[0] = vect[0];
02917 mptr[1] = vect[1];
02918 mptr[2] = vect[2];
02919 mptr += 3;
02920 }
02921
02922 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd);
02923 NMG_CK_LOOPUSE(lu);
02924 eu= BU_LIST_FIRST( edgeuse, &lu->down_hd);
02925 NMG_CK_EDGEUSE(eu);
02926
02927
02928 if(!flip)
02929 {
02930 rt_nurb_s_eval( fu->f_p->g.snurb_p,
02931 nmg_uv_unitcircle[0], nmg_uv_unitcircle[1], point );
02932 nmg_vertex_gv( eu->vu_p->v_p, point );
02933 } else
02934 {
02935 rt_nurb_s_eval( fu->f_p->g.snurb_p,
02936 nmg_uv_unitcircle[12], nmg_uv_unitcircle[13], point );
02937 nmg_vertex_gv( eu->vu_p->v_p, point );
02938 }
02939
02940 nmg_edge_g_cnurb(eu, 3, 12, NULL, 9, RT_NURB_MAKE_PT_TYPE(3,3,1),
02941 NULL);
02942
02943 eg = eu->g.cnurb_p;
02944 eg->order = 3;
02945
02946 eg->k.knots[0] = 0.0;
02947 eg->k.knots[1] = 0.0;
02948 eg->k.knots[2] = 0.0;
02949 eg->k.knots[3] = .25;
02950 eg->k.knots[4] = .25;
02951 eg->k.knots[5] = .5;
02952 eg->k.knots[6] = .5;
02953 eg->k.knots[7] = .75;
02954 eg->k.knots[8] = .75;
02955 eg->k.knots[9] = 1.0;
02956 eg->k.knots[10] = 1.0;
02957 eg->k.knots[11] = 1.0;
02958
02959 if( !flip )
02960 {
02961 for( i = 0; i < 27; i++)
02962 eg->ctl_points[i] = nmg_uv_unitcircle[i];
02963 }
02964 else
02965 {
02966
02967 VSET(&eg->ctl_points[0], 0.0, .5, 1.0);
02968 VSET(&eg->ctl_points[3], 0.0, 0.0, RAT);
02969 VSET(&eg->ctl_points[6], 0.5, 0.0, 1.0);
02970 VSET(&eg->ctl_points[9], RAT, 0.0, RAT);
02971 VSET(&eg->ctl_points[12], 1.0, .5, 1.0);
02972 VSET(&eg->ctl_points[15], RAT,RAT, RAT);
02973 VSET(&eg->ctl_points[18], .5, 1.0, 1.0);
02974 VSET(&eg->ctl_points[21], 0.0, RAT, RAT);
02975 VSET(&eg->ctl_points[24], 0.0, .5, 1.0);
02976 }
02977 }
02978
02979
02980
02981
02982
02983
02984
02985 static void
02986 nmg_tgc_nurb_cyl(struct faceuse *fu, fastf_t *top_mat, fastf_t *bot_mat)
02987 {
02988 struct face_g_snurb * fg;
02989 struct loopuse * lu;
02990 struct edgeuse * eu;
02991 fastf_t * mptr;
02992 int i;
02993 hvect_t vect;
02994 point_t uvw;
02995 point_t point;
02996 hvect_t hvect;
02997
02998 nmg_face_g_snurb( fu,
02999 3, 2,
03000 12, 4,
03001 NULL, NULL,
03002 2, 9,
03003 RT_NURB_MAKE_PT_TYPE(4,3,1),
03004 NULL );
03005
03006 fg = fu->f_p->g.snurb_p;
03007
03008 fg->v.knots[0] = 0.0;
03009 fg->v.knots[1] = 0.0;
03010 fg->v.knots[2] = 1.0;
03011 fg->v.knots[3] = 1.0;
03012
03013 fg->u.knots[0] = 0.0;
03014 fg->u.knots[1] = 0.0;
03015 fg->u.knots[2] = 0.0;
03016 fg->u.knots[3] = .25;
03017 fg->u.knots[4] = .25;
03018 fg->u.knots[5] = .5;
03019 fg->u.knots[6] = .5;
03020 fg->u.knots[7] = .75;
03021 fg->u.knots[8] = .75;
03022 fg->u.knots[9] = 1.0;
03023 fg->u.knots[10] = 1.0;
03024 fg->u.knots[11] = 1.0;
03025
03026 mptr = fg->ctl_points;
03027
03028 for(i = 0; i < 9; i++)
03029 {
03030 MAT4X4PNT(vect, top_mat, &nmg_tgc_unitcircle[i*4]);
03031 mptr[0] = vect[0];
03032 mptr[1] = vect[1];
03033 mptr[2] = vect[2];
03034 mptr[3] = vect[3];
03035 mptr += 4;
03036 }
03037
03038 for(i = 0; i < 9; i++)
03039 {
03040 MAT4X4PNT(vect, bot_mat, &nmg_tgc_unitcircle[i*4]);
03041 mptr[0] = vect[0];
03042 mptr[1] = vect[1];
03043 mptr[2] = vect[2];
03044 mptr[3] = vect[3];
03045 mptr += 4;
03046 }
03047
03048
03049
03050 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
03051 NMG_CK_LOOPUSE(lu);
03052 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd);
03053 NMG_CK_EDGEUSE(eu);
03054
03055
03056
03057 rt_nurb_s_eval( fg, 0.0, 0.0, hvect);
03058 HDIVIDE( point, hvect );
03059 nmg_vertex_gv( eu->vu_p->v_p, point );
03060
03061 VSET( uvw, 0, 0, 0);
03062 nmg_vertexuse_a_cnurb( eu->vu_p, uvw );
03063 VSET( uvw, 1, 0, 0);
03064 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
03065 eu = BU_LIST_NEXT( edgeuse, &eu->l);
03066
03067 VSET( uvw, 1, 0, 0);
03068 nmg_vertexuse_a_cnurb( eu->vu_p, uvw );
03069 VSET( uvw, 1, 1, 0);
03070 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
03071 eu = BU_LIST_NEXT( edgeuse, &eu->l);
03072
03073 VSET( uvw, 1, 1, 0);
03074 nmg_vertexuse_a_cnurb( eu->vu_p, uvw );
03075 VSET( uvw, 0, 1, 0);
03076 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
03077
03078 rt_nurb_s_eval( fg, 1., 1., hvect);
03079 HDIVIDE( point, hvect);
03080 nmg_vertex_gv( eu->vu_p->v_p, point );
03081
03082 eu = BU_LIST_NEXT( edgeuse, &eu->l);
03083
03084 VSET( uvw, 0, 1, 0);
03085 nmg_vertexuse_a_cnurb( eu->vu_p, uvw );
03086 VSET( uvw, 0, 0, 0);
03087 nmg_vertexuse_a_cnurb( eu->eumate_p->vu_p, uvw );
03088 eu = BU_LIST_NEXT( edgeuse, &eu->l);
03089
03090
03091
03092 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
03093 NMG_CK_LOOPUSE(lu);
03094 eu = BU_LIST_FIRST( edgeuse, &lu->down_hd);
03095 NMG_CK_EDGEUSE(eu);
03096
03097 for( i = 0; i < 4; i++)
03098 {
03099 nmg_edge_g_cnurb_plinear(eu);
03100 eu = BU_LIST_NEXT(edgeuse, &eu->l);
03101 }
03102 }
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112