diff options
author | rodri <rgl@antares-labs.eu> | 2020-05-11 09:59:39 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2020-05-11 09:59:39 +0000 |
commit | a946b00aa91ed059a1e9aad367bb6e872dcd1c1a (patch) | |
tree | b2d5064c70659627a8e9054d6ce02dd440c2a407 | |
download | etoys-a946b00aa91ed059a1e9aad367bb6e872dcd1c1a.tar.gz etoys-a946b00aa91ed059a1e9aad367bb6e872dcd1c1a.tar.bz2 etoys-a946b00aa91ed059a1e9aad367bb6e872dcd1c1a.zip |
new toy: triangles
-rw-r--r-- | mkfile | 7 | ||||
-rw-r--r-- | triangles.c | 236 |
2 files changed, 243 insertions, 0 deletions
@@ -0,0 +1,7 @@ +</$objtype/mkfile + +BIN=/$objtype/bin/etoys +TARG=\ + triangles\ + +</sys/src/cmd/mkmany diff --git a/triangles.c b/triangles.c new file mode 100644 index 0000000..320807f --- /dev/null +++ b/triangles.c @@ -0,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(); +} |