tplot.c

Go to the documentation of this file.
00001 /*                         T P L O T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-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 /** \addtogroup plot */
00022 /*@{*/
00023 /** @file tplot.c
00024  *@brief
00025  *      This routine is designed to simplify the creation of
00026  *  X,Y plots for user.
00027  *
00028  *                      George W. Hartwig, Jr.
00029  *                              16 March 1979
00030  *
00031  *      This routine is designed to simplify the creation of
00032  * X,Y plots for user. The user need only furnish this program
00033  * the data arrays to be plotted, the lengths of the respective
00034  * axis, titles for the axis, and the point on the page corresponding
00035  * to data point (0,0).
00036  *      The program will then do everything else required to make
00037  * the plot appear on the user's terminal including scaling of the
00038  * data, centering of the titles and positioning on the page.
00039  *
00040  * where
00041  * -    int xp,yp       page point corresponding to (0,0) of the data
00042  * -    int xl,yl       lengths of the x and y axis, respectively
00043  * -    char xtitle[], ytitle[] titles for the axis
00044  * -    float x[], y[]  the floating point data arrays
00045  * -    int n           the number of points in the data arrays
00046  *
00047  *              R E V I S I O N  H I S T O R Y
00048  *
00049  *      WHO     WHEN            WHAT
00050  *      GWH     5/21/79         Modified ftoa so that nos. < e-15
00051  *                              map to zero.
00052  *      GWH     6/29/79         Changed the axis drawing loops to
00053  *                              prevent a one tic mark overrun.
00054  *      GWH     7/10/79         Subtracted one from n to allow for the
00055  *                              fact that fortran arrays start at one
00056  *                              and not zero as with c.
00057  */
00058 
00059 
00060 #include "common.h"
00061 
00062 /* system headers */
00063 #include <stdio.h>
00064 #ifdef HAVE_STRING_H
00065 #  include <string.h>
00066 #else
00067 #  include <strings.h>
00068 #endif
00069 #include <math.h>
00070 
00071 /* interface headers */
00072 #include "machine.h"
00073 #include "vmath.h"
00074 #include "plot3.h"
00075 
00076 
00077 #define TIC             100
00078 #define REF_WIDTH       0.857143
00079 #define NUM_DISTANCE    250
00080 #define LAB_LNGTH       860
00081 
00082 void tp_ftoa(float x, char *s);
00083 void tp_fixsc(float *x, int npts, float size, float *xs, float *xmin, float *xmax, float *dx);
00084 void tp_sep(float x, float *coef, int *ex);
00085 double tp_ipow(double x, int n);
00086 
00087 
00088 /**
00089  * @param fp file pointer
00090  * @param xtitle title for the x axis
00091  * @param ytitle title for the y axis
00092  * @param xp is the x page point desired to be (0,0) for plot
00093  * @param yp is the y page point desired to be (0,0) for plot
00094  * @param xl is the length of the x axis
00095  * @param yl is the length of the y axis
00096  * @param n is the number of points
00097  * @param cscale is the character scale factor
00098  * @param x the x data
00099  * @param y the y data
00100  */
00101 void
00102 tp_plot(FILE *fp,
00103         int xp,
00104         int yp,
00105         int xl,
00106         int yl,
00107         char *xtitle,
00108         char *ytitle,
00109         float *x,
00110         float *y,
00111         int n,
00112         double cscale)
00113 {
00114     int  ddx, ddy, xend, yend, xpen, ypen;
00115     float fxl, fyl, xs, ys, xmin, xmax, ymin, ymax, dx, dy;
00116     float lab;
00117     int xtics, ytics, i, xtl, ytl, j;
00118     int ix[101], iy[101], isave;
00119     char str[32];
00120 
00121     if( xl == 0 ){
00122         j = 0;
00123         goto loop;
00124     }
00125     fxl = xl/1000.0;
00126     fyl = yl/1000.0;
00127     n -= 1; /* allow for the fact that fortran starts arrays at 1 */
00128     tp_fixsc (x, n, fxl, &xs, &xmin, &xmax, &dx);
00129     tp_fixsc (y, n, fyl, &ys, &ymin, &ymax, &dy);
00130     ddx = dx*xs;
00131     ddy = dy*ys;
00132     xtics = LAB_LNGTH / ddx + 1.0;
00133     ytics = 500/ddy + 1.0;
00134     xend = xl+xp;
00135     xpen = xp;
00136 
00137     pl_move(fp, xpen, yp-TIC);
00138     pl_cont(fp, xpen,yp);
00139 
00140     /* label first tic */
00141     lab = xmin;
00142     sprintf( str, "%3.3g", xmin );
00143     tp_2symbol( fp, str, (double)(xpen-171),(double)(yp-TIC-NUM_DISTANCE), cscale, 0.0);
00144 
00145     i = 0;
00146     while((xpen+ddx)<=xend){
00147         i++;
00148         xpen += ddx;
00149         pl_line( fp, xpen, yp, xpen, yp-TIC );
00150         /* while here label this tic mark if no overlapping will occur */
00151         lab += dx;
00152         /* need if test here to check for overlap */
00153         if( (i%xtics) == 0){
00154             sprintf( str, "%3.3g", lab );
00155             tp_2symbol( fp, str, (double)(xpen-171), (double)(yp-TIC-NUM_DISTANCE), cscale, 0.0);
00156         }
00157     }
00158 
00159     /* insert axis label here */
00160     xtl = xp+(xl - strlen(xtitle)*cscale)/2;
00161     ytl = yp - 8 * cscale;
00162     tp_2symbol( fp, xtitle,(double)xtl, (double)ytl, 100.0, 0.0);
00163     yend = yl+yp;
00164     ypen= yp;
00165     pl_line( fp, xp-TIC, ypen, xp, ypen );
00166 
00167     /* draw first y label */
00168     lab = ymin;
00169     sprintf( str, "%3.3g", lab );
00170     tp_2symbol( fp,str, (double)(xp-TIC-LAB_LNGTH-NUM_DISTANCE), (double)ypen, cscale, 0.0);
00171 
00172     i=0;
00173     while((ypen+ddy)<=yend){
00174         i++;
00175         ypen += ddy;
00176         pl_line( fp, xp, ypen, xp-TIC, ypen );
00177         /* label the y-axis now, nicely */
00178         lab += dy;
00179         if(( i%ytics) ==0){
00180             sprintf( str, "%3.3g", lab );
00181             tp_2symbol( fp,str, (double)(xp-TIC-LAB_LNGTH-NUM_DISTANCE), (double)ypen, cscale, 0.0);
00182         }
00183     }
00184 
00185     /* insert y-axis title here */
00186     xtl= xp-1500;
00187     ytl= yp + (yl - strlen(ytitle)*cscale)/2 ;
00188     tp_2symbol( fp,ytitle,(double)xtl,(double)ytl,100.0,90.0);
00189 
00190     /* now at long last plot the data */
00191     j = 0;
00192 
00193  loop:
00194     if( n <= 100 ) {
00195         isave = n-1;
00196     } else {
00197         isave = 100;
00198         n -= 101;
00199     }
00200 
00201     if(j == 0){
00202         ix[0] = (x[j] - xmin)*xs + xp;
00203         iy[0] = (y[j] - ymin)*ys + yp;
00204         j++;
00205     } else {
00206         ix[0] = (x[j-1] - xmin)*xs + xp;
00207         iy[0] = (y[j-1] - ymin)*ys + yp;
00208     }
00209 
00210     i = 1;
00211     while( i <= isave ){
00212         ix[i] = (x[j] - xmin)*xs + xp;
00213         iy[i] = (y[j] - ymin)*ys + yp;
00214         i++;
00215         j++;
00216     }
00217     tp_i2list( fp, ix, iy, isave+1 );
00218     if( isave == 100 ) {
00219         goto loop;
00220     }
00221 }
00222 
00223 
00224 /**                     T P _ F T O A
00225  * @brief
00226  * This routine converts a floating point number into a string
00227  * of ascii characters of the form "sX.XXXesXX". The string is
00228  * null terminated.
00229  */
00230 void
00231 tp_ftoa(float x, char *s)
00232 {
00233     int ex,tmp;
00234     float coef;
00235     char esgn, nsgn;
00236     char i;
00237 
00238     tp_sep(x, &coef, &ex);
00239     if( ex < -15 ){
00240         ex = 0;
00241         *s++ = '0';
00242         *s++ = '.';
00243         *s++ = '0';
00244         *s++ = '0';
00245         *s++ = '0';
00246         *s++ = 'e';
00247         *s++ = '+';
00248         *s++ = '0';
00249         *s++ = '0';
00250         *s   =  0 ;
00251         return;
00252     }
00253 
00254     if(ex < 0){
00255         esgn = '-';
00256         ex = -ex;
00257     } else {
00258         esgn = '+';
00259     }
00260 
00261     if( coef < 0.0){
00262         nsgn = '-';
00263         coef = -coef;
00264     } else {
00265         nsgn = ' ';
00266     }
00267     *s++ = nsgn;
00268 
00269     /* load the first numeral and the decimal point */
00270     tmp = coef;
00271     *s++ = tmp + '0';
00272     coef = (coef - tmp)*10.0;
00273     *s++ = '.';
00274 
00275     /* now do the three after the decimal */
00276     for( i=1 ; i<=3 ; ++i){
00277         tmp = coef;
00278         coef = (coef - tmp)*10.0;
00279         *s++ = tmp + '0';
00280     }
00281 
00282     /* put the e in */
00283     *s++ = 'e';
00284 
00285     /* the sign for the exponent */
00286     *s++ = esgn;
00287 
00288     /* and the exponent */
00289     if( ex < 0)
00290         ex = -ex;
00291 
00292     if( ex < 10 ){
00293         *s++ = '0';
00294         *s++ = ex + '0';
00295     } else{
00296         tmp = ex/10;
00297         *s++ = tmp + '0';
00298         ex = ex - tmp*10;
00299         *s++ = ex +'0';
00300     }
00301     /* add a null byte terminator */
00302     *s = 0;
00303 }
00304 
00305 
00306 /**                     T P _ F I X S C
00307  *
00308  *   tp_fixsc is a scaling routine intended to be used in conjunction
00309  *   with plotting routines. What tp_fixsc does is scale the user supplied
00310  *   data so that it fits on a specified axis and has 'nice' numbers
00311  *   for labels.
00312  *
00313  *   Calling sequence
00314  *
00315  *   tp_fixsc(x, npts, size, xs, xmin, xmax, dx)
00316  *   where
00317  *
00318  * @param       x[]     the data array to be scaled
00319  * @param       npts    the number of elements in x[]
00320  * @param       size    the length into which x[] is supposed to be fitted
00321  *                      (in inches)
00322  * @param       xs      the returned scale facter to integer space
00323  * @param       xmin    the new minimum value for the data array (a returned
00324  *                      value)
00325  * @param       xmax    the new maximum value for the data array (a returned
00326  *                      value)
00327  * @param       dx      the value in data units between tic marks (a returned
00328  *                      value)
00329  *
00330  */
00331 void
00332 tp_fixsc(float *x,
00333          int npts,
00334          float size,
00335          float *xs,
00336          float *xmin,
00337          float *xmax,
00338          float *dx)
00339 {
00340     float txmi, txma, coef, delta, diff;
00341     int i, ex;
00342 
00343     txmi=txma=x[0];
00344     i = 0;
00345     while( i <= npts ) {
00346         if( x[i] < txmi)
00347             txmi = x[i];
00348         if( x[i] > txma)
00349             txma = x[i];
00350         i++;
00351     }
00352 
00353     diff = txma - txmi;
00354     if( diff < .000001 )
00355         diff = .000001;
00356 
00357     tp_sep (diff, &coef, &ex);
00358     if( coef < 2.0 )
00359         delta = .1;
00360     else if ( coef < 4.0 )
00361         delta = .2;
00362     else
00363         delta = .5;
00364 
00365     i = 0;
00366     if(ex < 0 ){
00367         ex = -ex;
00368         i=12;
00369     }
00370 
00371     delta *= tp_ipow(10.0,ex);
00372     if(i == 12)
00373         delta = 1.0/delta;
00374     *dx = delta;
00375 
00376     i = (fabs(txmi)/delta);
00377     *xmin = i*delta;
00378     if( txmi < 0.0 )
00379         *xmin = -(*xmin+delta);
00380 
00381     i = (fabs(txma)/delta);
00382     *xmax = i*delta;
00383     if( txma < 0.0)
00384         *xmax = - *xmax;
00385     else
00386         *xmax = *xmax+delta;
00387     *xs = 1000.*size/(*xmax - *xmin);
00388 }
00389 
00390 
00391 /**                     T P _ S E P
00392  *@brief
00393  *  tp_sep() divides a floating point number into a coefficient
00394  *  and an exponent. works in base ten.
00395  */
00396 void
00397 tp_sep(float x, float *coef, int *ex)
00398 {
00399     int i, isv;
00400     float xx;
00401 
00402     isv = 1;
00403     if(x < 0.0 ){
00404         isv = -1;
00405         x = -x;
00406     }
00407 
00408     if( x > 1.0 ){
00409         xx = x;
00410         *ex = 0;
00411         *coef = 0.0;
00412 
00413         if ( xx < 10.0){
00414             *coef = xx*isv;
00415             return;
00416         }
00417 
00418         for ( i=1 ; i < 39 ; ++i){
00419             *ex += 1;
00420             xx = xx/10.0;
00421             if( xx < 10.0 )
00422                 break;
00423         }
00424         *coef = xx*isv;
00425         return;
00426     } else{
00427         xx = x;
00428         *ex = 0;
00429         *coef = 0.0;
00430         for ( i=1 ; i<39 ; ++i){
00431             *ex -= 1;
00432             xx *= 10.0;
00433             if( xx >= 1.0 )
00434                 break;
00435         }
00436         *coef = xx*isv;
00437         return;
00438     }
00439 }
00440 
00441 
00442 /**                     T P _ I P O W
00443  *@brief
00444  *  tp_ipow() raises a floating point number to a positve integer
00445  *  power.
00446  *  XXX Horribly inefficient!
00447  */
00448 double tp_ipow (double x, int n)
00449 {
00450     return(n>0?x*tp_ipow(x,n-1):1);
00451 }
00452 
00453 
00454 /**
00455  *      FORTRAN Interface Entry
00456  */
00457 void
00458 PL_FORTRAN(fplot, FPLOT)(FILE **fp, int *xp, int *yp, int *xl, int *yl, char *xtitle, char *ytitle, float *x, float *y, int *n, float *cscale)
00459 {
00460     tp_plot(*fp, *xp, *yp, *xl, *yl, xtitle, ytitle, x, y, *n, *cscale);
00461 }
00462 
00463 /*@}*/
00464 /*
00465  * Local Variables:
00466  * mode: C
00467  * tab-width: 8
00468  * c-basic-offset: 4
00469  * indent-tabs-mode: t
00470  * End:
00471  * ex: shiftwidth=4 tabstop=8
00472  */

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