track.c

Go to the documentation of this file.
00001 /*                         T R A C K . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1994-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup librt */
00023 
00024 /*@{*/
00025 /** @file track.c
00026  * f_amtrack(): Adds "tracks" to the data file given the required info
00027  *
00028  *  Author -
00029  *      Keith A. Applin
00030  *
00031  *  Source -
00032  *      The U. S. Army Research Laboratory
00033  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00034  *
00035  *
00036  *
00037  * Acknowledgements:
00038  * Modifications by Bob Parker (SURVICE Engineering):
00039  *       *- adapt for use in LIBRT's database object
00040  *       *- removed prompting for input
00041  *       *- removed signal catching
00042  *       *- added basename parameter
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 /*XXX The following WDB_ defines need to go inside of a header file */
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  *      Adds track given "wheel" info
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   /* base name */
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   /* first road wheel X */
00156   ++arg;
00157   fw[0] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00158 
00159   /* last road wheel X */
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   /* road wheel Z */
00170   ++arg;
00171   fw[1] = lw[1] = atof(argv[arg]) * wdbp->dbip->dbi_local2base;
00172 
00173   /* roadwheel radius */
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   /* drive sprocket X */
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   /* drive sprocket Z */
00194   ++arg;
00195   dw[1] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00196 
00197   /* drive sprocket radius */
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   /* idler wheel X */
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   /* idler wheel Z */
00218   ++arg;
00219   iw[1] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00220 
00221   /* idler wheel radius */
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   /* track MIN Y */
00232   ++arg;
00233   tr[2] = tr[0] = atof( argv[arg] ) * wdbp->dbip->dbi_local2base;
00234 
00235   /* track MAX Y */
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   /* track thickness */
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   bu_log("\nX of first road wheel  %10.4f\n",fw[0]);
00275   bu_log("X of last road wheel   %10.4f\n",lw[0]);
00276   bu_log("Z of road wheels       %10.4f\n",fw[1]);
00277   bu_log("radius of road wheels  %10.4f\n",fw[2]);
00278   bu_log("\nX of drive wheel       %10.4f\n",dw[0]);
00279   bu_log("Z of drive wheel       %10.4f\n",dw[1]);
00280   bu_log("radius of drive wheel  %10.4f\n",dw[2]);
00281   bu_log("\nX of idler wheel       %10.4f\n",iw[0]);
00282   bu_log("Z of idler wheel       %10.4f\n",iw[1]);
00283   bu_log("radius of idler wheel  %10.4f\n",iw[2]);
00284   bu_log("\nY MIN of track         %10.4f\n",tr[0]);
00285   bu_log("Y MAX of track         %10.4f\n",tr[1]);
00286   bu_log("thickness of track     %10.4f\n",tr[2]);
00287 */
00288 
00289 /* Check for names to use:
00290  *      grpname.s.0->9 and grpname.r.0->9
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       /* name already exists */
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   /* find the front track slope to the idler */
00310   for(i=0; i<24; i++)
00311     sol.s_values[i] = 0.0;
00312 
00313   /* add the solids */
00314   /* solid 0 */
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   /* solid 1 */
00326   /* find track around idler */
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   /* idler dummy rcc */
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   /* solid 2 */
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   /* solid 3 */
00349   /* find idler track dummy arb8 */
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   /* solid 4 */
00361   /* track slope to drive */
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   /* solid 5 */
00373   /* track around drive */
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   /* solid 6 */
00385   /* drive dummy rcc */
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   /* solid 7 */
00397   /* drive dummy arb8 */
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   /* solid 8 */
00409   /* track bottom */
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   /* solid 9 */
00419   /* track top */
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   /* add the regions */
00433   /* region 0 */
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   /* region 1 */
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   /* region 1 */
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   /* region 4 */
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   /* region 5 */
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   /* region 8 */
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   /* region 9 */
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   /* group all the track regions */
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   /* Add them all at once */
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 /*      ==== I T O A ( )
00899  *      convert integer to ascii  wd format
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         /* blank fill array
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         /* reverse the array
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  * The following functions were pulled in from libwdb
00930  * to prevent creating a new dependency.
00931  */
00932 
00933 /*
00934  *                      M K _ T R E E _ P U R E
00935  *
00936  *  Given a list of wmember structures, build a tree that performs
00937  *  the boolean operations in the given sequence.
00938  *  No GIFT semantics or precedence is provided.
00939  *  For that, use mk_tree_gift().
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                 /* Build a left-heavy tree */
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  *                      M K _ T R E E _ G I F T
00987  *
00988  *  Add some nodes to a new or existing combination's tree,
00989  *  with GIFT precedence and semantics.
00990  *
00991  *  NON-PARALLEL due to rt_uniresource
00992  *
00993  *  Returns -
00994  *      -1      ERROR
00995  *      0       OK
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;       /* OK, nothing to do */
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         /* make space for an extra leaf */
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         /* flatten tree */
01026         if( comb->tree )  {
01027                 /* Release storage for non-leaf nodes, steal leaves */
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         /* Add new members to the array */
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                                 /* Fall through */
01051                         case WMOP_UNION:
01052                                 tree_list[node_count].tl_op = OP_UNION;
01053                                 break;
01054                 }
01055 
01056                 /* make new leaf node, and insert at end of array */
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         /* rebuild the tree with GIFT semantics */
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;       /* OK */
01076 }
01077 
01078 /*
01079  *                      M K _ A D D M E M B E R
01080  *
01081  *  Obtain dynamic storage for a new wmember structure, fill in the
01082  *  name, default the operation and matrix, and add to doubly linked
01083  *  list.  In typical use, a one-line call is sufficient.  To change
01084  *  the defaults, catch the pointer that is returned, and adjust the
01085  *  structure to taste.
01086  *
01087  *  The caller is responsible for initializing the header structures
01088  *  forward and backward links.
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         /* if the user gave a matrix, use it.  otherwise use identity matrix*/
01114         if (mat) {
01115                 MAT_COPY( wp->wm_mat, mat );
01116         } else {
01117                 MAT_IDN( wp->wm_mat );
01118         }
01119 
01120         /* Append to end of doubly linked list */
01121         BU_LIST_INSERT( headp, &wp->l );
01122         return(wp);
01123 }
01124 
01125 /*
01126  *                      M K _ F R E E M E M B E R S
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  *                      M K _ C O M B
01143  *
01144  *  Make a combination, where the
01145  *  members are described by a linked list of wmember structs.
01146  *
01147  *  The linked list is freed when it has been output.
01148  *
01149  *  Has many operating modes.
01150  *
01151  *  Returns -
01152  *      -1      ERROR
01153  *      0       OK
01154  */
01155 static int
01156 track_mk_comb(
01157         struct rt_wdb           *wdbp,
01158         const char              *combname,
01159         struct bu_list          *headp,         /* Made by mk_addmember() */
01160         int                     region_kind,    /* 1 => region.  'P' and 'V' for FASTGEN */
01161         const char              *shadername,    /* shader name, or NULL */
01162         const char              *shaderargs,    /* shader args, or NULL */
01163         const unsigned char     *rgb,           /* NULL => no color */
01164         int                     id,             /* region_id */
01165         int                     air,            /* aircode */
01166         int                     material,       /* GIFTmater */
01167         int                     los,
01168         int                     inherit,
01169         int                     append_ok,      /* 0 = obj must not exit */
01170         int                     gift_semantics) /* 0 = pure, 1 = gift */
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                 /* We retrieved an existing object, append to it */
01183                 comb = (struct rt_comb_internal *)intern.idb_ptr;
01184                 RT_CK_COMB( comb );
01185 
01186                 fresh_combination = 0;
01187         } else {
01188                 /* Create a fresh new object for export */
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         /* Release the wmember list dynamic storage */
01208         track_mk_freemembers( headp );
01209 
01210         /* Don't change these things when appending to existing combination */
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                                 /* Regular non-FASTGEN Region */
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                         /* Convert to Tcl form if necessary.  Use heuristics */
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         /* The internal representation will be freed */
01263         return wdb_put_internal( wdbp, combname, &intern, 1.0);
01264 }
01265 
01266 /*
01267  * Local Variables:
01268  * mode: C
01269  * tab-width: 8
01270  * c-basic-offset: 4
01271  * indent-tabs-mode: t
01272  * End:
01273  * ex: shiftwidth=4 tabstop=8
01274  */

Generated on Mon Sep 18 01:24:57 2006 for BRL-CAD by  doxygen 1.4.6