#include #include #include #include #include #define MAXVARS 7 // test cmd awk 'BEGIN{for(x=0;x<100;x++) { print x " " 100*rand() " " 100*(rand()*rand()) }}' | 8.out -t 'awk rand() distribution' -s 0 -e 100 -m 120 -v x,'rand()','rand()^2' | topng > sample.png /* colors */ enum { Peach, Aqua, Green, Blue, Grey, Pink, Yellow, White, Black, }; struct Color { Memimage *bg; Memimage *fg; Memimage *hl; }; typedef struct Color Color; /* figures */ typedef struct fpoint { double x, y; } fpoint; typedef struct frectangle { fpoint min, max; } frectangle; typedef struct polygon { Point *p; /* a malloc'ed array */ int n; /* p[] has n elements: p[0..n] */ } polygon; /* input values */ struct Var { char *s; int c; double max; double min; double mean; double sum; polygon fig; }; typedef struct Var Var; Var *V; int Nvars; Color Pallete[8]; /* utils */ void* emalloc(ulong sz) { void *v; if((v = malloc(sz)) == nil) { fprint(2, "out of memory allocating %lud\n", sz); exits("mem"); } memset(v, 0, sz); setmalloctag(v, getcallerpc(&sz)); return v; } void* erealloc(void *v, ulong sz) { void *nv; if((nv = realloc(v, sz)) == nil) { fprint(2, "out of memory allocating %lud\n", sz); exits("mem"); } if(v == nil) setmalloctag(nv, getcallerpc(&v)); setrealloctag(nv, getcallerpc(&v)); return nv; } void mkcol(int i, int c0, int c1, int c2, Rectangle clipr) { Pallete[i].bg = allocmemimage(Rect(0,0,1,1),RGB24); memfillcolor(Pallete[i].bg,c0); Pallete[i].bg->flags=Frepl; Pallete[i].bg->clipr = clipr; Pallete[i].fg = allocmemimage(Rect(0,0,1,1),RGB24); memfillcolor(Pallete[i].fg,c1);Pallete[i].fg->flags=Frepl; Pallete[i].fg->clipr = clipr; Pallete[i].hl = allocmemimage(Rect(0,0,1,1),RGB24); memfillcolor(Pallete[i].hl,c2);Pallete[i].hl->flags=Frepl; Pallete[i].hl->clipr = clipr; } void colinit(Rectangle clipr) { mkcol(Peach, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF,clipr); mkcol(Aqua, DPalebluegreen, DPalegreygreen, DPurpleblue,clipr); mkcol(Yellow, DPaleyellow, DDarkyellow, DYellowgreen,clipr); mkcol(Green, DPalegreen, DMedgreen, DDarkgreen,clipr); mkcol(Blue, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF,clipr); mkcol(Grey,0xEEEEEEFF,0xCCCCCCFF,0x888888FF,clipr); mkcol(Pink,0xffaaaaFF, 0x990099FF, 0xffaa00FF,clipr); mkcol(White,0xffffffff,0xffffffff,0xffffffff,clipr); mkcol(Black,0,0,0,clipr); } Rectangle frtor(frectangle fr) { Rectangle r; r.max.x = (int) fr.max.x; r.max.y = (int) fr.max.y; r.min.x = (int) fr.min.x; r.min.y = (int) fr.min.y; return r; } Point fptop(fpoint fp) { Point p; p.x = (int)fp.x; p.y = (int)fp.y; return p; } fpoint fPt(double x, double y) { fpoint p; p.x = x; p.y = y; return p; } frectangle fRect(double x, double y, double bx, double by) { frectangle r; r.min.x = x; r.min.y = y; r.max.x = bx; r.max.y = by; return r; } fpoint transform(frectangle dr, frectangle s, fpoint sp) { fpoint dp; ( sp.x > s.max.x ) ? sp.x = s.max.x-1 : 1; ( sp.x <= s.min.x ) ? sp.x=s.min.x+1 : 1; (sp.y > s.max.y) ? sp.y=s.max.y-1 : 1; (sp.y <= s.min.y) ? sp.y=s.min.y+1 : 1; if ( sp.x == 0 ) dp.x = dr.min.x; else { dp.x =(dr.max.x-dr.min.x)/((s.max.x-s.min.x)/(sp.x-s.min.x)); dp.x += dr.min.x; } if (sp.y == 0 ) dp.y = dr.min.y; else { dp.y = (dr.max.y-dr.min.y)/((s.max.y-s.min.y)/(sp.y-s.min.y)); dp.y += dr.min.y; } // adjust the y coords dp.y = (dr.max.y - dp.y)+dr.min.y; return dp; } void addptvar(int i, fpoint p) { if( V[i].fig.p == nil ) { V[i].fig.p = emalloc(sizeof(Point)); V[i].fig.p[0] = fptop(p); V[i].fig.n = 0; } else { V[i].fig.p = erealloc(V[i].fig.p,sizeof(Point)*(V[i].fig.n+1)); V[i].fig.p[V[i].fig.n] = fptop(p); V[i].fig.n++; } } void endpolys(fpoint end){ for(int i=1;i=1 ) { addptvar(i,fPt(V[i].fig.p[V[i].fig.n-1].x, end.y)); addptvar(i,fPt(V[i].fig.p[0].x, end.y)); } } } void getvals(frectangle dst, double start, double end, double maxval) { Biobuf bin; char *line; double xval,yval; char *vals[MAXVARS]; fpoint p; frectangle src; int i,n, nvals; src=fRect(start,0,end,maxval); Binit(&bin,0,OREAD); nvals = 1; while((line=Brdstr(&bin, '\n', 1)) != nil){ n =getfields(line, vals, Nvars, 1, " "); if ( n != Nvars ) sysfatal("getvals(): error getting values"); xval=strtod(vals[0],0); for(i=1;i V[i].max ) V[i].max = yval; else if ( yval < V[i].min ) V[i].min = yval; V[i].sum += yval; V[i].mean = V[i].sum / nvals; } free(line); line = nil; nvals++; } Bterm(&bin); endpolys(dst.max); } void drawvalue(Memimage *dst,polygon *pol, int color, int fill) { if (fill) memfillpoly(dst, pol->p, pol->n, 0,Pallete[color].fg, pol->p[0], SoverD); mempoly(dst,pol->p,pol->n,Endsquare,Endsquare,0,Pallete[color].hl,pol->p[0],SoverD); } /* draw functions */ void drawbox(Memimage *dst, frectangle box,int color, int fill) { int radius; Point rect[5]; Drawop dop; dop = SoverD; radius=0; rect[0] = fptop(box.min); rect[1].x = box.max.x; rect[1].y = box.min.y; rect[2] = fptop(box.max); rect[3].x = box.min.x; rect[3].y = box.max.y; rect[4] = fptop(box.min); if (fill) memfillpoly(dst, rect, 5, 1,Pallete[color].fg, ZP, dop); else mempoly(dst,rect,5,Endsquare,Endsquare,radius,Pallete[color].fg,ZP,dop); } void drawtext(Memimage *dst,Point p, int color,int size,char *s) { Memsubfont *f; char *font; font=smprint("/lib/font/bit/lucida/latin1.%d.0",size); f = openmemsubfont(font); if ( f == nil ) sysfatal("cannot open font: %r\n"); memimagestring(dst, p, Pallete[color].fg, ZP, f, s); freememsubfont(f); } void drawresume(Memimage *dst,frectangle coord) { char *str; frectangle c; c = fRect(coord.min.x+2,coord.min.y+2,coord.min.x+10,coord.min.y+10); for(int i=1;i=0;i--) { p0x=Pt(stats.min.x+i*stepx,stats.min.y); p1x=Pt(stats.min.x+i*stepx,grid.max.y-10); p0y=Pt(grid.min.x+15,(stats.max.y-i*stepy)); p1y=Pt(grid.max.x,(stats.max.y-i*stepy)); memimageline(dst,p0x,p1x,0,0,0,Pallete[Grey].hl,ZP,SoverD); memimageline(dst,p0y,p1y,0,0,0,Pallete[Grey].hl,ZP,SoverD); xval = i*vstepx+xmin; if ( istime) { hms = xval % 86400L; if(hms < 0) hms += 86400L; d1 = hms / 60; min = d1 % 60; d1 /= 60; hour = d1; str = smprint("%0.2d:%0.2d",hour,min); } else str=smprint("%3.0G",xval); drawtext(dst,Pt(p1x.x-10,p1x.y+5),Black,6,str); free(str); str=smprint("%G",(ymax*i)/10); drawtext(dst,Pt(p0y.x-25,p0y.y-5),Black,6,str);free(str); } drawtext(dst,Pt(stats.min.x-25,grid.max.y-7), Black,8,V[0].s); } void usage(char *s) { fprint(2,"%s [-T] -t title -s start -e end -m maxval -v var1,var2,var3. . .\n",s); exits("usage"); } void main(int argc, char *argv[]) { frectangle r,stats,grid,legend,resume,total,title; Memimage *m; char *varlist, *tstr; char *varnames[MAXVARS]; int maxval,start,end,i; int istime=0; if (argc < 8 ) usage(argv[0]); ARGBEGIN { case 's': start=strtod(ARGF(),0); break; case 'e': end=strtod(ARGF(),0); break; case 'm': maxval=strtod(ARGF(),0); break; case 'v': varlist=ARGF(); break; case 't': tstr=ARGF(); break; case 'T': istime=1; break; default: fprint(2,"unknown flag ('%c')",ARGC()); exits("error in flags"); } ARGEND if ( argc != 0 || tstr == nil ) usage(argv[0]); memimageinit(); Nvars = getfields(varlist, varnames, MAXVARS, 1, ","); if ( Nvars == 0 || Nvars > MAXVARS) sysfatal("Incorrect var number check -v option (%d)\n",Nvars); V = emalloc(sizeof(Var)*Nvars); for(i=0;iclipr = m->r; colinit(m->clipr); grid = fRect(r.min.x+20,r.min.y+30,r.max.x-20,r.max.y-80); stats= fRect(grid.min.x+20,grid.min.y,grid.max.x,grid.max.y-20); resume = fRect(grid.min.x,grid.max.y+15,grid.max.x,r.max.y-2); title = fRect(grid.min.x,r.min.y+2,grid.max.x,stats.min.y-2); getvals(stats, start, end, maxval); // draw the data!! memfillcolor(m,DWhite); drawbox(m,stats,White,1); drawgrid(m,grid,stats,start,end,maxval, istime); for(i=1;i