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(); }