# Class MergeStrategy

Object
MergeStrategy

public abstract class MergeStrategy extends Object
Algorithm to apply when more than one grid coverage can be found at the same grid index. A merge may happen if an aggregated coverage is created with `CoverageAggregator`, and the extent of some source coverages are overlapping in the dimension to aggregate. `MergeStrategy` is ignored if only one coverage is contained in a requested extent.

## Example

A collection of `GridCoverage` instances may represent the same phenomenon (for example, air temperature) over the same geographic area but at different days. In such case, `CoverageAggregator` can build a three-dimensional data cube where each source coverage is located at a different position on the time axis. But if two coverages have overlapping time ranges, and if a user request data in the overlapping region, then there is an ambiguity about which data to return. This `MergeStrategy` specifies how to handle this multiplicity.

## Default behavior

If no merge strategy is specified, then the default behavior is to throw `SubspaceNotSpecifiedException` in situations of ambiguity. An ambiguity happens at `GridCoverage​.render(GridExtent)` invocation time if more than one source coverage (slice) is found for a specified grid index.

Since:
  1.3
See Also:
  - `CoverageAggregator​.setMergeStrategy(MergeStrategy)`

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `MergeStrategy()`
  Creates a new merge strategy.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected abstract RenderedImage`
  `aggregate(RenderedImage[] sources)`
  Aggregates images that have been accepted by the filter.
  `Resource`
  `apply(Resource resource)`
  Returns a resource with the same data as the specified resource, but using this merge strategy.
  `protected int[]`
  `filter(GridGeometry request, GridGeometry[] candidates)`
  Returns the indexes of the coverages to use in the aggregation.
  `static MergeStrategy`
  `opaqueOverlay(Rectangle areaOfInterest)`
  Builds an image overlay of all sources.
  `static MergeStrategy`
  `selectByTimeThenArea(Duration timeGranularity)`
  Selects a single slice using criteria based first on temporal extent, then on geographic area.

  ### Methods inherited from class Object

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

- ## Constructor Details

  - ### MergeStrategy

    protected MergeStrategy()
    Creates a new merge strategy.
    Since:
      1.5

- ## Method Details

  - ### opaqueOverlay

    public static MergeStrategy opaqueOverlay(Rectangle areaOfInterest)
    Builds an image overlay of all sources. The source images added first have precedence (foreground). Images added last are in background. All bands are referenced or copied verbatim, without special treatment for the alpha channel. In other words, this merge strategy does not handle transparency in overlapping regions.
    Parameters:
      `areaOfInterest` - range of pixel coordinates, or `null` for the union of all images.
    Returns:
      a merge strategy for building an overlay of all source images.
    Since:
      1.5

  - ### selectByTimeThenArea

    public static MergeStrategy selectByTimeThenArea(Duration timeGranularity)
    Selects a single slice using criteria based first on temporal extent, then on geographic area. This strategy applies the following rules, in order:
    1. Slice having largest intersection with the time of interest (TOI) is selected.
    2. If two or more slices have the same intersection with TOI, then the one with less "overtime" (time outside TOI) is selected.
    3. If two or more slices are considered equal after above criteria, then the one best centered on the TOI is selected.
    Rational: the "smallest time outside" criterion (rule 2) is before "best centered" criterion (rule 3) because of the following scenario: if a user specifies a "time of interest" (TOI) of 1 day and if there are two slices intersecting the TOI, with one slice being a raster of monthly averages the other slice being a raster of daily data, we want the daily data to be selected even if by coincidence the monthly averages is better centered.
    If the `timeGranularity` argument is non-null, then intersections with TOI will be rounded to an integer number of the specified granularity and the last criterion in above list is relaxed. This is useful when data are expected at an approximately regular time interval (for example one remote sensing image per day) and we want to ignore slight variations in the temporal extent declared for each image.

    If there is no time of interest, or the slices do not declare time range, or some slices are still at equality after application of above criteria, then the selection continues on the basis of geographic criteria:

    1. Largest intersection with the area of interest (AOI) is selected.
    2. If two or more slices have the same intersection area with AOI, then the one with the less "irrelevant" material is selected. "Irrelevant" material are area outside the AOI.
    3. If two or more slices are considered equal after above criteria, the one best centered on the AOI is selected.
    4. If two or more slices are considered equal after above criteria, then the first of those candidates is selected.
    If two slices are still considered equal after all above criteria, then an arbitrary one is selected.

    #### Limitations

    Current implementation does not check the vertical dimension. This check may be added in a future version.
    Parameters:
      `timeGranularity` - the temporal granularity of the Time of Interest (TOI), or `null` if none.
    Returns:
      a merge strategy for selecting a slice based on temporal criteria first.

  - ### apply

    public Resource apply(Resource resource)
    Returns a resource with the same data as the specified resource, but using this merge strategy. If the given resource is an instance created by `CoverageAggregator` and uses a different strategy, then a new resource using this merge strategy is returned. Otherwise, the given resource is returned as-is.
    Parameters:
      `resource` - the resource for which to update the merge strategy, or `null`.
    Returns:
      resource with updated merge strategy, or `null` if the given resource was null.

  - ### filter

    protected int[] filter(GridGeometry request, GridGeometry[] candidates)
    Returns the indexes of the coverages to use in the aggregation. The `candidates` array contains the grid geometries of all coverages that intersect the request. This method can decide to accept none of those candidates (by returning an empty array), or to select exactly one (for example, based on a temporal criterion), or on the contrary to select all of them, or any intermediate choice.

    The default implementation selects all candidates (i.e., filter nothing).

    Parameters:
      `request` - the geographic area and temporal extent requested by user.
      `candidates` - grid geometry of all slices that intersect the request.
    Returns:
      indexes of the slices to use according the heuristic rules of this `MergeStrategy`.
    Since:
      1.5

  - ### aggregate

    protected abstract RenderedImage aggregate(RenderedImage[] sources)
    Aggregates images that have been accepted by the filter. The length of the `sources` array is equal or smaller than the length of the index array returned by `filter(…)`. The array may be shorter if some images were outside the request, but the array always contains at least one element.
    Parameters:
      `sources` - the images accepted by the filter.
    Returns:
      the result of the aggregation.
    Since:
      1.5