braner@batcomputer.TN.CORNELL.EDU (braner) (09/30/86)
[]
Here is an improved version of my X-Y plotting program.
Note that I took the log-scale stuff out. That's because I didn't
like having to link to the math lib all the time. Instead, take logs
before you call plot().
I added a settable plotting area with VDI clipping, and also a cooked
call to v_pmarker. You are still limited to one plot at a time as long
as you use this simple approach.
Personally, I am AMAZED how fast this thing runs!
- Moshe Braner
---------------- cut here ------------------------
/*
* Simple VDI Interface for X-Y Plotting - version 2.
*
* by Moshe Braner, 860929
*
* #include "plotxyz.c" (this file) in your program.
*
*/
/* globally define arrays to be used by VDI: */
int contrl[12], intin[128], ptsin[128], intout[128], ptsout[128];
/* our own globals */
static int work_in[11], work_out[57];
static int plothand=0;
static int xl, xr, yt, yb;
static int curx, cury, curvalid;
static double p, q, r, s;
/*
* Subroutine to set up the VDI workstation.
* You have to call this first!
* You have to call cleanplot() before you call this again!
*
* The parameters define the clipping area, in screen coords.
* Suggested values (monochrome): 40,639,0,399.
*/
initplot(xmin, xmax, ymin, ymax)
int xmin, xmax, ymin, ymax;
{
int i, pxy[4];
/* initialize VDI */
if (plothand != 0) {
puts("initplot(): Recall - cleanplot() first!");
exit(0);
}
for(i=0; i<10; i++) /* init workstation params */
work_in[i]=1;
work_in[10]= 2; /* use raster coords */
v_opnvwk( work_in, &plothand, work_out );
vswr_mode(plothand, 1); /* "Replace" mode */
vsf_color(plothand, 1); /* black */
/* set up clipping boundaries */
pxy[0] = xmin;
pxy[1] = ymin;
pxy[2] = xmax;
pxy[3] = ymax;
vs_clip(plothand, 1, pxy);
/* store the boundaries in our globals */
xl = xmin;
xr = xmax;
yt = ymin;
yb = ymax;
}
/*
* Subroutine to translate from user coords to screen coords.
*/
coords(x, y, pix, piy)
double x, y;
int *pix, *piy;
{
*pix = (int)(r * (x-p)) + xl;
*piy = (int)(s * (q-y)) + yb;
}
/*
* Subroutine to set up axes and rescaling.
* You may call this repeatedly.
* The whole screen is cleared, and also the (text) cursor.
*
* Parameters:
*
* xmin = lowest X-value
* xmax = highest X-value
* xtik = tick interval for X (ratio if log)
* ymin = lowest Y-value
* ymax = highest Y-value
* ytik = tick interval for Y (ratio if log)
* xorg, yorg = position where axes cross
* mode - if 0 then just remember scaling, alse draw the axes.
*/
axes(xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg,mode)
double xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg;
int mode;
{
int i, pxy[4];
double w;
if (plothand == 0) {
puts("Must call initplot() before axes()!");
exit(0);
}
r = ((double)(xr-xl))/(xmax-xmin);
s = ((double)(yb-yt))/(ymax-ymin);
p = xmin;
q = ymin;
puts("\033E"); /* clear screen */
puts("\033f"); /* cursor invisible */
curvalid = 0;
if (mode == 0)
return;
/* draw X-axis */
coords(xmin, yorg, &pxy[0], &pxy[1]);
coords(xmax, yorg, &pxy[2], &pxy[3]);
v_pline(plothand, 2, pxy);
w = xorg;
while (w >= xmin)
w -= xtik;
while ((w+=xtik) <= xmax) {
coords(w, yorg, &pxy[2], &pxy[3]);
pxy[0] = pxy[2];
pxy[1] = pxy[3] - 4;
v_pline(plothand, 2, pxy);
}
/* draw y-axis */
coords(xorg, ymax, &pxy[0], &pxy[1]);
coords(xorg, ymin, &pxy[2], &pxy[3]);
v_pline(plothand, 2, pxy);
w = yorg;
while (w >= ymin)
w -= ytik;
while ((w+=ytik) <= ymax) {
coords(xorg, w, &pxy[0], &pxy[1]);
pxy[2] = pxy[0] + 4;
pxy[3] = pxy[1];
v_pline(plothand, 2, pxy);
}
}
/*
* Subroutine to plot a point
*
* (First call initplot() and axes().)
*
* Plots with the pen up if z==0, else pen down.
* Uses the preset p, q, r, s, for rescaling.
* Uses the remembered curx, cury if pen down.
*/
plot(x, y, z)
double x, y;
int z;
{
int xi, yi, pxy[4];
if (plothand == 0) {
puts("Must call initplot() and axes() before plot()!");
exit(0);
}
coords(x, y, &xi, &yi);
if (z && curvalid) {
pxy[0] = curx;
pxy[1] = cury;
} else {
pxy[0] = xi;
pxy[1] = yi;
}
curx = xi;
cury = yi;
curvalid = 1;
pxy[2] = xi;
pxy[3] = yi;
v_pline(plothand, 2, pxy);
}
/*
* Subroutine to draw a marker.
*
* (First call initplot() and axes().)
*
* Last argument is the marker type, a char: ./+/X/#/^/*
*/
mark(x, y, type)
double x, y;
int type;
{
static int types[] = {' ', '.', '+', '*', '#', 'X', '^'};
int i, xi, yi, pxy[2];
if (plothand == 0) {
puts("Must call initplot() and axes() before mark()!");
exit(0);
}
for (i=1; i<7; i++)
if (type == types[i])
break;
vsm_type(plothand, i);
coords(x, y, &pxy[0], &pxy[1]);
v_pmarker(plothand, 1, pxy);
}
/*
* clean up when you're done, or else you'll get cherry bombs!
*/
cleanplot()
{
v_clsvwk(plothand);
plothand = 0;
}