Class TransformSeparator

java.lang.Object
org.apache.sis.referencing.operation.transform.TransformSeparator

public class TransformSeparator extends Object
Extracts a sub-transform from a given MathTransform and source or target dimension indices. Given an arbitrary MathTransform, this class tries to return a new math transform that operates only on a given set of source or target dimensions.
Example: if the supplied transform has (x,y,z) inputs and (λ,φ,h) outputs, then the following code: will return a transform with (x,y) inputs and (probably) (λ,φ) outputs. The output dimensions can be verified with a call to getTargetDimensions().
Since:
0.7
Version:
1.1
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    The factory to use for creating new math transforms.
    private boolean
    Whether separate() is allowed to add new dimensions in sourceDimensions if this is required for computing all values specified in targetDimensions.
    protected int[]
    Indices of transform input dimensions to keep, or null if not yet defined.
    protected int[]
    Indices of transform output dimensions to keep, or null if not yet defined.
    protected final org.opengis.referencing.operation.MathTransform
    The transform to separate.
  • Constructor Summary

    Constructors
    Constructor
    Description
    TransformSeparator(org.opengis.referencing.operation.MathTransform transform)
    Constructs a separator for the given transform.
    TransformSeparator(org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.MathTransformFactory factory)
    Constructs a separator for the given transform and using the given factory.
  • Method Summary

    Modifier and Type
    Method
    Description
    private static int[]
    add(int[] sequence, int[] dimensions, int max)
    Adds the specified dimensions to the specified sequence.
    private static int[]
    add(int[] sequence, int lower, int upper, int max)
    Adds the specified range to the specified sequence.
    void
    addSourceDimensionRange(int lower, int upper)
    Adds a range of input dimensions to keep in the separated transform.
    void
    addSourceDimensions(int... dimensions)
    Adds input dimensions to keep in the separated transform.
    void
    addTargetDimensionRange(int lower, int upper)
    Adds a range of output dimensions to keep in the separated transform.
    void
    addTargetDimensions(int... dimensions)
    Adds output dimensions to keep in the separated transform.
    void
    Resets this transform separator in the same state than after construction.
    private static boolean
    containsAll(int[] sequence, int lower, int upper)
    Returns true if the given sequence contains all indices in the range lower inclusive to upper exclusive.
    private static boolean
    containsAny(int[] sequence, int lower, int upper)
    Returns true if the given sequence contains any value in the given range.
    protected org.opengis.referencing.operation.MathTransform
    filterSourceDimensions(org.opengis.referencing.operation.MathTransform step, int[] dimensions)
    Creates a transform for the same mathematic than the given step but expecting only the given dimensions as inputs.
    protected org.opengis.referencing.operation.MathTransform
    filterTargetDimensions(org.opengis.referencing.operation.MathTransform step, int[] dimensions)
    Creates a transform for the same mathematic than the given step but producing only the given dimensions as outputs.
    int[]
    Returns the input dimensions to keep or kept in the separated transform.
    int[]
    Returns the output dimensions to keep or kept in the separated transform.
    private static int[]
    insert(int[] sequence, int dimension)
    Inserts the specified dimension in the specified sequence at a position that preserve increasing order.
    boolean
    Returns whether separate() is allowed to expand the list of source dimensions.
    private org.opengis.referencing.operation.MathTransform
    removeUnusedSourceDimensions(org.opengis.referencing.operation.MathTransform head, int[] required)
    Removes the sources dimensions that are not required for computing the target dimensions.
    org.opengis.referencing.operation.MathTransform
    Separates the math transform specified at construction time for given dimension indices.
    void
    setSourceExpandable(boolean enabled)
    Sets whether separate() is allowed to expand the list of source dimensions.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • transform

      protected final org.opengis.referencing.operation.MathTransform transform
      The transform to separate.
    • sourceDimensions

      protected int[] sourceDimensions
      Indices of transform input dimensions to keep, or null if not yet defined. If non-null, the indices in the array must be sorted in strictly increasing order. This sequence can contain any integers in the range 0 inclusive to MathTransform.getSourceDimensions() exclusive.

      Values in this array should never be modified. For adding, removing or editing indices, new arrays should be created and assigned to this field. This approach makes easier to keep snapshots of indices arrays at various stages during the process of separating a MathTransform.

      See Also:
    • targetDimensions

      protected int[] targetDimensions
      Indices of transform output dimensions to keep, or null if not yet defined. If non-null, the indices in the array must be sorted in strictly increasing order. This sequence can contain any integers in the range 0 inclusive to MathTransform.getTargetDimensions() exclusive.

      Values in this array should never be modified. For adding, removing or editing indices, new arrays should be created and assigned to this field. This approach makes easier to keep snapshots of indices arrays at various stages during the process of separating a MathTransform.

      See Also:
    • factory

      private final MathTransformsOrFactory factory
      The factory to use for creating new math transforms.
    • isSourceExpandable

      private boolean isSourceExpandable
      Whether separate() is allowed to add new dimensions in sourceDimensions if this is required for computing all values specified in targetDimensions.
      See Also:
  • Constructor Details

    • TransformSeparator

      public TransformSeparator(org.opengis.referencing.operation.MathTransform transform)
      Constructs a separator for the given transform.
      Parameters:
      transform - the transform to separate.
    • TransformSeparator

      public TransformSeparator(org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.MathTransformFactory factory)
      Constructs a separator for the given transform and using the given factory.
      Parameters:
      transform - the transform to separate.
      factory - the factory to use for creating new math transforms, or null if none.
  • Method Details

    • clear

      public void clear()
      Resets this transform separator in the same state than after construction. This method clears any source and target dimensions settings and disables source expansion. This method can be invoked when the same MathTransform needs to be separated in more than one part, for example an horizontal and a vertical component.
    • insert

      private static int[] insert(int[] sequence, int dimension) throws IllegalArgumentException
      Inserts the specified dimension in the specified sequence at a position that preserve increasing order. This method does nothing if the given dimension already exists in the given array.
      Note: we do not provide public API for this method because we rather encourage bulk operations (adding many values at once), and because the public API does not allow to specify values in random order (for avoiding risk of confusion as some users could expect the separated transform to use the dimensions in the order he specified them).
      Parameters:
      sequence - the sourceDimensions or targetDimensions sequence to update.
      dimension - the value to add to the given sequence.
      Throws:
      IllegalArgumentException
    • add

      private static int[] add(int[] sequence, int[] dimensions, int max) throws IllegalArgumentException
      Adds the specified dimensions to the specified sequence. Values must be given in strictly increasing order (this will be verified by this method).
      Parameters:
      sequence - the sourceDimensions or targetDimensions sequence to update.
      dimensions - the user supplied dimensions to add to the given sequence.
      max - the maximal value allowed, exclusive.
      Throws:
      IllegalArgumentException - if a dimensions value does not met the conditions.
    • add

      private static int[] add(int[] sequence, int lower, int upper, int max) throws IllegalArgumentException
      Adds the specified range to the specified sequence.
      Parameters:
      sequence - the sourceDimensions or targetDimensions sequence to update.
      lower - the lower value of the range to add, inclusive.
      upper - the upper value of the range to add, exclusive.
      max - the maximal value allowed, exclusive.
      Throws:
      IllegalArgumentException - if the lower or upper value does not met the conditions.
    • addSourceDimensions

      public void addSourceDimensions(int... dimensions) throws IllegalArgumentException
      Adds input dimensions to keep in the separated transform. The given values are source dimension indices of the transform given to the constructor.

      Constraints:

      • All numbers shall be in the range 0 inclusive to MathTransform.getSourceDimensions() exclusive.
      • The dimensions values shall be in strictly increasing order.
      • The dimensions values shall be greater than all values specified by all previous calls of this method since construction or since the last call to clear().
      Parameters:
      dimensions - a sequence of source dimensions to keep, in strictly increasing order.
      Throws:
      IllegalArgumentException - if dimensions contains negative values or if values are not in a strictly increasing order.
    • addSourceDimensionRange

      public void addSourceDimensionRange(int lower, int upper) throws IllegalArgumentException
      Adds a range of input dimensions to keep in the separated transform. The lower and upper values define a range of source dimension indices of the transform given to the constructor.
      Parameters:
      lower - the lower dimension, inclusive. Shall not be smaller than 0.
      upper - the upper dimension, exclusive. Shall be smaller than MathTransform.getSourceDimensions().
      Throws:
      IllegalArgumentException - if lower or upper are out of bounds.
    • getSourceDimensions

      public int[] getSourceDimensions() throws IllegalStateException
      Returns the input dimensions to keep or kept in the separated transform. This method performs the first applicable action in the following list:
      1. Source dimensions have been explicitly set by at least one call to addSourceDimensions(int...) or addSourceDimensionRange(int, int) since construction or since last call to clear(). In such case, this method returns all specified source dimensions.
      2. No source dimensions were set but separate() has been invoked. In such case, this method returns the sequence of source dimensions that separate() chooses to retain. It may be all source dimensions of the transform given at construction time, but not necessarily.
      3. Otherwise an exception is thrown.
      If source dimensions have not been set explicitly, TransformSeparator tries to reduce the set of source dimensions to the smallest set required for computing the target dimensions.
      Returns:
      the input dimension as a sequence of strictly increasing values.
      Throws:
      IllegalStateException - if input dimensions have not been set and separate() has not yet been invoked.
    • addTargetDimensions

      public void addTargetDimensions(int... dimensions) throws IllegalArgumentException
      Adds output dimensions to keep in the separated transform. The given values are target dimension indices of the transform given to the constructor.

      Constraints:

      • All numbers shall be in the range 0 inclusive to MathTransform.getTargetDimensions() exclusive.
      • The dimensions values shall be in strictly increasing order.
      • The dimensions values shall be greater than all values specified by all previous calls of this method since construction or since the last call to clear().
      Parameters:
      dimensions - a sequence of target dimensions to keep, in strictly increasing order.
      Throws:
      IllegalArgumentException - if dimensions contains negative values or if values are not in a strictly increasing order.
    • addTargetDimensionRange

      public void addTargetDimensionRange(int lower, int upper) throws IllegalArgumentException
      Adds a range of output dimensions to keep in the separated transform. The lower and upper values define a range of target dimension indices of the transform given to the constructor.
      Parameters:
      lower - the lower dimension, inclusive. Shall not be smaller than 0.
      upper - the upper dimension, exclusive. Shall be smaller than MathTransform.getTargetDimensions().
      Throws:
      IllegalArgumentException - if lower or upper are out of bounds.
    • getTargetDimensions

      public int[] getTargetDimensions() throws IllegalStateException
      Returns the output dimensions to keep or kept in the separated transform. This method performs the first applicable action in the following list:
      1. Target dimensions have been explicitly set by at least one call to addTargetDimensions(int...) or addTargetDimensionRange(int, int) since construction or since last call to clear(). In such case, this method returns all specified target dimensions.
      2. No target dimensions were set but separate() has been invoked. In such case, the target dimensions are inferred automatically from the source dimensions and the transform.
      3. Otherwise an exception is thrown.
      Returns:
      the output dimension as a sequence of strictly increasing values.
      Throws:
      IllegalStateException - if output dimensions have not been set and separate() has not yet been invoked.
    • isSourceExpandable

      public boolean isSourceExpandable()
      Returns whether separate() is allowed to expand the list of source dimensions. The default value is false, which means that separate() either returns a MathTransform having exactly the requested source dimensions, or throws a FactoryException.
      Returns:
      whether separate() is allowed to add new source dimensions instead of throwing a FactoryException.
      Since:
      1.1
    • setSourceExpandable

      public void setSourceExpandable(boolean enabled)
      Sets whether separate() is allowed to expand the list of source dimensions. The default value is false, which means that separate() will throw a FactoryException if some target dimensions cannot be computed without inputs that are not in the list of source dimensions. If this flag is set to true, then separate() will be allowed to augment the list of source dimensions with any inputs that are essential for producing all requested outputs.
      Parameters:
      enabled - whether to allow source dimensions expansion.
      Since:
      1.1
    • separate

      public org.opengis.referencing.operation.MathTransform separate() throws org.opengis.util.FactoryException
      Separates the math transform specified at construction time for given dimension indices. This method creates a math transform that use only the specified source dimensions and return only the specified target dimensions. If the source or target dimensions were not specified, then they will be inferred as below:
      • If source dimensions were unspecified, then the returned transform will keep only the source dimensions needed for computing the specified target dimensions. If all source dimensions need to be kept, then they should be specified explicitly.
      • If target dimensions were unspecified, then the returned transform will expect only the specified source dimensions as inputs, and the target dimensions will be inferred automatically.
      • If neither source and target positions were specified, then the returned transform will have the same set of target dimensions, but only the set of source dimensions required for computing those targets. In other words, this method drops unused source dimensions.
      The source and target dimensions actually used can be queried by calls to getSourceDimensions() or getTargetDimensions() after this separate() method.
      Returns:
      the separated math transform.
      Throws:
      org.opengis.util.FactoryException - if the transform cannot be separated.
    • filterSourceDimensions

      protected org.opengis.referencing.operation.MathTransform filterSourceDimensions(org.opengis.referencing.operation.MathTransform step, int[] dimensions) throws org.opengis.util.FactoryException
      Creates a transform for the same mathematic than the given step but expecting only the given dimensions as inputs. This method is invoked by separate() when user-specified source dimensions need to be taken in account. The given step and dimensions are typically the values of transform and sourceDimensions fields respectively, but not necessarily. In particular those arguments will differ when this method is invoked recursively for processing concatenated or sub-transforms.

      Subclasses can override this method if they need to handle some MathTransform implementations in a special way. However, all implementations of this method shall obey to the following contract:

      • sourceDimensions and targetDimensions should not be assumed accurate since they may be temporarily outdated or modified during recursive calls to this method.
      • sourceDimensions should not be modified by this method.
      • targetDimensions must be overwritten (not updated) by this method to the sequence of all target dimensions of step that are also target dimensions of the returned transform. The indices shall be in strictly increasing order from 0 inclusive to step.getTargetDimensions() exclusive.
      Parameters:
      step - the transform for which to retain only a subset of the source dimensions.
      dimensions - indices of the source dimensions of step to retain.
      Returns:
      a transform expecting only the given source dimensions.
      Throws:
      org.opengis.util.FactoryException - if the given transform is not separable.
    • filterTargetDimensions

      protected org.opengis.referencing.operation.MathTransform filterTargetDimensions(org.opengis.referencing.operation.MathTransform step, int[] dimensions) throws org.opengis.util.FactoryException
      Creates a transform for the same mathematic than the given step but producing only the given dimensions as outputs. This method is invoked by separate() when user-specified target dimensions need to be taken in account. The given step and dimensions are typically the values of transform and targetDimensions fields respectively, but not necessarily.

      Subclasses can override this method if they need to handle some MathTransform implementations in a special way. However, all implementations of this method shall obey to the following contract:

      The number and nature of inputs stay unchanged. For example if the supplied transform has (longitude, latitude, height) outputs, then a filtered transform may keep only the (longitude, latitude) part for the same inputs. In most cases, the filtered transform is non-invertible since it looses information.
      Parameters:
      step - the transform for which to retain only a subset of the target dimensions.
      dimensions - indices of the target dimensions of step to retain.
      Returns:
      a transform producing only the given target dimensions.
      Throws:
      org.opengis.util.FactoryException - if the given transform is not separable.
    • removeUnusedSourceDimensions

      private org.opengis.referencing.operation.MathTransform removeUnusedSourceDimensions(org.opengis.referencing.operation.MathTransform head, int[] required)
      Removes the sources dimensions that are not required for computing the target dimensions. This method is invoked only if sourceDimensions is null at separate() invocation time. This method can operate only on the first transform of a transformation chain. If this method succeed, then sourceDimensions will be updated.

      This method can process only linear transforms (potentially indirectly through a concatenated transform). Actually it would be possible to also process pass-through transform followed by a linear transform, but this case should have been optimized during transform concatenation. If it is not the case, consider improving the PassThroughTransform.tryConcatenate(boolean, MathTransform, MathTransformFactory) method instead of this one.

      Parameters:
      head - the first transform of a transformation chain.
      required - sources to keep even if not necessary, or null if none.
      Returns:
      the reduced transform, or head if this method did not reduced the transform.
    • containsAll

      private static boolean containsAll(int[] sequence, int lower, int upper)
      Returns true if the given sequence contains all indices in the range lower inclusive to upper exclusive.
      Parameters:
      sequence - the sourceDimensions or targetDimensions sequence to test.
      lower - the lower value, inclusive.
      upper - the upper value, exclusive.
      Returns:
      true if the full range was found in the sequence.
    • containsAny

      private static boolean containsAny(int[] sequence, int lower, int upper)
      Returns true if the given sequence contains any value in the given range.
      Parameters:
      sequence - the sourceDimensions or targetDimensions sequence to test.
      lower - the lower value, inclusive.
      upper - the upper value, exclusive.
      Returns:
      true if the sequence contains at least one value in the given range.