braner@batcomputer.TN.CORNELL.EDU (braner) (09/25/86)
[]
For a long time I wanted to create a very simple, easy-to-use system
for plotting functions, data, etc from a C program. I am thinking of
scientific/engineering applications, where quick, one-shot plots are
wanted, not fancy, perfect, art pieces.
Well, I did it after all - it wasn't as hard as I thought, since I have
already done it before in Applesoft BASIC. Happy plotting!
- Moshe Braner
---------- cut here ----------------
/*
* Simple VDI Interface for X-Y Plotting
*
* by Moshe Braner, 860924
*
* #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 xlog, ylog, curx, cury, curvalid;
static int plothand=0;
static double p, q, r, s;
/*
* Subroutine to set up graphics
*
* 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 of origion
* xmode, ymode = 0 for linear, 1 for log-scale
*/
initplot(xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg,xmode,ymode)
double xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg;
int xmode, ymode;
{
int i, pxy[4];
double w;
puts("\033E"); /* clear screen */
puts("\033f"); /* cursor invisible */
/* initialize VDI */
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 );
vsf_color(plothand, 1); /* black */
vswr_mode(plothand, 1); /* "Replace" mode */
/* initialize our params */
xlog = xmode;
ylog = ymode;
if (xlog) {
xmin = log(xmin);
xmax = log(xmax);
xtik = log(xtik);
xorg = log(xorg);
}
if (ylog) {
ymin = log(ymin);
ymax = log(ymax);
ytik = log(ytik);
yorg = log(yorg);
}
r = 599.0/(xmax-xmin);
s = 399.0/(ymax-ymin);
p = xmin;
q = ymin;
/* draw X-axis */
pxy[0] = (int)(r * (xmin-p)) + 40;
pxy[1] = (int)(s * (q-yorg)) + 399;
pxy[2] = (int)(r * (xmax-p)) + 40;
pxy[3] = pxy[1];
v_pline(plothand, 2, pxy);
w = xorg;
while (w >= xmin) w -= xtik;
pxy[1] = (int)(s * (q-yorg)) + 395;
pxy[3] = pxy[1] + 3;
while ((w+=xtik) <= xmax) {
pxy[0] = (int)(r * (w-p)) + 40;
pxy[2] = pxy[0];
v_pline(plothand, 2, pxy);
}
/* draw y-axis */
pxy[0] = (int)(r * (xorg-p)) + 40;
pxy[1] = (int)(s * (q-ymin)) + 399;
pxy[2] = pxy[0];
pxy[3] = (int)(s * (q-ymax)) + 399;
v_pline(plothand, 2, pxy);
w = yorg;
while (w >= ymin) w -= ytik;
pxy[0] = (int)(r * (xorg-p)) + 41;
pxy[2] = pxy[0] + 3;
while ((w+=ytik) <= ymax) {
pxy[1] = (int)(s * (q-w)) + 399;
pxy[3] = pxy[1];
v_pline(plothand, 2, pxy);
}
curvalid = 0;
}
/*
* Subroutine to plot a point
*
* (First call initplot() for setup.)
*
* Plots with the pen up if z==0, else pen down.
* Uses the preset p, q, r, s, xlog, ylog 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() before plot()!");
exit(0);
}
if (xlog) x = log(x);
if (ylog) y = log(y);
xi = (int)(r * (x-p)) + 40;
yi = (int)(s * (q-y)) + 399;
if (xi<0 || xi>639) {
/* puts("plot(): x out of range!"); */
return;
}
if (yi<0 || yi>399) {
/* puts("plot(): y out of range!"); */
return;
}
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);
}
/*
* clean up when you're done, or else you'll get cherry bombs!
*/
cleanplot()
{
v_clsvwk(plothand);
plothand = 0;
}
------------- example program ------------------
#include <stdio.h>
#include <math.h>
#include "plotxyz.c"
main()
{
double x,y,xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg;
xmin = -2.0;
xmax = 6.0;
ymin = -1.3;
ymax = 1.3;
xtik = 1.0;
ytik = 0.25;
xorg = 0.0;
yorg = 0.0;
initplot(xmin,xmax,xtik,ymin,ymax,ytik,xorg,yorg,0,0);
for (x=xmin; x<xmax; x+=0.05) {
y = sin(x);
plot(x,y,1);
}
cleanplot();
getchar();
}