tomwalters@0
|
1 /****************************************************************************
|
tomwalters@0
|
2 * Routines for x11coord package.
|
tomwalters@0
|
3 ****************************************************************************/
|
tomwalters@0
|
4
|
tomwalters@0
|
5 #include <stdio.h>
|
tomwalters@0
|
6 #include <math.h>
|
tomwalters@0
|
7 #include "x11coord.h"
|
tomwalters@0
|
8
|
tomwalters@0
|
9 /****************************************************************************
|
tomwalters@0
|
10 * Set parameters for data-pixel conversion macros
|
tomwalters@0
|
11 ****************************************************************************/
|
tomwalters@0
|
12 /* Initialize parameters for size and position of window on screen */
|
tomwalters@0
|
13 set_window_parameters(xorg,yorg, width,height)
|
tomwalters@0
|
14 int xorg,yorg; /* Pixel coords of window origin wrt theDisplay origin */
|
tomwalters@0
|
15 int width,height; /* Size of window (in pixels) */
|
tomwalters@0
|
16 {
|
tomwalters@0
|
17 _xorg = xorg;
|
tomwalters@0
|
18 _yorg = yorg;
|
tomwalters@0
|
19 _width = width;
|
tomwalters@0
|
20 _height = height;
|
tomwalters@0
|
21 set_bordered_box((int)0); /* defaults */
|
tomwalters@0
|
22 set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height);
|
tomwalters@0
|
23 }
|
tomwalters@0
|
24
|
tomwalters@0
|
25 /* Initialize parameters for size and position of box in preset window */
|
tomwalters@0
|
26 set_box_parameters(xorg,yorg, width,height)
|
tomwalters@0
|
27 int xorg,yorg; /* Pixel coords of box origin wrt bottom-left of window */
|
tomwalters@0
|
28 int width,height; /* Size of window (in pixels) */
|
tomwalters@0
|
29 {
|
tomwalters@0
|
30 _Xp0 = xorg;
|
tomwalters@0
|
31 _Yp0 = _height - yorg;
|
tomwalters@0
|
32 _Xp1 = xorg + width;
|
tomwalters@0
|
33 _Yp1 = _height - (yorg + height);
|
tomwalters@0
|
34 _Wb = _Xp1 - _Xp0;
|
tomwalters@0
|
35 _Hb = _Yp0 - _Yp1;
|
tomwalters@0
|
36 set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height);
|
tomwalters@0
|
37 }
|
tomwalters@0
|
38
|
tomwalters@0
|
39
|
tomwalters@0
|
40 /* Initialize parameters for size and position of box in preset window, */
|
tomwalters@0
|
41 /* given the width of the border as a %age of the window size on any side */
|
tomwalters@0
|
42 set_bordered_box(bpc)
|
tomwalters@0
|
43 int bpc;
|
tomwalters@0
|
44 {
|
tomwalters@0
|
45 int xborder, yborder, Wb, Hb;
|
tomwalters@0
|
46
|
tomwalters@0
|
47 xborder = (_width * bpc) / 100;
|
tomwalters@0
|
48 yborder = (_height * bpc) / 100;
|
tomwalters@0
|
49 Wb = _width - 2*xborder;
|
tomwalters@0
|
50 Hb = _height - 2*yborder;
|
tomwalters@0
|
51 set_box_parameters(xborder,yborder, Wb,Hb);
|
tomwalters@0
|
52 }
|
tomwalters@0
|
53
|
tomwalters@0
|
54 /* Initialize parameters for area and location of data-space to appear in box */
|
tomwalters@0
|
55 set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
|
tomwalters@0
|
56 int xp0,yp0; /* Box origin shift as a percentage of box width,height */
|
tomwalters@0
|
57 float xd0,yd0; /* Data coord to appear under box origin. */
|
tomwalters@0
|
58 float xrange,yrange;/* Data ranges (corresponding to box width and height). */
|
tomwalters@0
|
59 {
|
tomwalters@0
|
60 _xrange = xrange;
|
tomwalters@0
|
61 _yrange = yrange;
|
tomwalters@0
|
62 _xshift = (_Wb * xp0)/100;
|
tomwalters@0
|
63 _yshift = (_Hb * yp0)/100;
|
tomwalters@0
|
64 _xd0 = xd0;
|
tomwalters@0
|
65 _yd0 = yd0;
|
tomwalters@0
|
66 _Xd0 = xd0 - _xrange*((float)_xshift/_Wb);
|
tomwalters@0
|
67 _Yd0 = yd0 - _yrange*((float)_yshift/_Hb);
|
tomwalters@0
|
68 _Xd1 = xd0 + (_xrange - _xrange*((float)_xshift/_Wb));
|
tomwalters@0
|
69 _Yd1 = yd0 + (_yrange - _yrange*((float)_yshift/_Hb));
|
tomwalters@0
|
70
|
tomwalters@0
|
71 _xoffset = _Xp0 + _xshift - _xd0*_Wb/_xrange ;
|
tomwalters@0
|
72 _yoffset = _Yp1 + _Hb - _yshift + _yd0*_Hb/_yrange ;
|
tomwalters@0
|
73 _xscale = _Wb/_xrange;
|
tomwalters@0
|
74 _yscale = _Hb/_yrange;
|
tomwalters@0
|
75 }
|
tomwalters@0
|
76
|
tomwalters@0
|
77
|
tomwalters@0
|
78 /****************************************************************************
|
tomwalters@0
|
79 * Creating windows, initializing GC and Font, etc.. (X11 specific)
|
tomwalters@0
|
80 ****************************************************************************/
|
tomwalters@0
|
81 xopen()
|
tomwalters@0
|
82 {
|
tomwalters@0
|
83
|
tomwalters@0
|
84 if ((char *)getenv("DISPLAY") == (char *)0 ) {
|
tomwalters@0
|
85 fprintf(stderr,"DISPLAY not set\n");
|
tomwalters@0
|
86 exit(1);
|
tomwalters@0
|
87 }
|
tomwalters@0
|
88 if ((theDisplay = XOpenDisplay(NULL)) == NULL) {
|
tomwalters@0
|
89 fprintf(stderr,"Can't open display %s\n", getenv("DISPLAY"));
|
tomwalters@0
|
90 exit(1);
|
tomwalters@0
|
91 }
|
tomwalters@0
|
92 theScreen = XDefaultScreen(theDisplay);
|
tomwalters@0
|
93 theForeground = theBlack = XBlackPixel(theDisplay,theScreen); /* Black lines, text, and borders */
|
tomwalters@0
|
94 theBackground = theWhite = XWhitePixel(theDisplay,theScreen); /* White background */
|
tomwalters@0
|
95 theWidth = XDisplayWidth(theDisplay,theScreen);
|
tomwalters@0
|
96 theHeight = XDisplayHeight(theDisplay,theScreen);
|
tomwalters@0
|
97 theGC = initGC() ;
|
tomwalters@0
|
98 }
|
tomwalters@0
|
99
|
tomwalters@0
|
100
|
tomwalters@0
|
101 /*
|
tomwalters@0
|
102 eg: xgc( 1, "times_roman14" ) ;
|
tomwalters@0
|
103 */
|
tomwalters@0
|
104
|
tomwalters@0
|
105 xgc( linewidth, fontstr )
|
tomwalters@0
|
106 int linewidth ;
|
tomwalters@0
|
107 char *fontstr ;
|
tomwalters@0
|
108 {
|
tomwalters@0
|
109 setLinewidth( linewidth ) ;
|
tomwalters@0
|
110 theFont = (XFontStruct *)0;
|
tomwalters@0
|
111 if ( setFont( fontstr ) == NULL ) {
|
tomwalters@0
|
112 fprintf( stderr,"can't load font %s\n", fontstr ) ;
|
tomwalters@0
|
113 exit( 1 ) ;
|
tomwalters@0
|
114 }
|
tomwalters@0
|
115 }
|
tomwalters@0
|
116
|
tomwalters@0
|
117
|
tomwalters@0
|
118 GC initGC()
|
tomwalters@0
|
119 {
|
tomwalters@0
|
120 GC gc;
|
tomwalters@0
|
121
|
tomwalters@0
|
122 gc = XDefaultGC(theDisplay, theScreen);
|
tomwalters@0
|
123 /* Set foreground and background pixel values (ie colours) */
|
tomwalters@0
|
124 XSetState(theDisplay, gc, theForeground, theBackground, GXcopy, AllPlanes);
|
tomwalters@0
|
125 return gc;
|
tomwalters@0
|
126 }
|
tomwalters@0
|
127
|
tomwalters@0
|
128
|
tomwalters@0
|
129
|
tomwalters@0
|
130 setLinewidth(width) /* Set line width, used by XDrawLine commands */
|
tomwalters@0
|
131 int width;
|
tomwalters@0
|
132 {
|
tomwalters@0
|
133 XGCValues gcvalues;
|
tomwalters@0
|
134
|
tomwalters@0
|
135 gcvalues.line_width = width;
|
tomwalters@0
|
136 XChangeGC(theDisplay, theGC, GCLineWidth, &gcvalues);
|
tomwalters@0
|
137 }
|
tomwalters@0
|
138
|
tomwalters@0
|
139
|
tomwalters@0
|
140 setFont(fontname) /* Free last theFont (unless null) and load new font */
|
tomwalters@0
|
141 char *fontname; /* return null if can't load font */
|
tomwalters@0
|
142 {
|
tomwalters@0
|
143 if (theFont != (XFontStruct *)0) XFreeFont(theDisplay,theFont);
|
tomwalters@0
|
144 if ((theFont = XLoadQueryFont(theDisplay, fontname)) == NULL)
|
tomwalters@0
|
145 return 0 ;
|
tomwalters@0
|
146 XSetFont(theDisplay, theGC, theFont->fid);
|
tomwalters@0
|
147 return 1 ;
|
tomwalters@0
|
148 }
|
tomwalters@0
|
149
|
tomwalters@0
|
150
|
tomwalters@0
|
151 Window xCreate(name, event_mask, xorg,yorg, width,height)
|
tomwalters@0
|
152 char *name;
|
tomwalters@0
|
153 long event_mask;
|
tomwalters@0
|
154 int xorg,yorg, width,height;
|
tomwalters@0
|
155 {
|
tomwalters@0
|
156 Window w;
|
tomwalters@0
|
157
|
tomwalters@0
|
158 if ((w = XCreateSimpleWindow(theDisplay, XDefaultRootWindow(theDisplay),
|
tomwalters@0
|
159 xorg, yorg, (unsigned)width, (unsigned)height, 1,
|
tomwalters@0
|
160 theForeground, theBackground)) == (Window)0 ) {
|
tomwalters@0
|
161 fprintf(stderr,"can't create window\n");
|
tomwalters@0
|
162 exit(1);
|
tomwalters@0
|
163 }
|
tomwalters@0
|
164 XStoreName(theDisplay, w, name);
|
tomwalters@0
|
165 XSelectInput(theDisplay, w, event_mask);
|
tomwalters@0
|
166 XMapWindow(theDisplay, w);
|
tomwalters@0
|
167 XFlush(theDisplay);
|
tomwalters@0
|
168 return w;
|
tomwalters@0
|
169 }
|
tomwalters@0
|
170
|
tomwalters@0
|
171
|
tomwalters@0
|
172 /****************************************************************************
|
tomwalters@0
|
173 * Drawing axes and boxes in a given window w.
|
tomwalters@0
|
174 ****************************************************************************/
|
tomwalters@0
|
175 axis(w, p0,p1, ploc,axis)
|
tomwalters@0
|
176 Window w;
|
tomwalters@0
|
177 int p0,p1; /* First and last axis pixel distances, relative to parent */
|
tomwalters@0
|
178 int ploc; /* Location of axis (orthogonal pixel dist from parent org) */
|
tomwalters@0
|
179 char axis; /* Orientation of axis ('x' or 'y') */
|
tomwalters@0
|
180 {
|
tomwalters@0
|
181 if (axis=='x') XDrawLine(theDisplay, w, theGC, p0,ploc, p1,ploc);
|
tomwalters@0
|
182 if (axis=='y') XDrawLine(theDisplay, w, theGC, ploc,p0, ploc,p1);
|
tomwalters@0
|
183 }
|
tomwalters@0
|
184
|
tomwalters@0
|
185 box(w, x0,y0, x1,y1) /* draw rectangular box */
|
tomwalters@0
|
186 Window w;
|
tomwalters@0
|
187 int x0,y0, x1,y1;
|
tomwalters@0
|
188 {
|
tomwalters@0
|
189 axis(w, y0,y1, x0,'y');
|
tomwalters@0
|
190 axis(w, y0,y1, x1,'y');
|
tomwalters@0
|
191 axis(w, x0,x1, y0,'x');
|
tomwalters@0
|
192 axis(w, x0,x1, y1,'x');
|
tomwalters@0
|
193 }
|
tomwalters@0
|
194
|
tomwalters@0
|
195 /****************************************************************************
|
tomwalters@0
|
196 * Calibrating axes and boxes in a given window w.
|
tomwalters@0
|
197 ****************************************************************************/
|
tomwalters@0
|
198 struct mark_struct {
|
tomwalters@0
|
199 int type; /* type= HALFMARK or FULLMARK */
|
tomwalters@0
|
200 int position; /* mark position on screen relative to the parent system */
|
tomwalters@0
|
201 char label[16]; /* ASCII label of real plot value (FULLMARK only) */
|
tomwalters@0
|
202 };
|
tomwalters@0
|
203
|
tomwalters@0
|
204 #define NMARKS 150 /* size of array of calibration marks */
|
tomwalters@0
|
205 #define FULLMARK 10 /* Box calibration marks */
|
tomwalters@0
|
206 #define HALFMARK 5
|
tomwalters@0
|
207
|
tomwalters@0
|
208 calibrate_Axis(w, p0,p1, d0,d1, ploc,axis)
|
tomwalters@0
|
209 Window w;
|
tomwalters@0
|
210 int p0,p1; /* First and last axis pixel distances, relative to parent */
|
tomwalters@0
|
211 float d0,d1; /* First and last axis data values */
|
tomwalters@0
|
212 int ploc; /* Location of axis (orthogonal pixel dist from parent org) */
|
tomwalters@0
|
213 char axis; /* Orientation of axis ('x' or 'y') */
|
tomwalters@0
|
214 {
|
tomwalters@0
|
215 int n;
|
tomwalters@0
|
216 struct mark_struct mark[NMARKS];
|
tomwalters@0
|
217
|
tomwalters@0
|
218 if ((n = calibrate(mark, p0,p1, d0,d1)) < 0) {
|
tomwalters@0
|
219 fprintf(stderr,"mark array out of space, increase NMARKS\n");
|
tomwalters@0
|
220 exit(1);
|
tomwalters@0
|
221 }
|
tomwalters@0
|
222 if (axis=='x') plotX(w, ploc, mark, n);
|
tomwalters@0
|
223 if (axis=='y') plotY(w, ploc, mark, n);
|
tomwalters@0
|
224 }
|
tomwalters@0
|
225
|
tomwalters@0
|
226
|
tomwalters@0
|
227 calibrate_Box(w, xp0,yp0, xp1,yp1, xd0,yd0, xd1,yd1)
|
tomwalters@0
|
228 Window w;
|
tomwalters@0
|
229 int xp0,yp0, xp1,yp1;
|
tomwalters@0
|
230 float xd0,yd0, xd1,yd1;
|
tomwalters@0
|
231 {
|
tomwalters@0
|
232 calibrate_Axis(w, xp0,xp1, xd0,xd1, yp0,'x');
|
tomwalters@0
|
233 calibrate_Axis(w, yp0,yp1, yd0,yd1, xp0,'y');
|
tomwalters@0
|
234 }
|
tomwalters@0
|
235
|
tomwalters@0
|
236
|
tomwalters@0
|
237 plotX(w, Y, mark, n) /* Plot calibration marks along an X axis */
|
tomwalters@0
|
238 Window w;
|
tomwalters@0
|
239 int Y;
|
tomwalters@0
|
240 struct mark_struct mark[];
|
tomwalters@0
|
241 int n;
|
tomwalters@0
|
242 {
|
tomwalters@0
|
243 int i, H, W;
|
tomwalters@0
|
244 int X;
|
tomwalters@0
|
245
|
tomwalters@0
|
246 for (i = 0 ; i < n ; i++) {
|
tomwalters@0
|
247 X = mark[i].position;
|
tomwalters@0
|
248 XDrawLine(theDisplay, w, theGC, X, Y, X, Y+mark[i].type);
|
tomwalters@0
|
249 if (mark[i].type == FULLMARK) /* Label calibration value */
|
tomwalters@0
|
250 {
|
tomwalters@0
|
251 W = stringwidth(mark[i].label) / 2; /* Shift label left by half width */
|
tomwalters@0
|
252 H=20; /* Shift label down a bit */
|
tomwalters@0
|
253 XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label));
|
tomwalters@0
|
254 }
|
tomwalters@0
|
255 }
|
tomwalters@0
|
256 }
|
tomwalters@0
|
257
|
tomwalters@0
|
258 plotY(w, X, mark, n) /* Plot calibration marks along a Y axis */
|
tomwalters@0
|
259 Window w;
|
tomwalters@0
|
260 int X;
|
tomwalters@0
|
261 struct mark_struct mark[];
|
tomwalters@0
|
262 int n;
|
tomwalters@0
|
263 {
|
tomwalters@0
|
264 int i, H, W;
|
tomwalters@0
|
265 int Y;
|
tomwalters@0
|
266
|
tomwalters@0
|
267 for (i = 0 ; i < n ; i++) {
|
tomwalters@0
|
268 Y = mark[i].position;
|
tomwalters@0
|
269 XDrawLine(theDisplay, w, theGC, X, Y, X-mark[i].type, Y);
|
tomwalters@0
|
270 if (mark[i].type == FULLMARK) { /* Label calibration value */
|
tomwalters@0
|
271 W = stringwidth(mark[i].label) + 10;/* Shift label left by width */
|
tomwalters@0
|
272 H=5; /* Shift label down a bit */
|
tomwalters@0
|
273 XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label));
|
tomwalters@0
|
274 }
|
tomwalters@0
|
275 }
|
tomwalters@0
|
276 }
|
tomwalters@0
|
277
|
tomwalters@0
|
278 /****************************************************************************
|
tomwalters@0
|
279 * Macros used by calibration routines
|
tomwalters@0
|
280 ****************************************************************************/
|
tomwalters@0
|
281 #define rem(x,y) fabs((x) - (y)*(int)((x)/(y))) /* real remainder */
|
tomwalters@0
|
282 #define rem2(x,y) fabs((x) - (y)*(int)((x)/(y)-0.5)) /* real remainder for -ve x */
|
tomwalters@0
|
283 #define round(x) ((x >= 0) ? ((int)(x+0.5)) : ((int)(x-0.5)))
|
tomwalters@0
|
284 #define min(x,y) ((x < y) ? x : y)
|
tomwalters@0
|
285 #define EPS 1.0e-5
|
tomwalters@0
|
286
|
tomwalters@0
|
287 /****************************************************************************
|
tomwalters@0
|
288 * Calibrate one axis.
|
tomwalters@0
|
289 * Fill the given array "mark" with mark structs, and return the number of
|
tomwalters@0
|
290 * marks, or -1 indicating that the mark array is full, (and NMARKS should
|
tomwalters@0
|
291 * be increased).
|
tomwalters@0
|
292 * Each mark struct in the array gives the mark position (in pixels relative
|
tomwalters@0
|
293 * to the given first and last mark positions), the mark type (being HALFMARK
|
tomwalters@0
|
294 * or FULLMARK), and a label string (for each FULLMARK only).
|
tomwalters@0
|
295 * Arguments are as follows:
|
tomwalters@0
|
296 * p0,p1 first and last screen positions in pixels, relative to the parent
|
tomwalters@0
|
297 * window, (used to calculate mark positions on the screen).
|
tomwalters@0
|
298 * d0,d1 first and last data values (used to calculate axis labels).
|
tomwalters@0
|
299 *****************************************************************************/
|
tomwalters@0
|
300 calibrate(mark, p0, p1, d0, d1)
|
tomwalters@0
|
301 struct mark_struct mark[];
|
tomwalters@0
|
302 int p0,p1; /* first and last axis pixel distances, relative to parent */
|
tomwalters@0
|
303 float d0,d1; /* first and last axis data values */
|
tomwalters@0
|
304 {
|
tomwalters@0
|
305 int position, plotsize, nmarks=0;
|
tomwalters@0
|
306 float div, hdiv, offset, hoffset, value, hvalue;
|
tomwalters@0
|
307 float range, scalefactor, maxerror, nextvalue, lastvalue;
|
tomwalters@0
|
308 float label, real_division (), sig_figs ();
|
tomwalters@0
|
309 float tmp;
|
tomwalters@0
|
310
|
tomwalters@0
|
311 if (d0 > d1) { /* swap to get +ve range */
|
tomwalters@0
|
312 tmp = d1; d1 = d0; d0 = tmp;
|
tomwalters@0
|
313 tmp = p1; p1 = p0; p0 = tmp;
|
tomwalters@0
|
314 }
|
tomwalters@0
|
315
|
tomwalters@0
|
316 plotsize = p1-p0; /* screen size */
|
tomwalters@0
|
317 range = d1-d0; /* real plot range */
|
tomwalters@0
|
318
|
tomwalters@0
|
319 div = real_division (range);
|
tomwalters@0
|
320 hdiv = div/10; /* Halfmarks every 10th labelled division (fullmark) */
|
tomwalters@0
|
321
|
tomwalters@0
|
322 /* calculate real offset and hoffset of 1st fullmark and halfmark */
|
tomwalters@0
|
323 /* respectively, from first (ie min) real value d0. */
|
tomwalters@0
|
324 if (d0 == 0)
|
tomwalters@0
|
325 {
|
tomwalters@0
|
326 offset = hoffset = 0;
|
tomwalters@0
|
327 }
|
tomwalters@0
|
328 else
|
tomwalters@0
|
329 {
|
tomwalters@0
|
330 if (d0 > 0)
|
tomwalters@0
|
331 {
|
tomwalters@0
|
332 offset = div - rem(d0,div);
|
tomwalters@0
|
333 hoffset = hdiv - rem(d0,hdiv);
|
tomwalters@0
|
334 }
|
tomwalters@0
|
335 else /* (d0 < 0) */
|
tomwalters@0
|
336 {
|
tomwalters@0
|
337 offset = rem2(d0,div);
|
tomwalters@0
|
338 hoffset = rem2(d0,hdiv);
|
tomwalters@0
|
339 }
|
tomwalters@0
|
340 }
|
tomwalters@0
|
341
|
tomwalters@0
|
342 value = d0 + offset; /* real value of 1st fullmark */
|
tomwalters@0
|
343 hvalue = d0 + hoffset; /* real value of 1st halfmark */
|
tomwalters@0
|
344
|
tomwalters@0
|
345 scalefactor = (float)plotsize/range; /* scale factor between real range and plotted range */
|
tomwalters@0
|
346 maxerror = hdiv/2;
|
tomwalters@0
|
347 lastvalue = d0+range+maxerror;
|
tomwalters@0
|
348 nextvalue = value-maxerror;
|
tomwalters@0
|
349
|
tomwalters@0
|
350 /* Plot halfmarks up to 1st fullmark */
|
tomwalters@0
|
351
|
tomwalters@0
|
352 for ( ; hvalue < nextvalue ; hvalue += hdiv)
|
tomwalters@0
|
353 {
|
tomwalters@0
|
354 position = (int)((hvalue-d0) * scalefactor); /* actual plotted position (in plot range) */
|
tomwalters@0
|
355 setmark (&mark[nmarks], HALFMARK, p0+position, NULL);
|
tomwalters@0
|
356 if (++nmarks >= NMARKS) return -1;
|
tomwalters@0
|
357 }
|
tomwalters@0
|
358
|
tomwalters@0
|
359 /* Loop plotting fullmarks, with halfmarks between each */
|
tomwalters@0
|
360
|
tomwalters@0
|
361 for ( ; value < lastvalue ; value += div)
|
tomwalters@0
|
362 {
|
tomwalters@0
|
363 position = (int)((value-d0) * scalefactor); /* actual plotted position */
|
tomwalters@0
|
364 label = sig_figs (value, range);
|
tomwalters@0
|
365 setmark (&mark[nmarks], FULLMARK, p0+position, label);
|
tomwalters@0
|
366 if (++nmarks >= NMARKS) return -1;
|
tomwalters@0
|
367
|
tomwalters@0
|
368 /* Loop plotting halfmarks between each fullmark */
|
tomwalters@0
|
369
|
tomwalters@0
|
370 nextvalue = value+div-maxerror;
|
tomwalters@0
|
371 if (nextvalue > lastvalue) nextvalue = lastvalue;
|
tomwalters@0
|
372 for (hvalue = value+hdiv ; hvalue < nextvalue ; hvalue += hdiv)
|
tomwalters@0
|
373 {
|
tomwalters@0
|
374 position = (int)((hvalue-d0) * scalefactor); /* actual plotted position */
|
tomwalters@0
|
375 setmark (&mark[nmarks], HALFMARK, p0+position, NULL);
|
tomwalters@0
|
376 if (++nmarks >= NMARKS) return -1;
|
tomwalters@0
|
377 }
|
tomwalters@0
|
378 }
|
tomwalters@0
|
379 return nmarks;
|
tomwalters@0
|
380 }
|
tomwalters@0
|
381
|
tomwalters@0
|
382
|
tomwalters@0
|
383 float
|
tomwalters@0
|
384 real_division (range) /* Return recomended division between fullmarks on real scale */
|
tomwalters@0
|
385 float range;
|
tomwalters@0
|
386 {
|
tomwalters@0
|
387 int power;
|
tomwalters@0
|
388 float scalefactor, scaled_range, div;
|
tomwalters@0
|
389
|
tomwalters@0
|
390 if (range <= 0) {
|
tomwalters@0
|
391 fprintf(stderr,"range must be positive\n");
|
tomwalters@0
|
392 exit(1);
|
tomwalters@0
|
393 }
|
tomwalters@0
|
394
|
tomwalters@0
|
395 if (range >= 1.0)
|
tomwalters@0
|
396 power = -(int)(log10(range) + EPS);
|
tomwalters@0
|
397 else
|
tomwalters@0
|
398 power = -(int)(log10(range) - 1 + EPS);
|
tomwalters@0
|
399 scalefactor = pow (10.0, (float)power);
|
tomwalters@0
|
400
|
tomwalters@0
|
401 scaled_range = range * scalefactor; /* scaled_range is (1 <= range <= 9.9999) */
|
tomwalters@0
|
402
|
tomwalters@0
|
403 /* Set division size (in scaled_range) between given breaks in the scale */
|
tomwalters@0
|
404
|
tomwalters@0
|
405 if (scaled_range < 1.5) div = 0.1;
|
tomwalters@0
|
406 else if (scaled_range < 2.5) div = 0.2;
|
tomwalters@0
|
407 else if (scaled_range < 5.0) div = 0.5;
|
tomwalters@0
|
408 else div = 1.0;
|
tomwalters@0
|
409
|
tomwalters@0
|
410 return (div/scalefactor); /* return div scaled down to real range */
|
tomwalters@0
|
411 }
|
tomwalters@0
|
412
|
tomwalters@0
|
413
|
tomwalters@0
|
414 float
|
tomwalters@0
|
415 sig_figs (value, range) /* Round value to 2 sig figs on the scale of the range */
|
tomwalters@0
|
416 float value, range;
|
tomwalters@0
|
417 {
|
tomwalters@0
|
418 int power;
|
tomwalters@0
|
419 float scalefactor, scaled_value;
|
tomwalters@0
|
420
|
tomwalters@0
|
421 if (range >= 1.0)
|
tomwalters@0
|
422 power = 1-(int)(log10(range) + EPS);
|
tomwalters@0
|
423 else
|
tomwalters@0
|
424 power = 1-(int)(log10(range) - 1 + EPS);
|
tomwalters@0
|
425 scalefactor = pow (10.0, (float)power);
|
tomwalters@0
|
426
|
tomwalters@0
|
427 scaled_value = value * scalefactor; /* scaled_value is in range (10 <= range <= 99.999) */
|
tomwalters@0
|
428 value = round(scaled_value);
|
tomwalters@0
|
429
|
tomwalters@0
|
430 return (value/scalefactor);
|
tomwalters@0
|
431 }
|
tomwalters@0
|
432
|
tomwalters@0
|
433 /* Fill one mark struct with the mark position, type, and label */
|
tomwalters@0
|
434 setmark (mark, mark_type, x, x1)
|
tomwalters@0
|
435 struct mark_struct *mark;
|
tomwalters@0
|
436 int mark_type;
|
tomwalters@0
|
437 int x; /* position */
|
tomwalters@0
|
438 float x1; /* value of label */
|
tomwalters@0
|
439 {
|
tomwalters@0
|
440 if ((mark->type = mark_type) == FULLMARK)
|
tomwalters@0
|
441 labelstring(mark->label, x1);
|
tomwalters@0
|
442 mark->position = x;
|
tomwalters@0
|
443 }
|
tomwalters@0
|
444
|
tomwalters@0
|
445 /* Return with str containing an appropriate ASCII string of the given value */
|
tomwalters@0
|
446 labelstring(str, value)
|
tomwalters@0
|
447 char *str;
|
tomwalters@0
|
448 float value;
|
tomwalters@0
|
449 {
|
tomwalters@0
|
450 float decval; /* decimal part of a number */
|
tomwalters@0
|
451
|
tomwalters@0
|
452 decval = value - (int)value;
|
tomwalters@0
|
453 if (value < 0) decval = -decval;
|
tomwalters@0
|
454 if (value > -EPS && value < EPS) sprintf(str,"0" );
|
tomwalters@0
|
455 else if (fabs(value) >= 10000) sprintf(str,"%g", value);
|
tomwalters@0
|
456 else if (decval <= EPS) sprintf(str,"%d", (int)value);
|
tomwalters@0
|
457 else if (decval <= 0.001) sprintf(str,"%.4f", value);
|
tomwalters@0
|
458 else if (decval <= 0.01) sprintf(str,"%.3f", value);
|
tomwalters@0
|
459 else if (decval <= 0.1) sprintf(str,"%.2f", value);
|
tomwalters@0
|
460 else sprintf(str,"%.1f", value);
|
tomwalters@0
|
461 }
|
tomwalters@0
|
462
|
tomwalters@0
|
463 /****************************************************************************
|
tomwalters@0
|
464 Text printing routines.
|
tomwalters@0
|
465 ****************************************************************************/
|
tomwalters@0
|
466 /* The origin for a char is an x-value of `lbearing' to the left of the */
|
tomwalters@0
|
467 /* left-most char ink, and a y-value between the `ascent' and the */
|
tomwalters@0
|
468 /* `descent', (ie along an underline), (ref 6-20). */
|
tomwalters@0
|
469 /* The `margin' is an ad-hoc idea. */
|
tomwalters@0
|
470
|
tomwalters@0
|
471 /* Return the width in pixels of the given string, using the current font */
|
tomwalters@0
|
472 stringwidth(str)
|
tomwalters@0
|
473 char *str;
|
tomwalters@0
|
474 {
|
tomwalters@0
|
475 int width;
|
tomwalters@0
|
476
|
tomwalters@0
|
477 width = XTextWidth(theFont, str, strlen(str));
|
tomwalters@0
|
478 return width;
|
tomwalters@0
|
479 }
|
tomwalters@0
|
480
|
tomwalters@0
|
481 /* Return the height in pixels of the given string, using the current font */
|
tomwalters@0
|
482 stringheight(str)
|
tomwalters@0
|
483 char *str;
|
tomwalters@0
|
484 {
|
tomwalters@0
|
485 XCharStruct stringinfo; /* ref Xlib 6-17 */
|
tomwalters@0
|
486 int dr, fa, fd;
|
tomwalters@0
|
487 short asc, desc, width;
|
tomwalters@0
|
488 int height;
|
tomwalters@0
|
489
|
tomwalters@0
|
490 XTextExtents(theFont, str, strlen(str), &dr,&fa,&fd, &stringinfo);
|
tomwalters@0
|
491 asc = stringinfo.ascent; /* max of char ascents in string */
|
tomwalters@0
|
492 desc = stringinfo.descent; /* max of char descents in string */
|
tomwalters@0
|
493 width = stringinfo.width; /* sum of char widths across string */
|
tomwalters@0
|
494 height = asc+desc; /* max height over all chars */
|
tomwalters@0
|
495 return height;
|
tomwalters@0
|
496 }
|
tomwalters@0
|
497
|
tomwalters@0
|
498
|
tomwalters@0
|
499 /****************************************************************************
|
tomwalters@0
|
500 Misc routines.
|
tomwalters@0
|
501 ****************************************************************************/
|
tomwalters@0
|
502 /* Plot a dot at data coord (x,y). Dotsize=0,1,2,3,.., and size 0 is empty */
|
tomwalters@0
|
503 Dot(w,x,y,dotsize)
|
tomwalters@0
|
504 Window w;
|
tomwalters@0
|
505 float x,y;
|
tomwalters@0
|
506 int dotsize;
|
tomwalters@0
|
507 {
|
tomwalters@0
|
508 int d, X,Y;
|
tomwalters@0
|
509
|
tomwalters@0
|
510 if ((d=dotsize-1) >= 0) {
|
tomwalters@0
|
511 if (d==0) /* dotsize = 1 */
|
tomwalters@0
|
512 Point(w, x,y);
|
tomwalters@0
|
513 else { /* dotsize > 1 */
|
tomwalters@0
|
514 for (X=(-d) ; X<=d ; X++)
|
tomwalters@0
|
515 for (Y=(-d) ; Y<=d ; Y++)
|
tomwalters@0
|
516 XDrawPoint(theDisplay,w,theGC,px(x)+X,py(y)+Y);
|
tomwalters@0
|
517 }
|
tomwalters@0
|
518 }
|
tomwalters@0
|
519 }
|