import vrml.*;
import vrml.field.*;
import vrml.node.*;
import java.lang.*;

public class Fractal3 extends Script{

  // Declare attributes
     private int x = 0;
     private int y = 0;
     private int z = 0;
     private int rad = 10;
     private int ht = 10;
     private int cpt = 0;
     private BaseNode myNode[];
     private SFBool start;
     private Browser myBrowser;

     private float txinit=0;
     private float tzinit=0;

  // Declare fields

  // Declare eventOut
     private MFNode nodes;

  // Set up fields and eventOut
  public void initialize() {
    myBrowser = getBrowser();
    nodes = (MFNode)getEventOut("newNode");
    System.out.println("Fractal: initialize() ");
  }

  public String Recursive_cylinder(float cpt, float tx, float ty, float tz, float rx, float ry, float rz, float ang, float rad, float ht) {

    String noeud="";
    float H, htmp, R, Delta;
    int NbBranche, i;

    if (cpt <= 0)
    {
      // return "Transform { translation "+tx+" "+ty+" "+tz+" scale 0.2 1 0.7 rotation "+(rx+Math.PI*0.5)+" "+ry+" "+rz+" "+ang+" children [Shape { appearance Appearance { material Material { diffuseColor 0.2 0.8 0.5 specularColor 1 1 1 ambientIntensity 0.7 }} geometry Cylinder {radius 1.5   height 0.001}}]} ";
      return "Transform { translation "+tx+" "+ty+" "+tz+" rotation "+rx+" "+ry+" "+rz+" "+ang+" children [Shape {appearance Appearance { material Material { diffuseColor 0.1 0.6 0.3 specularColor 1 1 1 shininess 0.4 }}geometry Cylinder {radius "+rad+" height "+ht+"}}]} ";
    } else {
        noeud = "Transform { translation "+tx+" "+ty+" "+tz+" rotation "+rx+" "+ry+" "+rz+" "+ang+" children [Shape {appearance Appearance { material Material { diffuseColor 0.6 0.4 0.2 specularColor 1 1 1 shininess 0.4 }}geometry Cylinder {radius "+rad+" height "+ht+"}} ";

        htmp = (float)(ht/2.0);

	// Cylindre
        if (ht <= (float)0.5) ht = (float)0.5;
	else ht = (float)(2.0*ht/3.0);
	if (rad <= (float)0.2) rad = (float)0.2;
	else rad = (float)(2.0*rad/3.0);

        NbBranche = (int)(Math.random()*2.2)+3; 

        ry = (float)0.0;

        Delta = (float)(2*Math.PI/NbBranche);

        for(i=0; i<NbBranche; i++)
        {
          ang = (float)(Math.random()*Math.PI*0.3+Math.PI*0.1);

          H = (float)(ht/2.0 * Math.sin(ang));
	  ty = htmp + (float)(ht/2.0 * Math.cos(ang));

          R = (float)(1.0 - (Math.random()-0.5)*0.5);
          rx = (float)Math.cos(i*Delta*R);
          rz = -(float)Math.sin(i*Delta*R);

          tx = -rz*H;
          tz = rx*H;

          R = (float)(1.0 - (Math.random()-0.5)*0.3);
          noeud = noeud + Recursive_cylinder(cpt-1,tx,ty,tz,rx,ry,rz,ang,rad*R,ht*R);
        }

        NbBranche = (int)(Math.random()*2); 

        Delta = (float)(2*Math.PI/NbBranche);
        for(i=0; i<NbBranche; i++)
        {
          if (ht <= (float)0.5) ht = (float)0.5;
      	  else ht = (float)(2.0*ht/3.0);
	  if (rad <= (float)0.2) rad = (float)0.2;
	  else rad = (float)(2.0*rad/3.0);

          H = (float)(ht/2.0 * Math.sin(ang));
	  ty = (float)(ht/2.0 * Math.cos(ang));

          R = (float)(1.0 - (Math.random()-0.5)*0.5);
          rx = (float)Math.cos(i*Delta*R);
          rz = -(float)Math.sin(i*Delta*R);

          tx = -rz*H;
          tz = rx*H;
          noeud = noeud + Recursive_cylinder(cpt-2,tx,ty,tz,rx,ry,rz,ang,rad,ht);
        } 
        return noeud + "]}";
     }
  }      
      
  // Handle events
  public void processEvent(Event event) {

    String noeud = "";

    if (event.getName().equals("start")) {
      if ((((ConstSFBool)event.getValue()).getValue()) == true) {

          System.out.println("Generation en cours.");

          txinit += 15;
          //tzinit += 0;

	  noeud = noeud + Recursive_cylinder(4,txinit,0,tzinit,0,1,0,0,1,10);
	  System.out.println("..........");
	  try {
	    myNode = myBrowser.createVrmlFromString(noeud);
	  } catch (InvalidVRMLSyntaxException e) {
	    System.out.println("vrml.InvalidVRMLSyntaxException");
	    return;
	  }
	  System.out.println(myNode.length);
	  System.out.println(myNode.toString());
	  nodes.addValue(myNode[0]);
          System.out.println("Generation terminee.");
      }
    }
  }
}
