Multi-Size Product API (Alternative)
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).
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()