I'm working on some software that's for performance tuning Subaru's. The software takes logged parameters from the vehicle, graphs it on a scatter plot against the X axis (engine RPM), and allows for drag/drop adjustment. The adjustments are made on a 2D table with an X and Y axis that looks similar to something like this: https://i.stack.imgur.com/HHJ1Y.jpg
In order to get the most precise adjustments, I first find the value on the table with the logged X/Y values (in this case, it's engine load and engine RPM) and then use bilinear interpolation to find the exact value. What I would like to accomplish is take said value, increase or decrease the value and then reverse the process adjusting all four cells accordingly to reflect the changes. I could increase/decrease all four cells equally by the difference and it will result in the correct value, but what I actually want is to adjust each of the four cells according to where the X and Y lands.
example using the attached table:
x0 = 2.00
x1 = 2.30
y0 = 2400
y1 = 2800
x0y0 = 18.67
x0y1 = 19.38
x1y0 = 16.56
x1y1 = 17.62
Logged_X = 2.15
Logged_Y = 2600
the bilinear interpolation value would be: 18.0575
A simpler example would be:
| 1 | 2 |
---------
400 | 4 | 6 |
800 | 6 | 8 |
x0 = 1
x1 = 2
y0 = 400
y1 = 800
x0y0 = 4
x0y1 = 6
x1y0 = 6
x1y1 = 8
Logged_X = 1
Logged_Y = 400
the bilinear interpolation value would be: 4
In the first example, if I wanted the new bilinear interpolation value to be 19.00, it's obvious I would increase all four cell values by the difference (0.9425) because the X/Y fall directly in the center, and all four cells equally contribute to the value. In the second example, 100% of the bilinear interpolation value comes from the x0y0 cell, so I would like 100% of the adjustment to go towards that cell.
Unfortunately most logged X/Y values will not fall into one of these two examples and will more than likely fall somewhere in between.
I'm looking for a streamlined approach to this. Any help is greatly appreciated.
The following is the code used currently:
public double test(JTable table, double xVal, double yVal, double oldVal, double newVal) {
double x0, x1, y0, y1, x0y0, x1y0, x0y1, x1y1, originalval, xCellVal, yCellVal;
int x0Idx, x1Idx, y0Idx, y1Idx;
ArrayList<Double> xAxisArray = getAxisData(table, 0);
ArrayList<Double> yAxisArray = getAxisData(table, 1);
int xIdx = Utils.closestValueIndex(xVal, xAxisArray);
int yIdx = Utils.closestValueIndex(yVal, yAxisArray);
xCellVal = xAxisArray.get(xIdx);
if (xVal < xCellVal) {
x1Idx = xIdx;
x1 = xCellVal;
if (xIdx > 0) {
x0Idx = xIdx - 1;
x0 = xAxisArray.get(x0Idx);
}
else {
x0Idx = x1Idx;
x0 = x1;
}
}
else if (xVal > xCellVal) {
x0Idx = xIdx;
x0 = xCellVal;
if (xIdx < xAxisArray.size() - 1) {
x1Idx = xIdx + 1;
x1 = xAxisArray.get(x1Idx);
}
else {
x1Idx = x0Idx;
x1 = x0;
}
}
else {
x0Idx = x1Idx = xIdx;
x0 = x1 = xCellVal;
}
yCellVal = yAxisArray.get(yIdx);
if (yVal < yCellVal) {
y1Idx = yIdx;
y1 = yCellVal;
if (yIdx > 0) {
y0Idx = yIdx - 1;
y0 = yAxisArray.get(y0Idx);
}
else {
y0Idx = y1Idx;
y0 = y1;
}
}
else if (yVal > yCellVal) {
y0Idx = yIdx;
y0 = yCellVal;
if (yIdx < yAxisArray.size() - 1) {
y1Idx = yIdx + 1;
y1 = yAxisArray.get(y1Idx);
}
else {
y1Idx = y0Idx;
y1 = y0;
}
}
else {
y0Idx = y1Idx = yIdx;
y0 = y1 = yCellVal;
}
x0y0 = Double.valueOf(table.getValueAt(y0Idx + 1, x0Idx + 1).toString());
x1y0 = Double.valueOf(table.getValueAt(y0Idx + 1, x1Idx + 1).toString());
x0y1 = Double.valueOf(table.getValueAt(y1Idx + 1, x0Idx + 1).toString());
x1y1 = Double.valueOf(table.getValueAt(y1Idx + 1, x1Idx + 1).toString());
return Utils.bilinearInterpolation(xVal, yVal, x0, x1, y0, y1, x0y0, x0y1, x1y0, x1y1);
}
public static double bilinearInterpolation(double x, double y, double x0, double x1, double y0, double y1, double x0y0, double x0y1, double x1y0, double x1y1) {
double t1, t2;
if (y1 == y0) {
t1 = x0y0;
t2 = x1y0;
}
else {
t1 = (y - y0) * (x0y1 - x0y0) / (y1 - y0) + x0y0;
t2 = (y - y0) * (x1y1 - x1y0) / (y1 - y0) + x1y0;
}
if (x1 == x0)
return t1;
return (x - x0) * (t2 - t1) / (x1 - x0) + t1;
}
This code is used to get the bilinear interpolation value. currently the only method I have to adjust the value is to add the difference between the desired value and the returned value to all four cell values.