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 #ifndef lint
00038 static const char RCSextrude[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_extrude.c,v 14.17 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00039 #endif
00040
00041 #include "common.h"
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <math.h>
00046 #ifdef HAVE_STRING_H
00047 # include <string.h>
00048 #else
00049 # include <strings.h>
00050 #endif
00051
00052 #include "machine.h"
00053 #include "tcl.h"
00054 #include "vmath.h"
00055 #include "db.h"
00056 #include "nmg.h"
00057 #include "rtgeom.h"
00058 #include "raytrace.h"
00059 #include "nurb.h"
00060 #include "./debug.h"
00061
00062 extern int seg_to_vlist( struct bu_list *vhead, const struct rt_tess_tol *ttol, point_t V,
00063 vect_t u_vec, vect_t v_vec, struct rt_sketch_internal *sketch_ip, genptr_t seg);
00064
00065 struct extrude_specific {
00066 mat_t rot, irot;
00067 vect_t unit_h;
00068 vect_t u_vec;
00069 vect_t v_vec;
00070 fastf_t uv_scale;
00071 vect_t rot_axis;
00072 vect_t perp;
00073 plane_t pl1, pl2;
00074 plane_t pl1_rot;
00075 point_t *verts;
00076 struct curve crv;
00077 };
00078
00079 static struct bn_tol extr_tol={
00080 BN_TOL_MAGIC,
00081 RT_LEN_TOL,
00082 RT_LEN_TOL*RT_LEN_TOL,
00083 0.0,
00084 1.0};
00085
00086 #define MAX_HITS 64
00087
00088
00089 #define TOP_FACE 1
00090 #define BOTTOM_FACE 2
00091 #define LINE_SEG 3
00092 #define CARC_SEG 4
00093 #define NURB_SEG 5
00094 #define BEZIER_SEG 6
00095
00096
00097 #define UNKNOWN 0
00098 #define A_IN_B 1
00099 #define B_IN_A 2
00100 #define DISJOINT 3
00101
00102 #define LOOPA 1
00103 #define LOOPB 2
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 int
00121 rt_extrude_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00122 {
00123 struct rt_extrude_internal *eip;
00124 register struct extrude_specific *extr;
00125 struct rt_sketch_internal *skt;
00126 LOCAL vect_t tmp, xyz[3];
00127 fastf_t tmp_f, ldir[3];
00128 int i, j;
00129 int vert_count;
00130 int curr_vert;
00131
00132 eip = (struct rt_extrude_internal *)ip->idb_ptr;
00133 RT_EXTRUDE_CK_MAGIC( eip );
00134 skt = eip->skt;
00135 RT_SKETCH_CK_MAGIC( skt );
00136
00137
00138 if( rt_check_curve( &skt->skt_curve, skt, 1 ) )
00139 {
00140 bu_log( "ERROR: referenced sketch (%s) is bad!!!\n",
00141 eip->sketch_name );
00142 return( -1 );
00143 }
00144
00145 BU_GETSTRUCT( extr, extrude_specific );
00146 stp->st_specific = (genptr_t)extr;
00147
00148 VMOVE( extr->unit_h, eip->h );
00149 VUNITIZE(extr->unit_h );
00150
00151
00152
00153
00154 extr->uv_scale = MAGNITUDE( eip->u_vec );
00155
00156
00157 VSET( tmp, 0, 0, 1 )
00158 bn_mat_fromto( extr->rot, eip->h, tmp );
00159
00160
00161 extr->rot[MDX] = -VDOT( eip->V, &extr->rot[0] );
00162 extr->rot[MDY] = -VDOT( eip->V, &extr->rot[4] );
00163 extr->rot[MDZ] = -VDOT( eip->V, &extr->rot[8] );
00164
00165
00166 bn_mat_inv( extr->irot, extr->rot );
00167
00168
00169 VCROSS( extr->pl1, eip->u_vec, eip->v_vec );
00170 VUNITIZE( extr->pl1 )
00171 extr->pl1[3] = VDOT( extr->pl1, eip->V );
00172 VMOVE( extr->pl2, extr->pl1 );
00173 VADD2( tmp, eip->V, eip->h );
00174 extr->pl2[3] = VDOT( extr->pl2, tmp );
00175
00176 vert_count = skt->vert_count;
00177
00178 for( i=0 ; i<skt->skt_curve.seg_count ; i++ )
00179 {
00180 struct carc_seg *csg=(struct carc_seg *)skt->skt_curve.segments[i];
00181
00182 if( csg->magic != CURVE_CARC_MAGIC )
00183 continue;
00184
00185 if( csg->radius <= 0.0 )
00186 continue;
00187
00188 vert_count++;
00189 }
00190
00191
00192 if( vert_count )
00193 extr->verts = (point_t *)bu_calloc( vert_count, sizeof( point_t ), "extr->verts" );
00194 VSETALL( stp->st_min, MAX_FASTF );
00195 VSETALL( stp->st_max, -MAX_FASTF );
00196 for( i=0 ; i<skt->vert_count ; i++ )
00197 {
00198 VJOIN2( tmp, eip->V, skt->verts[i][0], eip->u_vec, skt->verts[i][1], eip->v_vec );
00199 VMINMAX( stp->st_min, stp->st_max, tmp );
00200 MAT4X3PNT( extr->verts[i], extr->rot, tmp );
00201 VADD2( tmp, tmp, eip->h );
00202 VMINMAX( stp->st_min, stp->st_max, tmp );
00203 }
00204 curr_vert = skt->vert_count;
00205
00206
00207 MAT4X3VEC( extr->u_vec, extr->rot, eip->u_vec );
00208 MAT4X3VEC( extr->v_vec, extr->rot, eip->v_vec );
00209
00210
00211 VCROSS( extr->pl1_rot, extr->u_vec, extr->v_vec );
00212 VUNITIZE( extr->pl1_rot );
00213 extr->pl1_rot[3] = VDOT( extr->pl1_rot, extr->verts[0] );
00214
00215 VSET( tmp, 0, 0, 1 )
00216 tmp_f = VDOT( tmp, extr->unit_h );
00217 if( tmp_f < 0.0 )
00218 tmp_f = -tmp_f;
00219 tmp_f -= 1.0;
00220 if( NEAR_ZERO( tmp_f, SQRT_SMALL_FASTF ) )
00221 {
00222 VSET( extr->rot_axis, 1.0, 0.0, 0.0 );
00223 VSET( extr->perp, 0.0, 1.0, 0.0 );
00224 }
00225 else
00226 {
00227 VCROSS( extr->rot_axis, tmp, extr->unit_h );
00228 VUNITIZE( extr->rot_axis );
00229 if( MAGNITUDE( extr->rot_axis ) < SQRT_SMALL_FASTF )
00230 {
00231 VSET( extr->rot_axis, 1.0, 0.0, 0.0 );
00232 VSET( extr->perp, 0.0, 1.0, 0.0 );
00233 }
00234 else
00235 {
00236 VCROSS( extr->perp, extr->rot_axis, extr->pl1_rot );
00237 VUNITIZE( extr->perp );
00238 }
00239 }
00240
00241
00242 rt_copy_curve( &extr->crv, &skt->skt_curve );
00243
00244 VSET( xyz[X], 1, 0, 0 );
00245 VSET( xyz[Y], 0, 1, 0 );
00246 VSET( xyz[Z], 0, 0, 1 );
00247
00248 for( i=X ; i<=Z ; i++ ) {
00249 VCROSS( tmp, extr->unit_h, xyz[i] );
00250 ldir[i] = MAGNITUDE( tmp );
00251 }
00252
00253
00254 for( i=0 ; i<skt->skt_curve.seg_count ; i++ )
00255 {
00256 struct carc_seg *csg=(struct carc_seg *)skt->skt_curve.segments[i];
00257 struct carc_seg *csg_extr=(struct carc_seg *)extr->crv.segments[i];
00258 point_t center;
00259
00260 if( csg->magic != CURVE_CARC_MAGIC )
00261 continue;
00262
00263 if( csg->radius <= 0.0 )
00264 {
00265 point_t start;
00266 fastf_t radius;
00267
00268 csg_extr->center = csg->end;
00269 VJOIN2( start, eip->V, skt->verts[csg->start][0], eip->u_vec, skt->verts[csg->start][1], eip->v_vec );
00270 VJOIN2( center, eip->V, skt->verts[csg->end][0], eip->u_vec, skt->verts[csg->end][1], eip->v_vec );
00271 VSUB2( tmp, start, center );
00272 radius = MAGNITUDE( tmp );
00273 csg_extr->radius = -radius;
00274
00275 for( j=X ; j<=Z ; j++ ) {
00276 tmp_f = radius * ldir[j];
00277 VJOIN1( tmp, center, tmp_f, xyz[j] );
00278 VMINMAX( stp->st_min, stp->st_max, tmp );
00279 VADD2( tmp, tmp, eip->h );
00280 VMINMAX( stp->st_min, stp->st_max, tmp );
00281
00282 VJOIN1( tmp, center, -tmp_f, xyz[j] );
00283 VMINMAX( stp->st_min, stp->st_max, tmp );
00284 VADD2( tmp, tmp, eip->h );
00285 VMINMAX( stp->st_min, stp->st_max, tmp );
00286 }
00287 }
00288 else
00289 {
00290 point_t start, end, mid;
00291 vect_t s_to_m;
00292 vect_t bisector;
00293 fastf_t dist;
00294 fastf_t magsq_s2m;
00295
00296 VJOIN2( start, eip->V, skt->verts[csg->start][0], eip->u_vec, skt->verts[csg->start][1], eip->v_vec );
00297 VJOIN2( end, eip->V, skt->verts[csg->end][0], eip->u_vec, skt->verts[csg->end][1], eip->v_vec );
00298 VBLEND2( mid, 0.5, start, 0.5, end );
00299 VSUB2( s_to_m, mid, start );
00300 VCROSS( bisector, extr->pl1, s_to_m );
00301 VUNITIZE( bisector );
00302 magsq_s2m = MAGSQ( s_to_m );
00303 csg_extr->radius = csg->radius * extr->uv_scale;
00304 if( magsq_s2m > csg_extr->radius*csg_extr->radius )
00305 {
00306 fastf_t max_radius;
00307
00308 max_radius = sqrt( magsq_s2m );
00309 if( NEAR_ZERO( max_radius - csg_extr->radius, RT_LEN_TOL ) )
00310 csg_extr->radius = max_radius;
00311 else
00312 {
00313 bu_log( "Impossible radius for circular arc in extrusion (%s), is %g, cannot be more than %g!!!\n",
00314 stp->st_dp->d_namep, csg_extr->radius, sqrt(magsq_s2m) );
00315 bu_log( "Difference is %g\n", max_radius - csg->radius );
00316 return( -1 );
00317 }
00318 }
00319 dist = sqrt( csg_extr->radius*csg_extr->radius - magsq_s2m );
00320
00321
00322 if( csg->center_is_left )
00323 VJOIN1( center, mid, dist, bisector )
00324 else
00325 VJOIN1( center, mid, -dist, bisector )
00326 MAT4X3PNT( extr->verts[curr_vert], extr->rot, center );
00327 csg_extr->center = curr_vert;
00328 curr_vert++;
00329
00330 for( j=X ; j<=Z ; j++ ) {
00331 tmp_f = csg_extr->radius * ldir[j];
00332 VJOIN1( tmp, center, tmp_f, xyz[j] );
00333 VMINMAX( stp->st_min, stp->st_max, tmp );
00334 VADD2( tmp, tmp, eip->h );
00335 VMINMAX( stp->st_min, stp->st_max, tmp );
00336
00337 VJOIN1( tmp, center, -tmp_f, xyz[j] );
00338 VMINMAX( stp->st_min, stp->st_max, tmp );
00339 VADD2( tmp, tmp, eip->h );
00340 VMINMAX( stp->st_min, stp->st_max, tmp );
00341 }
00342 }
00343 }
00344
00345 VBLEND2( stp->st_center, 0.5, stp->st_min, 0.5, stp->st_max );
00346 VSUB2( tmp, stp->st_max, stp->st_min );
00347 stp->st_aradius = 0.5 * MAGNITUDE( tmp );
00348 stp->st_bradius = stp->st_aradius;
00349
00350 return(0);
00351 }
00352
00353
00354
00355
00356 void
00357 rt_extrude_print(register const struct soltab *stp)
00358 {
00359 }
00360
00361 int
00362 get_quadrant(fastf_t *v, fastf_t *local_x, fastf_t *local_y, fastf_t *vx, fastf_t *vy)
00363 {
00364
00365 *vx = V2DOT( v, local_x );
00366 *vy = V2DOT( v, local_y );
00367
00368 if( *vy >= 0.0 )
00369 {
00370 if( *vx >= 0.0 )
00371 return( 1 );
00372 else
00373 return( 2 );
00374 }
00375 else
00376 {
00377 if( *vx >= 0.0 )
00378 return( 4 );
00379 else
00380 return( 3 );
00381 }
00382 }
00383
00384 int
00385 isect_line2_ellipse(fastf_t *dist, fastf_t *ray_start, fastf_t *ray_dir, fastf_t *center, fastf_t *ra, fastf_t *rb)
00386 {
00387 fastf_t a, b, c;
00388 point2d_t pmc;
00389 fastf_t pmcda, pmcdb;
00390 fastf_t ra_sq, rb_sq;
00391 fastf_t ra_4, rb_4;
00392 fastf_t dda, ddb;
00393 fastf_t disc;
00394
00395 V2SUB2( pmc, ray_start, center );
00396 pmcda = V2DOT( pmc, ra );
00397 pmcdb = V2DOT( pmc, rb );
00398 ra_sq = V2DOT( ra, ra );
00399 ra_4 = ra_sq * ra_sq;
00400 rb_sq = V2DOT( rb, rb );
00401 rb_4 = rb_sq * rb_sq;
00402 if( ra_4 < SMALL_FASTF || rb_4 < SMALL_FASTF )
00403 {
00404 bu_log( "ray (%g %g %g) -> (%g %g %g), semi-axes = (%g %g %g) and (%g %g %g), center = (%g %g %g)\n",
00405 V3ARGS( ray_start ), V3ARGS( ray_dir ), V3ARGS( ra ), V3ARGS( rb ), V3ARGS( center ) );
00406 bu_bomb( "ERROR: isect_line2_ellipse: semi-axis length is too small!!!\n" );
00407 }
00408
00409 dda = V2DOT( ray_dir, ra );
00410 ddb = V2DOT( ray_dir, rb );
00411
00412 a = dda*dda/ra_4 + ddb*ddb/rb_4;
00413 b = 2.0 * (pmcda*dda/ra_4 + pmcdb*ddb/rb_4);
00414 c = pmcda*pmcda/ra_4 + pmcdb*pmcdb/rb_4 - 1.0;
00415
00416 disc = b*b - 4.0*a*c;
00417 if( disc < 0.0 )
00418 return( 0 );
00419
00420 if( disc <= SMALL_FASTF )
00421 {
00422 dist[0] = -b/(2.0*a);
00423 return( 1 );
00424 }
00425
00426 dist[0] = (-b - sqrt( disc )) / (2.0*a);
00427 dist[1] = (-b + sqrt( disc )) / (2.0*a);
00428 return( 2 );
00429 }
00430
00431
00432 int
00433 isect_line_earc(fastf_t *dist, fastf_t *ray_start, fastf_t *ray_dir, fastf_t *center, fastf_t *ra, fastf_t *rb, fastf_t *norm, fastf_t *start, fastf_t *end, int orientation)
00434
00435
00436
00437
00438
00439
00440 {
00441 int dist_count;
00442 vect_t local_x, local_y, local_z;
00443 fastf_t vx, vy;
00444 fastf_t ex, ey;
00445 fastf_t sx, sy;
00446 int quad_start, quad_end, quad_pt;
00447 point2d_t to_pt, pt;
00448 int i;
00449
00450 dist_count = isect_line2_ellipse( dist, ray_start, ray_dir, center, ra, rb);
00451
00452 if( dist_count == 0 )
00453 return( 0 );
00454
00455 if( orientation )
00456 VREVERSE( local_z, norm )
00457 else
00458 VMOVE( local_z, norm )
00459
00460 VMOVE( local_x, ra );
00461
00462 VCROSS( local_y, local_z, local_x );
00463
00464 V2SUB2( to_pt, end, center );
00465 quad_end = get_quadrant( to_pt, local_x, local_y, &ex, &ey );
00466 V2SUB2( to_pt, start, center );
00467 quad_start = get_quadrant( to_pt, local_x, local_y, &sx, &sy );
00468
00469 i = 0;
00470 while( i < dist_count )
00471 {
00472 int omit;
00473
00474 omit = 0;
00475 V2JOIN1( pt, ray_start, dist[i], ray_dir );
00476 V2SUB2( to_pt, pt, center );
00477 quad_pt = get_quadrant( to_pt, local_x, local_y, &vx, &vy );
00478
00479 if( quad_start < quad_end )
00480 {
00481 if( quad_pt > quad_end )
00482 omit = 1;
00483 else if( quad_pt < quad_start )
00484 omit = 1;
00485 else if( quad_pt == quad_end )
00486 {
00487 switch( quad_pt )
00488 {
00489 case 1:
00490 case 2:
00491 if( vx < ex )
00492 omit = 1;
00493 break;
00494 case 3:
00495 case 4:
00496 if( vx > ex )
00497 omit = 1;
00498 break;
00499 }
00500 }
00501 else if( quad_pt == quad_start )
00502 {
00503 switch( quad_pt )
00504 {
00505 case 1:
00506 case 2:
00507 if( vx > sx )
00508 omit = 1;
00509 break;
00510 case 3:
00511 case 4:
00512 if( vx < sx )
00513 omit = 1;
00514 break;
00515 }
00516 }
00517 }
00518 else if( quad_start > quad_end )
00519 {
00520 if( quad_pt > quad_end && quad_pt < quad_start )
00521 omit = 1;
00522 else if( quad_pt == quad_end )
00523 {
00524 switch( quad_pt )
00525 {
00526 case 1:
00527 case 2:
00528 if( vx < ex )
00529 omit = 1;
00530 break;
00531 case 3:
00532 case 4:
00533 if( vx > ex )
00534 omit = 1;
00535 break;
00536 }
00537 }
00538 else if( quad_pt == quad_start )
00539 {
00540 switch( quad_pt )
00541 {
00542 case 1:
00543 case 2:
00544 if( vx > sx )
00545 omit = 1;
00546 break;
00547 case 3:
00548 case 4:
00549 if( vx < sx )
00550 omit = 1;
00551 break;
00552 }
00553 }
00554 }
00555 else
00556 {
00557 if( quad_pt != quad_start )
00558 omit = 1;
00559 else
00560 {
00561 switch( quad_pt )
00562 {
00563 case 1:
00564 case 2:
00565 if( vx < ex || vx > sx )
00566 omit = 1;
00567 break;
00568 case 3:
00569 case 4:
00570 if( vx > ex || vx < sx )
00571 omit = 1;
00572 break;
00573 }
00574 }
00575 }
00576 if( omit )
00577 {
00578 if( i == 0 )
00579 dist[0] = dist[1];
00580 dist_count--;
00581 }
00582 else
00583 i++;
00584 }
00585
00586 return( dist_count );
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 int
00603 rt_extrude_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00604 {
00605 struct extrude_specific *extr=(struct extrude_specific *)stp->st_specific;
00606 register int i, j, k;
00607 fastf_t dist_top, dist_bottom, to_bottom=0;
00608 fastf_t dist[2];
00609 fastf_t dot_pl1, dir_dot_z;
00610 point_t tmp, tmp2;
00611 point_t ray_start, ray_dir, ray_dir_unit;
00612 struct curve *crv;
00613 struct hit hits[MAX_HITS];
00614 fastf_t dists_before[MAX_HITS];
00615 fastf_t dists_after[MAX_HITS];
00616 fastf_t *dists=NULL;
00617 int dist_count=0;
00618 int hit_count=0;
00619 int hits_before_bottom=0, hits_after_top=0;
00620 int code;
00621 int check_inout=0;
00622 int top_face=TOP_FACE, bot_face=BOTTOM_FACE;
00623 int surfno= -42;
00624 int free_dists=0;
00625 point2d_t *verts;
00626 point2d_t *intercept;
00627 point2d_t *normal;
00628 point2d_t ray_perp;
00629
00630 crv = &extr->crv;
00631
00632
00633 dot_pl1 = VDOT( rp->r_dir, extr->pl1 );
00634 if( NEAR_ZERO( dot_pl1, SMALL_FASTF ) )
00635 {
00636
00637 dist_bottom = DIST_PT_PLANE( rp->r_pt, extr->pl1 );
00638 dist_top = DIST_PT_PLANE( rp->r_pt, extr->pl2 );
00639 if( dist_bottom < 0.0 && dist_top < 0.0 )
00640 return( 0 );
00641 if( dist_bottom > 0.0 && dist_top > 0.0 )
00642 return( 0 );
00643 dist_bottom = -MAX_FASTF;
00644 dist_top = MAX_FASTF;
00645 }
00646 else
00647 {
00648 dist_bottom = -DIST_PT_PLANE( rp->r_pt, extr->pl1 )/dot_pl1;
00649 to_bottom = dist_bottom;
00650 dist_top = -DIST_PT_PLANE( rp->r_pt, extr->pl2 )/dot_pl1;
00651 if( dist_bottom > dist_top )
00652 {
00653 fastf_t tmp1;
00654
00655 tmp1 = dist_bottom;
00656 dist_bottom = dist_top;
00657 dist_top = tmp1;
00658 top_face = BOTTOM_FACE;
00659 bot_face = TOP_FACE;
00660 }
00661 }
00662
00663
00664 MAT4X3PNT( ray_start, extr->rot, rp->r_pt );
00665 MAT4X3VEC( ray_dir, extr->rot, rp->r_dir );
00666
00667 dir_dot_z = ray_dir[Z];
00668 if( dir_dot_z < 0.0 )
00669 dir_dot_z = -dir_dot_z;
00670
00671 if( NEAR_ZERO( dir_dot_z - 1.0, SMALL_FASTF ) )
00672 {
00673
00674
00675
00676 check_inout = 1;
00677
00678
00679 VJOIN1( tmp, rp->r_pt, to_bottom, rp->r_dir );
00680 MAT4X3PNT( ray_start, extr->rot, tmp );
00681
00682
00683 VMOVE( ray_dir, extr->u_vec );
00684 }
00685
00686
00687 for( i=0 ; i<crv->seg_count ; i++ )
00688 {
00689 long *lng=(long *)crv->segments[i];
00690 struct line_seg *lsg;
00691 struct carc_seg *csg=NULL;
00692 struct bezier_seg *bsg=NULL;
00693 fastf_t diff;
00694
00695 free_dists = 0;
00696 switch( *lng )
00697 {
00698 case CURVE_LSEG_MAGIC:
00699 lsg = (struct line_seg *)lng;
00700 VSUB2( tmp, extr->verts[lsg->end], extr->verts[lsg->start] );
00701 VMOVE( tmp2, extr->verts[lsg->start] );
00702 code = bn_isect_line2_line2( dist, ray_start, ray_dir, tmp2, tmp, &extr_tol );
00703 if( code < 1 )
00704 continue;
00705
00706 if( dist[1] > 1.0 || dist[1] < 0.0 )
00707 continue;
00708
00709 dists = dist;
00710 dist_count = 1;
00711 surfno = LINE_SEG;
00712 break;
00713 case CURVE_CARC_MAGIC:
00714
00715 csg = (struct carc_seg *)lng;
00716 {
00717 vect_t ra, rb;
00718 fastf_t radius;
00719
00720 if( csg->radius <= 0.0 )
00721 {
00722
00723 radius = -csg->radius;
00724
00725
00726
00727
00728 VSCALE( ra, extr->rot_axis, radius );
00729 VSCALE( rb, extr->perp, radius );
00730
00731 dist_count = isect_line2_ellipse( dist, ray_start, ray_dir, extr->verts[csg->end], ra, rb );
00732 MAT4X3PNT( tmp, extr->irot, extr->verts[csg->end] );
00733 }
00734 else
00735 {
00736 VSCALE( ra, extr->rot_axis, csg->radius );
00737 VSCALE( rb, extr->perp, csg->radius );
00738 dist_count = isect_line_earc( dist, ray_start, ray_dir, extr->verts[csg->center], ra, rb, extr->pl1_rot, extr->verts[csg->start], extr->verts[csg->end], csg->orientation );
00739 MAT4X3PNT( tmp, extr->irot, extr->verts[csg->center] );
00740 }
00741 }
00742 if( dist_count < 1 )
00743 continue;
00744
00745 dists = dist;
00746 surfno = CARC_SEG;
00747 break;
00748 case CURVE_BEZIER_MAGIC:
00749 bsg = (struct bezier_seg *)lng;
00750 verts = (point2d_t *)bu_calloc( bsg->degree + 1, sizeof( point2d_t ), "Bezier verts" );
00751 for( j=0 ; j<=bsg->degree ; j++ ) {
00752 V2MOVE( verts[j], extr->verts[bsg->ctl_points[j]] );
00753 }
00754 V2MOVE( ray_dir_unit, ray_dir );
00755 diff = sqrt( MAG2SQ( ray_dir ) );
00756 ray_dir_unit[X] /= diff;
00757 ray_dir_unit[Y] /= diff;
00758 ray_dir_unit[Z] = 0.0;
00759 ray_perp[X] = ray_dir[Y];
00760 ray_perp[Y] = -ray_dir[X];
00761 dist_count = FindRoots( verts, bsg->degree, &intercept, &normal, ray_start, ray_dir_unit, ray_perp,
00762 0, extr_tol.dist );
00763 if( dist_count ) {
00764 free_dists = 1;
00765 dists = (fastf_t *)bu_calloc( dist_count, sizeof( fastf_t ), "dists (Bezier)" );
00766 for( j=0 ; j<dist_count ; j++ ) {
00767 point2d_t to_pt;
00768 V2SUB2( to_pt, intercept[j], ray_start );
00769 dists[j] = V2DOT( to_pt, ray_dir_unit) / diff;
00770 }
00771 bu_free( (char *)intercept, "Bezier intercept" );
00772 surfno = BEZIER_SEG;
00773 }
00774 bu_free( (char *)verts, "Bezier verts" );
00775 break;
00776 case CURVE_NURB_MAGIC:
00777 break;
00778 default:
00779 bu_log( "Unrecognized segment type in sketch (%s) referenced by extrusion (%s)\n",
00780 stp->st_dp->d_namep );
00781 bu_bomb( "Unrecognized segment type in sketch\n" );
00782 break;
00783 }
00784
00785
00786 for( j=0 ; j<hit_count ; j++ )
00787 {
00788 k = 0;
00789 while( k < dist_count )
00790 {
00791 diff = dists[k] - hits[j].hit_dist;
00792 if( NEAR_ZERO( diff, extr_tol.dist ) )
00793 {
00794 int n;
00795 for( n=k ; n<dist_count-1 ; n++ ) {
00796 dists[n] = dists[n+1];
00797 if( *lng == CURVE_BEZIER_MAGIC ) {
00798 V2MOVE( normal[n], normal[n+1] );
00799 }
00800 }
00801 dist_count--;
00802 }
00803 else
00804 k++;
00805 }
00806 }
00807
00808
00809 for( j=0 ; j<hits_before_bottom ; j++ )
00810 {
00811 k = 0;
00812 while( k < dist_count )
00813 {
00814 diff = dists[k] - dists_before[j];
00815 if( NEAR_ZERO( diff, extr_tol.dist ) )
00816 {
00817 int n;
00818
00819 for( n=k ; n<dist_count-1 ; n++ ) {
00820 dists[n] = dists[n+1];
00821 if( *lng == CURVE_BEZIER_MAGIC ) {
00822 V2MOVE( normal[n], normal[n+1] );
00823 }
00824 }
00825 dist_count--;
00826 }
00827 else
00828 k++;
00829 }
00830 }
00831
00832
00833 for( j=0 ; j<hits_after_top ; j++ )
00834 {
00835 k = 0;
00836 while( k < dist_count )
00837 {
00838 diff = dists[k] - dists_after[j];
00839 if( NEAR_ZERO( diff, extr_tol.dist ) )
00840 {
00841 int n;
00842
00843 for( n=k ; n<dist_count-1 ; n++ )
00844 dists[n] = dists[n+1];
00845 dist_count--;
00846 }
00847 else
00848 k++;
00849 }
00850 }
00851
00852
00853 if( check_inout )
00854 {
00855 for( j=0 ; j<dist_count ; j++ )
00856 {
00857 if( dists[j] < 0.0 )
00858 hit_count++;
00859 }
00860 continue;
00861 }
00862
00863
00864 for( j=0 ; j<dist_count ; j++ )
00865 {
00866 if( dists[j] < dist_bottom )
00867 {
00868 if( hits_before_bottom >= MAX_HITS )
00869 {
00870 bu_log( "ERROR: rt_extrude_shot: too many hits before bottom on extrusion (%s), limit is %d\n",
00871 stp->st_dp->d_namep, MAX_HITS );
00872 bu_bomb( "ERROR: rt_extrude_shot: too many hits before bottom on extrusion\n" );
00873 }
00874 dists_before[hits_before_bottom] = dists[j];
00875 hits_before_bottom++;
00876 continue;
00877 }
00878 if( dists[j] > dist_top )
00879 {
00880 if( hits_after_top >= MAX_HITS )
00881 {
00882 bu_log( "ERROR: rt_extrude_shot: too many hits after top on extrusion (%s), limit is %d\n",
00883 stp->st_dp->d_namep, MAX_HITS );
00884 bu_bomb( "ERROR: rt_extrude_shot: too many hits after top on extrusion\n" );
00885 }
00886 dists_after[hits_after_top] = dists[j];
00887 hits_after_top++;
00888
00889 continue;
00890 }
00891
00892
00893 if( hit_count >= MAX_HITS )
00894 {
00895 bu_log( "Too many hits on extrusion (%s), limit is %d\n",
00896 stp->st_dp->d_namep, MAX_HITS );
00897 bu_bomb( "Too many hits on extrusion\n" );
00898 }
00899 hits[hit_count].hit_magic = RT_HIT_MAGIC;
00900 hits[hit_count].hit_dist = dists[j];
00901 hits[hit_count].hit_surfno = surfno;
00902 switch( *lng )
00903 {
00904 case CURVE_CARC_MAGIC:
00905 hits[hit_count].hit_private = (genptr_t)csg;
00906 VMOVE( hits[hit_count].hit_vpriv, tmp );
00907 break;
00908 case CURVE_LSEG_MAGIC:
00909 VMOVE( hits[hit_count].hit_vpriv, tmp );
00910 break;
00911 case CURVE_BEZIER_MAGIC:
00912 V2MOVE( hits[hit_count].hit_vpriv, normal[j] );
00913 hits[hit_count].hit_vpriv[Z] = 0.0;
00914 break;
00915 default:
00916 bu_log( "ERROR: rt_extrude_shot: unrecognized segment type in solid %s\n",
00917 stp->st_dp->d_namep );
00918 bu_bomb( "ERROR: rt_extrude_shot: unrecognized segment type in solid\n" );
00919 break;
00920 }
00921 hit_count++;
00922 }
00923 if( free_dists )
00924 bu_free( (char *)dists, "dists" );
00925 }
00926
00927 if( check_inout )
00928 {
00929 if( hit_count&1 )
00930 {
00931 register struct seg *segp;
00932
00933 hit_count = 2;
00934 hits[0].hit_magic = RT_HIT_MAGIC;
00935 hits[0].hit_dist = dist_bottom;
00936 hits[0].hit_surfno = bot_face;
00937 VMOVE( hits[0].hit_normal, extr->pl1 );
00938
00939 hits[1].hit_magic = RT_HIT_MAGIC;
00940 hits[1].hit_dist = dist_top;
00941 hits[1].hit_surfno = -top_face;
00942 VMOVE( hits[1].hit_normal, extr->pl1 );
00943
00944 RT_GET_SEG(segp, ap->a_resource);
00945 segp->seg_stp = stp;
00946 segp->seg_in = hits[0];
00947 segp->seg_out = hits[1];
00948 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00949 return( 2 );
00950 }
00951 else
00952 {
00953 return( 0 );
00954 }
00955 }
00956
00957 if( hit_count )
00958 {
00959
00960 rt_hitsort( hits, hit_count );
00961 }
00962
00963 if( hits_before_bottom & 1 )
00964 {
00965 if( hit_count >= MAX_HITS )
00966 {
00967 bu_log( "Too many hits on extrusion (%s), limit is %d\n",
00968 stp->st_dp->d_namep, MAX_HITS );
00969 bu_bomb( "Too many hits on extrusion\n" );
00970 }
00971 for( i=hit_count-1 ; i>=0 ; i-- )
00972 hits[i+1] = hits[i];
00973 hits[0].hit_magic = RT_HIT_MAGIC;
00974 hits[0].hit_dist = dist_bottom;
00975 hits[0].hit_surfno = bot_face;
00976 VMOVE( hits[0].hit_normal, extr->pl1 );
00977 hit_count++;
00978 }
00979
00980 if( hits_after_top & 1 )
00981 {
00982 if( hit_count >= MAX_HITS )
00983 {
00984 bu_log( "Too many hits on extrusion (%s), limit is %d\n",
00985 stp->st_dp->d_namep, MAX_HITS );
00986 bu_bomb( "Too many hits on extrusion\n" );
00987 }
00988 hits[hit_count].hit_magic = RT_HIT_MAGIC;
00989 hits[hit_count].hit_dist = dist_top;
00990 hits[hit_count].hit_surfno = top_face;
00991 VMOVE( hits[hit_count].hit_normal, extr->pl1 );
00992 hit_count++;
00993 }
00994
00995 if( hit_count%2 )
00996 {
00997 point_t pt;
00998
00999 if( hit_count != 1 ) {
01000 bu_log( "ERROR: rt_extrude_shot(): odd number of hits (%d) (ignoring last hit)\n", hit_count );
01001 bu_log( "ray start = (%20.10f %20.10f %20.10f)\n", V3ARGS( rp->r_pt ) );
01002 bu_log( "\tray dir = (%20.10f %20.10f %20.10f)", V3ARGS( rp->r_dir ) );
01003 VJOIN1( pt, rp->r_pt, hits[hit_count-1].hit_dist, rp->r_dir );
01004 bu_log( "\tignored hit at (%g %g %g)\n", V3ARGS( pt ) );
01005 }
01006 hit_count--;
01007 }
01008
01009
01010 {
01011 register struct seg *segp;
01012
01013 for( i=0; i < hit_count; i += 2 ) {
01014 RT_GET_SEG(segp, ap->a_resource);
01015 segp->seg_stp = stp;
01016 segp->seg_in = hits[i];
01017 segp->seg_out = hits[i+1];
01018 segp->seg_out.hit_surfno = -segp->seg_out.hit_surfno;
01019 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
01020 }
01021 }
01022
01023 return( hit_count );
01024 }
01025
01026 #define RT_EXTRUDE_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
01027
01028
01029
01030
01031
01032
01033 void
01034 rt_extrude_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
01035
01036
01037
01038
01039
01040 {
01041 rt_vstub( stp, rp, segp, n, ap );
01042 }
01043
01044
01045
01046
01047
01048
01049 void
01050 rt_extrude_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
01051 {
01052 struct extrude_specific *extr=(struct extrude_specific *)stp->st_specific;
01053 fastf_t alpha;
01054 point_t hit_in_plane;
01055 vect_t tmp, tmp2;
01056
01057 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
01058
01059 switch( hitp->hit_surfno )
01060 {
01061 case LINE_SEG:
01062 MAT4X3VEC( tmp, extr->irot, hitp->hit_vpriv );
01063 VCROSS( hitp->hit_normal, extr->unit_h, tmp );
01064 VUNITIZE( hitp->hit_normal );
01065 break;
01066 case -LINE_SEG:
01067 MAT4X3VEC( tmp, extr->irot, hitp->hit_vpriv );
01068 VCROSS( hitp->hit_normal, extr->unit_h, tmp );
01069 VUNITIZE( hitp->hit_normal );
01070 break;
01071 case TOP_FACE:
01072 case BOTTOM_FACE:
01073 case -TOP_FACE:
01074 case -BOTTOM_FACE:
01075 break;
01076 case CARC_SEG:
01077 case -CARC_SEG:
01078 alpha = DIST_PT_PLANE( hitp->hit_point, extr->pl1 ) / VDOT( extr->unit_h, extr->pl1 );
01079 VJOIN1( hit_in_plane, hitp->hit_point, -alpha, extr->unit_h );
01080 VSUB2( tmp, hit_in_plane, hitp->hit_vpriv );
01081 VCROSS( tmp2, extr->pl1, tmp );
01082 VCROSS( hitp->hit_normal, tmp2, extr->unit_h );
01083 VUNITIZE( hitp->hit_normal );
01084 break;
01085 case BEZIER_SEG:
01086 case -BEZIER_SEG:
01087 MAT4X3VEC( hitp->hit_normal, extr->irot, hitp->hit_vpriv );
01088 VUNITIZE( hitp->hit_normal );
01089 break;
01090 default:
01091 bu_bomb( "ERROR: rt_extrude_norm(): unrecognized surf_no in hit structure!!!\n" );
01092 break;
01093 }
01094 if( hitp->hit_surfno < 0 )
01095 {
01096 if( VDOT( hitp->hit_normal, rp->r_dir ) < 0.0 )
01097 VREVERSE( hitp->hit_normal, hitp->hit_normal );
01098 }
01099 else
01100 {
01101 if( VDOT( hitp->hit_normal, rp->r_dir ) > 0.0 )
01102 VREVERSE( hitp->hit_normal, hitp->hit_normal );
01103 }
01104
01105 }
01106
01107
01108
01109
01110
01111
01112 void
01113 rt_extrude_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
01114 {
01115 struct extrude_specific *extr=(struct extrude_specific *)stp->st_specific;
01116 struct carc_seg *csg;
01117 fastf_t radius, a, b, a_sq, b_sq;
01118 fastf_t curvature, tmp, dota, dotb;
01119 fastf_t der;
01120 vect_t diff;
01121 vect_t ra, rb;
01122
01123 switch( hitp->hit_surfno )
01124 {
01125 case LINE_SEG:
01126 case -LINE_SEG:
01127 VMOVE( cvp->crv_pdir, hitp->hit_vpriv );
01128 VUNITIZE( cvp->crv_pdir );
01129 cvp->crv_c1 = cvp->crv_c2 = 0;
01130 break;
01131 case CARC_SEG:
01132 case -CARC_SEG:
01133
01134
01135
01136 csg = (struct carc_seg *)hitp->hit_private;
01137 VCROSS( cvp->crv_pdir, extr->unit_h, hitp->hit_normal );
01138 VSUB2( diff, hitp->hit_point, hitp->hit_vpriv );
01139 if( csg->radius < 0.0 )
01140 radius = -csg->radius;
01141 else
01142 radius = csg->radius;
01143 VSCALE( ra, extr->rot_axis, radius );
01144 VSCALE( rb, extr->perp, radius );
01145
01146 a_sq = MAG2SQ( ra );
01147 b_sq = MAG2SQ( rb );
01148 a = sqrt( a_sq );
01149 b = sqrt( b_sq );
01150 dota = VDOT( diff, ra );
01151 dotb = VDOT( diff, rb );
01152 tmp = (a_sq/(b_sq*b_sq))*dotb*dotb + (b_sq/(a_sq*a_sq))*dota*dota;
01153 der = sqrt( tmp );
01154 curvature = a*b/(der*der*der);
01155 if( VDOT( hitp->hit_normal, diff ) > 0.0 )
01156 cvp->crv_c1 = curvature;
01157 else
01158 cvp->crv_c1 = -curvature;
01159 cvp->crv_c2 = 0;
01160 break;
01161 }
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 void
01173 rt_extrude_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
01174 {
01175 }
01176
01177
01178
01179
01180 void
01181 rt_extrude_free(register struct soltab *stp)
01182 {
01183 register struct extrude_specific *extrude =
01184 (struct extrude_specific *)stp->st_specific;
01185
01186 if( extrude->verts )
01187 bu_free( (char *)extrude->verts, "extrude->verts" );
01188 rt_curve_free( &(extrude->crv) );
01189 bu_free( (char *)extrude, "extrude_specific" );
01190 }
01191
01192
01193
01194
01195 int
01196 rt_extrude_class(void)
01197 {
01198 return(0);
01199 }
01200
01201
01202
01203
01204 int
01205 rt_extrude_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01206 {
01207 LOCAL struct rt_extrude_internal *extrude_ip;
01208 struct curve *crv=(struct curve *)NULL;
01209 struct rt_sketch_internal *sketch_ip;
01210 point_t end_of_h;
01211 int i1, i2, nused1, nused2;
01212 struct bn_vlist *vp1, *vp2, *vp2_start;
01213
01214 RT_CK_DB_INTERNAL(ip);
01215 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
01216 RT_EXTRUDE_CK_MAGIC(extrude_ip);
01217
01218 if( !extrude_ip->skt )
01219 {
01220 bu_log( "ERROR: no sketch to extrude!\n" );
01221 RT_ADD_VLIST( vhead, extrude_ip->V, BN_VLIST_LINE_MOVE );
01222 RT_ADD_VLIST( vhead, extrude_ip->V, BN_VLIST_LINE_DRAW );
01223 return( 0 );
01224 }
01225
01226 sketch_ip = extrude_ip->skt;
01227 RT_SKETCH_CK_MAGIC( sketch_ip );
01228
01229 crv = &sketch_ip->skt_curve;
01230
01231
01232 if (crv->seg_count == 0)
01233 {
01234 if (extrude_ip->sketch_name) {
01235 bu_log("Sketch [%s] is empty, nothing to draw\n", extrude_ip->sketch_name);
01236 } else {
01237 bu_log("Unnamed sketch is empty, nothing to draw\n");
01238 }
01239 RT_ADD_VLIST( vhead, extrude_ip->V, BN_VLIST_LINE_MOVE );
01240 RT_ADD_VLIST( vhead, extrude_ip->V, BN_VLIST_LINE_DRAW );
01241 return( 0 );
01242 }
01243
01244
01245 vp1 = BU_LIST_LAST( bn_vlist, vhead );
01246 nused1 = vp1->nused;
01247 if( curve_to_vlist( vhead, ttol, extrude_ip->V, extrude_ip->u_vec, extrude_ip->v_vec, sketch_ip, crv ) )
01248 {
01249 bu_log( "ERROR: sketch (%s) references non-existent vertices!\n",
01250 extrude_ip->sketch_name );
01251 return( -1 );
01252 }
01253
01254
01255 VADD2( end_of_h, extrude_ip->V, extrude_ip->h );
01256 vp2 = BU_LIST_LAST( bn_vlist, vhead );
01257 nused2 = vp2->nused;
01258 curve_to_vlist( vhead, ttol, end_of_h, extrude_ip->u_vec, extrude_ip->v_vec, sketch_ip, crv );
01259
01260
01261 vp2_start = vp2;
01262 i1 = nused1;
01263 if (i1 >= vp1->nused) {
01264 i1 = 0;
01265 vp1 = BU_LIST_NEXT( bn_vlist, &vp1->l );
01266 }
01267 i2 = nused2;
01268 if (i2 >= vp2->nused) {
01269 i2 = 0;
01270 vp2 = BU_LIST_NEXT( bn_vlist, &vp2->l );
01271 nused2--;
01272 }
01273
01274 while( vp1 != vp2_start || (i1 < BN_VLIST_CHUNK && i2 < BN_VLIST_CHUNK && i1 != nused2) )
01275 {
01276 RT_ADD_VLIST( vhead, vp1->pt[i1], BN_VLIST_LINE_MOVE );
01277 RT_ADD_VLIST( vhead, vp2->pt[i2], BN_VLIST_LINE_DRAW );
01278 i1++;
01279 if( i1 >= vp1->nused )
01280 {
01281 i1 = 0;
01282 vp1 = BU_LIST_NEXT( bn_vlist, &vp1->l );
01283 }
01284 i2++;
01285 if( i2 >= vp2->nused )
01286 {
01287 i2 = 0;
01288 vp2 = BU_LIST_NEXT( bn_vlist, &vp2->l );
01289 }
01290 }
01291
01292 return(0);
01293 }
01294
01295 void
01296 get_indices( genptr_t seg, int *start, int *end )
01297 {
01298 struct carc_seg *csg;
01299 struct nurb_seg *nsg;
01300 struct bezier_seg *bsg;
01301 struct line_seg *lsg=(struct line_seg *)seg;
01302
01303 switch (lsg->magic) {
01304 case CURVE_LSEG_MAGIC:
01305 *start = lsg->start;
01306 *end = lsg->end;
01307 break;
01308 case CURVE_CARC_MAGIC:
01309 csg = (struct carc_seg *)seg;
01310 if( csg->radius < 0.0 ) {
01311 *start = csg->start;
01312 *end = *start;
01313 break;
01314 }
01315 *start = csg->start;
01316 *end = csg->end;
01317 break;
01318 case CURVE_NURB_MAGIC:
01319 nsg = (struct nurb_seg *)seg;
01320 *start = nsg->ctl_points[0];
01321 *end = nsg->ctl_points[nsg->c_size-1];
01322 break;
01323 case CURVE_BEZIER_MAGIC:
01324 bsg = (struct bezier_seg *)seg;
01325 *start = bsg->ctl_points[0];
01326 *end = bsg->ctl_points[bsg->degree];
01327 break;
01328 }
01329 }
01330
01331 void
01332 get_seg_midpoint( genptr_t seg, struct rt_sketch_internal *skt, point2d_t pt )
01333 {
01334 struct edge_g_cnurb eg;
01335 point_t tmp_pt;
01336 struct line_seg *lsg;
01337 struct carc_seg *csg;
01338 struct nurb_seg *nsg;
01339 struct bezier_seg *bsg;
01340 long *lng;
01341 point2d_t *V;
01342 point2d_t pta;
01343 int i;
01344 int coords;
01345
01346 lng = (long *)seg;
01347
01348 switch( *lng )
01349 {
01350 case CURVE_LSEG_MAGIC:
01351 lsg = (struct line_seg *)lng;
01352 VADD2_2D( pta, skt->verts[lsg->start], skt->verts[lsg->end] );
01353 VSCALE_2D( pt, pta, 0.5 );
01354 break;
01355 case CURVE_CARC_MAGIC:
01356 csg = (struct carc_seg *)lng;
01357 if( csg->radius < 0.0 ) {
01358 VMOVE_2D( pt, skt->verts[csg->start] );
01359 } else {
01360 point2d_t start2d, end2d, mid_pt, s2m, dir, center2d;
01361 fastf_t tmp_len, len_sq, mid_ang, s2m_len_sq, cross_z;
01362 fastf_t start_ang, end_ang;
01363
01364
01365 V2MOVE( start2d, skt->verts[csg->start] );
01366 V2MOVE( end2d, skt->verts[csg->end] );
01367 mid_pt[0] = (start2d[0] + end2d[0]) * 0.5;
01368 mid_pt[1] = (start2d[1] + end2d[1]) * 0.5;
01369 V2SUB2( s2m, mid_pt, start2d );
01370 dir[0] = -s2m[1];
01371 dir[1] = s2m[0];
01372 s2m_len_sq = s2m[0]*s2m[0] + s2m[1]*s2m[1];
01373 if( s2m_len_sq < SMALL_FASTF ) {
01374 bu_log( "start and end points are too close together in circular arc of sketch\n" );
01375 break;
01376 }
01377 len_sq = csg->radius*csg->radius - s2m_len_sq;
01378 if( len_sq < 0.0 ) {
01379 bu_log( "Impossible radius for specified start and end points in circular arc\n");
01380 break;
01381 }
01382 tmp_len = sqrt( dir[0]*dir[0] + dir[1]*dir[1] );
01383 dir[0] = dir[0] / tmp_len;
01384 dir[1] = dir[1] / tmp_len;
01385 tmp_len = sqrt( len_sq );
01386 V2JOIN1( center2d, mid_pt, tmp_len, dir );
01387
01388
01389 cross_z = ( end2d[X] - start2d[X] )*( center2d[Y] - start2d[Y] ) -
01390 ( end2d[Y] - start2d[Y] )*( center2d[X] - start2d[X] );
01391 if( !(cross_z > 0.0 && csg->center_is_left) ) {
01392 V2JOIN1( center2d, mid_pt, -tmp_len, dir );
01393 }
01394 start_ang = atan2( start2d[Y]-center2d[Y], start2d[X]-center2d[X] );
01395 end_ang = atan2( end2d[Y]-center2d[Y], end2d[X]-center2d[X] );
01396 if( csg->orientation ) {
01397 while( end_ang > start_ang )
01398 end_ang -= 2.0 * M_PI;
01399 }
01400 else {
01401 while( end_ang < start_ang )
01402 end_ang += 2.0 * M_PI;
01403 }
01404
01405
01406 mid_ang = (start_ang + end_ang ) * 0.5;
01407
01408
01409 pt[X] = center2d[X] + csg->radius * cos( mid_ang );
01410 pt[Y] = center2d[Y] + csg->radius * sin( mid_ang );
01411 break;
01412 }
01413 break;
01414 case CURVE_NURB_MAGIC:
01415 nsg = (struct nurb_seg *)lng;
01416
01417 eg.l.magic = NMG_EDGE_G_CNURB_MAGIC;
01418 eg.order = nsg->order;
01419 eg.k.k_size = nsg->k.k_size;
01420 eg.k.knots = nsg->k.knots;
01421 eg.c_size = nsg->c_size;
01422 coords = 2 + RT_NURB_IS_PT_RATIONAL( nsg->pt_type );
01423 eg.pt_type = RT_NURB_MAKE_PT_TYPE( coords, 2, RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) );
01424 eg.ctl_points = (fastf_t *)bu_malloc( nsg->c_size * coords * sizeof( fastf_t ), "eg.ctl_points" );
01425 if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) ) {
01426 for( i=0 ; i<nsg->c_size ; i++ ) {
01427 VMOVE_2D( &eg.ctl_points[i*coords], skt->verts[nsg->ctl_points[i]] );
01428 eg.ctl_points[(i+1)*coords - 1] = nsg->weights[i];
01429 }
01430 }
01431 else {
01432 for( i=0 ; i<nsg->c_size ; i++ ) {
01433 VMOVE_2D( &eg.ctl_points[i*coords], skt->verts[nsg->ctl_points[i]] );
01434 }
01435 }
01436 rt_nurb_c_eval( &eg, (nsg->k.knots[nsg->k.k_size-1] - nsg->k.knots[0]) * 0.5, tmp_pt );
01437 if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) ) {
01438 int j;
01439
01440 for( j=0 ; j<coords-1 ; j++ )
01441 pt[j] = tmp_pt[j] / tmp_pt[coords-1];
01442 } else {
01443 V2MOVE( pt, tmp_pt );
01444 }
01445 bu_free( (char *)eg.ctl_points, "eg.ctl_points" );
01446 break;
01447 case CURVE_BEZIER_MAGIC:
01448 bsg = (struct bezier_seg *)lng;
01449 V = (point2d_t *)bu_calloc( bsg->degree+1, sizeof( point2d_t ), "Bezier control points" );
01450 for( i=0 ; i<= bsg->degree ; i++ ) {
01451 VMOVE_2D( V[i], skt->verts[bsg->ctl_points[i]] );
01452 }
01453 Bezier( V, bsg->degree, 0.51, NULL, NULL, pt, NULL );
01454 bu_free( (char *)V, "Bezier control points" );
01455 break;
01456 default:
01457 bu_bomb( "Unrecognized segment type in sketch\n");
01458 break;
01459 }
01460 }
01461
01462 struct loop_inter {
01463 int which_loop;
01464 int vert_index;
01465 fastf_t dist;
01466 struct loop_inter *next;
01467 };
01468
01469 void
01470 isect_2D_loop_ray( point2d_t pta, point2d_t dir, struct bu_ptbl *loop, struct loop_inter **root,
01471 int which_loop, struct rt_sketch_internal *ip, struct bn_tol *tol )
01472 {
01473 int i, j;
01474 int code;
01475 point2d_t norm;
01476 fastf_t dist[2];
01477
01478 norm[0] = -dir[1];
01479 norm[1] = dir[0];
01480
01481 for( i=0 ; i<BU_PTBL_END( loop ) ; i++ ) {
01482 long *lng;
01483 struct loop_inter *inter;
01484 struct line_seg *lsg=NULL;
01485 struct carc_seg *csg=NULL;
01486 struct bezier_seg *bsg=NULL;
01487 point2d_t d1;
01488 point2d_t diff;
01489 fastf_t radius;
01490 point2d_t *verts;
01491 point2d_t *intercept;
01492 point2d_t *normal;
01493
01494 lng = BU_PTBL_GET( loop, i );
01495 switch( *lng ) {
01496 case CURVE_LSEG_MAGIC:
01497 lsg = (struct line_seg *)lng;
01498 V2SUB2( d1, ip->verts[lsg->end], ip->verts[lsg->start] );
01499 code = bn_isect_line2_lseg2( dist, pta, dir, ip->verts[lsg->start], d1, tol );
01500 if( code < 0 )
01501 break;
01502 if( code == 0 ) {
01503
01504
01505 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01506 "loop intersection" );
01507 inter->which_loop = which_loop;
01508 inter->vert_index = lsg->start;
01509 inter->dist = dist[0];
01510 inter->next = NULL;
01511 if( !(*root) ) {
01512 (*root) = inter;
01513 } else {
01514 inter->next = (*root);
01515 (*root) = inter;
01516 }
01517 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01518 "loop intersection" );
01519 inter->which_loop = which_loop;
01520 inter->vert_index = lsg->end;
01521 inter->dist = dist[1];
01522 inter->next = NULL;
01523 inter->next = (*root);
01524 (*root) = inter;
01525 } else if( code == 1 ) {
01526
01527 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01528 "loop intersection" );
01529 inter->which_loop = which_loop;
01530 inter->vert_index = lsg->start;
01531 inter->dist = dist[0];
01532 inter->next = NULL;
01533 if( !(*root) ) {
01534 (*root) = inter;
01535 } else {
01536 inter->next = (*root);
01537 (*root) = inter;
01538 }
01539 } else if( code == 2 ) {
01540
01541 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01542 "loop intersection" );
01543 inter->which_loop = which_loop;
01544 inter->vert_index = lsg->end;
01545 inter->dist = dist[0];
01546 inter->next = NULL;
01547 if( !(*root) ) {
01548 (*root) = inter;
01549 } else {
01550 inter->next = (*root);
01551 (*root) = inter;
01552 }
01553 } else {
01554
01555 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01556 "loop intersection" );
01557 inter->which_loop = which_loop;
01558 inter->vert_index = -1;
01559 inter->dist = dist[0];
01560 inter->next = NULL;
01561 if( !(*root) ) {
01562 (*root) = inter;
01563 } else {
01564 inter->next = (*root);
01565 (*root) = inter;
01566 }
01567 }
01568 break;
01569 case CURVE_CARC_MAGIC:
01570 csg = (struct carc_seg *)lng;
01571 radius = csg->radius;
01572 if( csg->radius <= 0.0 ) {
01573 point2d_t ra, rb;
01574
01575 V2SUB2( diff, ip->verts[csg->start], ip->verts[csg->end] );
01576 radius = sqrt( MAG2SQ( diff ) );
01577 ra[X] = radius;
01578 ra[Y] = 0.0;
01579 rb[X] = 0.0;
01580 rb[Y] = radius;
01581 code = isect_line2_ellipse( dist, pta, dir, ip->verts[csg->end],
01582 ra, rb );
01583
01584 if( code <= 0 )
01585 break;
01586 for( j=0 ; j<code ; j++ ) {
01587 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01588 "loop intersection" );
01589 inter->which_loop = which_loop;
01590 inter->vert_index = -1;
01591 inter->dist = dist[j];
01592 inter->next = NULL;
01593 if( !(*root) ) {
01594 (*root) = inter;
01595 } else {
01596 inter->next = (*root);
01597 (*root) = inter;
01598 }
01599 }
01600
01601 } else {
01602 point2d_t ra, rb;
01603 vect_t s2m, tmp_dir;
01604 point2d_t start2d, end2d, mid_pt, center2d;
01605 fastf_t s2m_len_sq, len_sq, tmp_len, cross_z;
01606
01607 V2MOVE( start2d, ip->verts[csg->start] );
01608 V2MOVE( end2d, ip->verts[csg->end] );
01609 mid_pt[0] = (start2d[0] + end2d[0]) * 0.5;
01610 mid_pt[1] = (start2d[1] + end2d[1]) * 0.5;
01611 V2SUB2( s2m, mid_pt, start2d )
01612 tmp_dir[0] = -s2m[1];
01613 tmp_dir[1] = s2m[0];
01614 s2m_len_sq = s2m[0]*s2m[0] + s2m[1]*s2m[1];
01615 if( s2m_len_sq < SMALL_FASTF )
01616 {
01617 bu_log( "start and end points are too close together in circular arc of sketch\n" );
01618 break;
01619 }
01620 len_sq = radius*radius - s2m_len_sq;
01621 if( len_sq < 0.0 )
01622 {
01623 bu_log( "Impossible radius for specified start and end points in circular arc\n");
01624 break;
01625 }
01626 tmp_len = sqrt( tmp_dir[0]*tmp_dir[0] + tmp_dir[1]*tmp_dir[1] );
01627 tmp_dir[0] = tmp_dir[0] / tmp_len;
01628 tmp_dir[1] = tmp_dir[1] / tmp_len;
01629 tmp_len = sqrt( len_sq );
01630 V2JOIN1( center2d, mid_pt, tmp_len, tmp_dir )
01631
01632
01633 cross_z = ( end2d[X] - start2d[X] )*( center2d[Y] - start2d[Y] ) -
01634 ( end2d[Y] - start2d[Y] )*( center2d[X] - start2d[X] );
01635 if( !(cross_z > 0.0 && csg->center_is_left) )
01636 V2JOIN1( center2d, mid_pt, -tmp_len, tmp_dir );
01637
01638 ra[X] = radius;
01639 ra[Y] = 0.0;
01640 rb[X] = 0.0;
01641 rb[Y] = radius;
01642 code = isect_line_earc( dist, pta, dir, center2d, ra, rb,
01643 norm, ip->verts[csg->start], ip->verts[csg->end],
01644 csg->orientation );
01645 if( code <= 0 )
01646 break;
01647 for( j=0 ; j<code ; j++ ) {
01648 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01649 "loop intersection" );
01650 inter->which_loop = which_loop;
01651 inter->vert_index = -1;
01652 inter->dist = dist[j];
01653 inter->next = NULL;
01654 if( !(*root) ) {
01655 (*root) = inter;
01656 } else {
01657 inter->next = (*root);
01658 (*root) = inter;
01659 }
01660 }
01661 }
01662 break;
01663 case CURVE_BEZIER_MAGIC:
01664 bsg = (struct bezier_seg *)lng;
01665 intercept = NULL;
01666 normal = NULL;
01667 verts = (point2d_t *)bu_calloc( bsg->degree + 1, sizeof( point2d_t ), "Bezier verts" );
01668 for( j=0 ; j<=bsg->degree ; j++ ) {
01669 V2MOVE( verts[j], ip->verts[bsg->ctl_points[j]] );
01670 }
01671 code = FindRoots( verts, bsg->degree, &intercept, &normal, pta, dir, norm, 0, tol->dist );
01672 for( j=0 ; j<code ; j++ ) {
01673 V2SUB2( diff, intercept[j], pta );
01674 dist[0] = sqrt( MAG2SQ( diff ) );
01675 inter = (struct loop_inter *)bu_calloc( sizeof( struct loop_inter ), 1,
01676 "loop intersection" );
01677 inter->which_loop = which_loop;
01678 inter->vert_index = -1;
01679 inter->dist = dist[0];
01680 inter->next = NULL;
01681 if( !(*root) ) {
01682 (*root) = inter;
01683 } else {
01684 inter->next = (*root);
01685 (*root) = inter;
01686 }
01687 }
01688 if( (*intercept) )
01689 bu_free( (char *)intercept, "Bezier Intercepts" );
01690 if( (*normal) )
01691 bu_free( (char *)normal, "Bezier normals" );
01692 bu_free( ( char *)verts, "Bezier Ctl points" );
01693 break;
01694 default:
01695 bu_log( "isect_2D_loop_ray: Unrecognized curve segment type x%x\n", *lng );
01696 bu_bomb( "isect_2D_loop_ray: Unrecognized curve segment type\n" );
01697 break;
01698 }
01699 }
01700 }
01701
01702 static void
01703 sort_intersections( struct loop_inter **root, struct bn_tol *tol )
01704 {
01705 struct loop_inter *ptr, *prev, *pprev;
01706 int done=0;
01707 fastf_t diff;
01708
01709
01710 ptr = (*root);
01711 while( ptr->next ) {
01712 prev = ptr;
01713 ptr = ptr->next;
01714 if( ptr->vert_index > -1 && ptr->vert_index == prev->vert_index ) {
01715 prev->next = ptr->next;
01716 bu_free( (char *)ptr, "struct loop_inter" );
01717 ptr = prev;
01718 }
01719 }
01720
01721 ptr = (*root);
01722 while( ptr->next ) {
01723 prev = ptr;
01724 ptr = ptr->next;
01725 diff = fabs( ptr->dist - prev->dist );
01726 if( diff < tol->dist ) {
01727 prev->next = ptr->next;
01728 bu_free( (char *)ptr, "struct loop_inter" );
01729 ptr = prev;
01730 }
01731 }
01732
01733 while( !done ) {
01734 done = 1;
01735 ptr = (*root);
01736 prev = NULL;
01737 pprev = NULL;
01738 while( ptr->next ) {
01739 pprev = prev;
01740 prev = ptr;
01741 ptr = ptr->next;
01742 if( ptr->dist < prev->dist ) {
01743 done = 0;
01744 if( pprev ) {
01745 prev->next = ptr->next;
01746 pprev->next = ptr;
01747 ptr->next = prev;
01748 } else {
01749 prev->next = ptr->next;
01750 ptr->next = prev;
01751 (*root) = ptr;
01752 }
01753 }
01754 }
01755 }
01756 }
01757
01758 int
01759 classify_sketch_loops( struct bu_ptbl *loopa, struct bu_ptbl *loopb, struct rt_sketch_internal *ip )
01760 {
01761 struct loop_inter *inter_root=NULL, *ptr, *tmp;
01762 struct bn_tol tol;
01763 point2d_t pta, ptb;
01764 point2d_t dir;
01765 genptr_t seg;
01766 fastf_t inv_len;
01767 int loopa_count=0, loopb_count=0;
01768 int ret=UNKNOWN;
01769
01770 BU_CK_PTBL( loopa );
01771 BU_CK_PTBL( loopb );
01772 RT_SKETCH_CK_MAGIC( ip );
01773
01774 tol.magic = BN_TOL_MAGIC;
01775 tol.dist = 0.005;
01776 tol.dist_sq = tol.dist * tol.dist;
01777 tol.perp = 1.0e-5;;
01778 tol.para = 1.0 - tol.perp;
01779
01780
01781 seg = (genptr_t)BU_PTBL_GET( loopa, 0 );
01782 get_seg_midpoint( seg, ip, pta );
01783 seg = (genptr_t)BU_PTBL_GET( loopb, 0 );
01784 get_seg_midpoint( seg, ip, ptb );
01785
01786 V2SUB2( dir, ptb, pta );
01787 inv_len = 1.0 / sqrt( MAGSQ_2D( dir ) );
01788 V2SCALE( dir, dir, inv_len );
01789
01790
01791 isect_2D_loop_ray( pta, dir, loopa, &inter_root, LOOPA, ip, &tol );
01792 isect_2D_loop_ray( pta, dir, loopb, &inter_root, LOOPB, ip, &tol );
01793
01794 sort_intersections( &inter_root, &tol );
01795
01796
01797 ptr = inter_root;
01798 while( ptr ) {
01799 tmp = ptr;
01800 if( ret == UNKNOWN ) {
01801 if( ptr->which_loop == LOOPA ) {
01802 loopa_count++;
01803 if( loopa_count && loopb_count ) {
01804 if( loopb_count % 2 ) {
01805 ret = A_IN_B;
01806 } else {
01807 ret = DISJOINT;
01808 }
01809 }
01810 } else {
01811 loopb_count++;
01812 if( loopa_count && loopb_count ) {
01813 if( loopa_count % 2 ) {
01814 ret = B_IN_A;
01815 } else {
01816 ret = DISJOINT;
01817 }
01818 }
01819 }
01820 }
01821 ptr = ptr->next;
01822 bu_free( (char *)tmp, "loop intercept" );
01823 }
01824
01825 return( ret );
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835 int
01836 rt_extrude_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01837 {
01838 #if 0
01839 return( -1 );
01840 #else
01841 struct bu_list vhead;
01842 struct shell *s;
01843 struct faceuse *fu;
01844 struct vertex ***verts;
01845 struct vertex **vertsa;
01846 int vert_count=0;
01847 struct rt_extrude_internal *extrude_ip;
01848 struct rt_sketch_internal *sketch_ip;
01849 struct curve *crv=(struct curve *)NULL;
01850 struct bu_ptbl *aloop=NULL, loops, **containing_loops, *outer_loop;
01851 int i, j, k;
01852 int *used_seg;
01853 struct bn_vlist *vlp;
01854 plane_t pl;
01855
01856 RT_CK_DB_INTERNAL(ip);
01857 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
01858 RT_EXTRUDE_CK_MAGIC(extrude_ip);
01859
01860 if( !extrude_ip->skt )
01861 {
01862 bu_log( "rt_extrude_tess: ERROR: no sketch for extrusion!!!!\n" );
01863 return( -1 );
01864 }
01865
01866 sketch_ip = extrude_ip->skt;
01867 RT_SKETCH_CK_MAGIC( sketch_ip );
01868
01869 crv = &sketch_ip->skt_curve;
01870
01871 if( crv->seg_count < 1 )
01872 return( 0 );
01873
01874
01875 used_seg = (int *)bu_calloc( crv->seg_count, sizeof( int ), "used_seg" );
01876 bu_ptbl_init( &loops, 5, "loops" );
01877 for( i=0 ; i<crv->seg_count ; i++ ) {
01878 genptr_t cur_seg;
01879 int loop_start, loop_end;
01880 int seg_start, seg_end;
01881
01882 if( used_seg[i] )
01883 continue;
01884
01885 aloop = (struct bu_ptbl *)bu_calloc( 1, sizeof( struct bu_ptbl ), "aloop" );
01886 bu_ptbl_init( aloop, 5, "aloop" );
01887
01888 bu_ptbl_ins( aloop, (long *)crv->segments[i] );
01889 used_seg[i] = 1;
01890 cur_seg = crv->segments[i];
01891 get_indices( cur_seg, &loop_start, &loop_end );
01892
01893 while( loop_end != loop_start ) {
01894 int j;
01895 int added_seg;
01896
01897 added_seg = 0;
01898 for( j=0 ; j<crv->seg_count ; j++ ) {
01899 if( used_seg[j] )
01900 continue;
01901
01902 get_indices( crv->segments[j], &seg_start, &seg_end );
01903 if( seg_start != seg_end && seg_start == loop_end ) {
01904 added_seg++;
01905 bu_ptbl_ins( aloop, (long *)crv->segments[j] );
01906 used_seg[j] = 1;
01907 loop_end = seg_end;
01908 if( loop_start == loop_end )
01909 break;
01910 }
01911 }
01912 if( !added_seg ) {
01913 bu_log( "rt_extrude_tess: A loop is not closed in sketch %s\n",
01914 extrude_ip->sketch_name );
01915 bu_log( "\ttessellation failed!!\n" );
01916 for( j=0 ; j<BU_PTBL_END( &loops ) ; j++ ) {
01917 aloop = (struct bu_ptbl *)BU_PTBL_GET( &loops, j );
01918 bu_ptbl_free( aloop );
01919 bu_free( (char *)aloop, "aloop" );
01920 }
01921 bu_ptbl_free( &loops );
01922 bu_free( ( char *)used_seg, "used_seg" );
01923 return( -2 );
01924 }
01925 }
01926 bu_ptbl_ins( &loops, (long *)aloop );
01927 }
01928 bu_free( ( char *)used_seg, "used_seg" );
01929
01930
01931 containing_loops = (struct bu_ptbl **)bu_calloc( BU_PTBL_END( &loops ),
01932 sizeof( struct bu_ptbl *), "containing_loops" );
01933 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
01934 containing_loops[i] = (struct bu_ptbl *)bu_calloc( 1, sizeof( struct bu_ptbl ), "containing_loops[i]" );
01935 bu_ptbl_init( containing_loops[i], BU_PTBL_END( &loops ), "containing_loops[i]" );
01936 }
01937
01938 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
01939 struct bu_ptbl *loopa;
01940 int j;
01941
01942 loopa = (struct bu_ptbl *)BU_PTBL_GET( &loops, i );
01943 for( j=i+1 ; j<BU_PTBL_END( &loops ) ; j++ ) {
01944 struct bu_ptbl *loopb;
01945
01946 loopb = (struct bu_ptbl *)BU_PTBL_GET( &loops, j );
01947 switch( classify_sketch_loops( loopa, loopb, sketch_ip ) ) {
01948 case A_IN_B:
01949 bu_ptbl_ins( containing_loops[i], (long *)loopb );
01950 break;
01951 case B_IN_A:
01952 bu_ptbl_ins( containing_loops[j], (long *)loopa );
01953 break;
01954 case DISJOINT:
01955 break;
01956 default:
01957 bu_log( "rt_extrude_tess: Failed to classify loops!!\n" );
01958 goto failed;
01959 }
01960 }
01961 }
01962
01963
01964
01965
01966 outer_loop = (struct bu_ptbl *)NULL;
01967 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
01968 if( BU_PTBL_END( containing_loops[i] ) == 0 ) {
01969 outer_loop = (struct bu_ptbl *)BU_PTBL_GET( &loops, i );
01970 break;
01971 }
01972 }
01973
01974 if( !outer_loop ) {
01975 bu_log( "No outer loop in sketch %s\n", extrude_ip->sketch_name );
01976 bu_log( "\ttessellation failed\n" );
01977 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
01978 }
01979 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
01980 aloop = (struct bu_ptbl *)BU_PTBL_GET( &loops, i );
01981 bu_ptbl_free( aloop );
01982 bu_free( (char *)aloop, "aloop" );
01983 bu_ptbl_free( containing_loops[i] );
01984 bu_free( (char *)containing_loops[i], "aloop" );
01985 }
01986 bu_ptbl_free( &loops );
01987 bu_free( (char *)containing_loops, "containing_loops" );
01988 }
01989
01990 BU_LIST_INIT( &vhead );
01991 if( BU_LIST_UNINITIALIZED( &rt_g.rtg_vlfree ) ) {
01992 BU_LIST_INIT( &rt_g.rtg_vlfree );
01993 }
01994 for( i=0 ; i<BU_PTBL_END( outer_loop ) ; i++ ) {
01995 genptr_t seg;
01996
01997 seg = (genptr_t)BU_PTBL_GET( outer_loop, i );
01998 if( seg_to_vlist( &vhead, ttol, extrude_ip->V, extrude_ip->u_vec, extrude_ip->v_vec, sketch_ip, seg ) )
01999 goto failed;
02000 }
02001
02002
02003 vert_count = 0;
02004 for( BU_LIST_FOR( vlp, bn_vlist, &vhead ) ) {
02005 for( i=0 ; i<vlp->nused ; i++ ) {
02006 if( vlp->cmd[i] == BN_VLIST_LINE_DRAW )
02007 vert_count++;
02008 }
02009 }
02010
02011 *r = nmg_mrsv( m );
02012 s = BU_LIST_FIRST( shell, &((*r)->s_hd) );
02013
02014
02015 verts = (struct vertex ***)bu_calloc( vert_count, sizeof( struct vertex **), "verts" );
02016 for( i=0 ; i<vert_count ; i++ ) {
02017 verts[i] = (struct vertex **)bu_calloc( 1, sizeof( struct vertex *), "verts[i]" );
02018 }
02019
02020 fu = nmg_cmface( s, verts, vert_count );
02021 j = 0;
02022 for( BU_LIST_FOR( vlp, bn_vlist, &vhead ) ) {
02023 for( i=0 ; i<vlp->nused ; i++ ) {
02024 if( vlp->cmd[i] == BN_VLIST_LINE_DRAW ) {
02025 nmg_vertex_gv( *verts[j], vlp->pt[i] );
02026 j++;
02027 }
02028 }
02029 }
02030 BN_FREE_VLIST( &rt_g.rtg_vlfree, &vhead );
02031
02032
02033 bu_free( (char *)verts, "verts" );
02034 if( nmg_calc_face_plane( fu, pl ) ) {
02035 bu_log( "Failed to calculate face plane for extrusion\n" );
02036 return( -1 );
02037 }
02038 nmg_face_g( fu, pl );
02039 if( VDOT( pl, extrude_ip->h ) > 0.0 ) {
02040 nmg_reverse_face( fu );
02041 fu = fu->fumate_p;
02042 }
02043
02044
02045 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
02046 int fdir;
02047 vect_t cross;
02048 fastf_t pt_count=0.0;
02049 fastf_t dot;
02050 int rev=0;
02051
02052 aloop = (struct bu_ptbl *)BU_PTBL_GET( &loops, i );
02053 if( aloop == outer_loop )
02054 continue;
02055
02056 if( BU_PTBL_END( containing_loops[i] ) % 2 ) {
02057 fdir = OT_OPPOSITE;
02058 } else {
02059 fdir = OT_SAME;
02060 }
02061
02062 for( j=0 ; j<BU_PTBL_END( aloop ) ; j++ ) {
02063 genptr_t seg;
02064
02065 seg = (genptr_t)BU_PTBL_GET( aloop, j );
02066 if( seg_to_vlist( &vhead, ttol, extrude_ip->V,
02067 extrude_ip->u_vec, extrude_ip->v_vec, sketch_ip, seg ) )
02068 goto failed;
02069 }
02070
02071
02072 VSETALLN( pl, 0.0, 4 );
02073 for( BU_LIST_FOR( vlp, bn_vlist, &vhead ) ) {
02074 for( j=1 ; j<vlp->nused ; j++ ) {
02075 if( vlp->cmd[j] == BN_VLIST_LINE_DRAW ) {
02076 VCROSS( cross, vlp->pt[j-1], vlp->pt[j] );
02077 VADD2( pl, pl, cross );
02078 }
02079 }
02080 }
02081
02082 VUNITIZE( pl );
02083
02084 for( BU_LIST_FOR( vlp, bn_vlist, &vhead ) ) {
02085 for( j=1 ; j<vlp->nused ; j++ ) {
02086 if( vlp->cmd[j] == BN_VLIST_LINE_DRAW ) {
02087 pl[3] += VDOT( pl, vlp->pt[j] );
02088 pt_count++;
02089 }
02090 }
02091 }
02092 pl[3] /= pt_count;
02093
02094 dot = -VDOT( pl, extrude_ip->h );
02095 rev = 0;
02096 if( fdir == OT_SAME && dot < 0.0 )
02097 rev = 1;
02098 else if( fdir == OT_OPPOSITE && dot > 0.0 )
02099 rev = 1;
02100
02101 vertsa = (struct vertex **)bu_calloc((int)pt_count, sizeof( struct vertex *), "verts" );
02102
02103 fu = nmg_add_loop_to_face( s, fu, vertsa, (int)pt_count, fdir );
02104
02105 k = 0;
02106 for( BU_LIST_FOR( vlp, bn_vlist, &vhead ) ) {
02107 for( j=1 ; j<vlp->nused ; j++ ) {
02108 if( vlp->cmd[j] == BN_VLIST_LINE_DRAW ) {
02109 if( rev ) {
02110 nmg_vertex_gv( vertsa[(int)(pt_count) - k - 1], vlp->pt[j] );
02111 } else {
02112 nmg_vertex_gv( vertsa[k], vlp->pt[j] );
02113 }
02114 k++;
02115 }
02116 }
02117 }
02118 RT_FREE_VLIST( &vhead );
02119 }
02120
02121
02122 if( nmg_extrude_face( fu, extrude_ip->h, tol ) ) {
02123 bu_log( "Failed to extrude face sketch\n" );
02124 return( -1 );
02125 }
02126
02127 nmg_region_a( *r, tol );
02128
02129 return( 0 );
02130
02131 failed:
02132 for( i=0 ; i<BU_PTBL_END( &loops ) ; i++ ) {
02133 bu_ptbl_free( containing_loops[i] );
02134 bu_free( (char *)containing_loops[i], "containing_loops[i]" );
02135 }
02136 bu_free( (char *)containing_loops, "containing_loops" );
02137 bu_ptbl_free( aloop );
02138 bu_free( (char *)aloop, "aloop" );
02139 return( -1 );
02140 #endif
02141 }
02142
02143
02144
02145
02146
02147
02148
02149 int
02150 rt_extrude_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip, struct resource *resp)
02151 {
02152 LOCAL struct rt_extrude_internal *extrude_ip;
02153 struct rt_db_internal tmp_ip;
02154 struct directory *dp;
02155 char *sketch_name;
02156 union record *rp;
02157 char *ptr;
02158 point_t tmp_vec;
02159
02160 BU_CK_EXTERNAL( ep );
02161 rp = (union record *)ep->ext_buf;
02162
02163 if( rp->u_id != DBID_EXTR ) {
02164 bu_log("rt_extrude_import: defective record\n");
02165 return(-1);
02166 }
02167
02168 RT_CK_DB_INTERNAL( ip );
02169 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
02170 ip->idb_type = ID_EXTRUDE;
02171 ip->idb_meth = &rt_functab[ID_EXTRUDE];
02172 ip->idb_ptr = bu_malloc( sizeof(struct rt_extrude_internal), "rt_extrude_internal");
02173 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
02174 extrude_ip->magic = RT_EXTRUDE_INTERNAL_MAGIC;
02175
02176 sketch_name = (char *)rp + sizeof( struct extr_rec );
02177 if( !dbip )
02178 extrude_ip->skt = (struct rt_sketch_internal *)NULL;
02179 else if( (dp=db_lookup( dbip, sketch_name, LOOKUP_NOISY)) == DIR_NULL )
02180 {
02181 bu_log( "rt_extrude_import: ERROR: Cannot find sketch (%.16s) for extrusion (%.16s)\n",
02182 sketch_name, rp->extr.ex_name );
02183 extrude_ip->skt = (struct rt_sketch_internal *)NULL;
02184 }
02185 else
02186 {
02187 if( rt_db_get_internal( &tmp_ip, dp, dbip, bn_mat_identity, resp ) != ID_SKETCH )
02188 {
02189 bu_log( "rt_extrude_import: ERROR: Cannot import sketch (%.16s) for extrusion (%.16s)\n",
02190 sketch_name, rp->extr.ex_name );
02191 bu_free( ip->idb_ptr, "extrusion" );
02192 return( -1 );
02193 }
02194 else
02195 extrude_ip->skt = (struct rt_sketch_internal *)tmp_ip.idb_ptr;
02196 }
02197
02198 ntohd( (unsigned char *)tmp_vec, rp->extr.ex_V, ELEMENTS_PER_VECT );
02199 MAT4X3PNT( extrude_ip->V, mat, tmp_vec );
02200 ntohd( (unsigned char *)tmp_vec, rp->extr.ex_h, ELEMENTS_PER_VECT );
02201 MAT4X3VEC( extrude_ip->h, mat, tmp_vec );
02202 ntohd( (unsigned char *)tmp_vec, rp->extr.ex_uvec, ELEMENTS_PER_VECT );
02203 MAT4X3VEC( extrude_ip->u_vec, mat, tmp_vec );
02204 ntohd( (unsigned char *)tmp_vec, rp->extr.ex_vvec, ELEMENTS_PER_VECT );
02205 MAT4X3VEC( extrude_ip->v_vec, mat, tmp_vec );
02206 extrude_ip->keypoint = bu_glong( rp->extr.ex_key );
02207
02208 ptr = (char *)rp;
02209 ptr += sizeof( struct extr_rec );
02210 extrude_ip->sketch_name = (char *)bu_calloc( 17, sizeof( char ), "Extrude sketch name" );
02211 strncpy( extrude_ip->sketch_name, ptr, 16 );
02212
02213 return(0);
02214 }
02215
02216
02217
02218
02219
02220
02221 int
02222 rt_extrude_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
02223 {
02224 struct rt_extrude_internal *extrude_ip;
02225 vect_t tmp_vec;
02226 union record *rec;
02227 unsigned char *ptr;
02228
02229 RT_CK_DB_INTERNAL(ip);
02230 if( ip->idb_type != ID_EXTRUDE ) return(-1);
02231 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
02232 RT_EXTRUDE_CK_MAGIC(extrude_ip);
02233
02234 BU_CK_EXTERNAL(ep);
02235 ep->ext_nbytes = 2*sizeof( union record );
02236 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "extrusion external");
02237 rec = (union record *)ep->ext_buf;
02238
02239 rec->extr.ex_id = DBID_EXTR;
02240
02241 VSCALE( tmp_vec, extrude_ip->V, local2mm );
02242 htond( rec->extr.ex_V, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT );
02243 VSCALE( tmp_vec, extrude_ip->h, local2mm );
02244 htond( rec->extr.ex_h, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT );
02245 VSCALE( tmp_vec, extrude_ip->u_vec, local2mm );
02246 htond( rec->extr.ex_uvec, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT );
02247 VSCALE( tmp_vec, extrude_ip->v_vec, local2mm );
02248 htond( rec->extr.ex_vvec, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT );
02249 bu_plong( rec->extr.ex_key, extrude_ip->keypoint );
02250 bu_plong( rec->extr.ex_count, 1 );
02251
02252 ptr = (unsigned char *)rec;
02253 ptr += sizeof( struct extr_rec );
02254
02255 strcpy( (char *)ptr, extrude_ip->sketch_name );
02256
02257 return(0);
02258 }
02259
02260
02261
02262
02263
02264
02265
02266 int
02267 rt_extrude_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
02268 {
02269 struct rt_extrude_internal *extrude_ip;
02270 vect_t tmp_vec[4];
02271 unsigned char *ptr;
02272
02273 RT_CK_DB_INTERNAL(ip);
02274 if( ip->idb_type != ID_EXTRUDE ) return(-1);
02275
02276 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
02277 RT_EXTRUDE_CK_MAGIC(extrude_ip);
02278
02279 BU_CK_EXTERNAL(ep);
02280 ep->ext_nbytes = 4 * ELEMENTS_PER_VECT * SIZEOF_NETWORK_DOUBLE + SIZEOF_NETWORK_LONG + strlen( extrude_ip->sketch_name ) + 1;
02281 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "extrusion external");
02282 ptr = (unsigned char *)ep->ext_buf;
02283
02284 VSCALE( tmp_vec[0], extrude_ip->V, local2mm );
02285 VSCALE( tmp_vec[1], extrude_ip->h, local2mm );
02286 VSCALE( tmp_vec[2], extrude_ip->u_vec, local2mm );
02287 VSCALE( tmp_vec[3], extrude_ip->v_vec, local2mm );
02288 htond( ptr, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT*4 );
02289 ptr += ELEMENTS_PER_VECT * 4 * SIZEOF_NETWORK_DOUBLE;
02290 bu_plong( ptr, extrude_ip->keypoint );
02291 ptr += SIZEOF_NETWORK_LONG;
02292 strcpy( (char *)ptr, extrude_ip->sketch_name );
02293
02294 return(0);
02295 }
02296
02297
02298
02299
02300
02301
02302
02303
02304 int
02305 rt_extrude_import5(
02306 struct rt_db_internal *ip,
02307 const struct bu_external *ep,
02308 register const mat_t mat,
02309 const struct db_i *dbip,
02310 struct resource *resp,
02311 const int minor_type )
02312 {
02313 LOCAL struct rt_extrude_internal *extrude_ip;
02314 struct rt_db_internal tmp_ip;
02315 struct directory *dp;
02316 char *sketch_name;
02317 unsigned char *ptr;
02318 point_t tmp_vec[4];
02319
02320 BU_CK_EXTERNAL( ep );
02321
02322 RT_CK_DB_INTERNAL( ip );
02323 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
02324 ip->idb_type = ID_EXTRUDE;
02325 ip->idb_meth = &rt_functab[ID_EXTRUDE];
02326 ip->idb_ptr = bu_malloc( sizeof(struct rt_extrude_internal), "rt_extrude_internal");
02327 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
02328 extrude_ip->magic = RT_EXTRUDE_INTERNAL_MAGIC;
02329
02330 ptr = (unsigned char *)ep->ext_buf;
02331 sketch_name = (char *)ptr + ELEMENTS_PER_VECT*4*SIZEOF_NETWORK_DOUBLE + SIZEOF_NETWORK_LONG;
02332 if( !dbip )
02333 extrude_ip->skt = (struct rt_sketch_internal *)NULL;
02334 else if( (dp=db_lookup( dbip, sketch_name, LOOKUP_NOISY)) == DIR_NULL )
02335 {
02336 bu_log( "rt_extrude_import: ERROR: Cannot find sketch (%s) for extrusion\n",
02337 sketch_name );
02338 extrude_ip->skt = (struct rt_sketch_internal *)NULL;
02339 }
02340 else
02341 {
02342 if( rt_db_get_internal( &tmp_ip, dp, dbip, bn_mat_identity, resp ) != ID_SKETCH )
02343 {
02344 bu_log( "rt_extrude_import: ERROR: Cannot import sketch (%s) for extrusion\n",
02345 sketch_name );
02346 bu_free( ip->idb_ptr, "extrusion" );
02347 return( -1 );
02348 }
02349 else
02350 extrude_ip->skt = (struct rt_sketch_internal *)tmp_ip.idb_ptr;
02351 }
02352
02353 ntohd( (unsigned char *)tmp_vec, ptr, ELEMENTS_PER_VECT*4 );
02354 MAT4X3PNT( extrude_ip->V, mat, tmp_vec[0] );
02355 MAT4X3VEC( extrude_ip->h, mat, tmp_vec[1] );
02356 MAT4X3VEC( extrude_ip->u_vec, mat, tmp_vec[2] );
02357 MAT4X3VEC( extrude_ip->v_vec, mat, tmp_vec[3] );
02358 ptr += ELEMENTS_PER_VECT * 4 * SIZEOF_NETWORK_DOUBLE;
02359 extrude_ip->keypoint = bu_glong( ptr );
02360 ptr += SIZEOF_NETWORK_LONG;
02361 extrude_ip->sketch_name = bu_strdup( (const char *)ptr );
02362
02363 return(0);
02364 }
02365
02366
02367
02368
02369
02370
02371
02372
02373 int
02374 rt_extrude_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
02375 {
02376 register struct rt_extrude_internal *extrude_ip =
02377 (struct rt_extrude_internal *)ip->idb_ptr;
02378 char buf[256];
02379 point_t V;
02380 vect_t h, u, v;
02381
02382 RT_EXTRUDE_CK_MAGIC(extrude_ip);
02383 bu_vls_strcat( str, "2D extrude (EXTRUDE)\n");
02384 VSCALE( V, extrude_ip->V, mm2local );
02385 VSCALE( h, extrude_ip->h, mm2local );
02386 VSCALE( u, extrude_ip->u_vec, mm2local );
02387 VSCALE( v, extrude_ip->v_vec, mm2local );
02388 sprintf( buf, "\tV = (%g %g %g)\n\tH = (%g %g %g)\n\tu_dir = (%g %g %g)\n\tv_dir = (%g %g %g)\n",
02389 V3INTCLAMPARGS( V ),
02390 V3INTCLAMPARGS( h ),
02391 V3INTCLAMPARGS( u ),
02392 V3INTCLAMPARGS( v ) );
02393 bu_vls_strcat( str, buf );
02394 sprintf( buf, "\tsketch name: %s\n",
02395 extrude_ip->sketch_name );
02396 bu_vls_strcat( str, buf );
02397
02398
02399 return(0);
02400 }
02401
02402
02403
02404
02405
02406
02407 void
02408 rt_extrude_ifree(struct rt_db_internal *ip)
02409 {
02410 register struct rt_extrude_internal *extrude_ip;
02411 struct rt_db_internal tmp_ip;
02412
02413 RT_CK_DB_INTERNAL(ip);
02414 extrude_ip = (struct rt_extrude_internal *)ip->idb_ptr;
02415 RT_EXTRUDE_CK_MAGIC(extrude_ip);
02416 if( extrude_ip->skt )
02417 {
02418 RT_INIT_DB_INTERNAL( &tmp_ip );
02419 tmp_ip.idb_major_type = DB5_MAJORTYPE_BRLCAD;
02420 tmp_ip.idb_type = ID_SKETCH;
02421 tmp_ip.idb_ptr = (genptr_t)extrude_ip->skt;
02422 tmp_ip.idb_meth = &rt_functab[ID_SKETCH];
02423 rt_sketch_ifree( &tmp_ip );
02424 }
02425 extrude_ip->magic = 0;
02426
02427 bu_free( extrude_ip->sketch_name, "Extrude sketch_name" );
02428 bu_free( (char *)extrude_ip, "extrude ifree" );
02429 ip->idb_ptr = GENPTR_NULL;
02430 }
02431
02432 int
02433 rt_extrude_xform(
02434 struct rt_db_internal *op,
02435 const mat_t mat,
02436 struct rt_db_internal *ip,
02437 int free,
02438 struct db_i *dbip,
02439 struct resource *resp)
02440 {
02441 struct rt_extrude_internal *eip, *eop;
02442 point_t tmp_vec;
02443
02444 RT_CK_DB_INTERNAL( ip );
02445 RT_CK_RESOURCE(resp)
02446 eip = (struct rt_extrude_internal *)ip->idb_ptr;
02447 RT_EXTRUDE_CK_MAGIC( eip );
02448
02449 if( bu_debug&BU_DEBUG_MEM_CHECK )
02450 {
02451 bu_log( "Barrier check at start of extrude_xform():\n" );
02452 bu_mem_barriercheck();
02453 }
02454
02455 if( op != ip )
02456 {
02457 RT_INIT_DB_INTERNAL( op );
02458 eop = (struct rt_extrude_internal *)bu_malloc( sizeof( struct rt_extrude_internal ), "eop" );
02459 eop->magic = RT_EXTRUDE_INTERNAL_MAGIC;
02460 eop->sketch_name = bu_strdup( eip->sketch_name );
02461 op->idb_ptr = (genptr_t)eop;
02462 op->idb_meth = &rt_functab[ID_EXTRUDE];
02463 op->idb_major_type = DB5_MAJORTYPE_BRLCAD;
02464 op->idb_type = ID_EXTRUDE;
02465 if( ip->idb_avs.magic == BU_AVS_MAGIC ) {
02466 bu_avs_init( &op->idb_avs, ip->idb_avs.count, "avs" );
02467 bu_avs_merge( &op->idb_avs, &ip->idb_avs );
02468 }
02469 }
02470 else
02471 eop = (struct rt_extrude_internal *)ip->idb_ptr;
02472
02473 MAT4X3PNT( tmp_vec, mat, eip->V );
02474 VMOVE( eop->V, tmp_vec );
02475 MAT4X3VEC( tmp_vec, mat, eip->h );
02476 VMOVE( eop->h, tmp_vec );
02477 MAT4X3VEC( tmp_vec, mat, eip->u_vec );
02478 VMOVE( eop->u_vec, tmp_vec );
02479 MAT4X3VEC( tmp_vec, mat, eip->v_vec );
02480 VMOVE( eop->v_vec, tmp_vec );
02481 eop->keypoint = eip->keypoint;
02482
02483 if( free && ip != op )
02484 {
02485 eop->skt = eip->skt;
02486 eip->skt = (struct rt_sketch_internal *)NULL;
02487 rt_db_free_internal( ip, resp );
02488 }
02489 else if( eip->skt )
02490 eop->skt = rt_copy_sketch( eip->skt );
02491 else
02492 eop->skt = (struct rt_sketch_internal *)NULL;
02493
02494 if( bu_debug&BU_DEBUG_MEM_CHECK )
02495 {
02496 bu_log( "Barrier check at end of extrude_xform():\n" );
02497 bu_mem_barriercheck();
02498 }
02499
02500 return( 0 );
02501 }
02502
02503 int
02504 rt_extrude_tclform( const struct rt_functab *ftp, Tcl_Interp *interp )
02505 {
02506 RT_CK_FUNCTAB(ftp);
02507
02508 Tcl_AppendResult( interp,
02509 "V {%f %f %f} H {%f %f %f} A {%f %f %f} B {%f %f %f} S %s K %d", (char *)NULL );
02510
02511 return TCL_OK;
02512
02513 }
02514
02515 int
02516 rt_extrude_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
02517 {
02518 register struct rt_extrude_internal *extr=(struct rt_extrude_internal *) intern->idb_ptr;
02519 Tcl_DString ds;
02520 struct bu_vls vls;
02521 int ret=TCL_OK;
02522
02523 RT_EXTRUDE_CK_MAGIC( extr );
02524
02525 Tcl_DStringInit( &ds );
02526 bu_vls_init( &vls );
02527
02528
02529 if( attr == (char *)NULL )
02530 {
02531 bu_vls_strcpy( &vls, "extrude" );
02532 bu_vls_printf( &vls, " V {%.25g %.25g %.25g}", V3ARGS( extr->V ) );
02533 bu_vls_printf( &vls, " H {%.25g %.25g %.25g}", V3ARGS( extr->h ) );
02534 bu_vls_printf( &vls, " A {%.25g %.25g %.25g}", V3ARGS( extr->u_vec ) );
02535 bu_vls_printf( &vls, " B {%.25g %.25g %.25g}", V3ARGS( extr->v_vec ) );
02536 bu_vls_printf( &vls, " S %s", extr->sketch_name );
02537 bu_vls_printf( &vls, " K %d", extr->keypoint );
02538 }
02539 else if( *attr == 'V' )
02540 bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( extr->V ) );
02541 else if( *attr == 'H' )
02542 bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( extr->h ) );
02543 else if( *attr == 'A' )
02544 bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( extr->u_vec ) );
02545 else if( *attr == 'B' )
02546 bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( extr->v_vec ) );
02547 else if( *attr == 'S' )
02548 bu_vls_printf( &vls, "%s", extr->sketch_name );
02549 else if( *attr == 'K' )
02550 bu_vls_printf( &vls, "%d", extr->keypoint );
02551 else
02552 {
02553 bu_vls_strcat( &vls, "ERROR: unrecognized attribute, must be V, H, A, B, S, or K!!!" );
02554 ret = TCL_ERROR;
02555 }
02556
02557 Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
02558 Tcl_DStringResult( interp, &ds );
02559 Tcl_DStringFree( &ds );
02560 bu_vls_free( &vls );
02561 return( ret );
02562 }
02563
02564 int
02565 rt_extrude_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
02566 {
02567 struct rt_extrude_internal *extr;
02568 fastf_t *new;
02569 fastf_t len;
02570
02571 RT_CK_DB_INTERNAL( intern );
02572 extr = (struct rt_extrude_internal *)intern->idb_ptr;
02573 RT_EXTRUDE_CK_MAGIC( extr );
02574
02575 while( argc >= 2 )
02576 {
02577 int array_len=3;
02578
02579 if( *argv[0] == 'V' )
02580 {
02581 new = extr->V;
02582 if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len ) !=
02583 array_len ) {
02584 Tcl_SetResult( interp,
02585 "ERROR: incorrect number of coordinates for vertex\n",
02586 TCL_STATIC );
02587 return( TCL_ERROR );
02588 }
02589 }
02590 else if( *argv[0] == 'H' )
02591 {
02592 new = extr->h;
02593 if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len ) !=
02594 array_len ) {
02595 Tcl_SetResult( interp,
02596 "ERROR: incorrect number of coordinates for vector\n",
02597 TCL_STATIC );
02598 return( TCL_ERROR );
02599 }
02600 }
02601 else if( *argv[0] == 'A' )
02602 {
02603 new = extr->u_vec;
02604 if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len ) !=
02605 array_len ) {
02606 Tcl_SetResult( interp,
02607 "ERROR: incorrect number of coordinates for vector\n",
02608 TCL_STATIC );
02609 return( TCL_ERROR );
02610 }
02611
02612
02613 len = MAGNITUDE( extr->u_vec );
02614 VUNITIZE( extr->v_vec );
02615 VSCALE( extr->v_vec, extr->v_vec, len );
02616 }
02617 else if( *argv[0] == 'B' )
02618 {
02619 new = extr->v_vec;
02620 if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len ) !=
02621 array_len ) {
02622 Tcl_SetResult( interp,
02623 "ERROR: incorrect number of coordinates for vector\n",
02624 TCL_STATIC );
02625 return( TCL_ERROR );
02626 }
02627
02628 len = MAGNITUDE( extr->v_vec );
02629 VUNITIZE( extr->u_vec );
02630 VSCALE( extr->u_vec, extr->u_vec, len );
02631 }
02632 else if( *argv[0] =='K' )
02633 extr->keypoint = atoi( argv[1] );
02634 else if( *argv[0] == 'S' ) {
02635 if( extr->sketch_name )
02636 bu_free( (char *)extr->sketch_name, "rt_extrude_tcladjust: sketch_name" );
02637 extr->sketch_name = bu_strdup( argv[1] );
02638 }
02639
02640 argc -= 2;
02641 argv += 2;
02642 }
02643
02644 return( TCL_OK );
02645 }
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661