BRL-CAD
tplot.c
Go to the documentation of this file.
1 /* T P L O T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup plot */
21 /** @{ */
22 /** @file libbn/tplot.c
23  *
24  * @brief
25  * This routine is designed to simplify the creation of
26  * X, Y plots for user.
27  *
28  * George W. Hartwig, Jr.
29  * 16 March 1979
30  *
31  * This routine is designed to simplify the creation of
32  * X, Y plots for user. The user need only furnish this program with
33  * the data arrays to be plotted, the lengths of the respective
34  * axis, titles for the axis, and the point on the page corresponding
35  * to data point (0, 0).
36  * The program will then do everything else required to make
37  * the plot appear on the user's terminal including scaling of the
38  * data, centering of the titles and positioning on the page.
39  *
40  * where
41  * - int xp, yp page point corresponding to (0, 0) of the data
42  * - int xl, yl lengths of the x and y axis, respectively
43  * - char xtitle[], ytitle[] titles for the axis
44  * - float x[], y[] the floating point data arrays
45  * - int n the number of points in the data arrays
46  */
47 
48 #include "common.h"
49 
50 /* system headers */
51 #include <stdio.h>
52 #include <string.h>
53 #include <math.h>
54 
55 /* interface headers */
56 #include "vmath.h"
57 #include "plot3.h"
58 
59 
60 #define TIC 100
61 #define REF_WIDTH 0.857143
62 #define NUM_DISTANCE 250
63 #define LAB_LNGTH 860
64 
65 
66 /**
67  *@brief
68  * tp_sep() divides a floating point number into a coefficient
69  * and an exponent. Works in base ten.
70  */
71 void
72 tp_sep(float x, float *coef, int *ex)
73 {
74  int i, isv;
75  float xx;
76 
77  isv = 1;
78  if (x < 0.0 ) {
79  isv = -1;
80  x = -x;
81  }
82 
83  if ( x > 1.0 ) {
84  xx = x;
85  *ex = 0;
86  *coef = 0.0;
87 
88  if ( xx < 10.0) {
89  *coef = xx*isv;
90  return;
91  }
92 
93  for ( i=1; i < 39; ++i) {
94  *ex += 1;
95  xx = xx/10.0;
96  if ( xx < 10.0 )
97  break;
98  }
99  *coef = xx*isv;
100  return;
101  } else {
102  xx = x;
103  *ex = 0;
104  *coef = 0.0;
105  for ( i=1; i<39; ++i) {
106  *ex -= 1;
107  xx *= 10.0;
108  if ( xx >= 1.0 )
109  break;
110  }
111  *coef = xx*isv;
112  return;
113  }
114 }
115 
116 
117 /**
118  *@brief
119  * tp_ipow() raises a floating point number to a positive integer
120  * power.
121  * XXX Horribly inefficient!
122  */
123 double tp_ipow (double x, int n)
124 {
125  return n>0?x*tp_ipow(x, n-1):1;
126 }
127 
128 
129 /**
130  * tp_fixsc is a scaling routine intended to be used in conjunction
131  * with plotting routines. What tp_fixsc does is scale the user supplied
132  * data so that it fits on a specified axis and has 'nice' numbers
133  * for labels.
134  *
135  * Calling sequence
136  *
137  * tp_fixsc(x, npts, size, xs, xmin, xmax, dx)
138  * where
139  *
140  * @param x[] the data array to be scaled
141  * @param npts the number of elements in x[]
142  * @param size the length into which x[] is supposed to be fitted
143  * (in inches)
144  * @param xs the returned scale factor to integer space
145  * @param xmin the new minimum value for the data array (a returned
146  * value)
147  * @param xmax the new maximum value for the data array (a returned
148  * value)
149  * @param dx the value in data units between tic marks (a returned
150  * value)
151  *
152  */
153 void
154 tp_fixsc(float *x,
155  int npts,
156  float size,
157  float *xs,
158  float *xmin,
159  float *xmax,
160  float *dx)
161 {
162  float txmi, txma, coef, delta, diff;
163  int i, ex;
164 
165  txmi=txma=x[0];
166  i = 0;
167  while ( i <= npts ) {
168  V_MIN(txmi, x[i]);
169  V_MAX(txma, x[i]);
170  i++;
171  }
172 
173  diff = txma - txmi;
174  V_MAX(diff, 0.000001f);
175 
176  tp_sep (diff, &coef, &ex);
177  if ( coef < 2.0f )
178  delta = .1f;
179  else if ( coef < 4.0f )
180  delta = .2f;
181  else
182  delta = .5f;
183 
184  i = 0;
185  if (ex < 0 ) {
186  ex = -ex;
187  i=12;
188  }
189 
190  delta *= tp_ipow(10.0, ex);
191  if (i == 12)
192  delta = 1.0/delta;
193  *dx = delta;
194 
195  i = (fabs(txmi)/delta);
196  *xmin = i*delta;
197  if ( txmi < 0.0f )
198  *xmin = -(*xmin+delta);
199 
200  i = (fabs(txma)/delta);
201  *xmax = i*delta;
202  if ( txma < 0.0f)
203  *xmax = - *xmax;
204  else
205  *xmax = *xmax+delta;
206  *xs = 1000.0f*size/(*xmax - *xmin);
207 }
208 
209 
210 /**
211  * @param fp file pointer
212  * @param xtitle title for the x axis
213  * @param ytitle title for the y axis
214  * @param xp is the x page point desired to be (0, 0) for plot
215  * @param yp is the y page point desired to be (0, 0) for plot
216  * @param xl is the length of the x axis
217  * @param yl is the length of the y axis
218  * @param n is the number of points
219  * @param cscale is the character scale factor
220  * @param x the x data
221  * @param y the y data
222  */
223 void
224 tp_plot(FILE *fp,
225  int xp,
226  int yp,
227  int xl,
228  int yl,
229  char *xtitle,
230  char *ytitle,
231  float *x,
232  float *y,
233  int n,
234  double cscale)
235 {
236  int ddx = 0, ddy = 0, xend = 0, yend = 0, xpen = 0, ypen = 0;
237  float fxl = 0.0, fyl = 0.0, xs = 0.0, ys = 0.0, xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0, dx = 0.0, dy = 0.0;
238  float lab = 0.0;
239  int xtics = 0, ytics = 0, i = 0, xtl = 0, ytl = 0, j = 0;
240  int ix[101] = {0}, iy[101] = {0}, isave = 0;
241  char str[32] = {0};
242 
243  if ( xl == 0 ) {
244  j = 0;
245  goto loop;
246  }
247  fxl = xl/1000.0;
248  fyl = yl/1000.0;
249  n -= 1; /* allow for the fact that fortran starts arrays at 1 */
250  tp_fixsc (x, n, fxl, &xs, &xmin, &xmax, &dx);
251  tp_fixsc (y, n, fyl, &ys, &ymin, &ymax, &dy);
252  ddx = dx*xs;
253  ddy = dy*ys;
254  xtics = LAB_LNGTH / ddx + 1.0;
255  ytics = 500/ddy + 1.0;
256  xend = xl+xp;
257  xpen = xp;
258 
259  pl_move(fp, xpen, yp-TIC);
260  pl_cont(fp, xpen, yp);
261 
262  /* label first tic */
263  lab = xmin;
264  snprintf( str, 32, "%3.3g", xmin );
265  tp_2symbol( fp, str, (double)(xpen-171), (double)(yp-TIC-NUM_DISTANCE), cscale, 0.0);
266 
267  i = 0;
268  while ((xpen+ddx)<=xend) {
269  i++;
270  xpen += ddx;
271  pl_line( fp, xpen, yp, xpen, yp-TIC );
272  /* while here label this tic mark if no overlapping will occur */
273  lab += dx;
274  /* need if test here to check for overlap */
275  if ( (i%xtics) == 0) {
276  snprintf( str, 32, "%3.3g", lab );
277  tp_2symbol( fp, str, (double)(xpen-171), (double)(yp-TIC-NUM_DISTANCE), cscale, 0.0);
278  }
279  }
280 
281  /* insert axis label here */
282  xtl = xp+(xl - strlen(xtitle)*cscale)/2;
283  ytl = yp - 8 * cscale;
284  tp_2symbol( fp, xtitle, (double)xtl, (double)ytl, 100.0, 0.0);
285  yend = yl+yp;
286  ypen= yp;
287  pl_line( fp, xp-TIC, ypen, xp, ypen );
288 
289  /* draw first y label */
290  lab = ymin;
291  snprintf( str, 32, "%3.3g", lab );
292  tp_2symbol( fp, str, (double)(xp-TIC-LAB_LNGTH-NUM_DISTANCE), (double)ypen, cscale, 0.0);
293 
294  i=0;
295  while ((ypen+ddy)<=yend) {
296  i++;
297  ypen += ddy;
298  pl_line( fp, xp, ypen, xp-TIC, ypen );
299  /* label the y-axis now, nicely */
300  lab += dy;
301  if (( i%ytics) ==0) {
302  snprintf( str, 32, "%3.3g", lab );
303  tp_2symbol( fp, str, (double)(xp-TIC-LAB_LNGTH-NUM_DISTANCE), (double)ypen, cscale, 0.0);
304  }
305  }
306 
307  /* insert y-axis title here */
308  xtl= xp-1500;
309  ytl= yp + (yl - strlen(ytitle)*cscale)/2;
310  tp_2symbol( fp, ytitle, (double)xtl, (double)ytl, 100.0, 90.0);
311 
312  /* now at long last plot the data */
313  j = 0;
314 
315 loop:
316  if ( n <= 100 ) {
317  isave = n-1;
318  } else {
319  isave = 100;
320  n -= 101;
321  }
322 
323  if (j == 0) {
324  ix[0] = (x[j] - xmin)*xs + xp;
325  iy[0] = (y[j] - ymin)*ys + yp;
326  j++;
327  } else {
328  ix[0] = (x[j-1] - xmin)*xs + xp;
329  iy[0] = (y[j-1] - ymin)*ys + yp;
330  }
331 
332  i = 1;
333  while ( i <= isave ) {
334  ix[i] = (x[j] - xmin)*xs + xp;
335  iy[i] = (y[j] - ymin)*ys + yp;
336  i++;
337  j++;
338  }
339  tp_i2list( fp, ix, iy, isave+1 );
340  if ( isave == 100 ) {
341  goto loop;
342  }
343 }
344 
345 
346 /**
347  * @brief
348  * This routine converts a floating point number into a string
349  * of ascii characters of the form "sX.XXXesXX". The string is
350  * null terminated.
351  */
352 void
353 tp_ftoa(float x, char *s)
354 {
355  int ex, tmp;
356  float coef;
357  char esgn, nsgn;
358  char i;
359 
360  tp_sep(x, &coef, &ex);
361  if ( ex < -15 ) {
362  ex = 0;
363  *s++ = '0';
364  *s++ = '.';
365  *s++ = '0';
366  *s++ = '0';
367  *s++ = '0';
368  *s++ = 'e';
369  *s++ = '+';
370  *s++ = '0';
371  *s++ = '0';
372  *s = 0;
373  return;
374  }
375 
376  if (ex < 0) {
377  esgn = '-';
378  ex = -ex;
379  } else {
380  esgn = '+';
381  }
382 
383  if ( coef < 0.0) {
384  nsgn = '-';
385  coef = -coef;
386  } else {
387  nsgn = ' ';
388  }
389  *s++ = nsgn;
390 
391  /* load the first numeral and the decimal point */
392  tmp = coef;
393  *s++ = tmp + '0';
394  coef = (coef - tmp)*10.0;
395  *s++ = '.';
396 
397  /* now do the three after the decimal */
398  for ( i=1; i<=3; ++i) {
399  tmp = coef;
400  coef = (coef - tmp)*10.0;
401  *s++ = tmp + '0';
402  }
403 
404  /* put the e in */
405  *s++ = 'e';
406 
407  /* the sign for the exponent */
408  *s++ = esgn;
409 
410  /* and the exponent */
411  if ( ex < 0)
412  ex = -ex;
413 
414  if ( ex < 10 ) {
415  *s++ = '0';
416  *s++ = ex + '0';
417  } else {
418  tmp = ex/10;
419  *s++ = tmp + '0';
420  ex = ex - tmp*10;
421  *s++ = ex +'0';
422  }
423  /* add a null byte terminator */
424  *s = 0;
425 }
426 
427 
428 /**
429  * FORTRAN Interface Entry
430  */
431 void
432 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)
433 {
434  tp_plot(*fp, *xp, *yp, *xl, *yl, xtitle, ytitle, x, y, *n, *cscale);
435 }
436 
437 /** @} */
438 /*
439  * Local Variables:
440  * mode: C
441  * tab-width: 8
442  * indent-tabs-mode: t
443  * c-file-style: "stroustrup"
444  * End:
445  * ex: shiftwidth=4 tabstop=8
446  */
void tp_plot(FILE *fp, int xp, int yp, int xl, int yl, char *xtitle, char *ytitle, float *x, float *y, int n, double cscale)
Definition: tplot.c:224
void pl_cont(register FILE *plotfp, int x, int y)
Definition: plot3.c:232
if lu s
Definition: nmg_mod.c:3860
#define LAB_LNGTH
Definition: tplot.c:63
void tp_ftoa(float x, char *s)
This routine converts a floating point number into a string of ascii characters of the form "sX...
Definition: tplot.c:353
void tp_fixsc(float *x, int npts, float size, float *xs, float *xmin, float *xmax, float *dx)
Definition: tplot.c:154
void pl_line(register FILE *plotfp, int px1, int py1, int px2, int py2)
Definition: plot3.c:193
Header file for the BRL-CAD common definitions.
#define TIC
Definition: tplot.c:60
void tp_2symbol(FILE *fp, char *string, double x, double y, double scale, double theta)
Definition: symbol.c:123
void tp_sep(float x, float *coef, int *ex)
tp_sep() divides a floating point number into a coefficient and an exponent. Works in base ten...
Definition: tplot.c:72
double tp_ipow(double x, int n)
tp_ipow() raises a floating point number to a positive integer power. XXX Horribly inefficient! ...
Definition: tplot.c:123
void PL_FORTRAN(fplot, FPLOT)
Definition: tplot.c:432
void tp_i2list(register FILE *fp, register int *x, register int *y, register int npoints)
Definition: list.c:33
void pl_move(register FILE *plotfp, int x, int y)
Definition: plot3.c:220
#define NUM_DISTANCE
Definition: tplot.c:62
HIDDEN const point_t delta
Definition: sh_prj.c:618