Renderer 2D 3D Bridge results in non-invertable transform exception

Description

This may not strictly be a GeoTools issue, it is just that the stack trace is coming out of the renderer module so I am going to start my bug hunt there.

Andrea was kind enough to submit recast my 3D-2D downcast as a MathTransform and cleanly adapt the renderer code to expect a MathTransform (rather than a MathTransform2D).

Unfortunately this is producing the following exception:

2012-12-11 10:28:29,817 ERROR [org.geotools.rendering] - Transform is not invertible.
org.opengis.referencing.operation.NoninvertibleTransformException: Transform is not invertible.
at org.geotools.referencing.operation.transform.ProjectiveTransform.inverse(ProjectiveTransform.java:511)
at org.geotools.referencing.operation.transform.ProjectiveTransform2D.inverse(ProjectiveTransform2D.java:49)
at org.geotools.referencing.operation.transform.ProjectiveTransform2D.inverse(ProjectiveTransform2D.java:31)
at org.geotools.referencing.operation.transform.ConcatenatedTransform.inverse(ConcatenatedTransform.java:524)
at org.geotools.renderer.lite.StreamingRenderer$RenderableFeature.getTransformedShape(StreamingRenderer.java:3277)
at org.geotools.renderer.lite.StreamingRenderer$RenderableFeature.getShape(StreamingRenderer.java:3229)
at org.geotools.renderer.lite.StreamingRenderer.processSymbolizers(StreamingRenderer.java:2749)
at org.geotools.renderer.lite.StreamingRenderer.process(StreamingRenderer.java:2661)
at org.geotools.renderer.lite.StreamingRenderer.drawPlain(StreamingRenderer.java:2494)
at org.geotools.renderer.lite.StreamingRenderer.processStylers(StreamingRenderer.java:2044)
at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:828)
at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:490)
at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:254)
at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:126)
at org.geoserver.wms.GetMap.executeInternal(GetMap.java:465)
at org.geoserver.wms.GetMap.run(GetMap.java:201)
at org.geoserver.wms.GetMap.run(GetMap.java:111)
at org.geoserver.wms.DefaultWebMapService.getMap(DefaultWebMapService.java:356)
...
Caused by: javax.vecmath.MismatchedSizeException: cannot invert non square matrix
at javax.vecmath.GMatrix.invertGeneral(Unknown Source)
at javax.vecmath.GMatrix.invert(Unknown Source)
at org.geotools.referencing.operation.transform.ProjectiveTransform.inverse(ProjectiveTransform.java:505)
... 124 more

The exception seems fair, we cannot strictly invert this matrix - formally we are going with the assumption that WGS84 at 0 height will be fine (for what we hope is a bounding box calculation. If we want to be slightly kinder we could use WGS84 at the height of mount everest to cast a slightly wider bounding box conversion...

Initial thought was to:

1. Make a second MathTransform going the other way (armed with the above height assumption)
2. Fill in a MathTransform.inverse() method

Turns out a normal ConcatenatedTransform was used, so going to use a combination of identifying the special case up front and avoiding calling inverse().

available)
MathTransform reverse = ;
) {
ConcatenatedTransform
&& ((ConcatenatedTransform) sa.crsxform).transform1
.getTargetDimensions() >= 3
&& ((ConcatenatedTransform) sa.crsxform).transform2
.getTargetDimensions() == 2) {
reverse = // We are downcasting 3D data to 2D data so no inverse is available
} {
{
reverse = sa.crsxform.inverse();
} (Exception cannotReverse) {
reverse = // reverse transform not available
}
}
}
geom = projectionHandler.postProcess(reverse, geom);

Environment

None

Activity

Show:
codehaus
April 10, 2015, 3:12 PM

CodeHaus Comment From: jgarnett - Time: Sun, 16 Dec 2012 06:46:36 -0600
---------------------
Simply catching the exception does allow me to render again, the transform inverse is being constructed to pass into a post process routine:

    // first generalize and transform the geometry into the rendering CRS

    Decimator d = getDecimator(sa.xform);

    d.decimateTransformGeneralize(geom, sa.crsxform);

    geom.geometryChanged();

    // then post process it (provide reverse transform if available)

    MathTransform reverse;

    try {

        reverse = sa.crsxform == null ? null : sa.crsxform.inverse();

    } catch (Exception cannotReverse){

        reverse = null; // cannot reverse 2D/3D transform

    }

    geom = projectionHandler.postProcess(reverse, geom);

While that is not quite as a cool as constructing an inverse(), the comments indicated that we could provide a transform "if available", so I think this will work as a temporary fix (and am submitting it as a patch).

codehaus
April 10, 2015, 3:12 PM

CodeHaus Comment From: jgarnett - Time: Sun, 16 Dec 2012 06:50:25 -0600
---------------------
The supplied patch gets us back to where we started (producing the same screen snap example as attached to the parent issue)

codehaus
April 10, 2015, 3:12 PM

CodeHaus Comment From: jgarnett - Time: Mon, 17 Dec 2012 10:29:30 -0600
---------------------
<a href="https://github.com/geotools/geotools/pull/84">https://github.com/geotools/geotools/pull/84</a>

Andrea Aime
February 15, 2017, 11:33 AM

Mass transitioning all resolved issues that have not been updated in the last month to closed state

Fixed

Assignee

Jody Garnett

Reporter

codehaus

Triage

None

Components

Fix versions

Priority

Medium
Configure