RightTriangle t; PFont font; PGraphics grid; int stage; // demo phase we're on int stageMax; // number of phases String[] message = { "First we generate two random points.", "Then we make a line.", "How can we make a right triangle along this line?", "Randomly choose a length along this line for point C.", "Now we have a right triangle with center and area."}; void setup() { size(300,300); noSmooth(); rectMode(CENTER); font = loadFont("Monaco-9.vlw"); textFont(font, 9); t = new RightTriangle(); grid = createGrid(); stage = 0; stageMax = message.length; } void draw() { background(255); image(grid, 0, 0); t.update(); t.draw(); fill(0); NumberFormat formatter = new DecimalFormat(".0"); text("Angle a: " + formatter.format(degrees(t.angleA)) + "°", 0,9); text("Angle b: 90.0°", 0,18); text("Angle c: " + formatter.format(degrees(t.angleC)) + "°", 0,27); msg(); } void keyPressed() { if (key == 'n') { t = new RightTriangle(); stage = 0; } if (key == ' ') { stage++; if (stage == stageMax) { t = new RightTriangle(); stage = 0; } } if (keyCode == UP) { t.moveCx(1); } if (keyCode == DOWN) { t.moveCx(-1); } } void msg() { text("SPACE=continue N=new", 0, height-1); text(message[stage], 0, height-9); } PGraphics createGrid() { PGraphics img = createGraphics(width,height,P2D); img.beginDraw(); img.background(255); int gridSize = 5; img.stroke(0, 0, 0, 10); for (int i=0; i 0) { stroke(260,120,20); line(points[0].x, points[0].y, points[1].x, points[1].y); pushMatrix(); translate((points[0].x + points[1].x)/2, (points[0].y + points[1].y)/2); text("A", 0,0); popMatrix(); } // stage 2 if (stage > 1) { stage2line(points[0], points[1]); } if (stage > 2) { stroke(0); fill(255); rect(pc.x, pc.y, 5, 5); fill(0); text("c", pc.x + 4, pc.y); } if (stage > 3) { noFill(); rect(center.x, center.y, 8.0f, 8.0f); point(center.x, center.y); fill(0); text("center", center.x + 6.0f, center.y + 4.0f); pushMatrix(); translate((points[1].x + points[2].x)/2, (points[1].y + points[2].y)/2); text("B", 0,0); popMatrix(); pushMatrix(); translate((points[2].x + points[0].x)/2, (points[2].y + points[0].y)/2); text("C", 0,0); popMatrix(); stroke(230,90,20); line(points[1].x, points[1].y, points[2].x, points[2].y); stroke(200,60,20); line(points[2].x, points[2].y, points[0].x, points[0].y); } } void stage2line(p2d pointA, p2d pointB) { float rise = pointA.y - pointB.y; float run = pointA.x - pointB.x; float m = 0; try { m = rise/run; // m=slope } catch (ArithmeticException a) { println("div by zero oh sh..."); } // line ab // m = (y2-y1)/(x2 - x1) // line bc is negative reciprocal // m = -(x2-x1)/(y2-y1) // b is (x2,y2) // so line bc is y = - (x2-x1)/(y2-y1) * (x - x2) + y2 float x = 0; if (m > 0) { x = pointB.x + c; } else { x = pointB.x - c; } //float y = -(pointB.x - pointA.x) / (pointB.y - pointA.y) * (x - pointB.x) + pointB.y; //p2d p0 = points[2]; p2d p1 = points[1]; p2d p2 = points[2]; float y1 =(p2.y - p1.y) / (p2.x - p1.x) * (0 - p2.x) + p2.y; float y2 = (p2.y - p1.y) / (p2.x - p1.x) * (width - p2.x) + p2.y; strokeWeight(3); stroke(0,0,0,20); line(0, y1, height, y2); strokeWeight(1); } } class RightTriangle extends Triangle { public RightTriangle() { int minY = 80; int maxY = height-50; // picking two numbers too close on Y causes steep slope which causes weirdness // so generate a random number from 50 to height but not if they are within 10 float randomY0 = 0.0f; float randomY1 = 0.0f; while (abs(randomY0 - randomY1) < maxY * .05) { randomY0 = random(minY, maxY); randomY1 = random(minY, maxY); } points[0] = new p2d(random(50, width-50), randomY0); points[1] = new p2d(random(50, width-50), randomY1); points[2] = corner(points[0], points[1]); float cx = (points[0].x + points[1].x + points[2].x) / 3; float cy = (points[0].y + points[1].y + points[2].y) / 3; center = new p2d(cx, cy); } public void moveCx(int cx) { this.c += cx; points[2] = corner(points[0], points[1]); } // create 3rd point at right angle from two points private p2d corner(p2d p1, p2d p2) { float rise = p1.y - p2.y; float run = p1.x - p2.x; float m = 0; try { m = rise/run; // m=slope } catch (ArithmeticException a) { println("div by zero oh sh..."); } // line ab // m = (y2-y1)/(x2 - x1) // line bc is negative reciprocal // m = -(x2-x1)/(y2-y1) // b is (x2,y2) // so line bc is y = - (x2-x1)/(y2-y1) * (x - x2) + y2 float x = 0; if (m > 0) { x = p2.x + c; } else { x = p2.x - c; } float y = -(p2.x - p1.x) / (p2.y - p1.y) * (x - p2.x) + p2.y; float x3 = x; float y3 = y; return new p2d(x3,y3); } } class Vector2D{ float x; float y; Vector2D(){ this(0,0); } void set(float _x,float _y){x=_x;y=_y;} Vector2D(float _x, float _y){ x=_x; y=_y; } void clear(){x=0;y=0;} Vector2D add(Vector2D v){ return new Vector2D(x+=v.x,y+=v.y); } Vector2D add(float x, float y){ return new Vector2D(x+=x,y+=y); } Vector2D addSelf(Vector2D v){ x+=v.x; y+=v.y; return this; } Vector2D addSelf(float _x, float _y){ x+=_x; y+=_y; return this; } Vector2D sub(float x, float y){ return new Vector2D(x-=x,y-=y); } Vector2D sub(Vector2D v){ return new Vector2D(x-v.x,y-v.y); } Vector2D subSelf(Vector2D v){ x-=v.x; y-=v.y; return this; } Vector2D subSelf(float _x, float _y){ x-=_x; y-=_y; return this; } Vector2D mult(float alpha){ return new Vector2D(x*alpha,y*alpha); } Vector2D multSelf(float alpha){ x*=alpha; y*=alpha; return this; } Vector2D div(float alpha){ return new Vector2D(x/alpha,y/alpha); } Vector2D divSelf(float alpha){ x/=alpha; y/=alpha; return this; } float norm(){ return sqrt(pow(x,2)+pow(y,2)); } Vector2D versor(){ return new Vector2D(x/norm(),y/norm()); } Vector2D versorSelf(){ x/=norm(); y/=norm(); return this; } Vector2D clone(){ return new Vector2D(x,y); } String toString(){ return "["+x+","+y+"]"; } }