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:

  1. RasterDataNode.getSourceImage() returns a MultiLevelImage, whose getModel() method returns a MultiLevelModel
  2. MultiLevelModel has a getImageToModelTransform() method which returns an AffineTransform

So what does the model in getImageToModelTransform transform refer to? It can't actually be the 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 becomes Product.sceneCRS - also fits better to other properties such as Product.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 RasterDataNodes 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: