TITLE pprSubr.c - portable plotting routines DESCRIPTION These routines support simple 2-D plotting in a "window". The window can be either an actual display window, a PostScript printer page, or an EPS file for Encapsulated PostScript. QUICK REFERENCE PPR_AREA *pArea; pointer to a plot area PPR_WIN *pWin; pointer to a plot "window" void pprAnnotX( pArea, offset, dataL, dataR, nDiv, drawLine, xLabel, xAnnot, angle ) void pprAnnotY( pArea, offset, dataB, dataT, nDiv, drawLine, yLabel, yAnnot, angle ) void pprAnnotYMark( pArea, offset, markNum ) void pprAreaClose( pArea ) void pprAreaErase( pArea fracL, fracB, fracR, fracT ) PPR_AREA *pprAreaOpen( pWin, fracL, fracB, fracR, fracT, dataL, dataB, dataR, dataT, nXint, nYint, charHt ) PPR_AREA *pprAreaOpenDflt( pWin, fracL, fracB, fracR, fracT, dataL, dataB, dataR, dataT ) void pprAreaRescale( pArea, dataL, dataB, dataR, dataT ) long pprAreaSetAttr( pArea, code, attrVal, pAttr ) code: PPR_ATTR_{CLIP,COLORNUM,BG,FG,KEYNUM,LINE_THICK,NOCLIP,PATT_ARRAY} void pprAutoEnds( dbl1, dbl2, >pNewDbl1, >pNewDbl2 ) void pprAutoInterval( dbl1, dbl2, >pNint ) void pprAutoRangeD( dblAry, nPts, >minDbl, >maxDbl ) void pprAutoRangeF( fltAry, nPts, >minDbl, >maxDbl ) void pprAutoRangeL( lngAry, nPts, >minDbl, >maxDbl ) void pprAutoRangeS( shtAry, nPts, >minDbl, >maxDbl ) void pprChar( pArea, xDbl, yDbl, char, charHt, angle ) double pprCos_deg( angle ) void pprCvtDblToTxt( >text, width, dblVal, nSigDigits ) void pprGrid( pArea ) void pprGridErase( pArea ) void pprGridLabel( pArea, xLabel, xAnnot, yLabel, yAnnot, angle) void pprLineD( pArea, xDblAry, yDblAry, nPts ) void pprLineF( pArea, xFltAry, yFltAry, nPts ) void pprLineL( pArea, xLngAry, yLngAry, nPts ) void pprLineS( pArea, xShtAry, yShtAry, nPts ) void pprLineSegD( pArea, xDbl1, yDbl1, xDbl2, yDbl2 ) void pprLineSegL( pArea, xLng1, yLng1, xLng2, yLng2 ) void pprMarkD( pArea, xDbl1, yDbl1, markNum ) void pprMarkL( pArea, xLng1, yLng1, markNum ) void pprMoveD( pArea, xDbl1, yDbl1, penDown ) void pprPerim( pArea ) void pprPerimErase( pArea ) void pprPerimLabel( pArea, xLabel, xAnnot, yLabel, yAnnot, angle) void pprPointD( pArea, xDbl1, yDbl1 ) void pprPointL( pArea, xLng1, yLng1 ) double pprSin_deg( angle ) void pprText( pArea, xDbl, yDbl, text, just, charHt, angle) just: PPR_TXT_{CEN,RJ,LJ} void pprWinClose( pWin ) void pprWinErase( pWin ) void pprWinInfo( pWin, >pXpos, >pYpos, >pXwid, >pYht ) int pprWinIsMono( pWin ) long pprWinLoop( pWin, drawFn, pDrawArg ) void drawFn(pWin, pDrawArg) PPR_WIN *pprWinOpen( winType, dispName, winTitle, xPos, yPos, xWid,yHt) winType: PPR_WIN_{SCREEN,POSTSCRIPT,EPS} PPR_WIN *pprWinOpenUW( pFrame, pCanvas, NULL, NULL ) PPR_WIN *pprWinOpenUW( ppDisp, pWindow, pGC, NULL ) void pprWinReplot( pWin, drawFn, pDrawArg ) long pprWinSetAttr( pWin, code, pAttr ) code: PPR_ATTR_{COLORNUM,GC,KEYNUM,LINE_THICK,PATT_ARRAY} DESCRIPTION (continued) Plotting is done within "plot areas" which are defined within the window. Plot areas can be as large as the window, and they can overlap, if desired. Clipping service is optional, since plot areas are often calibrated for the "normal" range of data, and it is useful to see what's happening if the data are outside the normal range. One non-intuitive aspect of the term "plot area" is that the usual case ALWAYS plots outside the plot area. Generally, this happens when annotations and labels are added to a grid. The plot area itself only specified where the edges of the grid were to be drawn. Because of this, determining the size and placement of a plot area must take into account the necessary margins for text. (pprAreaOpenDflt automatically takes care of margins.) Most plotting is done using "data coordinates", which are the actual data values. In some cases, coordinates or distances are specified in terms of a fraction of the window height (see, for example, pprAreaOpen or pprText). Also provided in this package are some routines for interacting with the "window". In many cases, this means that a plotting program can totally avoid any knowledge of, or dependence on, a particular windowing environment. This makes easily available the capability for producing hard copies of plots on a PostScript printer. Many routines in this package require that values be represented with type 'double'. In some cases, however, other data types are directly supported, so that the caller doesn't need to alter the way data are stored. BUGS o Only linear axes are presently supported o There is presently no mechanism to allow a calling program to do other work while a plot is on the screen. It would be nice for a program to be able to periodically check with this package to see if resize or expose events need to be serviced. o The SunView version of this package won't run properly with programs which use the SunOs LightWeight Process library. o The SunView version of this package doesn't handle color. EXAMPLE The following program plots the first 80 points of a parabola. The size and position of the plot window can be freely changed; the window can be covered and exposed, iconified and de-iconified, etc. When a `click right' is done in the plot window, the window is closed. A PostScript file named "testPS" is produced; the size of the plot in this file is about the same as it was when the plot window was closed. (The plot window can be closed using the `quit' item on the window's title bar menu (but not under X!!).) The program is compiled and linked for SunView with the following command. (It will be necessary to find where pprPlot.o and pprPlotDefs.h are located and possibly `fix up' the command.) cc plotTest.c pprPlot.o -lsuntool -lsunwindow -lpixrect -lm The program is compiled and linked for X with the following command. (It will be necessary to find where pprPlot.o and pprPlotDefs.h are located and possibly `fix up' the command.) cc plotTest.c pprPlot.o -lX11 -lm (As of Feb 6, 1991, plotTest.c is available on the AT-division open network in ~gta/ar/plotTest.c. It should be copied into the user's working directory before using it.) (As of Feb 6, 1991, pprPlot is available on the AT-division open network in ~gta. Until access to this software has been formalized, use the following for Sun3/SunView: cc plotTest.c -I/home/obiwan/gtacs/h /home/obiwan/gtacs/ar/pprPlotS.o -lsuntool -lsunwindow -lpixrect -lm (For Sun3/X, use the following: cc plotTest.c -I/home/obiwan/gtacs/h /home/obiwan/gtacs/ar/pprPlotX.o -lX11 -lm (For Sun4 builds, use "/ar/ar4/" in place of "/ar/" in the above commands.) #include #include #define NPTS 80 ---------------------------------------------------------------------------- define a structure for holding the data. This is needed because the replot routine (which does the actual plotting) is only given a pointer to the information it needs. ---------------------------------------------------------------------------- typedef struct { int nPts; float x[NPTS]; float y[NPTS]; double xMin; double xMax; double yMin; double yMax; } MY_DATA; void replot(); main() { int i; int x=0,y=0,width=0,height=0; PPR_WIN *pWin; MY_DATA myData; long stat; ---------------------------------------------------------------------------- generate the data in the structure. Once it's generated, figure out the range of values and put the range into the structure using pprAutoRangeF. This specific routine was chosen because the data is in "float" arrays. Different forms of data would result in choosing a different routine. The routine pprAutoEnds is available to "round" the endpoints of the axes to "nicer" values. Depending on the application, it will be attractive to use this following the pprAutoRange call. ---------------------------------------------------------------------------- myData.nPts = NPTS; for (i=0; ixMin, pMyData->yMin, pMyData->xMax, pMyData->yMax, 5, 5, charHt); pprPerimLabel(pArea, "x label", NULL, "y label", NULL, 0.); pprLineF(pArea, pMyData->x, pMyData->y, pMyData->nPts); pprAreaClose(pArea); return; } NAME pprAnnotX - annotate an X axis, perhaps drawing a line and tick marks DESCRIPTION Annotate an X axis, placing annotations at the major tick intervals. If desired, an axis line is also drawn, with tick marks at the major intervals. The tick marks are drawn using the "generic" line attributes for the plot window. The axis line is drawn with the line attributes of the plot area; this allows using a dashed line pattern or color to associate an axis with a data line. The annotations and label are drawn using the default character height for the plot area, in the color, if any, for the plot area. An array of text strings can be supplied for annotating the tick intervals. This is useful if the desired annotations are text. If an annotation array isn't supplied, then numeric annotations are generated. To allow multiple calibrations for an axis, this routine accepts an `offset' argument. If this argument is greater than 0, then the annotation and labeling activity occurs that many lines (in the default character height for the plot area) below the axis which was established by pprAreaOpen. An alternate entry point, pprAnnotX_wc, is available to use the plot window's color for the annotation. RETURNS void BUGS o only linear axes are handled o doesn't presently support offset processing NOTES 1. Uses a space below the axis of 5 character heights. SEE ALSO pprAnnotY, pprGrid, pprPerim, pprAreaOpen, pprAreaSetAttr SYNOPSIS void pprAnnotX(pArea, offset, xLeft, xRight, xNint, drawLine, xLabel, xAnnot, angle) PPR_AREA *pArea; /* IO pointer to plotter area */ int offset; /* I offset as number of lines below yBot to annotate */ double xLeft; /* I x data value at left end of axis */ double xRight; /* I x data value at right end of axis */ int xNint; /* I number of major intervals for axis */ int drawLine; /* I 1 says to draw a line and tick marks */ char *xLabel; /* I label for x axis, or NULL; oriented horizontal */ char **xAnnot; /* I pointer to array of x annotations, or NULL */ double angle; /* I orientation angle for annotation text; 0. or 90. */ NAME pprAnnotY - annotate a Y axis, perhaps drawing line and tick marks DESCRIPTION Annotate a Y axis, placing annotations at the major tick intervals. If desired, an axis line is also drawn, with tick marks at the major intervals. The tick marks are drawn using the "generic" line attributes for the plot window. The axis line is drawn with the line attributes of the plot area; this allows using a dashed line pattern or color to associate an axis with a data line. The annotations and label are drawn using the default character height for the plot area, in the color, if any, for the plot area. An array of text strings can be supplied for annotating the tick intervals. This is useful if the desired annotations are text. If an annotation array isn't supplied, then numeric annotations are generated. To allow multiple calibrations for an axis, this routine accepts an `offset' argument. If this argument is greater than 0, then the annotation and labeling activity occurs that many lines (in the default character height for the plot area) to the left of the axis which was established by pprAreaOpen. An alternate entry point, pprAnnotY_wc, is available to use the plot window's color for the annotation. RETURNS void BUGS o only linear axes are handled NOTES 1. Uses a space to the left of the axis of 12 character heights if annotations are horizontal, and a space of 5 character heights if they are vertical. SEE ALSO pprAnnotX, pprGrid, pprPerim, pprAreaOpen, pprAreaSetAttr SYNOPSIS void pprAnnotY(pArea, offset, yBot, yTop, yNint, drawLine, yLabel, yAnnot, angle) PPR_AREA *pArea; /* IO pointer to plotter area */ int offset; /* I number of lines to left of axis for annotation */ double yBot; /* I y data value at bottom end of axis */ double yTop; /* I y data value at top end of axis */ int yNint; /* I number of major intervals for axis */ int drawLine; /* I 1 says to draw a line and tick marks */ char *yLabel; /* I label for y axis, or NULL; oriented vertical */ char **yAnnot; /* I pointer to array of y annotations, or NULL */ double angle; /* I orientation angle for annotation text; 0. or 90. */ NAME pprAnnotYMark - add plot marks to a Y axis annotation DESCRIPTION Draw two plot marks at the foot of the Y axis annotation, to allow associating the axis with a particular set of data. RETURNS void BUGS o only linear axes are handled SEE ALSO pprMark, pprAnnotY EXAMPLE SYNOPSIS void pprAnnotYMark(pArea, offset, markNum) PPR_AREA *pArea; /* I pointer to plot area structure */ int offset; /* I number of lines to left of axis for annotation */ int markNum; /* I mark number */ NAME pprArc - draw an arc DESCRIPTION Draw an arc. The arc is specified by a radius and two angles. The angles, in degrees, specify the angle at which the arc starts and the angle at which it ends. An angle increment specifies both the direction of the arc and the size of the chords which approximate the arc. Angles are measured counter-clockwise from the positive X axis. The radius of the arc is treated as representing data values in the plot area. If both the X and Y axes of the plot area have the same data scaling, then circular arcs will be produced (assuming a square plot area). If the X scaling is not the same as the Y scaling, then elliptical arcs will be produced. The arc is drawn using the color, dashed line, and other attributes of the plot area. Alternate entry points are: pprArcD_ac uses the area color, but ignores other attributes RETURNS void SEE ALSO SYNOPSIS void pprArcD(pArea, xDbl, yDbl, radDbl, angle1, angle2, angleIncr) PPR_AREA *pArea; /* I pointer to plot area structure */ double xDbl; /* I x data coordinate for center of arc */ double yDbl; /* I y data coordinate for center of arc */ double radDbl; double angle1; /* I angle to start arc */ double angle2; /* I angle to stop arc */ double angleIncr; /* I size of steps in drawing arc */ NAME pprAreaClose - close a plot area DESCRIPTION Frees the memory associated with a plot area pointer and does other cleanup operations. This routine should be called prior to calling pprWinClose. RETURNS void SYNOPSIS void pprAreaClose(pArea) PPR_AREA *pArea; /* I pointer to plot area structure */ NAME pprAreaErase - erase an area within a plot window DESCRIPTION Erases an area within a plot window. RETURNS void SEE ALSO pprWinErase, pprGridErase, pprPerimErase NOTES 1. Another mode of calling pprAreaErase, in which the arguments are pixel offsets from the data area boundaries, can be invoked by having one or more of the arguments be greater than 1. or less than 0. EXAMPLES 1. Erase within a data area, preserving the perimeter line. pprAreaErase(pArea, 1., 1., -1., -1.); SYNOPSIS void pprAreaErase(pArea, wfracXleft, wfracYbot, wfracXright, wfracYtop) PPR_AREA *pArea; /* I pointer to plot area structure */ double wfracXleft; /* I x window fraction of left edge of area */ double wfracYbot; /* I y window fraction of bottom edge of area */ double wfracXright; /* I x window fraction of right edge of area */ double wfracYtop; /* I y window fraction of top edge of area */ NAME pprAreaOpen - initialize a plot area DESCRIPTION Initialize a plot area within the plot window. This initialization must be done before calling any of the routines which do actual plotting. This routine establishes a rectangular "data area" within the plot window. It is within the data area that data will be plotted. The size and position of the data area are specified in terms of fractions of the window size; they are expressed as "coordinates" of the lower left and upper right corners of the area. The data area specified in the call to pprAreaOpen does NOT include space for axis annotations and labels. (pprAreaOpenDflt can be used to automatically get the necessary margins.) This routine must also be told the data values at the two corners of the data area in order to determine scaling. In addition to establishing scaling, this routine accepts information about how many major divisions there are for each axis and what default character height is to be used for displaying text within the plot area (see pprText for more information). If any of these parameters is specified as zero, this routine chooses an appropriate value. The default line attributes for the plot are copied from those of the plot window. pprAreaSetAttr can be used to change them. Under X11, a gc is created for the plot area with the foreground and background being copied from the gc for the plot window; pprAreaSetAttr can be used to change the foreground and background. When plotting is complete for a plot area, pprAreaClose should be called. RETURNS pointer to plot area, or NULL BUGS o only linear calibration is handled SEE ALSO pprWinOpen, pprAreaOpenDflt, pprAreaSetAttr pprAutoEnds, pprAutoInterval, pprAutoRange pprText EXAMPLE 1. Set up an area which occupies the full width of the window, but which uses the middle third vertically. The range for x values is 0 to 100; for y, the range is -10 to 10. Both the x and y axes are to be divided into 5 intervals. Allow space below and to the left of the actual area for plotting for pprPerim to place labels and annotations. The required size of "margins" depends on the size of characters used, so a default size is determined (and put into effect as part of the pprAreaOpen call). PPR_AREA *pArea; double charHt, charHtX; charHt = PprDfltCharHt(.33, .67); charHtX = pprYFracToXFrac(pWin, charHt); pArea = pprAreaOpen(pWin, 0.+12.*charHtX, .33+6*charHt, 1., .67, 0., -10., 100., 10., 5, 5, charHt); ... pprAreaClose(pArea); SYNOPSIS PPR_AREA * pprAreaOpen(pWin, wfracXleft, wfracYbot, wfracXright, wfracYtop, xLeft, yBot, xRight, yTop, xNint, yNint, charHt) PPR_WIN *pWin; /* I pointer to plot window structure */ double wfracXleft; /* I x window fraction of left edge of data area */ double wfracYbot; /* I y window fraction of bottom edge of data area */ double wfracXright; /* I x window fraction of right edge of data area */ double wfracYtop; /* I y window fraction of top edge of data area */ double xLeft; /* I x data value at left side of data area */ double yBot; /* I y data value at bottom side of data area */ double xRight; /* I x data value at right side of data area */ double yTop; /* I y data value at top side of data area */ int xNint; /* I x axis number of intervals; if <=0, a default value is provided */ int yNint; /* I y axis number of intervals; if <=0, a default value is provided */ double charHt; /* I value to use as default for character size, as a fraction of window height; if <= 0., a default value is provided */ NAME pprAreaOpenDflt - initialize a plot area using defaults DESCRIPTION Initialize a plot area within the plot window. This initialization must be done before calling any of the routines which do actual plotting. This routine is a variant on pprAreaOpen. It performs the functions of that routine, but uses some defaults rather than making the caller determine specific values. In particular, this routine: o sets a default character height o determines the number of major divisions for each axis o establishes, inside the plot area specified, margins which will be adequate for annotating and labeling the axes. See the description for pprAreaOpen for additional details. When plotting is complete for a plot area, pprAreaClose should be called. RETURNS pointer to plot area, or NULL BUGS o only linear calibration is handled SEE ALSO pprWinOpen, pprAreaOpen, pprAreaSetAttr pprAutoEnds, pprAutoInterval, pprAutoRange pprText SYNOPSIS PPR_AREA * pprAreaOpenDflt(pWin, wfracXleft, wfracYbot, wfracXright, wfracYtop, xLeft, yBot, xRight, yTop) PPR_WIN *pWin; /* I pointer to plot window structure */ double wfracXleft; /* I x window fraction of left edge of plot area */ double wfracYbot; /* I y window fraction of bottom edge of plot area */ double wfracXright; /* I x window fraction of right edge of plot area */ double wfracYtop; /* I y window fraction of top edge of plot area */ double xLeft; /* I x data value at left side of data area */ double yBot; /* I y data value at bottom side of data area */ double xRight; /* I x data value at right side of data area */ double yTop; /* I y data value at top side of data area */ NAME pprAreaRescale - change scaling for existing plot area DESCRIPTION Changes the scaling for a plot area using new data values at the edges of the data area. The actual size and position of the data area within the plot window aren't changed. No re-drawing is done by this routine. Typically, the caller will erase the appropriate area, draw the grid or perimeter, set the area for clipping, and, finally, replot the data. Default character height for the plot area is altered proportionally to the rescaling of the plot area. RETURNS void SEE ALSO pprAreaSetAttr, pprAreaErase SYNOPSIS void pprAreaRescale(pArea, xLeft, yBot, xRight, yTop) PPR_AREA *pArea; /* I pointer to plot area structure */ double xLeft; /* I x data value at left side of data area */ double yBot; /* I y data value at bottom side of data area */ double xRight; /* I x data value at right side of data area */ double yTop; /* I y data value at top side of data area */ NAME pprAreaSetAttr - set attributes for a plot area DESCRIPTION Set individual attributes for a plot area. In most cases, the attributes affect the drawing of lines in the plot area. To use this routine, an attribute code and a corresponding value are supplied. The form of the value argument depends on the code. o PPR_ATTR_CLIP sets the plot area so that line segments which lie outside the data area won't be drawn, but will terminate at their intersection with the edge of the data area. Clipping can be disabled by setting the PPR_ATTR_NOCLIP attribute; the default when a plot area is created is no clipping. pprAreaSetAttr(pArea, PPR_ATTR_CLIP, 0, NULL); pprAreaSetAttr(pArea, PPR_ATTR_NOCLIP, 0, NULL); o PPR_ATTR_COLORNUM selects a color for use in drawing lines in a plot area. For monochrome screens, no action is taken. There are PPR_NCOLORS colors provided, numbered starting with 1. A colorNum of 0 selects black. int colorNum; colorNum = 4; pprAreaSetAttr(pArea, PPR_ATTR_COLORNUM, colorNum, NULL); o PPR_ATTR_BG installs a caller-supplied background pixel value in the gc for the plot area. (For use only with X11. Under X11, pprAreaOpen initially set the gc for the plot area to have the same foreground and background colors as the gc for the plot window.) pprAreaSetAttr(pArea, PPR_ATTR_BG, 0, &bg); o PPR_ATTR_FG installs a caller-supplied foreground pixel value in the gc for the plot area. (For use only with X11. Under X11, pprAreaOpen initially set the gc for the plot area to have the same foreground and background colors as the gc for the plot window.) pprAreaSetAttr(pArea, PPR_ATTR_FG, 0, &fg); o PPR_ATTR_KEYNUM selects a legend key for identifying lines drawn in a plot area, and thus distinguishing them from the lines drawn by a different plot area. This is primarily useful for overlapping plot areas, where several sets of data are drawn on the same axis. The key number, which is expected to be in the range 0 to PPR_NKEYS, inclusive, selects either a dashed line pattern or a color, depending on the nature of the device on which the plot window resides. There are PPR_NKEYS unique patterns and colors; a key number of 0 resets to a "plain", solid line. Use of the PPR_ATTR_KEYNUM option provides a way to restart a dashed line pattern at its beginning. int keyNum; keyNum = 4; pprAreaSetAttr(pArea, PPR_ATTR_KEYNUM, keyNum, NULL); o PPR_ATTR_LINE_THICK sets the line thickness for the plot area. The thickness is the integer number of thousandths of plot window height. The thickness is used for data drawing operations. A thickness of 0. results in pixel-thick lines. As an example, a thickness of 10 represents 10/1000 (or .01) of the window height. int thick; thick = 3; .003 of window height pprAreaSetAttr(pArea, PPR_ATTR_LINE_THICK, thick, NULL); o PPR_ATTR_PATT_ARRAY installs a caller-supplied dashed line pattern array. This is an array of type short. The first element contains a number of pixels with `pen down'; the second has a number of pixels with `pen up'; the third with `pen down'; etc. Following the last element must be an element with a value of 0 . (pprAreaSetAttr stores only a pointer to the array, so the caller must preserve the array until pprAreaClose is called or until pprAreaSetAttr is called to `de-install' the pattern array.) An array pointer of NULL resets the plot area back to normal drawing. short pattern[]={16,4,2,4,0}; pprAreaSetAttr(pArea, PPR_ATTR_PATT_ARRAY, 0, pattern); Some pprXxx routines don't use the attributes from the plot area, but instead use the `generic' attributes from the plot window structure. The pprLineSegx_wc and pprMovex_wc routines provide an explicit mechanism for using the plot window attributes. RETURNS 0, or -1 if an error is encountered BUGS o color is supported only for X o when color is used, ALL output for the plot area is colored; it's not clear yet whether this is a bug or a feature. o line thickness doesn't operate consistently under SunView SEE ALSO pprAreaOpen SYNOPSIS long pprAreaSetAttr(pArea, code, arg, pArg) PPR_AREA *pArea; /* IO pointer to plotter area */ PPR_ATTR_CODE code; /* I attribute code: one of PPR_ATTR_xxx */ int arg; /* I attribute value, or 0 */ void *pArg; /* I pointer to attribute, or NULL */ NAME pprAutoEnds - choose `clean' endpoint valuess for an axis DESCRIPTION For a specific numeric range, this routine calculates a possibly altered numeric range which will produce more tasteful axis calibration. RETURNS void BUGS o this routine should probably focus some attention on choice of number of intervals for an axis; presently, the new endpoints chosen by this routine may be difficult to use for choosing interval size o uses exp10(), which doesn't exist in VxWorks o only linear calibration is handled SEE ALSO pprAutoInterval, pprAutoRange, pprAreaOpen SYNOPSIS void pprAutoEnds(left, right, pLeftNew, pRightNew) double left; /* I leftmost value */ double right; /* I rightmost value */ double *pLeftNew; /* O new leftmost value */ double *pRightNew; /* O new rightmost value */ NAME pprAutoInterval - figure out good interval size for an axis DESCRIPTION Determine a "good" interval size for an axis, so that axis annotation will be tasteful. RETURNS void BUGS o this routine always chooses to divide an axis into 5 intervals o only linear calibration is handled SEE ALSO pprAutoEnds, pprAutoRange, pprAreaOpen SYNOPSIS void pprAutoInterval(val1, val2, pNint) double val1; /* I value at one end of axis */ double val2; /* I value at other end of axis */ int *pNint; /* O number of intervals */ NAME pprAutoRange - find minimum and maximum values for an array DESCRIPTION Finds the minimum and maximum values in an array of values. Four different routines are available, depending on the type of the input array. Each returns the min and max as a double: void pprAutoRangeD(doubleArray, nPoints, doubleMin, doubleMax) void pprAutoRangeF(floatArray, nPoints, doubleMin, doubleMax) void pprAutoRangeL(longArray, nPoints, doubleMin, doubleMax) void pprAutoRangeS(shortArray, nPoints, doubleMin, doubleMax) RETURNS void SEE ALSO pprAutoEnds, pprAutoInterval, pprAreaOpen NAME pprCos_deg - get the cosine of an angle in degrees DESCRIPTION Get the cosine of an angle in degrees. A table lookup technique is used. The angle argument is truncated to the next lower 1/4 degree prior to lookup. RETURNS cosine SYNOPSIS double pprCos_deg(angle) double angle; /* I angle, in degrees */ NAME pprChar - plot a character DESCRIPTION Plots a single text character at a location. The center of the character is placed at the specified x,y position. The character height specification is in terms of a fraction of the height of the window. This results in automatic scaling of character sizes as the window size changes. If a height of zero is specified in the call, then the default height for the plot area is used. (The default height was established by pprAreaOpen.) A macro is available which returns the default character height used by this plot package. The value returned is proportional to the height of the plot area. This value can be used to generate "big" and "small" character sizes. PprDfltCharHt(lowYfrac, highYfrac) lowYfrac is the vertical fraction of the window at which the bottom edge of the plot area lies highYfrac is the vertical fraction of the window at which the top edge of the plot area lies RETURNS void BUGS o technique used works only with linear axes o ASCII character codes are assumed o no checks are made for illegal characters SEE ALSO pprText, pprAreaOpen, pprLine, pprPoint SYNOPSIS void pprChar(pArea, x, y, chr, height, angle) PPR_AREA *pArea; /* IO pointer to plot area structure */ double x; /* I x data coordinate of character */ double y; /* I y data coordinate of character */ char chr; /* I character to plot */ double height; /* I height of character, as a fraction of the height of the window; a value of zero results in using a default height */ double angle; /* I orientation angle of character, ccw degrees */ NAME pprCvtDblToTxt - format a double for printing DESCRIPTION Formats a double for printing. This routine is dedicated to getting as large a range of values as possible into a particular field width. This routine doesn't attempt to handle extremely small values. It assumes that the field is large enough to handle the smallest significant value to be encountered. RETURNS void BUGS o extremely small values aren't handled well NOTES 1. If the value can't be represented at all in the field, the sign followed by *'s appears. 2. In extreme cases, only the magnitude of the value will appear, as En or Enn. For negative values, a - will precede the E. 3. When appropriate, the value is rounded to the nearest integer for formatting. SYNOPSIS void pprCvtDblToTxt(text, width, value, sigDig) char *text; /* O text representation of value */ int width; /* I max width of text string (not counting '\0') */ double value; /* I value to print */ int sigDig; /* I max # of dec places to print */ NAME pprGrid - draw a grid DESCRIPTION Draw a perimeter and grid lines. The number of intervals specified in the plot area structure is used for placing the grid lines. The color attributes for the plot window are used for drawing; dashed line and line thickness are ignored. RETURNS void BUGS o only linear axes are handled SEE ALSO pprGridLabel, pprGridErase, pprPerim, pprAnnotX, pprAnnotY, pprAreaOpen SYNOPSIS void pprGrid(pArea) PPR_AREA *pArea; /* IO pointer to plotter area */ NAME pprGridErase - erase within a grid DESCRIPTION Erases the screen inside the grid for the plot area. (Actually, the entire data area is erased and then the grid is redrawn.) RETURNS void SEE ALSO pprPerimErase, pprAreaErase, pprWinErase SYNOPSIS void pprGridErase(pArea) PPR_AREA *pArea; /* IO pointer to plotter area */ NAME pprGridLabel - draw and label a grid DESCRIPTION Draw a perimeter and grid lines. The number of intervals specified in the plot area structure is used for placing the grid lines. Axis labels and annotations are drawn using the information from the plot area, as specified in the pprAreaOpen call. RETURNS void BUGS o only linear axes are handled SEE ALSO pprGrid, pprPerim, pprAnnotX, pprAnnotY, pprAreaOpen SYNOPSIS void pprGridLabel(pArea, xLabel, xAnnot, yLabel, yAnnot, angle) PPR_AREA *pArea; /* IO pointer to plotter area */ char *xLabel; /* I label for x axis, or NULL */ char **xAnnot; /* I pointer to array of x annotations, or NULL */ char *yLabel; /* I label for y axis, or NULL */ char **yAnnot; /* I pointer to array of y annotations, or NULL */ double angle; /* I angle for y annotations; 0. or 90. */ NAME pprLine - plot a line using x and y data value vectors DESCRIPTION Draw a line along the path specified by two value arrays. Several entry points are available to accomodate various types of data: pprLineF(pArea, x, y, npts) x and y are float[] pprLineD(pArea, x, y, npts) x and y are double[] pprLineS(pArea, x, y, npts) x and y are short[] pprLineL(pArea, x, y, npts) x and y are long[] RETURNS void BUGS o only linear calibration is handled SEE ALSO pprLineSeg, pprMove, pprPoint, pprText SYNOPSIS void pprLineF(pArea, x, y, npts) PPR_AREA *pArea; /* IO pointer to plot area structure */ float *x; /* I x array of data values */ float *y; /* I y array of data values */ int npts; /* I number of points to plot */ NAME pprLineSeg - plot a line segment between a pair of points DESCRIPTION Move to the first point and then draw a line to the second, using the line attributes of the plot area. If the attributes indicate a dashed line, the current dashed line pattern will be used. Two entry points are available: pprLineSegD(pArea, x1, y1, x2, y2) x and y are double pprLineSegL(pArea, x1, y1, x2, y2) x and y are long For drawing ignoring the dashed line, line thickness, and other plot area attributes, but using the area color attribute, two alternate entry points are available: pprLineSegD_ac(pArea, x1, y1, x2, y2) x and y are double pprLineSegL_ac(pArea, x1, y1, x2, y2) x and y are long RETURNS void BUGS o only linear calibration is handled SEE ALSO pprLine, pprMove, pprPoint, pprText SYNOPSIS void pprLineSegD(pArea, x1, y1, x2, y2) PPR_AREA *pArea; /* IO pointer to plot area structure */ double x1; /* I first x point */ double y1; /* I first y point */ double x2; /* I second x point */ double y2; /* I second y point */ NAME pprMarkD - draw a plotting mark DESCRIPTION Draw a plotting mark at the specified point. The color attribute (if any) of the plot area is used in drawing the mark. Line thickness and dashed line pattern attributes are ignored. Two entry points are available: pprMarkD(pArea, x, y, markNum) x and y are double pprMarkL(pArea, x, y, markNum) x and y are long RETURNS void BUGS o only linear calibration is handled SEE ALSO pprLine, pprLineSeg, pprPoint, pprText SYNOPSIS void pprMarkD(pArea, x, y, markNum) PPR_AREA *pArea; /* I pointer to plot area structure */ double x; /* I x data coordinate */ double y; /* I y data coordinate */ int markNum; /* I mark number--0 to PPR_NMARKS-1, inclusive */ NAME pprMoveD - move the pen, possibly drawing a line DESCRIPTION Move the "pen" to the specified point. If the "pen" is "down" a line will be drawn. The line attributes of the plot area are used in drawing the line. If the attributes indicate a dashed line, the current dashed line pattern will be used. The "clipping" attribute for the plot area is honored only by pprMoveD; pprMoveD_ac and pprMoveD_wc never clip lines at the data area edges. Two alternate entry points are available for drawing plain lines, ignoring all attributes except color. One uses the color for the plot area (pprMoveD_ac); the other uses the plot window color (pprMoveD_wc). pprMoveD_ac(pArea, x, y, pen) x and y are double pprMoveD_wc(pArea, x, y, pen) x and y are double RETURNS void BUGS o only linear calibration is handled SEE ALSO pprLine, pprLineSeg, pprText SYNOPSIS void pprMoveD(pArea, x, y, pen) PPR_AREA *pArea; /* IO pointer to plot area structure */ double x; /* I x data coordinate of new point */ double y; /* I y data coordinate of new point */ int pen; /* I pen indicator--non-zero draws a line */ NAME pprPerim - draw a perimeter DESCRIPTION Draw a perimeter with tick marks. The number of intervals specified in the plot area structure is used for placing the tick marks. The color attributes for the plot window are used for drawing; dashed line and line thickness are ignored. RETURNS void BUGS o only linear axes are handled SEE ALSO pprPerimLabel, pprPerimErase, pprGrid, pprAnnotX, pprAnnotY, pprAreaOpen SYNOPSIS void pprPerim(pArea) PPR_AREA *pArea; /* IO pointer to plotter area */ NAME pprPerimErase - erase within a perimeter DESCRIPTION Erases the screen inside the perimeter for the plot area. (Actually, the perimeter and tick marks are erased as well, since plot marks may have been drawn on (and thus lie partly outside of) the perimeter itself. The perimeter and tick marks are then redrawn.) RETURNS void SEE ALSO pprGridErase, pprAreaErase, pprWinErase SYNOPSIS void pprPerimErase(pArea) PPR_AREA *pArea; /* IO pointer to plotter area */ NAME pprPerimLabel - draw and label a perimeter DESCRIPTION Draw a perimeter with tick marks. The number of intervals specified in the plot area structure is used for placing the tick marks. Axis labels and annotations are drawn using the information from the plot area, as specified in the pprAreaOpen call. RETURNS void BUGS o only linear axes are handled SEE ALSO pprPerim, pprGrid, pprAnnotX, pprAnnotY, pprAreaOpen SYNOPSIS void pprPerimLabel(pArea, xLabel, xAnnot, yLabel, yAnnot, angle) PPR_AREA *pArea; /* IO pointer to plotter area */ char *xLabel; /* I label for x axis, or NULL */ char **xAnnot; /* I pointer to array of x annotations, or NULL */ char *yLabel; /* I label for y axis, or NULL */ char **yAnnot; /* I pointer to array of y annotations, or NULL */ double angle; /* I angle for y annotations; 0. or 90. */ NAME pprPoint - plot a point at a coordinate DESCRIPTION Plot a pixel sized point using the line thickness and color attributes of the plot area. Two entry points are available: pprPointD(pArea, x, y) x and y are double pprPointL(pArea, x, y) x and y are long RETURNS void BUGS o only linear calibration is handled SEE ALSO pprMark, pprAreaOpen, pprAreaSetAttr, pprLine, pprMove, pprText SYNOPSIS void pprPointD(pArea, x, y) PPR_AREA *pArea; /* IO pointer to plot area structure */ double x; /* I x data coordinate */ double y; /* I y data coordinate */ NAME pprSin_deg - get the sine of an angle in degrees DESCRIPTION Get the sine of an angle in degrees. A table lookup technique is used. The angle argument is truncated to the next lower 1/4 degree prior to lookup. RETURNS sine SYNOPSIS double pprSin_deg(angle) double angle; /* I angle, in degrees */ NAME pprText - plot a text string DESCRIPTION Plots a text string at a location. The character "half height" is placed at the specified x,y position; the 'justification' option selects whether the left end, center, or right end of the text is placed at the x,y coordinate. The character height specification is in terms of a fraction of the height of the window. This results in automatic scaling of character sizes as the window size changes. If a height of zero is specified in the call, then the default height for the plot area is used. (The default height was established by pprAreaOpen.) A macro is available which returns the default character height used by this plot package. The value returned is proportional to the height of the plot area. This value can be used to generate "big" and "small" character sizes with simple multiplication of the default height by a "scale factor". PprDfltCharHt(lowYfrac, highYfrac) lowYfrac is the vertical fraction of the window at which the bottom edge of the plot area lies highYfrac is the vertical fraction of the window at which the top edge of the plot area lies It is also often useful to know what horizontal fraction of the window width corresponds to a vertical fraction of the height. The following routine returns the horizontal fraction: pprYFracToXFrac(pWin, yFrac) An alternate entry point, pprText_wc, is available to use the plot window's color for drawing the text. RETURNS void BUGS o technique used works only with linear axes o ASCII character codes are assumed o no checks are made for illegal characters o positioning and sizing are somewhat different for the various window types SEE ALSO pprChar, pprAreaOpen, pprLine, pprPoint, pprCvtDblToTxt SYNOPSIS void pprText(pArea, x, y, text, just, height, angle) PPR_AREA *pArea; /* IO pointer to plot area structure */ double x; /* I x data coordinate of text */ double y; /* I y data coordinate of text */ char *text; /* I text to plot */ PPR_TXT_JUST just; /* I text justification selector: one of PPR_TXT_CEN, PPR_TXT_RJ, or PPR_TXT_LJ */ double height; /* I height of text characters, as a fraction of the height of the window; a value of zero results in using a default height */ double angle; /* I orientation angle of text string, ccw degrees */ NAME pprWinClose - close a plot window DESCRIPTION Free the memory associated with a plot window structure and do other cleanup activities. This routine should be called when plotting is complete for a plot window. Any plot areas not previously closed are automatically closed by this routine. No further references to the plot window may be made. RETURNS void SEE ALSO pprAreaClose, pprWinInfo, pprWinOpen SYNOPSIS void pprWinClose(pWin) PPR_WIN *pWin; /* IO pointer to plot window structure */ NAME pprWinErase - erase a plot window DESCRIPTION Erase the contents of the entire plot window. RETURNS void SEE ALSO pprGridErase, pprPerimErase, pprAreaErase SYNOPSIS void pprWinErase(pWin) PPR_WIN *pWin; /* IO pointer to plot window structure */ NAME pprWinInfo - get some information about the plot window DESCRIPTION Get the size of the plot window and its position on the screen. RETURNS void NOTES 1. The information returned is window system dependent. To avoid portability problems, this information should be used only in calls to pprWinXxx routines. SYNOPSIS void pprWinInfo(pWin, pXpos, pYpos, pXwid, pYht) PPR_WIN *pWin; /* I pointer to plot window structure */ int *pXpos; /* O pointer to place to store window x coord., in pixels */ int *pYpos; /* O pointer to place to store window y coord., in pixels */ int *pXwid; /* O pointer to place to store window width, in pixels */ int *pYht; /* O pointer to place to store window height, in pixels */ NAME pprWinIsMono - test to see if plot window is monochrome DESCRIPTION RETURNS 1 if plot window is monochrome or gray scale 0 if plot window is color SYNOPSIS int pprWinIsMono(pWin) PPR_WIN *pWin; /* I pointer to plot window structure */ NAME pprWinLoop - loop until "quit" event received in window DESCRIPTION Handles the interactions with the windowing system. The specific actions depend on the plot window type: PPR_WIN_SCREEN o creates a window on the screen o when the window actually appears, calls the caller's draw function o for all subsequent resize and expose events, calls the caller's draw function o when the right mouse button is clicked, closes the window and returns to the caller. The current position and size of the window are stored (and can be retrieved with pprWinInfo). PPR_WIN_POSTSCRIPT o calls the caller's draw function PPR_WIN_EPS o calls the caller's draw function The idea when using pprWinLoop is that a program will do some preliminary setup for the data to be plotted. Then the program must turn control over to the plot "window manager" using pprWinLoop, which will call the caller's actual plot routine. When pprWinLoop exits back to the calling program, that program can call pprWinInfo in order to "remember" the plot window size and position. RETURNS 0, or -1 if an error is encountered BUGS o doesn't furnish information to the draw function which would allow a partial redraw o terminology is confusing and inconsistent: "draw" function, redraw, replot, repaint, etc. SEE ALSO pprWinOpen, pprWinInfo NOTES 1. Even though there aren't any "events" associated with plotting on a PostScript printer, this routine must be called even when using PPR_WIN_POSTSCRIPT and PPR_WIN_EPS, since this routine invokes the caller's "draw" function. EXAMPLE See pprWinOpen for an example of a replot function. j SYNOPSIS long pprWinLoop(pWin, drawFun, pDrawArg) PPR_WIN *pWin; /* IO pointer to plot window structure */ void (*drawFun)();/* I pointer to function to draw the plot */ void *pDrawArg;/* I pointer to pass to drawFun */ NAME pprWinOpen - initialize a plotting "window" structure DESCRIPTION Initialize a plot window structure. This is the structure which keeps track of the information needed to interact with the device on which the "window" resides. The possible types of windows are: o PPR_WIN_SCREEN selects a window on a visual display. This will be a SunView or X window, depending on the version of the plotting used in linking the program. The pprWinOpen call actually creates a window, with the root window as the parent. The window thus created can be moved, resized, etc. according to the capabilities of the window manager of the windowing system being used. (To initialize a plotting window structure in a window which already exists, use pprWinOpenUW.) for SunView, `winDispName' is ignored and should be NULL `winTitle' appears on the window's title bar and icon `xPos' and `yPos' are pixel offsets from the upper left corner of the root window. If values of 0 are supplied, then the window will be positioned at 100,100. `xWid' and `yHt' are the width and height of the window, in pixels. If values of 0 are supplied, then a size of 512,512 will be used. for X, `winDispName' specifies the X display name on which the plot window is to appear. If NULL, then the DISPLAY environment variable will be used. `winTitle' appears on the window's title bar and icon `xPos' and `yPos' are pixel offsets from the upper left corner of the root window. If values of 0 are supplied, then the window will be positioned at 100,100. `xWid' and `yHt' are the width and height of the window, in pixels. If values of 0 are supplied, then a size of 512,512 will be used. o PPR_WIN_POSTSCRIPT selects a "window" on a PostScript printer. `winDispName' is the name of a file to receive PostScript output. This is the file which will eventually be sent to a PostScript printer to get a hard copy of the plot. If the file exists when pprWinOpen is called, its contents are erased before writing begins. `winTitle' is ignored and should be NULL `xPos' and `yPos' are ignored `xWid' and `yHt' are the width and height of the window, in pixels. If values of 0 are supplied, then a size of 512,512 will be used. If the size is larger than the page, then the plot will be scaled to fit. If necessary, the plot will be printed in landscape mode, rather than the default of portrait mode. o PPR_WIN_EPS selects a "window" in an Encapsulated PostScript file. EPS files are intended to be included into documents prepared by word processing programs such as Interleaf and TeX. EPS files will not print directly on a PostScript printer. The description of the arguments for PPR_WIN_POSTSCRIPT applies, except that scaling and rotation aren't done. The pprXxx routines can be used for several different styles of usage: o a complete set of data is available prior to calling any of the plotting routines. In this case, grids can be drawn and data can be plotted at the same time. For this style of usage, the typical usage will be: pprWinOpen to "open" a plot window pprWinLoop to map the plot window to the screen and call the caller's replot function when the window is exposed, resized, etc. pprWinClose to "close" a plot window o no data (or only part of the data) is available prior to calling any of the plotting routines. In this case, at least some of the data must be plotted at a later time than when the grids are drawn. The pprXxx routines don't automatically support this style of usage fully, but they do provide some tools which make it relatively easy to implement. See pprWinOpenUW for more details. Under all circumstances, the calling program is expected to call pprWinClose when plotting is complete for the plot window. RETURNS pointer to window structure, or NULL if an error is encountered SEE ALSO pprWinOpenUW, pprWinClose, pprWinInfo, pprWinLoop EXAMPLES 1. Plot an existing set of data, where the data is stored in `dataStruct'. PPR_WIN *pWindow; . pWindow = pprWinOpen(PPR_WIN_SCREEN, NULL, "test", 0, 0, 0, 0); if (pWindow == NULL) abort(); if (pprWinLoop(pWindow, replot, &dataStruct) != 0) abort(); pprWinClose(pWindow); SYNOPSIS PPR_WIN * pprWinOpen(winType, winDispName, winTitle, xPos, yPos, xWid, yHt) PPR_WIN_TY winType; /* I type of plot window: PPR_WIN_xxx */ char *winDispName; /* I name of "display" or file for window */ char *winTitle; /* I title for window title bar and icon */ int xPos; /* I x position for window; 0 for default */ int yPos; /* I y position for window; 0 for default */ int xWid; /* I width of window; 0 for default */ int yHt; /* I height of window; 0 for default */ NAME pprWinOpenUW - open a plot "window" to an existing User Window DESCRIPTION Initialize a plot window structure. This is the structure which keeps track of the information needed to interact with the device on which the "window" resides. This routine is for use when the caller already has a window in the windowing system. It is for use exclusively for PPR_WIN_SCREEN plot window type. The form of the call to this routine is heavily dependent on the windowing system being used. This routine provides the basis for obtaining `asynchronous' plotting. (It can also be used for `batched' plotting, in which all data is available prior to the first plotting call.) Under all circumstances, the calling program is expected to call pprWinClose when plotting is complete for the plot window. RETURNS pointer to window structure, or NULL if an error is encountered SEE ALSO pprWinOpenUW, pprWinClose, pprWinInfo, pprWinLoop EXAMPLES 1. for X PPR_WIN *pWin; Display *pDisp; Window plotWindow; GC plotGC; pWin = pprWinOpenUW(&pDisp, &plotWindow, &plotGC, NULL); ... pprWinReplot(pWin, drawFn, drawArg); ... pprWinClose(pWin); 2. for SunView PPR_WIN *pWin; Frame plotFrame; Canvas plotCanvas; pWin = pprWinOpenUW(&plotFrame, &plotCanvas, NULL, NULL); ... pprWinReplot(pWin, drawFn, drawArg); ... pprWinClose(pWin); 3. for XView PPR_WIN *pWin; Display *pDisp; Window plotWindow; GC plotGC; pDisp = (Display *)xv_get(frame, XV_DISPLAY); window = (Window)xv_get(canvas_paint_window(canvas), XV_XID); plotGC = DefaultGC(pDisp, DefaultScreen(pDisp)); pWin = pprWinOpenUW(&pDisp, &plotWindow, &plotGC, NULL); ... pprWinReplot(pWin, drawFn, drawArg); ... pprWinClose(pWin); SYNOPSIS PPR_WIN * pprWinOpenUW(pArg1, pArg2, pArg3, pArg4) void *pArg1; void *pArg2; void *pArg3; void *pArg4; NAME pprWinReplot - redraw a plot in a user owned window DESCRIPTION Calls the "replot" function to repaint the plot window. This routine is intended to be used with "user owned" plot windows which have been opened with pprWinOpenUW. Prior to calling the replot function, this routine determines the size of the actual window and rescales the existing plot areas. RETURNS void SEE ALSO pprWinOpenUW SYNOPSIS void pprWinReplot(pWin, pFunc, pArg) PPR_WIN *pWin; void (*pFunc)(); void *pArg; NAME pprYFracToXFrac - convert a Y fraction to an X fraction DESCRIPTION Converts a value which is a fraction of window height into a value which is a fraction of window width, so that the two values will represent the same physical size, in pixels. This routine is useful for laying out a plot area, especially when a grid with annotations and labels is to be used. The choice of "data area" size (i.e., the size of the grid) depends on the size of the characters which will be used for the annotations and labels. RETURNS void SEE ALSO pprText EXAMPLE A plot area is use the full width and the vertical 1/3 of the window. x values range from 0 to 100, while y is from -10 to 10. The x axis is to be divided into 10 divisions, the y into 4. Use the default character size for annotations and labels. Also, use the default window position and size. PPR_WIN *pWin; PPR_AREA *pArea; float charHt; height as a fraction of window height float charWid; width as a fraction of window width charHt = PprDfltCharHt(.33, .67); charWid = pprYFracToXFrac(pWin, charHt); pArea = pprAreaOpen(pWin, 12.*charWid, .33+6.*charHt, 1., .67, 0., -10., 100., 10, 4, charHt); SYNOPSIS double pprYFracToXFrac(pWin, yFrac) PPR_WIN *pWin; /* I pointer to plot window structure */ double yFrac; /* I fraction of window height */