ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/mgraph.c
Revision: 1.2
Committed: Sat Nov 15 02:13:37 2003 UTC (20 years, 4 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad3R7P2, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9, rad4R2P1, rad5R3, HEAD
Changes since 1.1: +130 -57 lines
Log Message:
Continued ANSIfication, and reduced other compile warnings.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 1.2 static const char RCSid[] = "$Id: mgraph.c,v 1.1 2003/02/22 02:07:26 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * mgraph.c - routines for plotting graphs from variables.
6     *
7     * 6/23/86
8     *
9     * Greg Ward Larson
10     */
11    
12     #include <stdio.h>
13 schorsch 1.2 #include <string.h>
14 greg 1.1
15 schorsch 1.2 #include "meta.h"
16 greg 1.1 #include "mgvars.h"
17     #include "mgraph.h"
18    
19     extern char *progname; /* argv[0] */
20    
21     extern double goodstep(), floor(), ceil(), sin(), cos();
22    
23     static BOUNDS xbounds, ybounds; /* the boundaries for the graph */
24    
25     static double period = DEFPERIOD; /* period for polar plot */
26    
27     static double axbegin, axsize; /* the mapped x axis boundaries */
28     static double aybegin, aysize; /* the mapped y axis boundaries */
29    
30     static int npltbl[MAXCUR]; /* plottable points per curve */
31    
32     static double lastx, lasty; /* last curve postion */
33     static int nplottable; /* number of plottable points */
34     static int nplotted; /* number of plotted points */
35    
36 schorsch 1.2 static void getbounds(void);
37     static void polaraxis(void);
38     static void makeaxis(void);
39     static void plotcurves(void);
40     static void cartaxis(void);
41     static void stretchbounds(int c, double x, double y);
42     static void boxstring(int xmin, int ymin, int xmax, int ymax,
43     char *s, int d, int width, int color);
44     static void drawcircle(int x, int y, int r, int typ, int wid, int col);
45     static int rconv(double r);
46     static int xconv(double x);
47     static int yconv(double y);
48     static void csymbol(int c, double u, double v);
49     static int cmline(int c, int x, int y);
50     static void cmsymbol(int c, int x, int y);
51     static int inbounds(double x, double y);
52     static void climline(int c, double x, double y, double xout, double yout);
53     static void nextpoint(register int c, double x, double y);
54     static void cline(int c, double u1, double v1, double u2, double v2);
55    
56 greg 1.1
57 schorsch 1.2 void
58     mgraph(void) /* plot the current graph */
59 greg 1.1 {
60     /* load the symbol file */
61     if (gparam[SYMFILE].flags & DEFINED)
62     minclude(gparam[SYMFILE].v.s);
63     /* check for polar plot */
64     if (gparam[PERIOD].flags & DEFINED)
65     period = varvalue(gparam[PERIOD].name);
66    
67     getbounds(); /* get the boundaries */
68     makeaxis(); /* draw the coordinate axis */
69     plotcurves(); /* plot the curves */
70    
71     mendpage(); /* advance page */
72     }
73    
74    
75 schorsch 1.2 void
76     getbounds(void) /* compute the boundaries */
77 greg 1.1 {
78 schorsch 1.2 int i;
79 greg 1.1
80     xbounds.min = gparam[XMIN].flags & DEFINED ?
81     varvalue(gparam[XMIN].name) - FTINY :
82     FHUGE ;
83     xbounds.max = gparam[XMAX].flags & DEFINED ?
84     varvalue(gparam[XMAX].name) + FTINY :
85     -FHUGE ;
86     ybounds.min = gparam[YMIN].flags & DEFINED ?
87     varvalue(gparam[YMIN].name) - FTINY :
88     FHUGE ;
89     ybounds.max = gparam[YMAX].flags & DEFINED ?
90     varvalue(gparam[YMAX].name) + FTINY :
91     -FHUGE ;
92    
93     nplottable = 0;
94     for (i = 0; i < MAXCUR; i++) {
95     npltbl[i] = 0;
96     mgcurve(i, stretchbounds);
97     nplottable += npltbl[i];
98     }
99     if (nplottable == 0) {
100     fprintf(stderr, "%s: no plottable data\n", progname);
101     quit(1);
102     }
103    
104     xbounds.step = gparam[XSTEP].flags & DEFINED ?
105     varvalue(gparam[XSTEP].name) :
106     period > FTINY ?
107     DEFPLSTEP*period :
108     goodstep(xbounds.max - xbounds.min) ;
109     if (!(gparam[XMIN].flags & DEFINED))
110     xbounds.min = floor(xbounds.min/xbounds.step) *
111     xbounds.step;
112     if (!(gparam[XMAX].flags & DEFINED))
113     xbounds.max = ceil(xbounds.max/xbounds.step) *
114     xbounds.step;
115     ybounds.step = gparam[YSTEP].flags & DEFINED ?
116     varvalue(gparam[YSTEP].name) :
117     period > FTINY ?
118     goodstep((ybounds.max - ybounds.min)*1.75) :
119     goodstep(ybounds.max - ybounds.min) ;
120     if (!(gparam[YMIN].flags & DEFINED))
121     ybounds.min = floor(ybounds.min/ybounds.step) *
122     ybounds.step;
123     if (!(gparam[YMAX].flags & DEFINED))
124     ybounds.max = ceil(ybounds.max/ybounds.step) *
125     ybounds.step;
126     if (gparam[XMAP].flags & DEFINED) {
127     axbegin = funvalue(gparam[XMAP].name, 1, &xbounds.min);
128     axsize = funvalue(gparam[XMAP].name, 1, &xbounds.max);
129     axsize -= axbegin;
130     } else {
131     axbegin = xbounds.min;
132     axsize = xbounds.max;
133     axsize -= axbegin;
134     }
135     if (gparam[YMAP].flags & DEFINED) {
136     aybegin = funvalue(gparam[YMAP].name, 1, &ybounds.min);
137     aysize = funvalue(gparam[YMAP].name, 1, &ybounds.max);
138     aysize -= aybegin;
139     } else {
140     aybegin = ybounds.min;
141     aysize = ybounds.max;
142     aysize -= aybegin;
143     }
144     }
145    
146    
147 schorsch 1.2 void
148     makeaxis(void) /* draw the coordinate axis */
149 greg 1.1 {
150     char stmp[64];
151    
152     if (period > FTINY)
153     polaraxis();
154     else
155     cartaxis();
156     /* x axis label */
157     if (gparam[XLABEL].flags & DEFINED)
158     boxstring(XL_L,XL_D,XL_R,XL_U,gparam[XLABEL].v.s,'r',0,0);
159     /* x mapping */
160     if (gparam[XMAP].flags & DEFINED) {
161     mgtoa(stmp, &gparam[XMAP]);
162     boxstring(XM_L,XM_D,XM_R,XM_U,stmp,'r',0,0);
163     }
164     /* y axis label */
165     if (gparam[YLABEL].flags & DEFINED)
166     boxstring(YL_L,YL_D,YL_R,YL_U,gparam[YLABEL].v.s,'u',0,0);
167     /* y mapping */
168     if (gparam[YMAP].flags & DEFINED) {
169     mgtoa(stmp, &gparam[YMAP]);
170     boxstring(YM_L,YM_D,YM_R,YM_U,stmp,'u',0,0);
171     }
172     /* title */
173     if (gparam[TITLE].flags & DEFINED)
174     boxstring(TI_L,TI_D,TI_R,TI_U,gparam[TITLE].v.s,'r',2,0);
175     /* subtitle */
176     if (gparam[SUBTITLE].flags & DEFINED)
177     boxstring(ST_L,ST_D,ST_R,ST_U,gparam[SUBTITLE].v.s,'r',1,0);
178     /* legend */
179     if (gparam[LEGEND].flags & DEFINED)
180     mtext(LT_X, LT_Y, gparam[LEGEND].v.s, CPI, 0);
181     }
182    
183    
184 schorsch 1.2 void
185     polaraxis(void) /* print polar coordinate axis */
186 greg 1.1 {
187     int lw, tstyle, t0, t1;
188 schorsch 1.2 double d, d1, ybeg;
189 greg 1.1 char stmp[64], *fmt, *goodformat();
190     /* get tick style */
191     if (gparam[TSTYLE].flags & DEFINED)
192     tstyle = varvalue(gparam[TSTYLE].name) + 0.5;
193     else
194     tstyle = DEFTSTYLE;
195     /* start of numbering */
196     ybeg = ceil(ybounds.min/ybounds.step)*ybounds.step;
197     /* theta (x) numbering */
198     fmt = goodformat(xbounds.step);
199     for (d = 0.0; d < period-FTINY; d += xbounds.step) {
200     sprintf(stmp, fmt, d);
201     d1 = d*(2*PI)/period;
202     t0 = TN_X + TN_R*cos(d1) + .5;
203     if (t0 < TN_X)
204     t0 -= strlen(stmp)*CWID;
205     mtext(t0,(int)(TN_Y+TN_R*sin(d1)+.5),stmp,CPI,0);
206     }
207     /* radius (y) numbering */
208     fmt = goodformat(ybounds.step);
209     lw = PL_R+RN_S;
210     for (d = ybeg; d <= ybounds.max+FTINY; d += ybounds.step) {
211     t0 = rconv(d);
212     if (t0 >= lw+RN_S || t0 <= lw-RN_S) {
213     sprintf(stmp, fmt, d);
214     mtext(RN_X+t0-strlen(stmp)*(CWID/2),RN_Y,stmp,CPI,0);
215     lw = t0;
216     }
217     }
218     /* frame */
219     if (gparam[FTHICK].flags & DEFINED)
220     lw = varvalue(gparam[FTHICK].name) + 0.5;
221     else
222     lw = DEFFTHICK;
223     if (lw-- > 0) {
224     drawcircle(PL_X,PL_Y,PL_R,0,lw,0);
225     switch (tstyle) {
226     case 1: /* outside */
227     t0 = 0; t1 = TLEN; break;
228     case 2: /* inside */
229     t0 = TLEN; t1 = 0; break;
230     case 3: /* accross */
231     t0 = TLEN/2; t1 = TLEN/2; break;
232     default: /* none */
233     t0 = t1 = 0; break;
234     }
235     if (t0 + t1) {
236     for (d = 0.0; d < 2*PI-FTINY;
237     d += xbounds.step*(2*PI)/period) {
238     mline((int)(PL_X+(PL_R-t0)*cos(d)+.5),
239     (int)(PL_Y+(PL_R-t0)*sin(d)+.5),
240     0, lw, 0);
241     mdraw((int)(PL_X+(PL_R+t1)*cos(d)+.5),
242     (int)(PL_Y+(PL_R+t1)*sin(d)+.5));
243     }
244     }
245     }
246     /* origin */
247     if (gparam[OTHICK].flags & DEFINED)
248     lw = varvalue(gparam[OTHICK].name) + 0.5;
249     else
250     lw = DEFOTHICK;
251     if (lw-- > 0) {
252     mline(PL_X-PL_R,PL_Y,0,lw,0);
253     mdraw(PL_X+PL_R,PL_Y);
254     mline(PL_X,PL_Y-PL_R,0,lw,0);
255     mdraw(PL_X,PL_Y+PL_R);
256     if (tstyle > 0)
257     for (d = ybeg; d <= ybounds.max+FTINY;
258     d += ybounds.step) {
259     t0 = rconv(d);
260     mline(PL_X+t0,PL_Y-TLEN/2,0,lw,0);
261     mdraw(PL_X+t0,PL_Y+TLEN/2);
262     mline(PL_X-TLEN/2,PL_Y+t0,0,lw,0);
263     mdraw(PL_X+TLEN/2,PL_Y+t0);
264     mline(PL_X-t0,PL_Y-TLEN/2,0,lw,0);
265     mdraw(PL_X-t0,PL_Y+TLEN/2);
266     mline(PL_X-TLEN/2,PL_Y-t0,0,lw,0);
267     mdraw(PL_X+TLEN/2,PL_Y-t0);
268     }
269     }
270     /* grid */
271     if (gparam[GRID].flags & DEFINED)
272     lw = varvalue(gparam[GRID].name);
273     else
274     lw = DEFGRID;
275     if (lw-- > 0) {
276     for (d = 0.0; d < PI-FTINY; d += xbounds.step*(2*PI)/period) {
277     mline((int)(PL_X+PL_R*cos(d)+.5),
278     (int)(PL_Y+PL_R*sin(d)+.5),2,0,0);
279     mdraw((int)(PL_X-PL_R*cos(d)+.5),
280     (int)(PL_Y-PL_R*sin(d)+.5));
281     }
282     for (d = ybeg; d <= ybounds.max + FTINY; d += ybounds.step)
283     drawcircle(PL_X,PL_Y,rconv(d),2,0,0);
284     }
285     }
286    
287 schorsch 1.2 void
288     cartaxis(void) /* print Cartesian coordinate axis */
289 greg 1.1 {
290     int lw, t0, t1, tstyle;
291     double d, xbeg, ybeg;
292     char stmp[64], *fmt, *goodformat();
293     register int i;
294     /* get tick style */
295     if (gparam[TSTYLE].flags & DEFINED)
296     tstyle = varvalue(gparam[TSTYLE].name) + 0.5;
297     else
298     tstyle = DEFTSTYLE;
299     /* start of numbering */
300     xbeg = ceil(xbounds.min/xbounds.step)*xbounds.step;
301     ybeg = ceil(ybounds.min/ybounds.step)*ybounds.step;
302    
303     /* x numbering */
304     fmt = goodformat(xbounds.step);
305     lw = 2*AX_L-AX_R;
306     for (d = xbeg;
307     d <= xbounds.max + FTINY;
308     d += xbounds.step)
309     if ((i = xconv(d)) >= lw+XN_S || i <= lw-XN_S) {
310     sprintf(stmp, fmt, d);
311     mtext(i-strlen(stmp)*(CWID/2)+XN_X,XN_Y,stmp,CPI,0);
312     lw = i;
313     }
314     /* y numbering */
315     fmt = goodformat(ybounds.step);
316     lw = 2*AX_D-AX_U;
317     for (d = ybeg;
318     d <= ybounds.max + FTINY;
319     d += ybounds.step)
320     if ((i = yconv(d)) >= lw+YN_S || i <= lw-YN_S) {
321     sprintf(stmp, fmt, d);
322     mtext(YN_X-strlen(stmp)*CWID,i+YN_Y,stmp,CPI,0);
323     lw = i;
324     }
325     /* frame */
326     if (gparam[FTHICK].flags & DEFINED)
327     lw = varvalue(gparam[FTHICK].name) + 0.5;
328     else
329     lw = DEFFTHICK;
330     if (lw-- > 0) {
331     mline(AX_L,AX_D,0,lw,0);
332     mdraw(AX_R,AX_D);
333     mdraw(AX_R,AX_U);
334     mdraw(AX_L,AX_U);
335     mdraw(AX_L,AX_D);
336     switch (tstyle) {
337     case 1: /* outside */
338     t0 = 0; t1 = TLEN; break;
339     case 2: /* inside */
340     t0 = TLEN; t1 = 0; break;
341     case 3: /* accross */
342     t0 = TLEN/2; t1 = TLEN/2; break;
343     default: /* none */
344     t0 = t1 = 0; break;
345     }
346     if (t0 + t1) {
347     for (d = xbeg;
348     d <= xbounds.max + FTINY;
349     d += xbounds.step) {
350     i = xconv(d);
351     mline(i,AX_D+t0,0,lw,0);
352     mdraw(i,AX_D-t1);
353     mline(i,AX_U-t0,0,lw,0);
354     mdraw(i,AX_U+t1);
355     }
356     for (d = ybeg;
357     d <= ybounds.max + FTINY;
358     d += ybounds.step) {
359     i = yconv(d);
360     mline(AX_L+t0,i,0,lw,0);
361     mdraw(AX_L-t1,i);
362     mline(AX_R-t0,i,0,lw,0);
363     mdraw(AX_R+t1,i);
364     }
365     }
366     }
367     /* origin */
368     if (gparam[OTHICK].flags & DEFINED)
369     lw = varvalue(gparam[OTHICK].name) + 0.5;
370     else
371     lw = DEFOTHICK;
372     if (lw-- > 0) {
373     i = yconv(0.0);
374     if (i >= AX_D && i <= AX_U) {
375     mline(AX_L,i,0,lw,0);
376     mdraw(AX_R,i);
377     if (tstyle > 0)
378     for (d = xbeg; d <= xbounds.max+FTINY;
379     d += xbounds.step) {
380     mline(xconv(d),i+TLEN/2,0,lw,0);
381     mdraw(xconv(d),i-TLEN/2);
382     }
383     }
384     i = xconv(0.0);
385     if (i >= AX_L && i <= AX_R) {
386     mline(i,AX_D,0,lw,0);
387     mdraw(i,AX_U);
388     if (tstyle > 0)
389     for (d = ybeg; d <= ybounds.max+FTINY;
390     d += ybounds.step) {
391     mline(i+TLEN/2,yconv(d),0,lw,0);
392     mdraw(i-TLEN/2,yconv(d));
393     }
394     }
395     }
396     /* grid */
397     if (gparam[GRID].flags & DEFINED)
398     lw = varvalue(gparam[GRID].name);
399     else
400     lw = DEFGRID;
401     if (lw-- > 0) {
402     for (d = xbeg;
403     d <= xbounds.max + FTINY;
404     d += xbounds.step) {
405     i = xconv(d);
406     mline(i,AX_D,2,0,0);
407     mdraw(i,AX_U);
408     }
409     for (d = ybeg;
410     d <= ybounds.max + FTINY;
411     d += ybounds.step) {
412     i = yconv(d);
413     mline(AX_L,i,2,0,0);
414     mdraw(AX_R,i);
415     }
416     }
417     }
418    
419 schorsch 1.2 void
420     plotcurves(void) /* plot the curves */
421 greg 1.1 {
422 schorsch 1.2 int i, j, k;
423 greg 1.1
424     for (i = 0; i < MAXCUR; i++) {
425     nplottable = nplotted = 0;
426     lastx = FHUGE;
427     if (mgcurve(i, nextpoint) > 0 &&
428     cparam[i][CLABEL].flags & DEFINED) {
429     j = (LE_U-LE_D)/MAXCUR;
430     k = LE_U - i*j;
431     mtext(LE_L+(LE_R-LE_L)/8,k+j/3,
432     cparam[i][CLABEL].v.s,CPI,0);
433     cmsymbol(i,LE_L,k);
434     if (cmline(i,LE_L,k) == 0)
435     mdraw(LE_R-(LE_R-LE_L)/4,k);
436     }
437     }
438     }
439    
440 schorsch 1.2 void
441     nextpoint( /* plot the next point for c */
442     register int c,
443     double x,
444     double y
445     )
446 greg 1.1 {
447     if (inbounds(x, y)) {
448    
449     if (!(cparam[c][CNPOINTS].flags & DEFINED) ||
450     nplotted * npltbl[c] <= nplottable *
451     (int)varvalue(cparam[c][CNPOINTS].name) ) {
452     csymbol(c, x, y);
453     nplotted++;
454     }
455     nplottable++;
456     if (lastx != FHUGE)
457     climline(c, x, y, lastx, lasty);
458    
459     } else if (inbounds(lastx, lasty)) {
460    
461     climline(c, lastx, lasty, x, y);
462    
463     }
464     lastx = x;
465     lasty = y;
466     }
467    
468    
469 schorsch 1.2 void
470     stretchbounds( /* stretch our boundaries */
471     int c,
472     double x,
473     double y
474     )
475 greg 1.1 {
476     if (gparam[XMIN].flags & DEFINED &&
477     x < xbounds.min)
478     return;
479     if (gparam[XMAX].flags & DEFINED &&
480     x > xbounds.max)
481     return;
482     if (gparam[YMIN].flags & DEFINED &&
483     y < ybounds.min)
484     return;
485     if (gparam[YMAX].flags & DEFINED &&
486     y > ybounds.max)
487     return;
488    
489     if (x < xbounds.min)
490     xbounds.min = x;
491     if (x > xbounds.max)
492     xbounds.max = x;
493     if (y < ybounds.min)
494     ybounds.min = y;
495     if (y > ybounds.max)
496     ybounds.max = y;
497    
498     npltbl[c]++;
499     }
500    
501    
502     #define exp10(x) exp((x)*2.3025850929940456)
503    
504     double
505 schorsch 1.2 goodstep( /* determine a good step for the interval */
506     double interval
507     )
508 greg 1.1 {
509     static int steps[] = {50, 20, 10, 5, 2, 1};
510     double fact, exp(), log10(), floor();
511     int i;
512    
513     if (interval <= FTINY)
514     return(1.0);
515     fact = exp10(floor(log10(interval)))/10;
516     interval /= fact * MINDIVS;
517     for (i = 0; interval < steps[i]; i++)
518     ;
519     return(steps[i] * fact);
520     }
521    
522     #undef exp10
523    
524    
525     int
526 schorsch 1.2 xconv( /* convert x to meta coords */
527     double x
528     )
529 greg 1.1 {
530     if (gparam[XMAP].flags & DEFINED)
531     x = funvalue(gparam[XMAP].name, 1, &x);
532     x = (x - axbegin)/axsize;
533     return( AX_L + (int)(x*(AX_R-AX_L)) );
534     }
535    
536    
537     int
538 schorsch 1.2 yconv( /* convert y to meta coords */
539     double y
540     )
541 greg 1.1 {
542     if (gparam[YMAP].flags & DEFINED)
543     y = funvalue(gparam[YMAP].name, 1, &y);
544     y = (y - aybegin)/aysize;
545     return( AX_D + (int)(y*(AX_U-AX_D)) );
546     }
547    
548    
549 schorsch 1.2 void
550     pconv( /* convert theta and radius to meta coords */
551     int *xp,
552     int *yp,
553     double t,
554     double r
555     )
556 greg 1.1 {
557     t *= (2.*PI)/period;
558     r = rconv(r);
559     *xp = r*cos(t) + (PL_X+.5);
560     *yp = r*sin(t) + (PL_Y+.5);
561     }
562    
563    
564     int
565 schorsch 1.2 rconv( /* convert radius to meta coords */
566     double r
567     )
568 greg 1.1 {
569     if (gparam[YMAP].flags & DEFINED)
570     r = funvalue(gparam[YMAP].name, 1, &r);
571    
572     return((r - aybegin)*PL_R/aysize + .5);
573     }
574    
575    
576 schorsch 1.2 void
577     boxstring( /* put string in box */
578     int xmin,
579     int ymin,
580     int xmax,
581     int ymax,
582     char *s,
583     int d,
584     int width,
585     int color
586     )
587 greg 1.1 {
588     register long size;
589    
590     if (d == 'u' || d == 'd') { /* up or down */
591     size = strlen(s)*(xmax-xmin)/ASPECT;
592     size -= ymax-ymin;
593     size /= 2;
594     if (size < 0) { /* center */
595     ymin -= size;
596     ymax += size;
597     }
598     } else { /* left or right */
599     size = strlen(s)*(ymax-ymin)/ASPECT;
600     size -= xmax-xmin;
601     size /= 2;
602     if (size < 0) { /* center */
603     xmin -= size;
604     xmax += size;
605     }
606     }
607     mvstr(xmin, ymin, xmax, ymax, s, d, width, color); /* print */
608     }
609    
610    
611     char *
612 schorsch 1.2 goodformat( /* return a suitable format string for d */
613     double d
614     )
615 greg 1.1 {
616     static char *f[5] = {"%.0f", "%.1f", "%.2f", "%.3f", "%.4f"};
617     double floor();
618     register int i;
619    
620     if (d < 0.0)
621     d = -d;
622     if (d > 1e-4 && d < 1e6)
623     for (i = 0; i < 5; i++) {
624     if (d - floor(d+FTINY) <= FTINY)
625     return(f[i]);
626     d *= 10.0;
627     }
628     return("%.1e");
629     }
630    
631    
632 schorsch 1.2 void
633     drawcircle( /* draw a circle */
634     int x,
635     int y,
636     int r,
637     int typ,
638     int wid,
639     int col
640     )
641 greg 1.1 {
642     double d;
643    
644     if (r <= 0)
645     return;
646     mline(x+r, y, typ, wid, col);
647     for (d = 2*PI*PL_F; d <= 2*PI+FTINY; d += 2*PI*PL_F)
648     mdraw((int)(x+r*cos(d)+.5), (int)(y+r*sin(d)+.5));
649     }
650    
651    
652 schorsch 1.2 void
653     climline( /* print line from/to out of bounds */
654     int c,
655     double x,
656     double y,
657     double xout,
658     double yout
659     )
660 greg 1.1 {
661     for ( ; ; )
662     if (xout < xbounds.min) {
663     yout = y + (yout - y)*(xbounds.min - x)/(xout - x);
664     xout = xbounds.min;
665     } else if (yout < ybounds.min) {
666     xout = x + (xout - x)*(ybounds.min - y)/(yout - y);
667     yout = ybounds.min;
668     } else if (xout > xbounds.max) {
669     yout = y + (yout - y)*(xbounds.max - x)/(xout - x);
670     xout = xbounds.max;
671     } else if (yout > ybounds.max) {
672     xout = x + (xout - x)*(ybounds.max - y)/(yout - y);
673     yout = ybounds.max;
674     } else {
675     cline(c, x, y, xout, yout);
676     break;
677     }
678     }
679    
680    
681 schorsch 1.2 void
682     cline( /* print a curve line */
683     int c,
684     double u1,
685     double v1,
686     double u2,
687     double v2
688     )
689 greg 1.1 {
690     int x, y;
691     double ustep, vstep;
692    
693     if (period > FTINY) { /* polar */
694     if (u1 > u2) {
695     ustep = u1; u1 = u2; u2 = ustep;
696     vstep = v1; v1 = v2; v2 = vstep;
697     }
698     pconv(&x, &y, u1, v1);
699     if (cmline(c, x, y) < 0)
700     return;
701     ustep = period*PL_F;
702     if (u2-u1 > ustep) {
703     vstep = ustep*(v2-v1)/(u2-u1);
704     while ((u1 += ustep) < u2) {
705     v1 += vstep;
706     pconv(&x, &y, u1, v1);
707     mdraw(x, y);
708     }
709     }
710     pconv(&x, &y, u2, v2);
711     mdraw(x, y);
712     } else if (cmline(c, xconv(u1), yconv(v1)) == 0)
713     mdraw(xconv(u2), yconv(v2));
714     }
715    
716    
717     int
718 schorsch 1.2 cmline( /* start curve line in meta coords */
719     int c,
720     int x,
721     int y
722     )
723 greg 1.1 {
724     int lw, lt, col;
725     register VARIABLE *cv;
726    
727     cv = cparam[c];
728     if (cv[CLINTYPE].flags & DEFINED)
729     lt = varvalue(cv[CLINTYPE].name);
730     else
731     lt = DEFLINTYPE;
732     if (lt-- <= 0)
733     return(-1);
734     if (cv[CTHICK].flags & DEFINED)
735     lw = varvalue(cv[CTHICK].name);
736     else
737     lw = DEFTHICK;
738     if (lw-- <= 0)
739     return(-1);
740     if (cv[CCOLOR].flags & DEFINED)
741     col = varvalue(cv[CCOLOR].name);
742     else
743     col = DEFCOLOR;
744     if (col-- <= 0)
745     return(-1);
746     mline(x, y, lt, lw, col);
747     return(0);
748     }
749    
750    
751 schorsch 1.2 void
752     csymbol( /* plot curve symbol */
753     int c,
754     double u,
755     double v
756     )
757 greg 1.1 {
758     int x, y;
759    
760     if (period > FTINY) {
761     pconv(&x, &y, u, v);
762     cmsymbol(c, x, y);
763     } else
764     cmsymbol(c, xconv(u), yconv(v));
765     }
766    
767    
768 schorsch 1.2 void
769     cmsymbol( /* print curve symbol in meta coords */
770     int c,
771     int x,
772     int y
773     )
774 greg 1.1 {
775     int col, ss;
776     register VARIABLE *cv;
777    
778     cv = cparam[c];
779     if (!(cv[CSYMTYPE].flags & DEFINED))
780     return;
781     if (cv[CSYMSIZE].flags & DEFINED)
782     ss = varvalue(cv[CSYMSIZE].name);
783     else
784     ss = DEFSYMSIZE;
785     if (ss <= 0)
786     return;
787     if (cv[CCOLOR].flags & DEFINED)
788     col = varvalue(cv[CCOLOR].name);
789     else
790     col = DEFCOLOR;
791     if (col-- <= 0)
792     return;
793     msegment(x-ss,y-ss,x+ss,y+ss,
794     cv[CSYMTYPE].v.s,'r',0,col);
795     }
796    
797    
798 schorsch 1.2 int
799     inbounds( /* determine if x and y are within gbounds */
800     double x,
801     double y
802     )
803 greg 1.1 {
804     if (x < xbounds.min || x > xbounds.max)
805     return(0);
806     if (y < ybounds.min || y > ybounds.max)
807     return(0);
808     return(1);
809     }