我试图将图灵扩散模型从JavaScript转换为JavaFX,如下所示:
...但我的代码表现不正常。我认为是错误逻辑与我更新UI 的方式相结合。任何帮助将不胜感激。代码编译并运行。
package application;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class Main extends Application {
private double dA = 1;
private double dB = 0.5;
private double feed = 0.055;
private double k = 0.062;
// Concentrate [x][y][t]
private double[][][] A = new double[100][100][100];
private double[][][] B = new double[100][100][100];
final NumberAxis xAxis = new NumberAxis(0, 100, 10);
final NumberAxis yAxis = new NumberAxis(0, 100, 10);
final ScatterChart<Number,Number> sc = new ScatterChart<Number,Number>(xAxis,yAxis);
Slider slider = new Slider(0,99,1);
VBox root = new VBox();
@SuppressWarnings("rawtypes")
XYChart.Series vizualize_A = new XYChart.Series();
@SuppressWarnings("rawtypes")
XYChart.Series vizualize_B = new XYChart.Series();
@SuppressWarnings("rawtypes")
XYChart.Data data_A;
@SuppressWarnings("rawtypes")
XYChart.Data data_B;
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) {
try {
xAxis.setLabel("x");
yAxis.setLabel("y");
sc.setTitle("Turing Diffusion");
initArray();
update();
draw(0);
sc.getData().setAll(vizualize_A, vizualize_B);
sc.setLegendVisible(false);
sc.setAnimated(false);
sc.setPrefSize(500, 500);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(10f);
slider.setBlockIncrement(1f);
slider.setValue(0);
root.getChildren().addAll(sc, slider);
Scene scene = new Scene(root,700,550);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
slider.valueProperty().addListener((obs, oldval, newVal) -> {
draw(newVal.intValue());
Platform.runLater(new Runnable() {
@Override
public void run() {
sc.getData().setAll(vizualize_A, vizualize_B);
}
});
});
}
private void initArray(){
for (int m = 0; m <= (100-1); m++ ){
// y: j
for (int j = 0; j <= (100-1); j++){
// x: i
for (int i = 0; i <= (100-1); i++){
A[i][j][m] = 1;
// B[i][j][m] = 1;
if (i >= 20 && i<= 35 && j >= 35 && j <= 75 && m == 0) {
B[i][j][m] = 1;
} else {
B[i][j][m] = 0;
}
}
}
}
}
Rectangle rect_A[][][] = new Rectangle[100][100][100];
Rectangle rect_B[][][] = new Rectangle[100][100][100];
@SuppressWarnings({ "rawtypes", "unchecked" })
public void draw(int time){
vizualize_A.getData().clear();
vizualize_B.getData().clear();
sc.getData().remove(vizualize_A);
sc.getData().remove(vizualize_B);
// y: j
for (int j = 0; j <= (100-1); j++){
// x: i
for (int i = 0; i <= (100-1); i++){
int m = time;
data_A = new XYChart.Data(i, j);
data_B = new XYChart.Data(i, j);
// Type A
rect_A[i][j][m] = new Rectangle(5, 5);
rect_A[i][j][m].setFill(Color.RED);
data_A.setNode(rect_A[i][j][m]);
data_A.getNode().setOpacity(A[i][j][m]);
vizualize_A.getData().add(data_A);
// Type B
rect_B[i][j][m] = new Rectangle(5, 5);
rect_B[i][j][m].setFill(Color.BLACK);
data_B.setNode(rect_B[i][j][m]);
data_B.getNode().setOpacity(B[i][j][m]);
vizualize_B.getData().add(data_B);
}
}
}
public void update(){
for (int m = 1; m <= (100-2); m++ ){
// y: j
for (int j = 1; j <= (100-2); j++){
// x: i
for (int i = 1; i <= (100-2); i++){
A[i][j][m+1] = A[i][j][m] + (dA * laplace(A, i, j, m)) - (A[i][j][m] * Math.pow(B[i][j][m] ,2)) + (feed * (1 - A[i][j][m]));
B[i][j][m+1] = B[i][j][m] + (dB * laplace(B, i, j, m)) + (A[i][j][m] * Math.pow(B[i][j][m] ,2)) - (( k + feed) + B[i][j][m]);
A[i][j][m+1] = Math.min(Math.max(A[i][j][m+1], (double) 0), (double) 1);
B[i][j][m+1] = Math.min(Math.max(B[i][j][m+1], (double) 0), (double) 1);
}
}
}
}
public double laplace(double[][][] xArray, int x, int y, int time){
double laValue = 0;
laValue = laValue + xArray[x][y][time] * -1;
laValue = laValue + xArray[x - 1][y][time] * 0.2;
laValue = laValue + xArray[x + 1][y][time] * 0.2;
laValue = laValue + xArray[x][y + 1][time] * 0.2;
laValue = laValue + xArray[x][y - 1][time] * 0.2;
laValue = laValue + xArray[x - 1][y - 1][time] * 0.05;
laValue = laValue + xArray[x + 1][y - 1][time] * 0.05;
laValue = laValue + xArray[x + 1][y + 1][time] * 0.05;
laValue = laValue + xArray[x - 1][y + 1][time] * 0.05;
return laValue;
}
public static void main(String[] args) {
launch(args);
}
}
更新:修正了更新方程中的一个错误。
答案 0 :(得分:1)
问题:
您在&#34;时间&#34;开始update
m=1
。但是m
是您从 读取的状态 的时间,这意味着您从第二个状态开始读取,而不是初始状态:
public void update(){
for (int m = 0; m <= (100-2); m++){ // fix here
请注意,以下代码包含一些修改,例如在Canvas
中显示代码(图表似乎是显示数据的遗憾选择),仅执行必要的初始化并更改索引顺序(使用&#34;时间&#34;首先允许您传递一个&#34;框架&#34;围绕double[][]
)的数据:
private static final double dA = 1;
private static final double dB = 0.5;
private static final double feed = 0.055;
private static final double k = 0.062;
private static final int FRAMES = 200;
private static final int WIDTH = 100;
private static final int HEIGHT = 100;
private double[][][] A = new double[FRAMES][WIDTH][HEIGHT];
private double[][][] B = new double[FRAMES][WIDTH][HEIGHT];
Slider slider = new Slider(0, FRAMES - 1, 1);
VBox root = new VBox();
PixelWriter writer;
@Override
public void start(Stage primaryStage) {
Canvas canvas = new Canvas(WIDTH, HEIGHT);
writer = canvas.getGraphicsContext2D().getPixelWriter();
try {
initArray();
update();
draw(0);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(10f);
slider.setBlockIncrement(1f);
slider.setValue(0);
root.getChildren().addAll(canvas, slider);
Scene scene = new Scene(root, 700, 550);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
slider.valueProperty().addListener((obs, oldval, newVal) -> {
draw(newVal.intValue());
});
}
private void initArray() {
double[][] state = A[0];
for (int j = 0; j < WIDTH; j++) {
Arrays.fill(state[j], 1);
}
// fill border
for (double[][] s : A) {
Arrays.fill(s[0], 1);
Arrays.fill(s[WIDTH - 1], 1);
for (int i = 1; i < (WIDTH - 1); i++) {
double[] line = s[i];
line[0] = 1;
line[HEIGHT - 1] = 1;
}
}
state = B[0];
for (int i = 20; i <= 35; i++) {
Arrays.fill(state[i], 35, 75 + 1, 1);
}
}
public void draw(int time) {
double[][] stateA = A[time];
double[][] stateB = B[time];
for (int i = 0; i < WIDTH; i++) {
double[] lineA = stateA[i];
double[] lineB = stateB[i];
for (int j = 0; j < HEIGHT; j++) {
double a = lineA[j];
double b = lineB[j];
double result = Math.max(0, a - b);
writer.setArgb(i, j,
0xff000000
| (((int) (0xff * result)) << 16));
}
}
}
public void update() {
for (int m = 0; m < (FRAMES - 1); m++) {
double[][] sourceA = A[m];
double[][] sourceB = B[m];
double[][] targetA = A[m + 1];
double[][] targetB = B[m + 1];
for (int i = 1; i <= (WIDTH - 2); i++) {
double[] sourceLineA = sourceA[i];
double[] sourceLineB = sourceB[i];
double[] targetLineA = targetA[i];
double[] targetLineB = targetB[i];
for (int j = 1; j <= (HEIGHT - 2); j++) {
double a = sourceLineA[j];
double b = sourceLineB[j];
targetLineA[j] = Math.max(0, Math.min(1, a
+ dA * laplace(sourceA, i, j)
- a * b * b
+ (feed * (1 - a))));
targetLineB[j] = Math.max(0, Math.min(1, b
+ dB * laplace(sourceB, i, j)
+ (a * b * b)
- ((k + feed) * b)));
}
}
}
}
public double laplace(double[][] xArray, int x, int y) {
return 0.2 * (xArray[x - 1][y] + xArray[x + 1][y] + xArray[x][y + 1] + xArray[x][y - 1])
+ 0.05 * (xArray[x + 1][y + 1] + xArray[x + 1][y - 1] + xArray[x - 1][y + 1] + xArray[x - 1][y - 1])
- xArray[x][y];
}
public static void main(String[] args) {
launch(args);
}