Package org.apache.sis.coverage.grid

# Class GridCoverageBuilder

Object
GridCoverageBuilder

public class GridCoverageBuilder extends Object
Helper class for the creation of `GridCoverage` instances. A grid coverage is a function described by three parts:

- A domain, which describes the input values (e.g. geographic coordinates).
- One or more ranges, which describe the output values that the coverage can produce.
- The actual values, distributed on a regular grid.

Each of those parts can be set by a `setDomain(…)`, `setRanges(…)` or `setValues(…)` method. Those methods are overloaded with many variants accepting different kind of arguments. For example values can be specified as a `RenderedImage`, a `Raster` or some other types.
Example: the easiest way to create a `GridCoverage` from a matrix of values is to set the values in a `WritableRaster` and to specify the domain as an `Envelope`:

>     WritableRaster data = Raster.createBandedRaster​(DataBuffer.TYPE_USHORT, width, height, numBands, null);
>     for (int y=0; y<height; y++) {
>         for (int x=0; x<width; x++) {
>             int value = ...;                     // Compute a value here.
>             data.setSample(x, y, 0, value);      // Set value in the first band.
>         }
>     }
>     GridCoverageBuilder builder = new GridCoverageBuilder();
>     builder.setValues(data).flixAxis(1);

>     Envelope domain = ...;                       // Specify here the "real world" coordinates.
>     GridCoverage coverage = builder.setDomain(domain).build();

## Limitations

Current implementation creates only two-dimensional coverages. A future version may extend this builder API for creating n-dimensional coverages.

Since:
  1.1
See Also:
  - `GridCoverage2D`
  - `SampleDimension​.Builder`

Defined in the `sis-feature` module

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `GridCoverageBuilder()`
  Creates an initially empty builder.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `addImageProperty(String key, Object value)`
  Adds a value associated to an image property.
  `GridCoverageBuilder`
  `addRange(SampleDimension band)`
  Adds a sample dimension for one band.
  `GridCoverage`
  `build()`
  Creates the grid coverage from the domain, ranges and values given to setter methods.
  `GridCoverageBuilder`
  `flipGridAxis(int dimension)`
  Reverses axis direction in the specified grid dimension.
  `GridCoverageBuilder`
  `setDomain(GridGeometry grid)`
  Sets the domain envelope (including its CRS) and/or the transform from grid indices to domain coordinates.
  `GridCoverageBuilder`
  `setDomain(Envelope domain)`
  Sets the domain as an enclosing envelope (including its CRS).
  `GridCoverageBuilder`
  `setRanges(Collection<? extends SampleDimension> bands)`
  Sets the sample dimensions for all bands.
  `GridCoverageBuilder`
  `setRanges(SampleDimension... bands)`
  Sets the sample dimensions for all bands.
  `GridCoverageBuilder`
  `setValues(DataBuffer data, Dimension size)`
  Sets a two-dimensional slice of sample values as a Java2D data buffer.
  `GridCoverageBuilder`
  `setValues(Raster data)`
  Sets a two-dimensional slice of sample values as a raster.
  `GridCoverageBuilder`
  `setValues(RenderedImage data)`
  Sets a two-dimensional slice of sample values as a rendered image.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### GridCoverageBuilder

    public GridCoverageBuilder()
    Creates an initially empty builder.

- ## Method Details

  - ### setDomain

    public GridCoverageBuilder setDomain(GridGeometry grid)
    Sets the domain envelope (including its CRS) and/or the transform from grid indices to domain coordinates. The given `GridGeometry` does not need to contain a `GridExtent` because that extent will be computed automatically if needed. However if an extent is present, then it must be consistent with the size of data given to `setValues(…)` method (will be verified at `build()` time).
    Parameters:
      `grid` - the new grid geometry, or `null` for removing previous domain setting.
    Returns:
      `this` for method invocation chaining.

  - ### setDomain

    public GridCoverageBuilder setDomain(Envelope domain)
    Sets the domain as an enclosing envelope (including its CRS). The given envelope should contain all pixel area. For example the envelope lower corner should locate the lower-left (or upper-left, depending on y axis orientation) pixel corner, not pixel center. If the given envelope contains a CRS, then that CRS will be the coverage CRS. A transform from grid indices to domain coordinates will be created automatically. That transform will map grid dimensions to envelope dimensions in the same order (i.e. the matrix representation of the affine transform will be diagonal, ignoring the translation column).

    #### Axis directions

    By default grid indices increase in the same direction than domain coordinates. When applied to images with pixels located by (column, row) indices, it means that by default row indices in the image are increasing toward up if the y coordinates in the coverage domain (e.g. latitude values) are also increasing toward up. It often results in images flipped vertically, because popular image formats such as PNG use row indices increasing in the opposite direction (toward down). This effect can be compensated by invoking `flipGridAxis(1)`.
    Design note: `GridCoverageBuilder` does not flip the y axis by default because not all file formats have row indices increasing toward down. A counter-example is the netCDF format. Even if we consider that the majority of images have y axis flipped, things become less obvious when considering data in more than two dimensions. Having the same default policy (no flipping) for all dimensions make problem analysis easier.
    `GridCoverageBuilder` provides method only for flipping axes. If more sophisticated operations is desired (for example a rotation), then `setDomain(GridGeometry)` should be used instead of this method.

    #### Default implementation

    The default implementation creates a new `GridGeometry` from the given envelope then invokes `setDomain(GridGeometry)`. Subclasses can override that later method as a single overriding point for all domain settings.
    Parameters:
      `domain` - envelope of the coverage domain together with its CRS, or `null` for removing previous domain setting.
    Returns:
      `this` for method invocation chaining.
    See Also:
      - `flipGridAxis(int)`
      - `GridGeometry(GridExtent, Envelope)`

  - ### setRanges

    public GridCoverageBuilder setRanges(Collection<? extends SampleDimension> bands)
    Sets the sample dimensions for all bands. The list size must be equal to the number of bands in the data specified to `setValues(…)` method (it will be verified at `build()` time).
    Parameters:
      `bands` - the new sample dimensions, or `null` for removing previous range setting.
    Returns:
      `this` for method invocation chaining.
    Throws:
      `IllegalArgumentException` - if the given list is empty.
    See Also:
      - `SampleDimension​.Builder`

  - ### setRanges

    public GridCoverageBuilder setRanges(SampleDimension... bands)
    Sets the sample dimensions for all bands. The array length must be equal to the number of bands in the data specified to `setValues(…)` method (it will be verified at `build()` time).
    Parameters:
      `bands` - the new sample dimensions, or `null` for removing previous range setting.
    Returns:
      `this` for method invocation chaining.
    Throws:
      `IllegalArgumentException` - if the given array is empty.
    See Also:
      - `SampleDimension​.Builder`

  - ### addRange

    public GridCoverageBuilder addRange(SampleDimension band)
    Adds a sample dimension for one band. This method can be invoked repeatedly until the number of sample dimensions is equal to the number of bands in the data specified to `setValues(…)`.
    Parameters:
      `band` - the sample dimension to add.
    Returns:
      `this` for method invocation chaining.
    See Also:
      - `SampleDimension​.Builder`

  - ### setValues

    public GridCoverageBuilder setValues(RenderedImage data)
    Sets a two-dimensional slice of sample values as a rendered image. If sample dimensions are specified, then the number of bands must be equal to the number of sample dimensions.

    Note: row indices in an image are usually increasing down, while geographic coordinates are usually increasing up. Consequently the `flipGridAxis(1)` method may need to be invoked after this method.

    Parameters:
      `data` - the rendered image to be wrapped in a `GridCoverage`. Can not be `null`.
    Returns:
      `this` for method invocation chaining.
    See Also:
      - `BufferedImage`

  - ### setValues

    public GridCoverageBuilder setValues(Raster data)
    Sets a two-dimensional slice of sample values as a raster. If sample dimensions are specified, then the number of bands must be equal to the number of sample dimensions.

    Note: row indices in a raster are usually increasing down, while geographic coordinates are usually increasing up. Consequently the `flipGridAxis(1)` method may need to be invoked after this method.

    Parameters:
      `data` - the raster to be wrapped in a `GridCoverage`. Can not be `null`.
    Returns:
      `this` for method invocation chaining.
    See Also:
      - `Raster​.createBandedRaster(int, int, int, int, Point)`

  - ### setValues

    public GridCoverageBuilder setValues(DataBuffer data, Dimension size)
    Sets a two-dimensional slice of sample values as a Java2D data buffer. The number of banks will be the number of bands in the image. If sample dimensions are specified, then the number of bands must be equal to the number of sample dimensions.
    Parameters:
      `data` - the data buffer to be wrapped in a `GridCoverage`. Can not be `null`.
      `size` - the image size in pixels, or `null` if unspecified. If null, then the image size will be taken from the grid extent.
    Returns:
      `this` for method invocation chaining.
    Throws:
      `IllegalArgumentException` - if `width` or `height` is negative or equals to zero.

  - ### flipGridAxis

    public GridCoverageBuilder flipGridAxis(int dimension)
    Reverses axis direction in the specified grid dimension. For example if grid indices are (column, row), then `flipGridAxis(1)` will reverse the direction of rows axis. Invoking this method a second time for the same dimension will cancel the flipping.

    When building coverage with a domain specified by an envelope (i.e. with no explicit grid to CRS transform), the default `GridCoverageBuilder` behavior is to create a `GridGeometry` with grid indices increasing in the same direction than domain coordinates. This method allows to reverse direction for an axis. The most typical usage is to reverse the direction of the y axis in images.

    Parameters:
      `dimension` - index of the dimension in the grid to reverse direction.
    Returns:
      `this` for method invocation chaining.
    See Also:
      - `setDomain(Envelope)`
      - `GridOrientation​.flipGridAxis(int)`

  - ### addImageProperty

    public void addImageProperty(String key, Object value)
    Adds a value associated to an image property. This method can be invoked only once for each `key`. Those properties will be given to the `RenderedImage` created by the `build()` method.
    Parameters:
      `key` - key of the property to set.
      `value` - value to associate to the given key.
    Throws:
      `IllegalArgumentException` - if a value is already associated to the given key.
    Since:
      1.1

  - ### build

    public GridCoverage build() throws IllegalStateException
    Creates the grid coverage from the domain, ranges and values given to setter methods. The returned coverage is often a `GridCoverage2D` instance, but not necessarily.
    Returns:
      grid coverage created from specified domain, ranges and sample values.
    Throws:
      `IllegalStateException` - if some properties are inconsistent, for example grid extent not matching image size or number of sample dimensions not matching the number of bands. This exception often wraps an `IllegalGridGeometryException`, `IllegalArgumentException` or `NullArgumentException`.