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 RCSars[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_ars.c,v 14.12 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 #ifdef HAVE_STRING_H
00047 # include <string.h>
00048 #endif
00049 #include <math.h>
00050 #include <ctype.h>
00051
00052 #include "machine.h"
00053 #include "tcl.h"
00054 #include "vmath.h"
00055 #include "db.h"
00056 #include "nmg.h"
00057 #include "raytrace.h"
00058 #include "rtgeom.h"
00059 #include "./debug.h"
00060 #include "./plane.h"
00061 #include "./bot.h"
00062
00063
00064 #define TRI_NULL ((struct tri_specific *)0)
00065
00066
00067
00068 extern int rt_bot_minpieces;
00069
00070
00071 extern int rt_bot_prep( struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip );
00072 extern void rt_bot_ifree( struct rt_db_internal *ip );
00073
00074 int rt_ars_tess( struct nmgregion **r, struct model *m, struct rt_db_internal *ip,
00075 const struct rt_tess_tol *ttol, const struct bn_tol *tol );
00076
00077 void
00078 rt_ars_free( register struct soltab *stp )
00079 {
00080 bu_bomb("rt_ars_free s/b rt_bot_free\n");
00081 }
00082 int
00083 rt_ars_class(const struct soltab *stp,
00084 const vect_t min,
00085 const vect_t max,
00086 const struct bn_tol *tol)
00087 {
00088 bu_bomb("rt_ars_class s/b rt_bot_class\n");
00089 return 0;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099 fastf_t *
00100 rt_ars_rd_curve(union record *rp, int npts)
00101 {
00102 LOCAL int lim;
00103 LOCAL fastf_t *base;
00104 register fastf_t *fp;
00105 register int i;
00106 LOCAL union record *rr;
00107 int rec;
00108
00109
00110 base = fp = (fastf_t *)bu_malloc(
00111 (npts+1) * sizeof(fastf_t) * ELEMENTS_PER_VECT,
00112 "ars curve" );
00113
00114 rec = 0;
00115 for( ; npts > 0; npts -= 8 ) {
00116 rr = &rp[rec++];
00117 if( rr->b.b_id != ID_ARS_B ) {
00118 bu_log("rt_ars_rd_curve(): non-ARS_B record!\n");
00119 break;
00120 }
00121 lim = (npts>8) ? 8 : npts;
00122 for( i=0; i<lim; i++ ) {
00123
00124 VMOVE( fp, (&(rr->b.b_values[i*3])) );
00125 fp += ELEMENTS_PER_VECT;
00126 }
00127 }
00128 return( base );
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 int
00144 rt_ars_import(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
00145 {
00146 struct rt_ars_internal *ari;
00147 union record *rp;
00148 register int i, j;
00149 LOCAL vect_t base_vect;
00150 int currec;
00151
00152 BU_CK_EXTERNAL( ep );
00153 rp = (union record *)ep->ext_buf;
00154 if( rp->u_id != ID_ARS_A ) {
00155 bu_log("rt_ars_import: defective record\n");
00156 return(-1);
00157 }
00158
00159 RT_CK_DB_INTERNAL( ip );
00160 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00161 ip->idb_type = ID_ARS;
00162 ip->idb_meth = &rt_functab[ID_ARS];
00163 ip->idb_ptr = bu_malloc(sizeof(struct rt_ars_internal), "rt_ars_internal");
00164 ari = (struct rt_ars_internal *)ip->idb_ptr;
00165 ari->magic = RT_ARS_INTERNAL_MAGIC;
00166 ari->ncurves = rp[0].a.a_m;
00167 ari->pts_per_curve = rp[0].a.a_n;
00168
00169
00170
00171
00172 ari->curves = (fastf_t **)bu_malloc(
00173 (ari->ncurves+1) * sizeof(fastf_t **), "ars curve ptrs" );
00174 currec = 1;
00175 for( i=0; i < ari->ncurves; i++ ) {
00176 ari->curves[i] =
00177 rt_ars_rd_curve( &rp[currec], ari->pts_per_curve );
00178 currec += (ari->pts_per_curve+7)/8;
00179 }
00180
00181
00182
00183
00184
00185
00186 for( i = 0; i < ari->ncurves; i++ ) {
00187 register fastf_t *v;
00188
00189 v = ari->curves[i];
00190 for( j = 0; j < ari->pts_per_curve; j++ ) {
00191 LOCAL vect_t homog;
00192
00193 if( i==0 && j == 0 ) {
00194
00195 VMOVE( homog, v );
00196 MAT4X3PNT( base_vect, mat, homog );
00197 VMOVE( v, base_vect );
00198 } else {
00199 MAT4X3VEC( homog, mat, v );
00200 VADD2( v, base_vect, homog );
00201 }
00202 v += ELEMENTS_PER_VECT;
00203 }
00204 VMOVE( v, ari->curves[i] );
00205 }
00206 return( 0 );
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 int
00216 rt_ars_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00217 {
00218 struct rt_ars_internal *arip;
00219 union record *rec;
00220 point_t base_pt;
00221 int per_curve_grans;
00222 int cur;
00223 int gno;
00224
00225 RT_CK_DB_INTERNAL(ip);
00226 if( ip->idb_type != ID_ARS ) return(-1);
00227 arip = (struct rt_ars_internal *)ip->idb_ptr;
00228 RT_ARS_CK_MAGIC(arip);
00229
00230 per_curve_grans = (arip->pts_per_curve+7)/8;
00231
00232 BU_CK_EXTERNAL(ep);
00233 ep->ext_nbytes = (1 + per_curve_grans * arip->ncurves) *
00234 sizeof(union record);
00235 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "ars external");
00236 rec = (union record *)ep->ext_buf;
00237
00238 rec[0].a.a_id = ID_ARS_A;
00239 rec[0].a.a_type = ARS;
00240 rec[0].a.a_m = arip->ncurves;
00241 rec[0].a.a_n = arip->pts_per_curve;
00242 rec[0].a.a_curlen = per_curve_grans;
00243 rec[0].a.a_totlen = per_curve_grans * arip->ncurves;
00244
00245 VMOVE( base_pt, &arip->curves[0][0] );
00246 gno = 1;
00247 for( cur=0; cur<arip->ncurves; cur++ ) {
00248 register fastf_t *fp;
00249 int npts;
00250 int left;
00251
00252 fp = arip->curves[cur];
00253 left = arip->pts_per_curve;
00254 for( npts=0; npts < arip->pts_per_curve; npts+=8, left -= 8 ) {
00255 register int el;
00256 register int lim;
00257 register struct ars_ext *bp = &rec[gno].b;
00258
00259 bp->b_id = ID_ARS_B;
00260 bp->b_type = ARSCONT;
00261 bp->b_n = cur+1;
00262 bp->b_ngranule = (npts/8)+1;
00263
00264 lim = (left > 8 ) ? 8 : left;
00265 for( el=0; el < lim; el++ ) {
00266 vect_t diff;
00267 if( cur==0 && npts==0 && el==0 )
00268 VSCALE( diff , fp , local2mm )
00269 else
00270 VSUB2SCALE( diff, fp, base_pt, local2mm )
00271
00272 VMOVE( &(bp->b_values[el*3]), diff );
00273 fp += ELEMENTS_PER_VECT;
00274 }
00275 gno++;
00276 }
00277 }
00278 return(0);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 int
00292 rt_ars_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
00293 {
00294 struct rt_ars_internal *ari;
00295 register int i, j;
00296 register unsigned char *cp;
00297 vect_t tmp_vec;
00298 register fastf_t *fp;
00299
00300 BU_CK_EXTERNAL( ep );
00301 RT_CK_DB_INTERNAL( ip );
00302
00303 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00304 ip->idb_type = ID_ARS;
00305 ip->idb_meth = &rt_functab[ID_ARS];
00306 ip->idb_ptr = bu_malloc(sizeof(struct rt_ars_internal), "rt_ars_internal");
00307
00308 ari = (struct rt_ars_internal *)ip->idb_ptr;
00309 ari->magic = RT_ARS_INTERNAL_MAGIC;
00310
00311 cp = (unsigned char *)ep->ext_buf;
00312 ari->ncurves = bu_glong( cp );
00313 cp += SIZEOF_NETWORK_LONG;
00314 ari->pts_per_curve = bu_glong( cp );
00315 cp += SIZEOF_NETWORK_LONG;
00316
00317
00318
00319
00320 ari->curves = (fastf_t **)bu_calloc(
00321 (ari->ncurves+1), sizeof(fastf_t *), "ars curve ptrs" );
00322 for( i=0; i < ari->ncurves; i++ ) {
00323 ari->curves[i] = (fastf_t *)bu_calloc( (ari->pts_per_curve + 1) * 3,
00324 sizeof( fastf_t ), "ARS points" );
00325 fp = ari->curves[i];
00326 for( j=0 ; j<ari->pts_per_curve ; j++ ) {
00327 ntohd( (unsigned char *)tmp_vec, cp, 3 );
00328 MAT4X3PNT( fp, mat, tmp_vec );
00329 cp += 3 * SIZEOF_NETWORK_DOUBLE;
00330 fp += ELEMENTS_PER_VECT;
00331 }
00332 VMOVE( fp, ari->curves[i] );
00333 }
00334 return( 0 );
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 int
00344 rt_ars_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00345 {
00346 struct rt_ars_internal *arip;
00347 unsigned char *cp;
00348 vect_t tmp_vec;
00349 int cur;
00350
00351 RT_CK_DB_INTERNAL(ip);
00352 if( ip->idb_type != ID_ARS ) return(-1);
00353 arip = (struct rt_ars_internal *)ip->idb_ptr;
00354 RT_ARS_CK_MAGIC(arip);
00355
00356 BU_CK_EXTERNAL(ep);
00357 ep->ext_nbytes = 2 * SIZEOF_NETWORK_LONG +
00358 3 * arip->ncurves * arip->pts_per_curve * SIZEOF_NETWORK_DOUBLE;
00359 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "ars external");
00360 cp = (unsigned char *)ep->ext_buf;
00361
00362 (void)bu_plong( cp, arip->ncurves );
00363 cp += SIZEOF_NETWORK_LONG;
00364 (void)bu_plong( cp, arip->pts_per_curve );
00365 cp += SIZEOF_NETWORK_LONG;
00366
00367 for( cur=0; cur<arip->ncurves; cur++ ) {
00368 register fastf_t *fp;
00369 int npts;
00370
00371 fp = arip->curves[cur];
00372 for( npts=0; npts < arip->pts_per_curve; npts++ ) {
00373 VSCALE( tmp_vec, fp, local2mm );
00374 ntohd( cp, (unsigned char *)tmp_vec, 3 );
00375 cp += 3 * SIZEOF_NETWORK_DOUBLE;
00376 fp += ELEMENTS_PER_VECT;
00377 }
00378 }
00379 return(0);
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 int
00390 rt_ars_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
00391 {
00392 register int j;
00393 register struct rt_ars_internal *arip =
00394 (struct rt_ars_internal *)ip->idb_ptr;
00395 char buf[256];
00396 int i;
00397
00398 RT_ARS_CK_MAGIC(arip);
00399 bu_vls_strcat( str, "arbitrary rectangular solid (ARS)\n");
00400
00401 sprintf(buf, "\t%d curves, %d points per curve\n",
00402 arip->ncurves, arip->pts_per_curve );
00403 bu_vls_strcat( str, buf );
00404
00405 if( arip->ncurves > 0 ) {
00406 sprintf(buf, "\tV (%g, %g, %g)\n",
00407 INTCLAMP(arip->curves[0][X] * mm2local),
00408 INTCLAMP(arip->curves[0][Y] * mm2local),
00409 INTCLAMP(arip->curves[0][Z] * mm2local) );
00410 bu_vls_strcat( str, buf );
00411 }
00412
00413 if( !verbose ) return(0);
00414
00415
00416 for( i=0; i < arip->ncurves; i++ ) {
00417 register fastf_t *v = arip->curves[i];
00418
00419 sprintf( buf, "\tCurve %d:\n", i );
00420 bu_vls_strcat( str, buf );
00421 for( j=0; j < arip->pts_per_curve; j++ ) {
00422 sprintf(buf, "\t\t(%g, %g, %g)\n",
00423 INTCLAMP(v[X] * mm2local),
00424 INTCLAMP(v[Y] * mm2local),
00425 INTCLAMP(v[Z] * mm2local) );
00426 bu_vls_strcat( str, buf );
00427 v += ELEMENTS_PER_VECT;
00428 }
00429 }
00430
00431 return(0);
00432 }
00433
00434
00435
00436
00437
00438
00439 void
00440 rt_ars_ifree(struct rt_db_internal *ip)
00441 {
00442 register struct rt_ars_internal *arip;
00443 register int i;
00444
00445 RT_CK_DB_INTERNAL(ip);
00446 arip = (struct rt_ars_internal *)ip->idb_ptr;
00447 RT_ARS_CK_MAGIC(arip);
00448
00449
00450
00451
00452 for( i = 0; i < arip->ncurves; i++ ) {
00453 bu_free( (char *)arip->curves[i], "ars curve" );
00454 }
00455 bu_free( (char *)arip->curves, "ars curve ptrs" );
00456 arip->magic = 0;
00457 arip->ncurves = 0;
00458 bu_free( (char *)arip, "ars ifree" );
00459 ip->idb_ptr = GENPTR_NULL;
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 int
00476 rt_ars_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00477 {
00478 #if 1
00479 struct rt_db_internal intern;
00480 struct rt_bot_internal *bot;
00481 struct model *m;
00482 struct nmgregion *r;
00483 struct shell *s;
00484 int ret;
00485
00486 m = nmg_mm();
00487 r = BU_LIST_FIRST( nmgregion, &m->r_hd );
00488
00489 if( rt_ars_tess( &r, m, ip, &rtip->rti_ttol, &rtip->rti_tol) ) {
00490 bu_log( "Failed to tessellate ARS (%s)\n", stp->st_dp->d_namep );
00491 nmg_km( m );
00492 return( -1 );
00493 }
00494 rt_ars_ifree( ip );
00495
00496 s = BU_LIST_FIRST( shell, &r->s_hd );
00497 bot = nmg_bot( s, &rtip->rti_tol );
00498
00499 if( !bot ) {
00500 bu_log( "Failed to convert ARS to BOT (%s)\n", stp->st_dp->d_namep );
00501 nmg_km( m );
00502 return( -1 );
00503 }
00504
00505 nmg_km( m );
00506
00507 intern.idb_magic = RT_DB_INTERNAL_MAGIC;
00508 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00509 intern.idb_minor_type = ID_BOT;
00510 intern.idb_meth = &rt_functab[ID_BOT];
00511 intern.idb_ptr = (genptr_t)bot;
00512 bu_avs_init( &intern.idb_avs, 0, "ARS to a BOT for prep" );
00513
00514 ret = rt_bot_prep( stp, &intern, rtip );
00515
00516 rt_bot_ifree( &intern );
00517
00518 return( ret );
00519 #else
00520 LOCAL fastf_t dx, dy, dz;
00521 int i, j, ntri;
00522 LOCAL fastf_t f;
00523 struct rt_ars_internal *arip;
00524 struct bot_specific *bot;
00525 const struct bn_tol *tol = &rtip->rti_tol;
00526 int ncv;
00527
00528 arip = (struct rt_ars_internal *)ip->idb_ptr;
00529 RT_ARS_CK_MAGIC(arip);
00530
00531
00532 BU_GETSTRUCT( bot, bot_specific );
00533 stp->st_specific = (genptr_t)bot;
00534 bot->bot_mode = RT_BOT_SOLID;
00535 bot->bot_orientation = RT_BOT_UNORIENTED;
00536 bot->bot_errmode = (unsigned char)NULL;
00537 bot->bot_thickness = (fastf_t *)NULL;
00538 bot->bot_facemode = (struct bu_bitv *)NULL;
00539 bot->bot_facelist = (struct tri_specific *)NULL;
00540
00541
00542
00543
00544
00545 VSETALL( stp->st_max, -INFINITY );
00546 VSETALL( stp->st_min, INFINITY );
00547
00548 for( i = 0; i < arip->ncurves; i++ ) {
00549 register fastf_t *v;
00550
00551 v = arip->curves[i];
00552 for( j = 0; j < arip->pts_per_curve; j++ ) {
00553 VMINMAX( stp->st_min, stp->st_max, v );
00554 v += ELEMENTS_PER_VECT;
00555 }
00556 }
00557 VSET( stp->st_center,
00558 (stp->st_max[X] + stp->st_min[X])/2,
00559 (stp->st_max[Y] + stp->st_min[Y])/2,
00560 (stp->st_max[Z] + stp->st_min[Z])/2 );
00561
00562 dx = (stp->st_max[X] - stp->st_min[X])/2;
00563 f = dx;
00564 dy = (stp->st_max[Y] - stp->st_min[Y])/2;
00565 if( dy > f ) f = dy;
00566 dz = (stp->st_max[Z] - stp->st_min[Z])/2;
00567 if( dz > f ) f = dz;
00568 stp->st_aradius = f;
00569 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00570
00571
00572
00573
00574
00575
00576 ncv = arip->ncurves-2;
00577 ntri = 0;
00578 for(i=0; i <= ncv; i++ ) {
00579 register fastf_t *v1, *v2;
00580
00581 v1 = arip->curves[i];
00582 v2 = arip->curves[i+1];
00583 for( j = 0; j < arip->pts_per_curve;
00584 j++, v1 += ELEMENTS_PER_VECT, v2 += ELEMENTS_PER_VECT ) {
00585
00586
00587
00588
00589
00590
00591 if (i != 0 &&
00592 rt_botface(stp, bot, &v1[0], &v2[ELEMENTS_PER_VECT],
00593 &v1[ELEMENTS_PER_VECT], ntri, tol) > 0) ntri++;
00594
00595
00596 if (i < ncv &&
00597 rt_botface(stp, bot, &v2[0], &v2[ELEMENTS_PER_VECT],
00598 &v1[0], ntri, tol) > 0) ntri++;
00599 }
00600 }
00601
00602
00603 if( bot->bot_facelist == (struct tri_specific *)0 ) {
00604 bu_log("ars(%s): no faces\n", stp->st_name);
00605 return(-1);
00606 }
00607
00608 bot->bot_ntri = ntri;
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 if( rt_bot_minpieces <= 0 ) return 0;
00624 if( ntri < rt_bot_minpieces ) return 0;
00625
00626
00627 rt_bot_prep_pieces(bot, stp, ntri, tol);
00628
00629 rt_ars_ifree( ip );
00630
00631
00632 return(0);
00633 #endif
00634 }
00635
00636
00637
00638
00639
00640 void
00641 rt_ars_print(register const struct soltab *stp)
00642 {
00643 register struct tri_specific *trip =
00644 (struct tri_specific *)stp->st_specific;
00645
00646 if( trip == TRI_NULL ) {
00647 bu_log("ars(%s): no faces\n", stp->st_name);
00648 return;
00649 }
00650 do {
00651 VPRINT( "A", trip->tri_A );
00652 VPRINT( "B-A", trip->tri_BA );
00653 VPRINT( "C-A", trip->tri_CA );
00654 VPRINT( "BA x CA", trip->tri_wn );
00655 VPRINT( "Normal", trip->tri_N );
00656 bu_log("\n");
00657 } while( (trip = trip->tri_forw) );
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 int
00671 rt_ars_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00672 {
00673 register struct tri_specific *trip =
00674 (struct tri_specific *)stp->st_specific;
00675 #define RT_ARS_MAXHITS 128
00676 LOCAL struct hit hits[RT_ARS_MAXHITS];
00677 register struct hit *hp;
00678 LOCAL int nhits;
00679
00680 nhits = 0;
00681 hp = &hits[0];
00682
00683
00684 for( ; trip; trip = trip->tri_forw ) {
00685 FAST fastf_t dn;
00686 LOCAL fastf_t abs_dn;
00687 FAST fastf_t k;
00688 LOCAL fastf_t alpha, beta;
00689 LOCAL fastf_t ds;
00690 LOCAL vect_t wxb;
00691 LOCAL vect_t xp;
00692
00693
00694
00695
00696 dn = VDOT( trip->tri_wn, rp->r_dir );
00697 if( RT_G_DEBUG & DEBUG_ARB8 )
00698 bu_log("N.Dir=%g ", dn );
00699
00700
00701
00702
00703 abs_dn = dn >= 0.0 ? dn : (-dn);
00704 if( abs_dn < 1.0e-10 )
00705 continue;
00706 VSUB2( wxb, trip->tri_A, rp->r_pt );
00707 VCROSS( xp, wxb, rp->r_dir );
00708
00709
00710 alpha = VDOT( trip->tri_CA, xp );
00711 if( dn < 0.0 ) alpha = -alpha;
00712 if( alpha < 0.0 || alpha > abs_dn )
00713 continue;
00714
00715
00716 beta = VDOT( trip->tri_BA, xp );
00717 if( dn > 0.0 ) beta = -beta;
00718 if( beta < 0.0 || beta > abs_dn )
00719 continue;
00720 if( alpha+beta > abs_dn )
00721 continue;
00722 ds = VDOT( wxb, trip->tri_wn );
00723 k = ds / dn;
00724
00725
00726
00727
00728
00729
00730
00731 hp->hit_magic = RT_HIT_MAGIC;
00732 hp->hit_dist = k;
00733 hp->hit_private = (char *)trip;
00734 hp->hit_vpriv[X] = dn;
00735 hp->hit_rayp = rp;
00736
00737 if(RT_G_DEBUG&DEBUG_ARB8) bu_log("ars: dist k=%g, ds=%g, dn=%g\n", k, ds, dn );
00738
00739
00740
00741
00742 if( ++nhits >= RT_ARS_MAXHITS ) {
00743 bu_log("ars(%s): too many hits\n", stp->st_name);
00744 break;
00745 }
00746 hp++;
00747 }
00748 if( nhits == 0 )
00749 return(0);
00750
00751
00752 rt_hitsort( hits, nhits );
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 {
00765 register int i, j;
00766
00767 if( nhits )
00768 RT_HIT_NORM( &hits[0], stp, 0 )
00769
00770 for( i=0 ; i<nhits-1 ; i++ )
00771 {
00772 fastf_t dist;
00773
00774 RT_HIT_NORM( &hits[i+1], stp, 0 )
00775 dist = hits[i].hit_dist - hits[i+1].hit_dist;
00776 if( NEAR_ZERO( dist, ap->a_rt_i->rti_tol.dist ) &&
00777 VDOT( hits[i].hit_normal, rp->r_dir ) *
00778 VDOT( hits[i+1].hit_normal, rp->r_dir) > 0)
00779 {
00780 for( j=i ; j<nhits-1 ; j++ )
00781 hits[j] = hits[j+1];
00782 nhits--;
00783 i--;
00784 }
00785 }
00786 }
00787
00788 if( nhits&1 ) {
00789 register int i;
00790
00791
00792
00793
00794 bu_log("ERROR: ars(%s): %d hits odd, skipping solid\n",
00795 stp->st_name, nhits);
00796 for(i=0; i < nhits; i++ )
00797 bu_log("k=%g dn=%g\n",
00798 hits[i].hit_dist, hp->hit_vpriv[X]);
00799 return(0);
00800 }
00801
00802
00803 {
00804 register struct seg *segp;
00805 register int i,j;
00806
00807
00808 for( i=nhits; i > 0; i -= 2 ) {
00809 if( hits[i-2].hit_vpriv[X] >= 0 )
00810 continue;
00811 if( hits[i-1].hit_vpriv[X] <= 0 )
00812 continue;
00813
00814 #ifndef CONSERVATIVE
00815
00816 if( (hits[i-1].hit_dist - hits[i-2].hit_dist) < 200.0*RT_LEN_TOL )
00817 {
00818 struct hit temp;
00819 fastf_t temp_dist;
00820
00821 temp_dist = hits[i-1].hit_dist;
00822 hits[i-1].hit_dist = hits[i-2].hit_dist;
00823 hits[i-2].hit_dist = temp_dist;
00824
00825 temp = hits[i-1];
00826 hits[i-1] = hits[i-2];
00827 hits[i-2] = temp;
00828 continue;
00829 }
00830 #endif
00831 bu_log("ars(%s): in/out error\n", stp->st_name );
00832 for( j=nhits-1; j >= 0; j-- ) {
00833 bu_log("%d %s dist=%g dn=%g\n",
00834 j,
00835 ((hits[j].hit_vpriv[X] > 0) ?
00836 " In" : "Out" ),
00837 hits[j].hit_dist,
00838 hits[j].hit_vpriv[X] );
00839 if( j>0 )
00840 bu_log( "\tseg length = %g\n", hits[j].hit_dist - hits[j-1].hit_dist );
00841 }
00842 #ifdef CONSERVATIVE
00843 return(0);
00844 #else
00845
00846 break;
00847 #endif
00848 }
00849
00850 for( i=nhits; i > 0; i -= 2 ) {
00851 RT_GET_SEG(segp, ap->a_resource);
00852 segp->seg_stp = stp;
00853 segp->seg_in = hits[i-2];
00854 segp->seg_out = hits[i-1];
00855 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00856 }
00857 }
00858 return(nhits);
00859 }
00860
00861
00862
00863
00864
00865
00866 void
00867 rt_hitsort(register struct hit *h, register int nh)
00868 {
00869 register int i, j;
00870 LOCAL struct hit temp;
00871
00872 for( i=0; i < nh-1; i++ ) {
00873 for( j=i+1; j < nh; j++ ) {
00874 if( h[i].hit_dist <= h[j].hit_dist )
00875 continue;
00876 temp = h[j];
00877 h[j] = h[i];
00878 h[i] = temp;
00879 }
00880 }
00881 }
00882
00883
00884
00885
00886
00887
00888 void
00889 rt_ars_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00890 {
00891 register struct tri_specific *trip =
00892 (struct tri_specific *)hitp->hit_private;
00893
00894 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00895 VMOVE( hitp->hit_normal, trip->tri_N );
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905 void
00906 rt_ars_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00907 {
00908
00909
00910
00911 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00912 cvp->crv_c1 = cvp->crv_c2 = 0;
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 void
00924 rt_ars_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00925 {
00926 register struct tri_specific *trip =
00927 (struct tri_specific *)hitp->hit_private;
00928 LOCAL vect_t P_A;
00929 LOCAL fastf_t r;
00930 LOCAL fastf_t xxlen, yylen;
00931
00932 xxlen = MAGNITUDE(trip->tri_BA);
00933 yylen = MAGNITUDE(trip->tri_CA);
00934
00935 VSUB2( P_A, hitp->hit_point, trip->tri_A );
00936
00937 uvp->uv_u = VDOT( P_A, trip->tri_BA ) * xxlen;
00938 uvp->uv_v = 1.0 - ( VDOT( P_A, trip->tri_CA ) * yylen );
00939 if( uvp->uv_u < 0 || uvp->uv_v < 0 ) {
00940 if( RT_G_DEBUG )
00941 bu_log("rt_ars_uv: bad uv=%g,%g\n", uvp->uv_u, uvp->uv_v);
00942
00943 if( uvp->uv_u < 0 ) uvp->uv_u = (-uvp->uv_u);
00944 if( uvp->uv_v < 0 ) uvp->uv_v = (-uvp->uv_v);
00945 }
00946 r = ap->a_rbeam + ap->a_diverge * hitp->hit_dist;
00947 uvp->uv_du = r * xxlen;
00948 uvp->uv_dv = r * yylen;
00949 }
00950
00951
00952
00953
00954
00955 int
00956 rt_ars_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00957 {
00958 register int i;
00959 register int j;
00960 struct rt_ars_internal *arip;
00961
00962 RT_CK_DB_INTERNAL(ip);
00963 arip = (struct rt_ars_internal *)ip->idb_ptr;
00964 RT_ARS_CK_MAGIC(arip);
00965
00966
00967
00968
00969
00970 for( i = 0; i < arip->ncurves; i++ ) {
00971 register fastf_t *v1;
00972
00973 v1 = arip->curves[i];
00974 RT_ADD_VLIST( vhead, v1, BN_VLIST_LINE_MOVE );
00975 v1 += ELEMENTS_PER_VECT;
00976 for( j = 1; j <= arip->pts_per_curve; j++, v1 += ELEMENTS_PER_VECT )
00977 RT_ADD_VLIST( vhead, v1, BN_VLIST_LINE_DRAW );
00978 }
00979
00980
00981
00982
00983 for( i = 0; i < arip->pts_per_curve; i++ ) {
00984 RT_ADD_VLIST( vhead, &arip->curves[0][i*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE );
00985 for( j = 1; j < arip->ncurves; j++ )
00986 RT_ADD_VLIST( vhead, &arip->curves[j][i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW );
00987 }
00988
00989 return(0);
00990 }
00991
00992 #define IJ(ii,jj) (((i+(ii))*(arip->pts_per_curve+1))+(j+(jj)))
00993 #define ARS_PT(ii,jj) (&arip->curves[i+(ii)][(j+(jj))*ELEMENTS_PER_VECT])
00994 #define FIND_IJ(a,b) \
00995 if( !(verts[IJ(a,b)]) ) { \
00996 verts[IJ(a,b)] = \
00997 nmg_find_pt_in_shell( s, ARS_PT(a,b), tol ); \
00998 }
00999 #define ASSOC_GEOM(corn, a,b) \
01000 if( !((*corners[corn])->vg_p) ) { \
01001 nmg_vertex_gv( *(corners[corn]), ARS_PT(a,b) ); \
01002 }
01003
01004
01005
01006 int
01007 rt_ars_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
01008 {
01009 register int i;
01010 register int j;
01011 register int k;
01012 struct rt_ars_internal *arip;
01013 struct shell *s;
01014 struct vertex **verts;
01015 struct faceuse *fu;
01016 struct bu_ptbl kill_fus;
01017 int bad_ars=0;
01018
01019 RT_CK_DB_INTERNAL(ip);
01020 arip = (struct rt_ars_internal *)ip->idb_ptr;
01021 RT_ARS_CK_MAGIC(arip);
01022
01023
01024 for( i = 0; i < arip->ncurves-1; i++ )
01025 {
01026 for( j = 2; j < arip->pts_per_curve; j++ )
01027 {
01028 fastf_t dist;
01029 vect_t pca;
01030 int code;
01031
01032 if( VAPPROXEQUAL( ARS_PT(0,-2), ARS_PT(0,-1), tol->dist ) )
01033 continue;
01034
01035 code = bn_dist_pt3_lseg3( &dist, pca, ARS_PT(0,-2), ARS_PT(0,-1), ARS_PT(0,0), tol );
01036
01037 if( code < 2 )
01038 {
01039 bu_log( "ARS curve backtracks on itself!!!\n" );
01040 bu_log( "\tCurve #%d, points #%d through %d are:\n", i, j-2, j );
01041 bu_log( "\t\t%d (%f %f %f)\n", j-2, V3ARGS( ARS_PT(0,-2) ) );
01042 bu_log( "\t\t%d (%f %f %f)\n", j-1, V3ARGS( ARS_PT(0,-1) ) );
01043 bu_log( "\t\t%d (%f %f %f)\n", j, V3ARGS( ARS_PT(0,0) ) );
01044 bad_ars = 1;
01045 j++;
01046 }
01047 }
01048 }
01049
01050 if( bad_ars )
01051 {
01052 bu_log( "TESSELATION FAILURE: This ARS solid has not been tesselated.\n\tAny result you may obtain is incorrect.\n" );
01053 return( -1 );
01054 }
01055
01056 bu_ptbl_init( &kill_fus, 64, " &kill_fus");
01057
01058
01059
01060 *r = nmg_mrsv( m );
01061 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
01062
01063 verts = (struct vertex **)bu_calloc( arip->ncurves * (arip->pts_per_curve+1),
01064 sizeof(struct vertex *),
01065 "rt_tor_tess *verts[]" );
01066
01067
01068
01069
01070
01071 k = arip->pts_per_curve-2;
01072 for( i = 0; i < arip->ncurves-1; i++ ) {
01073 int double_ended;
01074
01075 if( k != 1 && VAPPROXEQUAL( &arip->curves[i][1*ELEMENTS_PER_VECT], &arip->curves[i][k*ELEMENTS_PER_VECT], tol->dist ) )
01076 double_ended = 1;
01077 else
01078 double_ended = 0;
01079
01080 for( j = 0; j < arip->pts_per_curve; j++ ) {
01081 struct vertex **corners[3];
01082
01083
01084 if( double_ended &&
01085 i != 0 &&
01086 ( j == 0 || j == k || j == arip->pts_per_curve-1 ) )
01087 continue;
01088
01089
01090
01091
01092 if( bn_3pts_distinct( ARS_PT(0,0), ARS_PT(1,1),
01093 ARS_PT(0,1), tol )
01094 && !bn_3pts_collinear( ARS_PT(0,0), ARS_PT(1,1),
01095 ARS_PT(0,1), tol )
01096 ) {
01097
01098 FIND_IJ(0, 0);
01099 FIND_IJ(1, 1);
01100 FIND_IJ(0, 1);
01101
01102
01103 corners[0] = &verts[IJ(0,0)];
01104 corners[1] = &verts[IJ(0,1)];
01105 corners[2] = &verts[IJ(1,1)];
01106
01107 if( (fu = nmg_cmface( s, corners, 3 )) == (struct faceuse *)0 ) {
01108 bu_log("rt_ars_tess() nmg_cmface failed, skipping face a[%d][%d]\n",
01109 i,j);
01110 }
01111
01112
01113 ASSOC_GEOM( 0, 0, 0 );
01114 ASSOC_GEOM( 1, 0, 1 );
01115 ASSOC_GEOM( 2, 1, 1 );
01116 if( nmg_calc_face_g( fu ) )
01117 {
01118 bu_log( "Degenerate face created, will kill it later\n" );
01119 bu_ptbl_ins( &kill_fus, (long *)fu );
01120 }
01121 }
01122
01123
01124
01125
01126 if( bn_3pts_distinct( ARS_PT(1,0), ARS_PT(1,1),
01127 ARS_PT(0,0), tol )
01128 && !bn_3pts_collinear( ARS_PT(1,0), ARS_PT(1,1),
01129 ARS_PT(0,0), tol )
01130 ) {
01131
01132 FIND_IJ(1, 0);
01133 FIND_IJ(1, 1);
01134 FIND_IJ(0, 0);
01135
01136
01137 corners[0] = &verts[IJ(1,0)];
01138 corners[1] = &verts[IJ(0,0)];
01139 corners[2] = &verts[IJ(1,1)];
01140
01141 if( (fu = nmg_cmface( s, corners, 3 )) == (struct faceuse *)0 ) {
01142 bu_log("rt_ars_tess() nmg_cmface failed, skipping face b[%d][%d]\n",
01143 i,j);
01144 }
01145
01146
01147 ASSOC_GEOM( 0, 1, 0 );
01148 ASSOC_GEOM( 1, 0, 0 );
01149 ASSOC_GEOM( 2, 1, 1 );
01150 if( nmg_calc_face_g( fu ) )
01151 {
01152 bu_log( "Degenerate face created, will kill it later\n" );
01153 bu_ptbl_ins( &kill_fus, (long *)fu );
01154 }
01155 }
01156 }
01157 }
01158
01159 bu_free( (char *)verts, "rt_ars_tess *verts[]" );
01160
01161
01162 for( i=0 ; i<BU_PTBL_END( &kill_fus ) ; i++ )
01163 {
01164 fu = (struct faceuse *)BU_PTBL_GET( &kill_fus, i );
01165 NMG_CK_FACEUSE( fu );
01166 (void)nmg_kfu( fu );
01167 }
01168
01169
01170
01171
01172 nmg_fix_normals( s , tol );
01173
01174
01175 nmg_mark_edges_real( &s->l.magic );
01176
01177
01178 nmg_region_a( *r, tol );
01179
01180 return(0);
01181 }
01182
01183 int
01184 rt_ars_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
01185 {
01186 register struct rt_ars_internal *ars=(struct rt_ars_internal *)intern->idb_ptr;
01187 Tcl_DString ds;
01188 struct bu_vls vls;
01189 int i,j;
01190
01191 RT_ARS_CK_MAGIC( ars );
01192
01193 Tcl_DStringInit( &ds );
01194 bu_vls_init( &vls );
01195
01196 if( attr == (char *)NULL ) {
01197 bu_vls_strcpy( &vls, "ars" );
01198 bu_vls_printf( &vls, " NC %d PPC %d", ars->ncurves, ars->pts_per_curve );
01199 for( i=0 ; i<ars->ncurves ; i++ ) {
01200 bu_vls_printf( &vls, " C%d {", i );
01201 for( j=0 ; j<ars->pts_per_curve ; j++ ) {
01202 bu_vls_printf( &vls, " { %.25g %.25g %.25g }",
01203 V3ARGS( &ars->curves[i][j*3] ) );
01204 }
01205 bu_vls_printf( &vls, " }" );
01206 }
01207 }
01208 else if( !strcmp( attr, "NC" ) ) {
01209 bu_vls_printf( &vls, "%d", ars->ncurves );
01210 }
01211 else if( !strcmp( attr, "PPC" ) ) {
01212 bu_vls_printf( &vls, "%d", ars->pts_per_curve );
01213 }
01214 else if( attr[0] == 'C' ) {
01215 char *ptr;
01216
01217 if( attr[1] == '\0' ) {
01218
01219 for( i=0 ; i<ars->ncurves ; i++ ) {
01220 bu_vls_printf( &vls, " C%d {", i );
01221 for( j=0 ; j<ars->pts_per_curve ; j++ ) {
01222 bu_vls_printf( &vls, " { %.25g %.25g %.25g }",
01223 V3ARGS( &ars->curves[i][j*3] ) );
01224 }
01225 bu_vls_printf( &vls, " }" );
01226 }
01227 }
01228 else if( !isdigit( attr[1] ) ) {
01229 Tcl_SetResult( interp,
01230 "ERROR: illegal argument, must be NC, PPC, C, C#, or C#P#\n",
01231 TCL_STATIC );
01232 return( TCL_ERROR );
01233 }
01234
01235 if( (ptr=strchr( attr, 'P' )) ) {
01236
01237 if( !isdigit( *(ptr+1) ) ) {
01238 Tcl_SetResult( interp,
01239 "ERROR: illegal argument, must be NC, PPC, C, C#, or C#P#\n",
01240 TCL_STATIC );
01241 return( TCL_ERROR );
01242 }
01243 j = atoi( (ptr+1) );
01244 *ptr = '\0';
01245 i = atoi( &attr[1] );
01246 bu_vls_printf( &vls, "%.25g %.25g %.25g",
01247 V3ARGS( &ars->curves[i][j*3] ) );
01248 }
01249 else {
01250
01251 i = atoi( &attr[1] );
01252 for( j=0 ; j<ars->pts_per_curve ; j++ ) {
01253 bu_vls_printf( &vls, " { %.25g %.25g %.25g }",
01254 V3ARGS( &ars->curves[i][j*3] ) );
01255 }
01256 }
01257 }
01258 Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
01259 Tcl_DStringResult( interp, &ds );
01260 Tcl_DStringFree( &ds );
01261 bu_vls_free( &vls );
01262 return( TCL_OK );
01263 }
01264
01265 int
01266 rt_ars_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
01267 {
01268 struct rt_ars_internal *ars;
01269 int i,j,k;
01270 int len;
01271 fastf_t *array;
01272
01273 RT_CK_DB_INTERNAL( intern );
01274
01275 ars = (struct rt_ars_internal *)intern->idb_ptr;
01276 RT_ARS_CK_MAGIC( ars );
01277
01278 while( argc >= 2 ) {
01279 if( !strcmp( argv[0], "NC" ) ) {
01280
01281 i = atoi( argv[1] );
01282 if( i < ars->ncurves ) {
01283 for( j=i ; j<ars->ncurves ; j++ )
01284 bu_free( (char *)ars->curves[j], "ars->curves[j]" );
01285 ars->curves = (fastf_t **)bu_realloc( ars->curves,
01286 i*sizeof( fastf_t *), "ars->curves" );
01287 ars->ncurves = i;
01288 }
01289 else if( i > ars->ncurves ) {
01290 ars->curves = (fastf_t **)bu_realloc( ars->curves,
01291 i*sizeof( fastf_t *), "ars->curves" );
01292 if( ars->pts_per_curve ) {
01293
01294 for( j=ars->ncurves ; j<i ; j++ ) {
01295 ars->curves[j] = (fastf_t *)bu_malloc(
01296 ars->pts_per_curve * 3 * sizeof( fastf_t ),
01297 "ars->curves[j]" );
01298 for( k=0 ; k<ars->pts_per_curve ; k++ ) {
01299 if ( j ) {
01300 VMOVE( &ars->curves[j][k*3],
01301 &ars->curves[j-1][k*3] );
01302 }
01303 else {
01304 VSETALL(&ars->curves[j][k*3], 0.0);
01305 }
01306 }
01307 }
01308 }
01309 else {
01310 for( j=ars->ncurves ; j<i ; j++ ) {
01311 ars->curves[j] = NULL;
01312 }
01313 }
01314 ars->ncurves = i;
01315 }
01316 }
01317 else if( !strcmp( argv[0], "PPC" ) ) {
01318
01319 i = atoi( argv[1] );
01320 if( i < 3 ) {
01321 Tcl_SetResult( interp,
01322 "ERROR: must have at least 3 points per curve\n",
01323 TCL_STATIC );
01324 return( TCL_ERROR );
01325 }
01326 if( i < ars->pts_per_curve ) {
01327 for( j=0 ; j<ars->ncurves ; j++ ) {
01328 ars->curves[j] = bu_realloc( ars->curves[j],
01329 i * 3 * sizeof( fastf_t ),
01330 "ars->curves[j]" );
01331 }
01332 ars->pts_per_curve = i;
01333 }
01334 else if( i > ars->pts_per_curve ) {
01335 for( j=0 ; j<ars->ncurves ; j++ ) {
01336 ars->curves[j] = bu_realloc( ars->curves[j],
01337 i * 3 * sizeof( fastf_t ),
01338 "ars->curves[j]" );
01339
01340 for( k=ars->pts_per_curve ; k<i ; k++ ) {
01341 if( k ) {
01342 VMOVE( &ars->curves[j][k*3],
01343 &ars->curves[j][(k-1)*3] );
01344 }
01345 else {
01346 VSETALL( &ars->curves[j][k*3], 0 );
01347 }
01348 }
01349 }
01350 ars->pts_per_curve = i;
01351 }
01352 }
01353 else if( argv[0][0] == 'C' ) {
01354 if( isdigit( argv[0][1] ) ) {
01355 char *ptr;
01356
01357
01358 if( (ptr=strchr( argv[0], 'P' )) ) {
01359
01360 i = atoi( &argv[0][1] );
01361 j = atoi( ptr+1 );
01362 len = 3;
01363 array = &ars->curves[i][j*3];
01364 if( tcl_list_to_fastf_array( interp, argv[1],
01365 &array,
01366 &len )!= len ) {
01367 Tcl_SetResult( interp,
01368 "WARNING: incorrect number of parameters provided for a point\n",
01369 TCL_STATIC );
01370 }
01371 }
01372 else {
01373
01374 i = atoi( &argv[0][1] );
01375 len = ars->pts_per_curve * 3;
01376 ptr = argv[1];
01377 while( *ptr ) {
01378 if( *ptr == '{' || *ptr == '}' )
01379 *ptr = ' ';
01380 ptr++;
01381 }
01382 if( !ars->curves[i] ) {
01383 ars->curves[i] = (fastf_t *)bu_calloc(
01384 ars->pts_per_curve * 3,
01385 sizeof( fastf_t ),
01386 "ars->curves[i]" );
01387 }
01388 if( tcl_list_to_fastf_array( interp, argv[1],
01389 &ars->curves[i],
01390 &len ) != len ) {
01391 Tcl_SetResult( interp,
01392 "WARNING: incorrect number of parameters provided for a curve\n",
01393 TCL_STATIC );
01394 }
01395 }
01396 }
01397 else {
01398 Tcl_SetResult( interp,
01399 "ERROR: Illegal argument, must be NC, PPC, C#, or C#P#\n",
01400 TCL_STATIC );
01401 return( TCL_ERROR );
01402 }
01403 }
01404 else {
01405 Tcl_SetResult( interp,
01406 "ERROR: Illegal argument, must be NC, PPC, C#, or C#P#\n",
01407 TCL_STATIC );
01408 return( TCL_ERROR );
01409 }
01410 argc -= 2;
01411 argv += 2;
01412 }
01413
01414 return( TCL_OK );
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426