JavaFX中的图灵扩散

时间:2016-12-31 15:26:09

标签: user-interface math javafx

我试图将图灵扩散模型从JavaScript转换为JavaFX,如下所示:

CODE

VIDEO

...但我的代码表现不正常。我认为是错误逻辑与我更新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);
    }
}

更新:修正了更新方程中的一个错误。

1 个答案:

答案 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);
}