Multi-Size Product API (Alternative)

Model CRS Requirement

The transformation from raster data node's pixel coordinates into the product's model CRS must be an affine transformation.

Why? Here are some reasons:

Vector data is provided per product (not per raster data node) and vector data is always in model coordinates. In order to easily display vector data (pins, GCPs, shapes) in image views of all raster data nodes, there should be an affine transformation between vector data and raster data. Easily here means: with minimum effort to change the existing heritage code which was developed on top of the assumption that all vector data can be displayed with only affine transformations applied.

We would like to display multiple raster data nodes of a product in the same image view. In order to efficiently do so, there must be only affine transformations between the raster images and the display (see Java Graphics2D context).

Implication

The implication of the Model CRS requirement is as follows: the geo-coding of each raster data node (if any) must be the product’s scene geo-coding or an affine wrapper of it. This is true for map-projected products (where all raster data nodes have the same Map CRS) and all the other geo-coding types.


But this means, that we actually don't need a RasterDataNode.geoCoding property at all. We only need the Product.geoCoding and RasterDataNode.imageToModelTransform properties! With this insight (why only now?) we must conclude that either our original requirement was either too strict or never met. For example the AVNIR-2 product reader in S3TBX assigns distinct geo-codings to its bands.

TODO: check if the AVNIR-2 product reader is the only one with truly different geo-codings per band. If so, we could collocate one or the other band to meet the Model CRS Requirement and then replace the RasterDataNode.setGeoCoding(gc) calls by RasterDataNode.setImageToModelTransform(i2m) calls.

In the following comparison the two basic types of SNAP geo-codings are opposed to each other:

CrsGeoCoding (= MapGeoCoding)Other GeoCodings
Interpretation: rectified image with respect to a given Map CRS
Interpretation: image in satellite perspective, camera view as seen from the satellite
Image CRS is based on Map CRS with an affine transform between both
Image CRS is based on Map CRS with a non-linear transform between both
Map CRS provided
Map CRS is Geo CRS
Product Model CRS is Map CRS
Product Model CRS is the Image CRS of a selected geo-coding

class MultiLevelImageLayout:

  • rename MultiLevelModel into MultiLevelImageLayout (MLIL)
  • make MultiLevelImageLayout a pojo class, as only DefaultMultiLevelModel is currently used in the code
  • add getTileWidth/Height(level)
  • add getWidth/Height(level)

class Product:

  • modelCRS:
    • common coordinate reference system (CRS) for all vector data geometries
    • shall allow for affine transformation of model coordinates to individual RDNs
    • getter:
      • if explicitly set, return it
      • if sceneGeoCoding set, derive modelCRS from it (either mapCRS or imageCRS)
      • return Product.DEFAULT_IMAGE_CRS
  • sceneMultiLevelImageLayout
    • default for RDNs without explicitly set RDN.multiLevelImageLayout
    • getter:
      • if explicitly set, return it
      • if not set, get from reference raster data node
      • otherwise throw ISE
  • sceneGeoCoding
    • default for RDNs without explicitly set RDN.multiLevelImageLayout
    • provides a product's scene footprint together with sceneMultiLevelImageLayout
    • getter:
      • if explicitly set, return it
      • if not set, get from reference raster data node
      • otherwise return null

class RasterDataNode (RDN):

  • multiLevelImageLayout
    • must exist before a RDN is added to a product
    • used to implicitly and explicitly create source image
    • getter:
      • if source image exists, return MultiLevelImage.layout
      • if explicitly set, return it
      • if not set, get from Product.sceneMultiLevelImageLayout
      • otherwise throw ISE
  • geoCoding
    • getter:
      • if Product.sceneGeoCoding exists, create an affine wrapper using getImageToModelTransform(),
      • otherwise return null
    • setter:
      • remove!
      • replace by setImageToModelTransform() or setMultiLevelImageLayout()