ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/tgraph.c
Revision: 1.3
Committed: Mon Jul 21 22:30:18 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 1.2: +30 -23 lines
Log Message:
Eliminated copystruct() macro, which is unnecessary in ANSI.
Reduced ambiguity warnings for nested if/if/else clauses.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tgraph.c,v 1.2 2003/06/30 14:59:12 schorsch Exp $";
3 #endif
4 /*
5 * Routines for tel-a-graph file plotting
6 *
7 * 1/20/85
8 */
9
10 #include <ctype.h>
11 #include <string.h>
12
13 #include "tgraph.h"
14
15
16 #define isfloat(a) (isdigit(a) || (a) == '-' || (a) == '.' || \
17 (a) == 'E' || (a) == '+' || (a) == 'e')
18
19
20 extern double log10();
21
22
23
24
25
26 initialize()
27
28 {
29 int i;
30
31 for (i = 0; i < NCUR; i++)
32 usecurve[i] = 1;
33
34 }
35
36
37
38
39
40
41 option(s) /* record option */
42
43 char *s;
44
45 {
46 double atof();
47 char *sp;
48 short userror = 0;
49 int i;
50
51 if (s[0] == '-') {
52
53 switch(s[1]) {
54
55 case 'x':
56 xmnset = atof(s+2);
57 break;
58
59 case 'y':
60 ymnset = atof(s+2);
61 break;
62
63 case 's': /* set symbol size */
64 symrad = atoi(s+2);
65 break;
66
67 case 'l': /* log plot */
68 if (s[2] == 'x')
69 logx++;
70 else if (s[2] == 'y')
71 logy++;
72 else
73 userror++;
74 break;
75
76 case 'g': /* grid on */
77 grid = TRUE;
78 break;
79
80 case 'p': /* polar coordinates */
81 if (s[2] == 'd')
82 polar = DEGREES;
83 else if (s[2] == 'r')
84 polar = RADIANS;
85 else
86 userror++;
87 break;
88
89 default:
90 for (sp = s+1; *sp && *sp > '@' && *sp < '@'+NCUR; sp++)
91 usecurve[*sp-'@'] = 0;
92 userror = *sp;
93 break;
94 }
95 } else {
96
97 switch (s[1]) {
98
99 case 'x':
100 xmxset = atof(s+2);
101 break;
102
103 case 'y':
104 ymxset = atof(s+2);
105 break;
106
107 default:
108 for (i = 0; i < 27; i++)
109 usecurve[i] = 0;
110 for (sp = s+1; *sp && *sp > '@' && *sp < '@'+NCUR; sp++)
111 usecurve[*sp-'@'] = 1;
112 userror = *sp;
113 }
114 }
115
116 if (userror)
117 error(USER, "options are [-sSYMRAD][-g][-lx][-ly][-p{dr}][-xXMIN][+xXMAX][-yYMIN][+yYMAX][-C..|+C..]");
118
119 }
120
121
122
123
124 normalize(fp, fout) /* get extrema from file */
125
126 FILE *fp, *fout;
127
128 {
129 char line[255];
130 double x, y;
131 long npoints = 0;
132
133 ncurves = 0;
134 xmin = ymin = FHUGE;
135 xmax = ymax = -FHUGE;
136
137 while (fgets(line, sizeof line, fp) != NULL) {
138
139 if (fout != NULL)
140 fputs(line, fout);
141
142 if (islabel(line))
143
144 ncurves++;
145
146 else if (ncurves < NCUR && usecurve[ncurves] && isdata(line)) {
147
148 if (getdata(line, &x, &y) < 0)
149 continue;
150
151 if (x < xmin)
152 xmin = x;
153 if (x > xmax)
154 xmax = x;
155 if (y < ymin)
156 ymin = y;
157 if (y > ymax)
158 ymax = y;
159
160 npoints++;
161
162 }
163
164 }
165
166 if (npoints <= 1)
167 error(USER, "insufficient data in file");
168
169 }
170
171
172
173
174
175 makeaxis(flag) /* make and print x and y axis */
176
177 int flag;
178
179 {
180 double xstep, ystep, step(), pos;
181 int xorg, yorg;
182 char *format, stemp[32];
183
184 /* set limits */
185 if (polar) {
186 if (xmax-xmin < ymax-ymin) /* null aspect for polar */
187 xmax = xmin + ymax-ymin;
188 else
189 ymax = ymin + xmax-xmin;
190 } else {
191 if (xmnset > -FHUGE) {
192 if (logx) {
193 if (xmnset > FTINY)
194 xmin = log10(xmnset);
195 } else
196 xmin = xmnset;
197 }
198 if (xmxset < FHUGE) {
199 if (logx) {
200 if (xmxset > FTINY)
201 xmax = log10(xmxset);
202 } else
203 xmax = xmxset;
204 }
205 if (ymnset > -FHUGE) {
206 if (logy) {
207 if (ymnset > FTINY)
208 ymin = log10(ymnset);
209 } else
210 ymin = ymnset;
211 }
212 if (ymxset < FHUGE) {
213 if (logy) {
214 if (ymxset > FTINY)
215 ymax = log10(ymxset);
216 } else
217 ymax = ymxset;
218 }
219 }
220 /* set step */
221 if (logx) {
222 xmin = floor(xmin);
223 xmax = ceil(xmax);
224 xstep = 1.0;
225 } else
226 xstep = step(&xmin, &xmax);
227
228 if (logy) {
229 ymin = floor(ymin);
230 ymax = ceil(ymax);
231 ystep = 1.0;
232 } else
233 ystep = step(&ymin, &ymax);
234
235 xsize = xmax - xmin;
236 ysize = ymax - ymin;
237
238 if (polar) { /* null aspect again */
239 if (xsize < ysize)
240 xmax = xmin + (xsize = ysize);
241 else
242 ymax = ymin + (ysize = xsize);
243 }
244
245 if (xmin > 0.0)
246 xorg = XBEG;
247 else if (xmax < 0.0)
248 xorg = XBEG+XSIZ-1;
249 else
250 xorg = XCONV(0.0);
251 if (ymin > 0.0)
252 yorg = YBEG;
253 else if (ymax < 0.0)
254 yorg = YBEG+YSIZ-1;
255 else
256 yorg = YCONV(0.0);
257 /* make x-axis */
258 if (flag & BOX) {
259 plseg(010, XBEG, YBEG, XBEG+XSIZ-1, YBEG);
260 plseg(010, XBEG, YBEG+YSIZ-1, XBEG+XSIZ-1, YBEG+YSIZ-1);
261 }
262 if (flag & ORIGIN)
263 plseg(010, XBEG, yorg, XBEG+XSIZ-1, yorg);
264
265 #if CPM || MAC
266 if (xstep > 1.0)
267 format = "%5.0f";
268 else
269 format = "%5.3f";
270 #else
271 format = "%5g";
272 #endif
273 if (logx)
274 format = "1e%-3.0f";
275
276 for (pos = xmin; pos < xmax+xstep/2; pos += xstep) {
277 if (flag & XTICS) {
278 if (polar)
279 plseg(010, XCONV(pos), yorg-TSIZ/2, XCONV(pos), yorg+TSIZ/2);
280 else {
281 plseg(010, XCONV(pos), YBEG, XCONV(pos), YBEG-TSIZ);
282 plseg(010, XCONV(pos), YBEG+YSIZ-1, XCONV(pos), YBEG+YSIZ-1+TSIZ);
283 }
284 }
285 if (flag & XNUMS) {
286 sprintf(stemp, format, pos);
287 if (polar)
288 pprim(PMSTR, 020, XCONV(pos)-600, yorg-TSIZ-150,
289 XCONV(pos)-600, yorg-TSIZ-150, stemp);
290 else
291 pprim(PMSTR, 020, XCONV(pos)-600, YBEG-2*TSIZ-150,
292 XCONV(pos)-600, YBEG-2*TSIZ-150, stemp);
293 }
294 if (flag & XGRID)
295 plseg(040, XCONV(pos), YBEG, XCONV(pos), YBEG+YSIZ-1);
296 }
297 /* make y-axis */
298 if (flag & BOX) {
299 plseg(010, XBEG, YBEG, XBEG, YBEG+YSIZ-1);
300 plseg(010, XBEG+XSIZ-1, YBEG, XBEG+XSIZ-1, YBEG+YSIZ-1);
301 }
302 if (flag & ORIGIN)
303 plseg(010, xorg, YBEG, xorg, YBEG+YSIZ-1);
304
305 #if CPM || MAC
306 if (ystep > 1.0)
307 format = "%5.0f";
308 else
309 format = "%5.3f";
310 #else
311 format = "%5g";
312 #endif
313 if (logy)
314 format = "1e%-3.0f";
315
316 for (pos = ymin; pos < ymax+ystep/2; pos += ystep) {
317 if (flag & YTICS) {
318 if (polar)
319 plseg(010, xorg-TSIZ/2, YCONV(pos), xorg+TSIZ/2, YCONV(pos));
320 else {
321 plseg(010, XBEG, YCONV(pos), XBEG-TSIZ, YCONV(pos));
322 plseg(010, XBEG+XSIZ-1, YCONV(pos), XBEG+XSIZ-1+TSIZ, YCONV(pos));
323 }
324 }
325 if (flag & YNUMS) {
326 sprintf(stemp, format, pos);
327 if (polar)
328 pprim(PMSTR, 020, xorg-TSIZ-900, YCONV(pos)+32,
329 xorg-TSIZ-900, YCONV(pos)+32, stemp);
330 else
331 pprim(PMSTR, 020, XBEG-2*TSIZ-900, YCONV(pos)+32,
332 XBEG-2*TSIZ-900, YCONV(pos)+32, stemp);
333 }
334 if (flag & YGRID)
335 plseg(040, XBEG, YCONV(pos), XBEG+XSIZ-1, YCONV(pos));
336 }
337
338 }
339
340
341
342 isdata(s)
343
344 register char *s;
345
346 {
347 int commas = 0;
348
349 while (*s)
350 if (isfloat(*s) || isspace(*s))
351 s++;
352 else if (*s == ',') {
353 commas++;
354 s++;
355 }
356 else
357 return 0;
358
359 return commas <= 1;
360 }
361
362
363
364
365 islabel(s)
366
367 char s[];
368
369 {
370 int i;
371
372 i = strlen(s) - 2;
373
374 return(i > 0 && s[0] == '"' && s[i] == '"');
375 }
376
377
378
379
380 double
381 step(mn, mx) /* compute step size for axis */
382
383 double *mn, *mx;
384
385 {
386 static int steps[] = {100, 50, 20, 10, 5, 2, 1};
387 int i;
388 double fact, stp;
389 double pown(), floor(), ceil();
390
391 if (*mx-*mn <= FTINY) {
392 stp = 1.0;
393 }
394 else {
395 fact = pown(10.0, (int)log10(*mx-*mn)-2);
396 stp = (*mx-*mn)/fact/MINDIVS;
397
398 for (i = 0; stp < steps[i]; i++);
399 stp = steps[i]*fact;
400 }
401
402 *mn = floor(*mn/stp) * stp;
403 *mx = ceil(*mx/stp) * stp;
404
405 return(stp);
406 }
407
408
409
410 double
411 pown(x, n) /* raise x to an integer power */
412
413 double x;
414 int n;
415
416 {
417 register int i;
418 double p = 1.0;
419
420 if (n > 0)
421 for (i = 0; i < n; i++)
422 p *= x;
423 else
424 for (i = 0; i > n; i--)
425 p /= x;
426
427 return(p);
428 }
429
430
431
432
433 istitle(s)
434
435 char *s;
436
437 {
438 char word[32];
439
440 if (sscanf(s, "%10s", word) == 1)
441 return strcmp(word, "title") == 0;
442 else
443 return 0;
444 }
445
446
447
448
449 isdivlab(s) /* return TRUE if division label(s) */
450
451 register char *s;
452
453 {
454
455 return(instr(s, "division") != NULL);
456 }
457
458
459
460
461 isxlabel(s)
462
463 register char *s;
464
465 {
466 register char *xindex = instr(s, "x ");
467
468 return(xindex != NULL && instr(xindex, "label ") != NULL);
469 }
470
471
472
473
474 isylabel(s)
475
476 register char *s;
477
478 {
479 register char *yindex = instr(s, "y ");
480
481 return(yindex != NULL && instr(yindex, "label ") != NULL);
482 }
483
484
485
486 char *
487 instr(s, t) /* return pointer to first occurrence of t in s */
488
489 char *s,
490 *t;
491
492 {
493 register char *pt, *ps;
494
495 do {
496
497 ps = s;
498 pt = t;
499
500 while (*pt && *pt == *ps++)
501 pt++;
502
503 if (*pt == '\0')
504 return(s);
505
506 } while (*s++);
507
508 return(NULL);
509 }
510
511
512
513
514 char *
515 snagquo(s) /* find and return quoted string within s */
516
517 register char *s;
518
519 {
520 register char *rval = NULL;
521
522 for ( ; *s; s++)
523 if (*s == '"') {
524 if (rval == NULL)
525 rval = s+1;
526 else {
527 *s = '\0';
528 return(rval);
529 }
530 }
531
532 return(NULL);
533 }
534
535
536
537
538 getdata(s, xp, yp) /* get data from line */
539
540 char *s;
541 double *xp, *yp;
542
543 {
544 double sin(), cos();
545 int oobounds = 0;
546 double a;
547 register char *cp;
548
549 if ((cp = strchr(s, ',')) != NULL)
550 *cp = ' ';
551
552 if (sscanf(s, "%lf %lf", xp, yp) != 2)
553 return(-1);
554
555 if (*xp < xmnset || *xp > xmxset)
556 oobounds++;
557 if (*yp < ymnset || *yp > ymxset)
558 oobounds++;
559
560 if (logx) {
561 if (*xp < FTINY)
562 oobounds++;
563 else
564 *xp = log10(*xp);
565 }
566
567 if (logy) {
568 if (*yp < FTINY)
569 oobounds++;
570 else
571 *yp = log10(*yp);
572 }
573
574 if (polar) {
575 a = *xp;
576 if (polar == DEGREES)
577 a *= PI/180.0;
578 *xp = *yp * cos(a);
579 *yp *= sin(a);
580 }
581
582 return(oobounds ? -1 : 0);
583 }
584
585
586
587
588 symout(a0, x, y, sname) /* output a symbol */
589
590 int a0;
591 int x, y;
592 char *sname;
593
594 {
595
596 pprim(PSEG, a0, x-symrad, y-symrad, x+symrad, y+symrad, sname);
597
598 }
599
600
601
602 boxstring(a0, xmn, ymn, xmx, ymx, s) /* output a string within a box */
603
604 int a0;
605 int xmn, ymn, xmx, ymx;
606 char *s;
607
608 {
609 int start;
610 long size;
611
612 if (a0 & 020) { /* up or down */
613
614 size = (long)strlen(s)*(xmx-xmn)*2/3; /* aspect ratio is 1.5 */
615
616 if (size > ymx-ymn) {
617 size = ymx-ymn; /* squash it */
618 start = ymn;
619 } else
620 start = (ymx-ymn-(int)size)/2 + ymn; /* center it */
621
622 pprim(PVSTR, a0, xmn, start, xmx, start+(int)size, s);
623
624 } else { /* right or left */
625
626 size = (long)strlen(s)*(ymx-ymn)*2/3; /* aspect ratio is 1.5 */
627
628 if (size > xmx-xmn) {
629 size = xmx-xmn; /* squash it */
630 start = xmn;
631 } else
632 start = (xmx-xmn-(int)size)/2 + xmn; /* center it */
633
634 pprim(PVSTR, a0, start, ymn, start+(int)size, ymx, s);
635
636 }
637
638 }