shithub: etoys

Download patch

ref: a946b00aa91ed059a1e9aad367bb6e872dcd1c1a
author: rodri <rgl@antares-labs.eu>
date: Mon May 11 05:59:39 EDT 2020

new toy: triangles

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin/etoys
+TARG=\
+	triangles\
+
+</sys/src/cmd/mkmany
--- /dev/null
+++ b/triangles.c
@@ -1,0 +1,236 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+typedef struct Point2 Point2;
+typedef struct Triangle Triangle;
+typedef struct Circle Circle;
+typedef struct Object Object;
+
+struct Point2
+{
+	double x, y, w;
+};
+
+struct Triangle
+{
+	Point2 p0, p1, p2;
+};
+
+struct Circle
+{
+	Point2 c;
+	double r;
+};
+
+struct Object
+{
+	Triangle t;
+	Circle c;
+};
+
+enum {
+	Cbg,
+	Ctri,
+	Ccir,
+	NCOLOR
+};
+
+Image *pal[NCOLOR];
+Object *tris;
+ulong ntri;
+Point2 pts[3];
+int npt;
+
+Point2
+Pt2(double x, double y, double w)
+{
+	return (Point2){x,y,w};
+}
+
+Point2
+addpt2(Point2 p, Point2 q)
+{
+	return (Point2){p.x+q.x,p.y+q.y,p.w+q.w};
+}
+
+Point2
+subpt2(Point2 p, Point2 q)
+{
+	return (Point2){p.x-q.x,p.y-q.y,p.w-q.w};
+}
+
+Point2
+mulpt2(Point2 p, double s)
+{
+	return (Point2){p.x*s,p.y*s,p.w*s};
+}
+
+Point2
+divpt2(Point2 p, double s)
+{
+	return (Point2){p.x/s,p.y/s,p.w/s};
+}
+
+double
+veclen(Point2 p)
+{
+	return sqrt(p.x*p.x + p.y*p.y);
+};
+
+Point2
+crossvec(Point2 p, Point2 q)
+{
+	return (Point2){
+		p.y*q.w - p.w*q.y,
+		p.w*q.x - p.x*q.w,
+		p.x*q.y - p.y*q.x
+	};
+}
+
+void
+addobj(Triangle t, Circle c)
+{
+	tris = realloc(tris, ++ntri*sizeof(Object));
+	tris[ntri-1].t = t;
+	tris[ntri-1].c = c;
+}
+
+double
+triperi(Triangle t)
+{
+	return veclen(subpt2(t.p0, t.p1))
+		+ veclen(subpt2(t.p1, t.p2))
+		+ veclen(subpt2(t.p2, t.p0));
+};
+
+double
+triarea(Triangle t)
+{
+	Point2 p;
+	double r;
+
+	p = crossvec(t.p0, t.p1);
+	p = addpt2(p, crossvec(t.p1, t.p2));
+	p = addpt2(p, crossvec(t.p2, t.p0));
+	r = sqrt(p.x*p.x + p.y*p.y + p.w*p.w);
+	return r/2;
+}
+
+Point
+toscreen(Point2 p)
+{
+	return addpt(screen->r.min, Pt(p.x,p.y));
+}
+
+Point2
+fromscreen(Point p)
+{
+	p = subpt(p, screen->r.min);
+	return (Point2){p.x,p.y,0};
+}
+
+void
+triangle(Triangle t)
+{
+	Point p[4];
+
+	p[0] = toscreen(t.p0);
+	p[1] = toscreen(t.p1);
+	p[2] = toscreen(t.p2);
+	p[3] = p[0];
+	poly(screen, p, nelem(p), Endsquare, Endsquare, 0, pal[Ctri], ZP);
+}
+
+void
+circle(Circle c)
+{
+	ellipse(screen, toscreen(c.c), c.r, c.r, 0, pal[Ccir], ZP);
+}
+
+void
+initpalette(void)
+{
+	pal[Cbg] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000ff);
+	pal[Ctri] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x00ff00ff);
+	pal[Ccir] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xff0000ff);
+}
+
+void
+redraw(void)
+{
+	int i;
+
+	draw(screen, screen->r, pal[Cbg], nil, ZP);
+	for(i = 0; i < ntri; i++){
+		triangle(tris[i].t);
+		circle(tris[i].c);
+	}
+	for(i = 0; i < npt; i++)
+		fillellipse(screen, toscreen(pts[i]), 2, 2, pal[Ctri], ZP);
+	flushimage(display, 1);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s\n", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+	Event e;
+	Triangle t;
+	Circle c;
+
+	ARGBEGIN{
+	default: usage();
+	}ARGEND;
+	if(argc > 0)
+		usage();
+	if(initdraw(nil, nil, nil) < 0)
+		sysfatal("initdraw: %r");
+	initpalette();
+	einit(Emouse|Ekeyboard);
+	redraw();
+	for(;;)
+		switch(event(&e)){
+		case Emouse:
+			if((e.mouse.buttons&1) != 0){
+				pts[npt++] = fromscreen(e.mouse.xy);
+				if(npt >= nelem(pts)){
+					t.p0 = pts[0];
+					t.p1 = pts[1];
+					t.p2 = pts[2];
+					c.c = divpt2(addpt2(addpt2(mulpt2(t.p0, veclen(subpt2(t.p1, t.p2))),
+						mulpt2(t.p1, veclen(subpt2(t.p2, t.p0)))),
+						mulpt2(t.p2, veclen(subpt2(t.p0, t.p1)))),
+					triperi(t));
+					c.r = 2*triarea(t)/triperi(t);
+					addobj(t, c);
+					npt = 0;
+				}
+				redraw();
+			}
+			break;
+		case Ekeyboard:
+			switch(e.kbdc){
+			case 'q':
+			case Kdel:
+				exits(0);
+			}
+			break;
+		}
+}
+
+void
+eresized(int)
+{
+	if(getwindow(display, Refnone) < 0)
+		sysfatal("resize failed");
+	redraw();
+}