import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; public class CurveFit extends Applet implements MouseListener, MouseMotionListener { double x[]; double y[]; int selected; public void init() { selected = 0; x = new double[4]; y = new double[4]; x[1] = 40; y[1] = 150; x[2] = 75; y[2] = 75; x[3] = 150; y[3] = 40; setBackground( Color.black ); addMouseListener(this); addMouseMotionListener(this); } public void mousePressed(MouseEvent e) { int mx = e.getX(); int my = e.getY(); Ellipse2D check; for(int i = 0; i < 4; i++) { check = new Ellipse2D.Double(x[i]-6,y[i]-6,11,11); if(check.contains(mx,my)) selected = i; } } public void mouseReleased(MouseEvent e) { selected = 0; } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { x[selected] = e.getX(); y[selected] = e.getY(); repaint(); } public void fillOval(Graphics g, double xc, double yc, double size) { g.fillOval((int)(xc-(size/2.0)),(int)(yc-(size/2.0)), (int)(size), (int)(size)); } public void paint( Graphics g ) { // Midpoint between p1 and p2 double pDX = 0.0; double pDY = 0.0; // Midpoint between p0 and p1 double pEX = 0.0; double pEY = 0.0; double mAB = 0.0; // Slope of p1 to p2 double mBC = 0.0; // Slope of p2 to p3 double mDF = 0.0; // Slope from mid of p1-p2 to center of circle (center line 2) double mEF = 0.0; // Slope from mid of p2-p3 to center of circle (center line 1) boolean iDF = false; // Slope is vertical/infinity boolean iEF = false; // Slope is vertical/infinity double bDF = 0.0; // X-intercept of center line 2 double bEF = 0.0; // X-intercept of center line 1 // Center point of the curve double pFX = 0.0; double pFY = 0.0; g.setColor( Color.green ); // Fill circles at the 3 points used fillOval(g,x[1],y[1],7); fillOval(g,x[2],y[2],7); fillOval(g,x[3],y[3],7); // Draw lines between those three points g.drawLine((int)x[1],(int)y[1],(int)x[2],(int)y[2]); g.drawLine((int)x[2],(int)y[2],(int)x[3],(int)y[3]); g.setColor( Color.red ); // Calculate the midpoints between the main points pDX = x[1] + ((x[2]-x[1])/2.0); pDY = y[1] + ((y[2]-y[1])/2.0); pEX = x[2] + ((x[3]-x[2])/2.0); pEY = y[2] + ((y[3]-y[2])/2.0); // Fill circles at the midpoints of those two lines fillOval(g,pDX,pDY,7); fillOval(g,pEX,pEY,7); // Get the slope perpendicular to the line between p1 and p2 if( (x[2]-x[1]) == 0 ) { mDF = 0; } else if( (y[2]-y[1]) != 0 ) { mAB = ((y[2]-y[1])/(x[2]-x[1])); mDF = -1/mAB; } else { iDF = true; } // Get the slope perpendicular to the line between p2 and p3 if( (x[3]-x[2]) == 0 ) { mEF = 0; } else if( (y[3]-y[2]) != 0 ) { mBC = ((y[3]-y[2])/(x[3]-x[2])); mEF = -1/mBC; } else { iEF = true; } // Calculate the x-intercepts of the lines to the center bDF = -1 * (mDF*pDX - pDY); bEF = -1 * (mEF*pEX - pEY); // If the lines are perpendicular, there will be no center point if( (mDF == mEF) && (iDF == iEF)) return; // Calculate the center point of the circle if(iDF == true) { pFX = pDX; pFY = mEF*pFX + bEF; } else if(iEF == true) { pFX = pEX; pFY = mDF*pFX + bDF; } else { pFX = (bEF - bDF)/(mDF - mEF); pFY = mDF*pFX + bDF; } // Draw lines to the center g.setColor( Color.red ); g.drawLine((int)pDX,(int)pDY,(int)pFX,(int)pFY); g.drawLine((int)pEX,(int)pEY,(int)pFX,(int)pFY); // Fill the center point g.setColor( Color.blue ); fillOval(g,pFX,pFY,7); // Draw lines from p1, p2, p3 to the center g.drawLine((int)x[1],(int)y[1],(int)pFX,(int)pFY); g.drawLine((int)x[2],(int)y[2],(int)pFX,(int)pFY); g.drawLine((int)x[3],(int)y[3],(int)pFX,(int)pFY); // Get the radius of the circle double R = Math.sqrt(Math.pow(x[1]-pFX,2)+Math.pow(y[1]-pFY,2)); // Draw the circle itself g.drawOval((int)(pFX-R),(int)(pFY-R),(int)R*2,(int)R*2); } }