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

# Class AbstractMathTransform

Object
FormattableObject
AbstractMathTransform

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

Direct Known Subclasses:
  `AbstractMathTransform​.Inverse`, `AbstractMathTransform1D`, `AbstractMathTransform2D`, `DatumShiftTransform`, `EllipsoidToCentricTransform`, `PassThroughTransform`, `WraparoundTransform`

public abstract class AbstractMathTransform extends FormattableObject implements MathTransform, Parameterized, LenientComparable
Provides a default implementation for most methods required by the `MathTransform` interface. A `MathTransform` is an object that actually does the work of applying a formula to coordinate values. The math transform does not know or care how the coordinates relate to positions in the real world. For example if an affine transform scales z values by a factor of 1000, then it could be converting metres to millimetres, or it could be converting kilometres to metres.

`AbstractMathTransform` provides a convenient base class from which `MathTransform` implementations can be easily derived. It also defines a few additional SIS-specific methods for convenience of performance. The simplest way to implement this abstract class is to provide an implementation for the following methods only:

- `getSourceDimensions()`
- `getTargetDimensions()`
- `transform(double[], int, double[], int, boolean)`

However more performance may be gained by overriding the other `transform(…)` methods as well.

## Immutability and thread safety

All Apache SIS implementations of `MathTransform` are immutable and thread-safe. It is highly recommended that third-party implementations be immutable and thread-safe too. This means that unless otherwise noted in the javadoc, `MathTransform` instances can be shared by many objects and passed between threads without synchronization.

## Serialization

`MathTransform` may or may not be serializable, at implementation choices. Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible with future SIS versions. Serialization should be used only for short term storage or RMI between applications running the same SIS version.

Since:
  0.5
See Also:
  - `DefaultMathTransformFactory`
  - `AbstractCoordinateOperation`

Defined in the `sis-referencing` module

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected static class`
  `AbstractMathTransform​.Inverse`
  Base class for implementations of inverse math transforms.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `AbstractMathTransform()`
  Constructor for subclasses.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected int`
  `computeHashCode()`
  Computes a hash value for this transform.
  `Matrix`
  `derivative(DirectPosition point)`
  Gets the derivative of this transform at a point.
  `final boolean`
  `equals(Object object)`
  Compares the specified object with this math transform for strict equality.
  `boolean`
  `equals(Object object, ComparisonMode mode)`
  Compares the specified object with this math transform for equality.
  `protected String`
  `formatTo(Formatter formatter)`
  Formats the inner part of a Well Known Text version 1 (WKT 1) element.
  `protected ContextualParameters`
  `getContextualParameters()`
  Returns the parameters for a sequence of normalize → `this` → denormalize transforms (optional operation).
  `ParameterDescriptorGroup`
  `getParameterDescriptors()`
  Returns the parameter descriptors for this math transform, or `null` if unknown.
  `ParameterValueGroup`
  `getParameterValues()`
  Returns the parameter values for this math transform, or `null` if unknown.
  `abstract int`
  `getSourceDimensions()`
  Gets the dimension of input points.
  `abstract int`
  `getTargetDimensions()`
  Gets the dimension of output points.
  `final int`
  `hashCode()`
  Returns a hash value for this transform.
  `MathTransform`
  `inverse()`
  Returns the inverse transform of this object.
  `boolean`
  `isIdentity()`
  Tests whether this transform does not move any points.
  `abstract Matrix`
  `transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate)`
  Transforms a single coordinate point in an array, and optionally computes the transform derivative at that location.
  `void`
  `transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)`
  Transforms a list of coordinate points.
  `void`
  `transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)`
  Transforms a list of coordinate points.
  `void`
  `transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)`
  Transforms a list of coordinate points.
  `void`
  `transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)`
  Transforms a list of coordinate points.
  `DirectPosition`
  `transform(DirectPosition ptSrc, DirectPosition ptDst)`
  Transforms the specified `ptSrc` and stores the result in `ptDst`.
  `protected MathTransform`
  `tryConcatenate(boolean applyOtherFirst, MathTransform other, MathTransformFactory factory)`
  Concatenates or pre-concatenates in an optimized way this math transform with the given one, if possible.

  ### 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

  - ### AbstractMathTransform

    protected AbstractMathTransform()
    Constructor for subclasses.

- ## Method Details

  - ### getSourceDimensions

    public abstract int getSourceDimensions()
    Gets the dimension of input points.
    Specified by:
      `getSourceDimensions` in interface `MathTransform`
    Returns:
      the dimension of input points.
    See Also:
      - `DefaultOperationMethod​.getSourceDimensions()`

  - ### getTargetDimensions

    public abstract int getTargetDimensions()
    Gets the dimension of output points.
    Specified by:
      `getTargetDimensions` in interface `MathTransform`
    Returns:
      the dimension of output points.
    See Also:
      - `DefaultOperationMethod​.getTargetDimensions()`

  - ### getParameterDescriptors

    public ParameterDescriptorGroup getParameterDescriptors()
    Returns the parameter descriptors for this math transform, or `null` if unknown.
    Relationship with ISO 19111: This method is similar to `OperationMethod​.getParameters()`, except that typical `MathTransform` implementations return parameters in standard units (usually metres or decimal degrees).
    Specified by:
      `getParameterDescriptors` in interface `Parameterized`
    Returns:
      the parameter descriptors for this math transform, or `null` if unspecified.
    See Also:
      - `DefaultOperationMethod​.getParameters()`

  - ### getParameterValues

    public ParameterValueGroup getParameterValues()
    Returns the parameter values for this math transform, or `null` if unknown. This is not necessarily the parameters that the user specified at construction time, since implementations may have applied normalizations.

    #### Normalized and contextual parameters

    Most Apache SIS implementations of map projections perform their calculations on an ellipsoid having a semi-major axis length of 1. In such cases, the group returned by this method contains a `"semi_major"` parameter with a value of 1. If the real axis length is desired, we need to take in account the context of this math transform, i.e. the scales and offsets applied before and after this transform. This information is provided by `getContextualParameters()`.
    Specified by:
      `getParameterValues` in interface `Parameterized`
    Returns:
      the parameter values for this math transform, or `null` if unspecified. Note that those parameters may be normalized (e.g. represent a transformation of an ellipsoid of semi-major axis length of 1).
    See Also:
      - `getContextualParameters()`
      - `SingleOperation​.getParameterValues()`

  - ### getContextualParameters

    protected ContextualParameters getContextualParameters()
    Returns the parameters for a sequence of normalize → `this` → denormalize transforms (optional operation). Subclasses can override this method if they choose to split their computation in linear and non-linear parts. Such split is optional: it can leads to better performance (because SIS can concatenate efficiently consecutive linear transforms), but should not change significantly the result (ignoring differences in rounding errors). If a split has been done, then this `MathTransform` represents only the non-linear step and Apache SIS needs this method for reconstructing the parameters of the complete transform.
    Returns:
      the parameters values for the sequence of normalize → `this` → denormalize transforms, or `null` if unspecified. Callers should not modify the returned parameters, since modifications (if allowed) will generally not be reflected back in this `MathTransform`.
    Since:
      0.6

  - ### isIdentity

    public boolean isIdentity()
    Tests whether this transform does not move any points. The default implementation always returns `false`.
    Specified by:
      `isIdentity` in interface `MathTransform`

  - ### transform

    public DirectPosition transform(DirectPosition ptSrc, DirectPosition ptDst) throws TransformException
    Transforms the specified `ptSrc` and stores the result in `ptDst`. The default implementation performs the following steps:
    - Ensures that the dimension of the given points are consistent with the source and target dimensions of this math transform.
    - Delegates to the `transform(double[], int, double[], int, boolean)` method.
    This method does not update the associated `CoordinateReferenceSystem` value.
    Specified by:
      `transform` in interface `MathTransform`
    Parameters:
      `ptSrc` - the coordinate point to be transformed.
      `ptDst` - the coordinate point that stores the result of transforming `ptSrc`, or `null`.
    Returns:
      the coordinate point after transforming `ptSrc` and storing the result in `ptDst`, or a newly created point if `ptDst` was null.
    Throws:
      `MismatchedDimensionException` - if `ptSrc` or `ptDst` doesn't have the expected dimension.
      `TransformException` - if the point can not be transformed.

  - ### transform

    public abstract Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws TransformException
    Transforms a single coordinate point in an array, and optionally computes the transform derivative at that location. Invoking this method is conceptually equivalent to running the following:

    >     Matrix derivative = null;
    >     if (derivate) {
    >         double[] coordinates = Arrays.copyOfRange(srcPts, srcOff, srcOff + getSourceDimensions());
    >         derivative = this.derivative(new GeneralDirectPosition(coordinates));
    >     }
    >     this.transform(srcPts, srcOff, dstPts, dstOff, 1);                   // May overwrite srcPts.
    >     return derivative;

    However this method provides two advantages:
    - It is usually easier to implement for `AbstractMathTransform` subclasses. The default `transform(double[], int, double[], int, int)` method implementation will invoke this method in a loop, taking care of the iteration strategy depending on the argument value.
    - When both the transformed point and its derivative are needed, this method may be significantly faster than invoking the `transform` and `derivative` methods separately because many internal calculations are the same. Computing those two information in a single step can help to reduce redundant calculation.

    #### Note for implementers

    The source and destination may overlap. Consequently, implementers must read all source coordinate values before to start writing the transformed coordinates in the destination array.
    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:
      - `derivative(DirectPosition)`
      - `transform(DirectPosition, DirectPosition)`
      - `MathTransforms​.derivativeAndTransform(MathTransform, double[], int, double[], int)`

  - ### transform

    public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws TransformException
    Transforms a list of coordinate points. This method is provided for efficiently transforming many points. The supplied array of coordinate values will contain packed coordinate values.
    Example: if the source dimension is 3, then the coordinates will be packed in this order: (x₀,y₀,z₀, x₁,y₁,z₁ …).
    The default implementation invokes `transform(double[], int, double[], int, boolean)` in a loop, using an iteration strategy determined from the arguments for iterating over the points.
    Implementation note: see `IterationStrategy` javadoc for a method skeleton.
    Specified by:
      `transform` in interface `MathTransform`
    Parameters:
      `srcPts` - the array containing the source point coordinates.
      `srcOff` - the offset to the first point to be transformed in the source array.
      `dstPts` - the array into which the transformed point coordinates are returned. May be the same than `srcPts`.
      `dstOff` - the offset to the location of the first transformed point that is stored in the destination array.
      `numPts` - the number of point objects to be transformed.
    Throws:
      `TransformException` - if a point can not be transformed. Some implementations will stop at the first failure, wile some other implementations will fill the untransformable points with Double.NaN values, continue and throw the exception only at end. Implementations that fall in the later case should set the last completed transform to `this`.

  - ### transform

    public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws TransformException
    Transforms a list of coordinate points. The default implementation delegates to `transform(double[], int, double[], int, int)` using a temporary array of doubles.
    Implementation note: see `IterationStrategy` javadoc for a method skeleton.
    Specified by:
      `transform` in interface `MathTransform`
    Parameters:
      `srcPts` - the array containing the source point coordinates.
      `srcOff` - the offset to the first point to be transformed in the source array.
      `dstPts` - the array into which the transformed point coordinates are returned. May be the same than `srcPts`.
      `dstOff` - the offset to the location of the first transformed point that is stored in the destination array.
      `numPts` - the number of point objects to be transformed.
    Throws:
      `TransformException` - if a point can't be transformed. Some implementations will stop at the first failure, wile some other implementations will fill the un-transformable points with `Float​.NaN` values, continue and throw the exception only at end. Implementations that fall in the later case should set the last completed transform to `this`.

  - ### transform

    public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws TransformException
    Transforms a list of coordinate points. The default implementation delegates to `transform(double[], int, double[], int, int)` using a temporary array of doubles.
    Specified by:
      `transform` in interface `MathTransform`
    Parameters:
      `srcPts` - the array containing the source point coordinates.
      `srcOff` - the offset to the first point to be transformed in the source array.
      `dstPts` - the array into which the transformed point coordinates are returned.
      `dstOff` - the offset to the location of the first transformed point that is stored in the destination array.
      `numPts` - the number of point objects to be transformed.
    Throws:
      `TransformException` - if a point can not be transformed. Some implementations will stop at the first failure, wile some other implementations will fill the untransformable points with Float.NaN values, continue and throw the exception only at end. Implementations that fall in the later case should set the last completed transform to `this`.

  - ### transform

    public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws TransformException
    Transforms a list of coordinate points. The default implementation delegates to `transform(double[], int, double[], int, int)` using a temporary array of doubles if necessary.
    Specified by:
      `transform` in interface `MathTransform`
    Parameters:
      `srcPts` - the array containing the source point coordinates.
      `srcOff` - the offset to the first point to be transformed in the source array.
      `dstPts` - the array into which the transformed point coordinates are returned.
      `dstOff` - the offset to the location of the first transformed point that is stored in the destination array.
      `numPts` - the number of point objects to be transformed.
    Throws:
      `TransformException` - if a point can not be transformed. Some implementations will stop at the first failure, wile some other implementations will fill the untransformable points with Double.NaN values, continue and throw the exception only at end. Implementations that fall in the later case should set the last completed transform to `this`.

  - ### derivative

    public Matrix derivative(DirectPosition point) throws TransformException
    Gets the derivative of this transform at a point. The default implementation performs the following steps:
    - Ensure that the `point` dimension is equals to this math transform source dimensions.
    - Copy the coordinate in a temporary array and pass that array to the `transform(double[], int, double[], int, boolean)` method, with the `derivate` boolean argument set to `true`.
    - If the later method returned a non-null matrix, returns that matrix. Otherwise throws `TransformException`.
    Specified by:
      `derivative` in interface `MathTransform`
    Parameters:
      `point` - the coordinate point where to evaluate the derivative.
    Returns:
      the derivative at the specified point (never `null`).
    Throws:
      `NullPointerException` - if the derivative depends on coordinate and `point` is `null`.
      `MismatchedDimensionException` - if `point` does not have the expected dimension.
      `TransformException` - if the derivative can not be evaluated at the specified point.

  - ### inverse

    public MathTransform inverse() throws NoninvertibleTransformException
    Returns the inverse transform of this object. The default implementation returns `this` if this transform is an identity transform, or throws an exception otherwise. Subclasses should override this method.
    Implementation note: the `AbstractMathTransform​.Inverse` inner class can be used as a base for inverse transform implementations.
    Specified by:
      `inverse` in interface `MathTransform`
    Throws:
      `NoninvertibleTransformException`

  - ### tryConcatenate

    protected MathTransform tryConcatenate(boolean applyOtherFirst, MathTransform other, MathTransformFactory factory) throws FactoryException
    Concatenates or pre-concatenates in an optimized way this math transform with the given one, if possible. If an optimization is possible, a new math transform is created to perform the combined transformation. The `applyOtherFirst` value determines the transformation order as bellow:
    - If `applyOtherFirst` is `true`, then transforming a point p by the combined transform is equivalent to first transforming p by `other` and then transforming the result by `this`.
    - If `applyOtherFirst` is `false`, then transforming a point p by the combined transform is equivalent to first transforming p by `this` and then transforming the result by `other`.
    If no optimization is available for the combined transform, then this method returns `null`. In the later case, the concatenation will be prepared by `DefaultMathTransformFactory` using a generic implementation.

    The default implementation returns the identity transform if the other transform is the inverse of this transform, or returns `null` otherwise. This method is ought to be overridden by subclasses capable of concatenating some combination of transforms in a special way. `LinearTransform` implementations do not need to override this method since matrix multiplications will be handled automatically, and this method does not need to handle the `isIdentity()` case.

    Parameters:
      `applyOtherFirst` - `true` if the transformation order is `other` followed by `this`, or `false` if the transformation order is `this` followed by `other`.
      `other` - the other math transform to (pre-)concatenate with this transform.
      `factory` - the factory which is (indirectly) invoking this method, or `null` if none.
    Returns:
      the math transforms combined in an optimized way, or `null` if no such optimization is available.
    Throws:
      `FactoryException` - if an error occurred while combining the transforms.
    Since:
      0.8
    See Also:
      - `DefaultMathTransformFactory​.createConcatenatedTransform(MathTransform, MathTransform)`

  - ### hashCode

    public final int hashCode()
    Returns a hash value for this transform. This method invokes `computeHashCode()` when first needed and caches the value for future invocations. Subclasses shall override `computeHashCode()` instead of this method.
    Overrides:
      `hashCode` in class `Object`
    Returns:
      the hash code value. This value may change between different execution of the Apache SIS library.

  - ### computeHashCode

    protected int computeHashCode()
    Computes a hash value for this transform. This method is invoked by `hashCode()` when first needed.
    Returns:
      the hash code value. This value may change between different execution of the Apache SIS library.

  - ### equals

    public final boolean equals(Object object)
    Compares the specified object with this math transform for strict equality. This method is implemented as below (omitting assertions):

    >     return equals(other, ComparisonMode.STRICT);

    Specified by:
      `equals` in interface `LenientComparable`
    Overrides:
      `equals` in class `Object`
    Parameters:
      `object` - the object to compare with this transform.
    Returns:
      `true` if the given object is a transform of the same class and using the same parameter values.
    See Also:
      - `ComparisonMode​.STRICT`

  - ### equals

    public boolean equals(Object object, ComparisonMode mode)
    Compares the specified object with this math transform for equality. Two math transforms are considered equal if, given identical source positions, their transformed positions would be equal or `approximately` equal. This method may conservatively returns `false` if unsure.

    The default implementation returns `true` if the following conditions are met:

    - `object` is an instance of the same class than `this`. We require the same class because there is no interface for the various kinds of transform.
    - If the hash code value has already been computed for both instances, their values are the same (opportunist performance enhancement).
    - The contextual parameters are equal according the given comparison mode.
    Specified by:
      `equals` in interface `LenientComparable`
    Parameters:
      `object` - the object to compare with this transform.
      `mode` - the strictness level of the comparison. Default to `STRICT`.
    Returns:
      `true` if the given object is considered equals to this math transform.
    See Also:
      - `Utilities​.deepEquals(Object, Object, ComparisonMode)`

  - ### formatTo

    protected String formatTo(Formatter formatter)
    Formats the inner part of a Well Known Text version 1 (WKT 1) element. The default implementation formats all parameter values returned by `getParameterValues()`. The parameter group name is used as the math transform name.
    Compatibility note: `Param_MT` is defined in the WKT 1 specification only. If the formatter convention is set to WKT 2, then this method silently uses the WKT 1 convention without raising an error (unless this `MathTransform` can not be formatted as valid WKT 1 neither).
    Specified by:
      `formatTo` in class `FormattableObject`
    Parameters:
      `formatter` - the formatter to use.
    Returns:
      the WKT element name, which is `"Param_MT"` in the default implementation.
    See Also:
      - `DefaultMathTransformFactory​.createFromWKT(String)`