Package org.apache.sis.referencing.operation.transform

# Class InterpolatedGeocentricTransform

Object
FormattableObject
AbstractMathTransform
DatumShiftTransform
InterpolatedGeocentricTransform

All Implemented Interfaces:
  `Serializable`, `Parameterized`, `LenientComparable`, `MathTransform`

public class InterpolatedGeocentricTransform extends DatumShiftTransform
Transforms between two geographic CRS by performing geocentric translations interpolated from a grid file. This transform is used mainly for "France geocentric interpolation" (ESPG:9655) datum shifts, but Apache SIS implementation allows the use for other regions.

## Algorithm

This class transforms two- or three- dimensional coordinates from a geographic CRS to another geographic CRS. The changes between source and target coordinates are small (usually less than 400 metres), but vary for every position. Those changes are provided in a datum shift grid, usually loaded from one or two files.

Many datum shift grids like NADCON and NTv2 apply the changes directly on geographic coordinates. This relatively simple case is handled by `InterpolatedTransform`. But the `InterpolatedGeocentricTransform` algorithm uses the grid in a more complex way:

1. Convert input geographic coordinate (λ,φ) to geocentric coordinate (X,Y,Z).
2. Ask `DatumShiftGrid` for the offset to apply for coordinate (λ,φ). But instead of returning a (Δλ, Δφ) offset, the grid shall return a (ΔX, ΔY, ΔZ) offset.
3. Convert the shifted geocentric coordinate (X+ΔX, Y+ΔY, Z+ΔZ) back to a geographic coordinate.

Source: IGN document `NTG_88​.pdf`, "Grille de paramètres de transformation de coordonnées" at http://www.ign.fr. Note however that the signs of (ΔX, ΔY, ΔZ) values expected by this class are the opposite of the signs used in NTG_88 document. This is because NTG_88 grid defines shifts from target to source, while this class expects shifts from source to target.

Note: this algorithm is not the same as a (theoretical) `EllipsoidToCentricTransform` → `InterpolatedTransform` → (inverse of `EllipsoidToCentricTransform`) concatenation because the `DatumShiftGrid` inputs are geographic coordinates even if the interpolated grid values are in geocentric space.

## Performance consideration

`InterpolatedMolodenskyTransform` performs the same calculation more efficiently at the cost of a few centimetres error. Both classes are instantiated in the same way and expect the same inputs.

Since:
  0.7
See Also:
  - `InterpolatedMolodenskyTransform`
  - Serialized Form

Defined in the `sis-referencing` module

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `InterpolatedGeocentricTransform(Ellipsoid source, boolean isSource3D, Ellipsoid target, boolean isTarget3D, DatumShiftGrid<Angle,Length> grid)`
  Creates a transform from the specified parameters.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static MathTransform`
  `createGeodeticTransformation(MathTransformFactory factory, Ellipsoid source, boolean isSource3D, Ellipsoid target, boolean isTarget3D, DatumShiftGrid<Angle,Length> grid)`
  Creates a transformation between two geographic CRS.
  `int`
  `getSourceDimensions()`
  Gets the dimension of input points.
  `int`
  `getTargetDimensions()`
  Gets the dimension of output points.
  `MathTransform`
  `inverse()`
  Returns the inverse of this interpolated geocentric transform.
  `Matrix`
  `transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate)`
  Transforms the (λ,φ) or (λ,φ,h) coordinates between two geographic CRS, and optionally returns the derivative at that location.

  ### Methods inherited from class DatumShiftTransform

  `computeHashCode, equals, getContextualParameters, getParameterValues`

  ### Methods inherited from class AbstractMathTransform

  `derivative, equals, formatTo, getParameterDescriptors, hashCode, isIdentity, transform, transform, transform, transform, transform, tryConcatenate`

  ### Methods inherited from class FormattableObject

  `print, toString, toString, toWKT`

  ### Methods inherited from class Object

  `clone, finalize, getClass, notify, notifyAll, wait, wait, wait`

  ### Methods inherited from interface MathTransform

  `toWKT`

- ## Constructor Details

  - ### InterpolatedGeocentricTransform

    protected InterpolatedGeocentricTransform(Ellipsoid source, boolean isSource3D, Ellipsoid target, boolean isTarget3D, DatumShiftGrid<Angle,Length> grid)
    Creates a transform from the specified parameters. This `InterpolatedGeocentricTransform` class expects coordinate values in the following order and units:
    1. longitudes in radians relative to the prime meridian (usually Greenwich),
    2. latitudes in radians,
    3. optionally heights above the ellipsoid, in same units than the source ellipsoid axes.
    For converting geographic coordinates in degrees, `InterpolatedGeocentricTransform` instances need to be concatenated with the following affine transforms:
    - Normalization before `InterpolatedGeocentricTransform`:
      - Conversion of (λ,φ) from degrees to radians.
    - Denormalization after `InterpolatedGeocentricTransform`:
      - Conversion of (λ,φ) from radians to degrees.
    After `InterpolatedGeocentricTransform` construction, the full conversion chain including the above affine transforms can be created by `DatumShiftTransform​.getContextualParameters().completeTransform(factory, this)}`.
    Parameters:
      `source` - the source ellipsoid.
      `isSource3D` - `true` if the source coordinates have a height.
      `target` - the target ellipsoid.
      `isTarget3D` - `true` if the target coordinates have a height.
      `grid` - the grid of datum shifts from source to target datum. The `DatumShiftGrid​.interpolateInCell(…)` method shall compute (ΔX, ΔY, ΔZ) translations from source to target in the unit of source ellipsoid axes.
    See Also:
      - `createGeodeticTransformation(MathTransformFactory, Ellipsoid, boolean, Ellipsoid, boolean, DatumShiftGrid)`

- ## Method Details

  - ### createGeodeticTransformation

    public static MathTransform createGeodeticTransformation(MathTransformFactory factory, Ellipsoid source, boolean isSource3D, Ellipsoid target, boolean isTarget3D, DatumShiftGrid<Angle,Length> grid) throws FactoryException
    Creates a transformation between two geographic CRS. This factory method combines the `InterpolatedGeocentricTransform` instance with the steps needed for converting values between degrees to radians. The transform works with input and output coordinates in the following units:
    1. longitudes in degrees relative to the prime meridian (usually Greenwich),
    2. latitudes in degrees,
    3. optionally heights above the ellipsoid, in same units than the source ellipsoids axes.
    Note however that the given `grid` instance shall expect geographic coordinates (λ,φ) in radians.
    Parameters:
      `factory` - the factory to use for creating the transform.
      `source` - the source ellipsoid.
      `isSource3D` - `true` if the source coordinates have a height.
      `target` - the target ellipsoid.
      `isTarget3D` - `true` if the target coordinates have a height.
      `grid` - the grid of datum shifts from source to target datum. The `DatumShiftGrid​.interpolateInCell(…)` method shall compute (ΔX, ΔY, ΔZ) translations from source to target in the unit of source ellipsoid axes.
    Returns:
      the transformation between geographic coordinates in degrees.
    Throws:
      `FactoryException` - if an error occurred while creating a transform.

  - ### getSourceDimensions

    public int getSourceDimensions()
    Gets the dimension of input points.
    Specified by:
      `getSourceDimensions` in interface `MathTransform`
    Specified by:
      `getSourceDimensions` in class `AbstractMathTransform`
    Returns:
      the input dimension, which is 2 or 3.
    See Also:
      - `DefaultOperationMethod​.getSourceDimensions()`

  - ### getTargetDimensions

    public int getTargetDimensions()
    Gets the dimension of output points.
    Specified by:
      `getTargetDimensions` in interface `MathTransform`
    Specified by:
      `getTargetDimensions` in class `AbstractMathTransform`
    Returns:
      the output dimension, which is 2 or 3.
    See Also:
      - `DefaultOperationMethod​.getTargetDimensions()`

  - ### transform

    public Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws TransformException
    Transforms the (λ,φ) or (λ,φ,h) coordinates between two geographic CRS, and optionally returns the derivative at that location.
    Specified by:
      `transform` in class `AbstractMathTransform`
    Parameters:
      `srcPts` - the array containing the source coordinate (can not be `null`).
      `srcOff` - the offset to the point to be transformed in the source array.
      `dstPts` - the array into which the transformed coordinate is returned. May be the same than `srcPts`. May be `null` if only the derivative matrix is desired.
      `dstOff` - the offset to the location of the transformed point that is stored in the destination array.
      `derivate` - `true` for computing the derivative, or `false` if not needed.
    Returns:
      the matrix of the transform derivative at the given source position, or `null` if the `derivate` argument is `false`.
    Throws:
      `TransformException` - if the point can not be transformed or if a problem occurred while calculating the derivative.
    See Also:
      - `AbstractMathTransform​.derivative(DirectPosition)`
      - `AbstractMathTransform​.transform(DirectPosition, DirectPosition)`
      - `MathTransforms​.derivativeAndTransform(MathTransform, double[], int, double[], int)`

  - ### inverse

    public MathTransform inverse()
    Returns the inverse of this interpolated geocentric transform. The source ellipsoid of the returned transform will be the target ellipsoid of this transform, and conversely.
    Specified by:
      `inverse` in interface `MathTransform`
    Overrides:
      `inverse` in class `AbstractMathTransform`
    Returns:
      a transform from the target ellipsoid to the source ellipsoid of this transform.