1:import java.applet.*;
   2:import java.awt.*;
   3:import java.awt.event.*;
   4:import java.awt.geom.*;
   5:
   6:public class CurveFit extends Applet implements MouseListener, MouseMotionListener {
   7:        
   8:        double  x[];
   9:        double  y[];
  10:        int selected;
  11:        
  12:        public void init() {
  13:                selected = 0;
  14:                x = new double[4];
  15:                y = new double[4];
  16:                x[1] = 40;
  17:                y[1] = 150;
  18:                x[2] = 75;
  19:                y[2] = 75;
  20:                x[3] = 150;
  21:                y[3] = 40;
  22:                
  23:                setBackground( Color.black );
  24:                addMouseListener(this);
  25:                addMouseMotionListener(this);
  26:        }
  27:        
  28:        public void mousePressed(MouseEvent e) {
  29:                int     mx = e.getX();
  30:                int     my = e.getY();
  31:                Ellipse2D check;
  32:                for(int i = 0; i < 4; i++)
  33:                {
  34:                        check = new Ellipse2D.Double(x[i]-6,y[i]-6,11,11);
  35:                        if(check.contains(mx,my))
  36:                                selected = i;
  37:                }
  38:        }
  39:        
  40:        public void mouseReleased(MouseEvent e) {
  41:                selected = 0;
  42:        }
  43:        
  44:        public void mouseEntered(MouseEvent e) {
  45:        }
  46:        
  47:        public void mouseExited(MouseEvent e) {
  48:        }
  49:        
  50:        public void mouseClicked(MouseEvent e) {
  51:        }
  52:        
  53:        public void mouseMoved(MouseEvent e) {
  54:        }
  55:        
  56:        public void mouseDragged(MouseEvent e) {
  57:                x[selected] = e.getX();
  58:                y[selected] = e.getY();
  59:                repaint();
  60:        }
  61:        
  62:        public void fillOval(Graphics g, double xc, double yc, double size) {
  63:                g.fillOval((int)(xc-(size/2.0)),(int)(yc-(size/2.0)), (int)(size), (int)(size));
  64:        }
  65:        
  66:        public void paint( Graphics g ) {
  67:                // Midpoint between p1 and p2
  68:                double pDX = 0.0;
  69:                double pDY = 0.0;
  70:                // Midpoint between p0 and p1
  71:                double pEX = 0.0;
  72:                double pEY = 0.0;
  73:                double mAB = 0.0; // Slope of p1 to p2
  74:                double mBC = 0.0; // Slope of p2 to p3
  75:                double mDF = 0.0; // Slope from mid of p1-p2 to center of circle (center line 2)
  76:                double mEF = 0.0; // Slope from mid of p2-p3 to center of circle (center line 1)
  77:                boolean iDF = false; // Slope is vertical/infinity
  78:                boolean iEF = false; // Slope is vertical/infinity
  79:                double bDF = 0.0; // X-intercept of center line 2
  80:                double bEF = 0.0; // X-intercept of center line 1
  81:                // Center point of the curve
  82:                double pFX = 0.0;
  83:                double pFY = 0.0;
  84:                
  85:                g.setColor( Color.green );
  86:                
  87:                // Fill circles at the 3 points used
  88:                fillOval(g,x[1],y[1],7);
  89:                fillOval(g,x[2],y[2],7);
  90:                fillOval(g,x[3],y[3],7);
  91:                
  92:                // Draw lines between those three points
  93:                g.drawLine((int)x[1],(int)y[1],(int)x[2],(int)y[2]);
  94:                g.drawLine((int)x[2],(int)y[2],(int)x[3],(int)y[3]);
  95:                
  96:                g.setColor( Color.red );
  97:                
  98:                // Calculate the midpoints between the main points
  99:                pDX = x[1] + ((x[2]-x[1])/2.0);
 100:                pDY = y[1] + ((y[2]-y[1])/2.0);
 101:                pEX = x[2] + ((x[3]-x[2])/2.0);
 102:                pEY = y[2] + ((y[3]-y[2])/2.0);
 103:
 104:                // Fill circles at the midpoints of those two lines
 105:                fillOval(g,pDX,pDY,7);
 106:                fillOval(g,pEX,pEY,7);
 107:                
 108:                // Get the slope perpendicular to the line between p1 and p2
 109:                if( (x[2]-x[1]) == 0 )
 110:                {
 111:                        mDF = 0;
 112:                }
 113:                else if( (y[2]-y[1]) != 0 )
 114:                {
 115:                        mAB = ((y[2]-y[1])/(x[2]-x[1]));
 116:                        mDF = -1/mAB;
 117:                }
 118:                else
 119:                {
 120:                        iDF = true;
 121:                }
 122:                
 123:                // Get the slope perpendicular to the line between p2 and p3
 124:                if( (x[3]-x[2]) == 0 )
 125:                {
 126:                        mEF = 0;
 127:                }
 128:                else if( (y[3]-y[2]) != 0 )
 129:                {
 130:                        mBC = ((y[3]-y[2])/(x[3]-x[2]));
 131:                        mEF = -1/mBC;
 132:                }
 133:                else 
 134:                {
 135:                        iEF = true;
 136:                }
 137:                
 138:                // Calculate the x-intercepts of the lines to the center
 139:                bDF = -1 * (mDF*pDX - pDY);
 140:                bEF = -1 * (mEF*pEX - pEY);
 141:                
 142:                // If the lines are perpendicular, there will be no center point
 143:                if( (mDF == mEF) && (iDF == iEF))
 144:                        return;
 145:                
 146:                // Calculate the center point of the circle
 147:                if(iDF == true)
 148:                {
 149:                        pFX = pDX;
 150:                        pFY = mEF*pFX + bEF;
 151:                }
 152:                else if(iEF == true)
 153:                {
 154:                        pFX = pEX;
 155:                        pFY = mDF*pFX + bDF;
 156:                }
 157:                else
 158:                {
 159:                        pFX = (bEF - bDF)/(mDF - mEF);
 160:                        pFY = mDF*pFX + bDF;
 161:                }
 162:                
 163:                // Draw lines to the center
 164:                g.setColor( Color.red );
 165:                g.drawLine((int)pDX,(int)pDY,(int)pFX,(int)pFY);
 166:                g.drawLine((int)pEX,(int)pEY,(int)pFX,(int)pFY);
 167:                
 168:                // Fill the center point
 169:                g.setColor( Color.blue );
 170:                fillOval(g,pFX,pFY,7);
 171:                
 172:                // Draw lines from p1, p2, p3 to the center
 173:                g.drawLine((int)x[1],(int)y[1],(int)pFX,(int)pFY);
 174:                g.drawLine((int)x[2],(int)y[2],(int)pFX,(int)pFY);
 175:                g.drawLine((int)x[3],(int)y[3],(int)pFX,(int)pFY);
 176:                
 177:                // Get the radius of the circle
 178:                double  R = Math.sqrt(Math.pow(x[1]-pFX,2)+Math.pow(y[1]-pFY,2));
 179:                
 180:                // Draw the circle itself
 181:                g.drawOval((int)(pFX-R),(int)(pFY-R),(int)R*2,(int)R*2);
 182:        }
 183:}