00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef lint
00047 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/track.c,v 14.12 2006/09/16 02:04:26 lbutler Exp $ (ARL)";
00048 #endif
00049
00050 #include "common.h"
00051
00052 #include <stdlib.h>
00053 #include <stdio.h>
00054 #include <math.h>
00055 #ifdef HAVE_STRING_H
00056 # include <string.h>
00057 #else
00058 # include <strings.h>
00059 #endif
00060
00061 #include "machine.h"
00062 #include "bu.h"
00063 #include "vmath.h"
00064 #include "bn.h"
00065 #include "raytrace.h"
00066 #include "rtgeom.h"
00067 #include "wdb.h"
00068
00069
00070 #define WDB_TCL_CHECK_READ_ONLY \
00071 if (wdbp->dbip->dbi_read_only) {\
00072 Tcl_AppendResult(interp, "Sorry, this database is READ-ONLY\n", (char *)NULL); \
00073 return TCL_ERROR; \
00074 }
00075 #define WDB_TCL_ERROR_RECOVERY_SUGGESTION\
00076 Tcl_AppendResult(interp, "\
00077 The in-memory table of contents may not match the status of the on-disk\n\
00078 database. The on-disk database should still be intact. For safety,\n\
00079 you should exit now, and resolve the I/O problem, before continuing.\n", (char *)NULL)
00080
00081 extern void aexists();
00082
00083 static int Trackpos = 0;
00084 static int mat_default = 1;
00085 static int los_default = 50;
00086 static int item_default = 500;
00087 static fastf_t plano[4], plant[4];
00088 static int grpname_len;
00089 static int extraTypeChars = 3;
00090 static int extraChars = 4;
00091
00092 static struct track_solid {
00093 int s_type;
00094 char *s_name;
00095 fastf_t s_values[24];
00096 } sol;
00097
00098 static int wrobj();
00099 static void crname(), slope(), crdummy(), trcurve();
00100 static void bottom(), top(), crregion(), itoa();
00101
00102 static void track_mk_tree_pure();
00103 static int track_mk_tree_gift();
00104 static struct wmember *track_mk_addmember();
00105 static void track_mk_freemembers();
00106 static int track_mk_comb();
00107
00108
00109
00110
00111
00112
00113 int
00114 wdb_track_cmd(struct rt_wdb *wdbp,
00115 Tcl_Interp *interp,
00116 int argc,
00117 char **argv) {
00118 fastf_t fw[3], lw[3], iw[3], dw[3], tr[3];
00119 char *solname = NULL;
00120 char *regname = NULL;
00121 char *grpname = NULL;
00122 char oper[3];
00123 int i, memb[4];
00124 vect_t temp1, temp2;
00125 int item, mat, los;
00126 int arg;
00127 int edit_result = TCL_OK;
00128 struct bu_list head;
00129
00130 WDB_TCL_CHECK_READ_ONLY;
00131
00132 BU_LIST_INIT(&head);
00133
00134 if (argc != 15) {
00135 struct bu_vls vls;
00136
00137 bu_vls_init(&vls);
00138 bu_vls_printf(&vls, "helplib_alias wdb_track %s", argv[0]);
00139 Tcl_Eval(interp, bu_vls_addr(&vls));
00140 bu_vls_free(&vls);
00141 return TCL_ERROR;
00142 }
00143
00144 oper[0] = oper[2] = WMOP_INTERSECT;
00145 oper[1] = WMOP_SUBTRACT;
00146
00147
00148 arg = 1;
00149 grpname = bu_strdup(argv[arg]);
00150 grpname_len = strlen(grpname);
00151 solname = bu_malloc(grpname_len + 1 + extraChars, "solid name");
00152 regname = bu_malloc(grpname_len + 1 + extraChars, "region name");
00153 sol.s_name = bu_malloc(grpname_len + 1 + extraChars, "sol.s_name");
00154
00155
00156 ++arg;
00157 fw[0] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00158
00159
00160 ++arg;
00161 lw[0] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00162
00163 if (fw[0] <= lw[0]) {
00164 Tcl_AppendResult(interp, "First wheel after last wheel - STOP\n", (char *)NULL);
00165 edit_result = TCL_ERROR;
00166 goto end;
00167 }
00168
00169
00170 ++arg;
00171 fw[1] = lw[1] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00172
00173
00174 ++arg;
00175 fw[2] = lw[2] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00176
00177 if( fw[2] <= 0 ) {
00178 Tcl_AppendResult(interp, "Radius <= 0 - STOP\n", (char *)NULL);
00179 edit_result = TCL_ERROR;
00180 goto end;
00181 }
00182
00183
00184 ++arg;
00185 dw[0] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00186
00187 if( dw[0] >= lw[0] ) {
00188 Tcl_AppendResult(interp, "DRIVE wheel not in the rear - STOP \n", (char *)NULL);
00189 edit_result = TCL_ERROR;
00190 goto end;
00191 }
00192
00193
00194 ++arg;
00195 dw[1] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00196
00197
00198 ++arg;
00199 dw[2] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00200
00201 if( dw[2] <= 0 ) {
00202 Tcl_AppendResult(interp, "Radius <= 0 - STOP\n", (char *)NULL);
00203 edit_result = TCL_ERROR;
00204 goto end;
00205 }
00206
00207
00208 ++arg;
00209 iw[0] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00210
00211 if( iw[0] <= fw[0] ) {
00212 Tcl_AppendResult(interp, "IDLER wheel not in the front - STOP \n", (char *)NULL);
00213 edit_result = TCL_ERROR;
00214 goto end;
00215 }
00216
00217
00218 ++arg;
00219 iw[1] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00220
00221
00222 ++arg;
00223 iw[2] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00224
00225 if( iw[2] <= 0 ) {
00226 Tcl_AppendResult(interp, "Radius <= 0 - STOP\n", (char *)NULL);
00227 edit_result = TCL_ERROR;
00228 goto end;
00229 }
00230
00231
00232 ++arg;
00233 tr[2] = tr[0] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00234
00235
00236 ++arg;
00237 tr[1] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00238
00239 if( tr[0] == tr[1] ) {
00240 Tcl_AppendResult(interp, "MIN == MAX ... STOP\n", (char *)NULL);
00241 edit_result = TCL_ERROR;
00242 goto end;
00243 }
00244 if( tr[0] > tr[1] ) {
00245 Tcl_AppendResult(interp, "MIN > MAX .... will switch\n", (char *)NULL);
00246 tr[1] = tr[0];
00247 tr[0] = tr[2];
00248 }
00249
00250
00251 ++arg;
00252 tr[2] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00253
00254 if( tr[2] <= 0 ) {
00255 Tcl_AppendResult(interp, "Track thickness <= 0 - STOP\n", (char *)NULL);
00256 edit_result = TCL_ERROR;
00257 goto end;
00258 }
00259
00260 for (i = 0; i < grpname_len; ++i) {
00261 solname[i] = grpname[i];
00262 regname[i] = grpname[i];
00263 }
00264
00265 solname[i] = regname[i] = '.';
00266 ++i;
00267 solname[i] = 's';
00268 regname[i] = 'r';
00269 ++i;
00270 solname[i] = regname[i] = '.';
00271 ++i;
00272 solname[i] = regname[i] = '\0';
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 for (i=0; i<10; i++) {
00294 crname(interp, solname, i);
00295 crname(interp, regname, i);
00296 if ((db_lookup( wdbp->dbip, solname, LOOKUP_QUIET) != DIR_NULL) ||
00297 (db_lookup( wdbp->dbip, regname, LOOKUP_QUIET) != DIR_NULL)) {
00298
00299 Tcl_AppendResult(interp, "Track: naming error -- STOP\n",
00300 (char *)NULL);
00301 edit_result = TCL_ERROR;
00302 goto end;
00303 }
00304
00305 solname[grpname_len + extraTypeChars] = '\0';
00306 regname[grpname_len + extraTypeChars] = '\0';
00307 }
00308
00309
00310 for(i=0; i<24; i++)
00311 sol.s_values[i] = 0.0;
00312
00313
00314
00315 slope(interp, fw, iw, tr);
00316 VMOVE(temp2, &sol.s_values[0]);
00317 crname(interp, solname, 0);
00318 (void)strcpy(sol.s_name, solname);
00319 sol.s_type = ID_ARB8;
00320 if (wrobj(wdbp, interp, solname, DIR_SOLID))
00321 return TCL_ERROR;
00322
00323 solname[grpname_len + extraTypeChars] = '\0';
00324
00325
00326
00327 for(i=0; i<24; i++)
00328 sol.s_values[i] = 0.0;
00329 sol.s_type = ID_TGC;
00330 trcurve(iw, tr);
00331 crname(interp, solname, 1);
00332 (void)strcpy(sol.s_name, solname);
00333 if (wrobj(wdbp, interp, solname , DIR_SOLID ) )
00334 return TCL_ERROR;
00335 solname[grpname_len + extraTypeChars] = '\0';
00336
00337 sol.s_values[6] = iw[2];
00338 sol.s_values[11] = iw[2];
00339 VMOVE(&sol.s_values[12], &sol.s_values[6]);
00340 VMOVE(&sol.s_values[15], &sol.s_values[9]);
00341
00342 crname(interp, solname, 2);
00343 (void)strcpy(sol.s_name, solname);
00344 if (wrobj(wdbp, interp, solname , DIR_SOLID ) )
00345 return TCL_ERROR;
00346 solname[grpname_len + extraTypeChars] = '\0';
00347
00348
00349
00350 for(i=0; i<24; i++)
00351 sol.s_values[i] = 0.0;
00352 crname(interp, solname, 3);
00353 (void)strcpy(sol.s_name, solname);
00354 sol.s_type = ID_ARB8;
00355 crdummy(iw, tr, 1);
00356 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00357 return TCL_ERROR;
00358 solname[grpname_len + extraTypeChars] = '\0';
00359
00360
00361
00362 for(i=0; i<24; i++)
00363 sol.s_values[i] = 0.0;
00364 slope(interp, lw, dw, tr);
00365 VMOVE(temp1, &sol.s_values[0]);
00366 crname(interp, solname, 4);
00367 (void)strcpy(sol.s_name, solname);
00368 if (wrobj(wdbp, interp,solname,DIR_SOLID))
00369 return TCL_ERROR;
00370 solname[grpname_len + extraTypeChars] = '\0';
00371
00372
00373
00374 for(i=0; i<24; i++)
00375 sol.s_values[i] = 0.0;
00376 sol.s_type = ID_TGC;
00377 trcurve(dw, tr);
00378 crname(interp, solname, 5);
00379 (void)strcpy(sol.s_name, solname);
00380 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00381 return TCL_ERROR;
00382 solname[grpname_len + extraTypeChars] = '\0';
00383
00384
00385
00386 sol.s_values[6] = dw[2];
00387 sol.s_values[11] = dw[2];
00388 VMOVE(&sol.s_values[12], &sol.s_values[6]);
00389 VMOVE(&sol.s_values[15], &sol.s_values[9]);
00390 crname(interp, solname, 6);
00391 (void)strcpy(sol.s_name, solname);
00392 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00393 return TCL_ERROR;
00394 solname[grpname_len + extraTypeChars] = '\0';
00395
00396
00397
00398 for(i=0; i<24; i++)
00399 sol.s_values[i] = 0.0;
00400 crname(interp, solname, 7);
00401 (void)strcpy(sol.s_name, solname);
00402 sol.s_type = ID_ARB8;
00403 crdummy(dw, tr, 2);
00404 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00405 return TCL_ERROR;
00406 solname[grpname_len + extraTypeChars] = '\0';
00407
00408
00409
00410 temp1[1] = temp2[1] = tr[0];
00411 bottom(temp1, temp2, tr);
00412 crname(interp, solname, 8);
00413 (void)strcpy(sol.s_name, solname);
00414 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00415 return TCL_ERROR;
00416 solname[grpname_len + extraTypeChars] = '\0';
00417
00418
00419
00420 temp1[0] = dw[0];
00421 temp1[1] = temp2[1] = tr[0];
00422 temp1[2] = dw[1] + dw[2];
00423 temp2[0] = iw[0];
00424 temp2[2] = iw[1] + iw[2];
00425 top(temp1, temp2, tr);
00426 crname(interp, solname, 9);
00427 (void)strcpy(sol.s_name, solname);
00428 if (wrobj(wdbp, interp,solname,DIR_SOLID) )
00429 return TCL_ERROR;
00430 solname[grpname_len + extraTypeChars] = '\0';
00431
00432
00433
00434 item = item_default;
00435 mat = mat_default;
00436 los = los_default;
00437 item_default = 500;
00438 mat_default = 1;
00439 los_default = 50;
00440
00441 memb[0] = 0;
00442 memb[1] = 3;
00443 crname(interp, regname, 0);
00444 crregion(wdbp, interp, regname, oper, memb, 2, solname);
00445 solname[grpname_len + extraTypeChars] = '\0';
00446 regname[grpname_len + extraTypeChars] = '\0';
00447
00448
00449 crname(interp, regname, 1);
00450 memb[0] = 1;
00451 memb[1] = 2;
00452 memb[2] = 3;
00453 crregion(wdbp, interp, regname, oper, memb, 3, solname);
00454 solname[grpname_len + extraTypeChars] = '\0';
00455 regname[grpname_len + extraTypeChars] = '\0';
00456
00457
00458 crname(interp, regname, 4);
00459 memb[0] = 4;
00460 memb[1] = 7;
00461 crregion(wdbp, interp, regname, oper, memb, 2, solname);
00462 solname[grpname_len + extraTypeChars] = '\0';
00463 regname[grpname_len + extraTypeChars] = '\0';
00464
00465
00466 crname(interp, regname, 5);
00467 memb[0] = 5;
00468 memb[1] = 6;
00469 memb[2] = 7;
00470 crregion(wdbp, interp, regname, oper, memb, 3, solname);
00471 solname[grpname_len + extraTypeChars] = '\0';
00472 regname[grpname_len + extraTypeChars] = '\0';
00473
00474
00475 crname(interp, regname, 8);
00476 memb[0] = 8;
00477 memb[1] = 0;
00478 memb[2] = 4;
00479 oper[2] = WMOP_SUBTRACT;
00480 crregion(wdbp, interp, regname, oper, memb, 3, solname);
00481 solname[grpname_len + extraTypeChars] = '\0';
00482 regname[grpname_len + extraTypeChars] = '\0';
00483
00484
00485 crname(interp, regname, 9);
00486 memb[0] = 9;
00487 memb[1] = 3;
00488 memb[2] = 7;
00489 crregion(wdbp, interp, regname, oper, memb, 3, solname);
00490 solname[grpname_len + extraTypeChars] = '\0';
00491 regname[grpname_len + extraTypeChars] = '\0';
00492
00493
00494 for (i=0; i<10; i++) {
00495 if (i == 2 || i == 3 || i == 6 || i == 7)
00496 continue;
00497 regname[grpname_len + extraTypeChars] = '\0';
00498 crname(interp, regname, i);
00499 if (db_lookup( wdbp->dbip, regname, LOOKUP_QUIET) == DIR_NULL) {
00500 Tcl_AppendResult(interp, "group: ", grpname, " will skip member: ",
00501 regname, "\n", (char *)NULL);
00502 continue;
00503 }
00504 track_mk_addmember(regname, &head, NULL, WMOP_UNION);
00505 }
00506
00507
00508 if (track_mk_comb( wdbp, grpname, &head,
00509 0, NULL, NULL, NULL,
00510 0, 0, 0, 0,
00511 0, 1, 1) < 0) {
00512 Tcl_AppendResult(interp,
00513 "An error has occured while adding '",
00514 grpname, "' to the database.\n", (char *)NULL);
00515 }
00516
00517 Trackpos += 10;
00518 item_default = item;
00519 mat_default = mat;
00520 los_default = los;
00521
00522 bu_free((genptr_t)solname, "solid name");
00523 bu_free((genptr_t)regname, "region name");
00524 bu_free((genptr_t)grpname, "group name");
00525 bu_free((genptr_t)sol.s_name, "sol.s_name");
00526
00527 return edit_result;
00528
00529 end:
00530 bu_free((genptr_t)solname, "solid name");
00531 bu_free((genptr_t)regname, "region name");
00532 bu_free((genptr_t)grpname, "group name");
00533 bu_free((genptr_t)sol.s_name, "sol.s_name");
00534
00535 return edit_result;
00536 }
00537
00538 static void
00539 crname(Tcl_Interp *interp,
00540 char name[],
00541 int pos) {
00542 char temp[4];
00543
00544 itoa(interp, pos, temp, 1);
00545 (void)strcat(name, temp);
00546
00547 return;
00548 }
00549
00550 static int
00551 wrobj(struct rt_wdb *wdbp,
00552 Tcl_Interp *interp,
00553 char name[],
00554 int flags) {
00555 struct directory *tdp;
00556 struct rt_db_internal intern;
00557 int i;
00558
00559 if(wdbp->dbip == DBI_NULL)
00560 return 0;
00561
00562 if( db_lookup( wdbp->dbip, name, LOOKUP_QUIET) != DIR_NULL ) {
00563 Tcl_AppendResult(interp, "track naming error: ", name,
00564 " already exists\n", (char *)NULL);
00565 return(-1);
00566 }
00567
00568 if( flags != DIR_SOLID )
00569 {
00570 Tcl_AppendResult(interp, "wrobj can only write solids, aborting\n" );
00571 return( -1 );
00572 }
00573
00574 RT_INIT_DB_INTERNAL( &intern );
00575 switch( sol.s_type )
00576 {
00577 case ID_ARB8:
00578 {
00579 struct rt_arb_internal *arb;
00580
00581 BU_GETSTRUCT( arb, rt_arb_internal );
00582
00583 arb->magic = RT_ARB_INTERNAL_MAGIC;
00584
00585 VMOVE( arb->pt[0], &sol.s_values[0] );
00586 for( i=1 ; i<8 ; i++ )
00587 VADD2( arb->pt[i], &sol.s_values[i*3], arb->pt[0] )
00588
00589 intern.idb_ptr = (genptr_t)arb;
00590 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00591 intern.idb_type = ID_ARB8;
00592 intern.idb_meth = &rt_functab[ID_ARB8];
00593 }
00594 break;
00595 case ID_TGC:
00596 {
00597 struct rt_tgc_internal *tgc;
00598
00599 BU_GETSTRUCT( tgc, rt_tgc_internal );
00600
00601 tgc->magic = RT_TGC_INTERNAL_MAGIC;
00602
00603 VMOVE( tgc->v, &sol.s_values[0] );
00604 VMOVE( tgc->h, &sol.s_values[3] );
00605 VMOVE( tgc->a, &sol.s_values[6] );
00606 VMOVE( tgc->b, &sol.s_values[9] );
00607 VMOVE( tgc->c, &sol.s_values[12] );
00608 VMOVE( tgc->d, &sol.s_values[15] );
00609
00610 intern.idb_ptr = (genptr_t)tgc;
00611 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00612 intern.idb_type = ID_TGC;
00613 intern.idb_meth = &rt_functab[ID_TGC];
00614 }
00615 break;
00616 default:
00617 Tcl_AppendResult(interp, "Unrecognized solid type in 'wrobj', aborting\n", (char *)NULL );
00618 return( -1 );
00619 }
00620
00621 if( (tdp = db_diradd( wdbp->dbip, name, -1L, 0, flags, (genptr_t)&intern.idb_type)) == DIR_NULL )
00622 {
00623 rt_db_free_internal( &intern, &rt_uniresource );
00624 Tcl_AppendResult(interp, "Cannot add '", name, "' to directory, aborting\n", (char *)NULL );
00625 return( -1 );
00626 }
00627
00628 if( rt_db_put_internal( tdp, wdbp->dbip, &intern, &rt_uniresource ) < 0 )
00629 {
00630 rt_db_free_internal( &intern, &rt_uniresource );
00631 Tcl_AppendResult(interp, "wrobj(wdbp, interp, ", name, "): write error\n", (char *)NULL);
00632 WDB_TCL_ERROR_RECOVERY_SUGGESTION;
00633 return( -1 );
00634 }
00635 return(0);
00636 }
00637
00638 static void
00639 tancir(Tcl_Interp *interp,
00640 register fastf_t cir1[],
00641 register fastf_t cir2[]) {
00642 static fastf_t mag;
00643 vect_t work;
00644 FAST fastf_t f;
00645 static fastf_t temp, tempp, ang, angc;
00646
00647 work[0] = cir2[0] - cir1[0];
00648 work[2] = cir2[1] - cir1[1];
00649 work[1] = 0.0;
00650 mag = MAGNITUDE( work );
00651 if( mag > 1.0e-20 || mag < -1.0e-20 ) {
00652 f = 1.0/mag;
00653 } else {
00654 Tcl_AppendResult(interp, "tancir(): 0-length vector!\n", (char *)NULL);
00655 return;
00656 }
00657 VSCALE(work, work, f);
00658 temp = acos( work[0] );
00659 if( work[2] < 0.0 )
00660 temp = 6.28318512717958646 - temp;
00661 tempp = acos( (cir1[2] - cir2[2]) * f );
00662 ang = temp + tempp;
00663 angc = temp - tempp;
00664 if( (cir1[1] + cir1[2] * sin(ang)) >
00665 (cir1[1] + cir1[2] * sin(angc)) )
00666 ang = angc;
00667 plano[0] = cir1[0] + cir1[2] * cos(ang);
00668 plano[1] = cir1[1] + cir1[2] * sin(ang);
00669 plant[0] = cir2[0] + cir2[2] * cos(ang);
00670 plant[1] = cir2[1] + cir2[2] * sin(ang);
00671
00672 return;
00673 }
00674
00675 static void
00676 slope(Tcl_Interp *interp,
00677 fastf_t wh1[],
00678 fastf_t wh2[],
00679 fastf_t t[]) {
00680 int i, j, switchs;
00681 fastf_t temp;
00682 fastf_t mag;
00683 fastf_t z, r, b;
00684 vect_t del, work;
00685
00686 switchs = 0;
00687 if( wh1[2] < wh2[2] ) {
00688 switchs++;
00689 for(i=0; i<3; i++) {
00690 temp = wh1[i];
00691 wh1[i] = wh2[i];
00692 wh2[i] = temp;
00693 }
00694 }
00695 tancir(interp, wh1, wh2);
00696 if( switchs ) {
00697 for(i=0; i<3; i++) {
00698 temp = wh1[i];
00699 wh1[i] = wh2[i];
00700 wh2[i] = temp;
00701 }
00702 }
00703 if(plano[1] <= plant[1]) {
00704 for(i=0; i<2; i++) {
00705 temp = plano[i];
00706 plano[i] = plant[i];
00707 plant[i] = temp;
00708 }
00709 }
00710 del[1] = 0.0;
00711 del[0] = plano[0] - plant[0];
00712 del[2] = plano[1] - plant[1];
00713 mag = MAGNITUDE( del );
00714 work[0] = -1.0 * t[2] * del[2] / mag;
00715 if( del[0] < 0.0 )
00716 work[0] *= -1.0;
00717 work[1] = 0.0;
00718 work[2] = t[2] * fabs(del[0]) / mag;
00719 b = (plano[1] - work[2]) - (del[2]/del[0]*(plano[0] - work[0]));
00720 z = wh1[1];
00721 r = wh1[2];
00722 if( wh1[1] >= wh2[1] ) {
00723 z = wh2[1];
00724 r = wh2[2];
00725 }
00726 sol.s_values[2] = z - r - t[2];
00727 sol.s_values[1] = t[0];
00728 sol.s_values[0] = (sol.s_values[2] - b) / (del[2] / del[0]);
00729 sol.s_values[3] = plano[0] + (del[0]/mag) - work[0] - sol.s_values[0];
00730 sol.s_values[4] = 0.0;
00731 sol.s_values[5] = plano[1] + (del[2]/mag) - work[2] - sol.s_values[2];
00732 VADD2(&sol.s_values[6], &sol.s_values[3], work);
00733 VMOVE(&sol.s_values[9], work);
00734 work[0] = work[2] = 0.0;
00735 work[1] = t[1] - t[0];
00736 VMOVE(&sol.s_values[12], work);
00737 for(i=3; i<=9; i+=3) {
00738 j = i + 12;
00739 VADD2(&sol.s_values[j], &sol.s_values[i], work);
00740 }
00741
00742 return;
00743 }
00744
00745 static void
00746 crdummy( w, t, flag )
00747 fastf_t w[3], t[3];
00748 int flag;
00749 {
00750 fastf_t temp;
00751 vect_t vec;
00752 int i, j;
00753
00754 vec[1] = 0.0;
00755 if(plano[1] <= plant[1]) {
00756 for(i=0; i<2; i++) {
00757 temp = plano[i];
00758 plano[i] = plant[i];
00759 plant[i] = temp;
00760 }
00761 }
00762
00763 vec[0] = w[2] + t[2] + 1.0;
00764 vec[2] = ( (plano[1] - w[1]) * vec[0] ) / (plano[0] - w[0]);
00765 if( flag > 1 )
00766 vec[0] *= -1.0;
00767 if(vec[2] >= 0.0)
00768 vec[2] *= -1.0;
00769 sol.s_values[0] = w[0];
00770 sol.s_values[1] = t[0] -1.0;
00771 sol.s_values[2] = w[1];
00772 VMOVE(&sol.s_values[3] , vec);
00773 vec[2] = w[2] + t[2] + 1.0;
00774 VMOVE(&sol.s_values[6], vec);
00775 vec[0] = 0.0;
00776 VMOVE(&sol.s_values[9], vec);
00777 vec[2] = 0.0;
00778 vec[1] = t[1] - t[0] + 2.0;
00779 VMOVE(&sol.s_values[12], vec);
00780 for(i=3; i<=9; i+=3) {
00781 j = i + 12;
00782 VADD2(&sol.s_values[j], &sol.s_values[i], vec);
00783 }
00784
00785 return;
00786
00787 }
00788
00789 static void
00790 trcurve( wh, t )
00791 fastf_t wh[], t[];
00792 {
00793 sol.s_values[0] = wh[0];
00794 sol.s_values[1] = t[0];
00795 sol.s_values[2] = wh[1];
00796 sol.s_values[4] = t[1] - t[0];
00797 sol.s_values[6] = wh[2] + t[2];
00798 sol.s_values[11] = wh[2] + t[2];
00799 VMOVE(&sol.s_values[12], &sol.s_values[6]);
00800 VMOVE(&sol.s_values[15], &sol.s_values[9]);
00801 }
00802
00803 static void
00804 bottom( vec1, vec2, t )
00805 vect_t vec1, vec2;
00806 fastf_t t[];
00807 {
00808 vect_t tvec;
00809 int i, j;
00810
00811 VMOVE(&sol.s_values[0], vec1);
00812 tvec[0] = vec2[0] - vec1[0];
00813 tvec[1] = tvec[2] = 0.0;
00814 VMOVE(&sol.s_values[3], tvec);
00815 tvec[0] = tvec[1] = 0.0;
00816 tvec[2] = t[2];
00817 VADD2(&sol.s_values[6], &sol.s_values[3], tvec);
00818 VMOVE(&sol.s_values[9], tvec);
00819 tvec[0] = tvec[2] = 0.0;
00820 tvec[1] = t[1] - t[0];
00821 VMOVE(&sol.s_values[12], tvec);
00822
00823 for(i=3; i<=9; i+=3) {
00824 j = i + 12;
00825 VADD2(&sol.s_values[j], &sol.s_values[i], tvec);
00826 }
00827 }
00828
00829 static void
00830 top( vec1, vec2, t )
00831 vect_t vec1, vec2;
00832 fastf_t t[];
00833 {
00834 fastf_t tooch, mag;
00835 vect_t del, tvec;
00836 int i, j;
00837
00838 tooch = t[2] * .25;
00839 del[0] = vec2[0] - vec1[0];
00840 del[1] = 0.0;
00841 del[2] = vec2[2] - vec1[2];
00842 mag = MAGNITUDE( del );
00843 VSCALE(tvec, del, tooch/mag);
00844 VSUB2(&sol.s_values[0], vec1, tvec);
00845 VADD2(del, del, tvec);
00846 VADD2(&sol.s_values[3], del, tvec);
00847 tvec[0] = tvec[2] = 0.0;
00848 tvec[1] = t[1] - t[0];
00849 VCROSS(del, tvec, &sol.s_values[3]);
00850 mag = MAGNITUDE( del );
00851 if(del[2] < 0)
00852 mag *= -1.0;
00853 VSCALE(&sol.s_values[9], del, t[2]/mag);
00854 VADD2(&sol.s_values[6], &sol.s_values[3], &sol.s_values[9]);
00855 VMOVE(&sol.s_values[12], tvec);
00856
00857 for(i=3; i<=9; i+=3) {
00858 j = i + 12;
00859 VADD2(&sol.s_values[j], &sol.s_values[i], tvec);
00860 }
00861 }
00862
00863 static void
00864 crregion(struct rt_wdb *wdbp,
00865 Tcl_Interp *interp,
00866 char region[],
00867 char op[],
00868 int members[],
00869 int number,
00870 char solidname[]) {
00871 int i;
00872 struct bu_list head;
00873
00874 if(wdbp->dbip == DBI_NULL)
00875 return;
00876
00877 BU_LIST_INIT(&head);
00878
00879 for(i=0; i<number; i++) {
00880 solidname[grpname_len + extraTypeChars] = '\0';
00881 crname(interp, solidname, members[i]);
00882 if( db_lookup( wdbp->dbip, solidname, LOOKUP_QUIET) == DIR_NULL ) {
00883 Tcl_AppendResult(interp, "region: ", region, " will skip member: ",
00884 solidname, "\n", (char *)NULL);
00885 continue;
00886 }
00887 track_mk_addmember( solidname, &head, NULL, op[i] );
00888 }
00889 (void)track_mk_comb( wdbp, region, &head,
00890 1, NULL, NULL, NULL,
00891 500+Trackpos+i, 0, mat_default, los_default,
00892 0, 1, 1 );
00893 }
00894
00895
00896
00897
00898
00899
00900
00901 static void
00902 itoa(Tcl_Interp *interp,
00903 int n,
00904 char s[],
00905 int w) {
00906 int c, i, j, sign;
00907
00908 if( (sign = n) < 0 ) n = -n;
00909 i = 0;
00910 do s[i++] = n % 10 + '0'; while( (n /= 10) > 0 );
00911 if( sign < 0 ) s[i++] = '-';
00912
00913
00914
00915 for( j = i; j < w; j++ ) s[j] = ' ';
00916 if( i > w )
00917 Tcl_AppendResult(interp, "itoa: field length too small\n", (char *)NULL);
00918 s[w] = '\0';
00919
00920
00921 for( i = 0, j = w - 1; i < j; i++, j-- ) {
00922 c = s[i];
00923 s[i] = s[j];
00924 s[j] = c;
00925 }
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 static void
00942 track_mk_tree_pure( struct rt_comb_internal *comb, struct bu_list *member_hd )
00943 {
00944 register struct wmember *wp;
00945
00946 for( BU_LIST_FOR( wp, wmember, member_hd ) ) {
00947 union tree *leafp, *nodep;
00948
00949 WDB_CK_WMEMBER(wp);
00950
00951 BU_GETUNION( leafp, tree );
00952 leafp->tr_l.magic = RT_TREE_MAGIC;
00953 leafp->tr_l.tl_op = OP_DB_LEAF;
00954 leafp->tr_l.tl_name = bu_strdup( wp->wm_name );
00955 if( !bn_mat_is_identity( wp->wm_mat ) ) {
00956 leafp->tr_l.tl_mat = bn_mat_dup( wp->wm_mat );
00957 }
00958
00959 if( !comb->tree ) {
00960 comb->tree = leafp;
00961 continue;
00962 }
00963
00964 BU_GETUNION( nodep, tree );
00965 nodep->tr_b.magic = RT_TREE_MAGIC;
00966 switch( wp->wm_op ) {
00967 case WMOP_UNION:
00968 nodep->tr_b.tb_op = OP_UNION;
00969 break;
00970 case WMOP_INTERSECT:
00971 nodep->tr_b.tb_op = OP_INTERSECT;
00972 break;
00973 case WMOP_SUBTRACT:
00974 nodep->tr_b.tb_op = OP_SUBTRACT;
00975 break;
00976 default:
00977 bu_bomb("track_mk_tree_pure() bad wm_op");
00978 }
00979 nodep->tr_b.tb_left = comb->tree;
00980 nodep->tr_b.tb_right = leafp;
00981 comb->tree = nodep;
00982 }
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 static int
00998 track_mk_tree_gift( struct rt_comb_internal *comb, struct bu_list *member_hd )
00999 {
01000 struct wmember *wp;
01001 union tree *tp;
01002 struct rt_tree_array *tree_list;
01003 int node_count;
01004 int actual_count;
01005 int new_nodes;
01006
01007 if( (new_nodes = bu_list_len( member_hd )) <= 0 )
01008 return 0;
01009
01010 if( comb->tree && db_ck_v4gift_tree( comb->tree ) < 0 )
01011 {
01012 db_non_union_push( comb->tree, &rt_uniresource );
01013 if( db_ck_v4gift_tree( comb->tree ) < 0 )
01014 {
01015 bu_log("track_mk_tree_gift() Cannot flatten tree for editing\n");
01016 return -1;
01017 }
01018 }
01019
01020
01021 node_count = db_tree_nleaves( comb->tree ) ;
01022 tree_list = (struct rt_tree_array *)bu_calloc( node_count + new_nodes,
01023 sizeof( struct rt_tree_array ), "tree list" );
01024
01025
01026 if( comb->tree ) {
01027
01028 actual_count = (struct rt_tree_array *)db_flatten_tree(
01029 tree_list, comb->tree, OP_UNION,
01030 1, &rt_uniresource ) - tree_list;
01031 BU_ASSERT_LONG( actual_count, ==, node_count );
01032 comb->tree = TREE_NULL;
01033 } else {
01034 actual_count = 0;
01035 }
01036
01037
01038 for( BU_LIST_FOR( wp, wmember, member_hd ) ) {
01039 WDB_CK_WMEMBER(wp);
01040
01041 switch( wp->wm_op ) {
01042 case WMOP_INTERSECT:
01043 tree_list[node_count].tl_op = OP_INTERSECT;
01044 break;
01045 case WMOP_SUBTRACT:
01046 tree_list[node_count].tl_op = OP_SUBTRACT;
01047 break;
01048 default:
01049 bu_log("track_mk_tree_gift() unrecognized relation %c (assuming UNION)\n", wp->wm_op);
01050
01051 case WMOP_UNION:
01052 tree_list[node_count].tl_op = OP_UNION;
01053 break;
01054 }
01055
01056
01057 BU_GETUNION( tp, tree );
01058 tree_list[node_count++].tl_tree = tp;
01059 tp->tr_l.magic = RT_TREE_MAGIC;
01060 tp->tr_l.tl_op = OP_DB_LEAF;
01061 tp->tr_l.tl_name = bu_strdup( wp->wm_name );
01062 if( !bn_mat_is_identity( wp->wm_mat ) ) {
01063 tp->tr_l.tl_mat = bn_mat_dup( wp->wm_mat );
01064 } else {
01065 tp->tr_l.tl_mat = (matp_t)NULL;
01066 }
01067 }
01068 BU_ASSERT_LONG( node_count, ==, actual_count + new_nodes );
01069
01070
01071 comb->tree = (union tree *)db_mkgift_tree( tree_list, node_count, &rt_uniresource );
01072
01073 bu_free( (char *)tree_list, "track_mk_tree_gift: tree_list" );
01074
01075 return 0;
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 static struct wmember *
01091 track_mk_addmember(
01092 const char *name,
01093 struct bu_list *headp,
01094 mat_t mat,
01095 int op)
01096 {
01097 register struct wmember *wp;
01098
01099 BU_GETSTRUCT( wp, wmember );
01100 wp->l.magic = WMEMBER_MAGIC;
01101 wp->wm_name = bu_strdup( name );
01102 switch( op ) {
01103 case WMOP_UNION:
01104 case WMOP_INTERSECT:
01105 case WMOP_SUBTRACT:
01106 wp->wm_op = op;
01107 break;
01108 default:
01109 bu_log("mk_addmember() op=x%x is bad\n", op);
01110 return(WMEMBER_NULL);
01111 }
01112
01113
01114 if (mat) {
01115 MAT_COPY( wp->wm_mat, mat );
01116 } else {
01117 MAT_IDN( wp->wm_mat );
01118 }
01119
01120
01121 BU_LIST_INSERT( headp, &wp->l );
01122 return(wp);
01123 }
01124
01125
01126
01127
01128 static void
01129 track_mk_freemembers( struct bu_list *headp )
01130 {
01131 register struct wmember *wp;
01132
01133 while( BU_LIST_WHILE( wp, wmember, headp ) ) {
01134 WDB_CK_WMEMBER(wp);
01135 BU_LIST_DEQUEUE( &wp->l );
01136 bu_free( (char *)wp->wm_name, "wm_name" );
01137 bu_free( (char *)wp, "wmember" );
01138 }
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 static int
01156 track_mk_comb(
01157 struct rt_wdb *wdbp,
01158 const char *combname,
01159 struct bu_list *headp,
01160 int region_kind,
01161 const char *shadername,
01162 const char *shaderargs,
01163 const unsigned char *rgb,
01164 int id,
01165 int air,
01166 int material,
01167 int los,
01168 int inherit,
01169 int append_ok,
01170 int gift_semantics)
01171 {
01172 struct rt_db_internal intern;
01173 struct rt_comb_internal *comb;
01174 int fresh_combination;
01175
01176 RT_CK_WDB(wdbp);
01177
01178 RT_INIT_DB_INTERNAL(&intern);
01179
01180 if( append_ok &&
01181 wdb_import( wdbp, &intern, combname, (matp_t)NULL ) >= 0 ) {
01182
01183 comb = (struct rt_comb_internal *)intern.idb_ptr;
01184 RT_CK_COMB( comb );
01185
01186 fresh_combination = 0;
01187 } else {
01188
01189 BU_GETSTRUCT( comb, rt_comb_internal );
01190 comb->magic = RT_COMB_MAGIC;
01191 bu_vls_init( &comb->shader );
01192 bu_vls_init( &comb->material );
01193
01194 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
01195 intern.idb_type = ID_COMBINATION;
01196 intern.idb_ptr = (genptr_t)comb;
01197 intern.idb_meth = &rt_functab[ID_COMBINATION];
01198
01199 fresh_combination = 1;
01200 }
01201
01202 if( gift_semantics )
01203 track_mk_tree_gift( comb, headp );
01204 else
01205 track_mk_tree_pure( comb, headp );
01206
01207
01208 track_mk_freemembers( headp );
01209
01210
01211 if( fresh_combination ) {
01212 if( region_kind ) {
01213 comb->region_flag = 1;
01214 switch( region_kind ) {
01215 case 'P':
01216 comb->is_fastgen = REGION_FASTGEN_PLATE;
01217 break;
01218 case 'V':
01219 comb->is_fastgen = REGION_FASTGEN_VOLUME;
01220 break;
01221 case 'R':
01222 case 1:
01223
01224 break;
01225 default:
01226 bu_log("mk_comb(%s) unknown region_kind=%d (%c), assuming normal non-FASTGEN\n",
01227 combname, region_kind, region_kind);
01228 }
01229 }
01230 if( shadername ) bu_vls_strcat( &comb->shader, shadername );
01231 if( shaderargs ) {
01232 bu_vls_strcat( &comb->shader, " " );
01233 bu_vls_strcat( &comb->shader, shaderargs );
01234
01235 if( strchr( shaderargs, '=' ) != NULL &&
01236 strchr( shaderargs, '{' ) == NULL )
01237 {
01238 struct bu_vls old;
01239 bu_vls_init(&old);
01240 bu_vls_vlscatzap(&old, &comb->shader);
01241 if( bu_shader_to_tcl_list( bu_vls_addr(&old), &comb->shader) )
01242 bu_log("Unable to convert shader string '%s %s'\n", shadername, shaderargs);
01243 bu_vls_free(&old);
01244 }
01245 }
01246
01247 if( rgb ) {
01248 comb->rgb_valid = 1;
01249 comb->rgb[0] = rgb[0];
01250 comb->rgb[1] = rgb[1];
01251 comb->rgb[2] = rgb[2];
01252 }
01253
01254 comb->region_id = id;
01255 comb->aircode = air;
01256 comb->GIFTmater = material;
01257 comb->los = los;
01258
01259 comb->inherit = inherit;
01260 }
01261
01262
01263 return wdb_put_internal( wdbp, combname, &intern, 1.0);
01264 }
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274