comparison tools/x11coord.h @ 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 Still to consider:
3
4 A structure for a box-object, containing a complete set of internal
5 variables for one box. A routine could allocate a structure, call the
6 routines set_box_parameters() and set_data_parameters(), and return a ptr
7 to the structure. Now a set of #defines could take a structure pointer
8 (just as they currently often take a window ptr), and could call the
9 appropriate sub-routines using the internal variables for that box.
10 (The window could be a member of the structute too).
11
12 With this, you could easily maintain a set of boxes, and plot anything
13 in any of them. But if you need ore than one window, then you'll need a
14 window structure too, (to hold window parameters for each window).
15 For example:
16
17 struct st_window {
18 Window w;
19 int x,y; window origin wrt display
20 unsigned int width,height; window size
21 GC gc;
22 };
23
24 struct st_box {
25 struct st_window * pt; parent window
26 char *fname; file name for data
27 int n, s; num points and start point in file
28 ...all system variables...
29 };
30
31 */
32
33
34 /****************************************************************************
35
36 x11coord.h A file for inclusion into X11 plotting programs.
37 ---------- (See x11test.c for example).
38
39 ****************************************************************************
40
41 User parameters:
42 ================
43 1. Window parameters - Set size and position of a window on the display.
44 set_window_parameters(xorg,yorg, width,height)
45 int xorg,yorg Window origin (pixel coords of top-left wrt Display).
46 int width,height Window size (pixels).
47
48 2. Box parameters - Set size and position of a box in a preset window.
49 a) set_box_parameters(xorg,yorg, width,height)
50 int xorg,yorg Box origin (pixel coords of bottom-left wrt window).
51 int width,height Box size (pixels).
52 b) set_bordered_box(bpc)
53 int bpc Box border (constant width) as %age of window size.
54
55 3. Data parameters - Set area and location of data space to appear in box.
56 set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
57 int xp0,yp0 Plot origin (as a %age of box size from box origin).
58 float xd0,yd0 Data origin (data coords to appear under plot origin).
59 float xrange,yrange Data ranges (area of data space to appear under plot).
60
61 Notes:
62 1. Pixel coordinates and sizes are ints. Data coordinates and sizes are floats.
63 2. Pixel coords refer to the X11 coord system which has origin (0,0) in the
64 top-left of each window. Data coords refer to the user coord system which
65 has its origin (0,0) in the bottom-left of each box.
66 3. The parameter initialization routines must be called in order, (window,
67 box, data), and must be done first, otherwise macros which use the system
68 variables will not work. As a minimum, you MUST do set_window_parameters(),
69 and this will give you a box the same size as the window, with origin in
70 the bottom-left, with data origin at the box origin, and data ranges the
71 same as pixels.
72 4. Although its true that set_window_parameters only sets window pixel sizes,
73 set_box_parameters only sets box pixel sizes, and set_data_parameters only
74 sets data sizes, the data sizes are somewhat dependent upon the pixel
75 sizes, and so if you change the window or box parameters during a program,
76 (eg, to resize a box), then you must re-initialize set_data_parameters at
77 the same time. (Call it again with the same initial arguments; it will
78 re-initialize internal parameters).
79
80 User routines and macros:
81 =========================
82 Set system private parameters.
83 -----------------------------
84 set_window_parameters(xorg,yorg, width,height)
85 set_box_parameters(xorg,yorg, width,height)
86 set_bordered_box(bpc)
87 set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
88 Open connection and create window.
89 ---------------------------------
90 xopen()
91 Window xcreate(name, event_mask)
92 Convert coordinates.
93 -------------------
94 int px(x)
95 int py(y)
96 float xp(p)
97 float yp(p)
98 float xpc(pc)
99 float ypc(pc)
100 Return pixel coordinates.
101 -----------------------
102 int pleft()
103 int pright()
104 int pbottom()
105 int ptop()
106 int pwidth()
107 int pheight()
108 Return data coordinates.
109 -----------------------
110 float xleft()
111 float xright()
112 float ybottom()
113 float ytop()
114 float xwidth()
115 float yheight()
116 float xcentre()
117 float ycentre()
118 float Xjitter(x,p)
119 float Yjitter(y,p)
120 Test data coordinates.
121 ---------------------
122 bool Xinbox(x)
123 bool Yinbox(y)
124 bool inbox(x,y)
125 Draw and calibrate boxes and axes.
126 ---------------------------------
127 draw_Xaxis(w,yval)
128 calibrate_Xaxis(w,yval)
129 draw_Yaxis(w,xval)
130 calibrate_Yaxis(w,xval)
131 draw_box(w)
132 calibrate_box(w)
133 draw_calibrated_box(w)
134 Draw points, lines, and strings, etc..
135 -------------------------------------
136 setLinewidth(width)
137 Point(w,x,y)
138 xPoint(w,x,y)
139 Line(w,x1,y1,x2,y2)
140 xLine(w,x1,y1,x2,y2)
141 String(w,x,y,string)
142 xString(w,x,y,string)
143 Cross(w,x,y)
144 xCross(w,x,y)
145 Dot(w,x,y,dotsize)
146 xDot(w,x,y,dotsize)
147 Text string parameters.
148 -----------------------
149 setFont("fontname")
150 int nlines()
151 int ncols()
152 Return pixel sizes based on current "theFont".
153 ----------------------------------------------
154 int max_charwidth()
155 int max_charheight()
156 int stringwidth(string)
157 int stringheight(string)
158 int linespacing() white space between lines.
159 int lineheight() total line (y-value) increment.
160 int colwidth() total character (x-value) increment.
161 int margin() white space at sides of page.
162 int headroom() white space at head and foot of page.
163 Return pixel coordinates.
164 -------------------------
165 int leftmargin()
166 int rightmargin()
167 int topmargin()
168 int bottommargin()
169 int line(i)
170 int col(j)
171 Draw text strings.
172 ------------------
173 topline(w,string)
174 bottomline(w,string)
175 lineString(w,string,i,j)
176 leftString(w,string,i)
177 rightString(w,string,i)
178 centreString(w,string,i)
179 supertopline(w,string)
180
181
182 Notes:
183 1. The user routines conventionally take data coordinate arguments.
184 To convert pixel coordinates to data, use the xp,yp macros.
185
186 Development of coord system scaling transformations:
187 ====================================================
188 Internal variables (initialized by the `set' routines and used by the `px'
189 macros) are pixel coords and sizes, and refer to the X11 coord system:
190
191 | _Xp0 |
192 +---------------+
193 | |
194
195 | _Xp1 |
196 +---------------------------+
197 | |
198 (0,0)
199 -+- -+- +-------------------------------------------+
200 | | |Window |
201 | _Yp1| | |
202 | | | _Wb |
203 _Yp0| -+- | (_Xp0,_Yp1) +-----------+ (_Xp1,_Yp1) |
204 | | |Box | |
205 | | | |_Hb |
206 | | | | |
207 -+- | (_Xp0,_Yp0) +-----------+ (_Xp1,_Yp0) |
208 | |
209 | |
210 | |
211 +-------------------------------------------+
212
213 Consider a box of width Wb pixels (on horizontal axis) and height Hb pixels
214 (on vertical axis). Let this box size represent data ranges xrange and yrange,
215 (corresponding to Wb and Hb respectively). Let the pixel origin and the data
216 origin be superimposed at (0,0) in the bottom-left corner. Then a data coord
217 (x,y) is transformed into a pixel coord by the scaling:
218 px(x) = x * Wb/xrange
219 py(y) = y * Hb/yrange
220
221 If the data coordinate which we wish to appear at the plot origin is actually
222 (xd0,yd0), then the data origin must be shifted off the pixel origin, so that
223 the data coord (xd0,yd0) is represented by pixel coord (0,0). Hence:
224 px(x) = (x-xd0) * Wb/xrange
225 py(y) = (y-yd0) * Hb/yrange
226
227 It is necessary to invert the y-axis so that pixel coords are consistent with
228 the X11 coord system, (with pixel origin in the top-left of a window and pixel
229 y-values which increase down the window). Let the box be positioned in the
230 top-left corner of its parent window, so that the X11 origin corresponds with
231 the top-left corner of the box. Then the y-axis is inverted by:
232 px(x) = (x-xd0) * Wb/xrange
233 py(y) = Hb - (y-yd0) * Hb/yrange
234
235 In general, the box will be positioned within its parent window as in the
236 diagram above. The box is shifted into the window by an x-value Xp0 and a
237 y-value Yp1, and these must be added to any pixel coordinate:
238 px(x) = Xp0 + (x-xd0) * Wb/xrange
239 py(y) = Yp1 + Hb - (y-yd0) * Hb/yrange
240
241 Although Yp0 is the y-value at the bottom of the box, at its default origin,
242 note that Yp0>Yp1, since y-values increase down the window in the X11 pixel
243 coordinate system.
244 Finally, we may want the user origin of the box to be somewhere other than the
245 bottom-left corner, (Eg, scatter plots often have the user origin in the
246 centre of the plot; time-waveform plot often have the origin half-way up the
247 left side of the plot). To place the user origin at a pixel coordinate of
248 (xshift,yshift), we add xshift and subtract yshift from the transformed pixel
249 coordinates. (We subtract yshift since the transformed pixel coord is in the
250 X11 coord system). So we have:
251 px(x) = Xp0 + xshift + (x-xd0) * Wb/xrange
252 py(y) = Yp1 + Hb - yshift - (y-yd0) * Hb/yrange
253
254 Grouping terms we have:
255 px(x) = Xp0 + xshift - xd0*Wb/xrange + x*Wb/xrange
256 py(y) = Yp1 + Hb - yshift + yd0*Hb/yrange - y*Hb/yrange
257
258 Now substituting:
259 xoffset = Xp0 + xshift - xd0*Wb/xrange ; xscale = Wb/xrange
260 yoffset = Yp1 + Hb - yshift + yd0*Hb/yrange ; yscale = Hb/yrange
261 We have:
262 px(x) = xoffset + x * xscale
263 py(y) = yoffset - y * yscale
264
265 The inverse transformations xp(p) and yp(p) are just the inverse of these.
266
267 A typical program might be as follows:
268 -------------------------------------
269 ------------------------------------------------------------------
270 |#include <stdio.h> |
271 |#include <math.h> |
272 | |
273 |#include "x11coord.h" |
274 | |
275 | |
276 |main() |
277 |{ |
278 | Window w; |
279 | ..... |
280 | |
281 | set_window_parameters(100,85, 775,775); |
282 | set_bordered_box(10); |
283 | set_data_parameters(50,50, 0,0, 2.0,2.0); |
284 | |
285 | xopen(); |
286 | w = xcreate("test", ButtonPressMask | ExposureMask); |
287 | xevent_monitor(w); |
288 |} |
289 | |
290 | |
291 |xevent_monitor(w) |
292 |Window w; |
293 |{ |
294 | XEvent event; |
295 | |
296 | for ( ; ; ) { |
297 | XNextEvent(theDisplay,&event); |
298 | switch (event.type) { |
299 | .... |
300 | case ButtonPress: |
301 | switch(event.xbutton.button) { |
302 | case Button1: |
303 | XDestroyWindow(theDisplay,w); |
304 | return; |
305 | case Button2: |
306 | .... |
307 | } |
308 | break; |
309 | case Expose: |
310 | if (event.xexpose.count == 0) { |
311 | draw_calibrated_box(w); |
312 | plot(w); |
313 | } |
314 | break; |
315 | .... |
316 | } |
317 | } |
318 |} |
319 | |
320 ------------------------------------------------------------------
321 The purpose of the xevent_monitor is to loop endlessly and keep the program
322 running while the window is displayed. The window vanishes when the monitor
323 is quit using (in this example) the left mouse button.
324 Note that you let all plotting routines be called when an expose-event has
325 been caught. This is not just so that the screen re-draws itself when exposed,
326 but also to avoid data at the start of the plot going missing.
327 If you don't set up for expose-events, but try to plot data as soon as the
328 window is created, then it turns out that you tend to lose the first few bytes
329 of plot data. The correct way is to plot data when the window is exposed.
330 The window-creation and mapping process generates an expose event
331 automatically and, when caught by the event monitor, this causes the window to
332 be first plotted.
333
334
335 *****************************************************************************/
336 #include <X11/X.h> /* /usr/include/X11/X.h */
337 #include <X11/Xlib.h> /* /usr/include/X11/Xlib.h */
338
339
340 static char defFontString[] = "fixed" , *theFontString = defFontString ;
341
342
343 /****************************************************************************
344 * Defaults for some standard window sizes
345 ****************************************************************************/
346 #define FULLXORG 5 /* Full screen size */
347 #define FULLYORG 90
348 #define FULLWIDTH 1000
349 #define FULLHEIGHT 750
350
351 #define A4XORG 190 /* A4 size */
352 #define A4YORG 85
353 #define A4WIDTH 620
354 #define A4HEIGHT 760
355
356 #define PLOTXORG 100 /* Rectangular plotting area */
357 #define PLOTYORG 155
358 #define PLOTWIDTH 800
359 #define PLOTHEIGHT 600
360
361 #define BOXXORG 100 /* Square box */
362 #define BOXYORG 85
363 #define BOXWIDTH 775
364 #define BOXHEIGHT 775
365
366 /****************************************************************************
367 * Macros for pixel-data transformation
368 ****************************************************************************/
369 /* pixel coord from data coord */
370 #define px(x) ( (int)(_xoffset + (x) * _xscale) )
371 #define py(y) ( (int)(_yoffset - (y) * _yscale) )
372 /* data coord from pixel coord */
373 #define xp(p) ( (float)(((p) - _xoffset) / _xscale) )
374 #define yp(p) ( (float)((_yoffset - (p)) / _yscale) )
375 /* data coord from a %age of data range */
376 #define xpc(pc) ( ((xleft()+xright())*pc) / 100 )
377 #define ypc(pc) ( ((ybottom()+ytop())*pc) / 100 )
378 /* data coord of box centre */
379 #define xcentre() xpc(50)
380 #define ycentre() ypc(50)
381 /* pixel limits of box (note that ptop() < pbottom() ). */
382 #define pleft() (_Xp0)
383 #define pright() (_Xp1)
384 #define pbottom() (_Yp0)
385 #define ptop() (_Yp1)
386 #define pwidth() (_Wb)
387 #define pheight() (_Hb)
388 /* data limits of box */
389 #define xleft() xp(_Xp0)
390 #define xright() xp(_Xp1)
391 #define ybottom() yp(_Yp0)
392 #define ytop() yp(_Yp1)
393 #define xwidth() xp(_Wb)
394 #define yheight() yp(_Hb)
395 /* test if data argument is in box */
396 #define Xinbox(x) ( (xleft()<=x && x<=xright()) ? 1 : 0 )
397 #define Yinbox(y) ( (ybottom()<=y && y<=ytop()) ? 1 : 0 )
398 #define inbox(x,y) ( (Xinbox(x) && Yinbox(y)) ? 1 : 0 )
399 /* jitter data value (ie move by a given pixel distance) */
400 #define Xjitter(x,p) ( xp(px(x)+(p)) )
401 #define Yjitter(y,p) ( yp(py(y)+(p)) )
402
403 /****************************************************************************
404 * Macros for routines (using preset system parameters)
405 ****************************************************************************/
406 /* Xaxes: yval is a data value at which to place a horizontal axis. */
407 /* For example: 0 (zero line), ybottom() (box-bottom), ytop() (box-top). */
408 #define draw_Xaxis(w,yval) if (Yinbox(yval)) axis(w, _Xp0,_Xp1, py(yval),'x')
409 #define calibrate_Xaxis(w,yval) calibrate_Axis(w, _Xp0,_Xp1, _Xd0,_Xd1, py(yval),'x')
410
411 /* Yaxes: xval is a data value at which to place a vertical axis. */
412 /* For example: 0 (zero line), xleft() (box-left), xright() (box-right). */
413 #define draw_Yaxis(w,xval) if (Xinbox(xval)) axis(w, _Yp0,_Yp1, px(xval),'y')
414 #define calibrate_Yaxis(w,xval) calibrate_Axis(w, _Yp0,_Yp1, _Yd0,_Yd1, px(xval),'y')
415
416 #define draw_box(w) box(w, _Xp0,_Yp0, _Xp1,_Yp1)
417 #define calibrate_box(w) calibrate_Box(w, _Xp0,_Yp0, _Xp1,_Yp1, _Xd0,_Yd0, _Xd1,_Yd1)
418 #define draw_calibrated_box(w) draw_box(w); calibrate_box(w)
419
420 #define xcreate(name,mask) xCreate(name,mask, _xorg,_yorg, _width,_height)
421
422 /****************************************************************************
423 * Macros for standard X11 commands
424 ****************************************************************************/
425 #define Point(w,x,y) XDrawPoint(theDisplay,w,theGC,px(x),py(y))
426 #define Line(w,x1,y1,x2,y2) XDrawLine(theDisplay,w,theGC,px(x1),py(y1),px(x2),py(y2))
427 #define String(w,x,y,string) XDrawString(theDisplay, w, theGC, px(x),py(y), string, strlen(string))
428
429 #define Cross(w,x,y) XDrawLine(theDisplay,w,theGC,px(x)-10,py(y),px(x)+10,py(y)); XDrawLine(theDisplay,w,theGC,px(x),py(y)-10,px(x),py(y)+10)
430
431 #define xPoint(w,x,y) if (inbox(x,y)) Point(w,x,y)
432 #define xLine(w,x1,y1,x2,y2) if (inbox(x1,y1) && inbox(x2,y2)) Line(w,x1,y1,x2,y2)
433 #define xString(w,x,y,string) if (inbox(x,y)) String(w,x,y,string)
434
435 #define xCross(w,x,y) if (inbox(x,y)) Cross(w,x,y)
436 #define xDot(w,x,y,dotsize) if (inbox(x,y)) Dot(w,x,y,dotsize)
437
438 /* Max width and height (pixels) of chars in current font, (ref 6-17, 6-19) */
439 #define max_charwidth() ( theFont->max_bounds.rbearing - theFont->min_bounds.lbearing )
440 #define max_charheight() ( theFont->max_bounds.ascent + theFont->max_bounds.descent )
441 /* Number of lines and cols (chars) of current font which fit into box */
442 #define linespacing() ( (theFont->max_bounds.descent)>>1 )
443 #define lineheight() ( max_charheight()+linespacing() )
444 #define colwidth() ( max_charwidth() )
445 #define nlines() ( pheight() / lineheight() )
446 #define ncols() ( pwidth() / colwidth() )
447 #define topline(w,string) lineString(w,string,1,1)
448 #define bottomline(w,string) lineString(w,string,nlines(),1)
449 #define margin() ( theFont->max_bounds.lbearing + theFont->max_bounds.rbearing )
450 #define headroom() ( theFont->max_bounds.ascent )
451 #define leftmargin() ( pleft() + margin() )
452 #define rightmargin() ( pright() - margin() )
453 #define topmargin() ( ptop() + headroom() )
454 #define bottommargin() ( pbottom() - headroom() )
455 #define line(i) ( topmargin() + (i-1)*lineheight() )
456 #define col(j) ( leftmargin() + (j-1)*colwidth() )
457 #define lineString(w,string,i,j) ( XDrawString(theDisplay,w,theGC,col(j),line(i),string,strlen(string)) )
458 #define leftString(w,string,i) ( XDrawString(theDisplay,w,theGC,leftmargin(),line(i),string,strlen(string)) )
459 #define rightString(w,string,i) ( XDrawString(theDisplay,w,theGC,rightmargin()-stringwidth(string),line(i),string,strlen(string)) )
460 #define centreString(w,string,i) ( XDrawString(theDisplay,w,theGC,(pwidth()-stringwidth(string))>>1,line(i),string,strlen(string)) )
461 #define supertopline(w,string) ( XDrawString(theDisplay,w,theGC,col(1),ptop()-max_charheight()-headroom(),string,strlen(string)) )
462
463
464 /****************************************************************************
465 * Window parameters (X11-specific).
466 ****************************************************************************/
467 Display *theDisplay;
468 int theScreen; /* screen_number */
469 int theWidth; /* horizontal size, in pixels */
470 int theHeight; /* vertical size, in pixels */
471 unsigned long theForeground; /* lines, text, and border pixel value */
472 unsigned long theBackground; /* background pixel value */
473 GC theGC; /* graphics context */
474 XFontStruct *theFont; /* current font used to print text */
475 unsigned long theBlack; /* pixel value for black */
476 unsigned long theWhite; /* pixel value for white */
477
478 /****************************************************************************
479 * System (global) variables
480 *****************************************************************************/
481 int _xorg, _yorg; /* Window origin (pixel coords top-left wrt Display)*/
482 int _width, _height;/* Window size (pixels). */
483
484 int _Xp0, _Yp0; /* Box origin (pixel coords at bottom-left) */
485 int _Xp1, _Yp1; /* Box limits (pixel coords at top-right) */
486 int _Wb, _Hb; /* Box size (pixels). */
487
488 float _Xd0, _Yd0; /* Box origin (data coords at bottom-left) */
489 float _Xd1, _Yd1; /* Box limits (data coords at top-right) */
490 float _xrange,_yrange;/* Box size (data ranges). */
491
492 int _xshift,_yshift;/* Plot origin (pixel coords from box origin) */
493 float _xd0, _yd0; /* Data coords fixed at plot origin */
494
495 float _xoffset,_yoffset;
496 float _xscale, _yscale;
497
498 /****************************************************************************
499 * Functions (in x11coord.c)
500 *****************************************************************************/
501 extern set_window_parameters();
502 extern set_box_parameters();
503 extern set_bordered_box();
504 extern set_data_parameters();
505 extern xopen();
506 extern GC initGC();
507 extern setLinewidth();
508 extern setFont();
509 extern Window xCreate();
510 extern axis();
511 extern box();
512 extern calibrate_Axis();
513 extern calibrate_Box();
514 extern plotX();
515 extern plotY();
516 extern int stringwidth();
517 extern int stringheight();
518 extern calibrate();
519 extern Dot();
520