shithub: riscv

Download patch

ref: e183ea231d2953de2cab74fe80e32e709faa87ff
parent: e140aa0aeef3912d3d173b40603e86e5cf936299
author: aiju <[email protected]>
date: Sun Jul 17 08:53:41 EDT 2011

improved on fplot

--- a/sys/src/cmd/fplot.c
+++ b/sys/src/cmd/fplot.c
@@ -101,6 +101,10 @@
 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 @@
 }
 
 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);
+		iy2 = deconvy(r, y2);
+		pixel(ix2, iy2);
 	}
-	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);
-	}
+	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,8 +406,9 @@
 {
 	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);
 }
 
@@ -388,7 +415,7 @@
 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 @@
 	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_;
@@ -433,24 +460,73 @@
 }
 
 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();
+				}
 			}
 		}
 	}