fair-acc/chart-fx

Auto Ranging is doing unpredictable things

yetyman opened this issue · 2 comments

Hi, I'm trying out chart-fx and as a test I made a simple sliding window of sine and cosine values. very similar to your sample chart code.

my intent is for y-range to stay approximately the same but should be auto-ranged to the current data and for x-range to slide to higher radian values over time.

the two trend lines are updated in opposing ticks of the timer because i intend to use this for data that comes in sporadically from different sources.

Unfortunately I'm seeing some weird problems with the auto ranging and the tick marks on the axes.

Here is a minimum reproducible sample

I did notice several of the open tickets regard axis ranging and i saw that the usual recommendation was extra layout passes. i tried adding those(commented in my sample below) but it really didn't seem to affect the issues.

in this particular setup it seems like the minimum x value of the x-axis never updates to fit the dataset and the y-axis might be ranging too small? but in other variations both axes fling around wildly.

    final XYChart chart = new XYChart(new DefaultNumericAxis(), new DefaultNumericAxis());

    final DoubleDataSet dataSet1 = new DoubleDataSet("data set #1");
    final DoubleDataSet dataSet2 = new DoubleDataSet("data set #2");
    // lineChartPlot.getDatasets().add(dataSet1); // for single data set
    chart.getDatasets().addAll(dataSet1, dataSet2); // two data sets

    final int N_SAMPLES = 100;
    final double[] xValues = new double[N_SAMPLES];
    final double[] yValues1 = new double[N_SAMPLES];
    final double[] yValues2 = new double[N_SAMPLES];
    final double[] t1 = {TimeUnit.NANOSECONDS.toMillis(System.nanoTime())};
    for (int n = 0; n < N_SAMPLES; n++) {
        xValues[n] = -(N_SAMPLES-n);
        double time = -(N_SAMPLES-n)*100;
        double rad = time / 2000 * Math.PI*2.0;//rad
        yValues1[n] = Math.sin(rad);
        yValues2[n] = Math.cos(rad);
    }
    dataSet1.set(xValues, yValues1);
    dataSet2.set(xValues, yValues2);
    chart.setAnimated(true);
    chart.getXAxis().setAutoRanging(true);
    chart.getXAxis().setAutoGrowRanging(true);
    chart.getYAxis().setAutoGrowRanging(true);
    chart.getYAxis().setAutoRanging(true);
    
    
    Thread fakeDataSource = new Thread(new Runnable() {
        double rad = 0;
        int i = 0;
        @Override
        public void run() {
            while(true){
                //cycle every 2 seconds
                double time = TimeUnit.NANOSECONDS.toMillis(System.nanoTime())- t1[0];
                rad = time / 2000 * Math.PI*2.0; //rad

                //simulate sparse data updates
                if(i++%2 == 0) {
                    double val = Math.sin(rad);
                    dataSet1.remove(0);
                    dataSet1.add(rad, val);
                }else {
                    double val = Math.cos(rad);
                    dataSet2.remove(0);
                    dataSet2.add(rad, val);
                }
                
                
//                Platform.runLater(()->{
//                    chart.requestLayout();
//                });
                if(i == Integer.MAX_VALUE)
                    i = 0;

                try {
                    Thread.sleep((int)(1000/30.0)); //30Hz

                    double t2 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
                    while(c.pause)
                        Thread.sleep(1);
                    double t3 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
                    t1[0] += t3-t2;

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    });
    fakeDataSource.start();
ennerf commented

This is already fixed in main, and after #601 also works without requiring extra invalidation calls

closing as per @ennerf 's comment, feel free to reopen if it the problem persists on main or the upcoming release.