Search code examples
javagraphics2daffinetransform

Why invert method of AffineTransform in Graphics2D throw an error?


What is an example of inverted transform matrix that its invert can throw an error?

try {
        g2.getTransform().invert();
    } catch (NoninvertibleTransformException ex) {
        ex.printStackTrace();
    }

When it cannot be inverted, does that mean the matrix will be the same, so the inverted and original transform matrix will be the equal?

Any example please?

Thanks


Solution

  • No, if a transform cannot be inverted, it means that it's inverse transform simply does not exist.

    The inverse transform B of some transform A must fulfill the following property:

    B(A(p)) = p   for all points p,
    

    i.e. applying the inverse transform on the transform of p returns the original p.

    Now, some transforms just don't have a transform with this property. For example, an affine transform with scaling of zero transforms all possible points in the plane to a single point; its inverse can not exist as it would need to transform that single point back to the multiple original points.

    The API docs do not say anything about reasons for this exception except stating that a matrix is invertible if and only if its determinant is non-zero.

    From practical experience, the most common reason for this to happen is when you use the view transform to scale your view window to the viewport size, and your viewport size becomes 0 (in x or y dimension). In this case, the inverse transform does not really matter as the is nothing to display in your viewport anyway, and you should be able to safely ignore it.

    However, it is always be better to check first to prevent this exception; you can check whether getDeterminant() zero -- see below. The actual value Another possible reason for a NoninvertibleTransformException could be NaNs or infinite values in your original transform; this is just a guess, however -- I haven't checked, and the API docs don't say anything about it.

    To prevent this exception, you need to check that the determinant of the transform is not zero -- or, as we're talking floating-point here, you need to check it is not too small, something like

    if (Math.abs(transform.getDeterminant()) < EPS) {
        return; // probably not invertible
    }
    AffineTransform inverse = transform.invert();
    

    The exact value of the EPS above depends on your application, but for double precision, something like 1.0e-8 should be safe enough for most cases.