/************************************************
Grundlegende Algorithmen mit Java,
http://algorithmen-und-problemloesungen.de/
Copyright @2007-2008 by Doina Logofatu
************************************************/

import java.awt.*;
import java.io.*;
import java.util.*;

import javax.swing.*;

public class P12Koch extends JPanel {

  /* Because implements Serializable */
  private static final long serialVersionUID = 7412004320518032437L;

  private static final double SQRT3 = Math.sqrt(3.0);
  private static final double SQRT3DIV6 = Math.sqrt(3.0) / 6.0;

  private static final String FileInputName = "iteration.in";

  private int iterations;

  public P12Koch(int numIterations) {
    this.iterations = numIterations;
  }

  public void paint(Graphics g) {
    Dimension rect = this.getSize();
    int diff = rect.width - rect.height;
    PaintInvariant paintInv = new PaintInvariant(g, 5);
    int l;
    if (diff < 0) {
      diff *= -1;
      l = rect.width / 2;
      paintInv.dx = 0;
      paintInv.dy = diff / 2;
    } else {
      l = rect.height / 2;
      paintInv.dx = diff / 2;
      paintInv.dy = 0;
    }

    double xa, ya, xb, yb, t = l;
    xa = l;
    ya = l - t;
    xb = l - SQRT3 * t / 2;
    yb = l + t / 2;
    drawKoch(paintInv, this.iterations, (int) xa, (int) ya, (int) xb, (int) yb);
    xa = l + SQRT3 * t / 2;
    ya = l + t / 2;
    drawKoch(paintInv, this.iterations, (int) xb, (int) yb, (int) xa, (int) ya);
    xb = l;
    yb = l - t;
    drawKoch(paintInv, this.iterations, (int) xa, (int) ya, (int) xb, (int) yb);
  }

  private void drawKoch(PaintInvariant paintInv, int n, double xa, double ya,
      double xb, double yb) {
    if (n > 1) {
      double xc, yc, xm, ym, xd, yd;
      xm = (xa + xb) / 2 + SQRT3DIV6 * (ya - yb);
      ym = (ya + yb) / 2 + SQRT3DIV6 * (xb - xa);
      xc = (2 * xa + xb) / 3;
      yc = (2 * ya + yb) / 3;
      xd = (xa + 2 * xb) / 3;
      yd = (ya + 2 * yb) / 3;
      drawKoch(paintInv, n - 1, xa, ya, xc, yc);
      drawKoch(paintInv, n - 1, xc, yc, xm, ym);
      drawKoch(paintInv, n - 1, xm, ym, xd, yd);
      drawKoch(paintInv, n - 1, xd, yd, xb, yb);
    } else {
      paintInv.g.drawLine((int) xa, (int) ya, (int) xb, (int) yb);
    }

  }

  public static void main(String args[]) throws IOException {
    Scanner sc = new Scanner(new File(FileInputName));
    int numIterations;
    try {
      numIterations = sc.nextInt();

      JFrame frame = new JFrame("Rekursivitaet Beispiel");
      P12Koch quadratePanel = new P12Koch(numIterations);
      frame.getContentPane().add(quadratePanel);
      quadratePanel.setPreferredSize(new Dimension(400, 400));
      frame.pack();
      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

      // put the frame on the center of the screen
      Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
      Dimension frameDim = frame.getSize();
      frame.setLocation((screenDim.width - frameDim.width) / 2,
          (screenDim.height - frameDim.height) / 2);

      // display the frame
      frame.setVisible(true);

    } finally {
      sc.close();
    }
  }
}


class PaintInvariant {
  Graphics g;

  int dx, dy, minL;

  PaintInvariant(Graphics g, int minL) {
    this.g = g;
    this.minL = minL;
  }
}

