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 BiotSavart extends Anime3DApplet
{


    Ring ring;
    Yajirusi denryuSohen,vecP,jiba;
    HensuuSlider X,Z;
    JCheckBox cbS;


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

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

    class Ring extends BranchGroup{
        TransformGroup tg;
        Ring(int N) {
            float r=0.48f;
            float w=0.06f;
            float sr=r-w;

            Point3d v[]= new Point3d[N*16];
            Vector3f n[]= new Vector3f[N*16];

            int i;

            v[0]=new Point3d(sr,0f,0f);
            v[1]=new Point3d(r,0f,0f);
            v[N*4-2]=new Point3d(r,0f,0f);
            v[N*4-1]=new Point3d(sr,0f,0f);

            v[4*N]=new Point3d(r,w,0f);
            v[4*N+1]=new Point3d(sr,w,0f);
            v[N*8-2]=new Point3d(sr,w,0f);
            v[N*8-1]=new Point3d(r,w,0f);

            v[N*8]=new Point3d(r,0f,0f);
            v[N*8+1]=new Point3d(r,w,0f);
            v[N*12-2]=new Point3d(r,w,0f);
            v[N*12-1]=new Point3d(r,0f,0f);

            v[N*12]=new Point3d(sr,w,0f);
            v[N*12+1]=new Point3d(sr,0f,0f);
            v[N*16-2]=new Point3d(sr,0f,0f);
            v[N*16-1]=new Point3d(sr,w,0f);

            for( i=1 ; i< N ; i++ ) {
                double cosi=Math.cos(i*2.0*Math.PI/N);
                double sini=Math.sin(i*2.0*Math.PI/N);

                v[i*4+1]=v[i*4-2]=new Point3d(r*cosi,0f,r*sini);
                v[i*4]=v[i*4-1]=new Point3d(sr*cosi,0f,sr*sini);

                v[(i+N)*4+1]=v[(i+N)*4-2]=new Point3d(sr*cosi,w,sr*sini);
                v[(i+N)*4]=v[(i+N)*4-1]=new Point3d(r*cosi,w,r*sini);

                v[(i+2*N)*4-2]=new Point3d(r*cosi,w,r*sini);
                v[(i+2*N)*4-1]=new Point3d(r*cosi,0f,r*sini);
                v[(i+2*N)*4]=v[(i+2*N)*4-1];
                v[(i+2*N)*4+1]=v[(i+2*N)*4-2];

                v[(i+3*N)*4-2]=new Point3d(sr*cosi,0f,sr*sini);
                v[(i+3*N)*4-1]=new Point3d(sr*cosi,w,sr*sini);
                v[(i+3*N)*4]=v[(i+3*N)*4-1];
                v[(i+3*N)*4+1]=v[(i+3*N)*4-2];

            }
            for( i=0 ; i< 4*N ; i++ ) {
                n[i]=new Vector3f(0f,-1f,0f);
                n[i+4*N]=new Vector3f(0f,1f,0f);
            }
            for( i=0 ; i< N ; i++ ) {
                n[8*N+i*4]=new Vector3f(
                    -(float)Math.sin((i*2.0+1.0)*Math.PI/N),
                    0f,
                    (float)Math.cos((i*2.0+1.0)*Math.PI/N));
                n[8*N+i*4+1]= n[8*N+i*4];
                n[8*N+i*4+2]= n[8*N+i*4];
                n[8*N+i*4+3]= n[8*N+i*4];
                n[12*N+i*4]=new Vector3f(
                    (float)Math.sin((i*2.0+1.0)*Math.PI/N),
                    0f,
                    -(float)Math.cos((i*2.0+1.0)*Math.PI/N));
                n[12*N+i*4+1]=n[12*N+i*4];
                n[12*N+i*4+2]=n[12*N+i*4];
                n[12*N+i*4+3]=n[12*N+i*4];
            }

            QuadArray geometry = new QuadArray(v.length, 
                                               GeometryArray.COORDINATES| QuadArray.NORMALS);
            geometry.setCoordinates(0, v);
            geometry.setNormals(0,n);

            Shape3D shape = new Shape3D(geometry);
            Appearance ap = new Appearance();
            Material m = new Material();
            m.setDiffuseColor(0.5f,0.5f,0.5f);
            ap.setMaterial(m);
            TransparencyAttributes ta =new TransparencyAttributes(TransparencyAttributes.BLENDED,0.5f);
            ap.setTransparencyAttributes(ta);
            shape.setAppearance(ap);

            tg= new TransformGroup();
 
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            tg.addChild(shape);        
            addChild(tg);
        }
        public void setCoord(float y)
        {
            Transform3D ts0=new Transform3D();
            ts0.setTranslation(new Vector3f(0.0f, y, 0.0f));
            tg.setTransform(ts0); 
        }
    }

    class Surface {
        QuadArray geometry;
        Apperance app;
        Surface(Color3f c,Apperance ap) {
            app=ap;
            geometry= new QuadArray(4,GeometryArray.COORDINATES | GeometryArray.COLOR_3);
            colors=new Color3f[4];
            colors[0]=c;
            colors[1]=c;
            colors[2]=c;
            colors[3]=c;
        }
        setParamater(Point3d p,Point3d a,Point3d b) {
            shape.detach(); // $B8E$$$N$r<h$j30$9!#(B
            Point3d[] vertex=new Point3d[8];
            vertex[0]=p;
            vertex[1]=new Point3d(p.x+a.x,p.y+a.y,p.z+a.z);
            vertex[2]=new Point3d(p.x+a.x+b.x,p.y+a.y+b.y,p.z+a.z+b.z);
            vertex[3]=new Point3d(p.x+b.x,p.y+b.y,p.z+b.z);
            geometry.setCoordinates(0,vertex);
            geometry.setColor(0,colors);
            shape = new Shape3D(geometry,ap);
            scene.addchild(shape);
        }
    }


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

        setStepTime(0.05);

        JPanel p=new JPanel();

        X=new HensuuSlider("X=",0,70,0);
        Z=new HensuuSlider("Z=",-30,70,30);

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

        cbS=new JCheckBox("$B30@Q$rI=<($9$k(B",false);

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

        OrbitBehavior orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL);
        orbit.setSchedulingBounds(
            new BoundingSphere(new Point3d(0, 0, 0), 100.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));

        //        jishaku=new Jishaku();
        //scene.addChild(jishaku);

        Material apma = new Material();
        apma.setDiffuseColor(0.0f,0.5f,0.0f);
        apma.setAmbientColor(0.0f,0.5f,0.0f);

        denryuSohen=new Yajirusi(apma,0.07f);

        Material apma2 = new Material();
        apma2.setDiffuseColor(0.7f,0.7f,0.7f);
        apma2.setAmbientColor(0.7f,0.7f,0.7f);

        Material apma3 = new Material();
        apma3.setDiffuseColor(0.0f,0.0f,0.7f);
        apma3.setAmbientColor(0.0f,0.0f,0.7f);

        vecP=new Yajirusi(apma2,0.01f);
        jiba=new Yajirusi(apma3,0.04f);
        ring=new Ring(10);
        ring.setCoord(-0.35f);

        scene.addChild(ring);
        //        scene.addChild(charges);
        

        u.addBranchGraph(scene);


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

        tm.start();
        start();
    }

    public void writeCanvas() {
        double angle=t;
        jiba.detach();
        denryuSohen.detach();
        vecP.detach();
        Vector3f sohenP=new Vector3f((float)(0.45*Math.sin(angle)),-0.3f,(float)(0.45*Math.cos(angle)));
        Vector3f Idx=new Vector3f((float)(0.2*Math.cos(angle)),0.00f,(float)(-0.2*Math.sin(angle)));
        Vector3f kansokuP=new Vector3f(0.01f*X.get(),0.01f*Z.get()-0.3f,0.0f);
        Vector3f IP=new Vector3f(
            Idx.x+sohenP.x,
            Idx.y+sohenP.y,
            Idx.z+sohenP.z);
        denryuSohen.setParameter(sohenP,IP);
        vecP.setParameter(sohenP,kansokuP);
        Vector3f gaiseki=new Vector3f();
        Vector3f xxdash=new Vector3f(kansokuP.x-sohenP.x,
                                     kansokuP.y-sohenP.y,
                                     kansokuP.z-sohenP.z
                                     );
        gaiseki.cross(Idx,xxdash);
        float r=xxdash.length();
        r=r*r*r*5f;
        Vector3f B=new Vector3f(
            gaiseki.x/r+kansokuP.x,
            gaiseki.y/r+kansokuP.y,
            gaiseki.z/r+kansokuP.z);
        
        jiba.setParameter(kansokuP,B);
        scene.addChild(denryuSohen);
        scene.addChild(vecP);
        scene.addChild(jiba);
        canvas.startRenderer();
    }
}

