Package org.apache.sis.coverage.grid

# Class GridDerivation

Object
GridDerivation

public class GridDerivation extends Object
Creates a new grid geometry derived from a base grid geometry with different extent or resolution. `GridDerivation` are created by calls to `GridGeometry​.derive()`. Properties of the desired grid geometry can be specified by calls to the following methods, in that order (each method is optional):

1. `rounding(GridRoundingMode)`, `margin(int...)` and/or `chunkSize(int...)` in any order
2. `subgrid(GridGeometry)`, `subgrid(Envelope, double...)` or `subgrid(GridExtent, int...)`
3. `slice(DirectPosition)` and/or `sliceByRatio(double, int...)`

Then the grid geometry is created by a call to `build()`. The `getIntersection()` method can also be invoked for the `GridExtent` part without subsampling.

All methods in this class preserve the number of dimensions. For example the `slice(DirectPosition)` method sets the grid size to 1 in all dimensions specified by the slice point, but does not remove those dimensions from the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.

Since:
  1.0
See Also:
  - `GridGeometry​.derive()`
  - `GridGeometry​.reduce(int...)`

Defined in the `sis-feature` module

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final GridGeometry`
  `base`
  The base grid geometry from which to derive a new grid geometry.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `GridDerivation(GridGeometry base)`
  Creates a new builder for deriving a grid geometry from the specified base.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `GridGeometry`
  `build()`
  Builds a grid geometry with the configuration specified by the other methods in this `GridDerivation` class.
  `GridDerivation`
  `chunkSize(int... cellCounts)`
  Specifies the size of tiles or chunks in the base grid geometry.
  `GridDerivation`
  `clipping(GridClippingMode mode)`
  Specifies whether to clip the derived grid extent to the extent of the base grid geometry.
  `double`
  `getGlobalScale()`
  Deprecated.
  To be removed for avoiding operations that mix potentially unrelated dimensions.
  `GridExtent`
  `getIntersection()`
  Returns the extent of the modified grid geometry, ignoring subsampling or changes in resolution.
  `int[]`
  `getSubsampling()`
  Returns the strides for accessing cells along each axis of the base grid.
  `int[]`
  `getSubsamplingOffsets()`
  Returns the offsets to be subtracted from pixel coordinates before subsampling.
  `int[]`
  `getSubsamplings()`
  Deprecated.
  Renamed `getSubsampling()` (without "s" because "subsampling" is uncountable).
  `GridDerivation`
  `margin(int... cellCounts)`
  Specifies an amount of cells by which to expand `GridExtent` after rounding.
  `GridDerivation`
  `maximumSubsampling(int... subsampling)`
  Specifies the maximum subsampling values (inclusive) for each dimension.
  `GridDerivation`
  `resize(GridExtent extent, double... scales)`
  Deprecated.
  This method does not handle margin, chunk size and clipping according their contract.
  `GridDerivation`
  `rounding(GridRoundingMode mode)`
  Controls behavior of rounding from floating point values to integers.
  `GridDerivation`
  `slice(DirectPosition slicePoint)`
  Requests a grid geometry for a slice at the given "real world" position.
  `GridDerivation`
  `sliceByRatio(double sliceRatio, int... dimensionsToKeep)`
  Requests a grid geometry for a slice at the given relative position.
  `GridDerivation`
  `subgrid(GridExtent areaOfInterest, int... subsampling)`
  Requests a grid geometry over a sub-region of the base grid geometry and optionally with subsampling.
  `GridDerivation`
  `subgrid(GridGeometry areaOfInterest)`
  Adapts the base grid for the geographic area and resolution of the given grid geometry.
  `GridDerivation`
  `subgrid(Envelope areaOfInterest, double... resolution)`
  Requests a grid geometry over a sub-envelope and optionally with a different a coarser resolution.
  `GridDerivation`
  `subsample(int... subsampling)`
  Deprecated.
  Replaced by `subgrid(GridExtent, int...)` with a `null` extent.
  `String`
  `toString()`
  Returns a string representation of this `GridDerivation` for debugging purpose.

  ### Methods inherited from class Object

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

- ## Field Details

  - ### base

    protected final GridGeometry base
    The base grid geometry from which to derive a new grid geometry.

- ## Constructor Details

  - ### GridDerivation

    protected GridDerivation(GridGeometry base)
    Creates a new builder for deriving a grid geometry from the specified base.
    Parameters:
      `base` - the base to use as a template for deriving a new grid geometry.
    See Also:
      - `GridGeometry​.derive()`

- ## Method Details

  - ### rounding

    public GridDerivation rounding(GridRoundingMode mode)
    Controls behavior of rounding from floating point values to integers. This setting modifies computations performed by the following methods (it has no effect on other methods in this `GridDerivation` class):
    - `slice(DirectPosition)`
    - `subgrid(Envelope, double...)`
    If this method is never invoked, the default value is `GridRoundingMode​.NEAREST`. If this method is invoked too late, an `IllegalStateException` is thrown.
    Parameters:
      `mode` - the new rounding mode.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalStateException` - if `subgrid(Envelope, double...)` or `slice(DirectPosition)` has already been invoked.

  - ### clipping

    public GridDerivation clipping(GridClippingMode mode)
    Specifies whether to clip the derived grid extent to the extent of the base grid geometry. The default value is `GridClippingMode​.STRICT`.
    Parameters:
      `mode` - whether to clip the derived grid extent.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalStateException` - if `subgrid(Envelope, double...)` or `slice(DirectPosition)` has already been invoked.
    Since:
      1.1

  - ### margin

    public GridDerivation margin(int... cellCounts)
    Specifies an amount of cells by which to expand `GridExtent` after rounding. This setting modifies computations performed by the following methods:
    - `subgrid(GridGeometry)`
    - `subgrid(Envelope, double...)`
    - `subgrid(GridExtent, int...)`
    For each dimension i of the grid computed by above methods, the low grid coordinate is subtracted by `cellCount[i]` and the high grid coordinate is increased by `cellCount[i]`. This calculation is done in units of the base grid cells, i.e. before subsampling. For example if subsampling is 2, then a margin of 6 cells specified with this method will result in a margin of 3 cells in the grid extent computed by the `build()` method.
    Use case: if the caller wants to apply bilinear interpolations in an image, (s)he will need 1 more pixel on each image border. If the caller wants to apply bi-cubic interpolations, (s)he will need 2 more pixels on each image border.
    If this method is never invoked, the default value is zero for all dimensions. If this method is invoked too late, an `IllegalStateException` is thrown. If the `cellCounts` array length is shorter than the grid dimension, then zero is assumed for all missing dimensions.
    Parameters:
      `cellCounts` - number of cells by which to expand the grid extent.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalArgumentException` - if a value is negative.
      `IllegalStateException` - if `subgrid(Envelope, double...)` or `slice(DirectPosition)` has already been invoked.
    See Also:
      - `GridExtent​.expand(long...)`

  - ### chunkSize

    public GridDerivation chunkSize(int... cellCounts)
    Specifies the size of tiles or chunks in the base grid geometry. If a chunk size is specified, then the grid extent computed by `build()` will span an integer amount of chunks. The grid coordinates (0, 0, …) locate the corner of a chunk.

    This property operates on the same methods than the margin. If both a margin and a chunk size are specified, then margins are added first and the resulting grid coordinates are rounded to chunk size. This calculation is done in units of the base grid cells, i.e. before subsampling. For example if subsampling is 2, then a tile size of 20×20 pixels specified with this method will result in a tile size of 10×10 cells in the grid extent computed by the `build()` method.

    If this method is never invoked, the default value is one for all dimensions. If this method is invoked too late, an `IllegalStateException` is thrown. If the `cellCounts` array length is shorter than the grid dimension, then one is assumed for all missing dimensions.

    Parameters:
      `cellCounts` - number of cells in all tiles or chunks.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalArgumentException` - if a value is zero or negative.
      `IllegalStateException` - if `subgrid(Envelope, double...)` or `slice(DirectPosition)` has already been invoked.
    Since:
      1.1

  - ### maximumSubsampling

    public GridDerivation maximumSubsampling(int... subsampling)
    Specifies the maximum subsampling values (inclusive) for each dimension. If a subsampling value is greater than a specified value in the corresponding dimension, the subsampling will be clamped to the specified maximal value. Setting a maximum value of 1 in a dimension is equivalent to disabling subsampling in that dimension.

    If this method is never invoked, then there is no maximum value. If this method is invoked too late, an `IllegalStateException` is thrown. If the `cellCounts` array length is shorter than the grid dimension, then all missing dimensions have no maximum value.

    Parameters:
      `subsampling` - maximal subsampling values (inclusive).
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalArgumentException` - if a value is zero or negative.
      `IllegalStateException` - if `subgrid(Envelope, double...)` or `slice(DirectPosition)` has already been invoked.
    Since:
      1.1

  - ### resize

    @Deprecated public GridDerivation resize(GridExtent extent, double... scales)
    Deprecated.
    This method does not handle margin, chunk size and clipping according their contract. It is replaced by `subgrid(GridExtent, int...)`.
    Requests a grid geometry where cell sizes have been scaled by the given factors, which result in a change of grid size. The new grid geometry is given a "grid to CRS" transform computed as the concatenation of given scale factors (applied on grid indices) followed by the grid to CRS transform of the grid geometry specified at construction time. The resulting grid extent can be specified explicitly (typically as an extent computed by `GridExtent​.resize(long...)`) or computed automatically by this method.
    Example: if the original grid geometry had an extent of [0 … 5] in x and [0 … 8] in y, then a call to `resize(null, 0.1, 0.1)` will build a grid geometry with an extent of [0 … 50] in x and [0 … 80] in y. This new extent covers the same geographic area than the old extent but with pixels having a size of 0.1 times the old pixels size. The grid to CRS transform of the new grid geometry will be pre-concatenated with scale factors of 0.1 in compensation for the shrink in pixels size.

    Notes:

    - This method can be invoked only once.
    - This method can not be used together with a `subgrid(…)` method.
    - If a non-default rounding mode or a non-default clipping mode is desired, they should be specified before to invoke this method.
    - If the grid extent is recomputed by this method, then the margin and chunkSize(int...) will be taken in account.
    - This method does not reduce the number of dimensions of the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.
    The `scales` parameter in this method can be seen as an alternative to the `resolution` parameter in `subgrid(Envelope, double...)` working in grid coordinates space instead of CRS coordinates space.
    Parameters:
      `extent` - the grid extent to set as a result of the given scale, or `null` for computing it automatically. If non-null, then this given extent is used as-is without checking intersection with the base grid geometry.
      `scales` - the scale factors to apply on grid indices. If the length of this array is smaller than the number of grid dimension, then a scale of 1 is assumed for all missing dimensions.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalStateException` - if a `subgrid(…)` or `slice(…)` method has already been invoked.
    See Also:
      - `subsample(int...)`
      - `GridExtent​.resize(long...)`

  - ### subgrid

    public GridDerivation subgrid(GridGeometry areaOfInterest)
    Adapts the base grid for the geographic area and resolution of the given grid geometry. The new grid geometry will cover the spatiotemporal region given by `areaOfInterest` envelope (coordinate operations are applied as needed if the Coordinate Reference Systems are not the same). The new grid geometry resolution will be integer multiples of the `base` grid geometry resolution.
    Usage: This method can be helpful for implementation of `GridCoverageResource​.read(GridGeometry, int...)`. Example:

    >     class MyDataStorage extends GridCoverageResource {
    >         @Override
    >         public GridCoverage read(GridGeometry domain, int... range) throws DataStoreException {
    >             GridDerivation change = getGridGeometry().derive().subgrid(domain);
    >             GridExtent toRead = change.buildExtent();
    >             int[] subsampling = change.getSubsampling());
    >             // Do reading here.
    >         }
    >     }

    If `gridExtent` contains only an envelope, then this method delegates to `subgrid(Envelope, double...)`. Otherwise if `gridExtent` contains only an extent, then this method delegates to `subgrid(GridExtent, int...)`. Otherwise the following information are mandatory:
    - Extent in `areaOfInterest`.
    - Grid to CRS conversion in `areaOfInterest`.
    - Grid to CRS conversion in `base` grid.
    The following information are optional but recommended:
    - Coordinate reference system in `areaOfInterest`.
    - Coordinate reference system in `base` grid.
    - Extent in `base` grid.
    Optional margin and chunk size can be specified for increasing the size of the grid extent computed by this method. For example if the caller wants to apply bilinear interpolations in an image, (s)he will need 1 more pixel on each image border. If the caller wants to apply bi-cubic interpolations, (s)he will need 2 more pixels on each image border.

    Notes:

    - This method can be invoked only once.
    - This method can not be used together with another `subgrid(…)` method.
    - Rounding mode, clipping mode, margin and chunk size, if different than default values, should be set before to invoke this method.
    - Slicing can be applied after this method.
    - This method does not reduce the number of dimensions of the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.
    Parameters:
      `areaOfInterest` - the area of interest and desired resolution as a grid geometry.
    Returns:
      `this` for method call chaining.
    Throws:
      `DisjointExtentException` - if the given grid of interest does not intersect the grid extent.
      `IncompleteGridGeometryException` - if a mandatory property of a grid geometry is absent.
      `IllegalGridGeometryException` - if an error occurred while converting the envelope coordinates to grid coordinates.
      `IllegalStateException` - if a `subgrid(…)` or `slice(…)` method has already been invoked.
    See Also:
      - `getIntersection()`
      - `getSubsampling()`

  - ### subgrid

    public GridDerivation subgrid(Envelope areaOfInterest, double... resolution)
    Requests a grid geometry over a sub-envelope and optionally with a different a coarser resolution. The given envelope does not need to be expressed in the same coordinate reference system (CRS) than the CRS of the base grid geometry; coordinate conversions or transformations will be applied as needed. That envelope CRS may have fewer dimensions than the base grid geometry CRS, in which case grid dimensions not mapped to envelope dimensions will be returned unchanged. The target resolution, if provided, shall be in same units and same order than the given envelope axes. If the length of `resolution` array is less than the number of dimensions of `areaOfInterest`, then no subsampling will be applied on the missing dimensions.

    Notes:

    - This method can be invoked only once.
    - This method can not be used together with another `subgrid(…)` method.
    - Rounding mode, clipping mode, margin and chunk size, if different than default values, should be set before to invoke this method.
    - Slicing can be applied after this method.
    - This method does not reduce the number of dimensions of the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.
    - If the given envelope is known to be expressed in the same CRS than the grid geometry, then the CRS of the envelope can be left unspecified (`null`). It may give a slight performance improvement by avoiding the check for coordinate transformation.
    - Subsampling computed by this method may be fractional. Consequently calls to `getSubsampling()` and `getSubsamplingOffsets()` after this method may cause an `IllegalStateException` to be thrown.
    Parameters:
      `areaOfInterest` - the desired spatiotemporal region in any CRS (transformations will be applied as needed), or `null` for not restricting the sub-grid to a sub-area.
      `resolution` - the desired resolution in the same units and order than the axes of the given envelope, or `null` or an empty array if no subsampling is desired. The array length should be equal to the `areaOfInterest` dimension, but this is not mandatory (zero or missing values mean no sub-sampling, extraneous values are ignored).
    Returns:
      `this` for method call chaining.
    Throws:
      `DisjointExtentException` - if the given area of interest does not intersect the grid extent.
      `IncompleteGridGeometryException` - if the base grid geometry has no extent, no "grid to CRS" transform, or no CRS (unless `areaOfInterest` has no CRS neither, in which case the CRS are assumed the same).
      `IllegalGridGeometryException` - if an error occurred while converting the envelope coordinates to grid coordinates.
      `IllegalStateException` - if a `subgrid(…)` or `slice(…)` method has already been invoked.
    See Also:
      - `getIntersection()`
      - `getSubsampling()`

  - ### subgrid

    public GridDerivation subgrid(GridExtent areaOfInterest, int... subsampling)
    Requests a grid geometry over a sub-region of the base grid geometry and optionally with subsampling. The given grid geometry must have the same number of dimension than the base grid geometry. If the length of `subsampling` array is less than the number of dimensions, then no subsampling will be applied on the missing dimensions.

    Notes:

    - This method can be invoked only once.
    - This method can not be used together with another `subgrid(…)` method.
    - Rounding mode, clipping mode, margin and chunk size, if different than default values, should be set before to invoke this method.
    - Slicing can be applied after this method.
    - This method does not reduce the number of dimensions of the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.
    Parameters:
      `areaOfInterest` - the desired grid extent in unit of base grid cell (i.e. ignoring subsampling), or `null` for not restricting the sub-grid to a sub-area.
      `subsampling` - the subsampling to apply on each grid dimension, or `null` if none. All values shall be greater than zero. If the array length is shorter than the number of dimensions, missing values are assumed to be 1.
    Returns:
      `this` for method call chaining.
    Throws:
      `DisjointExtentException` - if the given area of interest does not intersect the grid extent.
      `IncompleteGridGeometryException` - if the base grid geometry has no extent, no "grid to CRS" transform, or no CRS (unless `areaOfInterest` has no CRS neither, in which case the CRS are assumed the same).
      `IllegalStateException` - if a `subgrid(…)` or `slice(…)` method has already been invoked.
    Since:
      1.1
    See Also:
      - `getIntersection()`
      - `getSubsampling()`

  - ### subsample

    @Deprecated public GridDerivation subsample(int... subsampling)
    Deprecated.
    Replaced by `subgrid(GridExtent, int...)` with a `null` extent.
    Applies a subsampling on the grid geometry to build. This method can be invoked as an alternative to `subgrid(…)` methods if only the resolution needs to be changed. The extent of the built grid geometry will be derived from `getIntersection()` as below for each dimension i:
    - The low is divided by `subsampling[i]`, rounded toward zero.
    - The size is divided by `subsampling[i]`, rounded toward zero.
    - The high is recomputed from above low and size.
    The grid to CRS transform is scaled accordingly

    #### Preconditions

    This method assumes that subsampling are divisors of chunk sizes and are not greater than the maximum subsampling. It is caller responsibility to ensure that those preconditions are met.
    Parameters:
      `subsampling` - the subsampling to apply on each grid dimension. All values shall be greater than zero. If the array length is shorter than the number of dimensions, missing values are assumed to be 1.
    Returns:
      `this` for method call chaining.
    Throws:
      `IllegalStateException` - if a subsampling has already been set, for example by a call to `subgrid(…)`.
    See Also:
      - `subgrid(GridExtent, int...)`
      - `getSubsampling()`
      - `GridExtent​.subsample(int...)`

  - ### slice

    public GridDerivation slice(DirectPosition slicePoint)
    Requests a grid geometry for a slice at the given "real world" position. The given position can be expressed in any coordinate reference system (CRS). The position should not define a coordinate for all dimensions, otherwise the slice would degenerate to a single point. Dimensions can be left unspecified either by assigning to `slicePoint` a CRS without those dimensions, or by assigning the NaN value to some coordinates.
    Example: if the coordinate reference system of base grid geometry has (longitude, latitude, time) axes, then a (longitude, latitude) slice at time t can be created with one of the following two positions:
    - A three-dimensional position with (`Double​.NaN`, `Double​.NaN`, t) coordinates.
    - A one-dimensional position with (t) coordinate and the coordinate reference system set to the temporal component of the grid geometry CRS.

    Notes:

    - This method can be invoked after `subgrid(Envelope, double...)`, but not before.
    - If a non-default rounding mode is desired, it should be specified before to invoke this method.
    - This method does not reduce the number of dimensions of the grid geometry. For dimensionality reduction, see `GridGeometry​.reduce(int...)`.
    - If the given point is known to be expressed in the same CRS than the grid geometry, then the CRS of the point can be left unspecified (`null`). It may give a slight performance improvement by avoiding the check for coordinate transformation.
    Parameters:
      `slicePoint` - the coordinates where to get a slice. If no coordinate reference system is attached to it, we consider it's the same as base grid geometry.
    Returns:
      `this` for method call chaining.
    Throws:
      `IncompleteGridGeometryException` - if the base grid geometry has no extent, no "grid to CRS" transform, or no CRS (unless `slicePoint` has no CRS neither, in which case the CRS are assumed the same).
      `IllegalGridGeometryException` - if an error occurred while converting the point coordinates to grid coordinates.
      `PointOutsideCoverageException` - if the given point is outside the grid extent.

  - ### sliceByRatio

    public GridDerivation sliceByRatio(double sliceRatio, int... dimensionsToKeep)
    Requests a grid geometry for a slice at the given relative position. The relative position is specified by a ratio between 0 and 1 where 0 maps to low grid coordinates, 1 maps to high grid coordinates and 0.5 maps to the median position. The slicing is applied on all dimensions except the specified dimensions to keep.
    Example: given a n-dimensional cube, the following call creates a slice of the two first dimensions (numbered 0 and 1, typically the dimensions of x and y axes) located at the center (ratio 0.5) of all other dimensions (typically z and/or t axes):

    >     gridGeometry.derive().sliceByRatio(0.5, 0, 1).build();

    Parameters:
      `sliceRatio` - the ratio to apply on all grid dimensions except the ones to keep.
      `dimensionsToKeep` - the grid dimension to keep unchanged.
    Returns:
      `this` for method call chaining.
    Throws:
      `IncompleteGridGeometryException` - if the base grid geometry has no extent.
      `IndexOutOfBoundsException` - if a `dimensionsToKeep` value is out of bounds.

  - ### build

    public GridGeometry build()
    Builds a grid geometry with the configuration specified by the other methods in this `GridDerivation` class.
    Returns:
      the modified grid geometry. May be the `base` grid geometry if no change apply.
    Throws:
      `IllegalGridGeometryException` - if the grid geometry can not be computed because of arguments given to a `subgrid(…)` or other methods.
    See Also:
      - `getIntersection()`

  - ### getIntersection

    public GridExtent getIntersection()
    Returns the extent of the modified grid geometry, ignoring subsampling or changes in resolution. This is the intersection of the `base` grid geometry with the (grid or geospatial) envelope given to a `subgrid(…)` method, expanded by the specified margin (if any) and potentially with some grid sizes set to 1 if a `slice(…)` method has been invoked. The returned extent is in units of the `base` grid cells, i.e. subsampling is ignored.

    This method can be invoked after `build()` for getting additional information.

    Returns:
      intersection of grid geometry extents in units of `base` grid cells.

  - ### getSubsamplings

    @Deprecated public int[] getSubsamplings()
    Deprecated.
    Renamed `getSubsampling()` (without "s" because "subsampling" is uncountable).

  - ### getSubsampling

    public int[] getSubsampling()
    Returns the strides for accessing cells along each axis of the base grid. Those values define part of the conversion from derived grid coordinates (x, y, z) to base grid coordinates (x′, y′, z′) as below (generalize to as many dimensions as needed):
    - x′ = s₀⋅x + t₀
    - y′ = s₁⋅y + t₁
    - z′ = s₂⋅z + t₂
    This method returns the {s₀, s₁, s₂} values while `getSubsamplingOffsets()` returns the {t₀, t₁, t₂} values. All subsampling values are strictly positive integers.
    Application to iterations
    Iteration over `areaOfInterest` grid coordinates with a stride Δx=1 corresponds to an iteration in `base` grid coordinates with a stride of Δx′=s₀, a stride Δy=1 corresponds to a stride Δy′=s₁, etc.
    This method can be invoked after `build()` for getting additional information. If `subgrid(GridExtent, int...)` has been invoked, then this method returns the values that were given in the `subsampling` argument.
    Returns:
      an estimation of the strides for accessing cells along each axis of `base` grid.
    Throws:
      `IllegalStateException` - if the subsampling factors are not integers. It may happen if the derived grid has been constructed by a call to `subgrid(Envelope, double...)`.
    Since:
      1.1
    See Also:
      - `getSubsamplingOffsets()`
      - `subgrid(GridGeometry)`
      - `subgrid(GridExtent, int...)`

  - ### getSubsamplingOffsets

    public int[] getSubsamplingOffsets()
    Returns the offsets to be subtracted from pixel coordinates before subsampling. In a conversion from derived grid to base grid coordinates (the opposite direction of subsampling), the offset is the value to add after multiplication by the scale factor. It may be negative.

    This method can be invoked after `build()` for getting additional information.

    Returns:
      conversion from the new grid to the original grid specified to the constructor.
    Throws:
      `IllegalStateException` - if the subsampling offsets are not integers. It may happen if the derived grid has been constructed by a call to `subgrid(Envelope, double...)`.
    Since:
      1.1
    See Also:
      - `getSubsampling()`
      - `subgrid(GridGeometry)`
      - `subgrid(GridExtent, int...)`

  - ### getGlobalScale

    @Deprecated public double getGlobalScale()
    Deprecated.
    To be removed for avoiding operations that mix potentially unrelated dimensions.
    Returns an estimation of the scale factor when converting sub-grid coordinates to `base` grid coordinates. This is for information purpose only since this method combines potentially different scale factors for all dimensions.
    Returns:
      an estimation of the scale factor for all dimensions.

  - ### toString

    public String toString()
    Returns a string representation of this `GridDerivation` for debugging purpose. The returned string is implementation dependent and may change in any future version.
    Overrides:
      `toString` in class `Object`
    Returns:
      a string representation of this `GridDerivation` for debugging purpose.