import javax.swing.*;
import org.math.plot.*;
import static java.lang.Math.*;
import static org.math.array.DoubleArray.*;
import visad.*;
import visad.java3d.DisplayImplJ3D;
import visad.java2d.DisplayImplJ2D;
import java.rmi.RemoteException;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class triangular_grid1
{
public triangular_element1 te[];
public setElement se[];
public int N,M,K,K1,K2,Nm1,Mm1;
public double x[][];
public double y[][];
public double T[][];
public double Ti[];
public double xi[];
public double yi[];
public boolean bi[];
public double dx,dy;
public int Bx0[],BxM[],By0[],ByN[];
public double L,W;
public double min(double xi[][])
{ double min=1e200;
  for(int i=0;i<xi.length;i++)
   {for(int j=0;j<xi[0].length;j++)
     {if(xi[i][j]<min) min=xi[i][j];}
 }
 return min;
}
public double max(double xi[][])
{double max=-1e200;
 for(int i=0;i<xi.length;i++)
 {for(int j=0;j<xi[0].length;j++)
   {if(xi[i][j]<max) max=xi[i][j];}
 }
 return max;
}
public triangular_grid1(double xi[][],double yi[][],double zi[][])
{x=xi;
 y=yi;
 T=zi;
 N=x.length-1;
 M=x[0].length-1;
 L=max(xi);
 W=max(yi);
 setElements();
}

public void generateTriangularGrid(double Li, double Wi,int Ni, int Mi,double zi[][])
{int i,j;
 N=Ni;M=Mi;
 L=Li;
 W=Wi;
 x=new double[N+1][M+1];
 y=new double[N+1][M+1];
 T=zi;
 setElements();
}

public void setElements()
{ int i,j;
 dx=L/M;
 dy=W/N;
 K=M*N;
 K1=K*2;
 K2=K1+1;
 //grid points
 xi=new double[K2];
 yi=new double[K2];
 Ti=new double[K2];
 bi=new boolean[K2];
 se=new setElement[K2];
 for(i=0;i<K2;i++) {se[i]=new setElement();}
 te=new triangular_element1[K1]; 
 int k1=-1,k=0,n=0,m=0;
for(n=0;n<=N;n++)
{ for(m=0;m<=M;m++)
  {k=(N+1)*n+m;
   x[n][m]=m*dx;y[n][m]=n*dy;
   xi[k]=x[n][m];
   yi[k]=y[n][m];
   bi[k]=false;
   Ti[k]=T[n][m];
  }
}

for(n=0;n<N;n++)
{for(m=0;m<M;m++)
  { k=(N+1)*n+m;
	int kp1=(N+1)*(n+1)+m;
	int kp1p1= kp1+1; 
	double xi1[]={x[n][m],x[n][m+1],x[n+1][m]};
	double yi1[]={y[n][m],y[n][m+1],y[n+1][m]};
    double zi1[]={T[n][m],T[n][m+1],T[n+1][m]};
	k1++; 
	int n_point1[]={k,(k+1),kp1};
	se[k].add(k1,0);
	se[k+1].add(k1,1);
	se[kp1].add(k1,2);
	te[k1]=new triangular_element1(k1,n_point1,xi1,yi1);  
	te[k1].setT(zi1);	
	double xi2[]={x[n][m+1],x[n+1][m+1],x[n+1][m]};
	double yi2[]={y[n][m+1],y[n+1][m+1],y[n+1][m]};
	double zi2[]={T[n][m+1],T[n+1][m+1],T[n+1][m]};
	k1++;
	int n_point2[]={k+1,kp1p1,kp1};
    se[k+1].add(k1,0);
	se[kp1p1].add(k1,1);
	se[kp1].add(k1,2);
	te[k1]=new triangular_element1(k1,n_point2,xi2,yi2);
	te[k1].setT(zi2); 
  } 
}	
}
public triangular_grid1(double Li, double Wi,int Ni, int Mi,double zz[][])
{generateTriangularGrid(Li,Wi,Ni,Mi,zz);}
public int find_element(double z[])
{ return find_element(z[0],z[1]);}
public int find_element(double x,double y)
{double R1=Math.sqrt(x*x+y*y);
 int kmin=0;
 double min=1.0e50;
 for(int k=0;k<K1;k++)
 {   te[k].setN(x,y);
     double r0=Math.sqrt((te[k].x[0]-x)*(te[k].x[0]-x)+(te[k].y[0]-y)*(te[k].y[0]-y));
     double r1=Math.sqrt((te[k].x[1]-x)*(te[k].x[1]-x)+(te[k].y[1]-y)*(te[k].y[1]-y));
     double r2=Math.sqrt((te[k].x[2]-x)*(te[k].x[2]-x)+(te[k].y[2]-y)*(te[k].y[2]-y));
     double dr=Math.sqrt(r0*r0+r1*r1+r2*r2);
	 boolean b1=(x>=te[k].x[0]) && (x<=te[k].x[2]);
	 boolean b2=(y>=te[k].y[0]) && (y<=te[k].y[1]);
	 boolean b= b1 && b2;
     if(dr<min) {min=dr;kmin=k;}
 }
 return kmin;
}


public void ContourPlot()
{
ContourPlot pp=new ContourPlot( x,y,T,16,true,"Finite element","x","y");
pp.plot();  
}

public void Plot3D(double L0,double L,double W0,double W) throws RemoteException, VisADException
{
Plot3D.plot3D_CD1(T,L0,L,W0,W,200,"x","y","T degree C");  
}
public void GridPlot(double L0,double L,double W0,double W)
{Plot3DPanel plot = new Plot3DPanel("SOUTH");
 double dx=(L-L0)/M;
 double dy=(W-W0)/N;
 double[] xx = increment(L0, dx,L); // x = 0.0:0.1:1.0
 double[] yy = increment(W0,dy,W);
 plot.addGridPlot("Finite element Grid", xx, yy, T);
 JFrame frame = new JFrame("a plot panel");
 frame.setSize(600, 600);
 frame.setContentPane(plot);
 frame.setVisible(true); 
}
public double getT(double x,double y)
{double z[]={x,y};
 int n=find_element(z);
 double T1=te[n].T(x,y); 
 return T1;
}

public static void main(String arg[]) throws RemoteException, VisADException
{double L=1.0;
 double W=1.0;
 int N=2,M=2;
 double TT[][]={{80.0,90.0,100.0},{90.0,100.0,110.0},{100.0,110.0,120.0}};
 double hi=20.0;
 triangular_grid1 tg=new triangular_grid1(L,W,M,N,TT);
 double z[]={0.65,0.55};
 int n=tg.find_element(z);
 System.out.println("element = "+n);
 double T=tg.getT(z[0],z[1]); 
 System.out.println("T = "+T);
 tg.Plot3D(0.0,L,0.0,W);
}
}