package ch.w3p.currgrid;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/**
* SimGrid - a flexible current grid simulation object
* Simulates a Current Grid. Mathematic Project I2
* Authors Daniel Schröter; Fabian Heusser
* Teacher: Dr. Josef F. Bürgler
* School: hta.fhz.ch, Horw;
* Project Homepage: http://www.w3p.ch/currgrid/
* Project Maillist: currgrid@w3p.ch
*
* supported features:
* interpolatet Plot:
* interpolatet VoltageOutput;
* change Voltage Points;
* delete Voltage Points;
* delete a Singel Voltage Point;
* drawLevelLinesM;
* Matrix ScrPrintOut
*
*
* LEGAL NOTICE
* THIS PROJECT AND ITS FILES ARE COPYRIGHTED BY THE AUTHORS
* THIS PROJECT CAN BE COPIED, MODIFIED AND DISTRIBUTED
* UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENCE
* WITH THE RESTRICTION OF SENDING US A MAIL WITH THE MODIFIED
* SOURCODE IF THE PROJECT IS MODIEFIED.
*
* if you like this progi feel free to send us something (beer, chips, playmates, houses....).
*
*
* @author Fabian Heusser
* @author Daniel Schröter
* @version 1.02, 07/03/01
* @(#) SimGrid.java
*/
public class SimGrid
{
private boolean calculated = false; //True wenn die Matrix gerechnet wurde.
private boolean changed = false; //ist True wenn das Grid geändert wurde
private double[] voltagePoints; //Enthält die Punkte mit Spannugen dran
//[][0] [][1] [][2]
//row | col | value
// | |
private double[] voltage;
private int xPos,yPos,height,width,col,row; //Die parameter des Gitters
private final boolean debug = true; //if true debug messages will printed to the System.out.
private long timeToCalculate, timeToDraw, timeToAssamble, timeToDrawLevelLine;
private Matrix unSolvedMatrix;
private Matrix solvedMatrix;
/**
* assembliert und gibt die matrix in auftrag.
*/
private void calculate() { //Berechnet die Matrix
long timeCalulationBase = System.currentTimeMillis();
System.out.println("gone to calculate:" + (System.currentTimeMillis()-timeCalulationBase));
Matrix currentMatrix; //Hält das Stromgitter.
int[] unknowPoints = new int[(col+1)*(row+1)]; //[x+y*col]
int pointNr=0;
//wir gehen hier zuerst alle punkte durch und nummerieren sie. --> array unknowPoints wird gefüllt
for (int i = 0; i<=row;i++){for(int k = 0; k<=col;k++){
if (Double.isNaN(getDefVoltage(k,i))){
unknowPoints[i*(col+1)+k]=pointNr++;
}
}}
if (debug){System.out.println("point list generated. gone to assamble:" + (System.currentTimeMillis()-timeCalulationBase));}
if (pointNr != 0){
//dann suchen wir die nachbarn und tragen sie in die matrix ein.
currentMatrix = new Matrix(pointNr);//da wir sonst das nullte element vergessen (d.h. das matrix objeckt braucht die anzahl elemente)
int matrixSize = currentMatrix.getSize();
int nrOfNeighbors = 0;
pointNr=0;
for (int i = 0; i<=row; i++){for(int k = 0; k<=col;k++){
if (Double.isNaN(getDefVoltage(k,i))){ //herausfinden ob der punkt eine festspannung ist wenn nein matrix füllen
// wir holen zuerst mal die nummer des punktes;
pointNr = unknowPoints[i*(col+1)+k];
// zuerst oberer nachbar
if (i>0){if (Double.isNaN(getDefVoltage(k,i-1))){ // wenn der obere nachbar vorhanden ist und keine festspannung eine 1 hineinschreiben
currentMatrix.setElement(unknowPoints[(i-1)*(col+1)+k], // wir setzten eine 1 in der zeile des elements und an der stelle des nachbars
pointNr,
1);
} else { // es ist eine festspannung, das heisst für uns wir setzten in der B spalte der Matrix das negative der spannung
currentMatrix.setElement(matrixSize,pointNr,
currentMatrix.getElement(matrixSize,pointNr)-getDefVoltage(k,i-1)
);} //für den fall das da schon eine spannung ist müssen wir sie subtrahieren
nrOfNeighbors++;} // wir habe einen Nachbar gefunden
// linker nachbar
if (k>0){if (Double.isNaN(getDefVoltage(k-1,i))){ // wenn der obere nachbar vorhanden ist und keine festspannung eine 1 hineinschreiben
currentMatrix.setElement(unknowPoints[i*(col+1)+k-1], // wir setzten eine 1 in der zeile des elements und an der stelle des nachbars
pointNr,
1);
} else { // es ist eine festspannung, das heisst für uns wir setzten in der B spalte der Matrix das negative der spannung
currentMatrix.setElement(matrixSize,pointNr,
currentMatrix.getElement(matrixSize,pointNr)-getDefVoltage(k-1,i));}
nrOfNeighbors++;} // wir habe einen Nachbar gefunden
// rechter nachbar
if (k<col){if (Double.isNaN(getDefVoltage(k+1,i))){ // wenn der obere nachbar vorhanden ist und keine festspannung eine 1 hineinschreiben
currentMatrix.setElement(unknowPoints[i*(col+1)+k+1], // wir setzten eine 1 in der zeile des elements und an der stelle des nachbars
pointNr,
1);
} else { // es ist eine festspannung, das heisst für uns wir setzten in der B spalte der Matrix das negative der spannung
currentMatrix.setElement(matrixSize,pointNr,
currentMatrix.getElement(matrixSize,pointNr)-getDefVoltage(k+1,i));}
nrOfNeighbors++;} // wir habe einen Nachbar gefunden
// untermieter
if (i<row){if (Double.isNaN(getDefVoltage(k,i+1))){ // wenn der obere nachbar vorhanden ist und keine festspannung eine 1 hineinschreiben
currentMatrix.setElement(unknowPoints[(i+1)*(col+1)+k], // wir setzten eine 1 in der zeile des elements und an der stelle des nachbars
pointNr,
1);
} else { // es ist eine festspannung, das heisst für uns wir setzten in der B spalte der Matrix das negative der spannung
currentMatrix.setElement(matrixSize,pointNr,
currentMatrix.getElement(matrixSize,pointNr)-getDefVoltage(k,i+1));}
nrOfNeighbors++;} // wir habe einen Nachbar gefunden
// nun muss die anzahl nachbarn noch in die matrix und zwar an der stelle des untersuchten punktes.
currentMatrix.setElement(pointNr,
pointNr,
-nrOfNeighbors);
nrOfNeighbors = 0;}
}}
timeToAssamble = System.currentTimeMillis()-timeCalulationBase;
if (debug){System.out.println("assambled. gone to solve system:" + (System.currentTimeMillis()-timeCalulationBase));}
unSolvedMatrix = currentMatrix.copy();
currentMatrix.gaussEliminate();
solvedMatrix = currentMatrix.copy();
timeToCalculate = System.currentTimeMillis()-timeCalulationBase-timeToAssamble;
if (debug){System.out.println("system solved." + (System.currentTimeMillis()-timeCalulationBase));}
for (int i = 0; i<=row;i++){for(int k = 0; k<=col;k++){
if (Double.isNaN(getDefVoltage(k,i))){
voltage[i*(col+1)+k] = currentMatrix.getX(unknowPoints[i*(col+1)+k]);
} else {
voltage[i*(col+1)+k] = getDefVoltage(k,i);
}
}}
} else {
for (int i = 0; i<=row;i++){for(int k = 0; k<=col;k++){
if (!Double.isNaN(getDefVoltage(k,i))){
voltage[i*(col+1)+k] = getDefVoltage(k,i);
}
}}
unSolvedMatrix = new Matrix(1);
solvedMatrix = new Matrix(1);
}
//aufräumen;
currentMatrix = null;
calculated = true;
changed = false;
}
/******************************************************************************
* the DRAW function
******************************************************************************/
// hef 15/05/01
/**
* zeichnet das spannungsgitter, wenn es noch nicht berechnet ist wird es.
* Das zeichnen funktioniert mit der quadratischer Interpollation.
* @param g Graphics Objekt in welches das Spannungsgitter gezeichnet werden soll.
*/
public void display(Graphics g){ //Zeichnet das Grid
if (!calculated || changed) {
calculate();}
long timeCalculationBase = System.currentTimeMillis();
double maxVoltage = getMaxVoltage();
double minVoltage = getMinVoltage();
double deltaVoltage = maxVoltage - minVoltage;
double v0,v1,v2,v3,vP,w,h;
for (int i = 0; i<row;i++){for (int k=0; k<col;k++){ //wir durchlaufen alle gitter punkte
v0 = getVoltage(k,i);
v1 = getVoltage(k+1,i);
v3 = getVoltage(k,i+1);
v2 = getVoltage(k+1,i+1);
h = (double)(height)/(double)(row);
w = (double)(width)/(double)(col);
for (int l=0; l<=h; l++){ // wir durschlaufen alle zeilen in einem quadrat
for (int m=0 ; m<=w; m++){ // wir durchlaufen alle pixel auf einer zeile des quadrates
vP = (v2-v3-v1+v0)*(m/w)*((l/h))+(v1-v0)*(m/w)+(v3-v0)*((l/h))+v0;
g.setColor(new Color(
(int)(255*((vP-minVoltage)/deltaVoltage)),
0,
(int)(255-(255*((vP-minVoltage)/deltaVoltage)))));
g.drawLine((int)(xPos+(k*w)+m),
(int)(yPos+(i*h)+l),
(int)(xPos+(k*w)+m),
(int)(yPos+(i*h)+l)); // pixel zeichnen
}}
}}
timeToDraw = System.currentTimeMillis() - timeCalculationBase;
System.out.println("System drawn. " + timeToDraw + "ms");
//for (int i = (int)getMinVoltage(); i<getMaxVoltage(); i += (getMaxVoltage()-getMinVoltage())/40){
// drawLevelLine(i,Color.white,g);}
}
/**
* Zeichnet das Gitternetz. Ünterstützt zusätzlich noch ein anders offset als dem grid zugewisen wurde
* @param g Graphics, das Fenster in das es gezeichnet werden soll.
* @param c Color, Farbe des Gitters
* @param xPos int, alternatives x offset
* @param yPos int, alternatives y offset
* @see #drawGrid(Graphics g, Color c)
* @see #drawGrid(Graphics g)
*
*/
public void drawGrid(Graphics g, Color c,int xPos, int yPos){
g.setColor(c);
for (int i = col; (--i)>0;){g.drawLine(xPos+width*i/col,yPos,xPos+ width*i/col,yPos+height);}
for (int i = row; (--i)>0;){g.drawLine(xPos,yPos+height*i/row,xPos+width,yPos+height*i/row);}
}
/**
* Zeichnet das Gitternetz
* @param g Graphics, das Fenster in das es gezeichnet werden soll.
* @param c Color, Farbe des Gitters
* @see #drawGrid(Graphics g, Color c,int xPos, int yPos)
* @see #drawGrid(Graphics g)
*/
public void drawGrid(Graphics g, Color c){
g.setColor(c);
for (int i = col; (--i)>0;){g.drawLine(xPos+width*i/col,yPos,xPos+ width*i/col,yPos+height);}
for (int i = row; (--i)>0;){g.drawLine(xPos,yPos+height*i/row,xPos+width,yPos+height*i/row);}
}
/**
* Zeichnet das Gitternetz. überschreibt die Funktion bei der zusätzlich noch die Farbe angegeben werden kann
* @param g Graphics, das Fenster in das es gezeichnet werden soll.
* @see #drawGrid(Graphics g, Color c)
* @see #drawGrid(Graphics g, Color c,int xPos, int yPos)
*/
public void drawGrid(Graphics g){
drawGrid(g,Color.gray);
}
/**
* Zeichnet das Gitternetz mit den Punkten welche sich im array befinden.
* diese Variante unterstützt zusätzlich das setzten eines anderen Offset als dem Grid Obj. zugewisen wurde.