Use a Grid Coverage

Once we have created a GridCoverage2D, we can then use the class to perform useful tasks. Many uses require access to the class itself but more generic uses can interact with the instance through its GeoAPI GridCoverage interface.

Simple uses

The simple uses of grid coverages can call methods on the coverages themselves; for more complex uses we go through the Operations class as explained in the next section.

Views

There are several "views" of a GridCoverage2D object. Views are themselves GridCoverage2D objects but they privilege a particular numerical representation.

The GridCoverage2D can present its values as they were in the original data source; such values are considered to be the NATIVE values. Under a different view, the GridCoverage2D can present the values as transformed by the Category defined for each SampleDimension which are the GEOPHYSICAL values. Under the RENDERED view, the values obtained from the GridCoverage2D will be the same as under the PACKED view unless those values cannot be rendered by the rendering system in which case the Geotk module will change the values into renderable numbers. The PHOTOGRAPHIC view type will convert the original values first to their geophysical realization and then using the default color table of each Category into some coloured pixel value.

To change the view on a GridCoverage2D called myGridCov, we can:

GridCoverage2D scicov = myGridCov.getView(ViewType.GEOPHYSICS);

and similarly we can get a GridCoverage2D view of one of the other kind even going back to the original view.

evaluate(...)

Once armed with the appropriate view, we can use the evaluate(DirectPosition dp) method to obtain a nearest-neighbor interpolated value for any DirectPosition within the extent of the GridCoverage2D. As a trivial example, we could evaluate the scientific value of the GEOPHYSICS view created above at a particular DirectPosition with:

Object result = scicov.evaluate(somedp);

with the return value dependent on the contents of our grid coverage. There are a series of such evaluate methods which return values in more useful formats.

getRenderedImage()

We can trivially get an AWT image from a GridCoverage2D with a simple call to the getRenderedImage() method. The result is a standard RenderedImage.

Obviously we can combine two of these steps to go directly from the created grid coverage to the final image:

RenderedImage ri = myGridCoverage.getView(ViewType.GEOPHYSICS).getRenderedImage()

It should be possible, when generating the RenderedImage, to specify the color scheme to use for that particular image. Unfortunately, this is currently work in progress and the module does not yet handle redefining the color scheme at this point.

Advanced Uses

The coverage module provides some powerful methods to use the different views of the grid coverage. Many of these uses are backed by the standard JAI mechanisms behind the scenes, sometimes combined with the georeferencing operations of the referencing module.

Operations

The Operations class provides a default instance with a series of methods to perform operations on a grid coverage. We use the static instance Operations.DEFAULT which acts merely as a convenience wrapper around the DefaultProcessor.doOperation(..) method and provides type safety and a simpler argument list.

For all the methods which return Coverages, when using the Geotk implementation we can simply cast them to the GridCoverage2D.

resample(...)

We can create a new grid coverage which is a resampling of the original grid coverage into a new image. We start by defining the georeferenced geometry of the resulting image and then call the resample(...) method of the Operations.DEFAULT instance.

A new GridGeometry class can be defined using either an Envelope, height and width for convenience or, like for the GridCoverage2D constructor, using the Math Transform and Coordinate Reference System instead of the envelope.

Then we can invoke the resample(...) operation.

GridGeometry mygg = new GridGeometry(...);
GridCoverage2D covresample = (GridCoverage2D) Operations.DEFAULT.resample(scicov, mygg);

We can use the resample(...) method to transform any GridCoverage2D to another CRS.

CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:32632");
GridCoverage2D covtransformed = (GridCoverage2D) Operations.DEFAULT.resample(scicov,targetCRS);

This georeferencing transformation works backwards from what one might naively expect and from what happens with vector data. With vector data, tranformations take the positions in the original referencing system and calculate the positions in the target referencing system. In the GridCoverage2D system, we are expecting a regular grid in the target referencing system. Therefore, we first calculate the position of the grid points in the target referencing system, then, for each, we calculate the equivalent position in the original referencing system and estimate the value which the original grid would have at that calculated position.

interpolate(...)

Similarly, we can interpolate an image using the Operations class. In this case we need to pick the interpolation method we will use.

import javax.media.jai.Interpolation;

Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
GridCoverage2D covinterpol = (GridCoverage2D) Operations.DEFAULT.interpolate(scicov, interp);
RenderedImage ri = covinterpol.getRenderedImage();

CoverageStack

We can combine several GridCoverage2D instances into a 3 dimensional stack of coverages using the CoverageStack class.

SpatioTemporalCoverage

This is a wrapper around another coverage which allows us to call the evaluate(...) methods with coordinate and time values rather than forcing us to create the appropriate DirectPosition argument.

Next section: Operations on a Grid Coverage.