1264 lines
33 KiB
C
1264 lines
33 KiB
C
/* $Header$ */
|
||
/*
|
||
* draw.c: xgraph drawing code
|
||
*
|
||
* Routines:
|
||
* void DrawWindow();
|
||
*
|
||
* $Log$
|
||
* Revision 1.1 2004-01-25 09:00:49 pnenzi
|
||
*
|
||
* Added xgraph plotting program.
|
||
*
|
||
* Revision 1.1.1.1 1999/12/03 23:15:53 heideman
|
||
* xgraph-12.0
|
||
*
|
||
*/
|
||
#ifndef lint
|
||
static char rcsid[] = "$Id$";
|
||
#endif
|
||
|
||
#include "copyright.h"
|
||
#include <stdio.h>
|
||
#include <math.h>
|
||
#include <pwd.h>
|
||
#include <ctype.h>
|
||
#include "xgraph.h"
|
||
#include "xtb.h"
|
||
#include "hard_devices.h"
|
||
#include "params.h"
|
||
|
||
|
||
static void DrawTitle();
|
||
static void DrawGridAndAxis();
|
||
static void WriteValue();
|
||
static void DrawData();
|
||
static void DrawLegend();
|
||
static int TransformCompute();
|
||
static double initGrid();
|
||
static double stepGrid();
|
||
static double RoundUp();
|
||
static void set_mark_flags();
|
||
|
||
void
|
||
DrawWindow(win_info)
|
||
LocalWin *win_info; /* Window information */
|
||
|
||
/*
|
||
* Draws the data in the window. Does not clear the window.
|
||
* The data is scaled so that all of the data will fit.
|
||
* Grid lines are drawn at the nearest power of 10 in engineering
|
||
* notation. Draws axis numbers along bottom and left hand edges.
|
||
* Centers title at top of window.
|
||
*/
|
||
{
|
||
/* Figure out the transformation constants */
|
||
if (TransformCompute(win_info)) {
|
||
|
||
/* Draw the title */
|
||
DrawTitle(win_info);
|
||
|
||
/* Draw the legend */
|
||
if (!PM_BOOL("NoLegend"))
|
||
DrawLegend(win_info);
|
||
|
||
/* Draw the axis unit labels, grid lines, and grid labels */
|
||
DrawGridAndAxis(win_info);
|
||
|
||
/* Draw the data sets themselves */
|
||
DrawData(win_info);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
static void
|
||
DrawTitle(wi)
|
||
LocalWin *wi; /* Window information */
|
||
|
||
/*
|
||
* This routine draws the title of the graph centered in
|
||
* the window. It is spaced down from the top by an amount
|
||
* specified by the constant PADDING. The font must be
|
||
* fixed width. The routine returns the height of the
|
||
* title in pixels.
|
||
*/
|
||
{
|
||
if (wi->DOrder == 0)
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
(int)(wi->dev_info.area_w*0.95) ,
|
||
wi->dev_info.axis_pad,
|
||
PM_STR("TitleText"), T_UPPERRIGHT, T_TITLE);
|
||
else if (wi->DOrder == 1)
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
(int)(wi->dev_info.area_w*0.95) ,
|
||
wi->dev_info.axis_pad,
|
||
"First Derivative", T_UPPERRIGHT, T_TITLE);
|
||
else if (wi->DOrder == 2)
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
(int)(wi->dev_info.area_w*0.95) ,
|
||
wi->dev_info.axis_pad,
|
||
"Second Derivative", T_UPPERRIGHT, T_TITLE);
|
||
}
|
||
|
||
|
||
|
||
|
||
static int
|
||
TransformCompute(wi)
|
||
LocalWin *wi; /* Window information */
|
||
|
||
/*
|
||
* This routine figures out how to draw the axis labels and grid lines.
|
||
* Both linear and logarithmic axes are supported. Axis labels are
|
||
* drawn in engineering notation. The power of the axes are labeled
|
||
* in the normal axis labeling spots. The routine also figures
|
||
* out the necessary transformation information for the display
|
||
* of the points (it touches XOrgX, XOrgY, UsrOrgX, UsrOrgY, and
|
||
* UnitsPerPixel).
|
||
*/
|
||
{
|
||
double bbCenX,
|
||
bbCenY,
|
||
bbHalfWidth,
|
||
bbHalfHeight;
|
||
int idx,
|
||
maxName,
|
||
leftWidth;
|
||
char err[MAXBUFSIZE];
|
||
char *XUnitText = PM_STR("XUnitText");
|
||
|
||
/*
|
||
* First, we figure out the origin in the X window. Above the space we
|
||
* have the title and the Y axis unit label. To the left of the space we
|
||
* have the Y axis grid labels.
|
||
*/
|
||
|
||
wi->XOrgX = wi->dev_info.bdr_pad + (7 * wi->dev_info.axis_width)
|
||
+ wi->dev_info.bdr_pad;
|
||
wi->XOrgY = wi->dev_info.bdr_pad + wi->dev_info.title_height
|
||
+ wi->dev_info.bdr_pad + wi->dev_info.axis_height
|
||
+ wi->dev_info.axis_height / 2 + wi->dev_info.bdr_pad;
|
||
|
||
/*
|
||
* Now we find the lower right corner. Below the space we have the X axis
|
||
* grid labels. To the right of the space we have the X axis unit label
|
||
* and the legend. We assume the worst case size for the unit label.
|
||
*/
|
||
|
||
maxName = 0;
|
||
for (idx = 0; idx < MAXSETS; idx++) {
|
||
if (PlotData[idx].list) {
|
||
int tempSize;
|
||
|
||
tempSize = strlen(PlotData[idx].setName);
|
||
if (tempSize > maxName)
|
||
maxName = tempSize;
|
||
}
|
||
}
|
||
if (PM_BOOL("NoLegend"))
|
||
maxName = 0;
|
||
/* Worst case size of the X axis label: */
|
||
leftWidth = (strlen(XUnitText)) * wi->dev_info.axis_width;
|
||
if ((maxName * wi->dev_info.axis_width) + wi->dev_info.bdr_pad > leftWidth)
|
||
leftWidth = maxName * wi->dev_info.axis_width + wi->dev_info.bdr_pad;
|
||
|
||
wi->XOppX = wi->dev_info.area_w - wi->dev_info.bdr_pad - leftWidth;
|
||
wi->XOppY = wi->dev_info.area_h - wi->dev_info.bdr_pad
|
||
- wi->dev_info.axis_height - wi->dev_info.bdr_pad;
|
||
|
||
if ((wi->XOrgX >= wi->XOppX) || (wi->XOrgY >= wi->XOppY)) {
|
||
do_error(strcpy(err, "Drawing area is too small\n"));
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* We now have a bounding box for the drawing region. Figure out the units
|
||
* per pixel using the data set bounding box.
|
||
*/
|
||
wi->XUnitsPerPixel = (wi->hiX - wi->loX) /
|
||
((double) (wi->XOppX - wi->XOrgX));
|
||
wi->YUnitsPerPixel = (wi->hiY - wi->loY) /
|
||
((double) (wi->XOppY - wi->XOrgY));
|
||
|
||
/*
|
||
* Find origin in user coordinate space. We keep the center of the
|
||
* original bounding box in the same place.
|
||
*/
|
||
bbCenX = (wi->loX + wi->hiX) / 2.0;
|
||
bbCenY = (wi->loY + wi->hiY) / 2.0;
|
||
bbHalfWidth = ((double) (wi->XOppX - wi->XOrgX)) / 2.0 * wi->XUnitsPerPixel;
|
||
bbHalfHeight = ((double) (wi->XOppY - wi->XOrgY)) / 2.0 * wi->YUnitsPerPixel;
|
||
wi->UsrOrgX = bbCenX - bbHalfWidth;
|
||
wi->UsrOrgY = bbCenY - bbHalfHeight;
|
||
wi->UsrOppX = bbCenX + bbHalfWidth;
|
||
wi->UsrOppY = bbCenY + bbHalfHeight;
|
||
|
||
/*
|
||
* Everything is defined so we can now use the SCREENX and SCREENY
|
||
* transformations.
|
||
*/
|
||
return 1;
|
||
}
|
||
|
||
static void
|
||
DrawGridAndAxis(wi)
|
||
LocalWin *wi; /* Window information */
|
||
|
||
/*
|
||
* This routine draws grid line labels in engineering notation,
|
||
* the grid lines themselves, and unit labels on the axes.
|
||
*/
|
||
{
|
||
int expX,
|
||
expY; /* Engineering powers */
|
||
int startX;
|
||
int Yspot,
|
||
Xspot;
|
||
char power[10],
|
||
value[10],
|
||
final[MAXBUFSIZE + 10];
|
||
double Xincr,
|
||
Yincr,
|
||
Xstart,
|
||
Ystart,
|
||
Yindex,
|
||
Xindex,
|
||
larger;
|
||
XSegment segs[2];
|
||
double initGrid(),
|
||
stepGrid();
|
||
int tickFlag = PM_BOOL("Ticks");
|
||
int axisFlag = PM_BOOL("TickAxis");
|
||
int logXFlag = PM_BOOL("LogX");
|
||
int logYFlag = PM_BOOL("LogY");
|
||
char *XUnitText = PM_STR("XUnitText");
|
||
char *YUnitText = PM_STR("YUnitText");
|
||
|
||
/*
|
||
* Grid display powers are computed by taking the log of the largest
|
||
* numbers and rounding down to the nearest multiple of 3.
|
||
*/
|
||
if (logXFlag) {
|
||
expX = 0;
|
||
}
|
||
else {
|
||
if (fabs(wi->UsrOrgX) > fabs(wi->UsrOppX)) {
|
||
larger = fabs(wi->UsrOrgX);
|
||
}
|
||
else {
|
||
larger = fabs(wi->UsrOppX);
|
||
}
|
||
expX = ((int) floor(nlog10(larger) / 3.0)) * 3;
|
||
}
|
||
if (logYFlag) {
|
||
expY = 0;
|
||
}
|
||
else {
|
||
if (fabs(wi->UsrOrgY) > fabs(wi->UsrOppY)) {
|
||
larger = fabs(wi->UsrOrgY);
|
||
}
|
||
else {
|
||
larger = fabs(wi->UsrOppY);
|
||
}
|
||
expY = ((int) floor(nlog10(larger) / 3.0)) * 3;
|
||
}
|
||
|
||
/*
|
||
* With the powers computed, we can draw the axis labels.
|
||
*/
|
||
if (expY != 0) {
|
||
(void) strcpy(final, YUnitText);
|
||
(void) strcat(final, " x 10");
|
||
Xspot = wi->dev_info.bdr_pad +
|
||
((strlen(YUnitText) + 5) * wi->dev_info.axis_width);
|
||
Yspot = wi->dev_info.bdr_pad * 2 + wi->dev_info.title_height +
|
||
wi->dev_info.axis_height / 2;
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
Xspot, Yspot, final, T_RIGHT, T_AXIS);
|
||
(void) sprintf(power, "%d", expY);
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
Xspot, Yspot, power, T_LOWERLEFT, T_AXIS);
|
||
}
|
||
else {
|
||
Yspot = wi->dev_info.bdr_pad * 2 + wi->dev_info.title_height;
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
wi->dev_info.bdr_pad, Yspot, YUnitText,
|
||
T_UPPERLEFT, T_AXIS);
|
||
}
|
||
|
||
startX = wi->dev_info.area_w - wi->dev_info.bdr_pad;
|
||
if (expX != 0) {
|
||
(void) sprintf(power, "%d", expX);
|
||
startX -= (strlen(power) * wi->dev_info.axis_width);
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
startX, wi->XOppY, power, T_LOWERLEFT, T_AXIS);
|
||
(void) strcpy(final, XUnitText);
|
||
(void) strcat(final, " x 10");
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
startX, wi->XOppY, final, T_RIGHT, T_AXIS);
|
||
}
|
||
else {
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
startX, wi->XOppY, XUnitText, T_RIGHT, T_AXIS);
|
||
}
|
||
|
||
/*
|
||
* First, the grid line labels
|
||
*/
|
||
Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) *
|
||
wi->YUnitsPerPixel;
|
||
Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag);
|
||
for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) {
|
||
Yspot = SCREENY(wi, Yindex);
|
||
/* Write the axis label */
|
||
WriteValue(value, PM_STR("Format X"), Yindex, expY, logYFlag);
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
wi->dev_info.bdr_pad +
|
||
(7 * wi->dev_info.axis_width),
|
||
Yspot, value, T_RIGHT, T_AXIS);
|
||
}
|
||
|
||
Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) *
|
||
wi->XUnitsPerPixel;
|
||
Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag);
|
||
|
||
for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) {
|
||
Xspot = SCREENX(wi, Xindex);
|
||
/* Write the axis label */
|
||
WriteValue(value, PM_STR("Format Y"), Xindex, expX, logXFlag);
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
Xspot,
|
||
wi->dev_info.area_h - wi->dev_info.bdr_pad,
|
||
value, T_BOTTOM, T_AXIS);
|
||
}
|
||
|
||
/*
|
||
* Now, the grid lines or tick marks
|
||
*/
|
||
Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) *
|
||
wi->YUnitsPerPixel;
|
||
Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag);
|
||
for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) {
|
||
Yspot = SCREENY(wi, Yindex);
|
||
/* Draw the grid line or tick mark */
|
||
if (tickFlag && !(axisFlag && Yindex == Ystart)) {
|
||
segs[0].x1 = wi->XOrgX;
|
||
segs[0].x2 = wi->XOrgX + wi->dev_info.tick_len;
|
||
segs[1].x1 = wi->XOppX - wi->dev_info.tick_len;
|
||
segs[1].x2 = wi->XOppX;
|
||
segs[0].y1 = segs[0].y2 = segs[1].y1 = segs[1].y2 = Yspot;
|
||
}
|
||
else {
|
||
segs[0].x1 = wi->XOrgX;
|
||
segs[0].x2 = wi->XOppX;
|
||
segs[0].y1 = segs[0].y2 = Yspot;
|
||
}
|
||
if ((ABS(Yindex) < ZERO_THRES) && !logYFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, segs, PM_INT("ZeroWidth"),
|
||
L_ZERO, 0, 0);
|
||
if (tickFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &(segs[1]), PM_INT("ZeroWidth"),
|
||
L_ZERO, 0, 0);
|
||
}
|
||
}
|
||
else {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, segs, PM_INT("GridSize"),
|
||
L_AXIS, 0, 0);
|
||
if (tickFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &(segs[1]), PM_INT("GridSize"),
|
||
L_AXIS, 0, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) *
|
||
wi->XUnitsPerPixel;
|
||
Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag);
|
||
for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) {
|
||
Xspot = SCREENX(wi, Xindex);
|
||
/* Draw the grid line or tick marks */
|
||
if (tickFlag && !(axisFlag && Xindex == Xstart)) {
|
||
segs[0].x1 = segs[0].x2 = segs[1].x1 = segs[1].x2 = Xspot;
|
||
segs[0].y1 = wi->XOrgY;
|
||
segs[0].y2 = wi->XOrgY + wi->dev_info.tick_len;
|
||
segs[1].y1 = wi->XOppY - wi->dev_info.tick_len;
|
||
segs[1].y2 = wi->XOppY;
|
||
}
|
||
else {
|
||
segs[0].x1 = segs[0].x2 = Xspot;
|
||
segs[0].y1 = wi->XOrgY;
|
||
segs[0].y2 = wi->XOppY;
|
||
}
|
||
if ((ABS(Xindex) < ZERO_THRES) && !logXFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, segs, PM_INT("ZeroWidth"), L_ZERO, 0, 0);
|
||
if (tickFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &(segs[1]), PM_INT("ZeroWidth"),
|
||
L_ZERO, 0, 0);
|
||
|
||
}
|
||
}
|
||
else {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, segs, PM_INT("GridSize"), L_AXIS, 0, 0);
|
||
if (tickFlag) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &(segs[1]), PM_INT("GridSize"), L_AXIS, 0, 0);
|
||
}
|
||
}
|
||
}
|
||
/* Check to see if he wants a bounding box */
|
||
if (PM_BOOL("BoundBox")) {
|
||
XSegment bb[4];
|
||
|
||
/* Draw bounding box */
|
||
bb[0].x1 = bb[0].x2 = bb[1].x1 = bb[3].x2 = wi->XOrgX;
|
||
bb[0].y1 = bb[2].y2 = bb[3].y1 = bb[3].y2 = wi->XOrgY;
|
||
bb[1].x2 = bb[2].x1 = bb[2].x2 = bb[3].x1 = wi->XOppX;
|
||
bb[0].y2 = bb[1].y1 = bb[1].y2 = bb[2].y1 = wi->XOppY;
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
4, bb, PM_INT("GridSize"), L_AXIS, 0, 0);
|
||
}
|
||
}
|
||
|
||
static double gridBase,
|
||
gridStep,
|
||
gridJuke[101];
|
||
static int gridNJuke,
|
||
gridCurJuke;
|
||
|
||
#define ADD_GRID(val) (gridJuke[gridNJuke++] = log10(val))
|
||
|
||
static double
|
||
initGrid(low, step, logFlag)
|
||
double low; /* desired low value */
|
||
double step; /* desired step (user coords) */
|
||
int logFlag; /* is axis logarithmic? */
|
||
{
|
||
double ratio,
|
||
x;
|
||
double RoundUp(),
|
||
stepGrid();
|
||
|
||
gridNJuke = gridCurJuke = 0;
|
||
gridJuke[gridNJuke++] = 0.0;
|
||
|
||
if (logFlag) {
|
||
ratio = pow(10.0, step);
|
||
gridBase = floor(low);
|
||
gridStep = ceil(step);
|
||
if (ratio <= 3.0) {
|
||
if (ratio > 2.0) {
|
||
ADD_GRID(3.0);
|
||
}
|
||
else if (ratio > 1.333) {
|
||
ADD_GRID(2.0);
|
||
ADD_GRID(5.0);
|
||
}
|
||
else if (ratio > 1.25) {
|
||
ADD_GRID(1.5);
|
||
ADD_GRID(2.0);
|
||
ADD_GRID(3.0);
|
||
ADD_GRID(5.0);
|
||
ADD_GRID(7.0);
|
||
}
|
||
else {
|
||
for (x = 1.0; x < 10.0 && (x + .5) / (x + .4) >= ratio; x += .5) {
|
||
ADD_GRID(x + .1);
|
||
ADD_GRID(x + .2);
|
||
ADD_GRID(x + .3);
|
||
ADD_GRID(x + .4);
|
||
ADD_GRID(x + .5);
|
||
}
|
||
if (floor(x) != x)
|
||
ADD_GRID(x += .5);
|
||
for (; x < 10.0 && (x + 1.0) / (x + .5) >= ratio; x += 1.0) {
|
||
ADD_GRID(x + .5);
|
||
ADD_GRID(x + 1.0);
|
||
}
|
||
for (; x < 10.0 && (x + 1.0) / x >= ratio; x += 1.0) {
|
||
ADD_GRID(x + 1.0);
|
||
}
|
||
if (x == 7.0) {
|
||
gridNJuke--;
|
||
x = 6.0;
|
||
}
|
||
if (x < 7.0) {
|
||
ADD_GRID(x + 2.0);
|
||
}
|
||
if (x == 10.0)
|
||
gridNJuke--;
|
||
}
|
||
x = low - gridBase;
|
||
for (gridCurJuke = -1; x >= gridJuke[gridCurJuke + 1]; gridCurJuke++) {
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
gridStep = RoundUp(step);
|
||
gridBase = floor(low / gridStep) * gridStep;
|
||
}
|
||
return (stepGrid());
|
||
}
|
||
|
||
static double
|
||
stepGrid()
|
||
{
|
||
if (++gridCurJuke >= gridNJuke) {
|
||
gridCurJuke = 0;
|
||
gridBase += gridStep;
|
||
}
|
||
return (gridBase + gridJuke[gridCurJuke]);
|
||
}
|
||
|
||
static double
|
||
RoundUp(val)
|
||
double val; /* Value */
|
||
|
||
/*
|
||
* This routine rounds up the given positive number such that
|
||
* it is some power of ten times either 1, 2, or 5. It is
|
||
* used to find increments for grid lines.
|
||
*/
|
||
{
|
||
int exponent,
|
||
idx;
|
||
|
||
exponent = (int) floor(nlog10(val));
|
||
if (exponent < 0) {
|
||
for (idx = exponent; idx < 0; idx++) {
|
||
val *= 10.0;
|
||
}
|
||
}
|
||
else {
|
||
for (idx = 0; idx < exponent; idx++) {
|
||
val /= 10.0;
|
||
}
|
||
}
|
||
if (val > 5.0)
|
||
val = 10.0;
|
||
else if (val > 2.0)
|
||
val = 5.0;
|
||
else if (val > 1.0)
|
||
val = 2.0;
|
||
else
|
||
val = 1.0;
|
||
if (exponent < 0) {
|
||
for (idx = exponent; idx < 0; idx++) {
|
||
val /= 10.0;
|
||
}
|
||
}
|
||
else {
|
||
for (idx = 0; idx < exponent; idx++) {
|
||
val *= 10.0;
|
||
}
|
||
}
|
||
return val;
|
||
}
|
||
|
||
static void
|
||
WriteValue(str, fmt, val, expv, logFlag)
|
||
char *str; /* String to write into */
|
||
char *fmt; /* Format to print str */
|
||
double val; /* Value to print */
|
||
int expv; /* Exponent */
|
||
int logFlag; /* Is this a log axis? */
|
||
|
||
/*
|
||
* Writes the value provided into the string in a fixed format
|
||
* consisting of seven characters. The format is:
|
||
* -ddd.dd
|
||
*/
|
||
{
|
||
int idx;
|
||
|
||
if (logFlag) {
|
||
if (val == floor(val)) {
|
||
if (strcmp(fmt, "%.2f") == 0)
|
||
fmt = "%.0e";
|
||
val = pow(10.0, val);
|
||
}
|
||
else {
|
||
if (strcmp(fmt, "%.2f") == 0)
|
||
fmt = "%.2g";
|
||
val = pow(10.0, val - floor(val));
|
||
}
|
||
}
|
||
else {
|
||
if (expv < 0) {
|
||
for (idx = expv; idx < 0; idx++) {
|
||
val *= 10.0;
|
||
}
|
||
}
|
||
else {
|
||
for (idx = 0; idx < expv; idx++) {
|
||
val /= 10.0;
|
||
}
|
||
}
|
||
}
|
||
if (strchr(fmt, 'd') || strchr(fmt, 'x'))
|
||
(void) sprintf(str, fmt, (int) val);
|
||
else
|
||
(void) sprintf(str, fmt, val);
|
||
}
|
||
|
||
|
||
#define LEFT_CODE 0x01
|
||
#define RIGHT_CODE 0x02
|
||
#define BOTTOM_CODE 0x04
|
||
#define TOP_CODE 0x08
|
||
|
||
/* Clipping algorithm from Neumann and Sproull by Cohen and Sutherland */
|
||
#define C_CODE(xval, yval, rtn) \
|
||
rtn = 0; \
|
||
if ((xval) < wi->UsrOrgX) rtn = LEFT_CODE; \
|
||
else if ((xval) > wi->UsrOppX) rtn = RIGHT_CODE; \
|
||
if ((yval) < wi->UsrOrgY) rtn |= BOTTOM_CODE; \
|
||
else if ((yval) > wi->UsrOppY) rtn |= TOP_CODE
|
||
|
||
void
|
||
EraseData(wi)
|
||
LocalWin *wi;
|
||
|
||
/*
|
||
* This routine draws the data sets themselves using the macros
|
||
* for translating coordinates.
|
||
*/
|
||
{
|
||
double sx1,
|
||
sy1,
|
||
sx2,
|
||
sy2,
|
||
tx = 0,
|
||
ty = 0;
|
||
int idx,
|
||
subindex;
|
||
int code1,
|
||
code2,
|
||
cd,
|
||
mark_inside;
|
||
int X_idx, StoreIDX; /* PW */
|
||
XSegment *ptr;
|
||
PointList *thisList,
|
||
*lastList;
|
||
int markFlag,
|
||
pixelMarks,
|
||
bigPixel,
|
||
colorMark;
|
||
int noLines = PM_BOOL("NoLines");
|
||
int lineWidth = PM_INT("LineWidth");
|
||
|
||
/* PW Suggests we Flush and set first */
|
||
set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
|
||
for (idx = 0; idx < MAXSETS; idx++) {
|
||
if (wi->DOrder == 0)
|
||
thisList = PlotData[idx].list;
|
||
else if (wi->DOrder == 1)
|
||
thisList = DataD1[idx].list;
|
||
else if (wi->DOrder == 2)
|
||
thisList = DataD2[idx].list;
|
||
else {
|
||
printf ("Internal Error differentiating - order > 2!\n");
|
||
exit (1);
|
||
}
|
||
while (thisList) {
|
||
X_idx = 0;
|
||
for (subindex = 0; subindex < thisList->numPoints - 1; subindex++) {
|
||
/* Put segment in (sx1,sy1) (sx2,sy2) */
|
||
sx1 = thisList->xvec[subindex];
|
||
sy1 = thisList->yvec[subindex];
|
||
sx2 = thisList->xvec[subindex + 1];
|
||
sy2 = thisList->yvec[subindex + 1];
|
||
/* Now clip to current window boundary */
|
||
C_CODE(sx1, sy1, code1);
|
||
C_CODE(sx2, sy2, code2);
|
||
mark_inside = (code1 == 0);
|
||
while (code1 || code2) {
|
||
if (code1 & code2)
|
||
break;
|
||
cd = (code1 ? code1 : code2);
|
||
if (cd & LEFT_CODE) { /* Crosses left edge */
|
||
ty = sy1 + (sy2 - sy1) * (wi->UsrOrgX - sx1) /
|
||
(sx2 - sx1);
|
||
tx = wi->UsrOrgX;
|
||
}
|
||
else if (cd & RIGHT_CODE) { /* Crosses right edge */
|
||
ty = sy1 + (sy2 - sy1) * (wi->UsrOppX - sx1) /
|
||
(sx2 - sx1);
|
||
tx = wi->UsrOppX;
|
||
}
|
||
else if (cd & BOTTOM_CODE) {/* Crosses bottom edge */
|
||
tx = sx1 + (sx2 - sx1) * (wi->UsrOrgY - sy1) /
|
||
(sy2 - sy1);
|
||
ty = wi->UsrOrgY;
|
||
}
|
||
else if (cd & TOP_CODE) { /* Crosses top edge */
|
||
tx = sx1 + (sx2 - sx1) * (wi->UsrOppY - sy1) /
|
||
(sy2 - sy1);
|
||
ty = wi->UsrOppY;
|
||
}
|
||
if (cd == code1) {
|
||
sx1 = tx;
|
||
sy1 = ty;
|
||
C_CODE(sx1, sy1, code1);
|
||
}
|
||
else {
|
||
sx2 = tx;
|
||
sy2 = ty;
|
||
C_CODE(sx2, sy2, code2);
|
||
}
|
||
}
|
||
if (!code1 && !code2) {
|
||
/* Add segment to list */
|
||
Xsegs[0][X_idx].x1 = Xsegs[1][X_idx].x1;
|
||
Xsegs[0][X_idx].y1 = Xsegs[1][X_idx].y1;
|
||
Xsegs[0][X_idx].x2 = Xsegs[1][X_idx].x2;
|
||
Xsegs[0][X_idx].y2 = Xsegs[1][X_idx].y2;
|
||
Xsegs[1][X_idx].x1 = SCREENX(wi, sx1);
|
||
Xsegs[1][X_idx].y1 = SCREENY(wi, sy1);
|
||
Xsegs[1][X_idx].x2 = SCREENX(wi, sx2);
|
||
Xsegs[1][X_idx].y2 = SCREENY(wi, sy2);
|
||
X_idx++;
|
||
}
|
||
|
||
/* Draw markers if requested and they are in drawing region */
|
||
if (markFlag && mark_inside) {
|
||
if (pixelMarks) {
|
||
if (bigPixel) {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_DOT, 0, idx % MAXATTR);
|
||
}
|
||
else {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_PIXEL, 0, PIXVALUE(idx));
|
||
}
|
||
}
|
||
else {
|
||
/* Distinctive markers */
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_MARK, MARKSTYLE(idx),
|
||
PIXVALUE(idx));
|
||
}
|
||
}
|
||
|
||
/* Draw bar elements if requested */
|
||
if (PM_BOOL("BarGraph")) {
|
||
int barPixels,
|
||
baseSpot;
|
||
XSegment line;
|
||
|
||
barPixels = (int) ((PM_DBL("BarWidth") /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (barPixels <= 0)
|
||
barPixels = 1;
|
||
baseSpot = SCREENY(wi, PM_DBL("BarBase"));
|
||
line.x1 = line.x2 = Xsegs[1][X_idx - 1].x1 +
|
||
(int) ((PM_DBL("BarOffset") * idx /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (PM_BOOL("StackGraph") && idx != 0)
|
||
line.y1 = Xsegs[0][X_idx - 1].y1;
|
||
else
|
||
line.y1 = baseSpot;
|
||
line.y2 = Xsegs[1][X_idx - 1].y1;
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &line, barPixels, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
}
|
||
}
|
||
/* Handle last marker */
|
||
if (markFlag && (thisList->numPoints > 0)) {
|
||
C_CODE(thisList->xvec[thisList->numPoints - 1],
|
||
thisList->yvec[thisList->numPoints - 1],
|
||
mark_inside);
|
||
if (mark_inside == 0) {
|
||
if (pixelMarks) {
|
||
if (bigPixel) {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_DOT, 0, idx % MAXATTR);
|
||
}
|
||
else {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_PIXEL, 0, PIXVALUE(idx));
|
||
}
|
||
}
|
||
else {
|
||
/* Distinctive markers */
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_MARK, MARKSTYLE(idx),
|
||
PIXVALUE(idx));
|
||
}
|
||
}
|
||
}
|
||
/* Handle last bar */
|
||
if ((thisList->numPoints > 0) && PM_BOOL("BarGraph")) {
|
||
int barPixels,
|
||
baseSpot;
|
||
XSegment line;
|
||
|
||
barPixels = (int) ((PM_DBL("BarWidth") /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (barPixels <= 0)
|
||
barPixels = 1;
|
||
baseSpot = SCREENY(wi, PM_DBL("BarBase"));
|
||
line.x1 = line.x2 = Xsegs[1][X_idx - 1].x2 +
|
||
(int) ((PM_DBL("BarOffset") * idx /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (PM_BOOL("StackGraph") && idx != 0)
|
||
line.y1 = Xsegs[0][X_idx - 1].y2;
|
||
else
|
||
line.y1 = baseSpot;
|
||
line.y2 = Xsegs[1][X_idx - 1].y2;
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &line, barPixels, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
}
|
||
|
||
/* Erase segments */
|
||
if ((thisList->numPoints > 0) && (!noLines) && (X_idx > 0)) {
|
||
ptr = Xsegs[1];
|
||
while (X_idx > wi->dev_info.max_segs) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
wi->dev_info.max_segs, ptr,
|
||
lineWidth, L_VAR,
|
||
16, (int)(1));
|
||
/*LINESTYLE(8), (int)(1));*/
|
||
ptr += wi->dev_info.max_segs;
|
||
X_idx -= wi->dev_info.max_segs;
|
||
}
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
X_idx, ptr,
|
||
lineWidth, L_VAR,
|
||
16,(int)(1));
|
||
}
|
||
/* Next subset */
|
||
thisList = thisList->next;
|
||
}
|
||
}
|
||
XFlush (disp);
|
||
}
|
||
|
||
|
||
static void
|
||
DrawData(wi)
|
||
LocalWin *wi;
|
||
|
||
/*
|
||
* This routine draws the data sets themselves using the macros
|
||
* for translating coordinates.
|
||
*/
|
||
{
|
||
double sx1,
|
||
sy1,
|
||
sx2,
|
||
sy2,
|
||
tx = 0,
|
||
ty = 0;
|
||
int idx,
|
||
subindex;
|
||
int code1,
|
||
code2,
|
||
cd,
|
||
mark_inside;
|
||
int X_idx, StoreIDX; /* PW */
|
||
XSegment *ptr;
|
||
PointList *thisList,
|
||
*lastList;
|
||
int markFlag,
|
||
pixelMarks,
|
||
bigPixel,
|
||
colorMark;
|
||
int noLines = PM_BOOL("NoLines");
|
||
int lineWidth = PM_INT("LineWidth");
|
||
/* PW */
|
||
int theDelay;
|
||
|
||
/* PW Suggests we Flush and set first */
|
||
theDelay = PM_INT("DelayValue")*100000;
|
||
XFlush(disp);
|
||
if (PM_BOOL("Animate")) sleep(1);
|
||
set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
|
||
for (idx = 0; idx < MAXSETS; idx++) {
|
||
if (wi->DOrder == 0)
|
||
thisList = PlotData[idx].list;
|
||
else if (wi->DOrder == 1)
|
||
thisList = DataD1[idx].list;
|
||
else if (wi->DOrder == 2)
|
||
thisList = DataD2[idx].list;
|
||
else {
|
||
printf ("Internal Error differentiating - order > 2!\n");
|
||
exit (1);
|
||
}
|
||
while (thisList) {
|
||
X_idx = 0;
|
||
for (subindex = 0; subindex < thisList->numPoints - 1; subindex++) {
|
||
/* Put segment in (sx1,sy1) (sx2,sy2) */
|
||
sx1 = thisList->xvec[subindex];
|
||
sy1 = thisList->yvec[subindex];
|
||
sx2 = thisList->xvec[subindex + 1];
|
||
sy2 = thisList->yvec[subindex + 1];
|
||
/* Now clip to current window boundary */
|
||
C_CODE(sx1, sy1, code1);
|
||
C_CODE(sx2, sy2, code2);
|
||
mark_inside = (code1 == 0);
|
||
while (code1 || code2) {
|
||
if (code1 & code2)
|
||
break;
|
||
cd = (code1 ? code1 : code2);
|
||
if (cd & LEFT_CODE) { /* Crosses left edge */
|
||
ty = sy1 + (sy2 - sy1) * (wi->UsrOrgX - sx1) /
|
||
(sx2 - sx1);
|
||
tx = wi->UsrOrgX;
|
||
}
|
||
else if (cd & RIGHT_CODE) { /* Crosses right edge */
|
||
ty = sy1 + (sy2 - sy1) * (wi->UsrOppX - sx1) /
|
||
(sx2 - sx1);
|
||
tx = wi->UsrOppX;
|
||
}
|
||
else if (cd & BOTTOM_CODE) {/* Crosses bottom edge */
|
||
tx = sx1 + (sx2 - sx1) * (wi->UsrOrgY - sy1) /
|
||
(sy2 - sy1);
|
||
ty = wi->UsrOrgY;
|
||
}
|
||
else if (cd & TOP_CODE) { /* Crosses top edge */
|
||
tx = sx1 + (sx2 - sx1) * (wi->UsrOppY - sy1) /
|
||
(sy2 - sy1);
|
||
ty = wi->UsrOppY;
|
||
}
|
||
if (cd == code1) {
|
||
sx1 = tx;
|
||
sy1 = ty;
|
||
C_CODE(sx1, sy1, code1);
|
||
}
|
||
else {
|
||
sx2 = tx;
|
||
sy2 = ty;
|
||
C_CODE(sx2, sy2, code2);
|
||
}
|
||
}
|
||
if (!code1 && !code2) {
|
||
/* Add segment to list */
|
||
Xsegs[0][X_idx].x1 = Xsegs[1][X_idx].x1;
|
||
Xsegs[0][X_idx].y1 = Xsegs[1][X_idx].y1;
|
||
Xsegs[0][X_idx].x2 = Xsegs[1][X_idx].x2;
|
||
Xsegs[0][X_idx].y2 = Xsegs[1][X_idx].y2;
|
||
Xsegs[1][X_idx].x1 = SCREENX(wi, sx1);
|
||
Xsegs[1][X_idx].y1 = SCREENY(wi, sy1);
|
||
Xsegs[1][X_idx].x2 = SCREENX(wi, sx2);
|
||
Xsegs[1][X_idx].y2 = SCREENY(wi, sy2);
|
||
X_idx++;
|
||
}
|
||
|
||
/* Draw markers if requested and they are in drawing region */
|
||
if (markFlag && mark_inside) {
|
||
if (pixelMarks) {
|
||
if (bigPixel) {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_DOT, 0, idx % MAXATTR);
|
||
}
|
||
else {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_PIXEL, 0, PIXVALUE(idx));
|
||
}
|
||
}
|
||
else {
|
||
/* Distinctive markers */
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x1,
|
||
Xsegs[1][X_idx - 1].y1,
|
||
P_MARK, MARKSTYLE(idx),
|
||
PIXVALUE(idx));
|
||
}
|
||
}
|
||
|
||
/* Draw bar elements if requested */
|
||
if (PM_BOOL("BarGraph")) {
|
||
int barPixels,
|
||
baseSpot;
|
||
XSegment line;
|
||
|
||
barPixels = (int) ((PM_DBL("BarWidth") /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (barPixels <= 0)
|
||
barPixels = 1;
|
||
baseSpot = SCREENY(wi, PM_DBL("BarBase"));
|
||
line.x1 = line.x2 = Xsegs[1][X_idx - 1].x1 +
|
||
(int) ((PM_DBL("BarOffset") * idx /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (PM_BOOL("StackGraph") && idx != 0)
|
||
line.y1 = Xsegs[0][X_idx - 1].y1;
|
||
else
|
||
line.y1 = baseSpot;
|
||
line.y2 = Xsegs[1][X_idx - 1].y1;
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &line, barPixels, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
}
|
||
}
|
||
/* Handle last marker */
|
||
if (markFlag && (thisList->numPoints > 0)) {
|
||
C_CODE(thisList->xvec[thisList->numPoints - 1],
|
||
thisList->yvec[thisList->numPoints - 1],
|
||
mark_inside);
|
||
if (mark_inside == 0) {
|
||
if (pixelMarks) {
|
||
if (bigPixel) {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_DOT, 0, idx % MAXATTR);
|
||
}
|
||
else {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_PIXEL, 0, PIXVALUE(idx));
|
||
}
|
||
}
|
||
else {
|
||
/* Distinctive markers */
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
Xsegs[1][X_idx - 1].x2,
|
||
Xsegs[1][X_idx - 1].y2,
|
||
P_MARK, MARKSTYLE(idx),
|
||
PIXVALUE(idx));
|
||
}
|
||
}
|
||
}
|
||
/* Handle last bar */
|
||
if ((thisList->numPoints > 0) && PM_BOOL("BarGraph")) {
|
||
int barPixels,
|
||
baseSpot;
|
||
XSegment line;
|
||
|
||
barPixels = (int) ((PM_DBL("BarWidth") /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (barPixels <= 0)
|
||
barPixels = 1;
|
||
baseSpot = SCREENY(wi, PM_DBL("BarBase"));
|
||
line.x1 = line.x2 = Xsegs[1][X_idx - 1].x2 +
|
||
(int) ((PM_DBL("BarOffset") * idx /
|
||
wi->XUnitsPerPixel) + 0.5);
|
||
if (PM_BOOL("StackGraph") && idx != 0)
|
||
line.y1 = Xsegs[0][X_idx - 1].y2;
|
||
else
|
||
line.y1 = baseSpot;
|
||
line.y2 = Xsegs[1][X_idx - 1].y2;
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &line, barPixels, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
}
|
||
|
||
/* Draw segments */
|
||
if (!PM_BOOL("Animate")) {
|
||
if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
|
||
ptr = Xsegs[1];
|
||
while (X_idx > wi->dev_info.max_segs) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
wi->dev_info.max_segs, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
ptr += wi->dev_info.max_segs;
|
||
X_idx -= wi->dev_info.max_segs;
|
||
}
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
X_idx, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
}
|
||
} else {
|
||
StoreIDX = X_idx;
|
||
if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
|
||
ptr = Xsegs[1];
|
||
while (X_idx > wi->dev_info.max_segs) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
wi->dev_info.max_segs, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(1), PIXVALUE(2));
|
||
ptr += wi->dev_info.max_segs;
|
||
X_idx -= wi->dev_info.max_segs;
|
||
}
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
X_idx, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(1), PIXVALUE(2));
|
||
}
|
||
XFlush (disp);
|
||
for (X_idx=1;X_idx<theDelay;X_idx++);
|
||
X_idx = StoreIDX;
|
||
if ((thisList->numPoints > 0) && (!noLines) && (X_idx > 0)) {
|
||
ptr = Xsegs[1];
|
||
while (X_idx > wi->dev_info.max_segs) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
wi->dev_info.max_segs, ptr,
|
||
lineWidth, L_VAR,
|
||
16, (int)(1));
|
||
/*LINESTYLE(8), (int)(1));*/
|
||
ptr += wi->dev_info.max_segs;
|
||
X_idx -= wi->dev_info.max_segs;
|
||
}
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
X_idx, ptr,
|
||
lineWidth, L_VAR,
|
||
16,(int)(1));
|
||
}
|
||
}
|
||
/* Next subset */
|
||
lastList = thisList;
|
||
thisList = thisList->next;
|
||
} /* End While */
|
||
}
|
||
if (PM_BOOL("Animate")) {
|
||
X_idx = StoreIDX;
|
||
thisList = lastList;
|
||
if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
|
||
ptr = Xsegs[1];
|
||
while (X_idx > wi->dev_info.max_segs) {
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
wi->dev_info.max_segs, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(1), PIXVALUE(2));
|
||
ptr += wi->dev_info.max_segs;
|
||
X_idx -= wi->dev_info.max_segs;
|
||
}
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
X_idx, ptr,
|
||
lineWidth, L_VAR,
|
||
LINESTYLE(1), PIXVALUE(2));
|
||
}
|
||
}
|
||
XFlush (disp);
|
||
}
|
||
|
||
|
||
|
||
static void
|
||
DrawLegend(wi)
|
||
LocalWin *wi;
|
||
|
||
/*
|
||
* This draws a legend of the data sets displayed. Only those that
|
||
* will fit are drawn.
|
||
*/
|
||
{
|
||
int idx,
|
||
spot,
|
||
lineLen,
|
||
oneLen,
|
||
incr;
|
||
XSegment leg_line;
|
||
int markFlag,
|
||
pixelMarks,
|
||
bigPixel,
|
||
colorMark;
|
||
|
||
set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
|
||
spot = wi->XOrgY;
|
||
lineLen = 0;
|
||
incr = 2 + wi->dev_info.axis_height + wi->dev_info.bdr_pad;
|
||
/* First pass draws the text */
|
||
for (idx = 0; idx < MAXSETS; idx++) {
|
||
if ((PlotData[idx].list) &&
|
||
(spot + wi->dev_info.axis_height + 2 < wi->XOppY)) {
|
||
/* Meets the criteria */
|
||
oneLen = strlen(PlotData[idx].setName);
|
||
if (oneLen > lineLen)
|
||
lineLen = oneLen;
|
||
wi->dev_info.xg_text(wi->dev_info.user_state,
|
||
wi->XOppX + wi->dev_info.bdr_pad,
|
||
spot + 2,
|
||
PlotData[idx].setName,
|
||
T_UPPERLEFT, T_AXIS);
|
||
spot += incr;
|
||
}
|
||
}
|
||
lineLen = lineLen * wi->dev_info.axis_width;
|
||
leg_line.x1 = wi->XOppX + wi->dev_info.bdr_pad;
|
||
leg_line.x2 = leg_line.x1 + lineLen;
|
||
spot = wi->XOrgY;
|
||
/* second pass draws the lines */
|
||
for (idx = 0; idx < MAXSETS; idx++) {
|
||
if ((PlotData[idx].list) &&
|
||
(spot + wi->dev_info.axis_height + 2 < wi->XOppY)) {
|
||
leg_line.y1 = leg_line.y2 = spot - wi->dev_info.legend_pad;
|
||
if (PM_BOOL("BarGraph"))
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &leg_line,
|
||
incr / 4,
|
||
L_VAR, LINESTYLE(idx), PIXVALUE(idx));
|
||
if (!PM_BOOL("NoLines"))
|
||
wi->dev_info.xg_seg(wi->dev_info.user_state,
|
||
1, &leg_line, 1, L_VAR,
|
||
LINESTYLE(idx), PIXVALUE(idx));
|
||
if (markFlag && !pixelMarks) {
|
||
wi->dev_info.xg_dot(wi->dev_info.user_state,
|
||
leg_line.x1, leg_line.y1,
|
||
P_MARK, MARKSTYLE(idx), PIXVALUE(idx));
|
||
|
||
}
|
||
spot += incr;
|
||
}
|
||
}
|
||
}
|
||
static void
|
||
set_mark_flags(markFlag, pixelMarks, bigPixel, colorMark)
|
||
int *markFlag;
|
||
int *pixelMarks;
|
||
int *bigPixel;
|
||
int *colorMark;
|
||
|
||
/*
|
||
* Determines the values of the old boolean flags based on the
|
||
* new values in the parameters database.
|
||
*/
|
||
{
|
||
*markFlag = 0;
|
||
*pixelMarks = 0;
|
||
*colorMark = 0;
|
||
*bigPixel = 0;
|
||
if (PM_BOOL("Markers")) {
|
||
*markFlag = 1;
|
||
*pixelMarks = 0;
|
||
*colorMark = 0;
|
||
}
|
||
if (PM_BOOL("PixelMarkers")) {
|
||
*markFlag = 1;
|
||
*pixelMarks = 1;
|
||
*bigPixel = 0;
|
||
}
|
||
if (PM_BOOL("LargePixels")) {
|
||
*markFlag = 1;
|
||
*pixelMarks = 1;
|
||
*bigPixel = 1;
|
||
}
|
||
if (PM_BOOL("StyleMarkers")) {
|
||
*markFlag = 1;
|
||
*pixelMarks = 0;
|
||
*colorMark = 1;
|
||
}
|
||
}
|
||
|
||
#undef DELAY
|