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 LineCharge extends Anime3DApplet
{
    Yajirusi vecP,denba,denbanormal;
    Line line;
    LineElement lineElement;

    int N;

    TransformGroup tg;

    HensuuSlider L,Z,Num;
    JCheckBox cbS;
    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);
        }
    }

    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 init() {
        super.init();
	N=64;
        Container cont=getContentPane();
        cont.setLayout(new BorderLayout());
                
	graphCanvas=new GraphPanel();
        JPanel p=new JPanel();

        Z=new HensuuSlider("X=",15,80,36);
        L=new HensuuSlider("L=",10,200,100);
        Num=new HensuuSlider("N=",8,200,25);

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

        JPanel p1=new JPanel();
        p.add(animePanel);
        p.add(p1);
        p1.add(Z);
	p1.add(L);
	p1.add(Num);

        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);


	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);

	scene.addChild(tg);
	// $BEE>l%Y%/%H%k(B
        denba=new Yajirusi(apma,0.02f);
	// $BEE>l%Y%/%H%k$NK!@~@.J,(B
        denbanormal=new Yajirusi(apma2,0.02f);
	// $B9M$($F$$$kLL$N0LCV%Y%/%H%k(B
        vecP=new Yajirusi(apma3,0.005f);

	line=new Line();

	scene.addChild(line);

	lineElement=new LineElement(0.011f,1f);
	scene.addChild(lineElement);

        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 Line extends BranchGroup {
	Cylinder cyl;
	Transform3D ts;
	TransformGroup tg;
	Line() {
	    cyl=new Cylinder(0.01f,1f);

	    Material apma5 = new Material();
	    apma5.setDiffuseColor(1.0f,1.0f,0.0f);
	    apma5.setAmbientColor(1.0f,1.0f,0.0f);
	    
	    Appearance ap2=new Appearance();
	    ap2.setMaterial(apma5);
	    cyl.setAppearance(ap2);

	    tg= new TransformGroup();
	    tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	    tg.addChild(cyl);
            setCapability(BranchGroup.ALLOW_DETACH);

	    addChild(tg);

	}
	public void setParameter() {
	    ts=new Transform3D();
	    ts.setScale(new Vector3d(1.0,0.01*((double)L.get()),1.0));
	    tg.setTransform(ts);
	}
    }


    class LineElement extends BranchGroup{
	TransformGroup tg;
	Transform3D ts2;
	Transform3D ts1;
	Cylinder cyl;
	LineElement(float r,float h) {
	    Appearance ap=new Appearance();
	    Material apma3 = new Material();
	    apma3.setDiffuseColor(0f,1f,0f);
	    apma3.setAmbientColor(0f,1f,0f);
	    ap.setMaterial(apma3); 
	    cyl=new Cylinder(r,h,ap);
	    tg= new TransformGroup();
	    tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	    tg.addChild(cyl);
            setCapability(BranchGroup.ALLOW_DETACH);

	    addChild(tg);
	}

	public void setCoordinate(float z,int nn) {
	    ts1=new Transform3D();
	    ts1.setScale(new Vector3d(1.0,((double)L.get())*0.01/((double)nn),1.0));

	    ts2=new Transform3D();
	    ts2.setTranslation(new Vector3f(0.0f,z, 0.0f));
	    ts2.mul(ts1);
	    tg.setTransform(ts2);

	}
    }

    class GraphPanel extends JPanel {
	public void paintComponent(Graphics gc){
	    int Time=(int)t;
	    int n=Time%N;

	    line.setParameter();
	    N=Num.get();
	    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 z;
	    float x=0.01f*Z.get();
	    float rr;
	    float l=((float)L.get())*0.01f;
	    

	    for( i=0 ; i<N ; i++ ) {
		z=((float)i+0.5f)*l/((float)N)-0.5f*l;
		rr=x*x+z*z;
		hh=(int)(x*h*0.1f/Math.sqrt(rr*rr*rr));
		gc.drawRect(w*i/N,h-hh,w/N,hh);
	    }

	    gc.setColor(Color.MAGENTA);	
	    z=((float)n+0.5f)*l/N-0.5f*l;
	    rr=x*x+z*z;
	    hh=(int)(x*h*0.1f/Math.sqrt(rr*rr*rr));
	    gc.fillRect(w*n/N,h-hh,w/N,hh);

	    rr=x*x+4f;
	    int py=h-(int)(x*h*0.1f/Math.sqrt(rr*rr*rr));
	    int y;
	    for(i=1; i<w ; i++ ) {
		z=((float)i)*l/((float)w)-0.5f*l;
		rr=x*x+z*z;
		y=h-(int)(x*h*0.1f/Math.sqrt(rr*rr*rr));
		gc.drawLine(i-1,py,i,y);
		py=y;
	    }


	    gc.setColor(Color.RED);	
	    rr=x*x+l*l*0.25f;
	    py=h-(int)(h*0.1f/rr);
	    for(i=1; i<w ; i++ ) {
		z=((float)i)*l/((float)w)-0.5f*l;
		rr=x*x+z*z;
		y=h-(int)(h*0.1f/rr);
		gc.drawLine(i-1,py,i,y);
		py=y;
	    }


	}
    }

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

	int Time=(int)t;
	int n=Time%N;

	float l=(float)(L.get())*0.01f;

	float z1=((float)n)*l/((float)N)-l*0.5f;
	float z2=((float)(n+1))*l/((float)N)-l*0.5f;

    	lineElement.setCoordinate((z1+z2)*0.5f,N);

	Vector3f origin=new Vector3f(0.0f,(z1+z2)*0.5f,0.0f);

        Vector3f P=new Vector3f(0.01f*((float)Z.get()),0.0f,0.0f);

	Vector3f PO=new Vector3f(P);

	PO.sub(origin);

	float Plen=PO.length();

        Vector3f vecE=new Vector3f(PO);

	vecE.scale((float)(0.1f/(Plen*Plen*Plen)));

	Vector3f vecEN=new Vector3f(vecE);

	vecEN.y=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(lineElement);

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

