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

# Class MathTransforms

Object
Static
MathTransforms

public final class MathTransforms extends Static
Utility methods creating or working on `MathTransform` instances. This class centralizes in one place some of the most commonly used functions this package. The `MathTransforms` class provides the following services:

- Create various SIS implementations of `MathTransform`.
- Perform non-standard operations on arbitrary instances.

The factory static methods are provided as convenient alternatives to the GeoAPI `MathTransformFactory` interface. However, users seeking for more implementation neutrality are encouraged to limit themselves to the GeoAPI factory interfaces instead.

Since:
  0.5
See Also:
  - `MathTransformFactory`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static MathTransform2D`
  `bidimensional(MathTransform transform)`
  Returns the given transform as a `MathTransform2D` instance.
  `static MathTransform`
  `compound(MathTransform... components)`
  Puts together a list of independent math transforms, each of them operating on a subset of coordinate values.
  `static MathTransform1D`
  `concatenate(MathTransform1D tr1, MathTransform1D tr2)`
  Concatenates the given one-dimensional transforms.
  `static MathTransform1D`
  `concatenate(MathTransform1D tr1, MathTransform1D tr2, MathTransform1D tr3)`
  Concatenates the three given one-dimensional transforms.
  `static MathTransform2D`
  `concatenate(MathTransform2D tr1, MathTransform2D tr2)`
  Concatenates the given two-dimensional transforms.
  `static MathTransform2D`
  `concatenate(MathTransform2D tr1, MathTransform2D tr2, MathTransform2D tr3)`
  Concatenates the three given two-dimensional transforms.
  `static MathTransform`
  `concatenate(MathTransform tr1, MathTransform tr2)`
  Concatenates the two given transforms.
  `static MathTransform`
  `concatenate(MathTransform tr1, MathTransform tr2, MathTransform tr3)`
  Concatenates the three given transforms.
  `static MathTransform1D`
  `convert(UnitConverter converter)`
  Converts the given unit converter to a math transform.
  `static Matrix`
  `derivativeAndTransform(MathTransform transform, double[] srcPts, int srcOff, double[] dstPts, int dstOff)`
  A buckle method for calculating derivative and coordinate transformation in a single step.
  `static Optional<Envelope>`
  `getDomain(MathTransform evaluated)`
  Returns source coordinate values where the transform is mathematically and numerically applicable.
  `static Matrix`
  `getMatrix(MathTransform transform)`
  If the given transform is linear, returns its coefficients as a matrix.
  `static Matrix`
  `getMatrix(MathTransform toApproximate, DirectPosition tangentPoint)`
  Returns the coefficients of an affine transform in the vicinity of the given position.
  `static List<MathTransform>`
  `getSteps(MathTransform transform)`
  Returns all single components of the given (potentially concatenated) transform.
  `static LinearTransform`
  `identity(int dimension)`
  Returns an identity transform of the specified dimension.
  `static MathTransform1D`
  `interpolate(double[] preimage, double[] values)`
  Creates a transform for the y=f(x) function where y are computed by a linear interpolation.
  `static LinearTransform`
  `linear(double scale, double offset)`
  Creates a one-dimensional affine transform for the given coefficients.
  `static LinearTransform`
  `linear(MathTransform transform, DirectPosition position)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  This method duplicates `tangent(MathTransform, DirectPosition)`.
  `static LinearTransform`
  `linear(Matrix matrix)`
  Creates an arbitrary linear transform from the specified matrix.
  `static MathTransform`
  `passThrough(int[] modifiedCoordinates, MathTransform subTransform, int resultDim)`
  Creates a transform which passes through a subset of coordinates to another transform.
  `static MathTransform`
  `passThrough(int firstAffectedCoordinate, MathTransform subTransform, int numTrailingCoordinates)`
  Creates a transform which passes through a subset of coordinates to another transform.
  `static LinearTransform`
  `scale(double... factors)`
  Creates an affine transform which applies the given scale.
  `static MathTransform`
  `specialize(MathTransform global, Map<Envelope,MathTransform> specializations)`
  Creates a transform defined as one transform applied globally except in sub-areas where more accurate transforms are available.
  `static LinearTransform`
  `tangent(MathTransform toApproximate, DirectPosition tangentPoint)`
  Returns a linear (usually affine) transform which approximates the given transform in the vicinity of the given position.
  `static LinearTransform`
  `translation(double... vector)`
  Creates an affine transform which applies the given translation.
  `static LinearTransform`
  `uniformTranslation(int dimension, double offset)`
  Creates an affine transform which applies the same translation for all dimensions.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### identity

    public static LinearTransform identity(int dimension)
    Returns an identity transform of the specified dimension.

    Special cases:

    - If `dimension == 1`, then the returned transform implements `MathTransform1D`.
    - If `dimension == 2`, then the returned transform implements `MathTransform2D`.
    Parameters:
      `dimension` - number of dimensions of the transform to be returned.
    Returns:
      an identity transform of the specified dimension.

  - ### uniformTranslation

    public static LinearTransform uniformTranslation(int dimension, double offset)
    Creates an affine transform which applies the same translation for all dimensions. For each dimension, input values x are converted into output values y using the following equation:

    > y = x + `offset`

    Parameters:
      `dimension` - number of input and output dimensions.
      `offset` - the `offset` term in the linear equation.
    Returns:
      an affine transform applying the specified translation.
    Since:
      1.0

  - ### translation

    public static LinearTransform translation(double... vector)
    Creates an affine transform which applies the given translation. The source and target dimensions of the transform are the length of the given vector.
    Parameters:
      `vector` - the translation vector.
    Returns:
      an affine transform applying the specified translation.
    Since:
      1.0

  - ### scale

    public static LinearTransform scale(double... factors)
    Creates an affine transform which applies the given scale. The source and target dimensions of the transform are the length of the given vector.
    Parameters:
      `factors` - the scale factors.
    Returns:
      an affine transform applying the specified scales.
    Since:
      1.0

  - ### linear

    public static LinearTransform linear(double scale, double offset)
    Creates a one-dimensional affine transform for the given coefficients. Input values x will be converted into output values y using the following equation:

    > y = x ⋅ `scale` + `offset`

    Parameters:
      `scale` - the `scale` term in the linear equation.
      `offset` - the `offset` term in the linear equation.
    Returns:
      the linear transform for the given scale and offset.
    See Also:
      - `Units​.converter(Number, Number)`

  - ### linear

    public static LinearTransform linear(Matrix matrix)
    Creates an arbitrary linear transform from the specified matrix. Usually the matrix is affine, but this is not mandatory. Non-affine matrix will define a projective transform.

    If the transform input dimension is `M`, and output dimension is `N`, then the given matrix shall have size `[N+1][M+1]`. The +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation. The `[M][j]` element of the matrix will be the j'th coordinate of the moved origin.

    Parameters:
      `matrix` - the matrix used to define the linear transform.
    Returns:
      the linear (usually affine) transform.
    See Also:
      - `getMatrix(MathTransform)`
      - `DefaultMathTransformFactory​.createAffineTransform(Matrix)`

  - ### linear

    @Deprecated(since="1.4", forRemoval=true) public static LinearTransform linear(MathTransform transform, DirectPosition position) throws TransformException
    Deprecated, for removal: This API element is subject to removal in a future version.
    This method duplicates `tangent(MathTransform, DirectPosition)`.
    Returns a linear (usually affine) transform which approximates the given transform in the vicinity of the given position.
    Parameters:
      `transform` - the transform to approximate by an affine transform.
      `position` - position in source CRS around which to get the an affine transform approximation.
    Returns:
      a transform approximating the given transform around the given position.
    Throws:
      `TransformException` - if an error occurred while transforming the given position or computing the derivative at that position.
    Since:
      1.0

  - ### tangent

    public static LinearTransform tangent(MathTransform toApproximate, DirectPosition tangentPoint) throws TransformException
    Returns a linear (usually affine) transform which approximates the given transform in the vicinity of the given position. If the given transform is already an instance of `LinearTransform`, then it is returned as-is. Otherwise an approximation for the given position is created using the transform derivative at that given position. The returned transform has the same number of source and target dimensions than the given transform.

    If the given transform is a one-dimensional curve, then this method computes the tangent line at the given position. The same computation is generalized to any number of dimensions (tangent plane if the given transform is two-dimensional, etc.).

    #### Invariant

    Transforming the given `position` using the given `transform` produces the same result (ignoring rounding error) than transforming the same `position` using the returned transform. This invariant holds only for that particular position; the transformation of any other positions may produce different results.
    Parameters:
      `toApproximate` - the potentially non-linear transform to approximate by a linear transform.
      `tangentPoint` - position in source CRS around which to get the an line approximation.
    Returns:
      a transform approximating the given transform around the given position.
    Throws:
      `TransformException` - if an error occurred while transforming the given position or computing the derivative at that position.
    Since:
      1.1
    See Also:
      - `getMatrix(MathTransform, DirectPosition)`

  - ### convert

    public static MathTransform1D convert(UnitConverter converter)
    Converts the given unit converter to a math transform. This is a bridge between Unit API and referencing API.
    Parameters:
      `converter` - the unit converter.
    Returns:
      a transform doing the same computation than the given unit converter.
    Since:
      1.4

  - ### interpolate

    public static MathTransform1D interpolate(double[] preimage, double[] values)
    Creates a transform for the y=f(x) function where y are computed by a linear interpolation. Both `preimage` (the x) and `values` (the y) arguments can be null:
    - If both `preimage` and `values` arrays are non-null, then they must have the same length.
    - If both `preimage` and `values` arrays are null, then this method returns the identity transform.
    - If only `preimage` is null, then the x values are taken as {0, 1, 2, …, `values​.length` - 1}.
    - If only `values` is null, then the y values are taken as {0, 1, 2, …, `preimage​.length` - 1}.
    All `preimage` elements shall be real numbers (not NaN) sorted in increasing or decreasing order. Elements in the `values` array do not need to be ordered, but the returned transform will be invertible only if all values are real numbers sorted in increasing or decreasing order. Furthermore, the returned transform is affine (i.e. implement the `LinearTransform` interface) if the interval between each `preimage` and `values` element is constant.

    The current implementation uses linear interpolation. This may be changed in a future SIS version.

    Parameters:
      `preimage` - the input values (x) in the function domain, or `null`.
      `values` - the output values (y) in the function range, or `null`.
    Returns:
      the y=f(x) function.
    Since:
      0.7

  - ### specialize

    public static MathTransform specialize(MathTransform global, Map<Envelope,MathTransform> specializations)
    Creates a transform defined as one transform applied globally except in sub-areas where more accurate transforms are available. Such constructs appear in some datum shift files. The result of transforming a point by the returned `MathTransform` is as if iterating over all given `Envelope`s in no particular order, find the smallest one containing the point to transform (envelope border considered inclusive), then use the associated `MathTransform` for transforming the point. If the point is not found in any envelope, then the global transform is applied.

    The following constraints apply:

    - The global transform must be a reasonable approximation of the specialized transforms (this is required for calculating the inverse transform).
    - All transforms in the `specializations` map must have the same number of source and target dimensions than the `global` transform.
    - All envelopes in the `specializations` map must have the same number of dimensions than the global transform source dimensions.
    - In current implementation, each envelope must either be fully included in another envelope, or not overlap any other envelope.
    Parameters:
      `global` - the transform to use globally where there is no suitable specialization.
      `specializations` - more accurate transforms available in some sub-areas.
    Returns:
      a transform applying the given global transform except in sub-areas where specializations are available.
    Throws:
      `IllegalArgumentException` - if a constraint is not met.
    Since:
      1.0

  - ### passThrough

    public static MathTransform passThrough(int firstAffectedCoordinate, MathTransform subTransform, int numTrailingCoordinates)
    Creates a transform which passes through a subset of coordinates to another transform. This method returns a transform having the following dimensions:

        int sourceDim = firstAffectedCoordinate + subTransform.getSourceDimensions() + numTrailingCoordinates;
        int targetDim = firstAffectedCoordinate + subTransform.getTargetDimensions() + numTrailingCoordinates;

    Affected coordinates will range from `firstAffectedCoordinate` inclusive to `dimTarget - numTrailingCoordinates` exclusive.
    Parameters:
      `firstAffectedCoordinate` - index of the first affected coordinate.
      `subTransform` - the sub-transform to apply on modified coordinates.
      `numTrailingCoordinates` - number of trailing coordinates to pass through.
    Returns:
      a pass-through transform, potentially as a `PassThroughTransform` instance but not necessarily.
    Since:
      1.0

  - ### passThrough

    public static MathTransform passThrough(int[] modifiedCoordinates, MathTransform subTransform, int resultDim)
    Creates a transform which passes through a subset of coordinates to another transform. The list of modified coordinates is specified by the `modifiedCoordinates` argument. The array length must be equal to the number of source dimensions of `subTransform` and all array elements must be in strictly increasing order.
    Parameters:
      `modifiedCoordinates` - positions in a source coordinate tuple of the coordinates affected by the transform.
      `subTransform` - the sub-transform to apply on modified coordinates.
      `resultDim` - total number of source dimensions of the pass-through transform to return.
    Returns:
      a pass-through transform for the given set of modified coordinates.
    Throws:
      `MismatchedDimensionException` - if the `modifiedCoordinates` array length is not equal to the number of source dimensions in `subTransform`.
      `IllegalArgumentException` - if the index of a modified coordinates is invalid.
    Since:
      1.4
    See Also:
      - `PassThroughTransform​.create(BitSet, MathTransform, int, MathTransformFactory)`

  - ### compound

    public static MathTransform compound(MathTransform... components)
    Puts together a list of independent math transforms, each of them operating on a subset of coordinate values. This method is often used for defining 4-dimensional (x,y,z,t) transform as an aggregation of 3 simpler transforms operating on (x,y), (z) and (t) values respectively.

    Invariants:

    - The source dimensions of the returned transform is equal to the sum of the source dimensions of all given transforms.
    - The target dimensions of the returned transform is equal to the sum of the target dimensions of all given transforms.
    Parameters:
      `components` - the transforms to aggregate in a single transform, in the given order.
    Returns:
      the aggregation of all given transforms, or `null` if the given `components` array was empty.
    Since:
      0.6
    See Also:
      - `PassThroughTransform`
      - `CRS​.compound(CoordinateReferenceSystem...)`
      - `Envelopes​.compound(Envelope...)`

  - ### concatenate

    public static MathTransform concatenate(MathTransform tr1, MathTransform tr2) throws MismatchedDimensionException
    Concatenates the two given transforms. The returned transform will implement `MathTransform1D` or `MathTransform2D` if the dimensions of the concatenated transform are equal to 1 or 2 respectively.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of the first transform does not match the input dimension of the second transform.
    See Also:
      - `DefaultMathTransformFactory​.createConcatenatedTransform(MathTransform, MathTransform)`

  - ### concatenate

    public static MathTransform1D concatenate(MathTransform1D tr1, MathTransform1D tr2) throws MismatchedDimensionException
    Concatenates the given one-dimensional transforms. This is a convenience methods delegating to `concatenate(MathTransform, MathTransform)` and casting the result to a `MathTransform1D` instance.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of the first transform does not match the input dimension of the second transform.

  - ### concatenate

    public static MathTransform2D concatenate(MathTransform2D tr1, MathTransform2D tr2) throws MismatchedDimensionException
    Concatenates the given two-dimensional transforms. This is a convenience methods delegating to `concatenate(MathTransform, MathTransform)` and casting the result to a `MathTransform2D` instance.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of the first transform does not match the input dimension of the second transform.

  - ### concatenate

    public static MathTransform concatenate(MathTransform tr1, MathTransform tr2, MathTransform tr3) throws MismatchedDimensionException
    Concatenates the three given transforms. This is a convenience methods doing its job as two consecutive concatenations.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
      `tr3` - the third math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of a transform does not match the input dimension of next transform.

  - ### concatenate

    public static MathTransform1D concatenate(MathTransform1D tr1, MathTransform1D tr2, MathTransform1D tr3) throws MismatchedDimensionException
    Concatenates the three given one-dimensional transforms. This is a convenience methods delegating to `concatenate(MathTransform, MathTransform, MathTransform)` and casting the result to a `MathTransform1D` instance.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
      `tr3` - the third math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of a transform does not match the input dimension of next transform.

  - ### concatenate

    public static MathTransform2D concatenate(MathTransform2D tr1, MathTransform2D tr2, MathTransform2D tr3) throws MismatchedDimensionException
    Concatenates the three given two-dimensional transforms. This is a convenience methods delegating to `concatenate(MathTransform, MathTransform, MathTransform)` and casting the result to a `MathTransform2D` instance.
    Parameters:
      `tr1` - the first math transform.
      `tr2` - the second math transform.
      `tr3` - the third math transform.
    Returns:
      the concatenated transform.
    Throws:
      `MismatchedDimensionException` - if the output dimension of a transform does not match the input dimension of next transform.

  - ### bidimensional

    public static MathTransform2D bidimensional(MathTransform transform)
    Returns the given transform as a `MathTransform2D` instance. If the given transform is `null` or already implements the `MathTransform2D` interface, then it is returned as-is. Otherwise the given transform is wrapped in an adapter.
    Parameters:
      `transform` - the transform to have as `MathTransform2D` instance, or `null`.
    Returns:
      the given transform as a `MathTransform2D`, or `null` if the argument was null.
    Throws:
      `MismatchedDimensionException` - if the number of source and target dimensions is not 2.
    Since:
      1.1

  - ### getSteps

    public static List<MathTransform> getSteps(MathTransform transform)
    Returns all single components of the given (potentially concatenated) transform. This method makes the following choice:
    - If `transform` is `null`, returns an empty list.
    - Otherwise if `transform` is the result of calls to `concatenate(…)` methods, returns all steps making the transformation chain. Nested concatenated transforms (if any) are flattened. Note that some steps may have have been merged together, resulting in a shorter list.
    - Otherwise returns the given transform in a list of size 1.
    Parameters:
      `transform` - the transform for which to get the components, or `null`.
    Returns:
      all single math transforms performed by this concatenated transform.

  - ### getMatrix

    @OptionalCandidate public static Matrix getMatrix(MathTransform transform)
    If the given transform is linear, returns its coefficients as a matrix. More specifically:
    - If the given transform is an instance of `LinearTransform`, returns `LinearTransform​.getMatrix()`.
    - Otherwise if the given transform is an instance of `AffineTransform`, returns its coefficients in a `Matrix3` instance.
    - Otherwise returns `null`.
    Parameters:
      `transform` - the transform for which to get the matrix, or `null`.
    Returns:
      the matrix of the given transform, or `null` if none.
    See Also:
      - `linear(Matrix)`
      - `LinearTransform​.getMatrix()`

  - ### getMatrix

    public static Matrix getMatrix(MathTransform toApproximate, DirectPosition tangentPoint) throws TransformException
    Returns the coefficients of an affine transform in the vicinity of the given position. If the given transform is linear, then this method produces a result identical to `getMatrix(MathTransform)`. Otherwise the returned matrix can be used for building a linear transform which can be used as an approximation of the given transform for short distances around the given position.
    Parameters:
      `toApproximate` - the potentially non-linear transform to approximate by an affine transform.
      `tangentPoint` - position in source CRS around which to get the coefficients of an affine transform approximation.
    Returns:
      the matrix representation of the affine approximation of the given transform around the given position.
    Throws:
      `TransformException` - if an error occurred while transforming the given position or computing the derivative at that position.
    Since:
      1.0
    See Also:
      - `tangent(MathTransform, DirectPosition)`

  - ### getDomain

    public static Optional<Envelope> getDomain(MathTransform evaluated) throws TransformException
    Returns source coordinate values where the transform is mathematically and numerically applicable. This is not the domain of validity for which a coordinate reference system has been defined, because this method ignores "real world" considerations such as datum and country boundaries. This method is for allowing callers to crop their data for removing areas that may cause numerical problems, for example latitudes too close to a pole before Mercator projection.

    See `AbstractMathTransform​.getDomain(DomainDefinition)` for more information. This static method delegates to above-cited method if possible, or returns an empty value otherwise.

    Parameters:
      `evaluated` - transform for which to evaluate a domain, or `null`.
    Returns:
      estimation of a domain where this transform is considered numerically applicable.
    Throws:
      `TransformException` - if the domain cannot be estimated.
    Since:
      1.3
    See Also:
      - `AbstractMathTransform​.getDomain(DomainDefinition)`
      - `CoordinateOperation​.getDomainOfValidity()`

  - ### derivativeAndTransform

    public static Matrix derivativeAndTransform(MathTransform transform, double[] srcPts, int srcOff, double[] dstPts, int dstOff) throws TransformException
    A buckle method for calculating derivative and coordinate transformation in a single step. The transform result is stored in the given destination array, and the derivative matrix is returned. Invoking this method is equivalent to the following code, except that it may execute faster with some `MathTransform` implementations:

        DirectPosition ptSrc = ...;
        DirectPosition ptDst = ...;
        Matrix matrixDst = derivative(ptSrc);
        ptDst = transform(ptSrc, ptDst);

    Parameters:
      `transform` - the transform to use.
      `srcPts` - the array containing the source coordinate.
      `srcOff` - the offset to the point to be transformed in the source array.
      `dstPts` - the array into which the transformed coordinate is returned.
      `dstOff` - the offset to the location of the transformed point that is stored in the destination array.
    Returns:
      the matrix of the transform derivative at the given source position.
    Throws:
      `TransformException` - if the point cannot be transformed or if a problem occurred while calculating the derivative.
    See Also:
      - `tangent(MathTransform, DirectPosition)`
      - `MathTransform​.derivative(DirectPosition)`
      - `Matrices​.createAffine(Matrix, DirectPosition)`