import Jama.*;
import Jama.util.*;


import java.applet.Applet;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class PrismaticPoles extends Object {

   private Group group;

   public PrismaticPoles(int zoom, int n, int h, int v, double H) {

		double Cv = Math.cos(2*v*Math.PI/n);
		double Sv = Math.sin(2*v*Math.PI/n);
		double Ch = Math.cos(2*h*Math.PI/n);
		double Sh = Math.sin(2*h*Math.PI/n);
		double C = Math.cos(2*Math.PI/n);
		double S = Math.sin(2*Math.PI/n);
		
		double[][] Xa = {{0}, {0}, {0}};
		Xa[0][0] = Cv - 1 + Math.sqrt(2-2*Cv);
		Xa[1][0] = Sv;
		double r = Math.sqrt(Math.pow(Xa[0][0],2) + Math.pow(Xa[1][0],2));
		Xa[0][0] = Xa[0][0]/r;
		Xa[1][0] = Xa[1][0]/r;
		Xa[2][0] = H/2;
        Matrix X = new Matrix(Xa);
        
        
      	Matrix A = new Matrix(3,3);
      	A.set(0, 0, C);
      	A.set(0, 1, -S);
      	A.set(1, 0, S);
      	A.set(1, 1, C);
      	A.set(2, 2, 1);

      	Matrix B = new Matrix(3,3);
      	B.set(0, 0, 1);
      	B.set(1, 1, -1);
      	B.set(2, 2, -1);
      	
      	Matrix V = new Matrix(3,3);
      	V.setMatrix(0,2,0,2, MatrixPower(A,v).times(B));      	

      // Define colors
      Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
      Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
      Color3f red   = new Color3f(1.0f, 0.0f, 0.0f);
      Color3f green = new Color3f( 0.0f, 1.0f, 0.0f );

      Color3f ambient = new Color3f(0.25f, 0.25f, 0.25f);
      Color3f diffuse = new Color3f(0.7f, 0.7f, 0.7f);
      Color3f specular = new Color3f(0.9f, 0.9f, 0.9f);
      Color3f ambientRed = new Color3f(0.2f, 0.05f, 0.0f);
      Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);

      // Appearance app;
      // Create the pole appearance
      Material poleMaterialCable1 =
         new Material(ambient, red, diffuse, specular, 110.f);
      Material poleMaterialCable2 =
         new Material(ambient, green, diffuse, specular, 110.f);
      poleMaterialCable1.setLightingEnable(true);
      Appearance aCable1 = new Appearance();
      aCable1.setMaterial(poleMaterialCable1);
      Appearance aCable2 = new Appearance();
      aCable1.setMaterial(poleMaterialCable2);

      Material poleMaterialStrut =
         new Material(ambient, black, diffuse, specular, 110.f);
      poleMaterialStrut.setLightingEnable(true);
      Appearance aStrut = new Appearance();
      aStrut.setMaterial(poleMaterialStrut);

      group = new Group();
      double[] px0={0,0,0}; double[] pxh1={0,0,0}; double[] pxh2={0,0,0};
      double[] pxv={0,0,0}; double[] pxs={0,0,0};
      Matrix X0 = new Matrix(3,1);
      Matrix Xh1 = new Matrix(3,1);
      Matrix Xh2 = new Matrix(3,1);
      Matrix Xv = new Matrix(3,1);
      Matrix Xs = new Matrix(3,1);
      Matrix G = new Matrix(3,3);
      for(int i=0;i<n;i++)
      	for(int j=0;j<2;j++){
      			G.setMatrix(0,2,0,2, MatrixPower(A,i));
      			G.setMatrix(0,2,0,2, G.times(MatrixPower(B,j)));
      			X0.setMatrix(0,2,0,0, G.times(X));
      			Xh1.setMatrix(0,2,0,0, G.times(MatrixPower(A,h)).times(X));
      			Xh2.setMatrix(0,2,0,0, G.times(MatrixPower(A,h).inverse()).times(X));
      			Xv.setMatrix(0,2,0,0, G.times(V).times(X));
      			Xs.setMatrix(0,2,0,0, G.times(B).times(X));

      			for(int p=0;p<3;p++){
      				px0[p] = X0.get(p,0)*zoom;
      				pxh1[p] = Xh1.get(p,0)*zoom;
      				pxh2[p] = Xh2.get(p,0)*zoom;
      				pxv[p] = Xv.get(p,0)*zoom;
      				pxs[p] = Xs.get(p,0)*zoom;
      			}

      			//OutPutMatrix(X0);
      			//OutPutArray(px0);
      			Point3d pX0 = new Point3d(px0);
      			Point3d pXh1 = new Point3d(pxh1);
      			Point3d pXh2 = new Point3d(pxh2);
      			Point3d pXv = new Point3d(pxv);
      			Point3d pXs = new Point3d(pxs);
        		CylinderCreator cylinder = new CylinderCreator(pX0, pXs, 1, aStrut);
    	   		group.addChild(cylinder.getShape());
        		CylinderCreator cylinder1 = new CylinderCreator(pX0, pXh1, 0.25, aCable1);
    	   		group.addChild(cylinder1.getShape());
        		CylinderCreator cylinder2 = new CylinderCreator(pX0, pXh2, 0.25, aCable1);
    	   		group.addChild(cylinder2.getShape());
        		CylinderCreator cylinder3 = new CylinderCreator(pX0, pXv, 0.25, aCable2);
    	   		group.addChild(cylinder3.getShape());

      			mySphere sphere = new mySphere(px0[0], px0[1], px0[2], 3, aStrut);
    	   		group.addChild(sphere.getShape());
      		}

        //myCylinder c = new myCylinder(point, 1.0f, appearance);

     }

   public Group getChild() {
      return group;
   }


    public Matrix MatrixPower(Matrix A, int p){
   		int m = A.getRowDimension();
   		int n = A.getColumnDimension();
   		Matrix B = Matrix.identity(m,n);
   		if(p>0)
   			for(int i=0;i<p;i++)
				B.setMatrix(0,A.getRowDimension()-1,0,A.getColumnDimension()-1,B.times(A));

		return B;
   }
}

