diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11coord.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,520 @@
+/*
+	Still to consider:
+
+    A structure for a box-object, containing a complete set of internal
+    variables for one box. A routine could allocate a structure, call the
+    routines set_box_parameters() and set_data_parameters(), and return a ptr
+    to the structure. Now a set of #defines could take a structure pointer
+    (just as they currently often take a window ptr), and could call the
+    appropriate sub-routines using the internal variables for that box.
+    (The window could be a member of the structute too).
+
+    With this, you could easily maintain a set of boxes, and plot anything
+    in any of them. But if you need ore than one window, then you'll need a
+    window structure too, (to hold window parameters for each window).
+    For example:
+
+    struct st_window {
+	Window          w;
+	int             x,y;            window origin wrt display
+	unsigned int    width,height;   window size
+	GC              gc;
+    };
+
+    struct st_box {
+	struct st_window * pt;          parent window
+	char *fname;                    file name for data
+	int   n, s;                     num points and start point in file
+	...all system variables...
+    };
+
+*/
+
+
+/****************************************************************************
+
+    x11coord.h    A file for inclusion into X11 plotting programs.
+    ----------    (See x11test.c for example).
+
+ ****************************************************************************
+
+User parameters:
+================
+1. Window parameters - Set size and position of a window on the display.
+    set_window_parameters(xorg,yorg, width,height)
+    int   xorg,yorg       Window origin (pixel coords of top-left wrt Display).
+    int   width,height    Window size (pixels).
+
+2. Box parameters -    Set size and position of a box in a preset window.
+ a) set_box_parameters(xorg,yorg, width,height)
+    int   xorg,yorg       Box origin (pixel coords of bottom-left wrt window).
+    int   width,height    Box size (pixels).
+ b) set_bordered_box(bpc)
+    int   bpc             Box border (constant width) as %age of window size.
+
+3. Data parameters -   Set area and location of data space to appear in box.
+    set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
+    int   xp0,yp0         Plot origin (as a %age of box size from box origin).
+    float xd0,yd0         Data origin (data coords to appear under plot origin).
+    float xrange,yrange   Data ranges (area of data space to appear under plot).
+
+Notes:
+1. Pixel coordinates and sizes are ints. Data coordinates and sizes are floats.
+2. Pixel coords refer to the X11 coord system which has origin (0,0) in the
+   top-left of each window. Data coords refer to the user coord system which
+   has its origin (0,0) in the bottom-left of each box.
+3. The parameter initialization routines must be called in order, (window,
+   box, data), and must be done first, otherwise macros which use the system
+   variables will not work. As a minimum, you MUST do set_window_parameters(),
+   and this will give you a box the same size as the window, with origin in
+   the bottom-left, with data origin at the box origin, and data ranges the
+   same as pixels.
+4. Although its true that set_window_parameters only sets window pixel sizes,
+   set_box_parameters only sets box pixel sizes, and set_data_parameters only
+   sets data sizes, the data sizes are somewhat dependent upon the pixel
+   sizes, and so if you change the window or box parameters during a program,
+   (eg, to resize a box), then you must re-initialize set_data_parameters at
+   the same time. (Call it again with the same initial arguments; it will
+   re-initialize internal parameters).
+
+User routines and macros:
+=========================
+Set system private parameters.
+-----------------------------
+	      set_window_parameters(xorg,yorg, width,height)
+	      set_box_parameters(xorg,yorg, width,height)
+	      set_bordered_box(bpc)
+	      set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
+Open connection and create window.
+---------------------------------
+	      xopen()
+Window        xcreate(name, event_mask)
+Convert coordinates.
+-------------------
+int           px(x)
+int           py(y)
+float         xp(p)
+float         yp(p)
+float         xpc(pc)
+float         ypc(pc)
+Return pixel coordinates.
+-----------------------
+int           pleft()
+int           pright()
+int           pbottom()
+int           ptop()
+int           pwidth()
+int           pheight()
+Return data coordinates.
+-----------------------
+float         xleft()
+float         xright()
+float         ybottom()
+float         ytop()
+float         xwidth()
+float         yheight()
+float         xcentre()
+float         ycentre()
+float         Xjitter(x,p)
+float         Yjitter(y,p)
+Test data coordinates.
+---------------------
+bool          Xinbox(x)
+bool          Yinbox(y)
+bool          inbox(x,y)
+Draw and calibrate boxes and axes.
+---------------------------------
+	      draw_Xaxis(w,yval)
+	      calibrate_Xaxis(w,yval)
+	      draw_Yaxis(w,xval)
+	      calibrate_Yaxis(w,xval)
+	      draw_box(w)
+	      calibrate_box(w)
+	      draw_calibrated_box(w)
+Draw points, lines, and strings, etc..
+-------------------------------------
+	      setLinewidth(width)
+	      Point(w,x,y)
+	      xPoint(w,x,y)
+	      Line(w,x1,y1,x2,y2)
+	      xLine(w,x1,y1,x2,y2)
+	      String(w,x,y,string)
+	      xString(w,x,y,string)
+	      Cross(w,x,y)
+	      xCross(w,x,y)
+	      Dot(w,x,y,dotsize)
+	      xDot(w,x,y,dotsize)
+Text string parameters.
+-----------------------
+	      setFont("fontname")
+int           nlines()
+int           ncols()
+Return pixel sizes based on current "theFont".
+----------------------------------------------
+int           max_charwidth()
+int           max_charheight()
+int           stringwidth(string)
+int           stringheight(string)
+int           linespacing()             white space between lines.
+int           lineheight()              total line (y-value) increment.
+int           colwidth()                total character (x-value) increment.
+int           margin()                  white space at sides of page.
+int           headroom()                white space at head and foot of page.
+Return pixel coordinates.
+-------------------------
+int           leftmargin()
+int           rightmargin()
+int           topmargin()
+int           bottommargin()
+int           line(i)
+int           col(j)
+Draw text strings.
+------------------
+	      topline(w,string)
+	      bottomline(w,string)
+	      lineString(w,string,i,j)
+	      leftString(w,string,i)
+	      rightString(w,string,i)
+	      centreString(w,string,i)
+	      supertopline(w,string)
+
+
+Notes:
+1. The user routines conventionally take data coordinate arguments.
+   To convert pixel coordinates to data, use the xp,yp macros.
+
+Development of coord system scaling transformations:
+====================================================
+Internal variables (initialized by the `set' routines and used by the `px'
+macros) are pixel coords and sizes, and refer to the X11 coord system:
+
+		|    _Xp0       |
+		+---------------+
+		|               |
+
+		|          _Xp1             |
+		+---------------------------+
+		|                           |
+	    (0,0)
+   -+-    -+-   +-------------------------------------------+
+    |      |    |Window                                     |
+    |  _Yp1|    |                                           |
+    |      |    |                    _Wb                    |
+_Yp0|     -+-   |   (_Xp0,_Yp1) +-----------+ (_Xp1,_Yp1)   |
+    |           |               |Box        |               |
+    |           |               |           |_Hb            |
+    |           |               |           |               |
+   -+-          |   (_Xp0,_Yp0) +-----------+ (_Xp1,_Yp0)   |
+		|                                           |
+		|                                           |
+		|                                           |
+		+-------------------------------------------+
+
+Consider a box of width Wb pixels (on horizontal axis) and height Hb pixels
+(on vertical axis). Let this box size represent data ranges xrange and yrange,
+(corresponding to Wb and Hb respectively). Let the pixel origin and the data
+origin be superimposed at (0,0) in the bottom-left corner. Then a data coord
+(x,y) is transformed into a pixel coord by the scaling:
+    px(x) = x * Wb/xrange
+    py(y) = y * Hb/yrange
+
+If the data coordinate which we wish to appear at the plot origin is actually
+(xd0,yd0), then the data origin must be shifted off the pixel origin, so that
+the data coord (xd0,yd0) is represented by pixel coord (0,0). Hence:
+    px(x) = (x-xd0) * Wb/xrange
+    py(y) = (y-yd0) * Hb/yrange
+
+It is necessary to invert the y-axis so that pixel coords are consistent with
+the X11 coord system, (with pixel origin in the top-left of a window and pixel
+y-values which increase down the window). Let the box be positioned in the
+top-left corner of its parent window, so that the X11 origin corresponds with
+the top-left corner of the box. Then the y-axis is inverted by:
+    px(x) =      (x-xd0) * Wb/xrange
+    py(y) = Hb - (y-yd0) * Hb/yrange
+
+In general, the box will be positioned within its parent window as in the
+diagram above. The box is shifted into the window by an x-value Xp0 and a
+y-value Yp1, and these must be added to any pixel coordinate:
+    px(x) = Xp0      + (x-xd0) * Wb/xrange
+    py(y) = Yp1 + Hb - (y-yd0) * Hb/yrange
+
+Although Yp0 is the y-value at the bottom of the box, at its default origin,
+note that Yp0>Yp1, since y-values increase down the window in the X11 pixel
+coordinate system.
+Finally, we may want the user origin of the box to be somewhere other than the
+bottom-left corner, (Eg, scatter plots often have the user origin in the
+centre of the plot; time-waveform plot often have the origin half-way up the
+left side of the plot). To place the user origin at a pixel coordinate of
+(xshift,yshift), we add xshift and subtract yshift from the transformed pixel
+coordinates. (We subtract yshift since the transformed pixel coord is in the
+X11 coord system). So we have:
+    px(x) = Xp0      + xshift + (x-xd0) * Wb/xrange
+    py(y) = Yp1 + Hb - yshift - (y-yd0) * Hb/yrange
+
+Grouping terms we have:
+    px(x) = Xp0      + xshift - xd0*Wb/xrange + x*Wb/xrange
+    py(y) = Yp1 + Hb - yshift + yd0*Hb/yrange - y*Hb/yrange
+
+Now substituting:
+      xoffset = Xp0      + xshift - xd0*Wb/xrange ;     xscale = Wb/xrange
+      yoffset = Yp1 + Hb - yshift + yd0*Hb/yrange ;     yscale = Hb/yrange
+We have:
+    px(x) = xoffset + x * xscale
+    py(y) = yoffset - y * yscale
+
+The inverse transformations xp(p) and yp(p) are just the inverse of these.
+
+A typical program might be as follows:
+-------------------------------------
+	------------------------------------------------------------------
+       |#include <stdio.h>                                                |
+       |#include <math.h>                                                 |
+       |                                                                  |
+       |#include "x11coord.h"                                             |
+       |                                                                  |
+       |                                                                  |
+       |main()                                                            |
+       |{                                                                 |
+       |    Window w;                                                     |
+       |        .....                                                     |
+       |                                                                  |
+       |    set_window_parameters(100,85, 775,775);                       |
+       |    set_bordered_box(10);                                         |
+       |    set_data_parameters(50,50, 0,0, 2.0,2.0);                     |
+       |                                                                  |
+       |    xopen();                                                      |
+       |    w = xcreate("test", ButtonPressMask | ExposureMask);          |
+       |    xevent_monitor(w);                                            |
+       |}                                                                 |
+       |                                                                  |
+       |                                                                  |
+       |xevent_monitor(w)                                                 |
+       |Window w;                                                         |
+       |{                                                                 |
+       |    XEvent event;                                                 |
+       |                                                                  |
+       |    for ( ; ; ) {                                                 |
+       |        XNextEvent(theDisplay,&event);                            |
+       |        switch (event.type) {                                     |
+       |            ....                                                  |
+       |            case ButtonPress:                                     |
+       |                switch(event.xbutton.button) {                    |
+       |                    case Button1:                                 |
+       |                        XDestroyWindow(theDisplay,w);             |
+       |                        return;                                   |
+       |                    case Button2:                                 |
+       |                        ....                                      |
+       |                }                                                 |
+       |                break;                                            |
+       |            case Expose:                                          |
+       |                if (event.xexpose.count == 0) {                   |
+       |                    draw_calibrated_box(w);                       |
+       |                    plot(w);                                      |
+       |                }                                                 |
+       |                break;                                            |
+       |            ....                                                  |
+       |        }                                                         |
+       |    }                                                             |
+       |}                                                                 |
+       |                                                                  |
+	------------------------------------------------------------------
+The purpose of the xevent_monitor is to loop endlessly and keep the program
+running while the window is displayed. The window vanishes when the monitor
+is quit using (in this example) the left mouse button.
+Note that you let all plotting routines be called when an expose-event has
+been caught. This is not just so that the screen re-draws itself when exposed,
+but also to avoid data at the start of the plot going missing.
+If you don't set up for expose-events, but try to plot data as soon as the
+window is created, then it turns out that you tend to lose the first few bytes
+of plot data. The correct way is to plot data when the window is exposed.
+The window-creation and mapping process generates an expose event
+automatically and, when caught by the event monitor, this causes the window to
+be first plotted.
+
+
+*****************************************************************************/
+#include <X11/X.h>      /*  /usr/include/X11/X.h     */
+#include <X11/Xlib.h>   /*  /usr/include/X11/Xlib.h  */
+
+
+static char defFontString[] = "fixed" ,  *theFontString = defFontString ;
+
+
+/****************************************************************************
+*       Defaults for some standard window sizes
+****************************************************************************/
+#define FULLXORG          5     /* Full screen size */
+#define FULLYORG         90
+#define FULLWIDTH      1000
+#define FULLHEIGHT      750
+
+#define A4XORG          190     /* A4 size */
+#define A4YORG           85
+#define A4WIDTH         620
+#define A4HEIGHT        760
+
+#define PLOTXORG        100     /* Rectangular plotting area */
+#define PLOTYORG        155
+#define PLOTWIDTH       800
+#define PLOTHEIGHT      600
+
+#define BOXXORG         100     /* Square box */
+#define BOXYORG          85
+#define BOXWIDTH        775
+#define BOXHEIGHT       775
+
+/****************************************************************************
+*       Macros for pixel-data transformation
+****************************************************************************/
+/* pixel coord from data coord */
+#define px(x)           ( (int)(_xoffset + (x) * _xscale) )
+#define py(y)           ( (int)(_yoffset - (y) * _yscale) )
+/* data coord from pixel coord */
+#define xp(p)           ( (float)(((p) - _xoffset) / _xscale) )
+#define yp(p)           ( (float)((_yoffset - (p)) / _yscale) )
+/* data coord from a %age of data range */
+#define xpc(pc)         ( ((xleft()+xright())*pc) / 100 )
+#define ypc(pc)         ( ((ybottom()+ytop())*pc) / 100 )
+/* data coord of box centre */
+#define xcentre()       xpc(50)
+#define ycentre()       ypc(50)
+/* pixel limits of box (note that ptop() < pbottom() ). */
+#define pleft()         (_Xp0)
+#define pright()        (_Xp1)
+#define pbottom()       (_Yp0)
+#define ptop()          (_Yp1)
+#define pwidth()        (_Wb)
+#define pheight()       (_Hb)
+/* data limits of box */
+#define xleft()         xp(_Xp0)
+#define xright()        xp(_Xp1)
+#define ybottom()       yp(_Yp0)
+#define ytop()          yp(_Yp1)
+#define xwidth()        xp(_Wb)
+#define yheight()       yp(_Hb)
+/* test if data argument is in box */
+#define Xinbox(x)       ( (xleft()<=x && x<=xright()) ? 1 : 0 )
+#define Yinbox(y)       ( (ybottom()<=y && y<=ytop()) ? 1 : 0 )
+#define inbox(x,y)      ( (Xinbox(x) && Yinbox(y)) ? 1 : 0 )
+/* jitter data value (ie move by a given pixel distance) */
+#define Xjitter(x,p)    ( xp(px(x)+(p)) )
+#define Yjitter(y,p)    ( yp(py(y)+(p)) )
+
+/****************************************************************************
+*       Macros for routines (using preset system parameters)
+****************************************************************************/
+/* Xaxes: yval is a data value at which to place a horizontal axis.        */
+/* For example: 0 (zero line), ybottom() (box-bottom), ytop() (box-top).   */
+#define draw_Xaxis(w,yval)      if (Yinbox(yval)) axis(w, _Xp0,_Xp1, py(yval),'x')
+#define calibrate_Xaxis(w,yval) calibrate_Axis(w, _Xp0,_Xp1, _Xd0,_Xd1, py(yval),'x')
+
+/* Yaxes: xval is a data value at which to place a vertical axis.          */
+/* For example: 0 (zero line), xleft() (box-left), xright() (box-right).   */
+#define draw_Yaxis(w,xval)      if (Xinbox(xval)) axis(w, _Yp0,_Yp1, px(xval),'y')
+#define calibrate_Yaxis(w,xval) calibrate_Axis(w, _Yp0,_Yp1, _Yd0,_Yd1, px(xval),'y')
+
+#define draw_box(w)             box(w, _Xp0,_Yp0, _Xp1,_Yp1)
+#define calibrate_box(w)        calibrate_Box(w, _Xp0,_Yp0, _Xp1,_Yp1, _Xd0,_Yd0, _Xd1,_Yd1)
+#define draw_calibrated_box(w)  draw_box(w); calibrate_box(w)
+
+#define xcreate(name,mask)      xCreate(name,mask, _xorg,_yorg, _width,_height)
+
+/****************************************************************************
+*       Macros for standard X11 commands
+****************************************************************************/
+#define Point(w,x,y)            XDrawPoint(theDisplay,w,theGC,px(x),py(y))
+#define Line(w,x1,y1,x2,y2)     XDrawLine(theDisplay,w,theGC,px(x1),py(y1),px(x2),py(y2))
+#define String(w,x,y,string)    XDrawString(theDisplay, w, theGC, px(x),py(y), string, strlen(string))
+
+#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)
+
+#define xPoint(w,x,y)           if (inbox(x,y)) Point(w,x,y)
+#define xLine(w,x1,y1,x2,y2)    if (inbox(x1,y1) && inbox(x2,y2)) Line(w,x1,y1,x2,y2)
+#define xString(w,x,y,string)   if (inbox(x,y)) String(w,x,y,string)
+
+#define xCross(w,x,y)           if (inbox(x,y)) Cross(w,x,y)
+#define xDot(w,x,y,dotsize)     if (inbox(x,y)) Dot(w,x,y,dotsize)
+
+/* Max width and height (pixels) of chars in current font, (ref 6-17, 6-19) */
+#define max_charwidth()         ( theFont->max_bounds.rbearing - theFont->min_bounds.lbearing )
+#define max_charheight()        ( theFont->max_bounds.ascent + theFont->max_bounds.descent )
+/* Number of lines and cols (chars) of current font which fit into box */
+#define linespacing()           ( (theFont->max_bounds.descent)>>1 )
+#define lineheight()            ( max_charheight()+linespacing() )
+#define colwidth()              ( max_charwidth() )
+#define nlines()                ( pheight() / lineheight() )
+#define ncols()                 ( pwidth() / colwidth() )
+#define topline(w,string)       lineString(w,string,1,1)
+#define bottomline(w,string)    lineString(w,string,nlines(),1)
+#define margin()                ( theFont->max_bounds.lbearing + theFont->max_bounds.rbearing )
+#define headroom()              ( theFont->max_bounds.ascent )
+#define leftmargin()            ( pleft() + margin() )
+#define rightmargin()           ( pright() - margin() )
+#define topmargin()             ( ptop() + headroom() )
+#define bottommargin()          ( pbottom() - headroom() )
+#define line(i)                 ( topmargin() + (i-1)*lineheight() )
+#define col(j)                  ( leftmargin() + (j-1)*colwidth() )
+#define lineString(w,string,i,j) ( XDrawString(theDisplay,w,theGC,col(j),line(i),string,strlen(string)) )
+#define leftString(w,string,i)   ( XDrawString(theDisplay,w,theGC,leftmargin(),line(i),string,strlen(string)) )
+#define rightString(w,string,i)  ( XDrawString(theDisplay,w,theGC,rightmargin()-stringwidth(string),line(i),string,strlen(string)) )
+#define centreString(w,string,i) ( XDrawString(theDisplay,w,theGC,(pwidth()-stringwidth(string))>>1,line(i),string,strlen(string)) )
+#define supertopline(w,string)   ( XDrawString(theDisplay,w,theGC,col(1),ptop()-max_charheight()-headroom(),string,strlen(string)) )
+
+
+/****************************************************************************
+*       Window parameters   (X11-specific).
+****************************************************************************/
+Display        *theDisplay;
+int             theScreen;        /* screen_number */
+int             theWidth;         /* horizontal size, in pixels */
+int             theHeight;        /* vertical size, in pixels */
+unsigned long   theForeground;    /* lines, text, and border pixel value */
+unsigned long   theBackground;    /* background pixel value */
+GC              theGC;            /* graphics context */
+XFontStruct    *theFont;          /* current font used to print text */
+unsigned long   theBlack;         /* pixel value for black */
+unsigned long   theWhite;         /* pixel value for white */
+
+/****************************************************************************
+*       System (global) variables
+*****************************************************************************/
+int     _xorg,  _yorg;  /* Window origin (pixel coords top-left wrt Display)*/
+int     _width, _height;/* Window size (pixels).                            */
+
+int     _Xp0,   _Yp0;   /* Box origin (pixel coords at bottom-left)         */
+int     _Xp1,   _Yp1;   /* Box limits (pixel coords at top-right)           */
+int     _Wb,    _Hb;    /* Box size (pixels).                               */
+
+float   _Xd0,   _Yd0;   /* Box origin (data coords at bottom-left)          */
+float   _Xd1,   _Yd1;   /* Box limits (data coords at top-right)            */
+float   _xrange,_yrange;/* Box size (data ranges).                          */
+
+int     _xshift,_yshift;/* Plot origin (pixel coords from box origin)       */
+float   _xd0,   _yd0;   /* Data coords fixed at plot origin                 */
+
+float   _xoffset,_yoffset;
+float   _xscale, _yscale;
+
+/****************************************************************************
+*       Functions (in x11coord.c)
+*****************************************************************************/
+extern                  set_window_parameters();
+extern                  set_box_parameters();
+extern                  set_bordered_box();
+extern                  set_data_parameters();
+extern                  xopen();
+extern  GC              initGC();
+extern                  setLinewidth();
+extern                  setFont();
+extern  Window          xCreate();
+extern                  axis();
+extern                  box();
+extern                  calibrate_Axis();
+extern                  calibrate_Box();
+extern                  plotX();
+extern                  plotY();
+extern  int             stringwidth();
+extern  int             stringheight();
+extern                  calibrate();
+extern                  Dot();
+