0

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.

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95

0 Answers0