package fem2;
import java.io.*;
import java.util.*;
import java.awt.*;

public class fem//Finite-Elemente-Verfahren, Dreiecke
{
  int apkt,adrk; //Anzahl Punkte, Dreiecke
  triang[] drk;  //Dreiecke
  double[][] pkt; //Gitterpunkte
  int aunb = 0;  //Anzahl Unbekannte (innere Pkte)
  int[] unb;    //Randmarken & Variablen-Nrn
  double[] yw; // Feld innere Funktionswerte
  double[] xmn = new double[3]; //Bereichs-Minima
  double[] xmx = new double[3]; //Bereichs-Maxima
  matrix mat; //System-Matrix
    
  private double[] gxf = new double[2]; //2D-Streckfaktoren
  private double fxx,fxy,fyx,fyy,fyz; //3D-Streckfaktoren

  void wbereich() { //bestimmt umschliessendes Rechteck [xmn,xmx]
    for (int j=0; j<2; j++) {
      xmn[j] = pkt[0][j];
      xmx[j] = xmn[j];
    }
    for (int k=1; k<apkt; k++){
      for (int j=0; j<2; j++) {
        if (xmn[j]>pkt[k][j]) xmn[j] = pkt[k][j];
        if (xmx[j]<pkt[k][j]) xmx[j] = pkt[k][j];
      }
    }
    xmn[2] = 0.0; xmx[2] = 0.2;//Bereich Funktionswerte
    for (int j=0; j<2; j++) gxf[j] = 592.0/(xmx[j]-xmn[j]); //2D-Grafik-Faktoren
  }//wbereich
  
  boolean liesgeom(String dname){ //liest Geometrie aus Datei dname
    int pn;
    String zl ="";
    StringTokenizer st;
    try { //Datei öffnen und zeilenweise lesen:
      BufferedReader eing = new BufferedReader(new FileReader(dname));
      zl = eing.readLine();
      st = new StringTokenizer(zl," ",false);
      apkt = Integer.parseInt(st.nextToken()); //Punktezahl
      adrk = Integer.parseInt(st.nextToken()); //Dreieck-Anzahl
      pkt = new double[apkt][2];
      drk = new triang[adrk];
      unb = new int[apkt];
      for (int i=0; i<apkt; i++) //Gitterpunkte einlesen
      {
        zl=eing.readLine();
        st = new StringTokenizer(zl," ",false);
        pn = Integer.parseInt(st.nextToken());
        pkt[i][0] = Double.parseDouble(st.nextToken());
        pkt[i][1] = Double.parseDouble(st.nextToken());
        unb[i] = Integer.parseInt(st.nextToken());
      }
      for (int k=0; k<adrk; k++) //Dreiecke erzeugen&lesen
      {
      	drk[k] = new triang();
        zl = eing.readLine();
        st = new StringTokenizer(zl," ",false);
        for (int i=0; i<3; i++) drk[k].ep[i] = Integer.parseInt(st.nextToken());
        drk[k].init(pkt);
      }
      eing.close(); 
      numeriere();
    } 
    catch (IOException e) {return false;}
    return true;
  }//liesgeom

  void numeriere() { //numeriert innere Werte unb[], erzeugt yw[aunb]
   //???
  }//numeriere

  double fktw(int ip) { //Funktionswert zu pkt[ip]
    int up = unb[ip];
    if (up<0) return 0; //ist Randwert, =0
    else return yw[up];// Gitterwert
  }//fktw

  void femlsg() { //Aufstellung & Lösung Ritz-Galerkin-System
   //???
  }//femlsg

  void grafkoord2(double[] xp, int[] gp) { //2D-Welt->Bildkoordinaten gp
    gp[0] = 2+(int) Math.round(gxf[0]*(xp[0]-xmn[0]));
    gp[1] = 596-(int) Math.round(gxf[1]*(xp[1]-xmn[1]));
  }//grafkoord

  void grafpar(double dw, double kw) {//berechnet 3D-Trafo zu Dreh-&KippWinkel
    double cd = Math.cos(dw);
    double sd = Math.sin(dw);
    double ck = Math.cos(kw)*0.707;
    double sk = Math.sin(kw)*0.707;
    double w2 = 420.0; //Graphikfaktor
    fxx = cd*w2/(xmx[0]-xmn[0]);
    fxy =-sd*w2/(xmx[1]-xmn[1]);
    fyx = sd*ck*w2/(xmx[0]-xmn[0]);
    fyy = cd*ck*w2/(xmx[1]-xmn[1]);
    fyz =-sk*w2/(xmx[2]-xmn[2]);
  }//grafpar
 
  void grafkoord3(double[] xp, double zp, int[] gp) {//3D-Welt->Bildkoordinaten gp
    double[] pm = new double[3];
    for (int i=0; i<2; i++) pm[i] = xp[i]-(xmn[i]+xmx[i])/2;//Um Mittelpunkt zentrieren  
    pm[2] = zp-(xmn[2]+xmx[2])/2;
    gp[0] = 300+(int)Math.round(fxx*pm[0]+fxy*pm[1]); //nur Drehanteil
    gp[1] = 300-(int)Math.round(fyx*pm[0]+fyy*pm[1]+fyz*pm[2]);
  }//grafkoord3
  
  void zeiggeom(Graphics g) {//2D-Gitter malen auf g
    int[] epgx = new int[3];
    int[] epgy = new int[3];
    int[] gp = new int[2];
    int pn;
    g.clearRect(0,0,600,600);
    for (int k=0; k<adrk; k++) { //alle Dreiecke zeichnen
      for (int j=0; j<3; j++) { //Eckpunkte tranformieren
      	pn = drk[k].ep[j];
        grafkoord2(pkt[pn],gp);
        epgx[j]=gp[0]; epgy[j]=gp[1];
      }
      g.setColor(Color.yellow);
      g.fillPolygon(epgx,epgy,3);
      g.setColor(Color.black);
      g.drawPolygon(epgx,epgy,3);
    }
  }//Ende zeiggeom

  void zeig_fkt(double dw, Graphics g) {
    int[] epgx = new int[3];
    int[] epgy = new int[3];
    int[] gp = new int[2];
    int pn;
    double zw;
    grafpar(dw,-0.5);//Trafo-Parameter zu aktueller Ansicht
    g.clearRect(0,0,600,600);
    g.setColor(Color.black);
    for (int k=0; k<adrk; k++) { //alle Dreiecke zeichnen
      for (int j=0; j<3; j++) { //Eckpunkte transformieren
      	pn = drk[k].ep[j];
        zw = fktw(pn);
        grafkoord3(pkt[pn],zw,gp);
        epgx[j]=gp[0]; epgy[j]=gp[1];
      }
      g.drawPolygon(epgx,epgy,3);
    }
  }//Ende zeig_fkt
}