/* 1610, Mon 10 Jun 96 N_PLOT.C: Nevil's simple plotting package Copyright (C) 1992-2002 by Nevil Brownlee, CAIDA | University of Auckland */ /* * $Log: n_plot.c,v $ * Revision 1.1.1.2.2.7 2002/02/23 01:57:18 nevil * Moving srl examples to examples/ directory. Modified examples/Makefile.in * * Revision 1.1.1.2.2.3 2000/06/06 03:38:09 nevil * Combine NEW_ATR with TCP_ATR, various bug fixes * * Revision 1.1.1.2 1999/10/03 21:06:15 nevil * *** empty log message *** * * Revision 1.1.1.1.2.1 1999/01/08 01:38:28 nevil * Distribution file for 4.3b7 * * Revision 1.1.1.1 1998/11/16 03:57:27 nevil * Import of NeTraMet 4.3b3 * * Revision 1.1.1.1 1998/11/16 03:22:00 nevil * Import of release 4.3b3 * * Revision 1.1.1.1 1998/10/28 20:31:23 nevil * Import of NeTraMet 4.3b1 * * Revision 1.1.3.2 1998/10/18 23:44:05 nevil * Added Nicolai's patches, some 'tidying up' of the source * * Revision 1.1.3.1 1998/10/13 02:48:17 nevil * Import of Nicolai's 4.2.2 * * Revision 1.1.1.1 1998/08/24 12:09:28 nguba * NetraMet 4.2 Original Distribution * * Revision 1.3 1998/05/07 04:28:53 rtfm * Implement NetFlowMet, the Cisco NetFlow RTFM meter */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "n_plot.h" #define noPLT_DEBUG #define noPLT_DEBUG_DRAW static Widget plot_w; static Drawable plot_d; static GC plot_gc; static int sxsize,sysize; static int currsx,currsy, sxmin,sxmax, symin,symax; static float currvx,currvy, vxmin,vxmax, vymin,vymax; static int vsmode = P_LIN_LIN; /* Current transform */ static float xscale,yscale, xoffset,yoffset, xlogf,ylogf; #define P_TIC_LEN 4 static XFontStruct *def_font_info; static int dfchasc,dfchht,dfchwd; static int imin(a,b) { return a < b ? a : b; } static int imax(a,b) { return a > b ? a : b; } #define onscreen(c,cl) imin(imax(0,c),cl-1) static void compute_transform(void) { #ifdef PLT_DEBUG printf("cmp_tfrm(): vsmode=%d, vxmin=%g,vxmax=%g, vymin=%g,vymax=%g\n", vsmode, vxmin,vxmax, vymin,vymax); printf(" sxmin=%d,sxmax=%d, symin=%d,symax=%d\n", sxmin,sxmax, symin,symax); #endif if (vsmode == P_LOG_LIN || vsmode == P_LOG_LOG) { if (vxmin < 0 || vxmax < 0) { printf("negative extrema for LOG x axis!\n"); exit(1); } } if (vsmode == P_LIN_LOG || vsmode == P_LOG_LOG) { if (vymin < 0 || vymax < 0) { printf("negative extrema for LOG y axis!\n"); exit(1); } } switch (vsmode) { case P_LIN_LIN: xscale = vxmin == vxmax ? 0 : (sxmax-sxmin)/(vxmax-vxmin); xoffset = sxmin - xscale*vxmin; yscale = vymin == vymax ? 0 : (symax-symin)/(vymax-vymin); yoffset = symin - yscale*vymin; break; case P_LOG_LIN: if (vxmin == 0) { vxmax = 0; vxmin = 1; } xlogf = (sxmax-sxmin)/log10(vxmax/vxmin); yscale = vymin == vymax ? 0 : (symax-symin)/(vymax-vymin); yoffset = symin - yscale*vymin; break; case P_LIN_LOG: xscale = vxmin == vxmax ? 0 : (sxmax-sxmin)/(vxmax-vxmin); xoffset = sxmin - xscale*vxmin; if (vymin == 0) { vymax = 0; vymin = 1; } ylogf = (symax-symin)/log10(vymax/vymin); break; case P_LOG_LOG: if (vxmin == 0) { vxmax = 0; vxmin = 1; } xlogf = (sxmax-sxmin)/log10(vxmax/vxmin); if (vymin == 0) { vymax = 0; vymin = 1; } ylogf = (symax-symin)/log10(vymax/vymin); break; } #ifdef PLT_DEBUG printf(" xscale=%g,xoff=%g, yscale=%g,yoff=%g, xlogf=%g,ylogf=%g\n", xscale,xoffset, yscale,yoffset, xlogf,ylogf); #endif } void settrn(int t) { vsmode = t; compute_transform(); } void swindo(int minx,int lenx, int miny,int leny) { sxmin = onscreen(minx,sxsize); sxmax = onscreen(minx+lenx-1,sxsize); symin = onscreen(miny,sysize); symax = onscreen(miny+leny-1,sysize); compute_transform(); } void dwindo(float minx,float maxx, float miny,float maxy) { vxmin = minx; vxmax = maxx; vymin = miny; vymax = maxy; compute_transform(); } void plot_window(Widget pw, GC pgc) { Dimension w_width,w_height; plot_w = pw; plot_gc = pgc; def_font_info = XQueryFont(XtDisplay(plot_w), XGContextFromGC(plot_gc)); dfchasc = def_font_info->ascent; dfchht = def_font_info->ascent+def_font_info->descent; dfchwd = astwdt("0",1); XtVaGetValues(pw, /* Get window size */ XmNwidth,&w_width, XmNheight,&w_height, NULL); sxsize = w_width; sysize = w_height; #ifdef PLT_DEBUG printf("plt_window(): sxsize=%d, sysize=%d\n", sxsize,sysize); #endif } void plot_device(Drawable d) { plot_d = d; } void vtostransform(int *ix,int *iy, float x,float y) { switch (vsmode) { case P_LIN_LIN: *ix = x*xscale + xoffset; *iy = y*yscale + yoffset; break; case P_LOG_LIN: *ix = sxmin + log10(x/vxmin)*xlogf; *iy = y*yscale + yoffset; break; case P_LIN_LOG: *ix = x*xscale + xoffset; *iy = symin + log10(y/vymin)*ylogf; break; case P_LOG_LOG: *ix = sxmin + log10(x/vxmin)*xlogf; *iy = symin + log10(y/vymin)*ylogf; break; } } static void vecplot(int code, int x,int y) { #ifdef PLT_DEBUG_DRAW printf("vecplot(%s): %d,%d\n", code == P_DRAW ? "draw" : "move", x,y); #endif if (code == P_DRAW) { XDrawLine(XtDisplay(plot_w), plot_d, plot_gc, currsx,sysize-currsy, x,sysize-y); } currsx = x; currsy = y; } void movabs(int x,int y) { vecplot(P_MOVE,x,y); } void drwabs(int x,int y) { vecplot(P_DRAW,x,y); } void movrel(int x,int y) { vecplot(P_MOVE,currsx+x,currsy+y); } void drwrel(int x,int y) { vecplot(P_DRAW,currsx+x,currsy+y); } void pltsym(int sym) { int sx = currsx, sy = currsy; char c; switch (sym) { case P_DOT: movrel(-1,-1); drwrel(2,0); drwrel(0,2); drwrel(-2,0); drwrel(0,-2); break; case P_DIAMOND: movrel(-2,0); drwrel(2,2); drwrel(2,-2); drwrel(-2,-2); drwrel(-2,2); break; case P_PLUS: movrel(-2,-0); drwrel(4,0); movrel(-2,2); drwrel(0,-4); break; case P_SQUARE: movrel(-2,-2); drwrel(4,0); drwrel(0,4); drwrel(-4,0); drwrel(0,-4); break; default: movrel(-dfchwd/2,-dfchasc/2); c = sym; aoutst(&c,1); break; } movabs(sx,sy); } #define updatevcursor(x,y) { currvx = x; currvy = y; } static void virtualplot(int code, float x,float y) { int ix,iy; vtostransform(&ix,&iy, x,y); vecplot(code, ix,iy); updatevcursor(x,y); #ifdef PLT_DEBUG_DRAW printf("vx,vy = %g,%g, ix,iy = %d,%d\n", x,y, ix,iy); #endif } void movea(float x,float y) { virtualplot(P_MOVE, x,y); } void drawa(float x,float y) { virtualplot(P_DRAW, x,y); } int astwdt(char *a, int n) { return XTextWidth(def_font_info, a,n); } void aoutst(char *a, int n) { int lw; if (n > 0) { /* Draw to right */ lw = astwdt(a,n); XDrawString(XtDisplay(plot_w), plot_d, plot_gc, currsx,sysize-currsy, a,n); } else { /* Draw to left */ lw = astwdt(a,-n); movabs(currsx-lw,currsy); XDrawString(XtDisplay(plot_w), plot_d, plot_gc, currsx,sysize-currsy, a,-n); } currsx += lw; } static void drawxtic(float x,float ypos, int ytics,int yticf,int ynbr) { char label[20]; int len, lw; movea(x,ypos); movabs(currsx,currsy+ytics); drwabs(currsx,currsy+yticf); sprintf(label,"%g", x); len = strlen(label); lw = astwdt(label,len); movabs(currsx-lw/2, currsy+ynbr); aoutst(label,len); } void xaxis(float xpos,float ypos, float xint) { int hticl, ytics,yticf,ynbr,ytitl; float x; hticl = P_TIC_LEN/2; movea(xpos,ypos); if ((currsy-symin) < (symax-currsy)) { /* Low */ ytics = hticl; yticf = -P_TIC_LEN; ynbr = -(hticl+dfchasc); ytitl = -(hticl+dfchasc); } else { /* High */ ytics = -hticl; yticf = P_TIC_LEN; ynbr = hticl; ytitl = hticl+dfchasc; } /* printf("xaxis(): ypos=%g, ytics=%d, yticf=%d, ynbr=%d, ytitl=%d\n", ypos, ytics,yticf,ynbr,ytitl); */ movea(vxmax,ypos); drawa(vxmin,ypos); for (x = xpos; ; ) { if (vsmode == P_LIN_LIN || vsmode == P_LIN_LOG) x = x-xint; else x = x/xint; if (x <= vxmin) break; drawxtic(x,ypos, ytics,yticf,ynbr); } for (x = xpos; ; ) { if (vsmode == P_LIN_LIN || vsmode == P_LIN_LOG) x = x+xint; else x = x*xint; if (x >= vxmax) break; drawxtic(x,ypos, ytics,yticf,ynbr); } movabs(currsx,currsy+ytitl); } static int drawytic(float xpos,float y, int xtics,int xticf,int xnbr,int mside) { char label[20]; int len, lw, xtitl; movea(xpos,y); movabs(currsx+xtics,currsy); drwabs(currsx+xticf,currsy); sprintf(label,"%g", y); len = strlen(label); lw = astwdt(label,len); movabs(xtitl = currsx+xnbr, currsy-dfchasc/2); aoutst(label,len*mside); return xtitl; } void yaxis(float xpos,float ypos, float yint) { int hticl, xtics,xticf,xnbr,mside, xtitl,ytitl; float y; hticl = P_TIC_LEN/2; movea(xpos,ypos); if ((currsx-sxmin) < (sxmax-currsx)) { /* Left */ xtics = hticl; xticf = -P_TIC_LEN; xnbr = -hticl; mside = -1; } else { /* Right */ xtics = -hticl; xticf = P_TIC_LEN; xnbr = hticl; mside = 1; } /* printf("yaxis(): xpos=%g, xtics=%d, xticf=%d, xnbr=%d, mside=%d\n", xpos, xtics,xticf,xnbr,mside); */ movea(xpos,vymax); drawa(xpos,vymin); for (y = ypos; ; ) { if (vsmode == P_LIN_LIN || vsmode == P_LOG_LIN) y = y-yint; else y = y/yint; if (y <= vymin) break; xtitl = drawytic(xpos,y, xtics,xticf,xnbr,mside); } for (y = ypos; ; ) { if (vsmode == P_LIN_LIN || vsmode == P_LOG_LIN) y = y+yint; else y = y*yint; if (y >= vymax) break; xtitl = drawytic(xpos,y, xtics,xticf,xnbr,mside); } ytitl = dfchht+hticl; if (symin > symax) y = -y; movabs(xtitl,currsy+ytitl); }