]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/fplot.c
kernel: keep segment locked for data2txt
[plan9front.git] / sys / src / cmd / fplot.c
index 42caa2941f04fa3b75c343f5e59338eec4458a29..9d6dd5301c825d66660e47d04057c41a87e3bcce 100644 (file)
@@ -101,6 +101,10 @@ int nfns;
 Token *opstackbot;
 double xmin = -10, xmax = 10;
 double ymin = -10, ymax = 10;
+Image *color;
+int cflag;
+char *imagedata;
+int picx = 640, picy = 480;
 
 void *
 emalloc(int size)
@@ -317,62 +321,84 @@ calc(Code *c, double x)
 }
 
 double
-convx(Image *i, int x)
+convx(Rectangle *r, int x)
 {
-       return (xmax - xmin) * (x - i->r.min.x) / (i->r.max.x - i->r.min.x) + xmin;
+       return (xmax - xmin) * (x - r->min.x) / (r->max.x - r->min.x) + xmin;
 }
 
 int
-deconvx(Image *i, double dx)
+deconvx(Rectangle *r, double dx)
 {
-       return (dx - xmin) * (i->r.max.x - i->r.min.x) / (xmax - xmin) + i->r.min.x + 0.5;
+       return (dx - xmin) * (r->max.x - r->min.x) / (xmax - xmin) + r->min.x + 0.5;
 }
 
 double
-convy(Image *i, int y)
+convy(Rectangle *r, int y)
 {
-       return (ymax - ymin) * (i->r.max.y - y) / (i->r.max.y - i->r.min.y) + ymin;
+       return (ymax - ymin) * (r->max.y - y) / (r->max.y - r->min.y) + ymin;
 }
 
 int
-deconvy(Image *i, double dy)
+deconvy(Rectangle *r, double dy)
 {
-       return (ymax - dy) * (i->r.max.y - i->r.min.y) / (ymax - ymin) + i->r.min.y + 0.5;
+       return (ymax - dy) * (r->max.y - r->min.y) / (ymax - ymin) + r->min.y + 0.5;
 }
 
 void
-drawinter(Code *co, Image *i, Image *c, double x1, double x2, int n)
+pixel(int x, int y)
+{
+       char *p;
+
+       if(cflag) {
+               if(x >= picx || y >= picy || x < 0 || y < 0)
+                       return;
+               p = imagedata + (picx * y + x) * 3;
+               p[0] = p[1] = p[2] = 0;
+       } else
+               draw(screen, Rect(x, y, x + 1, y + 1), color, nil, ZP);
+}
+
+void
+drawinter(Code *co, Rectangle *r, double x1, double x2, int n)
 {
        double y1, y2;
        int iy1, iy2;
        int ix1, ix2;
 
-       ix1 = deconvx(i, x1);
-       ix2 = deconvx(i, x2);
+       ix1 = deconvx(r, x1);
+       ix2 = deconvx(r, x2);
        iy1 = iy2 = 0;
        y1 = calc(co, x1);
        if(!isNaN(y1)) {
-               iy1 = deconvy(i, y1);
-               draw(i, Rect(ix1, iy1, ix1 + 1, iy1 + 1), c, nil, ZP);
+               iy1 = deconvy(r, y1);
+               pixel(ix1, iy1);
        }
        y2 = calc(co, x2);
        if(!isNaN(y2)) {
-               iy2 = deconvy(i, y2);
-               draw(i, Rect(ix2, iy2, ix2 + 1, iy2 + 1), c, nil, ZP);
-       }
-       if(!isNaN(y1) && !isNaN(y2) && (iy2 < iy1 - 1 || iy2 > iy1 + 1) && n < 10) {
-               drawinter(co, i, c, x1, (x1 + x2) / 2, n + 1);
-               drawinter(co, i, c, (x1 + x2) / 2, x2, n + 1);
+               iy2 = deconvy(r, y2);
+               pixel(ix2, iy2);
        }
+       if(isNaN(y1) || isNaN(y2))
+               return;
+       if(n >= 10)
+               return;
+       if(iy2 >= iy1 - 1 && iy2 <= iy1 + 1)
+               return;
+       if(iy1 > r->max.y && iy2 > r->max.y)
+               return;
+       if(iy1 < r->min.y && iy2 < r->min.y)
+               return;
+       drawinter(co, r, x1, (x1 + x2) / 2, n + 1);
+       drawinter(co, r, (x1 + x2) / 2, x2, n + 1);
 }
 
 void
-drawgraph(Code *co, Image *i, Image *c)
+drawgraph(Code *co, Rectangle *r)
 {
        int x;
        
-       for(x = i->r.min.x; x < i->r.max.x; x++)
-               drawinter(co, i, c, convx(i, x), convx(i, x + 1), 0);
+       for(x = r->min.x; x < r->max.x; x++)
+               drawinter(co, r, convx(r, x), convx(r, x + 1), 0);
 }
 
 void
@@ -380,15 +406,16 @@ drawgraphs(void)
 {
        int i;
        
+       color = display->black;
        for(i = 0; i < nfns; i++)
-               drawgraph(&fns[i], screen, display->black);
+               drawgraph(&fns[i], &screen->r);
        flushimage(display, 1);
 }
 
 void
 usage(void)
 {
-       fprint(2, "usage: fplot function\n");
+       fprint(2, "usage: fplot [-c [-s size]] [-r range] functions ...\n");
        exits("usage");
 }
 
@@ -403,10 +430,10 @@ zoom(void)
        r = egetrect(1, &m);
        if(r.min.x == 0 && r.min.y == 0 && r.max.x == 0 && r.max.y == 0)
                return;
-       xmin_ = convx(screen, r.min.x);
-       xmax_ = convx(screen, r.max.x);
-       ymin_ = convy(screen, r.max.y);
-       ymax_ = convy(screen, r.min.y);
+       xmin_ = convx(&screen->r, r.min.x);
+       xmax_ = convx(&screen->r, r.max.x);
+       ymin_ = convy(&screen->r, r.max.y);
+       ymax_ = convy(&screen->r, r.min.y);
        xmin = xmin_;
        xmax = xmax_;
        ymin = ymin_;
@@ -432,25 +459,74 @@ parsefns(int n, char **s)
        stack = emalloc(sizeof(*stack) * max);
 }
 
+void
+parserange(char *s)
+{
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       xmin = strtod(s, &s);
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       xmax = strtod(s, &s);
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       ymin = strtod(s, &s);
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       ymax = strtod(s, &s);
+}
+
+void
+parsesize(char *s)
+{
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       picx = strtol(s, &s, 0);
+       while(*s && !isdigit(*s)) s++;
+       if(*s == 0) return;
+       picy = strtol(s, &s, 0);
+}
+
 void
 main(int argc, char **argv)
 {
        Event e;
+       Rectangle r;
+       int i;
 
-       if(argc < 2)
+       ARGBEGIN {
+       case 'r': parserange(EARGF(usage())); break;
+       case 's': parsesize(EARGF(usage())); break;
+       case 'c': cflag++; break;
+       default: usage();
+       } ARGEND;
+       if(argc < 1)
                usage();
        setfcr(getfcr() & ~(FPZDIV | FPINVAL));
-       parsefns(argc - 1, argv + 1);
-       if(initdraw(nil, nil, "fplot") < 0)
-               sysfatal("initdraw: %r");
-       einit(Emouse | Ekeyboard);
-       drawgraphs();
-       for(;;) {
-               switch(event(&e)) {
-               case Ekeyboard:
-                       switch(e.kbdc) {
-                       case 'q': exits(nil);
-                       case 'z': zoom();
+       parsefns(argc, argv);
+       if(cflag) {
+               imagedata = emalloc(picx * picy * 3);
+               memset(imagedata, 0xFF, picx * picy * 3);
+               print("%11s %11d %11d %11d %11d ", "r8g8b8", 0, 0, picx, picy);
+               r.min.x = r.min.y = 0;
+               r.max.x = picx;
+               r.max.y = picy;
+               for(i = 0; i < nfns; i++)
+                       drawgraph(&fns[i], &r);
+               if(write(1, imagedata, picx * picy * 3) < picx * picy * 3)
+                       sysfatal("write: %r");
+       } else {
+               if(initdraw(nil, nil, "fplot") < 0)
+                       sysfatal("initdraw: %r");
+               einit(Emouse | Ekeyboard);
+               drawgraphs();
+               for(;;) {
+                       switch(event(&e)) {
+                       case Ekeyboard:
+                               switch(e.kbdc) {
+                               case 'q': exits(nil);
+                               case 'z': zoom();
+                               }
                        }
                }
        }