00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 #ifndef lint
00169 static const char RCSrpc[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_rpc.c,v 14.13 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00170 #endif
00171
00172 #include "common.h"
00173
00174 #include <stdlib.h>
00175 #include <stddef.h>
00176 #include <stdio.h>
00177 #ifdef HAVE_STRING_H
00178 # include <string.h>
00179 #else
00180 # include <strings.h>
00181 #endif
00182 #include <math.h>
00183
00184 #include "machine.h"
00185 #include "vmath.h"
00186 #include "db.h"
00187 #include "nmg.h"
00188 #include "raytrace.h"
00189 #include "rtgeom.h"
00190 #include "./debug.h"
00191
00192
00193 struct rpc_specific {
00194 point_t rpc_V;
00195 vect_t rpc_Bunit;
00196 vect_t rpc_Hunit;
00197 vect_t rpc_Runit;
00198 fastf_t rpc_b;
00199 fastf_t rpc_inv_rsq;
00200 mat_t rpc_SoR;
00201 mat_t rpc_invRoS;
00202 };
00203
00204 const struct bu_structparse rt_rpc_parse[] = {
00205 { "%f", 3, "V", bu_offsetof(struct rt_rpc_internal, rpc_V[X]), BU_STRUCTPARSE_FUNC_NULL },
00206 { "%f", 3, "H", bu_offsetof(struct rt_rpc_internal, rpc_H[X]), BU_STRUCTPARSE_FUNC_NULL },
00207 { "%f", 3, "B", bu_offsetof(struct rt_rpc_internal, rpc_B[X]), BU_STRUCTPARSE_FUNC_NULL },
00208 { "%f", 1, "r", bu_offsetof(struct rt_rpc_internal, rpc_r), BU_STRUCTPARSE_FUNC_NULL },
00209 { {'\0','\0','\0','\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL }
00210 };
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 int
00228 rt_rpc_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00229 {
00230 struct rt_rpc_internal *xip;
00231 register struct rpc_specific *rpc;
00232 #ifndef NO_BOMBING_MACROS
00233 const struct bn_tol *tol = &rtip->rti_tol;
00234 #endif
00235 LOCAL fastf_t magsq_b, magsq_h, magsq_r;
00236 LOCAL fastf_t mag_b, mag_h, mag_r;
00237 LOCAL fastf_t f;
00238 LOCAL mat_t R;
00239 LOCAL mat_t Rinv;
00240 LOCAL mat_t S;
00241 LOCAL vect_t invsq;
00242
00243 RT_CK_DB_INTERNAL(ip);
00244 BN_CK_TOL(tol);
00245 xip = (struct rt_rpc_internal *)ip->idb_ptr;
00246 RT_RPC_CK_MAGIC(xip);
00247
00248
00249 mag_b = sqrt( magsq_b = MAGSQ( xip->rpc_B ) );
00250 mag_h = sqrt( magsq_h = MAGSQ( xip->rpc_H ) );
00251 mag_r = xip->rpc_r;
00252 magsq_r = mag_r * mag_r;
00253
00254
00255 if( NEAR_ZERO(mag_h, RT_LEN_TOL) || NEAR_ZERO(mag_b, RT_LEN_TOL)
00256 || NEAR_ZERO(mag_r, RT_LEN_TOL) ) {
00257 return(1);
00258 }
00259
00260
00261 f = VDOT( xip->rpc_B, xip->rpc_H ) / (mag_b * mag_h);
00262 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00263 return(1);
00264 }
00265
00266
00267
00268
00269 stp->st_id = ID_RPC;
00270 stp->st_meth = &rt_functab[ID_RPC];
00271
00272 BU_GETSTRUCT( rpc, rpc_specific );
00273 stp->st_specific = (genptr_t)rpc;
00274 rpc->rpc_b = mag_b;
00275 rpc->rpc_inv_rsq = 1 / magsq_r;
00276
00277
00278 VMOVE( rpc->rpc_Hunit, xip->rpc_H );
00279 VUNITIZE( rpc->rpc_Hunit );
00280 VMOVE( rpc->rpc_Bunit, xip->rpc_B );
00281 VUNITIZE( rpc->rpc_Bunit );
00282 VCROSS( rpc->rpc_Runit, rpc->rpc_Bunit, rpc->rpc_Hunit );
00283
00284 VMOVE( rpc->rpc_V, xip->rpc_V );
00285
00286
00287 MAT_IDN( R );
00288 VREVERSE( &R[0], rpc->rpc_Hunit );
00289 VMOVE( &R[4], rpc->rpc_Runit );
00290 VREVERSE( &R[8], rpc->rpc_Bunit );
00291 bn_mat_trn( Rinv, R );
00292
00293
00294 VSET( invsq, 1.0/magsq_h, 1.0/magsq_r, 1.0/magsq_b );
00295 MAT_IDN( S );
00296 S[ 0] = sqrt( invsq[0] );
00297 S[ 5] = sqrt( invsq[1] );
00298 S[10] = sqrt( invsq[2] );
00299
00300
00301 bn_mat_mul( rpc->rpc_SoR, S, R );
00302 bn_mat_mul( rpc->rpc_invRoS, Rinv, S );
00303
00304
00305
00306 VJOIN2( stp->st_center, rpc->rpc_V,
00307 mag_h / 2.0, rpc->rpc_Hunit,
00308 mag_b / 2.0, rpc->rpc_Bunit );
00309
00310 stp->st_bradius = 0.5 * sqrt(magsq_h + 4.0*magsq_r + magsq_b);
00311
00312 stp->st_aradius = stp->st_bradius;
00313
00314
00315 stp->st_min[X] = stp->st_center[X] - stp->st_bradius;
00316 stp->st_max[X] = stp->st_center[X] + stp->st_bradius;
00317 stp->st_min[Y] = stp->st_center[Y] - stp->st_bradius;
00318 stp->st_max[Y] = stp->st_center[Y] + stp->st_bradius;
00319 stp->st_min[Z] = stp->st_center[Z] - stp->st_bradius;
00320 stp->st_max[Z] = stp->st_center[Z] + stp->st_bradius;
00321
00322 return(0);
00323 }
00324
00325
00326
00327
00328 void
00329 rt_rpc_print(register const struct soltab *stp)
00330 {
00331 register const struct rpc_specific *rpc =
00332 (struct rpc_specific *)stp->st_specific;
00333
00334 VPRINT("V", rpc->rpc_V);
00335 VPRINT("Bunit", rpc->rpc_Bunit);
00336 VPRINT("Hunit", rpc->rpc_Hunit);
00337 VPRINT("Runit", rpc->rpc_Runit);
00338 bn_mat_print("S o R", rpc->rpc_SoR );
00339 bn_mat_print("invR o S", rpc->rpc_invRoS );
00340 }
00341
00342
00343 #define RPC_NORM_BODY (1)
00344 #define RPC_NORM_TOP (2)
00345 #define RPC_NORM_FRT (3)
00346 #define RPC_NORM_BACK (4)
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 int
00360 rt_rpc_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00361 {
00362 register struct rpc_specific *rpc =
00363 (struct rpc_specific *)stp->st_specific;
00364 LOCAL vect_t dprime;
00365 LOCAL vect_t pprime;
00366 LOCAL fastf_t k1, k2;
00367 LOCAL vect_t xlated;
00368 LOCAL struct hit hits[3];
00369 register struct hit *hitp;
00370
00371
00372 hitp = &hits[0];
00373
00374
00375 MAT4X3VEC( dprime, rpc->rpc_SoR, rp->r_dir );
00376 VSUB2( xlated, rp->r_pt, rpc->rpc_V );
00377 MAT4X3VEC( pprime, rpc->rpc_SoR, xlated );
00378
00379
00380 if ( !NEAR_ZERO(dprime[Y], RT_PCOEF_TOL) ) {
00381 FAST fastf_t a, b, c;
00382 FAST fastf_t disc;
00383
00384 a = dprime[Y] * dprime[Y];
00385 b = 2.0 * dprime[Y] * pprime[Y] - dprime[Z];
00386 c = pprime[Y] * pprime[Y] - pprime[Z] - 1;
00387 disc = b*b - 4 * a * c;
00388 if (disc <= 0)
00389 goto check_plates;
00390 disc = sqrt(disc);
00391
00392 k1 = (-b + disc) / (2.0 * a);
00393 k2 = (-b - disc) / (2.0 * a);
00394
00395
00396
00397
00398
00399 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00400 if( hitp->hit_vpriv[X] >= -1.0 && hitp->hit_vpriv[X] <= 0.0
00401 && hitp->hit_vpriv[Z] <= 0.0 ) {
00402 hitp->hit_magic = RT_HIT_MAGIC;
00403 hitp->hit_dist = k1;
00404 hitp->hit_surfno = RPC_NORM_BODY;
00405 hitp++;
00406 }
00407
00408 VJOIN1( hitp->hit_vpriv, pprime, k2, dprime );
00409 if( hitp->hit_vpriv[X] >= -1.0 && hitp->hit_vpriv[X] <= 0.0
00410 && hitp->hit_vpriv[Z] <= 0.0 ) {
00411 hitp->hit_magic = RT_HIT_MAGIC;
00412 hitp->hit_dist = k2;
00413 hitp->hit_surfno = RPC_NORM_BODY;
00414 hitp++;
00415 }
00416 } else if ( !NEAR_ZERO(dprime[Z], RT_PCOEF_TOL) ) {
00417 k1 = (pprime[Y] * pprime[Y] - pprime[Z] - 1.0) / dprime[Z];
00418 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00419 if( hitp->hit_vpriv[X] >= -1.0 && hitp->hit_vpriv[X] <= 0.0
00420 && hitp->hit_vpriv[Z] <= 0.0 ) {
00421 hitp->hit_magic = RT_HIT_MAGIC;
00422 hitp->hit_dist = k1;
00423 hitp->hit_surfno = RPC_NORM_BODY;
00424 hitp++;
00425 }
00426 }
00427
00428
00429
00430
00431
00432 check_plates:
00433
00434 if( hitp < &hits[2] && !NEAR_ZERO(dprime[X], RT_PCOEF_TOL) ) {
00435
00436 k1 = -pprime[X] / dprime[X];
00437 k2 = (-1.0 - pprime[X]) / dprime[X];
00438
00439 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00440 if( hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y]
00441 - hitp->hit_vpriv[Z] <= 1.0
00442 && hitp->hit_vpriv[Z] <= 0.0) {
00443 hitp->hit_magic = RT_HIT_MAGIC;
00444 hitp->hit_dist = k1;
00445 hitp->hit_surfno = RPC_NORM_FRT;
00446 hitp++;
00447 }
00448
00449 VJOIN1( hitp->hit_vpriv, pprime, k2, dprime );
00450 if( hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y]
00451 - hitp->hit_vpriv[Z] <= 1.0
00452 && hitp->hit_vpriv[Z] <= 0.0) {
00453 hitp->hit_magic = RT_HIT_MAGIC;
00454 hitp->hit_dist = k2;
00455 hitp->hit_surfno = RPC_NORM_BACK;
00456 hitp++;
00457 }
00458 }
00459
00460
00461 if( hitp == &hits[1] && !NEAR_ZERO(dprime[Z], RT_PCOEF_TOL) ) {
00462
00463 k1 = -pprime[Z] / dprime[Z];
00464
00465 VJOIN1( hitp->hit_vpriv, pprime, k1, dprime );
00466 if( hitp->hit_vpriv[X] >= -1.0 && hitp->hit_vpriv[X] <= 0.0
00467 && hitp->hit_vpriv[Y] >= -1.0
00468 && hitp->hit_vpriv[Y] <= 1.0 ) {
00469 hitp->hit_magic = RT_HIT_MAGIC;
00470 hitp->hit_dist = k1;
00471 hitp->hit_surfno = RPC_NORM_TOP;
00472 hitp++;
00473 }
00474 }
00475
00476 if( hitp != &hits[2] )
00477 return(0);
00478
00479 if( hits[0].hit_dist < hits[1].hit_dist ) {
00480
00481 register struct seg *segp;
00482
00483 RT_GET_SEG(segp, ap->a_resource);
00484 segp->seg_stp = stp;
00485 segp->seg_in = hits[0];
00486 segp->seg_out = hits[1];
00487 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00488 } else {
00489
00490 register struct seg *segp;
00491
00492 RT_GET_SEG(segp, ap->a_resource);
00493 segp->seg_stp = stp;
00494 segp->seg_in = hits[1];
00495 segp->seg_out = hits[0];
00496 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00497 }
00498 return(2);
00499 }
00500
00501 #define RT_RPC_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
00502
00503
00504
00505
00506
00507
00508 void
00509 rt_rpc_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00510
00511
00512
00513
00514
00515 {
00516 rt_vstub( stp, rp, segp, n, ap );
00517 }
00518
00519
00520
00521
00522
00523
00524 void
00525 rt_rpc_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00526 {
00527 vect_t can_normal;
00528 register struct rpc_specific *rpc =
00529 (struct rpc_specific *)stp->st_specific;
00530
00531 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00532 switch( hitp->hit_surfno ) {
00533 case RPC_NORM_BODY:
00534 VSET( can_normal, 0.0, hitp->hit_vpriv[Y], -0.5 );
00535 MAT4X3VEC( hitp->hit_normal, rpc->rpc_invRoS, can_normal );
00536 VUNITIZE( hitp->hit_normal );
00537 break;
00538 case RPC_NORM_TOP:
00539 VREVERSE( hitp->hit_normal, rpc->rpc_Bunit );
00540 break;
00541 case RPC_NORM_FRT:
00542 VREVERSE( hitp->hit_normal, rpc->rpc_Hunit );
00543 break;
00544 case RPC_NORM_BACK:
00545 VMOVE( hitp->hit_normal, rpc->rpc_Hunit );
00546 break;
00547 default:
00548 bu_log("rt_rpc_norm: surfno=%d bad\n", hitp->hit_surfno);
00549 break;
00550 }
00551 }
00552
00553
00554
00555
00556
00557
00558 void
00559 rt_rpc_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00560 {
00561 fastf_t zp1, zp2;
00562 register struct rpc_specific *rpc =
00563 (struct rpc_specific *)stp->st_specific;
00564
00565 switch( hitp->hit_surfno ) {
00566 case RPC_NORM_BODY:
00567
00568 VMOVE( cvp->crv_pdir, rpc->rpc_Hunit );
00569 cvp->crv_c1 = 0;
00570
00571 zp2 = 2 * rpc->rpc_b * rpc->rpc_inv_rsq;
00572 zp1 = zp2 * hitp->hit_point[Y];
00573 cvp->crv_c2 = zp2 / pow( (1 + zp1*zp1), 1.5);
00574 break;
00575 case RPC_NORM_BACK:
00576 case RPC_NORM_FRT:
00577 case RPC_NORM_TOP:
00578
00579 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00580 cvp->crv_c1 = cvp->crv_c2 = 0;
00581 break;
00582 }
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 void
00594 rt_rpc_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00595 {
00596 register struct rpc_specific *rpc =
00597 (struct rpc_specific *)stp->st_specific;
00598 LOCAL vect_t work;
00599 LOCAL vect_t pprime;
00600 FAST fastf_t len;
00601
00602
00603
00604
00605
00606 VSUB2( work, hitp->hit_point, rpc->rpc_V );
00607 MAT4X3VEC( pprime, rpc->rpc_SoR, work );
00608
00609 switch( hitp->hit_surfno ) {
00610 case RPC_NORM_BODY:
00611
00612 len = sqrt(pprime[Y]*pprime[Y] + pprime[Z]*pprime[Z]);
00613 uvp->uv_u = acos(pprime[Y]/len) * bn_invpi;
00614 uvp->uv_v = -pprime[X];
00615 break;
00616 case RPC_NORM_FRT:
00617 case RPC_NORM_BACK:
00618
00619 len = sqrt(pprime[Y]*pprime[Y] + pprime[Z]*pprime[Z]);
00620 uvp->uv_u = acos(pprime[Y]/len) * bn_invpi;
00621 uvp->uv_v = len;
00622 break;
00623 case RPC_NORM_TOP:
00624 uvp->uv_u = 1.0 - (pprime[Y] + 1.0)/2.0;
00625 uvp->uv_v = -pprime[X];
00626 break;
00627 }
00628
00629
00630 uvp->uv_du = uvp->uv_dv = 0;
00631 }
00632
00633
00634
00635
00636 void
00637 rt_rpc_free(register struct soltab *stp)
00638 {
00639 register struct rpc_specific *rpc =
00640 (struct rpc_specific *)stp->st_specific;
00641
00642 bu_free( (char *)rpc, "rpc_specific" );
00643 }
00644
00645
00646
00647
00648 int
00649 rt_rpc_class(void)
00650 {
00651 return(0);
00652 }
00653
00654
00655
00656
00657 int
00658 rt_rpc_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00659 {
00660 LOCAL struct rt_rpc_internal *xip;
00661 fastf_t *front;
00662 fastf_t *back;
00663 fastf_t b, dtol, f, h, ntol, rh;
00664 int i, n;
00665 LOCAL mat_t R;
00666 LOCAL mat_t invR;
00667 struct rt_pt_node *old, *pos, *pts;
00668 vect_t Bu, Hu, Ru;
00669
00670 RT_CK_DB_INTERNAL(ip);
00671 xip = (struct rt_rpc_internal *)ip->idb_ptr;
00672 RT_RPC_CK_MAGIC(xip);
00673
00674
00675 b = MAGNITUDE( xip->rpc_B );
00676 rh = xip->rpc_r;
00677 h = MAGNITUDE( xip->rpc_H );
00678
00679
00680 if( NEAR_ZERO(h, RT_LEN_TOL) || NEAR_ZERO(b, RT_LEN_TOL)
00681 || NEAR_ZERO(rh, RT_LEN_TOL) ) {
00682 bu_log("rt_rpc_plot(): zero length H, B, or rh\n");
00683 return(-2);
00684 }
00685
00686
00687 f = VDOT( xip->rpc_B, xip->rpc_H ) / (b * h);
00688 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00689 bu_log("rt_rpc_plot(): B not perpendicular to H, f=%f\n", f);
00690 return(-3);
00691 }
00692
00693
00694 VMOVE( Hu, xip->rpc_H );
00695 VUNITIZE( Hu );
00696 VMOVE( Bu, xip->rpc_B );
00697 VUNITIZE( Bu );
00698 VCROSS( Ru, Bu, Hu );
00699
00700
00701 MAT_IDN( R );
00702 VREVERSE( &R[0], Hu );
00703 VMOVE( &R[4], Ru );
00704 VREVERSE( &R[8], Bu );
00705 bn_mat_trn( invR, R );
00706
00707
00708
00709
00710 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 ) {
00711 dtol = 0.0;
00712 } else {
00713
00714 if (rh < b)
00715 dtol = ttol->rel * 2 * rh;
00716 else
00717 dtol = ttol->rel * 2 * b;
00718 }
00719 if( ttol->abs <= 0.0 ) {
00720 if( dtol <= 0.0 ) {
00721
00722 if (rh < b)
00723 dtol = 2 * 0.10 * rh;
00724 else
00725 dtol = 2 * 0.10 * b;
00726 } else {
00727
00728 }
00729 } else {
00730
00731 if( ttol->rel <= 0.0 || dtol > ttol->abs )
00732 dtol = ttol->abs;
00733 }
00734
00735
00736 if( ttol->norm > 0.0 )
00737 ntol = ttol->norm;
00738 else
00739
00740 ntol = bn_pi;
00741
00742 #if 1
00743
00744 pts = rt_ptalloc();
00745 pts->next = rt_ptalloc();
00746 pts->next->next = NULL;
00747 VSET( pts->p, 0, -rh, 0);
00748 VSET( pts->next->p, 0, rh, 0);
00749
00750 n = 2;
00751
00752 n += rt_mk_parabola( pts, rh, b, dtol, ntol );
00753
00754
00755 front = (fastf_t *)bu_malloc(3*n * sizeof(fastf_t), "fastf_t");
00756 back = (fastf_t *)bu_malloc(3*n * sizeof(fastf_t), "fastf_t");
00757
00758
00759 pos = pts;
00760 i = 0;
00761 while (pos) {
00762
00763 MAT4X3VEC( &front[i], invR, pos->p );
00764
00765 VADD2( &front[i], &front[i], xip->rpc_V );
00766
00767 VADD2( &back[i], &front[i], xip->rpc_H );
00768 i += 3;
00769 old = pos;
00770 pos = pos->next;
00771 bu_free( (char *)old, "rt_pt_node" );
00772 }
00773 #else
00774
00775 pts = rt_ptalloc();
00776 pts->next = rt_ptalloc();
00777 pts->next->next = NULL;
00778 VSET( pts->p, 0, 0, -b);
00779 VSET( pts->next->p, 0, rh, 0);
00780
00781 n = 2;
00782
00783 n += rt_mk_parabola( pts, rh, b, dtol, ntol );
00784
00785
00786 front = (fastf_t *)bu_malloc((2*3*n-1) * sizeof(fastf_t), "fastf_t");
00787 back = (fastf_t *)bu_malloc((2*3*n-1) * sizeof(fastf_t), "fastf_t");
00788
00789
00790 pos = pts;
00791 i = 0;
00792 while (pos) {
00793
00794 MAT4X3VEC( &front[i], invR, pos->p );
00795
00796 VADD2( &front[i], &front[i], xip->rpc_V );
00797
00798 VADD2( &back[i], &front[i], xip->rpc_H );
00799 i += 3;
00800 old = pos;
00801 pos = pos->next;
00802 bu_free( (char *)old, "rt_pt_node" );
00803 }
00804 for (i = 3*n; i < 6*n-3; i+=3) {
00805 VMOVE( &front[i], &front[6*n-i-6] );
00806 front[i+1] = -front[i+1];
00807 VMOVE( &back[i], &back[6*n-i-6] );
00808 back[i+1] = -back[i+1];
00809 }
00810 n = 2*n - 1;
00811 #endif
00812
00813
00814 RT_ADD_VLIST( vhead, &front[(n-1)*ELEMENTS_PER_VECT],
00815 BN_VLIST_LINE_MOVE );
00816 for( i = 0; i < n; i++ ) {
00817 RT_ADD_VLIST( vhead, &front[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00818 }
00819
00820
00821 RT_ADD_VLIST( vhead, &back[(n-1)*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00822 for( i = 0; i < n; i++ ) {
00823 RT_ADD_VLIST( vhead, &back[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00824 }
00825
00826
00827 for( i = 0; i < n; i++ ) {
00828 RT_ADD_VLIST( vhead, &front[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00829 RT_ADD_VLIST( vhead, &back[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00830 }
00831
00832 bu_free( (char *)front, "fastf_t" );
00833 bu_free( (char *)back, "fastf_t" );
00834
00835 return(0);
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 int
00848 rt_mk_parabola(struct rt_pt_node *pts, fastf_t r, fastf_t b, fastf_t dtol, fastf_t ntol)
00849 {
00850 fastf_t dist, intr, m, theta0, theta1;
00851 int n;
00852 point_t mpt, p0, p1;
00853 vect_t norm_line, norm_parab;
00854 struct rt_pt_node *new, *rt_ptalloc(void);
00855
00856 #define RPC_TOL .0001
00857
00858 VMOVE( p0, pts->p );
00859 VMOVE( p1, pts->next->p );
00860
00861 m = ( p1[Z] - p0[Z] ) / ( p1[Y] - p0[Y] );
00862 intr = p0[Z] - m * p0[Y];
00863
00864 mpt[X] = 0;
00865 mpt[Y] = (r * r * m) / (2 * b);
00866 if (NEAR_ZERO( mpt[Y], RPC_TOL))
00867 mpt[Y] = 0.;
00868 mpt[Z] = (mpt[Y] * m / 2) - b;
00869 if (NEAR_ZERO( mpt[Z], RPC_TOL))
00870 mpt[Z] = 0.;
00871
00872 dist = fabs( mpt[Z] + b + b + intr ) / sqrt( m * m + 1 );
00873
00874 VSET( norm_line, m, -1., 0.);
00875 VSET( norm_parab, 2. * b / (r * r) * p0[Y], -1., 0.);
00876 VUNITIZE( norm_line );
00877 VUNITIZE( norm_parab );
00878 theta0 = fabs( acos( VDOT( norm_line, norm_parab )));
00879 VSET( norm_parab, 2. * b / (r * r) * p1[Y], -1., 0.);
00880 VUNITIZE( norm_parab );
00881 theta1 = fabs( acos( VDOT( norm_line, norm_parab )));
00882
00883 if ( dist > dtol || theta0 > ntol || theta1 > ntol ) {
00884
00885 new = rt_ptalloc();
00886 VMOVE( new->p, mpt );
00887 new->next = pts->next;
00888 pts->next = new;
00889
00890 n = 1;
00891
00892 n += rt_mk_parabola( pts, r, b, dtol, ntol );
00893
00894 n += rt_mk_parabola( new, r, b, dtol, ntol );
00895 } else
00896 n = 0;
00897 return( n );
00898 }
00899
00900
00901
00902
00903 struct rt_pt_node *
00904 rt_ptalloc(void)
00905 {
00906 struct rt_pt_node *mem;
00907
00908 mem = (struct rt_pt_node *)bu_malloc(sizeof(struct rt_pt_node), "rt_pt_node");
00909 return(mem);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919 int
00920 rt_rpc_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00921 {
00922 int i, j, n;
00923 fastf_t b, *back, f, *front, h, rh;
00924 fastf_t dtol, ntol;
00925 vect_t Bu, Hu, Ru;
00926 LOCAL mat_t R;
00927 LOCAL mat_t invR;
00928 LOCAL struct rt_rpc_internal *xip;
00929 struct rt_pt_node *old, *pos, *pts;
00930 struct shell *s;
00931 struct faceuse **outfaceuses;
00932 struct vertex **vfront, **vback, **vtemp, *vertlist[4];
00933 vect_t *norms;
00934 fastf_t r_sq_over_b;
00935
00936 NMG_CK_MODEL( m );
00937 BN_CK_TOL( tol );
00938 RT_CK_TESS_TOL( ttol );
00939
00940 RT_CK_DB_INTERNAL(ip);
00941 xip = (struct rt_rpc_internal *)ip->idb_ptr;
00942 RT_RPC_CK_MAGIC(xip);
00943
00944
00945 b = MAGNITUDE( xip->rpc_B );
00946 rh = xip->rpc_r;
00947 h = MAGNITUDE( xip->rpc_H );
00948
00949
00950 if( NEAR_ZERO(h, RT_LEN_TOL) || NEAR_ZERO(b, RT_LEN_TOL)
00951 || NEAR_ZERO(rh, RT_LEN_TOL) ) {
00952 bu_log("rt_rpc_tess(): zero length H, B, or rh\n");
00953 return(-2);
00954 }
00955
00956
00957 f = VDOT( xip->rpc_B, xip->rpc_H ) / (b * h);
00958 if( ! NEAR_ZERO(f, RT_DOT_TOL) ) {
00959 bu_log("rt_rpc_tess(): B not perpendicular to H, f=%f\n", f);
00960 return(-3);
00961 }
00962
00963
00964 VMOVE( Hu, xip->rpc_H );
00965 VUNITIZE( Hu );
00966 VMOVE( Bu, xip->rpc_B );
00967 VUNITIZE( Bu );
00968 VCROSS( Ru, Bu, Hu );
00969
00970
00971 MAT_IDN( R );
00972 VREVERSE( &R[0], Hu );
00973 VMOVE( &R[4], Ru );
00974 VREVERSE( &R[8], Bu );
00975 bn_mat_trn( invR, R );
00976
00977
00978
00979
00980 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 ) {
00981 dtol = 0.0;
00982 } else {
00983
00984 if (rh < b)
00985 dtol = ttol->rel * 2 * rh;
00986 else
00987 dtol = ttol->rel * 2 * b;
00988 }
00989 if( ttol->abs <= 0.0 ) {
00990 if( dtol <= 0.0 ) {
00991
00992 if (rh < b)
00993 dtol = 2 * 0.10 * rh;
00994 else
00995 dtol = 2 * 0.10 * b;
00996 } else {
00997
00998 }
00999 } else {
01000
01001 if( ttol->rel <= 0.0 || dtol > ttol->abs )
01002 dtol = ttol->abs;
01003 }
01004
01005
01006 if( ttol->norm > 0.0 )
01007 ntol = ttol->norm;
01008 else
01009
01010 ntol = bn_pi;
01011
01012
01013 pts = rt_ptalloc();
01014 pts->next = rt_ptalloc();
01015 pts->next->next = NULL;
01016 VSET( pts->p, 0, -rh, 0);
01017 VSET( pts->next->p, 0, rh, 0);
01018
01019 n = 2;
01020
01021 n += rt_mk_parabola( pts, rh, b, dtol, ntol );
01022
01023
01024 front = (fastf_t *)bu_malloc(3*n * sizeof(fastf_t), "fastf_t");
01025 back = (fastf_t *)bu_malloc(3*n * sizeof(fastf_t), "fastf_t");
01026 norms = (vect_t *)bu_calloc( n , sizeof( vect_t ) , "rt_rpc_tess: norms" );
01027 vfront = (struct vertex **)bu_malloc((n+1) * sizeof(struct vertex *), "vertex *");
01028 vback = (struct vertex **)bu_malloc((n+1) * sizeof(struct vertex *), "vertex *");
01029 vtemp = (struct vertex **)bu_malloc((n+1) * sizeof(struct vertex *), "vertex *");
01030 outfaceuses = (struct faceuse **)bu_malloc((n+2) * sizeof(struct faceuse *), "faceuse *");
01031
01032
01033 r_sq_over_b = rh * rh / b;
01034 pos = pts;
01035 i = 0;
01036 j = 0;
01037 while (pos) {
01038 vect_t tmp_norm;
01039
01040 VSET( tmp_norm , 0.0 , 2.0 * pos->p[Y] , -r_sq_over_b );
01041 MAT4X3VEC( norms[j] , invR , tmp_norm );
01042 VUNITIZE( norms[j] );
01043
01044 MAT4X3VEC( &front[i], invR, pos->p );
01045
01046 VADD2( &front[i], &front[i], xip->rpc_V );
01047
01048 VADD2( &back[i], &front[i], xip->rpc_H );
01049 i += 3;
01050 j++;
01051 old = pos;
01052 pos = pos->next;
01053 bu_free( (char *)old, "rt_pt_node" );
01054 }
01055
01056 *r = nmg_mrsv( m );
01057 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
01058
01059 for( i=0; i<n; i++ ) {
01060 vfront[i] = vtemp[i] = (struct vertex *)0;
01061 }
01062
01063
01064 outfaceuses[0] = nmg_cface(s, vfront, n);
01065
01066 (void)nmg_mark_edges_real( &outfaceuses[0]->l.magic );
01067
01068
01069 outfaceuses[1] = nmg_cface(s, vtemp, n);
01070
01071 (void)nmg_mark_edges_real( &outfaceuses[1]->l.magic );
01072
01073 for( i=0; i<n; i++ ) vback[i] = vtemp[n-1-i];
01074
01075
01076 vfront[n] = vfront[0];
01077 vback[n] = vback[0];
01078
01079
01080
01081
01082
01083 for( i=0; i<n; i++ ) {
01084 vertlist[0] = vfront[i];
01085 vertlist[1] = vback[i];
01086 vertlist[2] = vback[i+1];
01087 vertlist[3] = vfront[i+1];
01088 outfaceuses[2+i] = nmg_cface(s, vertlist, 4);
01089 }
01090
01091 (void)nmg_mark_edges_real( &outfaceuses[n+1]->l.magic );
01092
01093 for( i=0; i<n; i++ ) {
01094 NMG_CK_VERTEX(vfront[i]);
01095 NMG_CK_VERTEX(vback[i]);
01096 }
01097
01098
01099 for( i=0; i<n; i++ ) {
01100 nmg_vertex_gv( vfront[i], &front[3*(i)] );
01101 }
01102 for( i=0; i<n; i++ ) {
01103 nmg_vertex_gv( vback[i], &back[3*(i)] );
01104 }
01105
01106
01107 for (i=0 ; i < n+2 ; i++) {
01108 if( nmg_fu_planeeqn( outfaceuses[i], tol ) < 0 )
01109 {
01110
01111 bu_free( (char *)front, "fastf_t");
01112 bu_free( (char *)back, "fastf_t");
01113 bu_free( (char*)vfront, "vertex *");
01114 bu_free( (char*)vback, "vertex *");
01115 bu_free( (char*)vtemp, "vertex *");
01116 bu_free( (char*)outfaceuses, "faceuse *");
01117
01118 return(-1);
01119 }
01120 }
01121
01122
01123 for( i=0 ; i<n ; i++ )
01124 {
01125 struct vertexuse *vu;
01126 struct faceuse *fu;
01127 vect_t rev_norm;
01128
01129 VREVERSE( rev_norm , norms[i] );
01130
01131
01132 NMG_CK_VERTEX( vfront[i] );
01133 for( BU_LIST_FOR( vu , vertexuse , &vfront[i]->vu_hd ) )
01134 {
01135 NMG_CK_VERTEXUSE( vu );
01136 fu = nmg_find_fu_of_vu( vu );
01137 NMG_CK_FACEUSE( fu );
01138 if( fu->f_p == outfaceuses[0]->f_p ||
01139 fu->f_p == outfaceuses[1]->f_p ||
01140 fu->f_p == outfaceuses[n+1]->f_p )
01141 continue;
01142
01143 if( fu->orientation == OT_SAME )
01144 nmg_vertexuse_nv( vu , norms[i] );
01145 else if( fu->orientation == OT_OPPOSITE )
01146 nmg_vertexuse_nv( vu , rev_norm );
01147 }
01148
01149
01150 NMG_CK_VERTEX( vback[i] );
01151 for( BU_LIST_FOR( vu , vertexuse , &vback[i]->vu_hd ) )
01152 {
01153 NMG_CK_VERTEXUSE( vu );
01154 fu = nmg_find_fu_of_vu( vu );
01155 NMG_CK_FACEUSE( fu );
01156 if( fu->f_p == outfaceuses[0]->f_p ||
01157 fu->f_p == outfaceuses[1]->f_p ||
01158 fu->f_p == outfaceuses[n+1]->f_p )
01159 continue;
01160
01161 if( fu->orientation == OT_SAME )
01162 nmg_vertexuse_nv( vu , norms[i] );
01163 else if( fu->orientation == OT_OPPOSITE )
01164 nmg_vertexuse_nv( vu , rev_norm );
01165 }
01166 }
01167
01168
01169 nmg_gluefaces( outfaceuses, n+2, tol );
01170
01171
01172 nmg_region_a( *r, tol );
01173
01174
01175 bu_free( (char *)front, "fastf_t");
01176 bu_free( (char *)back, "fastf_t");
01177 bu_free( (char*)vfront, "vertex *");
01178 bu_free( (char*)vback, "vertex *");
01179 bu_free( (char*)vtemp, "vertex *");
01180 bu_free( (char*)outfaceuses, "faceuse *");
01181
01182 return(0);
01183 }
01184
01185
01186
01187
01188
01189
01190
01191 int
01192 rt_rpc_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01193 {
01194 LOCAL struct rt_rpc_internal *xip;
01195 union record *rp;
01196
01197 BU_CK_EXTERNAL( ep );
01198 rp = (union record *)ep->ext_buf;
01199
01200 if( rp->u_id != ID_SOLID ) {
01201 bu_log("rt_rpc_import: defective record\n");
01202 return(-1);
01203 }
01204
01205 RT_CK_DB_INTERNAL( ip );
01206 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01207 ip->idb_type = ID_RPC;
01208 ip->idb_meth = &rt_functab[ID_RPC];
01209 ip->idb_ptr = bu_malloc( sizeof(struct rt_rpc_internal), "rt_rpc_internal");
01210 xip = (struct rt_rpc_internal *)ip->idb_ptr;
01211 xip->rpc_magic = RT_RPC_INTERNAL_MAGIC;
01212
01213
01214 MAT4X3PNT( xip->rpc_V, mat, &rp->s.s_values[0*3] );
01215 MAT4X3VEC( xip->rpc_H, mat, &rp->s.s_values[1*3] );
01216 MAT4X3VEC( xip->rpc_B, mat, &rp->s.s_values[2*3] );
01217 xip->rpc_r = rp->s.s_values[3*3] / mat[15];
01218
01219 if( xip->rpc_r < SMALL_FASTF )
01220 {
01221 bu_log( "rt_rpc_import: r is zero\n" );
01222 bu_free( (char *)ip->idb_ptr , "rt_rpc_import: ip->idp_ptr" );
01223 return( -1 );
01224 }
01225
01226 return(0);
01227 }
01228
01229
01230
01231
01232
01233
01234 int
01235 rt_rpc_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01236 {
01237 struct rt_rpc_internal *xip;
01238 union record *rpc;
01239 fastf_t f,mag_b,mag_h;
01240
01241 RT_CK_DB_INTERNAL(ip);
01242 if( ip->idb_type != ID_RPC ) return(-1);
01243 xip = (struct rt_rpc_internal *)ip->idb_ptr;
01244 RT_RPC_CK_MAGIC(xip);
01245
01246 BU_CK_EXTERNAL(ep);
01247 ep->ext_nbytes = sizeof(union record);
01248 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "rpc external");
01249 rpc = (union record *)ep->ext_buf;
01250
01251 rpc->s.s_id = ID_SOLID;
01252 rpc->s.s_type = RPC;
01253
01254 mag_b = MAGNITUDE( xip->rpc_B );
01255 mag_h = MAGNITUDE( xip->rpc_H );
01256
01257 if( mag_b < RT_LEN_TOL || mag_h < RT_LEN_TOL || xip->rpc_r < RT_LEN_TOL) {
01258 bu_log("rt_rpc_export: not all dimensions positive!\n");
01259 return(-1);
01260 }
01261
01262 f = VDOT(xip->rpc_B, xip->rpc_H) / (mag_b * mag_h );
01263 if ( !NEAR_ZERO( f , RT_DOT_TOL) ) {
01264 bu_log("rt_rpc_export: B and H are not perpendicular! (dot = %g)\n",f );
01265 return(-1);
01266 }
01267
01268
01269 VSCALE( &rpc->s.s_values[0*3], xip->rpc_V, local2mm );
01270 VSCALE( &rpc->s.s_values[1*3], xip->rpc_H, local2mm );
01271 VSCALE( &rpc->s.s_values[2*3], xip->rpc_B, local2mm );
01272 rpc->s.s_values[3*3] = xip->rpc_r * local2mm;
01273
01274 return(0);
01275 }
01276
01277
01278
01279
01280
01281
01282
01283 int
01284 rt_rpc_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01285 {
01286 struct rt_rpc_internal *xip;
01287 fastf_t vec[10];
01288
01289 BU_CK_EXTERNAL( ep );
01290
01291 BU_ASSERT_LONG( ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * 10 );
01292
01293 RT_CK_DB_INTERNAL( ip );
01294 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01295 ip->idb_type = ID_RPC;
01296 ip->idb_meth = &rt_functab[ID_RPC];
01297 ip->idb_ptr = bu_malloc( sizeof(struct rt_rpc_internal), "rt_rpc_internal");
01298
01299 xip = (struct rt_rpc_internal *)ip->idb_ptr;
01300 xip->rpc_magic = RT_RPC_INTERNAL_MAGIC;
01301
01302
01303 ntohd( (unsigned char *)vec, ep->ext_buf, 10 );
01304
01305
01306 MAT4X3PNT( xip->rpc_V, mat, &vec[0*3] );
01307 MAT4X3VEC( xip->rpc_H, mat, &vec[1*3] );
01308 MAT4X3VEC( xip->rpc_B, mat, &vec[2*3] );
01309 xip->rpc_r = vec[3*3] / mat[15];
01310
01311 if( xip->rpc_r < SMALL_FASTF )
01312 {
01313 bu_log( "rt_rpc_import: r is zero\n" );
01314 bu_free( (char *)ip->idb_ptr , "rt_rpc_import: ip->idp_ptr" );
01315 return( -1 );
01316 }
01317
01318 return(0);
01319 }
01320
01321
01322
01323
01324
01325
01326 int
01327 rt_rpc_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01328 {
01329 struct rt_rpc_internal *xip;
01330 fastf_t vec[10];
01331 fastf_t f,mag_b,mag_h;
01332
01333 RT_CK_DB_INTERNAL(ip);
01334 if( ip->idb_type != ID_RPC ) return(-1);
01335 xip = (struct rt_rpc_internal *)ip->idb_ptr;
01336 RT_RPC_CK_MAGIC(xip);
01337
01338 BU_CK_EXTERNAL(ep);
01339 ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * 10;
01340 ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "rpc external");
01341
01342 mag_b = MAGNITUDE( xip->rpc_B );
01343 mag_h = MAGNITUDE( xip->rpc_H );
01344
01345 if( mag_b < RT_LEN_TOL || mag_h < RT_LEN_TOL || xip->rpc_r < RT_LEN_TOL) {
01346 bu_log("rt_rpc_export: not all dimensions positive!\n");
01347 return(-1);
01348 }
01349
01350 f = VDOT(xip->rpc_B, xip->rpc_H) / (mag_b * mag_h );
01351 if ( !NEAR_ZERO( f , RT_DOT_TOL) ) {
01352 bu_log("rt_rpc_export: B and H are not perpendicular! (dot = %g)\n",f );
01353 return(-1);
01354 }
01355
01356
01357 VSCALE( &vec[0*3], xip->rpc_V, local2mm );
01358 VSCALE( &vec[1*3], xip->rpc_H, local2mm );
01359 VSCALE( &vec[2*3], xip->rpc_B, local2mm );
01360 vec[3*3] = xip->rpc_r * local2mm;
01361
01362
01363 htond( ep->ext_buf, (unsigned char *)vec, 10 );
01364
01365 return(0);
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375 int
01376 rt_rpc_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01377 {
01378 register struct rt_rpc_internal *xip =
01379 (struct rt_rpc_internal *)ip->idb_ptr;
01380 char buf[256];
01381
01382 RT_RPC_CK_MAGIC(xip);
01383 bu_vls_strcat( str, "Right Parabolic Cylinder (RPC)\n");
01384
01385 sprintf(buf, "\tV (%g, %g, %g)\n",
01386 INTCLAMP(xip->rpc_V[X] * mm2local),
01387 INTCLAMP(xip->rpc_V[Y] * mm2local),
01388 INTCLAMP(xip->rpc_V[Z] * mm2local) );
01389 bu_vls_strcat( str, buf );
01390
01391 sprintf(buf, "\tB (%g, %g, %g) mag=%g\n",
01392 INTCLAMP(xip->rpc_B[X] * mm2local),
01393 INTCLAMP(xip->rpc_B[Y] * mm2local),
01394 INTCLAMP(xip->rpc_B[Z] * mm2local),
01395 INTCLAMP(MAGNITUDE(xip->rpc_B) * mm2local));
01396 bu_vls_strcat( str, buf );
01397
01398 sprintf(buf, "\tH (%g, %g, %g) mag=%g\n",
01399 INTCLAMP(xip->rpc_H[X] * mm2local),
01400 INTCLAMP(xip->rpc_H[Y] * mm2local),
01401 INTCLAMP(xip->rpc_H[Z] * mm2local),
01402 INTCLAMP(MAGNITUDE(xip->rpc_H) * mm2local));
01403 bu_vls_strcat( str, buf );
01404
01405 sprintf(buf, "\tr=%g\n", INTCLAMP(xip->rpc_r * mm2local));
01406 bu_vls_strcat( str, buf );
01407
01408 return(0);
01409 }
01410
01411
01412
01413
01414
01415
01416 void
01417 rt_rpc_ifree(struct rt_db_internal *ip)
01418 {
01419 register struct rt_rpc_internal *xip;
01420
01421 RT_CK_DB_INTERNAL(ip);
01422 xip = (struct rt_rpc_internal *)ip->idb_ptr;
01423 RT_RPC_CK_MAGIC(xip);
01424 xip->rpc_magic = 0;
01425
01426 bu_free( (char *)xip, "rpc ifree" );
01427 ip->idb_ptr = GENPTR_NULL;
01428 }
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438