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