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 #ifndef lint
00039 static const char RCSpipe[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_pipe.c,v 14.20 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00040 #endif
00041
00042 #include "common.h"
00043
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <ctype.h>
00047 #ifdef HAVE_UNISTD_H
00048 # include <unistd.h>
00049 #endif
00050 #ifdef HAVE_STRING_H
00051 # include <string.h>
00052 #endif
00053 #include <math.h>
00054
00055 #ifdef HAVE_FLOAT_H
00056
00057 # include <float.h>
00058 #endif
00059
00060 #include "tcl.h"
00061 #include "machine.h"
00062 #include "vmath.h"
00063 #include "bu.h"
00064 #include "bn.h"
00065 #include "db.h"
00066 #include "nmg.h"
00067 #include "raytrace.h"
00068 #include "wdb.h"
00069 #include "rtgeom.h"
00070 #include "./debug.h"
00071
00072 struct id_pipe
00073 {
00074 struct bu_list l;
00075 int pipe_is_bend;
00076 };
00077
00078 struct lin_pipe
00079 {
00080 struct bu_list l;
00081 int pipe_is_bend;
00082 vect_t pipe_V;
00083 vect_t pipe_H;
00084 fastf_t pipe_ribase, pipe_ritop;
00085 fastf_t pipe_ribase_sq, pipe_ritop_sq;
00086 fastf_t pipe_ridiff_sq, pipe_ridiff;
00087 fastf_t pipe_rodiff_sq, pipe_rodiff;
00088 fastf_t pipe_robase, pipe_rotop;
00089 fastf_t pipe_robase_sq, pipe_rotop_sq;
00090 fastf_t pipe_len;
00091 mat_t pipe_SoR;
00092 mat_t pipe_invRoS;
00093 };
00094
00095 struct bend_pipe
00096 {
00097 struct bu_list l;
00098 int pipe_is_bend;
00099 fastf_t bend_radius;
00100 fastf_t bend_or;
00101 fastf_t bend_ir;
00102 mat_t bend_invR;
00103 mat_t bend_SoR;
00104 point_t bend_V;
00105 point_t bend_start;
00106 point_t bend_end;
00107 fastf_t bend_alpha_i;
00108 fastf_t bend_alpha_o;
00109 fastf_t bend_angle;
00110 vect_t bend_ra;
00111 vect_t bend_rb;
00112 vect_t bend_N;
00113 fastf_t bend_R_SQ;
00114 point_t bend_min;
00115 point_t bend_max;
00116 };
00117
00118
00119 struct hit_list
00120 {
00121 struct bu_list l;
00122 struct hit *hitp;
00123 };
00124
00125 #define PIPE_MM(_v) VMINMAX( stp->st_min, stp->st_max, _v );
00126
00127 #define ARC_SEGS 16
00128
00129 #define PIPE_LINEAR_OUTER_BODY 1
00130 #define PIPE_LINEAR_INNER_BODY 2
00131 #define PIPE_LINEAR_TOP 3
00132 #define PIPE_LINEAR_BASE 4
00133 #define PIPE_BEND_OUTER_BODY 5
00134 #define PIPE_BEND_INNER_BODY 6
00135 #define PIPE_BEND_BASE 7
00136 #define PIPE_BEND_TOP 8
00137
00138 BU_EXTERN( void rt_pipe_ifree, (struct rt_db_internal *ip) );
00139
00140
00141 HIDDEN int
00142 rt_bend_pipe_prep(struct soltab *stp, struct bu_list *head, fastf_t *bend_center, fastf_t *bend_start, fastf_t *bend_end, fastf_t bend_radius, fastf_t bend_angle, fastf_t *v1, fastf_t *v2, fastf_t od, fastf_t id)
00143 {
00144 register struct bend_pipe *pipe;
00145 LOCAL vect_t to_start,to_end;
00146 LOCAL mat_t R;
00147 LOCAL point_t work;
00148 LOCAL vect_t tmp_vec;
00149 LOCAL fastf_t f;
00150
00151 pipe = (struct bend_pipe *)bu_malloc( sizeof( struct bend_pipe ), "rt_bend_pipe_prep:pipe" ) ;
00152
00153 pipe->pipe_is_bend = 1;
00154 pipe->bend_or = od * 0.5;
00155 pipe->bend_ir = id * 0.5;
00156
00157 VMOVE( pipe->bend_start, bend_start );
00158 VMOVE( pipe->bend_end, bend_end );
00159 VMOVE( pipe->bend_V, bend_center );
00160 VSUB2( to_start, bend_start, bend_center );
00161 pipe->bend_radius = bend_radius;
00162 VSUB2( to_end, bend_end, bend_center );
00163 VSCALE( pipe->bend_ra, to_start, 1.0/pipe->bend_radius );
00164 VCROSS( pipe->bend_N, to_start, to_end );
00165 VUNITIZE( pipe->bend_N );
00166 VCROSS( pipe->bend_rb, pipe->bend_N, pipe->bend_ra );
00167
00168 pipe->bend_angle = bend_angle;
00169
00170
00171 if( pipe->bend_angle >= bn_pi )
00172 {
00173 bu_log( "Error: rt_pipe_prep: Bend section bends through more than 180 degrees\n" );
00174 return( 1 );
00175 }
00176
00177 pipe->bend_alpha_i = pipe->bend_ir/pipe->bend_radius;
00178 pipe->bend_alpha_o = pipe->bend_or/pipe->bend_radius;
00179
00180 pipe->bend_R_SQ = (pipe->bend_radius + pipe->bend_or) *
00181 (pipe->bend_radius + pipe->bend_or);
00182
00183 MAT_IDN( R );
00184 VMOVE( &R[0], pipe->bend_ra );
00185 VMOVE( &R[4], pipe->bend_rb );
00186 VMOVE( &R[8], pipe->bend_N );
00187
00188 if (bn_mat_inverse( pipe->bend_invR, R ) == 0) {
00189 bu_free(pipe, "rt_bend_pipe_prep:pipe");
00190 return 0;
00191 }
00192
00193
00194 MAT_COPY( pipe->bend_SoR, R );
00195 pipe->bend_SoR[15] *= pipe->bend_radius;
00196
00197
00198
00199 VSET( tmp_vec, 1.0, 0.0, 0.0 );
00200 VCROSS( work, pipe->bend_N, tmp_vec );
00201 f = pipe->bend_or + pipe->bend_radius * MAGNITUDE(work);
00202 pipe->bend_min[X] = pipe->bend_V[X] - f;
00203 pipe->bend_max[X] = pipe->bend_V[X] + f;
00204
00205
00206 VSET( tmp_vec, 0.0, 1.0, 0.0 );
00207 VCROSS( work, pipe->bend_N, tmp_vec );
00208 f = pipe->bend_or + pipe->bend_radius * MAGNITUDE(work);
00209 pipe->bend_min[Y] = pipe->bend_V[Y] - f;
00210 pipe->bend_max[Y] = pipe->bend_V[Y] + f;
00211
00212
00213 VSET( tmp_vec, 0.0, 0.0, 1.0 );
00214 VCROSS( work, pipe->bend_N, tmp_vec );
00215 f = pipe->bend_or + pipe->bend_radius * MAGNITUDE(work);
00216 pipe->bend_min[Z] = pipe->bend_V[Z] - f;
00217 pipe->bend_max[Z] = pipe->bend_V[Z] + f;
00218
00219 PIPE_MM( pipe->bend_min );
00220 PIPE_MM( pipe->bend_max );
00221
00222 BU_LIST_INSERT( head, &pipe->l );
00223
00224 return( 0 );
00225
00226 }
00227
00228 HIDDEN void
00229 rt_linear_pipe_prep(struct soltab *stp, struct bu_list *head, fastf_t *pt1, fastf_t id1, fastf_t od1, fastf_t *pt2, fastf_t id2, fastf_t od2)
00230 {
00231 register struct lin_pipe *pipe;
00232 LOCAL mat_t R;
00233 LOCAL mat_t Rinv;
00234 LOCAL mat_t S;
00235 LOCAL point_t work;
00236 LOCAL vect_t seg_ht;
00237 LOCAL vect_t v1,v2;
00238
00239 pipe = (struct lin_pipe *)bu_malloc( sizeof( struct lin_pipe ), "rt_bend_pipe_prep:pipe" );
00240 BU_LIST_INSERT( head, &pipe->l );
00241
00242
00243 VMOVE( pipe->pipe_V, pt1 );
00244
00245 VSUB2( seg_ht, pt2, pt1 );
00246 pipe->pipe_ribase = id1/2.0;
00247 pipe->pipe_ribase_sq = pipe->pipe_ribase * pipe->pipe_ribase;
00248 pipe->pipe_ritop = id2/2.0;
00249 pipe->pipe_ritop_sq = pipe->pipe_ritop * pipe->pipe_ritop;
00250 pipe->pipe_robase = od1/2.0;
00251 pipe->pipe_robase_sq = pipe->pipe_robase * pipe->pipe_robase;
00252 pipe->pipe_rotop = od2/2.0;
00253 pipe->pipe_rotop_sq = pipe->pipe_rotop * pipe->pipe_rotop;
00254 pipe->pipe_ridiff = pipe->pipe_ritop - pipe->pipe_ribase;
00255 pipe->pipe_ridiff_sq = pipe->pipe_ridiff * pipe->pipe_ridiff;
00256 pipe->pipe_rodiff = pipe->pipe_rotop - pipe->pipe_robase;
00257 pipe->pipe_rodiff_sq = pipe->pipe_rodiff * pipe->pipe_rodiff;
00258 pipe->pipe_is_bend = 0;
00259
00260 pipe->pipe_len = MAGNITUDE( seg_ht );
00261 VSCALE( seg_ht, seg_ht, 1.0/pipe->pipe_len );
00262 VMOVE( pipe->pipe_H, seg_ht );
00263 bn_vec_ortho( v1, seg_ht );
00264 VCROSS( v2, seg_ht, v1 );
00265
00266
00267 MAT_IDN( R );
00268 VMOVE( &R[0], v1 );
00269 VMOVE( &R[4], v2 );
00270 VMOVE( &R[8], seg_ht );
00271
00272
00273 bn_mat_trn( Rinv, R );
00274
00275
00276 MAT_IDN( S );
00277 S[10] = 1.0/pipe->pipe_len;
00278
00279
00280 bn_mat_mul( pipe->pipe_SoR, S, R );
00281 bn_mat_mul( pipe->pipe_invRoS, Rinv, S );
00282
00283
00284
00285 VJOIN2( work, pt1, od1, v1, od1, v2 );
00286 PIPE_MM( work )
00287 VJOIN2( work, pt1, -od1, v1, od1, v2 );
00288 PIPE_MM( work )
00289 VJOIN2( work, pt1, od1, v1, -od1, v2 );
00290 PIPE_MM( work )
00291 VJOIN2( work, pt1, -od1, v1, -od1, v2 );
00292 PIPE_MM( work )
00293
00294 VJOIN2( work, pt2, od2, v1, od2, v2 );
00295 PIPE_MM( work )
00296 VJOIN2( work, pt2, -od2, v1, od2, v2 );
00297 PIPE_MM( work )
00298 VJOIN2( work, pt2, od2, v1, -od2, v2 );
00299 PIPE_MM( work )
00300 VJOIN2( work, pt2, -od2, v1, -od2, v2 );
00301 PIPE_MM( work )
00302
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 int
00321 rt_pipe_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00322 {
00323 register struct bu_list *head;
00324 struct rt_pipe_internal *pip;
00325 struct wdb_pipept *pp1,*pp2,*pp3;
00326 point_t curr_pt;
00327 fastf_t curr_id, curr_od;
00328 fastf_t dx,dy,dz,f;
00329
00330 RT_CK_DB_INTERNAL( ip );
00331 pip = (struct rt_pipe_internal *)ip->idb_ptr;
00332 RT_PIPE_CK_MAGIC(pip);
00333
00334 head = (struct bu_list *)bu_malloc( sizeof( struct bu_list ), "rt_pipe_prep:head" );
00335 stp->st_specific = (genptr_t)head;
00336 BU_LIST_INIT( head );
00337
00338 if( BU_LIST_IS_EMPTY( &(pip->pipe_segs_head) ) )
00339 return( 0 );
00340
00341 pp1 = BU_LIST_FIRST( wdb_pipept, &(pip->pipe_segs_head) );
00342 pp2 = BU_LIST_NEXT( wdb_pipept, &pp1->l );
00343 if( BU_LIST_IS_HEAD( &pp2->l, &(pip->pipe_segs_head) ) )
00344 return( 0 );
00345 pp3 = BU_LIST_NEXT( wdb_pipept, &pp2->l );
00346 if( BU_LIST_IS_HEAD( &pp3->l , &(pip->pipe_segs_head) ) )
00347 pp3 = (struct wdb_pipept *)NULL;
00348
00349 VMOVE( curr_pt, pp1->pp_coord );
00350 curr_od = pp1->pp_od;
00351 curr_id = pp1->pp_id;
00352 while( 1 )
00353 {
00354 vect_t n1,n2;
00355 vect_t norm;
00356 vect_t v1,v2;
00357 fastf_t angle;
00358 fastf_t dist_to_bend;
00359 point_t bend_start, bend_end, bend_center;
00360
00361 VSUB2( n1, curr_pt, pp2->pp_coord );
00362 if( VNEAR_ZERO( n1, SQRT_SMALL_FASTF ) )
00363 {
00364
00365 goto next_pt;
00366 }
00367
00368 if( !pp3 )
00369 {
00370
00371 rt_linear_pipe_prep( stp, head, curr_pt, curr_id, curr_od, pp2->pp_coord, pp2->pp_id, pp2->pp_od );
00372 break;
00373 }
00374
00375 VSUB2( n2, pp3->pp_coord, pp2->pp_coord );
00376 VCROSS( norm, n1, n2 );
00377 VUNITIZE( n1 );
00378 VUNITIZE( n2 );
00379 angle = bn_pi - acos( VDOT( n1, n2 ) );
00380 dist_to_bend = pp2->pp_bendradius * tan( angle/2.0 );
00381 if( isnan( dist_to_bend ) || VNEAR_ZERO( norm, SQRT_SMALL_FASTF) || NEAR_ZERO( dist_to_bend, SQRT_SMALL_FASTF) )
00382 {
00383
00384 rt_linear_pipe_prep( stp, head, curr_pt, curr_id, curr_od,
00385 pp2->pp_coord, pp2->pp_id, pp2->pp_od );
00386 VMOVE( curr_pt, pp2->pp_coord );
00387 goto next_pt;
00388 }
00389
00390 VJOIN1( bend_start, pp2->pp_coord, dist_to_bend, n1 );
00391 VJOIN1( bend_end, pp2->pp_coord, dist_to_bend, n2 );
00392
00393 VUNITIZE( norm );
00394
00395
00396 rt_linear_pipe_prep( stp, head, curr_pt, curr_id, curr_od,
00397 bend_start, pp2->pp_id, pp2->pp_od );
00398
00399
00400 VCROSS( v1, n1, norm );
00401 VCROSS( v2, v1, norm );
00402 VJOIN1( bend_center, bend_start, -pp2->pp_bendradius, v1 );
00403 rt_bend_pipe_prep( stp, head, bend_center, bend_start, bend_end, pp2->pp_bendradius, angle,
00404 v1, v2, pp2->pp_od, pp2->pp_id );
00405
00406 VMOVE( curr_pt, bend_end );
00407 next_pt:
00408 if (!pp3) break;
00409 curr_id = pp2->pp_id;
00410 curr_od = pp2->pp_od;
00411 pp1 = pp2;
00412 pp2 = pp3;
00413 pp3 = BU_LIST_NEXT( wdb_pipept, &pp3->l );
00414 if( BU_LIST_IS_HEAD( &pp3->l , &(pip->pipe_segs_head) ) )
00415 pp3 = (struct wdb_pipept *)NULL;
00416 }
00417
00418 VSET( stp->st_center,
00419 (stp->st_max[X] + stp->st_min[X])/2,
00420 (stp->st_max[Y] + stp->st_min[Y])/2,
00421 (stp->st_max[Z] + stp->st_min[Z])/2 );
00422
00423 dx = (stp->st_max[X] - stp->st_min[X])/2;
00424 f = dx;
00425 dy = (stp->st_max[Y] - stp->st_min[Y])/2;
00426 if( dy > f ) f = dy;
00427 dz = (stp->st_max[Z] - stp->st_min[Z])/2;
00428 if( dz > f ) f = dz;
00429 stp->st_aradius = f;
00430 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00431
00432 return( 0 );
00433 }
00434
00435
00436
00437
00438 void
00439 rt_pipe_print(register const struct soltab *stp)
00440 {
00441
00442
00443 }
00444
00445
00446
00447
00448 void
00449 rt_pipept_print( const struct wdb_pipept *pipe, double mm2local )
00450 {
00451 point_t p1;
00452
00453 bu_log( "Pipe Vertex:\n" );
00454 VSCALE( p1, pipe->pp_coord, mm2local );
00455 bu_log( "\tat (%g %g %g)\n", V3ARGS( p1 ) );
00456 bu_log( "\tbend radius = %g\n", pipe->pp_bendradius*mm2local );
00457 if( pipe->pp_id > 0.0 )
00458 bu_log( "\tod=%g, id=%g\n",
00459 pipe->pp_od*mm2local,
00460 pipe->pp_id*mm2local );
00461 else
00462 bu_log( "\tod=%g\n", pipe->pp_od*mm2local );
00463 }
00464
00465
00466
00467
00468 void
00469 rt_vls_pipept(
00470 struct bu_vls *vp,
00471 int seg_no,
00472 const struct rt_db_internal *ip,
00473 double mm2local)
00474 {
00475 struct rt_pipe_internal *pint;
00476 struct wdb_pipept *pipe;
00477 int seg_count=0;
00478 char buf[256];
00479 point_t p1;
00480
00481 pint = (struct rt_pipe_internal *)ip->idb_ptr;
00482 RT_PIPE_CK_MAGIC( pint );
00483
00484 pipe = BU_LIST_FIRST( wdb_pipept, &pint->pipe_segs_head );
00485 while( ++seg_count != seg_no && BU_LIST_NOT_HEAD( &pipe->l, &pint->pipe_segs_head ) )
00486 pipe = BU_LIST_NEXT( wdb_pipept, &pipe->l );
00487
00488
00489 sprintf( buf, "Pipe Vertex:\n" );
00490 bu_vls_strcat( vp, buf );
00491 VSCALE( p1, pipe->pp_coord, mm2local );
00492 sprintf( buf, "\tat (%g %g %g)\n", V3ARGS( p1 ) );
00493 bu_vls_strcat( vp, buf );
00494 sprintf( buf, "\tbend radius = %g\n", pipe->pp_bendradius*mm2local );
00495 bu_vls_strcat( vp, buf );
00496 if( pipe->pp_id > 0.0 )
00497 sprintf( buf, "\tod=%g, id=%g\n",
00498 pipe->pp_od*mm2local,
00499 pipe->pp_id*mm2local );
00500 else
00501 sprintf( buf, "\tod=%g\n", pipe->pp_od*mm2local );
00502 bu_vls_strcat( vp, buf );
00503 }
00504
00505 HIDDEN void
00506 bend_pipe_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead, struct bend_pipe *pipe, struct hit_list *hit_headp, int *hit_count, int seg_no)
00507 {
00508 LOCAL vect_t dprime;
00509 LOCAL vect_t pprime;
00510 LOCAL vect_t work;
00511 LOCAL bn_poly_t C;
00512 LOCAL bn_complex_t val[4];
00513 LOCAL int j;
00514 LOCAL int root_count=0;
00515 LOCAL bn_poly_t A, Asqr;
00516 LOCAL bn_poly_t X2_Y2;
00517 LOCAL vect_t cor_pprime;
00518 LOCAL fastf_t cor_proj;
00519
00520 *hit_count = 0;
00521
00522 if( !rt_in_rpp( rp, ap->a_inv_dir, pipe->bend_min, pipe->bend_max ) ) {
00523 return;
00524 }
00525
00526
00527 MAT4X3VEC( dprime, pipe->bend_SoR, rp->r_dir );
00528 VUNITIZE( dprime );
00529
00530 VSUB2( work, rp->r_pt, pipe->bend_V );
00531 MAT4X3VEC( pprime, pipe->bend_SoR, work );
00532
00533
00534
00535
00536
00537
00538
00539
00540 cor_proj = VDOT( pprime, dprime );
00541 VSCALE( cor_pprime, dprime, cor_proj );
00542 VSUB2( cor_pprime, pprime, cor_pprime );
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 X2_Y2.dgr = 2;
00561 X2_Y2.cf[0] = dprime[X] * dprime[X] + dprime[Y] * dprime[Y];
00562 X2_Y2.cf[1] = 2.0 * (dprime[X] * cor_pprime[X] +
00563 dprime[Y] * cor_pprime[Y]);
00564 X2_Y2.cf[2] = cor_pprime[X] * cor_pprime[X] +
00565 cor_pprime[Y] * cor_pprime[Y];
00566
00567
00568 A.dgr = 2;
00569 A.cf[0] = X2_Y2.cf[0] + dprime[Z] * dprime[Z];
00570 A.cf[1] = X2_Y2.cf[1] + 2.0 * dprime[Z] * cor_pprime[Z];
00571 A.cf[2] = X2_Y2.cf[2] + cor_pprime[Z] * cor_pprime[Z] +
00572 1.0 - pipe->bend_alpha_o * pipe->bend_alpha_o;
00573
00574
00575
00576 Asqr.dgr = 4;
00577 Asqr.cf[0] = A.cf[0] * A.cf[0];
00578 Asqr.cf[1] = A.cf[0] * A.cf[1] + A.cf[1] * A.cf[0];
00579 Asqr.cf[2] = A.cf[0] * A.cf[2] + A.cf[1] * A.cf[1] + A.cf[2] * A.cf[0];
00580 Asqr.cf[3] = A.cf[1] * A.cf[2] + A.cf[2] * A.cf[1];
00581 Asqr.cf[4] = A.cf[2] * A.cf[2];
00582
00583
00584
00585
00586 C.dgr = 4;
00587 C.cf[0] = Asqr.cf[0];
00588 C.cf[1] = Asqr.cf[1];
00589 C.cf[2] = Asqr.cf[2] - X2_Y2.cf[0] * 4.0;
00590 C.cf[3] = Asqr.cf[3] - X2_Y2.cf[1] * 4.0;
00591 C.cf[4] = Asqr.cf[4] - X2_Y2.cf[2] * 4.0;
00592
00593
00594
00595
00596 if ( (root_count = rt_poly_roots( &C, val, stp->st_dp->d_namep )) != 4 ){
00597 if( root_count > 0 ) {
00598 bu_log("tor: rt_poly_roots() 4!=%d\n", root_count);
00599 bn_pr_roots( stp->st_name, val, root_count );
00600 } else if (root_count < 0) {
00601 static int reported=0;
00602 bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
00603 if (!reported) {
00604 VPRINT("while shooting from:\t", rp->r_pt);
00605 VPRINT("while shooting at:\t", rp->r_dir);
00606 bu_log("Additional pipe convergence failure details will be suppressed.\n");
00607 reported=1;
00608 }
00609 }
00610 return;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619 for ( j=0, (*hit_count)=0; j < 4; j++ ){
00620 if( NEAR_ZERO( val[j].im, 0.0001 ) )
00621 {
00622 struct hit_list *hitp;
00623 fastf_t normalized_dist;
00624 fastf_t dist;
00625 point_t hit_pt;
00626 vect_t to_hit;
00627 fastf_t angle;
00628
00629 normalized_dist = val[j].re - cor_proj;
00630 dist = normalized_dist * pipe->bend_radius;
00631
00632
00633 VJOIN1( hit_pt, rp->r_pt, dist, rp->r_dir );
00634 VSUB2( to_hit, hit_pt, pipe->bend_V );
00635 angle = atan2( VDOT( to_hit, pipe->bend_rb ), VDOT( to_hit, pipe->bend_ra ) );
00636 if( angle < 0.0 )
00637 angle += 2.0 * bn_pi;
00638 if( angle <= pipe->bend_angle )
00639 {
00640 BU_GETSTRUCT( hitp, hit_list );
00641 BU_GETSTRUCT( hitp->hitp, hit );
00642 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00643 hitp->hitp->hit_dist = dist;
00644 VJOIN1( hitp->hitp->hit_vpriv, pprime, normalized_dist, dprime );
00645 hitp->hitp->hit_surfno = seg_no*10 + PIPE_BEND_OUTER_BODY;
00646 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00647 (*hit_count)++;
00648 }
00649 }
00650 }
00651
00652 if( pipe->bend_alpha_i <= 0.0 )
00653 return;
00654
00655
00656 A.cf[2] = X2_Y2.cf[2] + cor_pprime[Z] * cor_pprime[Z] +
00657 1.0 - pipe->bend_alpha_i * pipe->bend_alpha_i;
00658
00659
00660
00661 Asqr.dgr = 4;
00662 Asqr.cf[0] = A.cf[0] * A.cf[0];
00663 Asqr.cf[1] = A.cf[0] * A.cf[1] + A.cf[1] * A.cf[0];
00664 Asqr.cf[2] = A.cf[0] * A.cf[2] + A.cf[1] * A.cf[1] + A.cf[2] * A.cf[0];
00665 Asqr.cf[3] = A.cf[1] * A.cf[2] + A.cf[2] * A.cf[1];
00666 Asqr.cf[4] = A.cf[2] * A.cf[2];
00667
00668
00669
00670
00671 C.dgr = 4;
00672 C.cf[0] = Asqr.cf[0];
00673 C.cf[1] = Asqr.cf[1];
00674 C.cf[2] = Asqr.cf[2] - X2_Y2.cf[0] * 4.0;
00675 C.cf[3] = Asqr.cf[3] - X2_Y2.cf[1] * 4.0;
00676 C.cf[4] = Asqr.cf[4] - X2_Y2.cf[2] * 4.0;
00677
00678
00679
00680
00681 if ( (root_count = rt_poly_roots( &C, val, stp->st_dp->d_namep)) != 4 ){
00682 if( root_count > 0 ) {
00683 bu_log("tor: rt_poly_roots() 4!=%d\n", root_count);
00684 bn_pr_roots( stp->st_name, val, root_count );
00685 } else if (root_count < 0) {
00686 static int reported=0;
00687 bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
00688 if (!reported) {
00689 VPRINT("while shooting from:\t", rp->r_pt);
00690 VPRINT("while shooting at:\t", rp->r_dir);
00691 bu_log("Additional pipe convergence failure details will be suppressed.\n");
00692 reported=1;
00693 }
00694 }
00695 return;
00696 }
00697
00698
00699
00700
00701
00702
00703
00704 for ( j=0, root_count=0; j < 4; j++ ){
00705 if( NEAR_ZERO( val[j].im, 0.0001 ) )
00706 {
00707 struct hit_list *hitp;
00708 fastf_t normalized_dist;
00709 fastf_t dist;
00710 point_t hit_pt;
00711 vect_t to_hit;
00712 fastf_t angle;
00713
00714 normalized_dist = val[j].re - cor_proj;
00715 dist = normalized_dist * pipe->bend_radius;
00716
00717
00718 VJOIN1( hit_pt, rp->r_pt, dist, rp->r_dir );
00719 VSUB2( to_hit, hit_pt, pipe->bend_V );
00720 angle = atan2( VDOT( to_hit, pipe->bend_rb ), VDOT( to_hit, pipe->bend_ra ) );
00721 if( angle < 0.0 )
00722 angle += 2.0 * bn_pi;
00723 if( angle <= pipe->bend_angle )
00724 {
00725 BU_GETSTRUCT( hitp, hit_list );
00726 BU_GETSTRUCT( hitp->hitp, hit );
00727 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00728 hitp->hitp->hit_dist = dist;
00729 VJOIN1( hitp->hitp->hit_vpriv, pprime, normalized_dist, dprime );
00730 hitp->hitp->hit_surfno = seg_no*10 + PIPE_BEND_INNER_BODY;
00731 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00732 root_count++;
00733 }
00734 }
00735 }
00736
00737 *hit_count += root_count;
00738
00739 return;
00740
00741 }
00742
00743 HIDDEN void
00744 linear_pipe_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead, struct lin_pipe *pipe, struct hit_list *hit_headp, int *hit_count, int seg_no)
00745 {
00746 LOCAL struct hit_list *hitp;
00747 LOCAL point_t work_pt;
00748 LOCAL point_t ray_start;
00749 LOCAL vect_t ray_dir;
00750 LOCAL double t_tmp;
00751 LOCAL double a,b,c;
00752 LOCAL double descrim;
00753
00754 if( pipe->pipe_is_bend )
00755 {
00756 bu_log( "linear_pipe_shot called for pipe bend\n" );
00757 rt_bomb( "linear_pipe_shot\n" );
00758 }
00759
00760 *hit_count = 0;
00761
00762
00763 VSUB2( work_pt, rp->r_pt, pipe->pipe_V );
00764 MAT4X3VEC( ray_start, pipe->pipe_SoR, work_pt );
00765
00766
00767 MAT4X3VEC( ray_dir, pipe->pipe_SoR, rp->r_dir );
00768
00769
00770 a = ray_dir[X]*ray_dir[X]
00771 + ray_dir[Y]*ray_dir[Y]
00772 - ray_dir[Z]*ray_dir[Z]*pipe->pipe_rodiff_sq;
00773 b = 2.0*(ray_start[X]*ray_dir[X]
00774 + ray_start[Y]*ray_dir[Y]
00775 - ray_start[Z]*ray_dir[Z]*pipe->pipe_rodiff_sq
00776 - ray_dir[Z]*pipe->pipe_robase*pipe->pipe_rodiff);
00777 c = ray_start[X]*ray_start[X]
00778 + ray_start[Y]*ray_start[Y]
00779 - pipe->pipe_robase*pipe->pipe_robase
00780 - ray_start[Z]*ray_start[Z]*pipe->pipe_rodiff_sq
00781 - 2.0*ray_start[Z]*pipe->pipe_robase*pipe->pipe_rodiff;
00782
00783 descrim = b*b - 4.0*a*c;
00784
00785 if( descrim > 0.0 )
00786 {
00787 LOCAL fastf_t sqrt_descrim;
00788 LOCAL point_t hit_pt;
00789
00790 sqrt_descrim = sqrt( descrim );
00791
00792 t_tmp = (-b - sqrt_descrim)/(2.0*a);
00793 VJOIN1( hit_pt, ray_start, t_tmp, ray_dir );
00794 if( hit_pt[Z] >= 0.0 && hit_pt[Z] <= 1.0 )
00795 {
00796 BU_GETSTRUCT( hitp, hit_list );
00797 BU_GETSTRUCT( hitp->hitp, hit );
00798 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00799 hitp->hitp->hit_dist = t_tmp;
00800 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_OUTER_BODY;
00801 VMOVE( hitp->hitp->hit_vpriv, hit_pt );
00802 hitp->hitp->hit_vpriv[Z] = (-pipe->pipe_robase - hit_pt[Z] * pipe->pipe_rodiff) *
00803 pipe->pipe_rodiff;
00804 (*hit_count)++;
00805 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00806 }
00807
00808 t_tmp = (-b + sqrt_descrim)/(2.0*a);
00809 VJOIN1( hit_pt, ray_start, t_tmp, ray_dir );
00810 if( hit_pt[Z] >= 0.0 && hit_pt[Z] <= 1.0 )
00811 {
00812 BU_GETSTRUCT( hitp, hit_list );
00813 BU_GETSTRUCT( hitp->hitp, hit );
00814 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00815 hitp->hitp->hit_dist = t_tmp;
00816 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_OUTER_BODY;
00817 VMOVE( hitp->hitp->hit_vpriv, hit_pt );
00818 hitp->hitp->hit_vpriv[Z] = (-pipe->pipe_robase - hit_pt[Z] * pipe->pipe_rodiff) *
00819 pipe->pipe_rodiff;
00820 (*hit_count)++;
00821 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00822 }
00823 }
00824
00825 if( pipe->pipe_ribase > 0.0 || pipe->pipe_ritop > 0.0 )
00826 {
00827
00828
00829 a = ray_dir[X]*ray_dir[X]
00830 + ray_dir[Y]*ray_dir[Y]
00831 - ray_dir[Z]*ray_dir[Z]*pipe->pipe_ridiff_sq;
00832 b = 2.0*(ray_start[X]*ray_dir[X]
00833 + ray_start[Y]*ray_dir[Y]
00834 - ray_start[Z]*ray_dir[Z]*pipe->pipe_ridiff_sq
00835 - ray_dir[Z]*pipe->pipe_ribase*pipe->pipe_ridiff);
00836 c = ray_start[X]*ray_start[X]
00837 + ray_start[Y]*ray_start[Y]
00838 - pipe->pipe_ribase*pipe->pipe_ribase
00839 - ray_start[Z]*ray_start[Z]*pipe->pipe_ridiff_sq
00840 - 2.0*ray_start[Z]*pipe->pipe_ribase*pipe->pipe_ridiff;
00841
00842 descrim = b*b - 4.0*a*c;
00843
00844 if( descrim > 0.0 )
00845 {
00846 LOCAL fastf_t sqrt_descrim;
00847 LOCAL point_t hit_pt;
00848
00849 sqrt_descrim = sqrt( descrim );
00850
00851 t_tmp = (-b - sqrt_descrim)/(2.0*a);
00852 VJOIN1( hit_pt, ray_start, t_tmp, ray_dir );
00853 if( hit_pt[Z] >= 0.0 && hit_pt[Z] <= 1.0 )
00854 {
00855 BU_GETSTRUCT( hitp, hit_list );
00856 BU_GETSTRUCT( hitp->hitp, hit );
00857 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00858 hitp->hitp->hit_dist = t_tmp;
00859 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_INNER_BODY;
00860 VMOVE( hitp->hitp->hit_vpriv, hit_pt );
00861 hitp->hitp->hit_vpriv[Z] = (-pipe->pipe_ribase - hit_pt[Z] * pipe->pipe_ridiff) *
00862 pipe->pipe_ridiff;
00863 (*hit_count)++;
00864 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00865 }
00866
00867 t_tmp = (-b + sqrt_descrim)/(2.0*a);
00868 VJOIN1( hit_pt, ray_start, t_tmp, ray_dir );
00869 if( hit_pt[Z] >= 0.0 && hit_pt[Z] <= 1.0 )
00870 {
00871 BU_GETSTRUCT( hitp, hit_list );
00872 BU_GETSTRUCT( hitp->hitp, hit );
00873 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00874 hitp->hitp->hit_dist = t_tmp;
00875 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_INNER_BODY;
00876 VMOVE( hitp->hitp->hit_vpriv, hit_pt );
00877 hitp->hitp->hit_vpriv[Z] = (-pipe->pipe_ribase - hit_pt[Z] * pipe->pipe_ridiff) *
00878 pipe->pipe_ridiff;
00879 (*hit_count)++;
00880 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00881 }
00882 }
00883 }
00884
00885 }
00886
00887 HIDDEN void
00888 pipe_start_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead, struct id_pipe *pipe, struct hit_list *hit_headp, int *hit_count, int seg_no)
00889 {
00890 point_t hit_pt;
00891 fastf_t t_tmp;
00892 fastf_t radius_sq;
00893 struct hit_list *hitp;
00894
00895 *hit_count = 0;
00896
00897 if( !pipe->pipe_is_bend )
00898 {
00899 struct lin_pipe *lin=(struct lin_pipe *)(&pipe->l);
00900 fastf_t dist_to_plane;
00901 fastf_t norm_dist;
00902 fastf_t slant_factor;
00903
00904 dist_to_plane = VDOT( lin->pipe_H, lin->pipe_V );
00905 norm_dist = dist_to_plane - VDOT( lin->pipe_H, rp->r_pt );
00906 slant_factor = VDOT( lin->pipe_H, rp->r_dir );
00907 if( !NEAR_ZERO( slant_factor, SMALL_FASTF ) )
00908 {
00909 vect_t to_center;
00910
00911 t_tmp = norm_dist/slant_factor;
00912 VJOIN1( hit_pt, rp->r_pt, t_tmp, rp->r_dir );
00913 VSUB2( to_center, lin->pipe_V, hit_pt );
00914 radius_sq = MAGSQ( to_center );
00915 if( radius_sq <= lin->pipe_robase_sq && radius_sq >= lin->pipe_ribase_sq )
00916 {
00917 BU_GETSTRUCT( hitp, hit_list );
00918 BU_GETSTRUCT( hitp->hitp, hit );
00919 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00920 hitp->hitp->hit_dist = t_tmp;
00921 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_BASE;
00922 (*hit_count)++;
00923 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00924 }
00925 }
00926 }
00927 else if( pipe->pipe_is_bend )
00928 {
00929 struct bend_pipe *bend=(struct bend_pipe *)(&pipe->l);
00930 fastf_t dist_to_plane;
00931 fastf_t norm_dist;
00932 fastf_t slant_factor;
00933
00934 dist_to_plane = VDOT( bend->bend_rb, bend->bend_start );
00935 norm_dist = dist_to_plane - VDOT( bend->bend_rb, rp->r_pt );
00936 slant_factor = VDOT( bend->bend_rb, rp->r_dir );
00937
00938 if( !NEAR_ZERO( slant_factor, SMALL_FASTF ) )
00939 {
00940 vect_t to_center;
00941
00942 t_tmp = norm_dist/slant_factor;
00943 VJOIN1( hit_pt, rp->r_pt, t_tmp, rp->r_dir );
00944 VSUB2( to_center, bend->bend_start, hit_pt );
00945 radius_sq = MAGSQ( to_center );
00946 if( radius_sq <= bend->bend_or*bend->bend_or && radius_sq >= bend->bend_ir*bend->bend_ir )
00947 {
00948 BU_GETSTRUCT( hitp, hit_list );
00949 BU_GETSTRUCT( hitp->hitp, hit );
00950 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00951 hitp->hitp->hit_dist = t_tmp;
00952 hitp->hitp->hit_surfno = seg_no*10 + PIPE_BEND_BASE;
00953 (*hit_count)++;
00954 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00955 }
00956 }
00957 }
00958 }
00959
00960 HIDDEN void
00961 pipe_end_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead, struct id_pipe *pipe, struct hit_list *hit_headp, int *hit_count, int seg_no)
00962 {
00963 point_t hit_pt;
00964 fastf_t t_tmp;
00965 fastf_t radius_sq;
00966 struct hit_list *hitp;
00967
00968 *hit_count = 0;
00969
00970 if( !pipe->pipe_is_bend )
00971 {
00972 struct lin_pipe *lin=(struct lin_pipe *)(&pipe->l);
00973 point_t top;
00974 fastf_t dist_to_plane;
00975 fastf_t norm_dist;
00976 fastf_t slant_factor;
00977
00978 VJOIN1( top, lin->pipe_V, lin->pipe_len, lin->pipe_H );
00979 dist_to_plane = VDOT( lin->pipe_H, top );
00980 norm_dist = dist_to_plane - VDOT( lin->pipe_H, rp->r_pt );
00981 slant_factor = VDOT( lin->pipe_H, rp->r_dir );
00982 if( !NEAR_ZERO( slant_factor, SMALL_FASTF ) )
00983 {
00984 vect_t to_center;
00985
00986 t_tmp = norm_dist/slant_factor;
00987 VJOIN1( hit_pt, rp->r_pt, t_tmp, rp->r_dir );
00988 VSUB2( to_center, top, hit_pt );
00989 radius_sq = MAGSQ( to_center );
00990 if( radius_sq <= lin->pipe_rotop_sq && radius_sq >= lin->pipe_ritop_sq )
00991 {
00992 BU_GETSTRUCT( hitp, hit_list );
00993 BU_GETSTRUCT( hitp->hitp, hit );
00994 hitp->hitp->hit_magic = RT_HIT_MAGIC;
00995 hitp->hitp->hit_dist = t_tmp;
00996 hitp->hitp->hit_surfno = seg_no*10 + PIPE_LINEAR_TOP;
00997 (*hit_count)++;
00998 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
00999 }
01000 }
01001 }
01002 else if( pipe->pipe_is_bend )
01003 {
01004 struct bend_pipe *bend=(struct bend_pipe *)(&pipe->l);
01005 vect_t to_end;
01006 vect_t plane_norm;
01007 fastf_t dist_to_plane;
01008 fastf_t norm_dist;
01009 fastf_t slant_factor;
01010
01011 VSUB2( to_end, bend->bend_end, bend->bend_V );
01012 VCROSS( plane_norm, to_end, bend->bend_N );
01013 VUNITIZE( plane_norm );
01014
01015 dist_to_plane = VDOT( plane_norm, bend->bend_end );
01016 norm_dist = dist_to_plane - VDOT( plane_norm, rp->r_pt );
01017 slant_factor = VDOT( plane_norm, rp->r_dir );
01018
01019 if( !NEAR_ZERO( slant_factor, SMALL_FASTF ) )
01020 {
01021 vect_t to_center;
01022
01023 t_tmp = norm_dist/slant_factor;
01024 VJOIN1( hit_pt, rp->r_pt, t_tmp, rp->r_dir );
01025 VSUB2( to_center, bend->bend_end, hit_pt );
01026 radius_sq = MAGSQ( to_center );
01027 if( radius_sq <= bend->bend_or*bend->bend_or && radius_sq >= bend->bend_ir*bend->bend_ir )
01028 {
01029 BU_GETSTRUCT( hitp, hit_list );
01030 BU_GETSTRUCT( hitp->hitp, hit );
01031 hitp->hitp->hit_magic = RT_HIT_MAGIC;
01032 hitp->hitp->hit_dist = t_tmp;
01033 hitp->hitp->hit_surfno = seg_no*10 + PIPE_BEND_TOP;
01034 (*hit_count)++;
01035 BU_LIST_INSERT( &hit_headp->l, &hitp->l );
01036 }
01037 }
01038 }
01039 }
01040
01041 HIDDEN void
01042 rt_pipe_hitsort(struct hit_list *h, int *nh, register struct xray *rp, struct soltab *stp)
01043 {
01044 struct hit_list *hitp;
01045 struct hit_list *first;
01046 struct hit_list *second;
01047 struct hit_list *prev;
01048 struct hit_list *next_hit;
01049
01050 hitp = BU_LIST_FIRST( hit_list, &h->l );
01051 while( BU_LIST_NEXT_NOT_HEAD( &hitp->l, &h->l ) )
01052 {
01053 struct hit_list *next_hit;
01054 struct hit_list *prev_hit;
01055
01056 next_hit = BU_LIST_NEXT( hit_list, &hitp->l );
01057 if( hitp->hitp->hit_dist > next_hit->hitp->hit_dist )
01058 {
01059 struct hit_list *tmp;
01060
01061 if( hitp == BU_LIST_FIRST( hit_list, &h->l ) )
01062 prev_hit = (struct hit_list *)NULL;
01063 else
01064 prev_hit = BU_LIST_PREV( hit_list, &hitp->l );
01065
01066
01067 tmp = hitp;
01068 BU_LIST_DEQUEUE( &tmp->l );
01069 BU_LIST_INSERT( &h->l, &tmp->l );
01070
01071 if( prev_hit )
01072 hitp = prev_hit;
01073 else
01074 hitp = BU_LIST_FIRST( hit_list, &h->l );
01075 }
01076 else
01077 hitp = next_hit;
01078 }
01079
01080
01081 hitp = BU_LIST_FIRST( hit_list, &h->l );
01082 while( BU_LIST_NEXT_NOT_HEAD( &hitp->l, &h->l ) )
01083 {
01084 next_hit = BU_LIST_NEXT( hit_list, &hitp->l );
01085
01086 if( NEAR_ZERO( hitp->hitp->hit_dist - next_hit->hitp->hit_dist, 0.00001) &&
01087 hitp->hitp->hit_surfno == next_hit->hitp->hit_surfno )
01088 {
01089 struct hit_list *tmp;
01090
01091 tmp = hitp;
01092 hitp = next_hit;
01093 BU_LIST_DEQUEUE( &tmp->l );
01094 bu_free( (char *)tmp->hitp, "rt_pipe_hitsort: tmp->hitp" );
01095 bu_free( (char *)tmp, "rt_pipe_hitsort: tmp" );
01096 (*nh)--;
01097 tmp = hitp;
01098 next_hit = BU_LIST_NEXT( hit_list, &hitp->l );
01099 hitp = next_hit;
01100 BU_LIST_DEQUEUE( &tmp->l );
01101 bu_free( (char *)tmp->hitp, "rt_pipe_hitsort: tmp->hitp" );
01102 bu_free( (char *)tmp, "rt_pipe_hitsort: tmp" );
01103 (*nh)--;
01104 if( BU_LIST_IS_HEAD( &hitp->l, &h->l ) )
01105 break;
01106 }
01107 else
01108 hitp = next_hit;
01109 }
01110
01111 if( *nh == 1 )
01112 {
01113 while( BU_LIST_WHILE( hitp, hit_list, &h->l ) )
01114 {
01115 BU_LIST_DEQUEUE( &hitp->l );
01116 bu_free( (char *)hitp->hitp, "pipe_hitsort: hitp->hitp" );
01117 bu_free( (char *)hitp, "pipe_hitsort: hitp" );
01118 }
01119 (*nh) = 0;
01120 return;
01121 }
01122
01123 if( *nh == 0 || *nh == 2 )
01124 return;
01125
01126
01127 first = BU_LIST_FIRST( hit_list, &h->l );
01128 if( VDOT( first->hitp->hit_normal, rp->r_dir ) > 0.0 )
01129 {
01130
01131 bu_log( "ERROR: first hit on %s (surfno = %d) is an exit at (%g %g %g)\n",
01132 stp->st_dp->d_namep, first->hitp->hit_surfno, V3ARGS( first->hitp->hit_point ) );
01133 bu_log( "\tray start = (%.12e %.12e %.12e), ray dir = (%.12e %.12e %.12e)\n",
01134 V3ARGS( rp->r_pt ), V3ARGS( rp->r_dir ) );
01135
01136 while( BU_LIST_WHILE( hitp, hit_list, &h->l ) )
01137 {
01138 BU_LIST_DEQUEUE( &hitp->l );
01139 bu_free( (char *)hitp->hitp, "pipe_hitsort: hitp->hitp" );
01140 bu_free( (char *)hitp, "pipe_hitsort: hitp" );
01141 }
01142 (*nh) = 0;
01143 return;
01144 }
01145
01146 while( BU_LIST_NOT_HEAD( &first->l, &h->l ) )
01147 {
01148 second = BU_LIST_NEXT( hit_list, &first->l );
01149 if( BU_LIST_IS_HEAD( &second->l, &h->l ) )
01150 break;
01151
01152 while( BU_LIST_NOT_HEAD( &second->l, &h->l ) && VDOT( second->hitp->hit_normal, rp->r_dir ) < 0.0 )
01153 {
01154 prev = second;
01155 second = BU_LIST_NEXT( hit_list, &second->l );
01156 if( BU_LIST_NOT_HEAD( &second->l, &h->l ) )
01157 {
01158 BU_LIST_DEQUEUE( &prev->l );
01159 bu_free( (char *)prev->hitp, "pipe_hitsort: prev->hitp" );
01160 bu_free( (char *)prev, "pipe_hitsort: prev" );
01161 (*nh)--;
01162 }
01163 }
01164 prev = NULL;
01165 while( BU_LIST_NOT_HEAD( &second->l, &h->l ) && VDOT( second->hitp->hit_normal, rp->r_dir ) > 0.0 )
01166 {
01167 if( prev )
01168 {
01169 BU_LIST_DEQUEUE( &prev->l );
01170 bu_free( (char *)prev->hitp, "pipe_hitsort: prev->hitp" );
01171 bu_free( (char *)prev, "pipe_hitsort: prev" );
01172 (*nh)--;
01173 }
01174 prev = second;
01175 second = BU_LIST_NEXT( hit_list, &second->l );
01176 }
01177 first = second;
01178 }
01179 }
01180
01181
01182
01183
01184
01185
01186 void
01187 rt_pipe_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
01188 {
01189 register struct bu_list *pipe =
01190 (struct bu_list *)stp->st_specific;
01191 register struct id_pipe *pipe_id;
01192 register struct lin_pipe *pipe_lin;
01193 register struct bend_pipe *pipe_bend;
01194 LOCAL fastf_t w;
01195 LOCAL vect_t work;
01196 LOCAL vect_t work1;
01197 LOCAL int segno;
01198 LOCAL int i;
01199
01200 segno = hitp->hit_surfno/10;
01201
01202 pipe_id = BU_LIST_FIRST( id_pipe, pipe );
01203 for( i=1 ; i<segno ; i++ )
01204 pipe_id = BU_LIST_NEXT( id_pipe, &pipe_id->l );
01205
01206 pipe_lin = (struct lin_pipe *)pipe_id;
01207 pipe_bend = (struct bend_pipe *)pipe_id;
01208
01209 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
01210 switch( hitp->hit_surfno%10 )
01211 {
01212 case PIPE_LINEAR_TOP:
01213 VMOVE( hitp->hit_normal, pipe_lin->pipe_H );
01214 break;
01215 case PIPE_LINEAR_BASE:
01216 VREVERSE( hitp->hit_normal, pipe_lin->pipe_H );
01217 break;
01218 case PIPE_LINEAR_OUTER_BODY:
01219 MAT4X3VEC( hitp->hit_normal, pipe_lin->pipe_invRoS, hitp->hit_vpriv );
01220 VUNITIZE( hitp->hit_normal );
01221 break;
01222 case PIPE_LINEAR_INNER_BODY:
01223 MAT4X3VEC( hitp->hit_normal, pipe_lin->pipe_invRoS, hitp->hit_vpriv );
01224 VUNITIZE( hitp->hit_normal );
01225 VREVERSE( hitp->hit_normal, hitp->hit_normal );
01226 break;
01227 case PIPE_BEND_OUTER_BODY:
01228 w = hitp->hit_vpriv[X]*hitp->hit_vpriv[X] +
01229 hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y] +
01230 hitp->hit_vpriv[Z]*hitp->hit_vpriv[Z] +
01231 1.0 - pipe_bend->bend_alpha_o*pipe_bend->bend_alpha_o;
01232 VSET( work,
01233 ( w - 2.0 ) * hitp->hit_vpriv[X],
01234 ( w - 2.0 ) * hitp->hit_vpriv[Y],
01235 w * hitp->hit_vpriv[Z] );
01236 VUNITIZE( work );
01237 MAT3X3VEC( hitp->hit_normal, pipe_bend->bend_invR, work );
01238 break;
01239 case PIPE_BEND_INNER_BODY:
01240 w = hitp->hit_vpriv[X]*hitp->hit_vpriv[X] +
01241 hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y] +
01242 hitp->hit_vpriv[Z]*hitp->hit_vpriv[Z] +
01243 1.0 - pipe_bend->bend_alpha_o*pipe_bend->bend_alpha_o;
01244 VSET( work,
01245 ( w - 2.0 ) * hitp->hit_vpriv[X],
01246 ( w - 2.0 ) * hitp->hit_vpriv[Y],
01247 w * hitp->hit_vpriv[Z] );
01248 VUNITIZE( work );
01249 MAT3X3VEC( work1, pipe_bend->bend_invR, work );
01250 VREVERSE( hitp->hit_normal, work1 );
01251 break;
01252 case PIPE_BEND_BASE:
01253 VREVERSE( hitp->hit_normal, pipe_bend->bend_rb );
01254 break;
01255 case PIPE_BEND_TOP:
01256 VSUB2( work, pipe_bend->bend_end, pipe_bend->bend_V );
01257 VCROSS( hitp->hit_normal, pipe_bend->bend_N, work );
01258 VUNITIZE( hitp->hit_normal );
01259 break;
01260 default:
01261 bu_log( "rt_pipe_norm: Unrecognized surfno (%d)\n", hitp->hit_surfno );
01262 break;
01263 }
01264 }
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 int
01278 rt_pipe_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
01279 {
01280 register struct bu_list *head =
01281 (struct bu_list *)stp->st_specific;
01282 register struct id_pipe *pipe_id;
01283 register struct seg *segp;
01284 LOCAL struct hit_list hit_head;
01285 LOCAL struct hit_list *hitp;
01286 LOCAL int hit_count;
01287 LOCAL int total_hits;
01288 LOCAL int seg_no;
01289 LOCAL int i;
01290
01291 BU_LIST_INIT( &hit_head.l );
01292
01293 pipe_start_shot( stp, rp, ap, seghead, BU_LIST_FIRST( id_pipe, head ),
01294 &hit_head, &total_hits, 1 );
01295 seg_no = 0;
01296 for( BU_LIST_FOR( pipe_id, id_pipe, head ) )
01297 seg_no++;
01298 pipe_end_shot( stp, rp, ap, seghead, BU_LIST_LAST( id_pipe, head ),
01299 &hit_head, &hit_count, seg_no );
01300 total_hits += hit_count;
01301
01302 seg_no = 0;
01303 for( BU_LIST_FOR( pipe_id, id_pipe, head ) )
01304 {
01305 seg_no++;
01306
01307 if( !pipe_id->pipe_is_bend )
01308 {
01309 linear_pipe_shot( stp, rp, ap, seghead, (struct lin_pipe *)pipe_id,
01310 &hit_head, &hit_count, seg_no );
01311 total_hits += hit_count;
01312 }
01313 else
01314 {
01315 bend_pipe_shot( stp, rp, ap, seghead, (struct bend_pipe *)pipe_id,
01316 &hit_head, &hit_count, seg_no );
01317 total_hits += hit_count;
01318 }
01319 }
01320 if( !total_hits )
01321 return( 0 );
01322
01323
01324 for( BU_LIST_FOR( hitp, hit_list, &hit_head.l ) )
01325 rt_pipe_norm( hitp->hitp, stp , rp );
01326
01327 rt_pipe_hitsort( &hit_head, &total_hits, rp, stp );
01328
01329
01330 if( total_hits%2 )
01331 {
01332 i = 0;
01333 bu_log( "rt_pipe_shot: bad number of hits on solid %s (%d)\n", stp->st_dp->d_namep, total_hits );
01334 bu_log( "Ignoring this solid for this ray\n" );
01335 bu_log( "\tray start = (%e %e %e), ray dir = (%e %e %e)\n", V3ARGS( rp->r_pt ), V3ARGS( rp->r_dir ) );
01336 for( BU_LIST_FOR( hitp, hit_list, &hit_head.l ) )
01337 {
01338 point_t hit_pt;
01339
01340 bu_log( "#%d, dist = %g, surfno=%d\n" , ++i, hitp->hitp->hit_dist, hitp->hitp->hit_surfno );
01341 VJOIN1( hit_pt, rp->r_pt, hitp->hitp->hit_dist, rp->r_dir );
01342 bu_log( "\t( %g %g %g )\n" , V3ARGS( hit_pt ) );
01343 }
01344
01345
01346 while( BU_LIST_WHILE( hitp, hit_list, &hit_head.l ) )
01347 {
01348 BU_LIST_DEQUEUE( &hitp->l );
01349 bu_free( (char *)hitp->hitp, "rt_pipe_shot: hitp->hitp" );
01350 bu_free( (char *)hitp, "rt_pipe_shot: hitp" );
01351 }
01352
01353 return( 0 );
01354 }
01355
01356 hitp = BU_LIST_FIRST( hit_list, &hit_head.l );
01357 while( BU_LIST_NOT_HEAD( &hitp->l, &hit_head.l ) )
01358 {
01359 struct hit_list *next;
01360
01361 next = BU_LIST_NEXT( hit_list, &hitp->l );
01362
01363 RT_GET_SEG(segp, ap->a_resource);
01364
01365 segp->seg_stp = stp;
01366 segp->seg_in = (*hitp->hitp);
01367 segp->seg_out = (*next->hitp);
01368
01369 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
01370
01371 hitp = BU_LIST_NEXT( hit_list, &next->l );
01372 }
01373
01374
01375 while( BU_LIST_WHILE( hitp, hit_list, &hit_head.l ) )
01376 {
01377 BU_LIST_DEQUEUE( &hitp->l );
01378 bu_free( (char *)hitp->hitp, "rt_pipe_shot: hitp->hitp" );
01379 bu_free( (char *)hitp, "rt_pipe_shot: hitp" );
01380 }
01381
01382 if( total_hits )
01383 return( 1 );
01384 else
01385 return(0);
01386 }
01387
01388 #define SEG_MISS(SEG) (SEG).seg_stp=(struct soltab *) 0;
01389
01390
01391
01392
01393
01394
01395 void
01396 rt_pipe_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
01397
01398
01399
01400
01401
01402 {
01403 rt_vstub( stp, rp, segp, n, ap );
01404 }
01405
01406
01407
01408
01409
01410
01411 void
01412 rt_pipe_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
01413 {
01414
01415
01416
01417 cvp->crv_c1 = cvp->crv_c2 = 0;
01418
01419
01420 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
01421 }
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431 void
01432 rt_pipe_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
01433 {
01434
01435
01436 }
01437
01438
01439
01440
01441 void
01442 rt_pipe_free(register struct soltab *stp)
01443 {
01444 #if 0
01445 register struct bu_list *pipe =
01446 (struct bu_list *)stp->st_specific;
01447
01448
01449 while( BU_LIST_NON_EMPTY( &pipe->id.l ) )
01450 {
01451 register struct bu_list *pipe_ptr;
01452
01453 pipe_ptr = (struct bu_list *)(&pipe->id.l)->forw;
01454 bu_free( (char *)pipe_ptr, "pipe_specific" );
01455 }
01456
01457
01458 bu_free( (char *)pipe, "pipe_specific head" );
01459 #endif
01460 }
01461
01462
01463
01464
01465 int
01466 rt_pipe_class(void)
01467 {
01468 return(0);
01469 }
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480 HIDDEN void
01481 draw_pipe_arc(struct bu_list *vhead, fastf_t radius, fastf_t *center, const fastf_t *v1, const fastf_t *v2, fastf_t *end, int seg_count, int full_circle)
01482 {
01483 fastf_t arc_angle;
01484 fastf_t delta_ang;
01485 fastf_t cos_del, sin_del;
01486 fastf_t x, y, xnew, ynew;
01487 vect_t to_end;
01488 point_t pt;
01489 int i;
01490
01491 if( !full_circle )
01492 {
01493 VSUB2( to_end, end, center );
01494 arc_angle = atan2( VDOT( to_end, v2 ), VDOT( to_end, v1 ) );
01495 delta_ang = arc_angle/seg_count;
01496 }
01497 else
01498 delta_ang = 2.0*bn_pi/seg_count;
01499
01500 cos_del = cos( delta_ang );
01501 sin_del = sin( delta_ang );
01502
01503 x = radius;
01504 y = 0.0;
01505 VJOIN2( pt, center, x, v1, y, v2 );
01506 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01507 for( i=0 ; i<seg_count ; i++ )
01508 {
01509 xnew = x*cos_del - y*sin_del;
01510 ynew = x*sin_del + y*cos_del;
01511 VJOIN2( pt, center, xnew, v1, ynew, v2 );
01512 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01513 x = xnew;
01514 y = ynew;
01515 }
01516 }
01517
01518 HIDDEN void
01519 draw_linear_seg(struct bu_list *vhead, const fastf_t *p1, const fastf_t or1, const fastf_t ir1, const fastf_t *p2, const fastf_t or2, const fastf_t ir2, const fastf_t *v1, const fastf_t *v2)
01520 {
01521 point_t pt;
01522
01523 VJOIN1( pt, p1, or1, v1 );
01524 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01525 VJOIN1( pt, p2, or2, v1 );
01526 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01527 VJOIN1( pt, p1, or1, v2 );
01528 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01529 VJOIN1( pt, p2, or2, v2 );
01530 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01531 VJOIN1( pt, p1, -or1, v1 );
01532 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01533 VJOIN1( pt, p2, -or2, v1 );
01534 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01535 VJOIN1( pt, p1, -or1, v2 );
01536 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01537 VJOIN1( pt, p2, -or2, v2 );
01538 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01539
01540 if( ir1 <= 0.0 && ir2 <= 0.0 )
01541 return;
01542
01543 VJOIN1( pt, p1, ir1, v1 );
01544 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01545 VJOIN1( pt, p2, ir2, v1 );
01546 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01547 VJOIN1( pt, p1, ir1, v2 );
01548 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01549 VJOIN1( pt, p2, ir2, v2 );
01550 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01551 VJOIN1( pt, p1, -ir1, v1 );
01552 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01553 VJOIN1( pt, p2, -ir2, v1 );
01554 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01555 VJOIN1( pt, p1, -ir1, v2 );
01556 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
01557 VJOIN1( pt, p2, -ir2, v2 );
01558 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
01559 }
01560
01561 HIDDEN void
01562 draw_pipe_bend(struct bu_list *vhead, const fastf_t *center, const fastf_t *end, const fastf_t radius, const fastf_t angle, const fastf_t *v1, const fastf_t *v2, const fastf_t *norm, const fastf_t or, const fastf_t ir, fastf_t *f1, fastf_t *f2, const int
01563 seg_count)
01564 {
01565
01566 point_t tmp_center, tmp_start, tmp_end;
01567 vect_t tmp_vec;
01568 fastf_t tmp_radius;
01569 fastf_t move_dist;
01570 vect_t end_f1,end_f2;
01571 mat_t mat;
01572 vect_t tmp_norm;
01573
01574 VREVERSE( tmp_norm, norm );
01575 bn_mat_arb_rot( mat, center, tmp_norm, angle );
01576 MAT4X3VEC( tmp_vec, mat, f1 );
01577 VMOVE( end_f1, tmp_vec );
01578 MAT4X3VEC( tmp_vec, mat, f2 );
01579 VMOVE( end_f2, tmp_vec );
01580
01581 move_dist = or * VDOT( f1, norm );
01582 VJOIN2( tmp_start, center, radius, v1, or, f1 );
01583 VJOIN1( tmp_center, center, move_dist, norm );
01584 VJOIN1( tmp_end, end, or, end_f1 );
01585 VSUB2( tmp_vec, tmp_start, tmp_center );
01586 tmp_radius = MAGNITUDE( tmp_vec );
01587 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01588 VJOIN2( tmp_start, center, radius, v1, -or, f1 );
01589 VJOIN1( tmp_center, center, -move_dist, norm );
01590 VJOIN1( tmp_end, end, -or, end_f1 );
01591 VSUB2( tmp_vec, tmp_start, tmp_center );
01592 tmp_radius = MAGNITUDE( tmp_vec );
01593 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01594 move_dist = or * VDOT( f2, norm );
01595 VJOIN2( tmp_start, center, radius, v1, or, f2 );
01596 VJOIN1( tmp_center, center, move_dist, norm );
01597 VJOIN1( tmp_end, end, or, end_f2 );
01598 VSUB2( tmp_vec, tmp_start, tmp_center );
01599 tmp_radius = MAGNITUDE( tmp_vec );
01600 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01601 VJOIN2( tmp_start, center, radius, v1, -or, f2 );
01602 VJOIN1( tmp_center, center, -move_dist, norm );
01603 VJOIN1( tmp_end, end, -or, end_f2 );
01604 VSUB2( tmp_vec, tmp_start, tmp_center );
01605 tmp_radius = MAGNITUDE( tmp_vec );
01606 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01607
01608 if( ir <= 0.0 )
01609 {
01610 VMOVE( f1, end_f1 );
01611 VMOVE( f2, end_f2 );
01612 return;
01613 }
01614
01615 move_dist = ir * VDOT( f1, norm );
01616 VJOIN2( tmp_start, center, radius, v1, ir, f1 );
01617 VJOIN1( tmp_center, center, move_dist, norm );
01618 VJOIN1( tmp_end, end, ir, end_f1 );
01619 VSUB2( tmp_vec, tmp_start, tmp_center );
01620 tmp_radius = MAGNITUDE( tmp_vec );
01621 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01622 VJOIN2( tmp_start, center, radius, v1, -ir, f1 );
01623 VJOIN1( tmp_center, center, -move_dist, norm );
01624 VJOIN1( tmp_end, end, -ir, end_f1 );
01625 VSUB2( tmp_vec, tmp_start, tmp_center );
01626 tmp_radius = MAGNITUDE( tmp_vec );
01627 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01628 move_dist = ir * VDOT( f2, norm );
01629 VJOIN2( tmp_start, center, radius, v1, ir, f2 );
01630 VJOIN1( tmp_center, center, move_dist, norm );
01631 VJOIN1( tmp_end, end, ir, end_f2 );
01632 VSUB2( tmp_vec, tmp_start, tmp_center );
01633 tmp_radius = MAGNITUDE( tmp_vec );
01634 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01635 VJOIN2( tmp_start, center, radius, v1, -ir, f2 );
01636 VJOIN1( tmp_center, center, -move_dist, norm );
01637 VJOIN1( tmp_end, end, -ir, end_f2 );
01638 VSUB2( tmp_vec, tmp_start, tmp_center );
01639 tmp_radius = MAGNITUDE( tmp_vec );
01640 draw_pipe_arc( vhead, tmp_radius, tmp_center, v1, v2, tmp_end, seg_count, 0 );
01641
01642 VMOVE( f1, end_f1 );
01643 VMOVE( f2, end_f2 );
01644 }
01645
01646
01647
01648
01649 int
01650 rt_pipe_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01651 {
01652 register struct wdb_pipept *prevp;
01653 register struct wdb_pipept *curp;
01654 register struct wdb_pipept *nextp;
01655 LOCAL struct rt_pipe_internal *pip;
01656 LOCAL point_t current_point;
01657 LOCAL vect_t f1,f2,f3;
01658
01659 RT_CK_DB_INTERNAL(ip);
01660 pip = (struct rt_pipe_internal *)ip->idb_ptr;
01661 RT_PIPE_CK_MAGIC(pip);
01662
01663 if( BU_LIST_IS_EMPTY( &pip->pipe_segs_head ) )
01664 return( 0 );
01665
01666 prevp = BU_LIST_FIRST( wdb_pipept, &pip->pipe_segs_head );
01667 curp = BU_LIST_NEXT( wdb_pipept, &prevp->l );
01668 nextp = BU_LIST_NEXT( wdb_pipept, &curp->l );
01669
01670 if( BU_LIST_IS_HEAD( &curp->l , &pip->pipe_segs_head ) )
01671 return( 0 );
01672
01673 VMOVE( current_point, prevp->pp_coord );
01674
01675
01676 VSUB2( f3, prevp->pp_coord, curp->pp_coord );
01677 bn_vec_ortho( f1, f3 );
01678 VCROSS( f2, f3, f1 );
01679 VUNITIZE( f2 );
01680
01681 draw_pipe_arc( vhead, prevp->pp_od/2.0, prevp->pp_coord, f1, f2, f2, ARC_SEGS, 1 );
01682 if( prevp->pp_id > 0.0 )
01683 draw_pipe_arc( vhead, prevp->pp_id/2.0, prevp->pp_coord, f1, f2, f2, ARC_SEGS, 1 );
01684
01685 while( 1 )
01686 {
01687 LOCAL vect_t n1,n2;
01688 LOCAL vect_t norm;
01689 LOCAL fastf_t angle;
01690 LOCAL fastf_t dist_to_bend;
01691
01692 if( BU_LIST_IS_HEAD( &nextp->l, &pip->pipe_segs_head ) )
01693 {
01694
01695 draw_linear_seg( vhead, current_point, prevp->pp_od/2.0, prevp->pp_id/2.0,
01696 curp->pp_coord, curp->pp_od/2.0, curp->pp_id/2.0, f1, f2 );
01697 break;
01698 }
01699
01700 VSUB2( n1, prevp->pp_coord, curp->pp_coord );
01701 if( VNEAR_ZERO( n1, SQRT_SMALL_FASTF ) )
01702 {
01703
01704 goto next_pt;
01705 }
01706 VSUB2( n2, nextp->pp_coord, curp->pp_coord );
01707 VCROSS( norm, n1, n2 );
01708 VUNITIZE( n1 );
01709 VUNITIZE( n2 );
01710 angle = bn_pi - acos( VDOT( n1, n2 ) );
01711 dist_to_bend = curp->pp_bendradius * tan( angle/2.0 );
01712 if( isnan( dist_to_bend ) || VNEAR_ZERO( norm, SQRT_SMALL_FASTF) || NEAR_ZERO( dist_to_bend, SQRT_SMALL_FASTF) )
01713 {
01714
01715 draw_linear_seg( vhead, current_point, prevp->pp_od/2.0, prevp->pp_id/2.0,
01716 curp->pp_coord, curp->pp_od/2.0, curp->pp_id/2.0, f1, f2 );
01717 VMOVE( current_point, curp->pp_coord );
01718 }
01719 else
01720 {
01721 LOCAL point_t bend_center;
01722 LOCAL point_t bend_start;
01723 LOCAL point_t bend_end;
01724 LOCAL vect_t v1,v2;
01725
01726 VUNITIZE( norm );
01727
01728
01729 VJOIN1( bend_start, curp->pp_coord, dist_to_bend, n1 );
01730 draw_linear_seg( vhead, current_point, prevp->pp_od/2.0, prevp->pp_id/2.0,
01731 bend_start, curp->pp_od/2.0, curp->pp_id/2.0, f1, f2 );
01732
01733
01734 VJOIN1( bend_end, curp->pp_coord, dist_to_bend, n2 );
01735 VCROSS( v1, n1, norm );
01736 VCROSS( v2, v1, norm );
01737 VJOIN1( bend_center, bend_start, -curp->pp_bendradius, v1 );
01738 draw_pipe_bend( vhead, bend_center, bend_end, curp->pp_bendradius, angle, v1, v2, norm,
01739 curp->pp_od/2.0, curp->pp_id/2.0, f1, f2, ARC_SEGS );
01740
01741 VMOVE( current_point, bend_end );
01742 }
01743 next_pt:
01744 prevp = curp;
01745 curp = nextp;
01746 nextp = BU_LIST_NEXT( wdb_pipept, &curp->l );
01747 }
01748
01749 draw_pipe_arc( vhead, curp->pp_od/2.0, curp->pp_coord, f1, f2, f2, ARC_SEGS, 1 );
01750 if( curp->pp_id > 0.0 )
01751 draw_pipe_arc( vhead, curp->pp_id/2.0, curp->pp_coord, f1, f2, f2, ARC_SEGS, 1 );
01752
01753 return(0);
01754 }
01755
01756 HIDDEN void
01757 tesselate_pipe_start(struct wdb_pipept *pipe, int arc_segs, double sin_del, double cos_del, struct vertex ***outer_loop, struct vertex ***inner_loop, fastf_t *r1, fastf_t *r2, struct shell *s, const struct bn_tol *tol)
01758 {
01759 struct faceuse *fu;
01760 struct loopuse *lu;
01761 struct edgeuse *eu;
01762 struct wdb_pipept *next;
01763 point_t pt;
01764 fastf_t or;
01765 fastf_t ir;
01766 fastf_t x,y,xnew,ynew;
01767 vect_t n;
01768 int i;
01769
01770 NMG_CK_SHELL( s );
01771 BN_CK_TOL( tol );
01772
01773 next = BU_LIST_NEXT( wdb_pipept, &pipe->l );
01774
01775 VSUB2( n, pipe->pp_coord, next->pp_coord );
01776 VUNITIZE( n );
01777 bn_vec_ortho( r1, n );
01778 VCROSS( r2, n, r1 );
01779
01780 or = pipe->pp_od/2.0;
01781 ir = pipe->pp_id/2.0;
01782
01783 if( or <= tol->dist )
01784 return;
01785
01786 if( ir > or )
01787 {
01788 bu_log( "Inner radius larger than outer radius at start of pipe solid\n" );
01789 return;
01790 }
01791
01792 if( NEAR_ZERO( ir - or, tol->dist) )
01793 return;
01794
01795
01796 fu = nmg_cface( s, *outer_loop, arc_segs );
01797
01798 x = or;
01799 y = 0.0;
01800 i = (-1);
01801 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
01802 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
01803 {
01804 VJOIN2( pt, pipe->pp_coord, x, r1, y, r2 );
01805 (*outer_loop)[++i] = eu->vu_p->v_p;
01806 nmg_vertex_gv( eu->vu_p->v_p, pt );
01807 xnew = x*cos_del - y*sin_del;
01808 ynew = x*sin_del + y*cos_del;
01809 x = xnew;
01810 y = ynew;
01811 }
01812
01813 if( ir > tol->dist )
01814 {
01815 struct edgeuse *new_eu;
01816 struct vertexuse *vu;
01817
01818
01819 lu = nmg_mlv( &fu->l.magic, (struct vertex *)NULL, OT_OPPOSITE );
01820
01821 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
01822 eu = nmg_meonvu( vu );
01823 (*inner_loop)[0] = eu->vu_p->v_p;
01824
01825 x = ir;
01826 y = 0.0;
01827 VJOIN2( pt, pipe->pp_coord, x, r1, y, r2 );
01828 nmg_vertex_gv( (*inner_loop)[0], pt );
01829
01830 for( i=1 ; i<arc_segs ; i++ )
01831 {
01832 new_eu = nmg_eusplit( (struct vertex *)NULL, eu, 0 );
01833 (*inner_loop)[i] = new_eu->vu_p->v_p;
01834 xnew = x*cos_del - y*sin_del;
01835 ynew = x*sin_del + y*cos_del;
01836 x = xnew;
01837 y = ynew;
01838 VJOIN2( pt, pipe->pp_coord, x, r1, y, r2 );
01839 nmg_vertex_gv( (*inner_loop)[i], pt );
01840 }
01841 }
01842
01843 else if( next->pp_id > tol->dist )
01844 {
01845 struct vertexuse *vu;
01846
01847
01848 lu = nmg_mlv( &fu->l.magic, (struct vertex *)NULL, OT_OPPOSITE );
01849 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
01850
01851 nmg_vertex_gv( vu->v_p, pipe->pp_coord );
01852 }
01853
01854 if( nmg_calc_face_g( fu ) )
01855 rt_bomb( "tesselate_pipe_start: nmg_calc_face_g failed\n" );
01856
01857 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
01858 {
01859 NMG_CK_LOOPUSE( lu );
01860
01861 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
01862 continue;
01863
01864 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
01865 {
01866 NMG_CK_EDGEUSE( eu );
01867 eu->e_p->is_real = 1;
01868 }
01869 }
01870 }
01871
01872 HIDDEN void
01873 tesselate_pipe_linear(fastf_t *start_pt,
01874 fastf_t or,
01875 fastf_t ir,
01876 fastf_t *end_pt,
01877 fastf_t end_or,
01878 fastf_t end_ir,
01879 int arc_segs,
01880 double sin_del,
01881 double cos_del,
01882 struct vertex ***outer_loop,
01883 struct vertex ***inner_loop,
01884 fastf_t *r1,
01885 fastf_t *r2,
01886 struct shell *s,
01887 const struct bn_tol *tol)
01888 {
01889 struct vertex **new_outer_loop;
01890 struct vertex **new_inner_loop;
01891 struct vertex **verts[3];
01892 struct faceuse *fu;
01893 vect_t *norms;
01894 vect_t n;
01895 fastf_t slope;
01896 fastf_t seg_len;
01897 int i,j;
01898
01899 NMG_CK_SHELL( s );
01900 BN_CK_TOL( tol );
01901
01902 norms = (vect_t *)bu_calloc( arc_segs, sizeof( vect_t ), "tesselate_pipe_linear: new normals" );
01903
01904 if( end_or > tol->dist )
01905 new_outer_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
01906 "tesselate_pipe_linear: new_outer_loop" );
01907 else
01908 new_outer_loop = (struct vertex **)NULL;
01909
01910 if( end_ir > tol->dist )
01911 new_inner_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
01912 "tesselate_pipe_linear: new_inner_loop" );
01913 else
01914 new_inner_loop = (struct vertex **)NULL;
01915
01916 VSUB2( n, end_pt, start_pt );
01917 seg_len = MAGNITUDE( n );
01918 VSCALE( n, n, 1.0/seg_len );
01919 slope = (or - end_or)/seg_len;
01920
01921 if( or > tol->dist && end_or > tol->dist )
01922 {
01923 point_t pt;
01924 fastf_t x,y,xnew,ynew;
01925 struct faceuse *fu_prev=(struct faceuse *)NULL;
01926 struct vertex **verts[3];
01927
01928 x = 1.0;
01929 y = 0.0;
01930 VCOMB2( norms[0], x, r1, y, r2 );
01931 VJOIN1( norms[0], norms[0], slope, n );
01932 VUNITIZE( norms[0] );
01933 for( i=0 ; i<arc_segs ; i++ )
01934 {
01935 j = i+1;
01936 if( j == arc_segs )
01937 j = 0;
01938
01939 VJOIN2( pt, end_pt, x*end_or, r1, y*end_or, r2 );
01940 xnew = x*cos_del - y*sin_del;
01941 ynew = x*sin_del + y*cos_del;
01942 x = xnew;
01943 y = ynew;
01944 if( i < arc_segs-1 )
01945 {
01946 VCOMB2( norms[j], x, r1, y, r2 );
01947 VJOIN1( norms[j], norms[j], slope, n );
01948 VUNITIZE( norms[j] );
01949 }
01950
01951 if( fu_prev )
01952 {
01953 nmg_vertex_gv( new_outer_loop[i], pt );
01954 if( nmg_calc_face_g( fu_prev ) )
01955 {
01956 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
01957 nmg_kfu( fu_prev );
01958 }
01959 else
01960 {
01961
01962 struct loopuse *lu;
01963 struct edgeuse *eu;
01964
01965 NMG_CK_FACEUSE( fu_prev );
01966
01967 if( fu_prev->orientation != OT_SAME )
01968 fu_prev = fu_prev->fumate_p;
01969
01970 lu = BU_LIST_FIRST( loopuse, &fu_prev->lu_hd );
01971
01972 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
01973 {
01974 vect_t reverse_norm;
01975 struct edgeuse *eu_opp_use;
01976
01977 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
01978 if( eu->vu_p->v_p == new_outer_loop[i-1] )
01979 {
01980 nmg_vertexuse_nv( eu->vu_p, norms[i-1] );
01981 VREVERSE( reverse_norm, norms[i-1] );
01982 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
01983 }
01984 else if( eu->vu_p->v_p == (*outer_loop)[i-1] )
01985 {
01986 nmg_vertexuse_nv( eu->vu_p, norms[i-1] );
01987 VREVERSE( reverse_norm, norms[i-1] );
01988 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
01989 }
01990 else if( eu->vu_p->v_p == new_outer_loop[i] )
01991 {
01992 nmg_vertexuse_nv( eu->vu_p, norms[i] );
01993 VREVERSE( reverse_norm, norms[i] );
01994 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
01995 }
01996 else if( eu->vu_p->v_p == (*outer_loop)[i] )
01997 {
01998 nmg_vertexuse_nv( eu->vu_p, norms[i] );
01999 VREVERSE( reverse_norm, norms[i] );
02000 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02001 }
02002 else
02003 {
02004 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02005 bu_log( "\ti=%d, arc_segs=%d, fu_prev = x%x\n" , i, arc_segs, fu_prev );
02006 }
02007 }
02008 }
02009 }
02010
02011 verts[0] = &(*outer_loop)[j];
02012 verts[1] = &(*outer_loop)[i];
02013 verts[2] = &new_outer_loop[i];
02014
02015 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02016 {
02017 bu_log( "tesselate_pipe_linear: failed to make outer face #%d or=%g, end_or=%g\n",
02018 i, or, end_or );
02019 continue;
02020 }
02021 if( !new_outer_loop[i]->vg_p )
02022 nmg_vertex_gv( new_outer_loop[i], pt );
02023
02024 if( nmg_calc_face_g( fu ) )
02025 {
02026 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02027 nmg_kfu( fu );
02028 }
02029 else
02030 {
02031
02032 struct loopuse *lu;
02033 struct edgeuse *eu;
02034
02035 NMG_CK_FACEUSE( fu );
02036
02037 if( fu->orientation != OT_SAME )
02038 fu = fu->fumate_p;
02039
02040 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02041
02042 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02043 {
02044 vect_t reverse_norm;
02045 struct edgeuse *eu_opp_use;
02046
02047 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02048 if( eu->vu_p->v_p == (*outer_loop)[0] )
02049 {
02050 nmg_vertexuse_nv( eu->vu_p, norms[0] );
02051 VREVERSE( reverse_norm, norms[0] );
02052 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02053 }
02054 else if( eu->vu_p->v_p == new_outer_loop[i] )
02055 {
02056 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02057 VREVERSE( reverse_norm, norms[i] );
02058 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02059 }
02060 else if( eu->vu_p->v_p == (*outer_loop)[i] )
02061 {
02062 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02063 VREVERSE( reverse_norm, norms[i] );
02064 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02065 }
02066 else if( eu->vu_p->v_p == (*outer_loop)[j] )
02067 {
02068 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02069 VREVERSE( reverse_norm, norms[j] );
02070 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02071 }
02072 else
02073 {
02074 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02075 bu_log( "\ti=%d, arc_segs=%d, fu = x%x\n" , i, arc_segs, fu );
02076 }
02077 }
02078 }
02079
02080 verts[1] = verts[2];
02081 verts[2] = &new_outer_loop[j];
02082
02083 if( (fu_prev = nmg_cmface( s, verts, 3 ) ) == NULL )
02084 {
02085 bu_log( "tesselate_pipe_linear: failed to make outer face #%d or=%g, end_or=%g\n",
02086 i, or, end_or );
02087 continue;
02088 }
02089 if( i == arc_segs-1 )
02090 {
02091 if( nmg_calc_face_g( fu_prev ) )
02092 {
02093 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02094 nmg_kfu( fu_prev );
02095 }
02096 }
02097 }
02098 bu_free( (char *)(*outer_loop), "tesselate_pipe_bend: outer_loop" );
02099 *outer_loop = new_outer_loop;
02100 }
02101 else if( or > tol->dist && end_or <= tol->dist )
02102 {
02103 struct vertex *v=(struct vertex *)NULL;
02104
02105 VSUB2( norms[0], (*outer_loop)[0]->vg_p->coord, start_pt );
02106 VJOIN1( norms[0], norms[0], slope*or, n );
02107 VUNITIZE( norms[0] );
02108 for( i=0 ; i<arc_segs; i++ )
02109 {
02110 j = i+1;
02111 if( j == arc_segs )
02112 j = 0;
02113
02114 verts[0] = &(*outer_loop)[j];
02115 verts[1] = &(*outer_loop)[i];
02116 verts[2] = &v;
02117
02118 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02119 {
02120 bu_log( "tesselate_pipe_linear: failed to make outer face #%d or=%g, end_or=%g\n",
02121 i, or, end_or );
02122 continue;
02123 }
02124 if( i == 0 )
02125 nmg_vertex_gv( v, end_pt );
02126
02127 if( i < arc_segs-1 )
02128 {
02129 VSUB2( norms[j], (*outer_loop)[j]->vg_p->coord, start_pt );
02130 VJOIN1( norms[j], norms[j], slope*or, n );
02131 VUNITIZE( norms[j] );
02132 }
02133
02134 if( nmg_calc_face_g( fu ) )
02135 {
02136 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02137 nmg_kfu( fu );
02138 }
02139 else
02140 {
02141 struct loopuse *lu;
02142 struct edgeuse *eu;
02143 struct edgeuse *eu_opp_use;
02144 vect_t reverse_norm;
02145
02146 NMG_CK_FACEUSE( fu );
02147 if( fu->orientation != OT_SAME )
02148 fu = fu->fumate_p;
02149
02150 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02151 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02152 {
02153 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02154 if( eu->vu_p->v_p == (*outer_loop)[i] )
02155 {
02156 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02157 VREVERSE( reverse_norm, norms[i] );
02158 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02159 }
02160 else if( eu->vu_p->v_p == (*outer_loop)[j] )
02161 {
02162 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02163 VREVERSE( reverse_norm, norms[j] );
02164 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02165 }
02166 else if( eu->vu_p->v_p == v )
02167 {
02168 vect_t tmp_norm;
02169 VBLEND2( tmp_norm, 0.5, norms[i], 0.5, norms[j] );
02170 VUNITIZE( tmp_norm );
02171 nmg_vertexuse_nv( eu->vu_p, tmp_norm );
02172 VREVERSE( reverse_norm, tmp_norm );
02173 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02174 }
02175 else
02176 {
02177 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02178 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02179 }
02180 }
02181 }
02182 }
02183
02184 bu_free( (char *)(*outer_loop), "tesselate_pipe_linear: outer_loop" );
02185 outer_loop[0] = &v;
02186 }
02187 else if( or <= tol->dist && end_or > tol->dist )
02188 {
02189 point_t pt,pt_next;
02190 fastf_t x,y,xnew,ynew;
02191 struct vertex **verts[3];
02192
02193
02194 x = 1.0;
02195 y = 0.0;
02196 VCOMB2( norms[0], x, r1, y, r2 );
02197 VJOIN1( pt_next, end_pt, end_or, norms[0] );
02198 VJOIN1( norms[0], norms[0], slope, n );
02199 VUNITIZE( norms[0] );
02200 for( i=0 ; i<arc_segs; i++ )
02201 {
02202 j = i + 1;
02203 if( j == arc_segs )
02204 j = 0;
02205
02206 VMOVE( pt, pt_next )
02207 xnew = x*cos_del - y*sin_del;
02208 ynew = x*sin_del + y*cos_del;
02209 x = xnew;
02210 y = ynew;
02211 if( i < j )
02212 {
02213 VCOMB2( norms[j], x, r1, y, r2 );
02214 VJOIN1( pt_next, end_pt, end_or, norms[j] );
02215 VJOIN1( norms[j], norms[j], slope, n );
02216 VUNITIZE( norms[j] );
02217 }
02218
02219 verts[0] = &(*outer_loop)[0];
02220 verts[1] = &new_outer_loop[i];
02221 verts[2] = &new_outer_loop[j];
02222
02223 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02224 {
02225 bu_log( "tesselate_pipe_linear: failed to make outer face #%d or=%g, end_or=%g\n",
02226 i, or, end_or );
02227 continue;
02228 }
02229 if( !(*outer_loop)[0]->vg_p )
02230 nmg_vertex_gv( (*outer_loop)[0], start_pt );
02231 if( !new_outer_loop[i]->vg_p )
02232 nmg_vertex_gv( new_outer_loop[i], pt );
02233 if( !new_outer_loop[j]->vg_p )
02234 nmg_vertex_gv( new_outer_loop[j], pt_next );
02235 if( nmg_calc_face_g( fu ) )
02236 {
02237 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02238 nmg_kfu( fu );
02239 }
02240 else
02241 {
02242 struct loopuse *lu;
02243 struct edgeuse *eu;
02244 struct edgeuse *eu_opp_use;
02245 vect_t reverse_norm;
02246
02247 NMG_CK_FACEUSE( fu );
02248 if( fu->orientation != OT_SAME )
02249 fu = fu->fumate_p;
02250
02251 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02252 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02253 {
02254 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02255 if( eu->vu_p->v_p == new_outer_loop[i] )
02256 {
02257 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02258 VREVERSE( reverse_norm, norms[i] );
02259 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02260 }
02261 else if( eu->vu_p->v_p == new_outer_loop[j] )
02262 {
02263 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02264 VREVERSE( reverse_norm, norms[j] );
02265 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02266 }
02267 else if( eu->vu_p->v_p == (*outer_loop)[0] )
02268 {
02269 vect_t tmp_norm;
02270 VBLEND2( tmp_norm, 0.5, norms[i], 0.5, norms[j] );
02271 VUNITIZE( tmp_norm );
02272 nmg_vertexuse_nv( eu->vu_p, tmp_norm );
02273 VREVERSE( reverse_norm, tmp_norm );
02274 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02275 }
02276 else
02277 {
02278 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02279 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02280 }
02281 }
02282 }
02283 }
02284 bu_free( (char *)(*outer_loop), "tesselate_pipe_linear: outer_loop" );
02285 *outer_loop = new_outer_loop;
02286 }
02287
02288 slope = (ir - end_ir)/seg_len;
02289
02290 if( ir > tol->dist && end_ir > tol->dist )
02291 {
02292 point_t pt;
02293 fastf_t x,y,xnew,ynew;
02294 struct faceuse *fu_prev=(struct faceuse *)NULL;
02295 struct vertex **verts[3];
02296
02297 x = 1.0;
02298 y = 0.0;
02299 VCOMB2( norms[0], -x, r1, -y, r2 );
02300 VJOIN1( norms[0], norms[0], -slope, n );
02301 VUNITIZE( norms[0] );
02302 for( i=0 ; i<arc_segs ; i++ )
02303 {
02304 j = i+1;
02305 if( j == arc_segs )
02306 j = 0;
02307
02308 VJOIN2( pt, end_pt, x*end_ir, r1, y*end_ir, r2 );
02309 xnew = x*cos_del - y*sin_del;
02310 ynew = x*sin_del + y*cos_del;
02311 x = xnew;
02312 y = ynew;
02313 if( i < arc_segs-1 )
02314 {
02315 VCOMB2( norms[j], -x, r1, -y, r2 );
02316 VJOIN1( norms[j], norms[j], -slope, n );
02317 VUNITIZE( norms[j] );
02318 }
02319
02320 if( fu_prev )
02321 {
02322 nmg_vertex_gv( new_inner_loop[i], pt );
02323 if( nmg_calc_face_g( fu_prev ) )
02324 {
02325 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02326 nmg_kfu( fu_prev );
02327 }
02328 else
02329 {
02330
02331 struct loopuse *lu;
02332 struct edgeuse *eu;
02333
02334 NMG_CK_FACEUSE( fu_prev );
02335
02336 if( fu_prev->orientation != OT_SAME )
02337 fu_prev = fu_prev->fumate_p;
02338
02339 lu = BU_LIST_FIRST( loopuse, &fu_prev->lu_hd );
02340
02341 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02342 {
02343 vect_t reverse_norm;
02344 struct edgeuse *eu_opp_use;
02345
02346 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02347 if( eu->vu_p->v_p == new_inner_loop[i-1] )
02348 {
02349 nmg_vertexuse_nv( eu->vu_p, norms[i-1] );
02350 VREVERSE( reverse_norm, norms[i-1] );
02351 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02352 }
02353 else if( eu->vu_p->v_p == (*inner_loop)[i-1] )
02354 {
02355 nmg_vertexuse_nv( eu->vu_p, norms[i-1] );
02356 VREVERSE( reverse_norm, norms[i-1] );
02357 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02358 }
02359 else if( eu->vu_p->v_p == new_inner_loop[i] )
02360 {
02361 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02362 VREVERSE( reverse_norm, norms[i] );
02363 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02364 }
02365 else if( eu->vu_p->v_p == (*inner_loop)[i] )
02366 {
02367 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02368 VREVERSE( reverse_norm, norms[i] );
02369 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02370 }
02371 else
02372 {
02373 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02374 bu_log( "\ti=%d, arc_segs=%d, fu_prev = x%x\n" , i, arc_segs, fu_prev );
02375 }
02376 }
02377 }
02378 }
02379
02380 verts[0] = &(*inner_loop)[j];
02381 verts[1] = &new_inner_loop[i];
02382 verts[2] = &(*inner_loop)[i];
02383
02384 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02385 {
02386 bu_log( "tesselate_pipe_linear: failed to make inner face #%d ir=%g, end_ir=%g\n",
02387 i, ir, end_ir );
02388 continue;
02389 }
02390 if( !new_inner_loop[i]->vg_p )
02391 nmg_vertex_gv( new_inner_loop[i], pt );
02392
02393 if( nmg_calc_face_g( fu ) )
02394 {
02395 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02396 nmg_kfu( fu );
02397 }
02398 else
02399 {
02400
02401 struct loopuse *lu;
02402 struct edgeuse *eu;
02403
02404 NMG_CK_FACEUSE( fu );
02405
02406 if( fu->orientation != OT_SAME )
02407 fu = fu->fumate_p;
02408
02409 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02410
02411 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02412 {
02413 vect_t reverse_norm;
02414 struct edgeuse *eu_opp_use;
02415
02416 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02417 if( eu->vu_p->v_p == (*inner_loop)[0] )
02418 {
02419 nmg_vertexuse_nv( eu->vu_p, norms[0] );
02420 VREVERSE( reverse_norm, norms[0] );
02421 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02422 }
02423 else if( eu->vu_p->v_p == new_inner_loop[i] )
02424 {
02425 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02426 VREVERSE( reverse_norm, norms[i] );
02427 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02428 }
02429 else if( eu->vu_p->v_p == (*inner_loop)[i] )
02430 {
02431 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02432 VREVERSE( reverse_norm, norms[i] );
02433 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02434 }
02435 else if( eu->vu_p->v_p == (*inner_loop)[j] )
02436 {
02437 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02438 VREVERSE( reverse_norm, norms[j] );
02439 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02440 }
02441 else
02442 {
02443 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02444 bu_log( "\ti=%d, arc_segs=%d, fu = x%x\n" , i, arc_segs, fu );
02445 }
02446 }
02447 }
02448
02449 verts[2] = verts[0];
02450 verts[0] = verts[1];
02451 verts[1] = verts[2];
02452 if( i == arc_segs-1 )
02453 verts[2] = &new_inner_loop[0];
02454 else
02455 verts[2] = &new_inner_loop[j];
02456 if( (fu_prev = nmg_cmface( s, verts, 3 ) ) == NULL )
02457 {
02458 bu_log( "tesselate_pipe_linear: failed to make inner face #%d ir=%g, end_ir=%g\n",
02459 i, ir, end_ir );
02460 continue;
02461 }
02462 if( i == arc_segs-1 )
02463 {
02464 if( nmg_calc_face_g( fu_prev ) )
02465 {
02466 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02467 nmg_kfu( fu_prev );
02468 }
02469 }
02470
02471 }
02472 bu_free( (char *)(*inner_loop), "tesselate_pipe_bend: inner_loop" );
02473 *inner_loop = new_inner_loop;
02474 }
02475 else if( ir > tol->dist && end_ir <= tol->dist )
02476 {
02477 struct vertex *v=(struct vertex *)NULL;
02478
02479 VSUB2( norms[0], (*inner_loop)[0]->vg_p->coord, start_pt );
02480 VJOIN1( norms[0], norms[0], -slope*ir, n );
02481 VUNITIZE( norms[0] );
02482 VREVERSE( norms[0], norms[0] );
02483 for( i=0 ; i<arc_segs; i++ )
02484 {
02485 j = i+1;
02486 if( j == arc_segs )
02487 j = 0;
02488
02489 verts[0] = &(*inner_loop)[i];
02490 verts[1] = &(*inner_loop)[j];
02491 verts[2] = &v;
02492
02493 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02494 {
02495 bu_log( "tesselate_pipe_linear: failed to make inner face #%d ir=%g, end_ir=%g\n",
02496 i, ir, end_ir );
02497 continue;
02498 }
02499 if( i == 0 )
02500 nmg_vertex_gv( v, end_pt );
02501
02502 if( i < arc_segs-1 )
02503 {
02504 VSUB2( norms[j], (*inner_loop)[j]->vg_p->coord, start_pt );
02505 VJOIN1( norms[j], norms[j], -slope*ir, n );
02506 VUNITIZE( norms[j] );
02507 VREVERSE( norms[j], norms[j] );
02508 }
02509
02510 if( nmg_calc_face_g( fu ) )
02511 {
02512 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02513 nmg_kfu( fu );
02514 }
02515 else
02516 {
02517 struct loopuse *lu;
02518 struct edgeuse *eu;
02519 struct edgeuse *eu_opp_use;
02520 vect_t reverse_norm;
02521
02522 NMG_CK_FACEUSE( fu );
02523 if( fu->orientation != OT_SAME )
02524 fu = fu->fumate_p;
02525
02526 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02527 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02528 {
02529 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02530 if( eu->vu_p->v_p == (*inner_loop)[i] )
02531 {
02532 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02533 VREVERSE( reverse_norm, norms[i] );
02534 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02535 }
02536 else if( eu->vu_p->v_p == (*inner_loop)[j] )
02537 {
02538 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02539 VREVERSE( reverse_norm, norms[j] );
02540 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02541 }
02542 else if( eu->vu_p->v_p == v )
02543 {
02544 vect_t tmp_norm;
02545 VBLEND2( tmp_norm, 0.5, norms[i], 0.5, norms[j] );
02546 VUNITIZE( tmp_norm );
02547 nmg_vertexuse_nv( eu->vu_p, tmp_norm );
02548 VREVERSE( reverse_norm, tmp_norm );
02549 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02550 }
02551 else
02552 {
02553 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02554 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02555 }
02556 }
02557 }
02558 }
02559
02560 bu_free( (char *)(*inner_loop), "tesselate_pipe_linear: inner_loop" );
02561 inner_loop[0] = &v;
02562 }
02563 else if( ir <= tol->dist && end_ir > tol->dist )
02564 {
02565 point_t pt,pt_next;
02566 fastf_t x,y,xnew,ynew;
02567 struct vertex **verts[3];
02568
02569 x = 1.0;
02570 y = 0.0;
02571 VCOMB2( norms[0], -x, r1, -y, r2 );
02572 VJOIN1( pt_next, end_pt, -end_ir, norms[0] );
02573 VJOIN1( norms[0], norms[0], -slope, n );
02574 VUNITIZE( norms[0] );
02575 for( i=0 ; i<arc_segs; i++ )
02576 {
02577 j = i + 1;
02578 if( j == arc_segs )
02579 j = 0;
02580
02581 VMOVE( pt, pt_next )
02582 xnew = x*cos_del - y*sin_del;
02583 ynew = x*sin_del + y*cos_del;
02584 x = xnew;
02585 y = ynew;
02586 if( i < j )
02587 {
02588 VCOMB2( norms[j], -x, r1, -y, r2 );
02589 VJOIN1( pt_next, end_pt, -end_ir, norms[j] );
02590 VJOIN1( norms[j], norms[j], -slope, n );
02591 VUNITIZE( norms[j] );
02592 }
02593
02594 verts[0] = &new_inner_loop[j];
02595 verts[1] = &new_inner_loop[i];
02596 verts[2] = &(*inner_loop)[0];
02597
02598 if( (fu = nmg_cmface( s, verts, 3 ) ) == NULL )
02599 {
02600 bu_log( "tesselate_pipe_linear: failed to make inner face #%d ir=%g, end_ir=%g\n",
02601 i, ir, end_ir );
02602 continue;
02603 }
02604 if( !(*inner_loop)[0]->vg_p )
02605 nmg_vertex_gv( (*inner_loop)[0], start_pt );
02606 if( !new_inner_loop[i]->vg_p )
02607 nmg_vertex_gv( new_inner_loop[i], pt );
02608 if( !new_inner_loop[j]->vg_p )
02609 nmg_vertex_gv( new_inner_loop[j], pt_next );
02610 if( nmg_calc_face_g( fu ) )
02611 {
02612 bu_log( "tesselate_pipe_linear: nmg_calc_face_g failed\n" );
02613 nmg_kfu( fu );
02614 }
02615 else
02616 {
02617 struct loopuse *lu;
02618 struct edgeuse *eu;
02619 struct edgeuse *eu_opp_use;
02620 vect_t reverse_norm;
02621
02622 NMG_CK_FACEUSE( fu );
02623 if( fu->orientation != OT_SAME )
02624 fu = fu->fumate_p;
02625
02626 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02627 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02628 {
02629 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02630 if( eu->vu_p->v_p == new_inner_loop[i] )
02631 {
02632 nmg_vertexuse_nv( eu->vu_p, norms[i] );
02633 VREVERSE( reverse_norm, norms[i] );
02634 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02635 }
02636 else if( eu->vu_p->v_p == new_inner_loop[j] )
02637 {
02638 nmg_vertexuse_nv( eu->vu_p, norms[j] );
02639 VREVERSE( reverse_norm, norms[j] );
02640 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02641 }
02642 else if( eu->vu_p->v_p == (*inner_loop)[0] )
02643 {
02644 vect_t tmp_norm;
02645 VBLEND2( tmp_norm, 0.5, norms[i], 0.5, norms[j] );
02646 VUNITIZE( tmp_norm );
02647 nmg_vertexuse_nv( eu->vu_p, tmp_norm );
02648 VREVERSE( reverse_norm, tmp_norm );
02649 nmg_vertexuse_nv( eu_opp_use->vu_p, reverse_norm );
02650 }
02651 else
02652 {
02653 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02654 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02655 }
02656 }
02657 }
02658 }
02659 bu_free( (char *)(*inner_loop), "tesselate_pipe_linear: inner_loop" );
02660 *inner_loop = new_inner_loop;
02661 }
02662 bu_free( (char *)norms, "tesselate_linear_pipe: norms" );
02663 }
02664
02665 HIDDEN void
02666 tesselate_pipe_bend(fastf_t *bend_start, fastf_t *bend_end, fastf_t *bend_center, fastf_t or, fastf_t ir, int arc_segs, double sin_del, double cos_del, struct vertex ***outer_loop, struct vertex ***inner_loop, fastf_t *start_r1, fastf_t *start_r2, struct
02667 shell *s, const struct bn_tol *tol, const struct rt_tess_tol *ttol)
02668 {
02669 struct vertex **new_outer_loop;
02670 struct vertex **new_inner_loop;
02671 fastf_t bend_radius;
02672 fastf_t bend_angle;
02673 fastf_t x,y,xnew,ynew;
02674 fastf_t delta_angle;
02675 mat_t rot;
02676 vect_t b1;
02677 vect_t b2;
02678 vect_t r1, r2;
02679 vect_t r1_tmp,r2_tmp;
02680 vect_t bend_norm;
02681 vect_t to_start;
02682 vect_t to_end;
02683 vect_t norm;
02684 point_t origin;
02685 point_t center;
02686 point_t old_center;
02687 int bend_segs=1;
02688 int bend_seg;
02689 int tol_segs;
02690 int i,j;
02691
02692 NMG_CK_SHELL( s );
02693 BN_CK_TOL( tol );
02694 RT_CK_TESS_TOL( ttol );
02695
02696 VMOVE( r1, start_r1 );
02697 VMOVE( r2, start_r2 );
02698
02699
02700
02701
02702 VSUB2( to_start, bend_start, bend_center );
02703 bend_radius = MAGNITUDE( to_start );
02704 VSCALE( b1, to_start, 1.0/bend_radius );
02705
02706
02707 VSUB2( to_end, bend_end, bend_center );
02708 VCROSS( bend_norm, b1, to_end );
02709 VUNITIZE( bend_norm );
02710
02711
02712 VCROSS( b2, bend_norm, b1 );
02713
02714 bend_angle = atan2( VDOT( to_end, b2 ), VDOT( to_end, b1 ) );
02715 if( bend_angle < 0.0 )
02716 bend_angle += 2.0*bn_pi;
02717
02718
02719 if( ttol->abs > 0.0 && ttol->abs < bend_radius+or )
02720 {
02721 tol_segs = ceil( bend_angle/(2.0*acos( 1.0 - ttol->abs/(bend_radius+or) ) ) );
02722 if( tol_segs > bend_segs )
02723 bend_segs = tol_segs;
02724 }
02725 if( ttol->rel > 0.0 )
02726 {
02727 tol_segs = ceil(bend_angle/(2.0*acos( 1.0 - ttol->rel ) ) );
02728 if( tol_segs > bend_segs )
02729 bend_segs = tol_segs;
02730 }
02731 if( ttol->norm > 0.0 )
02732 {
02733 tol_segs = ceil( bend_angle/(2.0*ttol->norm ) );
02734 if( tol_segs > bend_segs )
02735 bend_segs = tol_segs;
02736 }
02737
02738 delta_angle = bend_angle/(fastf_t)(bend_segs);
02739
02740 VSETALL( origin, 0.0 );
02741 bn_mat_arb_rot( rot, origin, bend_norm, delta_angle);
02742
02743 VMOVE( old_center, bend_start )
02744 for( bend_seg=0; bend_seg<bend_segs ; bend_seg++ )
02745 {
02746
02747 new_outer_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
02748 "tesselate_pipe_bend(): new_outer_loop" );
02749
02750 MAT4X3VEC( r1_tmp, rot, r1 )
02751 MAT4X3VEC( r2_tmp, rot, r2 )
02752 VMOVE( r1, r1_tmp )
02753 VMOVE( r2, r2_tmp )
02754
02755 VSUB2( r1_tmp, old_center, bend_center )
02756 MAT4X3PNT( r2_tmp, rot, r1_tmp )
02757 VADD2( center, r2_tmp, bend_center )
02758
02759 x = or;
02760 y = 0.0;
02761 for( i=0; i<arc_segs; i++ )
02762 {
02763 struct faceuse *fu;
02764 struct vertex **verts[3];
02765 point_t pt;
02766
02767 j = i+1;
02768 if( j == arc_segs )
02769 j = 0;
02770
02771 verts[0] = &(*outer_loop)[j];
02772 verts[1] = &(*outer_loop)[i];
02773 verts[2] = &new_outer_loop[i];
02774
02775 if( (fu=nmg_cmface( s, verts, 3 )) == NULL )
02776 {
02777 bu_log( "tesselate_pipe_bend(): nmg_cmface failed\n" );
02778 rt_bomb( "tesselate_pipe_bend\n" );
02779 }
02780 VJOIN2( pt, center, x, r1, y, r2 );
02781 if( !new_outer_loop[i]->vg_p )
02782 nmg_vertex_gv( new_outer_loop[i], pt );
02783 if( nmg_calc_face_g( fu ) )
02784 {
02785 bu_log( "tesselate_pipe_bend: nmg_calc_face_g failed\n" );
02786 nmg_kfu( fu );
02787 }
02788 else
02789 {
02790 struct loopuse *lu;
02791 struct edgeuse *eu;
02792
02793 NMG_CK_FACEUSE( fu );
02794 if( fu->orientation != OT_SAME )
02795 fu = fu->fumate_p;
02796
02797 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02798 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02799 {
02800 struct edgeuse *eu_opp_use;
02801
02802 NMG_CK_EDGEUSE( eu );
02803 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02804
02805 if( eu->vu_p->v_p == (*outer_loop)[j] )
02806 {
02807 VSUB2( norm, (*outer_loop)[j]->vg_p->coord, old_center );
02808 VUNITIZE( norm );
02809 nmg_vertexuse_nv( eu->vu_p, norm );
02810 VREVERSE( norm, norm );
02811 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02812 }
02813 else if( eu->vu_p->v_p == (*outer_loop)[i] )
02814 {
02815 VSUB2( norm, (*outer_loop)[i]->vg_p->coord, old_center );
02816 VUNITIZE( norm );
02817 nmg_vertexuse_nv( eu->vu_p, norm );
02818 VREVERSE( norm, norm );
02819 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02820 }
02821 else if( eu->vu_p->v_p == new_outer_loop[i] )
02822 {
02823 VSUB2( norm, new_outer_loop[i]->vg_p->coord, center );
02824 VUNITIZE( norm );
02825 nmg_vertexuse_nv( eu->vu_p, norm );
02826 VREVERSE( norm, norm );
02827 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02828 }
02829 else
02830 {
02831 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02832 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02833 }
02834 }
02835 }
02836
02837 xnew = x*cos_del - y*sin_del;
02838 ynew = x*sin_del + y*cos_del;
02839 x = xnew;
02840 y = ynew;
02841
02842 verts[1] = verts[2];
02843 verts[2] = &new_outer_loop[j];
02844
02845 if( (fu=nmg_cmface( s, verts, 3 )) == NULL )
02846 {
02847 bu_log( "tesselate_pipe_bend(): nmg_cmface failed\n" );
02848 rt_bomb( "tesselate_pipe_bend\n" );
02849 }
02850 VJOIN2( pt, center, x, r1, y, r2 );
02851 if( !(*verts[2])->vg_p )
02852 nmg_vertex_gv( *verts[2], pt );
02853 if( nmg_calc_face_g( fu ) )
02854 {
02855 bu_log( "tesselate_pipe_bend: nmg_calc_face_g failed\n" );
02856 nmg_kfu( fu );
02857 }
02858 else
02859 {
02860 struct loopuse *lu;
02861 struct edgeuse *eu;
02862
02863 NMG_CK_FACEUSE( fu );
02864 if( fu->orientation != OT_SAME )
02865 fu = fu->fumate_p;
02866
02867 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02868 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02869 {
02870 struct edgeuse *eu_opp_use;
02871
02872 NMG_CK_EDGEUSE( eu );
02873 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02874
02875 if( eu->vu_p->v_p == (*outer_loop)[j] )
02876 {
02877 VSUB2( norm, (*outer_loop)[j]->vg_p->coord, old_center );
02878 VUNITIZE( norm );
02879 nmg_vertexuse_nv( eu->vu_p, norm );
02880 VREVERSE( norm, norm );
02881 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02882 }
02883 else if( eu->vu_p->v_p == new_outer_loop[i] )
02884 {
02885 VSUB2( norm, new_outer_loop[i]->vg_p->coord, center );
02886 VUNITIZE( norm );
02887 nmg_vertexuse_nv( eu->vu_p, norm );
02888 VREVERSE( norm, norm );
02889 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02890 }
02891 else if( eu->vu_p->v_p == new_outer_loop[j] )
02892 {
02893 VSUB2( norm, new_outer_loop[j]->vg_p->coord, center );
02894 VUNITIZE( norm );
02895 nmg_vertexuse_nv( eu->vu_p, norm );
02896 VREVERSE( norm, norm );
02897 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02898 }
02899 else
02900 {
02901 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
02902 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
02903 }
02904 }
02905 }
02906 }
02907
02908 bu_free( (char *)(*outer_loop), "tesselate_pipe_bend: outer_loop" );
02909 *outer_loop = new_outer_loop;
02910 VMOVE( old_center, center );
02911 }
02912
02913 if( ir <= tol->dist )
02914 {
02915 VMOVE( start_r1, r1 )
02916 VMOVE( start_r2, r2 )
02917 return;
02918 }
02919
02920 VMOVE( r1, start_r1 )
02921 VMOVE( r2, start_r2 )
02922
02923 VMOVE( old_center, bend_start )
02924 for( bend_seg=0; bend_seg<bend_segs ; bend_seg++ )
02925 {
02926
02927 new_inner_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
02928 "tesselate_pipe_bend(): new_inner_loop" );
02929
02930 MAT4X3VEC( r1_tmp, rot, r1 )
02931 MAT4X3VEC( r2_tmp, rot, r2 )
02932 VMOVE( r1, r1_tmp )
02933 VMOVE( r2, r2_tmp )
02934
02935 VSUB2( r1_tmp, old_center, bend_center )
02936 MAT4X3PNT( r2_tmp, rot, r1_tmp )
02937 VADD2( center, r2_tmp, bend_center )
02938
02939 x = ir;
02940 y = 0.0;
02941 for( i=0; i<arc_segs; i++ )
02942 {
02943 struct faceuse *fu;
02944 struct vertex **verts[3];
02945 point_t pt;
02946
02947 j = i + 1;
02948 if( j == arc_segs )
02949 j = 0;
02950
02951 verts[0] = &(*inner_loop)[i];
02952 verts[1] = &(*inner_loop)[j];
02953 verts[2] = &new_inner_loop[i];
02954
02955 if( (fu=nmg_cmface( s, verts, 3 )) == NULL )
02956 {
02957 bu_log( "tesselate_pipe_bend(): nmg_cmface failed\n" );
02958 rt_bomb( "tesselate_pipe_bend\n" );
02959 }
02960 VJOIN2( pt, center, x, r1, y, r2 );
02961 if( !new_inner_loop[i]->vg_p )
02962 nmg_vertex_gv( new_inner_loop[i], pt );
02963 if( nmg_calc_face_g( fu ) )
02964 {
02965 bu_log( "tesselate_pipe_bend: nmg_calc_face_g failed\n" );
02966 nmg_kfu( fu );
02967 }
02968 else
02969 {
02970 struct loopuse *lu;
02971 struct edgeuse *eu;
02972
02973 NMG_CK_FACEUSE( fu );
02974 if( fu->orientation != OT_SAME )
02975 fu = fu->fumate_p;
02976
02977 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
02978 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
02979 {
02980 struct edgeuse *eu_opp_use;
02981
02982 NMG_CK_EDGEUSE( eu );
02983 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
02984
02985 if( eu->vu_p->v_p == (*inner_loop)[j] )
02986 {
02987 VSUB2( norm, old_center, (*inner_loop)[j]->vg_p->coord );
02988 VUNITIZE( norm );
02989 nmg_vertexuse_nv( eu->vu_p, norm );
02990 VREVERSE( norm, norm );
02991 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
02992 }
02993 else if( eu->vu_p->v_p == (*inner_loop)[i] )
02994 {
02995 VSUB2( norm, old_center, (*inner_loop)[i]->vg_p->coord );
02996 VUNITIZE( norm );
02997 nmg_vertexuse_nv( eu->vu_p, norm );
02998 VREVERSE( norm, norm );
02999 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
03000 }
03001 else if( eu->vu_p->v_p == new_inner_loop[i] )
03002 {
03003 VSUB2( norm, center, new_inner_loop[i]->vg_p->coord );
03004 VUNITIZE( norm );
03005 nmg_vertexuse_nv( eu->vu_p, norm );
03006 VREVERSE( norm, norm );
03007 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
03008 }
03009 else
03010 {
03011 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
03012 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
03013 }
03014 }
03015 }
03016
03017 xnew = x*cos_del - y*sin_del;
03018 ynew = x*sin_del + y*cos_del;
03019 x = xnew;
03020 y = ynew;
03021
03022 verts[0] = verts[2];
03023 verts[2] = &new_inner_loop[j];
03024
03025 if( (fu=nmg_cmface( s, verts, 3 )) == NULL )
03026 {
03027 bu_log( "tesselate_pipe_bend(): nmg_cmface failed\n" );
03028 rt_bomb( "tesselate_pipe_bend\n" );
03029 }
03030 VJOIN2( pt, center, x, r1, y, r2 );
03031 if( !(*verts[2])->vg_p )
03032 nmg_vertex_gv( *verts[2], pt );
03033 if( nmg_calc_face_g( fu ) )
03034 {
03035 bu_log( "tesselate_pipe_bend: nmg_calc_face_g failed\n" );
03036 nmg_kfu( fu );
03037 }
03038 else
03039 {
03040 struct loopuse *lu;
03041 struct edgeuse *eu;
03042
03043 NMG_CK_FACEUSE( fu );
03044 if( fu->orientation != OT_SAME )
03045 fu = fu->fumate_p;
03046
03047 lu = BU_LIST_FIRST( loopuse, &fu->lu_hd );
03048 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03049 {
03050 struct edgeuse *eu_opp_use;
03051
03052 NMG_CK_EDGEUSE( eu );
03053 eu_opp_use = BU_LIST_PNEXT_CIRC( edgeuse, &eu->eumate_p->l );
03054
03055 if( eu->vu_p->v_p == (*inner_loop)[j] )
03056 {
03057 VSUB2( norm, old_center, (*inner_loop)[j]->vg_p->coord );
03058 VUNITIZE( norm );
03059 nmg_vertexuse_nv( eu->vu_p, norm );
03060 VREVERSE( norm, norm );
03061 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
03062 }
03063 else if( eu->vu_p->v_p == new_inner_loop[i] )
03064 {
03065 VSUB2( norm, center, new_inner_loop[i]->vg_p->coord );
03066 VUNITIZE( norm );
03067 nmg_vertexuse_nv( eu->vu_p, norm );
03068 VREVERSE( norm, norm );
03069 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
03070 }
03071 else if( eu->vu_p->v_p == new_inner_loop[j] )
03072 {
03073 VSUB2( norm, center, new_inner_loop[j]->vg_p->coord );
03074 VUNITIZE( norm );
03075 nmg_vertexuse_nv( eu->vu_p, norm );
03076 VREVERSE( norm, norm );
03077 nmg_vertexuse_nv( eu_opp_use->vu_p, norm );
03078 }
03079 else
03080 {
03081 bu_log( "No vu_normal assigned at (%g %g %g)\n", V3ARGS( eu->vu_p->v_p->vg_p->coord ) );
03082 bu_log( "\ti=%d, j=%d, arc_segs=%d, fu = x%x\n" , i,j, arc_segs, fu );
03083 }
03084 }
03085 }
03086 }
03087 bu_free( (char *)(*inner_loop), "tesselate_pipe_bend: inner_loop" );
03088 *inner_loop = new_inner_loop;
03089 VMOVE( old_center, center );
03090 }
03091 VMOVE( start_r1, r1 )
03092 VMOVE( start_r2, r2 )
03093 }
03094
03095 HIDDEN void
03096 tesselate_pipe_end(struct wdb_pipept *pipe, int arc_segs, double sin_del, double cos_del, struct vertex ***outer_loop, struct vertex ***inner_loop, struct shell *s, const struct bn_tol *tol)
03097 {
03098 struct wdb_pipept *prev;
03099 struct faceuse *fu;
03100 struct loopuse *lu;
03101
03102 NMG_CK_SHELL( s );
03103 BN_CK_TOL( tol );
03104
03105 if( pipe->pp_od <= tol->dist )
03106 return;
03107
03108 if( NEAR_ZERO( pipe->pp_od - pipe->pp_id, tol->dist) )
03109 return;
03110
03111 if( (fu = nmg_cface( s, *outer_loop, arc_segs )) == NULL )
03112 {
03113 bu_log( "tesselate_pipe_end(): nmg_cface failed\n" );
03114 return;
03115 }
03116 fu = fu->fumate_p;
03117 if( nmg_calc_face_g( fu ) )
03118 {
03119 bu_log( "tesselate_pipe_end: nmg_calc_face_g failed\n" );
03120 nmg_kfu( fu );
03121 return;
03122 }
03123
03124 prev = BU_LIST_PREV( wdb_pipept, &pipe->l );
03125
03126 if( pipe->pp_id > tol->dist )
03127 {
03128 struct vertex **verts;
03129 int i;
03130
03131 verts = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
03132 "tesselate_pipe_end: verts" );
03133 for( i=0 ; i<arc_segs; i++ )
03134 verts[i] = (*inner_loop)[i];
03135
03136 fu = nmg_add_loop_to_face( s, fu, verts, arc_segs, OT_OPPOSITE );
03137
03138 bu_free( (char *)verts, "tesselate_pipe_end: verts" );
03139 }
03140
03141 else if( prev->pp_id > tol->dist )
03142 {
03143 struct vertexuse *vu;
03144
03145
03146 lu = nmg_mlv( &fu->l.magic, (struct vertex *)NULL, OT_OPPOSITE );
03147 vu = BU_LIST_FIRST( vertexuse, &lu->down_hd );
03148
03149 nmg_vertex_gv( vu->v_p, pipe->pp_coord );
03150 }
03151
03152 for( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
03153 {
03154 struct edgeuse *eu;
03155
03156 NMG_CK_LOOPUSE( lu );
03157
03158 if( BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC )
03159 continue;
03160
03161 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
03162 {
03163 NMG_CK_EDGEUSE( eu );
03164 eu->e_p->is_real = 1;
03165 }
03166 }
03167 }
03168
03169
03170
03171
03172
03173
03174 int
03175 rt_pipe_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
03176 {
03177 struct wdb_pipept *pp1;
03178 struct wdb_pipept *pp2;
03179 struct wdb_pipept *pp3;
03180 point_t curr_pt;
03181 struct shell *s;
03182 struct rt_pipe_internal *pip;
03183 int arc_segs=6;
03184 int tol_segs;
03185 fastf_t max_diam=0.0;
03186 fastf_t pipe_size;
03187 fastf_t curr_od,curr_id;
03188 double delta_angle;
03189 double sin_del;
03190 double cos_del;
03191 point_t min_pt;
03192 point_t max_pt;
03193 vect_t min_to_max;
03194 vect_t r1, r2;
03195 struct vertex **outer_loop;
03196 struct vertex **inner_loop;
03197
03198 RT_CK_DB_INTERNAL(ip);
03199 pip = (struct rt_pipe_internal *)ip->idb_ptr;
03200 RT_PIPE_CK_MAGIC( pip );
03201
03202 BN_CK_TOL( tol );
03203 RT_CK_TESS_TOL( ttol );
03204 NMG_CK_MODEL( m );
03205
03206 *r = (struct nmgregion *)NULL;
03207
03208 if( BU_LIST_IS_EMPTY( &pip->pipe_segs_head ) )
03209 return( 0 );
03210
03211 pp1 = BU_LIST_FIRST( wdb_pipept, &pip->pipe_segs_head );
03212
03213 VMOVE( min_pt, pp1->pp_coord );
03214 VMOVE( max_pt, pp1->pp_coord );
03215
03216
03217 for( BU_LIST_FOR( pp1, wdb_pipept, &pip->pipe_segs_head ) )
03218 {
03219 if( pp1->pp_od > 0.0 && pp1->pp_od > max_diam )
03220 max_diam = pp1->pp_od;
03221
03222 VMINMAX( min_pt, max_pt, pp1->pp_coord );
03223 }
03224
03225 if( max_diam <= tol->dist )
03226 return( 0 );
03227
03228
03229 VSUB2( min_to_max, max_pt, min_pt );
03230 pipe_size = MAGNITUDE( min_to_max );
03231
03232
03233 if( ttol->abs > 0.0 && ttol->abs * 2.0 < max_diam )
03234 {
03235 tol_segs = ceil( bn_pi/acos( 1.0 - 2.0 * ttol->abs/max_diam) );
03236 if( tol_segs > arc_segs )
03237 arc_segs = tol_segs;
03238 }
03239 if( ttol->rel > 0.0 && 2.0 * ttol->rel * pipe_size < max_diam )
03240 {
03241 tol_segs = ceil( bn_pi/acos( 1.0 - 2.0 * ttol->rel*pipe_size/max_diam) );
03242 if( tol_segs > arc_segs )
03243 arc_segs = tol_segs;
03244 }
03245 if( ttol->norm > 0.0 )
03246 {
03247 tol_segs = ceil( bn_pi/ttol->norm );
03248 if( tol_segs > arc_segs )
03249 arc_segs = tol_segs;
03250 }
03251
03252 *r = nmg_mrsv( m );
03253 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
03254
03255 outer_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
03256 "rt_pipe_tess: outer_loop" );
03257 inner_loop = (struct vertex **)bu_calloc( arc_segs, sizeof( struct vertex *),
03258 "rt_pipe_tess: inner_loop" );
03259 delta_angle = 2.0 * bn_pi / (double)arc_segs;
03260 sin_del = sin( delta_angle );
03261 cos_del = cos( delta_angle );
03262
03263 pp1 = BU_LIST_FIRST( wdb_pipept, &(pip->pipe_segs_head) );
03264 tesselate_pipe_start( pp1, arc_segs, sin_del, cos_del,
03265 &outer_loop, &inner_loop, r1, r2, s, tol );
03266
03267 pp2 = BU_LIST_NEXT( wdb_pipept, &pp1->l );
03268 if( BU_LIST_IS_HEAD( &pp2->l, &(pip->pipe_segs_head) ) )
03269 return( 0 );
03270 pp3 = BU_LIST_NEXT( wdb_pipept, &pp2->l );
03271 if( BU_LIST_IS_HEAD( &pp3->l , &(pip->pipe_segs_head) ) )
03272 pp3 = (struct wdb_pipept *)NULL;
03273
03274 VMOVE( curr_pt, pp1->pp_coord );
03275 curr_od = pp1->pp_od;
03276 curr_id = pp1->pp_id;
03277 while( 1 )
03278 {
03279 vect_t n1,n2;
03280 vect_t norm;
03281 vect_t v1;
03282 fastf_t angle;
03283 fastf_t dist_to_bend;
03284 point_t bend_start, bend_end, bend_center;
03285
03286 VSUB2( n1, curr_pt, pp2->pp_coord );
03287 if( VNEAR_ZERO( n1, SQRT_SMALL_FASTF ) )
03288 {
03289
03290 goto next_pt;
03291 }
03292
03293 if( !pp3 )
03294 {
03295
03296 tesselate_pipe_linear(curr_pt, curr_od/2.0, curr_id/2.0,
03297 pp2->pp_coord, pp2->pp_od/2.0, pp2->pp_id/2.0,
03298 arc_segs, sin_del, cos_del, &outer_loop, &inner_loop, r1, r2, s, tol );
03299 break;
03300 }
03301
03302 VSUB2( n2, pp3->pp_coord, pp2->pp_coord );
03303 VCROSS( norm, n1, n2 );
03304 if( VNEAR_ZERO( norm, SQRT_SMALL_FASTF ) )
03305 {
03306
03307 tesselate_pipe_linear(curr_pt, curr_od/2.0, curr_id/2.0,
03308 pp2->pp_coord, pp2->pp_od/2.0, pp2->pp_id/2.0,
03309 arc_segs, sin_del, cos_del, &outer_loop, &inner_loop, r1, r2, s, tol );
03310
03311 VMOVE( curr_pt, pp2->pp_coord );
03312 curr_id = pp2->pp_id;
03313 curr_od = pp2->pp_od;
03314 goto next_pt;
03315 }
03316
03317 VUNITIZE( n1 );
03318 VUNITIZE( n2 );
03319 VUNITIZE( norm );
03320
03321
03322 angle = bn_pi - acos( VDOT( n1, n2 ) );
03323 dist_to_bend = pp2->pp_bendradius * tan( angle/2.0 );
03324 VJOIN1( bend_start, pp2->pp_coord, dist_to_bend, n1 );
03325 tesselate_pipe_linear( curr_pt, curr_od/2.0, curr_id/2.0,
03326 bend_start, pp2->pp_od/2.0, pp2->pp_id/2.0,
03327 arc_segs, sin_del, cos_del, &outer_loop, &inner_loop, r1, r2, s, tol );
03328
03329
03330 VJOIN1( bend_end, pp2->pp_coord, dist_to_bend, n2 );
03331 VCROSS( v1, n1, norm );
03332 VJOIN1( bend_center, bend_start, -pp2->pp_bendradius, v1 );
03333 tesselate_pipe_bend( bend_start, bend_end, bend_center, curr_od/2.0, curr_id/2.0,
03334 arc_segs, sin_del, cos_del, &outer_loop, &inner_loop,
03335 r1, r2, s, tol, ttol );
03336
03337 VMOVE( curr_pt, bend_end );
03338 curr_id = pp2->pp_id;
03339 curr_od = pp2->pp_od;
03340 next_pt:
03341 pp1 = pp2;
03342 pp2 = pp3;
03343 pp3 = BU_LIST_NEXT( wdb_pipept, &pp3->l );
03344 if( BU_LIST_IS_HEAD( &pp3->l , &(pip->pipe_segs_head) ) )
03345 pp3 = (struct wdb_pipept *)NULL;
03346 }
03347
03348 tesselate_pipe_end( pp2, arc_segs, sin_del, cos_del, &outer_loop, &inner_loop, s, tol );
03349
03350 bu_free( (char *)outer_loop, "rt_pipe_tess: outer_loop" );
03351 bu_free( (char *)inner_loop, "rt_pipe_tess: inner_loop" );
03352
03353 nmg_rebound( m, tol );
03354
03355 return( 0 );
03356 }
03357
03358
03359
03360
03361 int
03362 rt_pipe_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
03363 {
03364 register struct exported_pipept *exp;
03365 register struct wdb_pipept *ptp;
03366 struct wdb_pipept tmp;
03367 struct rt_pipe_internal *pipe;
03368 union record *rp;
03369
03370 BU_CK_EXTERNAL( ep );
03371 rp = (union record *)ep->ext_buf;
03372
03373 if( rp->u_id != DBID_PIPE ) {
03374 bu_log("rt_pipe_import: defective record\n");
03375 return(-1);
03376 }
03377
03378 RT_CK_DB_INTERNAL( ip );
03379 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
03380 ip->idb_type = ID_PIPE;
03381 ip->idb_meth = &rt_functab[ID_PIPE];
03382 ip->idb_ptr = bu_malloc( sizeof(struct rt_pipe_internal), "rt_pipe_internal");
03383 pipe = (struct rt_pipe_internal *)ip->idb_ptr;
03384 pipe->pipe_magic = RT_PIPE_INTERNAL_MAGIC;
03385 pipe->pipe_count = bu_glong( rp->pwr.pwr_pt_count);
03386
03387
03388
03389
03390
03391
03392 BU_LIST_INIT( &pipe->pipe_segs_head );
03393 for( exp = &rp->pwr.pwr_data[pipe->pipe_count-1]; exp >= &rp->pwr.pwr_data[0]; exp-- ) {
03394 ntohd( (unsigned char *)&tmp.pp_id, exp->epp_id, 1 );
03395 ntohd( (unsigned char *)&tmp.pp_od, exp->epp_od, 1 );
03396 ntohd( (unsigned char *)&tmp.pp_bendradius, exp->epp_bendradius, 1 );
03397 ntohd( (unsigned char *)tmp.pp_coord, exp->epp_coord, 3 );
03398
03399
03400 BU_GETSTRUCT( ptp, wdb_pipept );
03401 ptp->l.magic = WDB_PIPESEG_MAGIC;
03402 MAT4X3PNT( ptp->pp_coord, mat, tmp.pp_coord );
03403 ptp->pp_id = tmp.pp_id / mat[15];
03404 ptp->pp_od = tmp.pp_od / mat[15];
03405 ptp->pp_bendradius = tmp.pp_bendradius / mat[15];
03406 BU_LIST_APPEND( &pipe->pipe_segs_head, &ptp->l );
03407 }
03408
03409 return(0);
03410 }
03411
03412
03413
03414
03415 int
03416 rt_pipe_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
03417 {
03418 struct rt_pipe_internal *pip;
03419 struct bu_list *headp;
03420 register struct exported_pipept *epp;
03421 register struct wdb_pipept *ppt;
03422 struct wdb_pipept tmp;
03423 int count;
03424 int ngran;
03425 int nbytes;
03426 union record *rec;
03427
03428 RT_CK_DB_INTERNAL(ip);
03429 if( ip->idb_type != ID_PIPE ) return(-1);
03430 pip = (struct rt_pipe_internal *)ip->idb_ptr;
03431 RT_PIPE_CK_MAGIC(pip);
03432
03433 if (pip->pipe_segs_head.magic == 0) {
03434 return -1;
03435 }
03436 headp = &pip->pipe_segs_head;
03437
03438
03439 count = 0;
03440 for( BU_LIST_FOR( ppt, wdb_pipept, headp ) )
03441 count++;
03442
03443 if( count < 1 )
03444 return(-4);
03445
03446
03447 nbytes = sizeof(struct pipewire_rec) +
03448 (count-1) * sizeof(struct exported_pipept);
03449 ngran = (nbytes + sizeof(union record) - 1) / sizeof(union record);
03450
03451 BU_CK_EXTERNAL(ep);
03452 ep->ext_nbytes = ngran * sizeof(union record);
03453 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "pipe external");
03454 rec = (union record *)ep->ext_buf;
03455
03456 rec->pwr.pwr_id = DBID_PIPE;
03457 (void)bu_plong( rec->pwr.pwr_count, ngran-1 );
03458 (void)bu_plong( rec->pwr.pwr_pt_count, count );
03459
03460
03461 epp = &rec->pwr.pwr_data[0];
03462 for( BU_LIST_FOR( ppt, wdb_pipept, headp ), epp++ ) {
03463
03464 VSCALE( tmp.pp_coord, ppt->pp_coord, local2mm );
03465 tmp.pp_id = ppt->pp_id * local2mm;
03466 tmp.pp_od = ppt->pp_od * local2mm;
03467 tmp.pp_bendradius = ppt->pp_bendradius * local2mm;
03468 htond( epp->epp_coord, (unsigned char *)tmp.pp_coord, 3 );
03469 htond( epp->epp_id, (unsigned char *)&tmp.pp_id, 1 );
03470 htond( epp->epp_od, (unsigned char *)&tmp.pp_od, 1 );
03471 htond( epp->epp_bendradius, (unsigned char *)&tmp.pp_bendradius, 1 );
03472 }
03473
03474 return(0);
03475 }
03476
03477
03478
03479
03480 int
03481 rt_pipe_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
03482 {
03483 register struct wdb_pipept *ptp;
03484 struct rt_pipe_internal *pipe;
03485 fastf_t *vec;
03486 int total_count;
03487 int double_count;
03488 int byte_count;
03489 unsigned long pipe_count;
03490 int i;
03491
03492 BU_CK_EXTERNAL( ep );
03493
03494 pipe_count = bu_glong((unsigned char *)ep->ext_buf);
03495 double_count = pipe_count * 6;
03496 byte_count = double_count * SIZEOF_NETWORK_DOUBLE;
03497 total_count = 4 + byte_count;
03498 BU_ASSERT_LONG( ep->ext_nbytes, ==, total_count);
03499
03500 RT_CK_DB_INTERNAL( ip );
03501 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
03502 ip->idb_type = ID_PIPE;
03503 ip->idb_meth = &rt_functab[ID_PIPE];
03504 ip->idb_ptr = bu_malloc( sizeof(struct rt_pipe_internal), "rt_pipe_internal");
03505
03506 pipe = (struct rt_pipe_internal *)ip->idb_ptr;
03507 pipe->pipe_magic = RT_PIPE_INTERNAL_MAGIC;
03508 pipe->pipe_count = pipe_count;
03509
03510 vec = (fastf_t *)bu_malloc(byte_count, "rt_pipe_import5: vec");
03511
03512 ntohd((unsigned char *)vec, (unsigned char *)ep->ext_buf + 4, double_count);
03513
03514
03515
03516
03517
03518
03519 BU_LIST_INIT( &pipe->pipe_segs_head );
03520 for (i = 0; i < double_count; i += 6) {
03521
03522 BU_GETSTRUCT( ptp, wdb_pipept );
03523 ptp->l.magic = WDB_PIPESEG_MAGIC;
03524 MAT4X3PNT( ptp->pp_coord, mat, &vec[i] );
03525 ptp->pp_id = vec[i+3] / mat[15];
03526 ptp->pp_od = vec[i+4] / mat[15];
03527 ptp->pp_bendradius = vec[i+5] / mat[15];
03528 BU_LIST_INSERT( &pipe->pipe_segs_head, &ptp->l );
03529 }
03530
03531 bu_free((genptr_t)vec, "rt_pipe_import5: vec");
03532 return(0);
03533 }
03534
03535
03536
03537
03538 int
03539 rt_pipe_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
03540 {
03541 struct rt_pipe_internal *pip;
03542 struct bu_list *headp;
03543 register struct wdb_pipept *ppt;
03544 fastf_t *vec;
03545 int total_count;
03546 int double_count;
03547 int byte_count;
03548 unsigned long pipe_count;
03549 int i = 0;
03550
03551 RT_CK_DB_INTERNAL(ip);
03552 if( ip->idb_type != ID_PIPE ) return(-1);
03553 pip = (struct rt_pipe_internal *)ip->idb_ptr;
03554 RT_PIPE_CK_MAGIC(pip);
03555
03556 if (pip->pipe_segs_head.magic == 0) {
03557 return -1;
03558 }
03559 headp = &pip->pipe_segs_head;
03560
03561
03562 pipe_count = 0;
03563 for( BU_LIST_FOR( ppt, wdb_pipept, headp ) )
03564 pipe_count++;
03565
03566 if( pipe_count <= 1 )
03567 return(-4);
03568
03569 double_count = pipe_count * 6;
03570 byte_count = double_count * SIZEOF_NETWORK_DOUBLE;
03571 total_count = 4 + byte_count;
03572 vec = (fastf_t *)bu_malloc(byte_count, "rt_pipe_export5: vec");
03573
03574 BU_CK_EXTERNAL(ep);
03575 ep->ext_nbytes = total_count;
03576 ep->ext_buf = (genptr_t)bu_malloc(ep->ext_nbytes, "pipe external");
03577
03578 (void)bu_plong((unsigned char *)ep->ext_buf, pipe_count);
03579
03580
03581 for( BU_LIST_FOR( ppt, wdb_pipept, headp ), i += 6 ) {
03582
03583 VSCALE( &vec[i], ppt->pp_coord, local2mm );
03584 vec[i+3] = ppt->pp_id * local2mm;
03585 vec[i+4] = ppt->pp_od * local2mm;
03586 vec[i+5] = ppt->pp_bendradius * local2mm;
03587 }
03588
03589
03590 htond((unsigned char *)ep->ext_buf + 4, (unsigned char *)vec, double_count);
03591
03592 bu_free((genptr_t)vec, "rt_pipe_export5: vec");
03593 return(0);
03594 }
03595
03596
03597
03598
03599
03600
03601
03602
03603 int
03604 rt_pipe_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
03605 {
03606 register struct rt_pipe_internal *pip;
03607 register struct wdb_pipept *ptp;
03608 char buf[256];
03609 int segno = 0;
03610
03611 RT_CK_DB_INTERNAL(ip);
03612 pip = (struct rt_pipe_internal *)ip->idb_ptr;
03613 RT_PIPE_CK_MAGIC(pip);
03614
03615 sprintf(buf, "pipe with %d points\n", pip->pipe_count );
03616 bu_vls_strcat( str, buf );
03617
03618 if( !verbose ) return(0);
03619
03620 #if 1
03621
03622 for( BU_LIST_FOR( ptp, wdb_pipept, &pip->pipe_segs_head ) ) {
03623 sprintf(buf, "\t%d ", segno++ );
03624 bu_vls_strcat( str, buf );
03625 sprintf( buf, "\tbend radius = %g", INTCLAMP(ptp->pp_bendradius * mm2local) );
03626 bu_vls_strcat( str, buf );
03627 sprintf(buf, " od=%g", INTCLAMP(ptp->pp_od * mm2local) );
03628 bu_vls_strcat( str, buf );
03629 if( ptp->pp_id > 0 ) {
03630 sprintf(buf, ", id = %g", INTCLAMP(ptp->pp_id * mm2local) );
03631 bu_vls_strcat( str, buf );
03632 }
03633 bu_vls_strcat( str, "\n" );
03634
03635 sprintf(buf, "\t at=(%g, %g, %g)\n",
03636 INTCLAMP(ptp->pp_coord[X] * mm2local),
03637 INTCLAMP(ptp->pp_coord[Y] * mm2local),
03638 INTCLAMP(ptp->pp_coord[Z] * mm2local) );
03639 bu_vls_strcat( str, buf );
03640
03641 }
03642 #endif
03643 return(0);
03644 }
03645
03646
03647
03648
03649
03650
03651 void
03652 rt_pipe_ifree(struct rt_db_internal *ip)
03653 {
03654 register struct rt_pipe_internal *pipe;
03655 register struct wdb_pipept *ptp;
03656
03657 RT_CK_DB_INTERNAL(ip);
03658 pipe = (struct rt_pipe_internal*)ip->idb_ptr;
03659 RT_PIPE_CK_MAGIC(pipe);
03660
03661 if (pipe->pipe_segs_head.magic != 0) {
03662 while( BU_LIST_WHILE( ptp, wdb_pipept, &pipe->pipe_segs_head ) ) {
03663 BU_LIST_DEQUEUE( &(ptp->l) );
03664 bu_free( (char *)ptp, "wdb_pipept" );
03665 }
03666 }
03667 bu_free( ip->idb_ptr, "pipe ifree" );
03668 ip->idb_ptr = GENPTR_NULL;
03669 }
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680 int
03681 rt_pipe_ck( const struct bu_list *headp )
03682 {
03683 int error_count=0;
03684 struct wdb_pipept *cur,*prev,*next;
03685 fastf_t old_bend_dist=0.0;
03686 fastf_t new_bend_dist;
03687 fastf_t v2_len=0.0;
03688
03689 prev = BU_LIST_FIRST( wdb_pipept, headp );
03690 if( prev->pp_bendradius < prev->pp_od * 0.5 )
03691 {
03692 bu_log( "Bend radius (%gmm) is less than outer radius at ( %g %g %g )\n",
03693 prev->pp_bendradius, V3ARGS( prev->pp_coord ) );
03694 error_count++;
03695 }
03696 cur = BU_LIST_NEXT( wdb_pipept, &prev->l );
03697 next = BU_LIST_NEXT( wdb_pipept, &cur->l );
03698 while( BU_LIST_NOT_HEAD( &next->l, headp ) )
03699 {
03700 vect_t v1, v2, norm;
03701 fastf_t v1_len;
03702 fastf_t angle;
03703
03704 if( cur->pp_bendradius < cur->pp_od * 0.5 )
03705 {
03706 bu_log( "Bend radius (%gmm) is less than outer radius at ( %g %g %g )\n",
03707 cur->pp_bendradius, V3ARGS( cur->pp_coord ) );
03708 error_count++;
03709 }
03710
03711 VSUB2( v1, prev->pp_coord, cur->pp_coord );
03712 v1_len = MAGNITUDE( v1 );
03713 if( v1_len > VDIVIDE_TOL )
03714 {
03715 fastf_t inv_len;
03716
03717 inv_len = 1.0/v1_len;
03718 VSCALE( v1, v1, inv_len );
03719 }
03720 else
03721 VSETALL( v1, 0.0 )
03722
03723 VSUB2( v2, next->pp_coord, cur->pp_coord );
03724 v2_len = MAGNITUDE( v2 );
03725 if( v2_len > VDIVIDE_TOL )
03726 {
03727 fastf_t inv_len;
03728
03729 inv_len = 1.0/v2_len;
03730 VSCALE( v2, v2, inv_len );
03731 }
03732 else
03733 VSETALL( v2, 0.0 )
03734
03735 VCROSS( norm, v1, v2 );
03736 if( VNEAR_ZERO( norm, SQRT_SMALL_FASTF) )
03737 {
03738 new_bend_dist = 0.0;
03739 goto next_pt;
03740 }
03741
03742 angle = bn_pi - acos( VDOT( v1, v2 ) );
03743 new_bend_dist = cur->pp_bendradius * tan( angle/2.0 );
03744
03745 if( new_bend_dist + old_bend_dist > v1_len )
03746 {
03747 error_count++;
03748 bu_log( "Bend radii (%gmm) at ( %g %g %g ) and (%gmm) at ( %g %g %g ) are too large\n",
03749 prev->pp_bendradius, V3ARGS( prev->pp_coord),
03750 cur->pp_bendradius,V3ARGS( cur->pp_coord ) );
03751 bu_log( "for pipe segment between ( %g %g %g ) and ( %g %g %g )\n",
03752 V3ARGS( prev->pp_coord ), V3ARGS( cur->pp_coord ) );
03753 }
03754 next_pt:
03755 old_bend_dist = new_bend_dist;
03756 prev = cur;
03757 cur = next;
03758 next = BU_LIST_NEXT( wdb_pipept, &cur->l );
03759 }
03760
03761 if( old_bend_dist > v2_len )
03762 {
03763 error_count++;
03764 bu_log( "last segment ( %g %g %g ) to ( %g %g %g ) is too short to allow\n",
03765 V3ARGS( prev->pp_coord ), V3ARGS( cur->pp_coord ) );
03766 bu_log( "bend radius of %gmm\n", prev->pp_bendradius );
03767 }
03768 return( error_count );
03769 }
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784 int
03785 rt_pipe_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
03786 {
03787 register struct rt_pipe_internal *pipe=(struct rt_pipe_internal *)intern->idb_ptr;
03788 struct wdb_pipept *ptp;
03789 Tcl_DString ds;
03790 struct bu_vls vls;
03791 int status=TCL_OK;
03792 int seg_no;
03793 int num_segs=0;
03794
03795 RT_PIPE_CK_MAGIC( pipe );
03796
03797 Tcl_DStringInit( &ds );
03798 bu_vls_init( &vls );
03799
03800
03801 for( BU_LIST_FOR( ptp, wdb_pipept, &pipe->pipe_segs_head ) )
03802 num_segs++;
03803
03804 if( attr == (char *)NULL )
03805 {
03806 bu_vls_strcat( &vls, "pipe");
03807
03808 seg_no = 0;
03809 for( BU_LIST_FOR( ptp, wdb_pipept, &pipe->pipe_segs_head ) ) {
03810 bu_vls_printf( &vls, " V%d { %.25G %.25G %.25G } O%d %.25G I%d %.25G R%d %.25G",
03811 seg_no, V3ARGS( ptp->pp_coord ),
03812 seg_no, ptp->pp_od,
03813 seg_no, ptp->pp_id,
03814 seg_no, ptp->pp_bendradius );
03815 seg_no++;
03816 }
03817 }
03818 else if( attr[0] == 'N' )
03819 {
03820 bu_vls_printf( &vls, "%d", num_segs );
03821 goto out;
03822 }
03823 else
03824 {
03825 int curr_seg=0;
03826
03827 seg_no = atoi( &attr[1] );
03828 if( seg_no < 0 || seg_no >= num_segs ) {
03829 bu_vls_printf( &vls, "segment number out of range (0 - %d)", num_segs-1 );
03830 status = TCL_ERROR;
03831 goto out;
03832 }
03833
03834
03835 for( BU_LIST_FOR( ptp, wdb_pipept, &pipe->pipe_segs_head ) ) {
03836 if( curr_seg == seg_no )
03837 break;
03838 curr_seg++;
03839 }
03840
03841 switch( attr[0] ) {
03842 case 'V':
03843 bu_vls_printf( &vls, "%.25G %.25G %.25G", V3ARGS( ptp->pp_coord ) );
03844 break;
03845 case 'I':
03846 bu_vls_printf( &vls, "%.25G", ptp->pp_id );
03847 break;
03848 case 'O':
03849 bu_vls_printf( &vls, "%.25G", ptp->pp_od );
03850 break;
03851 case 'R':
03852 bu_vls_printf( &vls, "%.25G", ptp->pp_bendradius );
03853 break;
03854 case 'P':
03855 bu_vls_printf( &vls, " V%d { %.25G %.25G %.25G } I%d %.25G O%d %.25G R%d %.25G",
03856 seg_no, V3ARGS( ptp->pp_coord ),
03857 seg_no, ptp->pp_id,
03858 seg_no, ptp->pp_od,
03859 seg_no, ptp->pp_bendradius );
03860 break;
03861 default:
03862 bu_vls_printf( &vls, "unrecognized attribute (%c), choices are V, I, O, R, or P", attr[0] );
03863 status = TCL_ERROR;
03864 break;
03865 }
03866 }
03867 out:
03868 Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
03869 Tcl_DStringResult( interp, &ds );
03870 Tcl_DStringFree( &ds );
03871 bu_vls_free( &vls );
03872
03873 return( status );
03874
03875 }
03876
03877 int
03878 rt_pipe_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv, struct resource *resp)
03879 {
03880 struct rt_pipe_internal *pipe;
03881 struct wdb_pipept *ptp;
03882 Tcl_Obj *obj, *list;
03883 int seg_no;
03884 int num_segs;
03885 int curr_seg;
03886 fastf_t tmp;
03887 char *v_str;
03888
03889
03890 RT_CK_DB_INTERNAL( intern );
03891 pipe = (struct rt_pipe_internal *)intern->idb_ptr;
03892 RT_PIPE_CK_MAGIC( pipe );
03893
03894 while( argc >= 2 ) {
03895
03896
03897 num_segs = 0;
03898 if( pipe->pipe_segs_head.forw ) {
03899 for( BU_LIST_FOR( ptp, wdb_pipept, &pipe->pipe_segs_head ) )
03900 num_segs++;
03901 } else {
03902 BU_LIST_INIT( &pipe->pipe_segs_head );
03903 }
03904
03905 if( !isdigit( argv[0][1] ) ) {
03906 Tcl_SetResult( interp, "no vertex number specified", TCL_STATIC );
03907 return( TCL_ERROR );
03908 }
03909
03910 seg_no = atoi( &argv[0][1] );
03911 if( seg_no == num_segs ) {
03912 struct wdb_pipept *new_pt;
03913
03914 new_pt = (struct wdb_pipept *)bu_calloc( 1, sizeof( struct wdb_pipept ), "New pipe segment" );
03915 if( num_segs > 0 ) {
03916 ptp = BU_LIST_LAST( wdb_pipept, &pipe->pipe_segs_head );
03917 *new_pt = *ptp;
03918 BU_LIST_INSERT( &pipe->pipe_segs_head, &new_pt->l );
03919 ptp = new_pt;
03920 } else {
03921 VSETALL( new_pt->pp_coord, 0.0 );
03922 new_pt->pp_id = 0.0;
03923 new_pt->pp_od = 10.0;
03924 new_pt->pp_bendradius = 20.0;
03925 BU_LIST_INSERT( &pipe->pipe_segs_head, &new_pt->l );
03926 ptp = new_pt;
03927 }
03928 num_segs++;
03929 }
03930 if( seg_no < 0 || seg_no >= num_segs ) {
03931 Tcl_SetResult( interp, "vertex number out of range", TCL_STATIC );
03932 return( TCL_ERROR );
03933 }
03934
03935
03936 curr_seg = 0;
03937 for( BU_LIST_FOR( ptp, wdb_pipept, &pipe->pipe_segs_head ) ) {
03938 if( curr_seg == seg_no )
03939 break;
03940 curr_seg++;
03941 }
03942
03943
03944 switch( argv[0][0] ) {
03945 case 'V':
03946 obj = Tcl_NewStringObj( argv[1], -1 );
03947 list = Tcl_NewListObj( 0, NULL );
03948 Tcl_ListObjAppendList( interp, list, obj );
03949 v_str = Tcl_GetStringFromObj( list, NULL );
03950 while( isspace( *v_str ) ) v_str++;
03951 if( *v_str == '\0' ) {
03952 Tcl_SetResult( interp, "incomplete vertex specification", TCL_STATIC );
03953 Tcl_DecrRefCount( list );
03954 return( TCL_ERROR );
03955 }
03956 ptp->pp_coord[0] = atof( v_str );
03957 v_str = bu_next_token( v_str );
03958 if( *v_str == '\0' ) {
03959 Tcl_SetResult( interp, "incomplete vertex specification", TCL_STATIC );
03960 Tcl_DecrRefCount( list );
03961 return( TCL_ERROR );
03962 }
03963 ptp->pp_coord[1] = atof( v_str );
03964 v_str = bu_next_token( v_str );
03965 if( *v_str == '\0' ) {
03966 Tcl_SetResult( interp, "incomplete vertex specification", TCL_STATIC );
03967 Tcl_DecrRefCount( list );
03968 return( TCL_ERROR );
03969 }
03970 ptp->pp_coord[2] = atof( v_str );
03971 Tcl_DecrRefCount( list );
03972 break;
03973 case 'I':
03974 tmp = atof( argv[1] );
03975 if( tmp >= ptp->pp_od ) {
03976 Tcl_SetResult( interp, "inner diameter must be less than outer diameter", TCL_STATIC );
03977 return( TCL_ERROR );
03978 }
03979 ptp->pp_id = tmp;
03980 break;
03981 case 'O':
03982 tmp = atof( argv[1] );
03983 if( tmp <= 0.0 ) {
03984 Tcl_SetResult( interp, "outer diameter cannot be 0.0 or less", TCL_STATIC );
03985 return( TCL_ERROR );
03986 }
03987 if( tmp <= ptp->pp_id ) {
03988 Tcl_SetResult( interp, "outer diameter must be greater than inner diameter", TCL_STATIC );
03989 return( TCL_ERROR );
03990 }
03991 ptp->pp_od = tmp;
03992 break;
03993 case 'R':
03994 tmp = atof( argv[1] );
03995 if( tmp < ptp->pp_od * 0.5 ) {
03996 Tcl_SetResult( interp, "cannot set bend radius to less than outer radius", TCL_STATIC );
03997 return( TCL_ERROR );
03998 }
03999 ptp->pp_bendradius = tmp;
04000 break;
04001 default:
04002 Tcl_SetResult( interp, "unrecognized attribute, choices are V, I, O, or R", TCL_STATIC );
04003 return( TCL_ERROR );
04004 }
04005
04006 argc -= 2;
04007 argv += 2;
04008 }
04009
04010 return( TCL_OK );
04011 }
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021