import java.*; import java.awt.*; public class Ninept extends java.applet.Applet implements Runnable { Thread nineptdemo; NineptControl mycontrol; int state; Font font; int fsize; DPoint a,b,c; DPoint l,m,n; DPoint p,q,r; DPoint h; DPoint d,e,f; DLine sideab,sidebc,sideca,altap,altbq,altcr; DPoint center; double radius; public void init() { setLayout(new BorderLayout()); font = new Font("TimesRoman", Font.PLAIN, 12); fsize = font.getSize(); mycontrol = new NineptControl(this); mycontrol.addcontinuebutton(); mycontrol.addrestartbutton(); add("South",mycontrol); state = 0; a = new DPoint(40.0,20.0,"A"); b = new DPoint(270.0,20.0,"B"); c = new DPoint(120.0,150.0,"C"); sideab = new DLine(a,b); repaint(); } public void draw0(Graphics g) { g.setColor(Color.black); g.setFont(font); g.drawString("Click any point above this text and below line AB.",10,180); sideab.Show(g); a.Show(g,7); b.Show(g,1); } public void draw1(Graphics g) { g.setColor(Color.black); g.setFont(font); g.drawString("Take any triangle ABC.",10,180); sideab.Show(g); sidebc.Show(g); sideca.Show(g); a.Show(g,7); b.Show(g,1); c.Show(g,4); } public void draw2(Graphics g){ draw1(g); g.setColor(Color.red); g.drawString("The midpoints of the sides, ",10,180+fsize); l.Show(g,0); m.Show(g,3); n.Show(g,5); } public void draw3(Graphics g){ draw2(g); int width2 = g.getFontMetrics().stringWidth("The midpoints of the sides, "); g.setColor(Color.green); g.drawString("the feet of the altitudes ",10+width2, 180+fsize); p.Show(g,3); q.Show(g,5); r.Show(g,0); altap.Show(g); altbq.Show(g); altcr.Show(g); g.setColor(Color.blue); h.Show(g,7); g.drawString("(H, the point where the altitudes meet, is the orthocenter), ",10,180+2*fsize); } public void draw4(Graphics g){ draw3(g); g.setColor(Color.cyan); d.Show(g,1); e.Show(g,7); f.Show(g,3); g.drawString("and the midpoints of AH, BH and CH ",10,180+3*fsize); } public void draw5(Graphics g){ draw4(g); g.setColor(Color.magenta); int width2 = g.getFontMetrics().stringWidth("and the midpoints of AH, BH and CH "); g.drawString("all lie on a circle.",10+width2,180+3*fsize); g.drawOval( (int)(center.x-radius),(int)(center.y-radius),(int)(2.0*radius),(int)(2.0*radius)); } public void paint(Graphics g) { switch (state) { case 0: { draw0(g); break; } case 1: { draw1(g); break; } case 2: { draw2(g); break; } case 3: { draw3(g); break; } case 4: { draw4(g); break; } default: { draw5(g); break; } } } public boolean mouseUp(Event evt, int x, int y){ if((state == 0) && (y > 20) && (y < 180)){ c.x = (double) x; c.y = (double) y; state = 1; sidebc = new DLine(b,c); sideca = new DLine(c,a); l = sideab.midpoint(); m = sidebc.midpoint(); n = sideca.midpoint(); l.label = "L"; m.label = "M"; n.label = "N"; r = sideab.footalt(c); p = sidebc.footalt(a); q = sideca.footalt(b); p.label = "P"; q.label = "Q"; r.label = "R"; altap = new DLine(a,p); altbq = new DLine(b,q); altcr = new DLine(c,r); h = altap.intersect(altbq); h.label = "H"; d = new DLine(a,h).midpoint(); e = new DLine(b,h).midpoint(); f = new DLine(c,h).midpoint(); d.label = "D"; e.label = "E"; f.label = "F"; center = l.circumcenter(m,n); center.label = "CENTER"; radius = center.dist(l); repaint(); } return true; } public void start(){ nineptdemo = new Thread(this); nineptdemo.start(); } public void stop(){ nineptdemo.stop(); } public void run() { } } class DPoint{ double x, y; String label; public DPoint(double first, double second, String name){ x = first; y = second; label = name; } public DPoint(double first, double second){ x = first; y = second; label = ""; } public void Show(Graphics g, int where){ int first = (int) x; int second = (int) y; // where tells us where to place the character // relative to the point --- 0 = north, 1 = northeast, // 2 = east, ..., 7 = northwest. int xoffs[] = {0,3,5,6,-3,-10,-12,-10}; int yoffs[] = {-5,-3,0,10,13,10,0,-3}; int offsetx = xoffs[where]; int offsety = yoffs[where]; g.drawOval(first-1,second-1,2,2); g.drawString(label,first+offsetx,second+offsety); } public double dist(DPoint q){ return Math.sqrt((q.x - x)*(q.x - x) + (q.y - y)*(q.y - y)); } public DPoint orthocenter(DPoint m, DPoint n){ // orthocenter of triangle DLine sidemn = new DLine(m,n); DLine sidelm = new DLine(this,m); DPoint foot1 = sidemn.footalt(this); DPoint foot2 = sidelm.footalt(n); DLine alt1 = new DLine(this, foot1); DLine alt2 = new DLine(n, foot2); return alt1.intersect(alt2); } public DPoint circumcenter(DPoint b, DPoint c){ // circumcenter of triangle formed by the 3 points DPoint l = new DLine(this,b).midpoint(); DPoint m = new DLine(this,c).midpoint(); DPoint n = new DLine(b,c).midpoint(); return l.orthocenter(m,n); } } class DLine{ DPoint p,q; public DLine(DPoint first, DPoint second){ p = first; q = second; } public void Show(Graphics g){ int x1 = (int) p.x; int y1 = (int) p.y; int x2 = (int) q.x; int y2 = (int) q.y; g.drawLine(x1,y1,x2,y2); } public DPoint lambdapoint(double lambda){ // The result is the point a fraction lambda // of the way from point p to point q. For example, // if lambda == 0.5, we get the midpoint. In // vector notation, r = p*(1-lambda) + q*lambda. return(new DPoint(q.x*lambda + p.x*(1.0-lambda), q.y*lambda + p.y*(1.0-lambda))); } public DPoint midpoint(){ return lambdapoint(0.5); } public DPoint intersect(DLine m){ double numerator = (m.q.x-q.x)*(m.q.y-m.p.y) - (m.q.x-m.p.x)*(m.q.y-q.y); double denominator = (p.x-q.x)*(m.q.y-m.p.y) - (m.q.x-m.p.x)*(p.y-q.y); double lambda = 1.0 - numerator / denominator; return( lambdapoint(lambda)); } public DPoint footalt(DPoint c){ // foot of the altitude from point c to this line // determine lambda so that // lambdapoint h on line qp satisfies // dot product ch.pq == 0. double lambda = ( (q.x-p.x)*(q.x-c.x) + (q.y-p.y)*(q.y-c.y) ) / ( (q.x-p.x)*(q.x-p.x) + (q.y-p.y)*(q.y-p.y) ); return lambdapoint(1.0-lambda); } } class NineptControl extends Panel{ Button continuebutton, restartbutton; Ninept applet; public NineptControl(Ninept app){ applet = app; } public void addcontinuebutton(){ add(continuebutton = new Button("Continue")); } public void addrestartbutton(){ add(restartbutton = new Button("Restart")); } public boolean action(Event ev, Object arg){ if(ev.target instanceof Button && applet.state > 0){ if("Continue".equals(arg)){ applet.state++; } if("Restart".equals(arg)){ applet.state = 0; } applet.repaint(); return true; } return false; } }