Ich habe es mit der folgenden Diffusionsgleichung gemacht.
Da ich versuche, mich auf vergangene Rennen einzulassen, gebe ich als Übung eine Bilddatei im ppm-Format aus.
InkFlow.java
package flow;
import java.io.FileWriter;
import java.io.IOException;
public class InkFlow{
//Simulieren Sie die Diffusion von Tinte, die auf die Wasseroberfläche fällt
static double INK = 255.; //Maximaler RGB-Wert
static int mx; //Anzahl der horizontalen Maschen(Anzahl der Pixel im Bild? werden)
static int my; //Vertikal
static int fc=0; //Dateiname Variable
public static void main(String[] args) throws IOException {
/*******
*Aufbau(Hier ändern)
*******/
//Wasseroberflächeneinstellung
int x = 10; //Seitenlänge[cm]
int y = 10; //Vertikale Länge[cm]
//Orte, an denen Tinte abfällt (oben links, oben rechts, oben rechts, links, Mitte, rechts, unten links, unten rechts unten)
boolean CPlace[][] = { // Cyan
{false,false,false},
{true,false,false},
{false,false,false}
};
boolean MPlace[][] = { // Magenta
{false,true,false},
{false,false,false},
{false,false,false}
};
boolean YPlace[][] = { // Yellow
{false,false,false},
{false,false,false},
{false,true,false}
};
//Die Größe der Tinte, die herunterhängen soll
int InkSize = 13;
//Zeiteinstellung
int t=0; //Anfangszeit 0[msec]
int T=10000; //Endzeit[msec]
int ut = 1000; //Zeit der Dateiausgabeeinheit[msec]
int inkt = 5000; //Zeit, Tinte zu tropfen[msec]
//Variablen für die Diffusion
double ul = 0.1; //Einheitsabstand[cm]
mx = (int) (x / ul);
my = (int) (y / ul);
double D = 0.25; //Diffusionskoeffizient(<0.25)
LogSettings(x,y,InkSize,T,ut, inkt ,ul,mx,my,D); //Konfigurationsprotokoll
/*******
*Initialisieren
*******/
//Farbinitialisierung (weiß)
double R[][] = InitialInk();
double G[][] = InitialInk();
double B[][] = InitialInk();
//Tinte abtropfen lassen
DipInk(CPlace, MPlace, YPlace, InkSize, R, G, B);
Output(R, G, B);
/*******
*Hauptschleife
*******/
while(t++ <= T) { //Schleife bis zur Endzeit T.
//Diffusion
R = CalcDiffusion(R, D);
G = CalcDiffusion(G, D);
B = CalcDiffusion(B, D);
//Tinte abtropfen lassen
if(t < inkt) { //inkt msec hängen
DipInk(CPlace, MPlace, YPlace, InkSize, R, G, B);
}
//Ausgabe
if(t % ut == 0){
Output(R, G, B);
}
}
System.out.println("done");
}
/*******
*Verschiedene Methoden
*******/
static double[][] InitialInk(){ //Tinteninitialisierung
double a[][] = new double[mx][my];
for(int i = 0; i < mx; i++) {
for(int j = 0; j < my; j++) {
a[i][j] = INK;
}
}
return a;
}
static double[][] CalcDiffusion(double[][] a, double D){ //Diffusionsberechnung
double b[][] = new double[mx][my];
//Innere Berechnung
for(int i=1;i<(mx-1);i++){
for(int j=1;j<(my-1);j++){ //Diffusionsgleichung
b[i][j] = a[i][j] + D * (a[i+1][j] + a[i-1][j] - 2*a[i][j]) + D * (a[i][j+1] + a[i][j-1] - 2*a[i][j]);
}
}
//Äußere Berechnung
for(int i=0;i<mx;i++){
b[i][my-1] = b[i][my-2];
b[i][0] = b[i][1];
}
for(int j=0;j<my;j++){
b[mx-1][j] = b[mx-2][j];
b[0][j] = b[1][j];
}
return b;
}
static void DipInk(boolean[][] CPlace, boolean[][] MPlace, boolean[][] YPlace, int InkSize, double[][] R, double[][] G, double[][] B) {
for(int i = 0; i < CPlace.length; i++) {
for(int j = 0; j < CPlace[0].length; j++) {
if(CPlace[i][j] || MPlace[i][j] || YPlace[i][j]) {
if(CPlace[i][j]) {
DipWithInkSize(R, InkSize, i, j, 0);
} else {
DipWithInkSize(R, InkSize, i, j, 212);
}
if(MPlace[i][j]) {
DipWithInkSize(G, InkSize, i, j, 0);
} else {
DipWithInkSize(G, InkSize, i, j, 212);
}
if(YPlace[i][j]) {
DipWithInkSize(B, InkSize, i, j, 0);
} else {
DipWithInkSize(B, InkSize, i, j, 212);
}
}
}
}
}
static void DipWithInkSize(double[][] C, int InkSize, int a, int b, double val) {
//Erhöhen Sie die Tintenmenge in einer Spirale entsprechend der Tintengröße
C[(int) (mx*(2*a+1)/6)][(int) (my*(2*b+1)/6)] = val; //Erste Tinte
int itr = 1;
int i = 1;
while(true) {
for(int x = itr, y = 0; x > 0; x--,y++) {
C[(int) (mx*(2*a+1)/6)+x][(int) (my*(2*b+1)/6)+y] = val;
i++;
if(i >= InkSize) {
return;
}
}
for(int x = 0, y = itr; y > 0; x--, y--) {
C[(int) (mx*(2*a+1)/6)+x][(int) (my*(2*b+1)/6)+y] = val;
i++;
if(i >= InkSize) {
return;
}
}
for(int x = -itr, y = 0; x < 0; x++,y--) {
C[(int) (mx*(2*a+1)/6)+x][(int) (my*(2*b+1)/6)+y] = val;
i++;
if(i >= InkSize) {
return;
}
}
for(int x = 0, y = -itr; y < 0; x++, y++) {
C[(int) (mx*(2*a+1)/6)+x][(int) (my*(2*b+1)/6)+y] = val;
i++;
if(i >= InkSize) {
return;
}
}
itr++;
}
}
static void Output(double[][] R, double[][] G, double[][] B) throws IOException { //Bilddatei(ppm-Format)Ausgabe von
String fname = "3_" + fc++ + ".ppm";
FileWriter fw = new FileWriter(fname); // Difine file name
// Header
fw.write("P3 \r\n");
fw.write("#The P3 means colors are in ASCII, then columns and rows, then 255 for max color, then RGB triplets \r\n");
fw.write(mx + " " + my + " \r\n");
fw.write("" + (int) INK + " \r\n");
// Body
for(int i = 0; i < mx; i++) {
for(int j = 0; j < my; j++) {
fw.write("" + (int) R[i][j] + " " + (int) G[i][j] + " " + (int) B[i][j]);
fw.write(" \r\n");
}
}
fw.close();
System.out.println("output: " + fname);
}
static void LogSettings(int x, int y, int InkSize, int T, int ut, int inkt, double ul, int mx, int my, double D) {
System.out.println("Wasseroberfläche(Horizontal x vertikal) : " + x + " cm × " + y + " cm");
System.out.println("Tintengröße: " + ul*ul*InkSize + " cm^2");
System.out.println("Zeit zum Aufhängen:" + inkt + " msec");
System.out.println("Endzeit: " + T + " msec");
System.out.println("Zeiteinheit ausgeben: " + ut + " msec");
System.out.println("Einheitsabstand: " + ul + " cm");
System.out.println("Anzahl der horizontalen Maschen: " + mx);
System.out.println("Anzahl der vertikalen Maschen: " + my);
System.out.println("Diffusionskoeffizient: " + D);
System.out.println("-*-*-*-");
if(mx / 6 < InkSize) {
System.out.println("InkSize ist zu groß");
}
}
}
In der Konsole lautet die Ausgabe wie folgt.
Wasseroberfläche(Horizontal x vertikal) : 10 cm × 10 cm
Tintengröße: 0.13000000000000003 cm^2
Zeit zum Aufhängen:5000 msec
Endzeit: 10000 msec
Zeiteinheit ausgeben: 1000 msec
Einheitsabstand: 0.1 cm
Anzahl der horizontalen Maschen: 100
Anzahl der vertikalen Maschen: 100
Diffusionskoeffizient: 0.25
-*-*-*-
output: 3_0.ppm
output: 3_1.ppm
output: 3_2.ppm
output: 3_3.ppm
output: 3_4.ppm
output: 3_5.ppm
output: 3_6.ppm
output: 3_7.ppm
output: 3_8.ppm
output: 3_9.ppm
output: 3_10.ppm
done
Das Ausgabebild sollte wie folgt aussehen
Recommended Posts