Search code examples
openglmatrixglslscaleellipse

How to determine if a 2x2 matrix scales more in the x axis than the y axis?


Let M be an invertible 2x2 matrix. Let C be a circle of radius 1 centered at (0,0). Let E be the ellipse M*C with semi-major axis s1 and semi-minor axis s2. (Then s1 >= s2.) I need to find sx, the horizontal scale applied to C by M, and sy, the vertical scale applied to C by M.

I can measure s1 and s2 by performing singular value decomposition on M. (The algorithm I use is based on Pedro Gimeno's answer to Robust algorithm for 2x2 SVD. s1 is the bigger singular value and s2 is the smaller singular value.) I know that <sx,sy> equals either <s1,s2> or <s2,s1>, but I don't know which one; however, if I can determine that sx > sy, (by implementing the scalesMoreInXAxis(mat2) function below), then I can conclude that <sx,sy> = <s1,s2> (and vice versa if sx <= sy).

Here is my GLSL code:

bool scalesMoreInXAxis(mat2 m){
    // TODO: implement
    return false;
}

void main(){

    float a = M[0][0];
    float b = M[1][0];
    float c = M[0][1];
    float d = M[1][1];

    float e = (a + d) / 2.0;
    float f = (a - d) / 2.0;
    float g = (c + b) / 2.0;
    float h = (c - b) / 2.0;

    float q = sqrt(e*e + h*h);
    float r = sqrt(f*f + g*g);

    float s1 = q + r;       // Semi major axis
    float s2 = abs(q - r);  // Semi minor axis

    vec2 s = scalesMoreInXAxis(M) ? vec2(s1,s2) : vec2 (s2,s1);
}

Solution

  • What do you want to achieve? I don't understand what do you mean by semi-x axis.

    However, here's what I think, how can you calculate semi axises:

    let M=U*s*V (SVD decomposition)

    V*C will be C, as V is just a rotation (rotating a circle wouldn't change it).

    So, we left with U*s. This transformation is angle preserving. U*s will first scale the circle (so it becomes an ellipse with semi axises s*[1 0]' and s*[0 1]'), and then rotate it. So, the final semi axises are U*s*[1 0]' and U*s*[0 1]', which are the columns of U*s.

    Note: for a general matrix, there is no such question that "how does it scale in the horizontal direction". All one can say is how much scale happened for the original x-axis (I mean, how long become the original x-axis after the transformation), which is just the length of M*[1 0]', the length of the first column.