import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.*;
import javax.swing.*;

public class Midpoint2 extends JApplet {
    public void init() {
        Curve curve = new Curve();
        getContentPane().add(curve);
        getContentPane().add("North", new CurveControls(curve));
    }
    static class Curve extends JPanel {
        public int m = 400;
        public int n = 1;
        public int max = 400; 
        public Curve() {
            setBackground(Color.white);
        }
        public void drawCurve(int w, int h, Graphics2D g2) {
            int midx= w/2;    
            int midy = h/2;    
            int maxx = midx < max ? midx : max;
            g2.setColor(Color.red);
            g2.draw(new Line2D.Double(0.0, (double)midy, (double)w, (double)midy));
            g2.draw(new Line2D.Double((double)midx, 0.0, (double)midx, (double)h));
            for(int i = midx + 20; i <= w; i+=20){
                g2.draw(new Line2D.Double((double)i, (double)(midy-2), (double)i, (double)(midy+2)));
                g2.draw(new Line2D.Double((double)(w-i), (double)(midy-2), (double)(w-i), (double)(midy+2)));
            }
            for(int i = midy + 20; i <= h; i+=20) {
                g2.draw(new Line2D.Double((double)(midx-2), (double)i, (double)(midx+2), (double)i));
                g2.draw(new Line2D.Double((double)(midx-2), (double)(h-i), (double)(midx+2), (double)(h-i)));
            }
            /*********************************
             * FP-free algorithm starts here *
             *********************************/
            int x = 0, y = 0;     
            int newx = 0, newx2 = 0; 
            int newy = 0;        
            int d_flag = ((n < 0 && m > 0) || (n > 0 && m < 0)) ? -1 : 1;
            m = (m < 0) ? -m : m;
            n = (n < 0) ? -n : n;
            int d0 = 2*n - m;     
            int d = d0;
            int n_2 = n<<1;
            int n_4 = n_2<<1; 
            int n_8 = n_4<<1; 
            int m_2 = m<<1;
            int m_4 = m_2<<1;
            int det = n_2;            
            g2.setColor(Color.black);
            while(x < maxx && x * det < m) {
                x++;
                d = d + 4 * n * (x + 2) - (d < 0 ? 0 : 2*m);
                if (d > 0 && ++y > midy)
                    break;
                newx = midx + x;
                newx2 = midx - x;
                newy = midy - y*d_flag;
                g2.draw(new Line2D.Double((double)(newx), (double)(newy), 
                        (double)(newx), (double)(newy)));
                g2.draw(new Line2D.Double((double)(newx2), (double)(newy), 
                        (double)(newx2), (double)(newy)));
            }
            d = n * (2*x + 1) * (2*x + 1) - m_4 * (y + 1);
            while(y < midy && x < maxx) {
                y++;
                d = d - m_4 + (d < 0 ?  n_8*(x+1) : 0);
                if (d < 0 && ++x > maxx)    
                    break;
                newx = midx + x;
                newx2 = midx - x;
                newy = midy - y*d_flag;
                g2.draw(new Line2D.Double((double)(newx), (double)(newy), 
                        (double)(newx), (double)(newy)));
                g2.draw(new Line2D.Double((double)(newx2), (double)(newy), 
                        (double)(newx2), (double)(newy)));
            }
        }
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            Dimension d = getSize();
            g2.setBackground(getBackground());
            g2.clearRect(0, 0, d.width, d.height);
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            drawCurve(d.width, d.height, g2);
        }
    }  
       class CurveControls extends JPanel implements ActionListener {
        Curve curve;
        JTextField tf1, tf2, tf3;
        public CurveControls(Curve curve) {
            this.curve = curve;
            setBackground(Color.gray);
            JLabel l = new JLabel(" Enter values for my = nx^2:");
            l.setForeground(Color.black);
            add(l);
            l = new JLabel(" m=");
            l.setForeground(Color.black);
            add(l);
            add(tf1 = new JTextField(String.valueOf(curve.m)));
            tf1.setPreferredSize(new Dimension(40,20));
            tf1.addActionListener(this);
            l = new JLabel("  n=");
            l.setForeground(Color.black);
            add(l);
            add(tf2 = new JTextField(String.valueOf(curve.n)));
            tf2.setPreferredSize(new Dimension(40,20));
            tf2.addActionListener(this);
            l = new JLabel("  max X=");
            l.setForeground(Color.black);
            add(l);
            add(tf3 = new JTextField(String.valueOf(curve.max)));
            tf3.setPreferredSize(new Dimension(40,20));
            tf3.addActionListener(this);
        }
        public void actionPerformed(ActionEvent e) {
            try { 
                curve.m = Integer.parseInt(tf1.getText().trim());
                curve.n = Integer.parseInt(tf2.getText().trim());
                curve.max = Integer.parseInt(tf3.getText().trim());
                curve.repaint();
            } catch (Exception ex) {}
        }
    } 
   public static void main(String argv[]) {
        final Midpoint2 demo = new Midpoint2();
        demo.init();
        JFrame f = new JFrame("Midpoint curve calculation for f(y) = (nx^2)/m");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        f.getContentPane().add("Center", demo);
        f.pack();
        f.setSize(new Dimension(500, 500));
        f.show();
    }
}
