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);
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 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 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>
Mass transitioning all resolved issues that have not been updated in the last month to closed state