Singular cube

A singular cube is an n-dimensional generalization of the [0..1] range. On a plane, it's an axis-aligned square that has four corners in (0, 0), (1, 0), (1, 1), and (0, 0).

Bilinear transformation from the singular cube


Auxiliary figures:

Points:

(0, 0) (0, 1) (1, 1) (1, 0)

Polynomials:

Px(x, y) = ax 1 x y + ax 2 x + ax 3 y + ax 4
Py(x, y) = ay 1 x y + ay 2 x + ay 3 y + ay 4

Equations

Interpolating interpolants

// linear interpolation by the two values in 0 and 1
function lerp(y1, y2, x) {
    return y1 * (1. - x) + y2 * x;
}
	
function l_transform(points, x, y) {
    const x1 = lerp(points[0][0], points[1][0], x);
    const x2 = lerp(points[2][0], points[3][0], x);
    const x_transformed = lerp(x1, x2, y);
    const y1 = lerp(points[0][1], points[1][1], x);
    const y2 = lerp(points[2][1], points[3][1], x);
    const y_transformed = lerp(y1, y2, y);
    return [x_transformed, y_transformed];
}
	

Biquadratic


// quadratic interpolation by the three values in 0, 0.5, and 1
function qerp(y1, y2, y3, x) {
    const a = 2*y1 - 4*y2 + 2*y3;
    const b = -3*y1 + 4*y2 - y3;
    const c = y1;
    return a*x*x + b*x + c;
}
	
function q_transform(points, x, y) {
    const x1 = qerp(points[0][0], points[1][0], points[2][0], x);
    const x2 = qerp(points[3][0], points[4][0], points[5][0], x);
    const x3 = qerp(points[6][0], points[7][0], points[8][0], x);
    const x_transformed = qerp(x1, x2, x3, y);
    const y1 = qerp(points[0][1], points[1][1], points[2][1], x);
    const y2 = qerp(points[3][1], points[4][1], points[5][1], x);
    const y3 = qerp(points[6][1], points[7][1], points[8][1], x);
    const y_transformed = qerp(y1, y2, y3, y);
    return [x_transformed, y_transformed];
}
	

Linear-cubic


// cubic interpolation by the four values in 0, 1/3, 2/3 and 1
function cerp(y1, y2, y3, y4, x) {
    const a = -9*y1/2 + 27*y2/2 - 27*y3/2 + 9*y4/2;
    const b = 9*y1 - 45*y2/2 + 18*y3 - 9*y4/2;
    const c = -11*y1/2 + 9*y2 - 9*y3/2 + y4;
    const d = y1;
    return a*x*x*x + b*x*x + c*x + d;
}

function cl_transform(points, x, y) {
    const x1 = lerp(points[0][0], points[1][0], x);
    const x2 = lerp(points[2][0], points[3][0], x);
    const x3 = lerp(points[4][0], points[5][0], x);
    const x4 = lerp(points[6][0], points[7][0], x);
    const x_transformed = cerp(x1, x2, x3, x4, y);
    const y1 = lerp(points[0][1], points[1][1], x);
    const y2 = lerp(points[2][1], points[3][1], x);
    const y3 = lerp(points[4][1], points[5][1], x);
    const y4 = lerp(points[6][1], points[7][1], x);
    const y_transformed = cerp(y1, y2, y3, y4, y);
    return [x_transformed, y_transformed];
}