vlist.c

Go to the documentation of this file.
00001 /*                         V L I S T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1992-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 /** @file vlist.c
00025  *  Routines for the import and export of vlist chains as:
00026  *      Network independent binary,
00027  *      BRL-extended UNIX-Plot files.
00028  *
00029  *  Author -
00030  *      Michael John Muuss
00031  *
00032  *  Source -
00033  *      SECAD/VLD Computing Consortium
00034  *      The U. S. Army Ballistic Research Laboratory
00035  *      Aberdeen Proving Ground, Maryland  21005-5066
00036  *
00037  */
00038 /*@}*/
00039 #ifndef lint
00040 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/vlist.c,v 14.12 2006/09/16 02:04:26 lbutler Exp $ (BRL)";
00041 #endif
00042 
00043 #include "common.h"
00044 
00045 
00046 
00047 #include <stdio.h>
00048 #include <math.h>
00049 #include <string.h>
00050 #include "machine.h"
00051 #include "vmath.h"
00052 #include "bu.h"
00053 #include "bn.h"
00054 #include "raytrace.h"
00055 #include "plot3.h"
00056 
00057 /************************************************************************
00058  *                                                                      *
00059  *                      Generic VLBLOCK routines                        *
00060  *                                                                      *
00061  ************************************************************************/
00062 
00063 /*
00064  *                      B N _ V L B L O C K _ I N I T
00065  */
00066 struct bn_vlblock *
00067 bn_vlblock_init(
00068         struct bu_list  *free_vlist_hd,         /* where to get/put free vlists */
00069         int             max_ent)
00070 {
00071         struct bn_vlblock *vbp;
00072         int     i;
00073 
00074         if (BU_LIST_UNINITIALIZED( free_vlist_hd ))
00075                 BU_LIST_INIT( free_vlist_hd );
00076 
00077         BU_GETSTRUCT( vbp, bn_vlblock );
00078         vbp->magic = BN_VLBLOCK_MAGIC;
00079         vbp->free_vlist_hd = free_vlist_hd;
00080         vbp->max = max_ent;
00081         vbp->head = (struct bu_list *)bu_calloc( vbp->max,
00082                 sizeof(struct bu_list), "head[]" );
00083         vbp->rgb = (long *)bu_calloc( vbp->max,
00084                 sizeof(long), "rgb[]" );
00085 
00086         for( i=0; i < vbp->max; i++ )  {
00087                 vbp->rgb[i] = 0;
00088                 BU_LIST_INIT( &(vbp->head[i]) );
00089         }
00090 
00091         vbp->rgb[0] = 0xFFFF00L;        /* Yellow, default */
00092         vbp->rgb[1] = 0xFFFFFFL;        /* White */
00093         vbp->nused = 2;
00094 
00095         return(vbp);
00096 }
00097 
00098 /*
00099  *                      R T _ V L B L O C K _ I N I T
00100  */
00101 struct bn_vlblock *
00102 rt_vlblock_init(void)
00103 {
00104         return bn_vlblock_init( &rt_g.rtg_vlfree, 32 );
00105 }
00106 
00107 /*
00108  *                      R T _ V L B L O C K _ F R E E
00109  */
00110 void
00111 rt_vlblock_free(struct bn_vlblock *vbp)
00112 {
00113         int     i;
00114 
00115         BN_CK_VLBLOCK(vbp);
00116         for( i=0; i < vbp->nused; i++ )  {
00117                 /* Release any remaining vlist storage */
00118                 if( vbp->rgb[i] == 0 )  continue;
00119                 if( BU_LIST_IS_EMPTY( &(vbp->head[i]) ) )  continue;
00120                 BN_FREE_VLIST( vbp->free_vlist_hd, &(vbp->head[i]) );
00121         }
00122 
00123         bu_free( (char *)(vbp->head), "head[]" );
00124         bu_free( (char *)(vbp->rgb), "rgb[]" );
00125         bu_free( (char *)vbp, "bn_vlblock" );
00126 }
00127 
00128 /*
00129  *                      R T _ V L B L O C K _ F I N D
00130  */
00131 struct bu_list *
00132 rt_vlblock_find(struct bn_vlblock *vbp, int r, int g, int b)
00133 {
00134         long    new;
00135         int     n;
00136         int     omax;           /* old max */
00137 
00138         BN_CK_VLBLOCK(vbp);
00139 
00140         new = ((r&0xFF)<<16)|((g&0xFF)<<8)|(b&0xFF);
00141 
00142         for( n=0; n < vbp->nused; n++ )  {
00143                 if( vbp->rgb[n] == new )
00144                         return( &(vbp->head[n]) );
00145         }
00146         if( vbp->nused < vbp->max )  {
00147                 /* Allocate empty slot */
00148                 n = vbp->nused++;
00149                 vbp->rgb[n] = new;
00150                 return( &(vbp->head[n]) );
00151         }
00152 
00153         /************** enlarge the table ****************/
00154         omax = vbp->max;
00155         vbp->max *= 2;
00156 
00157         /* Look for empty lists and mark for use below. */
00158         for (n=0; n < omax; n++)
00159                 if (BU_LIST_IS_EMPTY(&vbp->head[n]))
00160                         vbp->head[n].forw = BU_LIST_NULL;
00161 
00162         vbp->head = (struct bu_list *)bu_realloc((genptr_t)vbp->head,
00163                                                  vbp->max * sizeof(struct bu_list),
00164                                                  "head[]");
00165         vbp->rgb = (long *)bu_realloc((genptr_t)vbp->rgb,
00166                                       vbp->max * sizeof(long),
00167                                       "rgb[]");
00168 
00169         /* re-initialize pointers in lower half */
00170         for (n=0; n < omax; n++) {
00171                 /*
00172                  * Check to see if list is empty
00173                  * (i.e. yellow and/or white are not used).
00174                  * Note - we can't use BU_LIST_IS_EMPTY here because
00175                  * the addresses of the list heads have possibly changed.
00176                  */
00177                 if (vbp->head[n].forw == BU_LIST_NULL) {
00178                         vbp->head[n].forw = &vbp->head[n];
00179                         vbp->head[n].back = &vbp->head[n];
00180                 } else {
00181                         vbp->head[n].forw->back = &vbp->head[n];
00182                         vbp->head[n].back->forw = &vbp->head[n];
00183                 }
00184         }
00185 
00186         /* initialize upper half of memory */
00187         for (n=omax; n < vbp->max; n++) {
00188                 vbp->rgb[n] = 0;
00189                 BU_LIST_INIT(&vbp->head[n]);
00190         }
00191 
00192         /* here we go again */
00193         return rt_vlblock_find(vbp, r, g, b);
00194 }
00195 
00196 /************************************************************************
00197  *                                                                      *
00198  *                      Generic BN_VLIST routines                       *
00199  *                                                                      *
00200  ************************************************************************/
00201 const char *rt_vlist_cmd_descriptions[] = {
00202         "line move ",
00203         "line draw ",
00204         "poly start",
00205         "poly move ",
00206         "poly draw ",
00207         "poly end  ",
00208         "poly vnorm",
00209         "**unknown*"
00210 };
00211 
00212 /*
00213  *                      R T _ C K _ V L I S T
00214  *
00215  *  Validate an bn_vlist chain for having reasonable
00216  *  values inside.  Calls bu_bomb() if not.
00217  *
00218  *  Returns -
00219  *      npts    Number of point/command sets in use.
00220  */
00221 int
00222 rt_ck_vlist( const struct bu_list *vhead )
00223 {
00224         register struct bn_vlist        *vp;
00225         int                     npts = 0;
00226 
00227         for( BU_LIST_FOR( vp, bn_vlist, vhead ) )  {
00228                 register int    i;
00229                 register int    nused = vp->nused;
00230                 register int    *cmd = vp->cmd;
00231                 register point_t *pt = vp->pt;
00232 
00233                 BN_CK_VLIST( vp );
00234                 npts += nused;
00235 
00236                 for( i = 0; i < nused; i++,cmd++,pt++ )  {
00237                         register int    j;
00238 
00239                         for( j=0; j < 3; j++ )  {
00240                                 /*
00241                                  *  If (*pt)[j] is an IEEE NaN, then all comparisons
00242                                  *  between it and any genuine number will return
00243                                  *  FALSE.  This test is formulated so that NaN
00244                                  *  values will activate the "else" clause.
00245                                  */
00246                                 if( (*pt)[j] > -INFINITY && (*pt)[j] < INFINITY )  {
00247                                         /* Number is good */
00248                                 } else {
00249                                         bu_log("  %s (%g, %g, %g)\n",
00250                                                 rt_vlist_cmd_descriptions[*cmd],
00251                                                 V3ARGS( *pt ) );
00252                                         bu_bomb("rt_ck_vlist() bad coordinate value\n");
00253                                 }
00254                                 /* XXX Need a define for largest command number */
00255                                 if( *cmd < 0 || *cmd > BN_VLIST_POLY_VERTNORM )  {
00256                                         bu_log("cmd = x%x (%d.)\n", *cmd, *cmd);
00257                                         bu_bomb("rt_ck_vlist() bad vlist command\n");
00258                                 }
00259                         }
00260                 }
00261         }
00262         return npts;
00263 }
00264 
00265 /*
00266  *                      R T _ V L I S T _ C O P Y
00267  *
00268  *  Duplicate the contents of a vlist.  Note that the copy may be more
00269  *  densely packed than the source.
00270  */
00271 void
00272 rt_vlist_copy( struct bu_list *dest, const struct bu_list *src )
00273 {
00274         struct bn_vlist *vp;
00275 
00276         for( BU_LIST_FOR( vp, bn_vlist, src ) )  {
00277                 register int    i;
00278                 register int    nused = vp->nused;
00279                 register int    *cmd = vp->cmd;
00280                 register point_t *pt = vp->pt;
00281                 for( i = 0; i < nused; i++,cmd++,pt++ )  {
00282                         BN_ADD_VLIST( &rt_g.rtg_vlfree, dest, *pt, *cmd );
00283                 }
00284         }
00285 }
00286 
00287 /*
00288  *                      B N _ V L I S T _ C L E A N U P
00289  *
00290  *  The macro RT_FREE_VLIST() simply appends to the list &rt_g.rtg_vlfree.
00291  *  Now, give those structures back to bu_free().
00292  */
00293 void
00294 bn_vlist_cleanup( struct bu_list *hd )
00295 {
00296         register struct bn_vlist        *vp;
00297 
00298         if (BU_LIST_UNINITIALIZED( hd ))  {
00299                 BU_LIST_INIT( hd );
00300                 return;
00301         }
00302 
00303         while( BU_LIST_WHILE( vp, bn_vlist, hd ) )  {
00304                 BN_CK_VLIST( vp );
00305                 BU_LIST_DEQUEUE( &(vp->l) );
00306                 bu_free( (char *)vp, "bn_vlist" );
00307         }
00308 }
00309 
00310 /*  XXX This needs to remain a LIBRT function. */
00311 void
00312 rt_vlist_cleanup(void)
00313 {
00314         bn_vlist_cleanup( &rt_g.rtg_vlfree );
00315 }
00316 
00317 /*
00318  *                      B N _ V L I S T _ R P P
00319  *
00320  *  Given an RPP, draw the outline of it into the vlist.
00321  */
00322 void
00323 bn_vlist_rpp( struct bu_list *hd, const point_t minn, const point_t maxx )
00324 {
00325         point_t p;
00326 
00327         VSET( p, minn[X], minn[Y], minn[Z] );
00328         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_MOVE )
00329 
00330         /* first side */
00331         VSET( p, minn[X], maxx[Y], minn[Z] );
00332         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00333         VSET( p, minn[X], maxx[Y], maxx[Z] );
00334         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00335         VSET( p, minn[X], minn[Y], maxx[Z] );
00336         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00337         VSET( p, minn[X], minn[Y], minn[Z] );
00338         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00339 
00340         /* across */
00341         VSET( p, maxx[X], minn[Y], minn[Z] );
00342         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00343 
00344         /* second side */
00345         VSET( p, maxx[X], maxx[Y], minn[Z] );
00346         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00347         VSET( p, maxx[X], maxx[Y], maxx[Z] );
00348         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00349         VSET( p, maxx[X], minn[Y], maxx[Z] );
00350         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00351         VSET( p, maxx[X], minn[Y], minn[Z] );
00352         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00353 
00354         /* front edge */
00355         VSET( p, minn[X], maxx[Y], minn[Z] );
00356         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_MOVE )
00357         VSET( p, maxx[X], maxx[Y], minn[Z] );
00358         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00359 
00360         /* bottom back */
00361         VSET( p, minn[X], minn[Y], maxx[Z] );
00362         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_MOVE )
00363         VSET( p, maxx[X], minn[Y], maxx[Z] );
00364         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00365 
00366         /* top back */
00367         VSET( p, minn[X], maxx[Y], maxx[Z] );
00368         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_MOVE )
00369         VSET( p, maxx[X], maxx[Y], maxx[Z] );
00370         BN_ADD_VLIST( &rt_g.rtg_vlfree, hd, p, BN_VLIST_LINE_DRAW )
00371 }
00372 
00373 /************************************************************************
00374  *                                                                      *
00375  *                      Binary VLIST import/export routines             *
00376  *                                                                      *
00377  ************************************************************************/
00378 
00379 /*
00380  *                      R T _ V L I S T _ E X P O R T
00381  *
00382  *  Convert a vlist chain into a blob of network-independent binary,
00383  *  for transmission to another machine.
00384  *  The result is stored in a vls string, so that both the address
00385  *  and length are available conveniently.
00386  */
00387 void
00388 rt_vlist_export(struct bu_vls *vls, struct bu_list *hp, const char *name)
00389 {
00390         register struct bn_vlist        *vp;
00391         int             nelem;
00392         int             namelen;
00393         int             nbytes;
00394         unsigned char   *buf;
00395         unsigned char   *bp;
00396 
00397         BU_CK_VLS(vls);
00398 
00399         /* Count number of element in the vlist */
00400         nelem = 0;
00401         for( BU_LIST_FOR( vp, bn_vlist, hp ) )  {
00402                 nelem += vp->nused;
00403         }
00404 
00405         /* Build output buffer for binary transmission
00406          * nelem[4], String[n+1], cmds[nelem*1], pts[3*nelem*8]
00407          */
00408         namelen = strlen(name)+1;
00409         nbytes = namelen + 4 + nelem * (1+3*8) + 2;
00410 
00411         bu_vls_setlen( vls, nbytes );
00412         buf = (unsigned char *)bu_vls_addr(vls);
00413         bp = bu_plong( buf, nelem );
00414         strncpy( (char *)bp, name, namelen );
00415         bp += namelen;
00416 
00417         /* Output cmds, as bytes */
00418         for( BU_LIST_FOR( vp, bn_vlist, hp ) )  {
00419                 register int    i;
00420                 register int    nused = vp->nused;
00421                 register int    *cmd = vp->cmd;
00422                 for( i = 0; i < nused; i++ )  {
00423                         *bp++ = *cmd++;
00424                 }
00425         }
00426 
00427         /* Output points, as three 8-byte doubles */
00428         for( BU_LIST_FOR( vp, bn_vlist, hp ) )  {
00429                 register int    i;
00430                 register int    nused = vp->nused;
00431                 register point_t *pt = vp->pt;
00432                 for( i = 0; i < nused; i++,pt++ )  {
00433                         htond( bp, (unsigned char *)pt, 3 );
00434                         bp += 3*8;
00435                 }
00436         }
00437 }
00438 
00439 /*
00440  *                      R T _ V L I S T _ I M P O R T
00441  *
00442  *  Convert a blob of network-independent binary prepared by vls_vlist()
00443  *  and received from another machine, into a vlist chain.
00444  */
00445 void
00446 rt_vlist_import(struct bu_list *hp, struct bu_vls *namevls, const unsigned char *buf)
00447 {
00448         register const unsigned char    *bp;
00449         const unsigned char             *pp;            /* point pointer */
00450         int             nelem;
00451         int             namelen;
00452         int             i;
00453         point_t         point;
00454 
00455         BU_CK_VLS(namevls);
00456 
00457         nelem = bu_glong( buf );
00458         bp = buf+4;
00459 
00460         namelen = strlen((char *)bp)+1;
00461         bu_vls_strncpy( namevls, (char *)bp, namelen );
00462         bp += namelen;
00463 
00464         pp = bp + nelem*1;
00465 
00466         for( i=0; i < nelem; i++ )  {
00467                 int     cmd;
00468 
00469                 cmd = *bp++;
00470                 ntohd( (unsigned char *)point, pp, 3 );
00471                 pp += 3*8;
00472                 BN_ADD_VLIST( &rt_g.rtg_vlfree, hp, point, cmd );
00473         }
00474 }
00475 
00476 /************************************************************************
00477  *                                                                      *
00478  *                      UNIX-Plot VLIST import/export routines          *
00479  *                                                                      *
00480  ************************************************************************/
00481 
00482 /*
00483  *                      R T _ P L O T _ V L B L O C K
00484  *
00485  *  Output a bn_vlblock object in extended UNIX-plot format,
00486  *  including color.
00487  */
00488 void
00489 rt_plot_vlblock(FILE *fp, const struct bn_vlblock *vbp)
00490 {
00491         int     i;
00492 
00493         BN_CK_VLBLOCK(vbp);
00494 
00495         for( i=0; i < vbp->nused; i++ )  {
00496                 if( vbp->rgb[i] == 0 )  continue;
00497                 if( BU_LIST_IS_EMPTY( &(vbp->head[i]) ) )  continue;
00498                 pl_color( fp,
00499                         (vbp->rgb[i]>>16) & 0xFF,
00500                         (vbp->rgb[i]>> 8) & 0xFF,
00501                         (vbp->rgb[i]    ) & 0xFF );
00502                 rt_vlist_to_uplot( fp, &(vbp->head[i]) );
00503         }
00504 }
00505 
00506 /*
00507  *                      R T _ V L I S T _ T O _ U P L O T
00508  *
00509  *  Output a vlist as an extended 3-D floating point UNIX-Plot file.
00510  *  You provide the file.
00511  *  Uses libplot3 routines to create the UNIX-Plot output.
00512  */
00513 void
00514 rt_vlist_to_uplot(FILE *fp, const struct bu_list *vhead)
00515 {
00516         register struct bn_vlist        *vp;
00517 
00518         for( BU_LIST_FOR( vp, bn_vlist, vhead ) )  {
00519                 register int            i;
00520                 register int            nused = vp->nused;
00521                 register const int      *cmd = vp->cmd;
00522                 register point_t         *pt = vp->pt;
00523 
00524                 for( i = 0; i < nused; i++,cmd++,pt++ )  {
00525                         switch( *cmd )  {
00526                         case BN_VLIST_POLY_START:
00527                                 break;
00528                         case BN_VLIST_POLY_MOVE:
00529                         case BN_VLIST_LINE_MOVE:
00530                                 pdv_3move( fp, *pt );
00531                                 break;
00532                         case BN_VLIST_POLY_DRAW:
00533                         case BN_VLIST_POLY_END:
00534                         case BN_VLIST_LINE_DRAW:
00535                                 pdv_3cont( fp, *pt );
00536                                 break;
00537                         default:
00538                                 bu_log("rt_vlist_to_uplot: unknown vlist cmd x%x\n",
00539                                         *cmd );
00540                         }
00541                 }
00542         }
00543 }
00544 
00545 
00546 #define TBAD    0       /* no such command */
00547 #define TNONE   1       /* no arguments */
00548 #define TSHORT  2       /* Vax 16-bit short */
00549 #define TIEEE   3       /* IEEE 64-bit floating */
00550 #define TCHAR   4       /* unsigned chars */
00551 #define TSTRING 5       /* linefeed terminated string */
00552 
00553 struct uplot {
00554         int     targ;           /* type of args */
00555         int     narg;           /* number or args */
00556         char    desc[14];       /* description */
00557 };
00558 static const struct uplot rt_uplot_error = { 0, 0, "error" };
00559 static const struct uplot rt_uplot_letters[] = {
00560 /*A*/   { 0, 0, "" },
00561 /*B*/   { 0, 0, "" },
00562 /*C*/   { TCHAR, 3, "color" },
00563 /*D*/   { 0, 0, "" },
00564 /*E*/   { 0, 0, "" },
00565 /*F*/   { TNONE, 0, "flush" },
00566 /*G*/   { 0, 0, "" },
00567 /*H*/   { 0, 0, "" },
00568 /*I*/   { 0, 0, "" },
00569 /*J*/   { 0, 0, "" },
00570 /*K*/   { 0, 0, "" },
00571 /*L*/   { TSHORT, 6, "3line" },
00572 /*M*/   { TSHORT, 3, "3move" },
00573 /*N*/   { TSHORT, 3, "3cont" },
00574 /*O*/   { TIEEE, 3, "d_3move" },
00575 /*P*/   { TSHORT, 3, "3point" },
00576 /*Q*/   { TIEEE, 3, "d_3cont" },
00577 /*R*/   { 0, 0, "" },
00578 /*S*/   { TSHORT, 6, "3space" },
00579 /*T*/   { 0, 0, "" },
00580 /*U*/   { 0, 0, "" },
00581 /*V*/   { TIEEE, 6, "d_3line" },
00582 /*W*/   { TIEEE, 6, "d_3space" },
00583 /*X*/   { TIEEE, 3, "d_3point" },
00584 /*Y*/   { 0, 0, "" },
00585 /*Z*/   { 0, 0, "" },
00586 /*[*/   { 0, 0, "" },
00587 /*\*/   { 0, 0, "" },
00588 /*]*/   { 0, 0, "" },
00589 /*^*/   { 0, 0, "" },
00590 /*_*/   { 0, 0, "" },
00591 /*`*/   { 0, 0, "" },
00592 /*a*/   { TSHORT, 6, "arc" },
00593 /*b*/   { 0, 0, "" },
00594 /*c*/   { TSHORT, 3, "circle" },
00595 /*d*/   { 0, 0, "" },
00596 /*e*/   { TNONE, 0, "erase" },
00597 /*f*/   { TSTRING, 1, "linmod" },
00598 /*g*/   { 0, 0, "" },
00599 /*h*/   { 0, 0, "" },
00600 /*i*/   { TIEEE, 3, "d_circle" },
00601 /*j*/   { 0, 0, "" },
00602 /*k*/   { 0, 0, "" },
00603 /*l*/   { TSHORT, 4, "line" },
00604 /*m*/   { TSHORT, 2, "move" },
00605 /*n*/   { TSHORT, 2, "cont" },
00606 /*o*/   { TIEEE, 2, "d_move" },
00607 /*p*/   { TSHORT, 2, "point" },
00608 /*q*/   { TIEEE, 2, "d_cont" },
00609 /*r*/   { TIEEE, 6, "d_arc" },
00610 /*s*/   { TSHORT, 4, "space" },
00611 /*t*/   { TSTRING, 1, "label" },
00612 /*u*/   { 0, 0, "" },
00613 /*v*/   { TIEEE, 4, "d_line" },
00614 /*w*/   { TIEEE, 4, "d_space" },
00615 /*x*/   { TIEEE, 2, "d_point" },
00616 /*y*/   { 0, 0, "" },
00617 /*z*/   { 0, 0, "" }
00618 };
00619 
00620 /*
00621  *      getshort                Read VAX-order 16-bit number
00622  */
00623 static int
00624 getshort(FILE *fp)
00625 {
00626         register long   v, w;
00627 
00628         v = getc(fp);
00629         v |= (getc(fp)<<8);     /* order is important! */
00630 
00631         /* worry about sign extension - sigh */
00632         if( v <= 0x7FFF )  return(v);
00633         w = -1;
00634         w &= ~0x7FFF;
00635         return( w | v );
00636 }
00637 
00638 static void
00639 rt_uplot_get_args(FILE *fp, const struct uplot *up, char *carg, fastf_t *arg )
00640 {
00641         int     i, j;
00642         int     cc;
00643         char    inbuf[8];
00644 
00645         for ( i = 0; i < up->narg; i++ ) {
00646             switch( up->targ ) {
00647             case TSHORT:
00648                 arg[i] = getshort( fp );
00649                 break;
00650             case TIEEE:
00651                 fread(inbuf, 8, 1, fp);
00652                 ntohd( (unsigned char *)&arg[i],
00653                        (unsigned char *)inbuf, 1 );
00654                 break;
00655             case TSTRING:
00656                 j = 0;
00657                 while (!feof(fp) &&
00658                        (cc = getc(fp)) != '\n')
00659                     carg[j++] = cc;
00660                 carg[j] = '\0';
00661                 break;
00662             case TCHAR:
00663                 carg[i] = getc(fp);
00664                 arg[i] = 0;
00665                 break;
00666             case TNONE:
00667             default:
00668                 arg[i] = 0;     /* ? */
00669                 break;
00670             }
00671         }
00672 }
00673 
00674 static void
00675 rt_uplot_get_text_args(FILE *fp, const struct uplot *up, char *carg, fastf_t *arg )
00676 {
00677         int     i, j;
00678         int     cc;
00679         char    inbuf[8];
00680 
00681         for ( i = 0; i < up->narg; i++ ) {
00682             switch ( up->targ ) {
00683             case TSHORT:
00684                 fscanf(fp, "%lf", &arg[i]);
00685                 break;
00686             case TIEEE:
00687                 fscanf(fp, "%lf", &arg[i]);
00688                 break;
00689             case TSTRING:
00690                 fscanf(fp, "%s\n", &carg[0]);
00691                 break;
00692             case TCHAR:
00693                 fscanf(fp, "%u", &carg[i]);
00694                 arg[i] = 0;
00695                 break;
00696             case TNONE:
00697             default:
00698                 arg[i] = 0;     /* ? */
00699                 break;
00700             }
00701         }
00702 }
00703 
00704 int
00705 rt_process_uplot_value(register struct bu_list **vhead,
00706                        struct bn_vlblock *vbp,
00707                        FILE *fp,
00708                        register int c,
00709                        double char_size,
00710                        int mode)
00711 {
00712         mat_t                   mat;
00713         const struct uplot      *up;
00714         char                    carg[256];
00715         fastf_t                 arg[6];
00716         vect_t                  a,b;
00717         point_t                 last_pos;
00718         static point_t          lpnt;           /* last point of a move/draw series */
00719         static int              moved = 0;      /* moved since color change */
00720 
00721         /* look it up */
00722         if( c < 'A' || c > 'z' ) {
00723                 up = &rt_uplot_error;
00724         } else {
00725                 up = &rt_uplot_letters[ c - 'A' ];
00726         }
00727 
00728         if( up->targ == TBAD ) {
00729                 fprintf( stderr, "Lee : Bad command '%c' (0x%02x)\n", c, c );
00730                 return(-1);
00731         }
00732 
00733         if( up->narg > 0 )  {
00734             if (mode == PL_OUTPUT_MODE_BINARY)
00735                 rt_uplot_get_args( fp, up, carg, arg );
00736             else
00737                 rt_uplot_get_text_args( fp, up, carg, arg );
00738         }
00739 
00740         switch( c ) {
00741         case 's':
00742         case 'w':
00743         case 'S':
00744         case 'W':
00745                 /* Space commands, do nothing. */
00746                 break;
00747         case 'm':
00748         case 'o':
00749                 /* 2-D move */
00750                 arg[Z] = 0;
00751                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_MOVE );
00752                 VMOVE(lpnt, arg);
00753                 moved = 1;
00754                 break;
00755         case 'M':
00756         case 'O':
00757                 /* 3-D move */
00758                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_MOVE );
00759                 VMOVE(lpnt, arg);
00760                 moved = 1;
00761                 break;
00762         case 'n':
00763         case 'q':
00764                 /*
00765                  * If no move command was issued since the last color change,
00766                  * insert one now using the last point from a move/draw.
00767                  */
00768                 if (!moved) {
00769                         BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, lpnt, BN_VLIST_LINE_MOVE );
00770                         moved = 1;
00771                 }
00772 
00773                 /* 2-D draw */
00774                 arg[Z] = 0;
00775                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_DRAW );
00776                 VMOVE(lpnt, arg);
00777                 break;
00778         case 'N':
00779         case 'Q':
00780                 /*
00781                  * If no move command was issued since the last color change,
00782                  * insert one now using the last point from a move/draw.
00783                  */
00784                 if (!moved) {
00785                         BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, lpnt, BN_VLIST_LINE_MOVE );
00786                         moved = 1;
00787                 }
00788 
00789                 /* 3-D draw */
00790                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_DRAW );
00791                 VMOVE(lpnt, arg);
00792                 break;
00793         case 'l':
00794         case 'v':
00795                 /* 2-D line */
00796                 VSET( a, arg[0], arg[1], 0.0 );
00797                 VSET( b, arg[2], arg[3], 0.0 );
00798                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, a, BN_VLIST_LINE_MOVE );
00799                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, b, BN_VLIST_LINE_DRAW );
00800                 break;
00801         case 'L':
00802         case 'V':
00803                 /* 3-D line */
00804                 VSET( a, arg[0], arg[1], arg[2] );
00805                 VSET( b, arg[3], arg[4], arg[5] );
00806                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, a, BN_VLIST_LINE_MOVE );
00807                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, b, BN_VLIST_LINE_DRAW );
00808                 break;
00809         case 'p':
00810         case 'x':
00811                 /* 2-D point */
00812                 arg[Z] = 0;
00813                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_MOVE );
00814                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_DRAW );
00815                 break;
00816         case 'P':
00817         case 'X':
00818                 /* 3-D point */
00819                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_MOVE );
00820                 BN_ADD_VLIST( vbp->free_vlist_hd, *vhead, arg, BN_VLIST_LINE_DRAW );
00821                 break;
00822         case 'C':
00823                 /* Color */
00824                 *vhead = rt_vlblock_find( vbp,
00825                         carg[0], carg[1], carg[2] );
00826                 moved = 0;
00827                 break;
00828         case 't':
00829                 /* Text string */
00830                 MAT_IDN(mat);
00831                 if( BU_LIST_NON_EMPTY( *vhead ) )  {
00832                         struct bn_vlist *vlp;
00833                         /* Use coordinates of last op */
00834                         vlp = BU_LIST_LAST( bn_vlist, *vhead );
00835                         VMOVE( last_pos, vlp->pt[vlp->nused-1] );
00836                 } else {
00837                         VSETALL( last_pos, 0 );
00838                 }
00839                 bn_vlist_3string( *vhead, vbp->free_vlist_hd, carg, last_pos, mat, char_size );
00840                 break;
00841         }
00842 
00843         return(0);
00844 }
00845 
00846 /*
00847  *                      R T _ U P L O T _ T O _ V L I S T
00848  *
00849  *  Read a BRL-style 3-D UNIX-plot file into a vector list.
00850  *  For now, discard color information, only extract vectors.
00851  *  This might be more naturally located in mged/plot.c
00852  */
00853 int
00854 rt_uplot_to_vlist(struct bn_vlblock *vbp, register FILE *fp, double char_size, int mode)
00855 {
00856         struct bu_list  *vhead;
00857         register int    c;
00858 
00859         vhead = rt_vlblock_find( vbp, 0xFF, 0xFF, 0x00 );       /* Yellow */
00860 
00861 #if 1
00862         while(!feof(fp) && (c=getc(fp)) != EOF ) {
00863             int ret;
00864 
00865 #else
00866         while( (c = getc(fp)) != EOF ) {
00867                int ret;
00868 #endif
00869 
00870                /* pass the address of vhead so it can be updated */
00871                ret = rt_process_uplot_value( &vhead,
00872                                              vbp,
00873                                              fp,
00874                                              c,
00875                                              char_size,
00876                                              mode );
00877                if ( ret )
00878                   return(ret);
00879         }
00880 
00881         return(0);
00882 }
00883 
00884 /*
00885  *                      R T _ L A B E L _ V L I S T _ V E R T S
00886  *
00887  *  Used by MGED's "labelvert" command.
00888  */
00889 void
00890 rt_label_vlist_verts(struct bn_vlblock *vbp, struct bu_list *src, fastf_t *mat, double sz, double mm2local)
00891 {
00892         struct bn_vlist *vp;
00893         struct bu_list  *vhead;
00894         char            label[256];
00895 
00896         vhead = rt_vlblock_find( vbp, 255, 255, 255 );  /* white */
00897 
00898         for( BU_LIST_FOR( vp, bn_vlist, src ) )  {
00899                 register int    i;
00900                 register int    nused = vp->nused;
00901                 register int    *cmd = vp->cmd;
00902                 register point_t *pt = vp->pt;
00903                 for( i = 0; i < nused; i++,cmd++,pt++ )  {
00904                         /* XXX Skip polygon markers? */
00905                         sprintf( label, " %g, %g, %g",
00906                                 (*pt)[0]*mm2local, (*pt)[1]*mm2local, (*pt)[2]*mm2local );
00907                         bn_vlist_3string( vhead, vbp->free_vlist_hd, label, (*pt), mat, sz );
00908                 }
00909         }
00910 }
00911 
00912 /*
00913  * Local Variables:
00914  * mode: C
00915  * tab-width: 8
00916  * c-basic-offset: 4
00917  * indent-tabs-mode: t
00918  * End:
00919  * ex: shiftwidth=4 tabstop=8
00920  */

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