comparison tools/x11coord.c @ 0:5242703e91d3 tip

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