josef.van.niekerk
josef.van.niekerk

Reputation: 12121

JavaScript cosine interpolation

I'm building an Indicated Airspeed instrument with JavaScript that gets data from X-Plane via a WebSocket. The airspeed is received in knots, and needs to be plotted on the instrument, which has a non-linear scale.

An array, called intervals keeps a list of markings on the instrument, corresponding to the angle of rotation, for the needle, in degrees, for the corresponding airspeed in knots.

var intervals = {
    0: 0.00,
    40: 29.73,
    50: 49.00,
    60: 69.67,
    70: 91.25,
    80: 114.51,
    90: 137.42,
    100: 162.68,
    110: 185.38,
    120: 206.40,
    130: 222.46,
    140: 238.30,
    150: 252.54,
    160: 267.25,
    170: 279.28,
    180: 291.76,
    190: 304.81,
    200: 317.29
};

The interpolation function receives the above array, figures out the y1 and y2 values where x lies between, and uses that in a trigonometric formula to try and calculate the cosine interpolated angle the needle must be angled at, in degrees, to represent the correct IAS in Knots.

function interpolate(intervals, x) {
    var y1, y2, angle = 0;

    // Find y1 <= mu <= y2
    for (var key in intervals) {
        var f_key = parseFloat(key);
        if (x < f_key) {
            y1 = intervals[f_key - 10] / 360;
            y2 = intervals[f_key] / 360;
            break;
        }
    }

    // Calculate cosine interpolated value and return
    x = x / 360;
    f = (1 - Math.cos(x * Math.PI)) / 2;
    angle = (y1 * (1 - f) + y2 * f);

    return angle * 360;
}

function setIas(kts) {
    var angle = interpolate(intervals, kts);
    $('g#needle-1').css({transform: 'rotate(' + angle + 'deg)'});
}

This doesn't work at present, the needle snaps to the angles in the array, and makes only minute movements for values in between two intervals.

I"m not a mathematician by any standards, so was hoping someone could assist with the math in the above. The solution seems extremely close, but just doesn't cut it quite just yet.

Upvotes: 2

Views: 603

Answers (1)

Blindy
Blindy

Reputation: 67449

The argument to your cos function is wrong. Your goal here is to emulate the lerp function, y1*(1-f)+y2*f, where f is between 0 and 1.

That means that the argument to your cos function has to be between 0 and pi/2, where your range is a small subset of this depending on where in the whole sequence you are.

Upvotes: 1

Related Questions