import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.border.*; import java.util.*; import java.text.*; public class InscribedAngles extends JApplet { double r, a, rad; int clicks; int x1,y1, x2,y2, x3,y3; int endX, endY; //so mouseListener has access int rLen; int midX, midY; DecimalFormat d2; public void init() { rLen = getHeight()/2-20; //mouseListener needs midX = getWidth()/2; midY = getHeight()/2; d2 = new DecimalFormat ("0.00"); addMouseListener( new MouseAdapter() { public void mouseClicked( MouseEvent event) { int px, py; px = event.getX(); py = event.getY(); double d = distanceFormula(px,py,midX,midY); double dc; if (d > rLen) dc = d - rLen; else dc = rLen - d; //within the circle if (dc < 30) { double m = (double)(py-midY)/(px-midX); double dx = rLen / Math.sqrt(m*m+1); double dy = rLen*m / Math.sqrt(m*m+1); int cx, cy; if (px < midX) cx = midX - (int)dx; else cx = midX + (int)dx; if (m > 0) if (py < midY) cy = midY - (int)dy; else cy = midY + (int)dy; else if (py < midY) cy = midY + (int)dy; else cy = midY - (int)dy; clicks++; switch (clicks) { case 1: x1 = cx; //y1 = getHeight() - event.getY(); y1 = cy; //sx1 = x1*scale; //sy1 = y1*scale; break; case 2: x2 = cx; //y2 c getHeight() - event.getY(); y2 = cy; //sx2 = x2*scale; //sy2 = y2*scale; break; case 3: x3 = cx; //y3 c getHeight() - event.getY(); y3 = cy; //sx3 = x3*scale; //sy3 = y3*scale; break; default: clicks = 3; //set it back to 3?? return; //do not repaint } repaint(); } } } ); addMouseMotionListener( new MouseMotionAdapter() { public void mouseDragged( MouseEvent event) { int px = event.getX(); int py = event.getY(); //double x=-999, y=-999; //inits to fake out compiler for showStatus double mouseDistance1 = distanceFormula(px,py, x1,y1); double mouseDistance2 = distanceFormula(px,py, x2,y2); double mouseDistance3 = distanceFormula(px,py, x3,y3); if (mouseDistance1<30 || mouseDistance2<30 || mouseDistance3<30) { double m = (double)(py-midY)/(px-midX); if (px == midX) //crossing vertical line m = 1000000; //instead of inf double dx = rLen / Math.sqrt(m*m+1); double dy = rLen*m / Math.sqrt(m*m+1); int cx, cy; if (px < midX) cx = midX - (int)dx; else cx = midX + (int)dx; if (m > 0) if (py < midY) cy = midY - (int)dy; else cy = midY + (int)dy; else if (py < midY) cy = midY + (int)dy; else cy = midY - (int)dy; switch (minDistance(mouseDistance1,mouseDistance2,mouseDistance3)) { case 1: x1 = cx; y1 = cy; break; case 2: x2 = cx; y2 = cy; break; case 3: x3 = cx; y3 = cy; break; } repaint(); //there's a problem at vertical??? /*if (a < 180) { //left right: px change x = (double)(px-midX)/rLen; if (x <= r && x >= -r) //avoid going under?? at 0 //if (a < 0) // ?? nope // a = 0; } else if (a > 180) { //left right: opp. of upper half circle x = (double)(midX-px)/rLen; if (x <= r && x >= -r) //avoid going under?? at 360 } else { //a==180 ?? if (py != midY) { //has to be at least one pixel above or below y = (double)(py-midY)/rLen; } } //showStatus("("+px+","+(getHeight()-py)+") x="+x+" y="+y+" a="+a); */ } } } ); } public void start(){ clicks = 0; JOptionPane.showMessageDialog( this, "Click 3 points on the circle."+ "\n THEN Drag them around", "TriangleApplet: what to do", JOptionPane.INFORMATION_MESSAGE ); } public void paint (Graphics g) { super.paint( g ); //erase g.setFont( new Font( "SansSerif", Font.BOLD, 12 ) ); g.drawString("Drag points around circle",5,70); int w = getWidth(); int h = getHeight(); g.drawOval(midX-rLen,midY-rLen,2*rLen,2*rLen); g.setColor(Color.RED); if (clicks < 3) { //still getting the vertices switch (clicks) { case 1: g.fillOval(x1-2,y1-2,4,4); break; case 2: //g.fillOval(x1-2,h-y1-2,4,4); //g.fillOval(x2-2,h-y2-2,4,4); g.fillOval(x1-2,y1-2,4,4); g.fillOval(x2-2,y2-2,4,4); break; } } else { //clicks == 3 or mouse dragged a vertex //g.fillOval(x1-2,h-y1-2,4,4); //g.fillOval(x2-2,h-y2-2,4,4); //g.fillOval(x3-2,h-y3-2,4,4); g.fillOval(x1-2,y1-2,4,4); g.fillOval(x2-2,y2-2,4,4); g.fillOval(x3-2,y3-2,4,4); g.drawLine(midX,midY, x1,y1); g.drawLine(midX,midY, x2,y2); g.drawLine(x1,y1, x3,y3); g.drawLine(x2,y2, x3,y3); double alpha, d13, d23, d12; d13 = distanceFormula(x1,y1, x3,y3); d23 = distanceFormula(x2,y2, x3,y3); d12 = distanceFormula(x1,y1, x2,y2); alpha = Math.toDegrees(Math.acos((d13*d13+d23*d23-d12*d12) / (2*d13*d23))); g.setColor( Color.BLUE ); g.drawString(""+d2.format(alpha)+"\u00B0",x3,y3); double m13 = (double)(y1-y3)/(x1-x3); if (x1 == x3) m13 = 1000000; double m23 = (double)(y2-y3)/(x2-x3); if (x2 == x3) m23 = 1000000; double angle13 = Math.toDegrees(Math.atan(m13)); //angle of the line double angle23 = Math.toDegrees(Math.atan(m23)); if (x3 < midX) //leftside if (angle13 < angle23) //from the bigger to the smaller g.drawArc(x3-20,y3-20,40,40, -(int)angle23,(int)alpha); else g.drawArc(x3-20,y3-20,40,40, -(int)angle13,(int)alpha); else if (angle13 < angle23) //from the bigger to the smaller g.drawArc(x3-20,y3-20,40,40, 180-(int)angle23,(int)alpha); else g.drawArc(x3-20,y3-20,40,40, 180-(int)angle13,(int)alpha); showStatus("m13="+m13+" m23="+m23+" angle13="+angle13+" angle23="+angle23+" alpha="+alpha); g.drawArc(50,50,20,20, 45,90); g.drawArc(50,80,20,20, -45,90); g.drawArc(50,110,20,20, 180,90); double beta, d1mid, d2mid; d1mid = distanceFormula(x1,y1, midX,midY); d2mid = distanceFormula(x2,y2, midX,midY); beta = Math.toDegrees(Math.acos((d1mid*d1mid+d2mid*d2mid-d12*d12) / (2*d1mid*d2mid))); g.drawString(""+d2.format(beta)+"\u00B0",midX,midY); //g.drawArc(midX-10,midY-10,20,20, 0,(int)beta); //g.drawArc(midX-15,midY-15,30,30, 0,(int)beta); double a1 = Math.toDegrees(Math.acos((d1mid*d1mid+d13*d13-rLen*rLen) / (2*d1mid*d13))); g.drawString(""+d2.format(a1)+"\u00B0",x1,y1); double a2 = Math.toDegrees(Math.acos((d2mid*d2mid+d23*d23-rLen*rLen) / (2*d2mid*d23))); g.drawString(""+d2.format(a2)+"\u00B0",x2,y2); } } public double distanceFormula (double x1, double y1, double x2, double y2){ return Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); } //indicate which of 3 parameters is the min public int minDistance (double d1, double d2, double d3){ if (d1<=d2 && d1<=d3) return 1; else if (d2<=d1 && d2<=d3) return 2; else return 3; } }