Multi-size Product API (Alternative 2)
The first alternative Multi-size Product API lead to the insight that actually only a single, product level geo-coding is required when we force all raster data node image-to-model transformation to be affine. If we follow that approach, we'd have to either remove the RasterDataNode.geoCoding
property entirely or remove just the setter. The getter could then look like this after inventing a AffineWrapperGeoCoding:
public final void getGeoCoding() { Product product = getProduct(); if (product != null && product.getGeoCoding() != null) { return new AffineWrapperGeoCoding(product.getGeoCoding(), getImageToModelTransform()); } return null; }
However, we feel that such a model would be too restrictive. Also, we'd had to replace all RasterDataNode.setGeoCoding(gc)
occurences. This includes places where no affine alternative exists, e.g. the AVNIR2 and probably also the S-1 L1 SLC and S-3 SLSTR L1B bands (see Multi-size Products Specification).
If we drop our "affine" requirement we face new logical as well as terminological problems in the current SNAP datamodel API:
RasterDataNode.getSourceImage()
returns aMultiLevelImage
, whosegetModel()
method returns aMultiLevelModel
MultiLevelModel
has agetImageToModelTransform()
method which returns anAffineTransform
So what does the model in getImageToModel
transform refer to? It can't actually be the Transform
Product.modelCRS
because in the general case - with different geo-codings per raster data node - there may be any, including non-linear transformations between a raster data node's image coordinates and the product's scene image coordinates.
Possible problem mitigation and API clarification:
Product.modelCRS
becomesProduct.sceneCRS
- also fits better to other properties such asProduct.sceneRasterSize
(or better sceneImageSize?). However, remember that all vector data is then stored in scene CRS coordinates.- We wont use the term model in
org.esa.snap.framework
API anymore - The term model makes still perfect sense in the Ceres Layer and MultiLevelImage APIs.
After all, the model coordinate space is the one used by graphical layers before layers render their content (model elements) onto views that use view coordinates.
- Image layers: In order to display an image on a view, a concatenated tranformation from image to model coordinates (from multi-level images) and then from model to view coordinates is used (both affine).
- Vector data layers: In order to display vector data nodes, we'll have to generate figures for it. Figure geometries must always be in model coordinates, but vector data geometries are given in scene coordinates. In order to generate the transformed figure geometries, we need a scene-to-model transformation. Where does this come from? I.e.
CRS.findTransform(product.getSceneCRS(), ???) ->
We actually have to differenciate two cases, which are even independent of whether a Product has multi-size images or not:
Case 1: The model coordinate reference systems of all images are the same
This is usually the case for map-projected products or products in satellite projection where all images cover the same scene on Earth (and hence own the same geo-coding). For map-projected products, the scene CRS will be any geo-coding's map CRS. For products in satellite projection, it is the image CRS of the common geo-coding.
Since the scene CRS is equal to any image's model CRS, all images can be transformed into the scene CRS by affine transformations which is given by the RasterDataNode.imageToModelTransform
property. Individual imageToModelTransform
values are derived from each RasterDataNode
's CrsGeoCoding.imageToMapTransform
or are explicitely set.
Let S be the scene CRS of a product and Mk be the model CRS of a raster data node k. Then S = Mk for all k. Let Vk be the view CRS used to display raster data node k.
Vector data can be displayed in any image view of a case 1 product without further transformation because all geometry is already stored in S coordinates and S = Mk. The layer renderer can directly transform them into view coordinates:
- Model to view transform (affine): S --> Vk
Case 2: The model coordinate reference systems of images are different
This may be the case for products in satellite projection where individual images cary different geo-referencing information, i.e. refer different locations (e.g. multiple reference frames) or use multiple views (e.g. forward/nadir view). The product's scene CRS may be of any type and individual images are transfromed into the scene CRS by a RasterDataNode.sceneRasterTransform
of type SceneRasterTransform
which is a composition of arbitrary including non-linear forward and inverse MathTransform
(e.g. local image coords --> WGS-84 coords --> scene image coords).
The sceneRasterTransform
must be explicitly set in order to become active i.e. to make a product a case 2 product. If none of the RasterDataNode
s of a product have a sceneRasterTransform
, then the product is assumend to be a case 1 product.
If we want to display vector data in an image view of a case 2 product we have to transform them as follows:
- Scene raster transform (non-linear): S --> Ik
- Image to model transform (affine): Ik --> Mk
- Model to view transform (affine): Mk --> Vk
The scene raster transformations are usually set by the product readers or operators, as the required transformations are well known to them. If both the raster data node's and the product's scene geo-coding are known, then a scene raster transformation can be derived by finding the transformation from the raster data node's image CRS into the product's scene image CRS:
product.setSceneCRS(product.getSceneGeoCoding().getImageCRS());
forward = CRS.findTransform(rasterDataNode.getGeoCoding().getImageCRS(), product.getSceneCRS());
inverse = CRS.findTransform(product.getSceneCRS(), rasterDataNode.getGeoCoding().getImageCRS());
rasterDataNode.setSceneRasterTransform(new DefaultSceneRasterTransform(forward, inverse));
This file lists some places where the scene raster transformations would need to be taken into account: