import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;


public class Sierpinski extends JFrame {

   private final int UNIT = 5;
   private int depth;

   private int x = 400;
   private int y = 100;
   private int direction;

   /*
   * Constructor - assigns parameter n to depth and sets
   * initial direction of line segment to 0 (north)
   */
    public Sierpinski(int n, int w, int h) 
   {
      super("Sierpinski");
      depth = n;
      direction = 0;
      setSize(w, h );
      setVisible( true );
   }

   /*
   * Changes the line segment 'direction' leftwards (0 =north
   * 1=west, 2=south, 3=east) i.e. 0 becomes 1, 1 becomes 2,
   * 2 becomes 3 and 3 becomes 0
   */
   private int turnLeft()
   {
      int newD;
      if (direction == 3)
         newD = 0;
      else
         newD = direction + 1;
      return newD;
   }

   /*
   * Changes the line segment 'direction' rightwards, i.e.
   *  0 becomes 3, 1 becomes 0, 2 becomes 1 and 3 becomes 2
   */
   private int turnRight()
   {
      int newD;
      if (direction == 0)
         newD = 3;
      else
         newD = direction - 1;
      return newD;
   }

   /*
   * Computes the x coordinate of the end of the line segment
   * to be drawn - depending on direction, the x coordinate
   * is either the same as the x coordinate of the other end
   * or + or - the segment length (UNIT).
   */
   private int newX()
   {
      int xNew;
      if (direction == 0 || direction == 2)
         xNew = x;
      else if (direction == 1)
         xNew = x - UNIT;
      else
         xNew = x + UNIT;
      return xNew;
   }

   /*
   * Computes the y coordinate of the end of the line segment
   * to be drawn - depending on direction, the y coordinate
   * is either the same as the y coordinate of the other end
   * or + or - the segment length (UNIT).
   */
   private int newY()
   {
      int yNew;
      if (direction == 1 || direction == 3)
         yNew = y;
      else if (direction == 0)
         yNew = y - UNIT;
      else
         yNew = y + UNIT;
      return yNew;
   }

   /*
   * Base case (n=1):
   *    draw the two line segments with a left turn
   * Recursive Case:
   *    Call zig, zag, zig, zag on n/2
   *    (Note the indirect recursion in the call to zag - which
   *     itself calls zig.)
   */
   private void zig(Graphics2D g, int n)
   {
      int xNew, yNew;

      if (n == 1) {
         direction = turnLeft();
         xNew = newX();
         yNew = newY();
         Line2D.Double l = new Line2D.Double(x,y,xNew,yNew);
         g.draw(l);
         x = xNew;
         y = yNew;
         System.out.println(x + " " + y);

         direction = turnLeft();
         xNew = newX();
         yNew = newY();
         l = new Line2D.Double(x,y,xNew,yNew);
         g.draw(l);
         x = xNew;
         y = yNew;
         System.out.println(x + " " + y);
      }
      else
      {
         zig(g, n/2);
         zag(g, n/2);
         zig(g, n/2);
         zag(g, n/2);
      }
   }

   /*
   * Base case (n=1):
   *    draw the three line segments with a right turn and a
   *    left turn.
   * Recursive Case:
   *    Call zag, zag, zig, zag on n/2
   *    (Note the indirect recursion in the call to zig - which
   *     itself calls zag.)
   */
   private void zag(Graphics2D g, int n)
   {
      int xNew, yNew;

      if (n == 1) {
         direction = turnRight();
         xNew = newX();
         yNew = newY();
         Line2D.Double l = new Line2D.Double(x,y,xNew,yNew);
         g.draw(l);
         x = xNew;
         y = yNew;
        System.out.println(x + " " + y);

         direction = turnRight();
         xNew = newX();
         yNew = newY();
         l = new Line2D.Double(x,y,xNew,yNew);
         g.draw(l);
         x = xNew;
         y = yNew;
        System.out.println(x + " " + y);

         direction = turnLeft();
         xNew = newX();
         yNew = newY();
         l = new Line2D.Double(x,y,xNew,yNew);
         g.draw(l);
         x = xNew;
         y = yNew;
        System.out.println(x + " " + y);

      }
      else
      {
         zag(g, n/2);
         zag(g, n/2);
         zig(g, n/2);
         zag(g, n/2);
      }
   }

   /*
   * Initiate the drawing of the panel - with the two calls
   * to zig.
   */
   public void paint(Graphics g1)
   {
      Graphics2D g = (Graphics2D) g1;
      super.paint(g);
 
      zig(g, depth);
      zig(g, depth);
   }

}