import java.awt.Event; 
import zBuffer;

public class Lindenmeyer extends StereoImage implements Runnable
{
  Matrix TRAFO=new Matrix();
  XYZ OldPT,NewPT;
  int SIZE=100;
  int DEPTH=3;
  int LEAVES=3;
  float ANGLE=0.5f;
  float RADIUS=0.05f;
  float SCALEDOWN=0.6f;
  boolean DEFINE_LEAVES=false,DEFINE_ANGLE=false,DEFINE_RADIUS=false,
          DEFINE_SCALEDOWN=false;
  int PAUSE=2000;
  RGB Farbe=new RGB(0.5f,1f,0f);
  XYZ Zero=new XYZ(0f,0f,0f);
  XYZ ZM=new XYZ(0f,0f,-1f);
  XYZ ZP=new XYZ(0f,0f,1f);
  Thread engine=null;


public void init()
  {
    String param=getParameter("Size");
    SIZE=(param==null)?SIZE:Integer.parseInt(param);
    param=getParameter("Depth");
    DEPTH=(param==null)?DEPTH:Integer.parseInt(param);
    param=getParameter("Leaves");
    LEAVES=(param==null)?LEAVES:Integer.parseInt(param);
    DEFINE_LEAVES=(param==null)?false:true;
    param=getParameter("Angle");
    ANGLE=(param==null)?ANGLE:Float.valueOf(param).floatValue();
    DEFINE_ANGLE=(param==null)?false:true;
    param=getParameter("Radius");
    RADIUS=(param==null)?RADIUS:Float.valueOf(param).floatValue();
    DEFINE_RADIUS=(param==null)?false:true;
    param=getParameter("Scaledown");
    SCALEDOWN=(param==null)?SCALEDOWN:Float.valueOf(param).floatValue();
    DEFINE_SCALEDOWN=(param==null)?false:true;
    param=getParameter("Pause");
    PAUSE=(param==null)?PAUSE:Integer.parseInt(param);
    Resize(SIZE,SIZE);
    engine=new Thread(this);
    engine.start();
  }

public void Pflanze(int d)
  {
    int i;
    Cylinder(Zero,ZP,RADIUS,Farbe);
    if (d>0) {
      PushMatrix();
      Translate(ZP);
      Scale(SCALEDOWN);
      PushMatrix();
      for (i=0;i<LEAVES;i++) {
        RestoreMatrix();
        RotateZ((float)(i*2*Math.PI/LEAVES));
        RotateX(ANGLE);
        Pflanze(d-1);
      };
      PopMatrix();
      PopMatrix();
    };   
  }

public void DrawScene()
  {
    PushMatrix();
    Clear();
    Scale(2*(1-SCALEDOWN));
    Pflanze(DEPTH);
    PopMatrix();
  }

public void run()
  {
    while (true) {
      ClearMatrix();
      RotateX(1f);
      Translate(ZM);
      RotateZ((float)(2*Math.PI*Math.random()));
      RotateY((float)(Math.PI*Math.random()/6));
      if (!DEFINE_LEAVES) LEAVES=(int)(3.5*Math.random()+3);
      if (!DEFINE_ANGLE) ANGLE=(float)(Math.random()+0.5f);
      if (!DEFINE_RADIUS) RADIUS=(float)(Math.random()*0.04f+0.04f);
      if (!DEFINE_SCALEDOWN) SCALEDOWN=(float)(Math.random()*0.5f+0.25f);
      DrawScene();
      repaint();
      engine.suspend();
      try {
        Thread.sleep(PAUSE);
      } catch (InterruptedException e) {
      };
    };
  }

  public boolean handleEvent(Event evt) {
    if (evt.id == Event.MOUSE_DOWN) {
      if (engine != null && engine.isAlive()) {
            engine.resume();
        };
      };
    return(true);
  }
}
