import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.Math.*;
import javax.swing.*;
import javax.swing.event.*;
import com.sun.j3d.utils.universe.*;
import java.awt.GraphicsConfiguration;
import javax.media.j3d.*;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.geometry.Cone;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;

public class Heimen extends Anime3DApplet
{
    Yajirusi denryuSohen,vecP,denba,denbanormal;
    SurfaceElement se;
    Cylinder plate[];
    TransformGroup tg;
    HensuuSlider Z;
    GraphPanel graphCanvas;

    class HensuuSlider extends JPanel {
        int a;
        JLabel l;
        JSlider sl;
        String name;
        HensuuSlider(String s,int min, int max, int now){
            name =s;
            l = new JLabel(s);
            sl= new JSlider(min,max,now);
            sl.setSnapToTicks(true);
            a=now;
            setLayout(new BorderLayout());
            add("West",l);
            add("Center",sl);

            sl.addChangeListener(new ChangeListener() {
		public void stateChanged(ChangeEvent evt) {
                    Change();
		}
	    });
        }
        int get() { return(a); }
        double getD() { return((double)a); }

        public void set(int n) {
            sl.setValue(n);
            Change();
        }

        public void Change() {
            a= sl.getValue();
            String str=name;
            str = name + Integer.toString(a);
            l.setText(str);
	    ChangePlate();
        }
    }


    class SurfaceElement extends BranchGroup {
	Shape3D s;
	Appearance ap;
	TransformGroup tg;

	SurfaceElement(Material apm) {
	    ap=new Appearance();
	    ap.setMaterial(apm);

	    QuadArray polygon1 = new QuadArray (4, QuadArray.COORDINATES);		    
	    polygon1.setCoordinate(0,new Point3f(0f,0f,0f));
	    polygon1.setCoordinate(1,new Point3f(0f,0f,0f));
	    polygon1.setCoordinate(2,new Point3f(0f,0f,0f));
	    polygon1.setCoordinate(3,new Point3f(0f,0f,0f));
	    s=new Shape3D(polygon1,ap);
            setCapability(BranchGroup.ALLOW_DETACH);
	    addChild(s);
	}

	public void setCoordinate(
				  float x1,float y1, float z1,
				  float x2,float y2, float z2,
				  float x3,float y3, float z3,
				  float x4,float y4, float z4
				  ) {
	    QuadArray polygon1 = new QuadArray (4, QuadArray.COORDINATES);		    
	    polygon1.setCoordinate(0,new Point3f(x1,y1,z1));
	    polygon1.setCoordinate(1,new Point3f(x2,y2,z2));
	    polygon1.setCoordinate(2,new Point3f(x3,y3,z3));
	    polygon1.setCoordinate(3,new Point3f(x4,y4,z4));
	    s.setGeometry(polygon1);
            setCapability(BranchGroup.ALLOW_DETACH);

	    /*            tg= new TransformGroup();
            tg.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

	    tg.addChild(s);*/
	}
    }

    class Yajirusi extends BranchGroup {
        TransformGroup tg;
        Yajirusi(Material apma,float futosa) {          
            Appearance ap = new Appearance();
            ap.setMaterial(apma);
 

            Cylinder c=new Cylinder(futosa,0.8f,ap);
            Transform3D ts0=new Transform3D();
            ts0.setTranslation(new Vector3f(0.0f,0.4f, 0.0f));

            Cone cn=new Cone(futosa*2.0f,0.2f,ap);
            Transform3D ts1=new Transform3D();
            ts1.setTranslation(new Vector3f(0.0f, 0.9f, 0.0f));

            tg= new TransformGroup();
            tg.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            setCapability(BranchGroup.ALLOW_DETACH);
            TransformGroup tg0=new TransformGroup(ts0);
            tg0.addChild(c);

            TransformGroup tg1=new TransformGroup(ts1);
            tg1.addChild(cn);

            tg.addChild(tg0);
            tg.addChild(tg1);

            setCapability(BranchGroup.ALLOW_DETACH);

            addChild(tg);
        }

        public void setParameter(Vector3f p,Vector3f q){
            double vx=p.x-q.x;
            double vy=p.y-q.y;
            double vz=p.z-q.z;
            double rq=vx*vx+vz*vz;
            double a=Math.sqrt(rq+vy*vy);
            double angle1;
            if( vy==0.0 ) {
                angle1=-0.5*Math.PI;
            } else if( vy >0 ) {
                angle1=Math.atan(Math.sqrt(rq)/vy)+Math.PI;
            } else {
                angle1=Math.atan(Math.sqrt(rq)/vy);
            }
            double angle2=Math.atan2(vz,-vx);
            setParameter(p,a,angle1,angle2);
        }

        public void setParameter(Vector3f p, double a,double angle1, double angle2) {
            Transform3D tss=new Transform3D();
            tss.setScale(a);

            Transform3D ts0=new Transform3D();
            ts0.setTranslation(p);

            Transform3D ts1=new Transform3D();
            ts1.rotZ(angle1);

            Transform3D ts2=new Transform3D();
            ts2.rotY(angle2);

            ts0.mul(ts2);
            ts0.mul(ts1);
            ts0.mul(tss);

            tg.setTransform(ts0);
        }
    }



    public void ChangePlate()
    {
	Transform3D ts0=new Transform3D();
	ts0.setTranslation(new Vector3f(0.0f,0.01f*((float)Z.get()), 0.0f));
	tg.setTransform(ts0);
    }

    public void init() {
        super.init();
        Container cont=getContentPane();
        cont.setLayout(new BorderLayout());
                
        setStepTime(0.05);

	plate=new Cylinder[10];

	graphCanvas=new GraphPanel();
        JPanel p=new JPanel();

        Z=new HensuuSlider("Z=",20,100,60);

        p.setLayout(new GridLayout(2,1));

	p.setLayout(new BorderLayout());
        p.add(animePanel,"East");
        p.add(Z,"West");

        OrbitBehavior orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL);
        orbit.setSchedulingBounds(
            new BoundingSphere(new Point3d(0, 0, 0), 500.0));
        u.getViewingPlatform().setViewPlatformBehavior(orbit);
        
        
        DirectionalLight light1 = new DirectionalLight( true,
                                                        new Color3f(1.0f, 1.0f, 1.0f),
                                                        new Vector3f(0.0f, -1.0f, -1.0f));
        
        AmbientLight light2= new AmbientLight(new Color3f(1f,1f,1f));
        light1.setInfluencingBounds(new BoundingSphere(new Point3d(), 100.0));
        light2.setInfluencingBounds(new BoundingSphere(new Point3d(), 100.0));

        scene.addChild(light1);
        scene.addChild(light2);
        scene.addChild(new Background(1.0f,1.0f,1.0f));

	// $B@V(B
        Material apma = new Material();
        apma.setDiffuseColor(1.0f,0.0f,0.0f);
        apma.setAmbientColor(1.0f,0.0f,0.0f);


	// $B%^%<%s%?(B
        Material apma2 = new Material();
        apma2.setDiffuseColor(1.0f,0.0f,1.0f);
        apma2.setAmbientColor(1.0f,0.0f,1.0f);

	// $B%0%l!<(B
        Material apma3 = new Material();
        apma3.setDiffuseColor(0.7f,0.7f,0.7f);
        apma3.setAmbientColor(0.7f,0.7f,0.7f);

	// $B%7%"%s(B
        Material apma4 = new Material();
        apma4.setDiffuseColor(0.0f,1.0f,1.0f);
        apma4.setAmbientColor(0.0f,1.0f,1.0f);

	// $B2+?'(B
        Material apma5 = new Material();
        apma5.setDiffuseColor(1.0f,1.0f,0.0f);
        apma5.setAmbientColor(1.0f,1.0f,0.0f);

	se=new SurfaceElement(apma5);

	Appearance ap=new Appearance();
	ap.setMaterial(apma4);
	TransparencyAttributes ta =new TransparencyAttributes(TransparencyAttributes.BLENDED,0.8f);
	ap.setTransparencyAttributes(ta);
	int i;
	
	Transform3D ts0=new Transform3D();
	ts0.setTranslation(new Vector3f(0.0f,0.01f*((float)Z.get()), 0.0f));
	tg=new TransformGroup(ts0);
	tg.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
	tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

	for(i=0 ; i<10 ; i++ ) {
	    plate[i]=new Cylinder(0.1f*(i+1),0.01f,ap);
	    tg.addChild(plate[i]);
	}
	scene.addChild(tg);
	// $BEE>l%Y%/%H%k(B
        denba=new Yajirusi(apma,0.01f);
	// $BEE>l%Y%/%H%k$NK!@~@.J,(B
        denbanormal=new Yajirusi(apma2,0.01f);
	// $B9M$($F$$$kLL$N0LCV%Y%/%H%k(B
        vecP=new Yajirusi(apma3,0.005f);


        u.addBranchGraph(scene);

	JPanel pc=new JPanel();
	pc.setLayout(new GridLayout(1,2));

        pc.add("East",canvas);
	pc.add("West",graphCanvas);

        cont.add("South",p);
        cont.add("Center",pc);

	stepT=1.0;
        tm.start();
        start();
    }


    class GraphPanel extends JPanel {
	public void paintComponent(Graphics gc){
	    int Time=(int)t;
	    int RR=Time/15;
	    int Th=Time%15;

	    int w=getWidth();
	    int h=getHeight();
	    gc.setColor(Color.WHITE);
	    gc.fillRect(0,0,w,h);
	    
	    gc.setColor(Color.BLACK);

	    int hh;
	    int i;
	    float r,rr;
	    float z=0.01f*Z.get();

	    for( i=0 ; i<10 ; i++ ) {
		r=i*0.10f+0.05f;
		rr=r*r+z*z;
		hh=(int)(r*h*0.2f*z/Math.sqrt(rr*rr*rr));
		gc.drawRect(w/10*i,h-hh,w/10,hh);
	    }

	    gc.setColor(Color.GREEN);
	    r=RR*0.10f+0.05f;
	    rr=r*r+z*z;
	    hh=(int)(r*h*0.2f*z/Math.sqrt(rr*rr*rr));
	    int hh2=(int)(r*h*0.2f*z/Math.sqrt(rr*rr*rr)*Th/15f);
	    int hh3=hh/15;
	    if( hh3 < 1 ) { hh3=1;}

	    gc.fillRect(w/10*RR,h-hh2-hh/15,w/10,hh3);


	    int py=0;
	    int py1=(int)(h*0.05f/(z*z));
	    int py2=py1;
	    int y,y1,y2;

	    for(i=1; i< w; i++ ) {
		r=((float)i)/((float)w);
		gc.setColor(Color.BLUE);
		rr=r*r+z*z;
		y=(int)(r*h*0.2f*z/Math.sqrt(rr*rr*rr));
		gc.drawLine(i-1,h-py,i,h-y);
		py=y;

		gc.setColor(Color.RED);
		y1=(int)(h*0.05f/rr);
		gc.drawLine(i-1,h-py1,i,h-y1);
		py1=y1;

		gc.setColor(Color.MAGENTA);
		y2=(int)(h*0.05f*z/Math.sqrt(rr*rr*rr));
		gc.drawLine(i-1,h-py2,i,h-y2);
		py2=y2;
	    }

	}
    }

    public void writeCanvas() {
	se.detach();
        denba.detach();
        denbanormal.detach();
        vecP.detach();

	int Time=(int)t;
	int RR=Time/15;
	int Theta=Time%15;

	if( RR > 9 ) {
	    t=0;
	    Time=0;
	    RR=0;
	    Theta=0;
	}


	float r=RR*0.10f;
        double angle=((double)Theta-0.5)/7.5*Math.PI;
        double angle1=((double)Theta+0.5)/7.5*Math.PI;
	float r1=(RR+1)*0.10f;
	float z=0.01f*Z.get()+0.02f;

    	se.setCoordinate (
			  (float)(r1*Math.sin(angle)), z, (float)(r1*Math.cos(angle)),
			  (float)(r1*Math.sin(angle1)), z, (float)(r1*Math.cos(angle1)),
			  (float)(r*Math.sin(angle1)), z, (float)(r*Math.cos(angle1)),
			  (float)(r*Math.sin(angle)), z, (float)(r*Math.cos(angle))
			  );

        angle=((double)Theta)/7.5*Math.PI;
	r=RR*0.10f+0.05f;

	Vector3f origin=new Vector3f(0.0f,0.0f,0.0f);

        Vector3f P=new Vector3f((float)(r*Math.sin(angle)),0.01f*((float)Z.get()),(float)(r*Math.cos(angle)));
	float Plen=P.length();

        Vector3f vecE=new Vector3f(P);
	vecE.scale(0.3f/(Plen*Plen*Plen));
	Vector3f vecEN=new Vector3f(vecE);
	vecEN.x=0.0f;
	vecEN.z=0.0f;
	
	vecE.add(P);
	vecEN.add(P);

        vecP.setParameter(origin,P);
	denba.setParameter(P,vecE);
	denbanormal.setParameter(P,vecEN);

        scene.addChild(vecP);
        scene.addChild(denba);
        scene.addChild(denbanormal);

	scene.addChild(se);
        canvas.startRenderer();
	repaint();
	//graphCanvas.paintComponent(graphCanvas.getGraphics());
    }
}

