I don't know that I understand it well so I will talk about the case when you want to decimate the data.
The best solution would be to resample your input data and time vector.
But if you want to be simple, you can try something like this:
- Always add the starting end ending data point
- For inner data points calculate the decimation
Example
This example will always produce a LineChart
with 20 nodes independently from how many data points you input array has.
Note: this solution is far not the best you can have, and heavily relies on that the input data vectors has the same time vector. It is also influences the result that the step size of the time vector is fixed.
public class ChartingApp extends Application {
@Override
public void start(Stage stage) throws Exception {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
// Size of the input data
int dataCount = 777;
// One X axis two Y axis
double[] xValues = new double[dataCount];
double[] y1Values = new double[dataCount];
double[] y2Values = new double[dataCount];
// Generate some initial data
Random randomGenerator = new Random();
for (int i = 0; i < dataCount; i++) {
xValues[i] = i;
y1Values[i] = randomGenerator.nextInt(200);
y2Values[i] = randomGenerator.nextInt(200);
}
// Amount of nodes to display
int valueCountToDisplay = 20;
Series<Number, Number> series1 = new Series<Number, Number>();
Series<Number, Number> series2 = new Series<Number, Number>();
// The first element is always added
series1.getData().add(new Data<Number, Number>(xValues[0], y1Values[0]));
series2.getData().add(new Data<Number, Number>(xValues[0], y2Values[0]));
// Generate the inner nodes
double elementToPick = Math.floor((dataCount - 2) / (valueCountToDisplay - 2));
for (int i = 1; i < dataCount - 1; i++) {
if (i % elementToPick == 0) {
series1.getData().add(new Data<Number, Number>(xValues[i], y1Values[i]));
series2.getData().add(new Data<Number, Number>(xValues[i], y2Values[i]));
}
}
// The last element is always added
series1.getData().add(new Data<Number, Number>(xValues[dataCount - 1], y1Values[dataCount - 1]));
series2.getData().add(new Data<Number, Number>(xValues[dataCount - 1], y2Values[dataCount - 1]));
Scene scene = new Scene(lineChart, 800, 600);
lineChart.getData().addAll(series1, series2);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The result is:

The logic behind can be summarized like this:
double[] createSparseArray(double[] inputData, int arraySize) {
List<Double> sparseList = new ArrayList<Double>();
sparseList.add(inputData[0]);
double elementToPick = Math.floor((inputData.length - 2) / (arraySize - 2));
for (int i = 1; i < inputData.length - 1; i++) {
if (i % elementToPick == 0)
sparseList.add(inputData[i]);
}
sparseList.add(inputData[arraySize - 1]);
return sparseList.stream().mapToDouble(d -> d).toArray();
}
The example uses arrays to store the data, but it is really similar with you data structure (using size of Set
and looping with the good-old for loop).