/* CMPT 460; Assignment 2
 * Andrey Mirtchovski; SN == 358764
 * 
 */
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 Midpoint 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 Curve() {
            setBackground(Color.white);
        }
    
    
        public void drawCurve(int w, int h, Graphics2D g2) {
    		

			// calculate middle of window. since this calculation 
			// is not within the loop, it could be
			// considered harmless, even though it involves division
			int midx= w/2;	
			int midy = h/2;	

			// draw axis
			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));
			// draw tickmarks 20 pixels apart
			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; //starting points
			int d0 = 2*n - m; // initial decision function
			int d = d0;
			int det = 2*n;		// used in calculating the slope 

			g2.setColor(Color.black);
			// draw origin
			g2.draw(new Rectangle(midx, midy, 1, 1));

			while(x++ < midx && y < midy && x * det < m) {
				if(d<0) {
					d = d + 4 * n * (x + 2);
				} else {
					y++;
					d = d + 4 * n * (x + 2) - 2*m;
				}
				// draw proper (x,y) to compensate for the screwed up
				// coordinate system java has
				g2.draw(new Rectangle(x+midx, midy-y, 1, 1));
				g2.draw(new Rectangle(midx-x, midy-y, 1, 1));
			}


			// calculate the new d0 (for the new axis)
			d = n * (2*x + 1) * (2*x + 1) - 4 * m * (y + 1);

			// dx/dy > 1 from now on
			// or the end of the window is reached
			while(y++ < midy && x < midx) {
				if(d<0) {
					x++;
					d = d + 8*n*(x+1) - 4*m;
				} else {
					d = d - 4*m;
				}
				// draw proper (x,y) to compensate for the screwed up
				// coordinate system java has
				g2.draw(new Rectangle(x+midx, midy-y, 1, 1));
				g2.draw(new Rectangle(midx-x, midy-y, 1, 1));
			}



		}
    
    
        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);
        }
    }  // End Curve class


	   class CurveControls extends JPanel implements ActionListener {

        Curve curve;
        JTextField tf1, tf2;

        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(60,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(30,20));
            tf2.addActionListener(this);
        }

        public void actionPerformed(ActionEvent e) {
            try { 
                if (e.getSource().equals(tf1)) {
                    curve.m = Integer.parseInt(tf1.getText().trim());
                } else if (e.getSource().equals(tf2)) {
                    curve.n = Integer.parseInt(tf2.getText().trim());
                }
                curve.repaint();
            } catch (Exception ex) {}
        }
    } // End CurveControls class



   public static void main(String argv[]) {
        final Midpoint demo = new Midpoint();
        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();
    }
}
