Class CoordinateOperationRegistry

java.lang.Object
org.apache.sis.referencing.operation.CoordinateOperationRegistry
Direct Known Subclasses:
CoordinateOperationFinder

class CoordinateOperationRegistry extends Object
Base class of code that search for coordinate operation, either by looking in a registry maintained by an authority or by trying to infer the coordinate operation by itself. For maintenance and testing purposes, we separate the task in two classes for the two main strategies used for finding coordinate operations:
  • CoordinateOperationRegistry implements the late-binding approach (i.e. search coordinate operation paths specified by authorities like the ones listed in the EPSG dataset), which is the preferred approach.
  • CoordinateOperationFinder adds an early-binding approach (i.e. find a coordinate operation path by inspecting the properties associated to the CRS). That approach is used only as a fallback when the late-binding approach gave no result.
When createOperations(sourceCRS, targetCRS) is invoked, this class fetches the authority codes for source and target CRS and submits them to the authority factory through a call to its createFromCoordinateReferenceSystemCodes(sourceCode, targetCode) method. If the authority factory does not know about the specified CRS, then CoordinateOperationFinder will use its own fallback.
Since:
0.7
Version:
1.2
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    private static enum 
    Strategies for decomposing a three-dimensional CRS into components that may be present in EPSG database.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected org.opengis.metadata.extent.Extent
    The spatiotemporal area of interest, or null if none.
    private final Map<org.opengis.referencing.crs.CoordinateReferenceSystem,List<String>>
    Authority codes found for CRS.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for conversion using an affine transform for axis swapping and/or unit conversions.
    The object to use for finding authority codes, or null if none.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for an operation setting some coordinates to constant values.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for a transformation which is a datum shift.
    protected double
    The desired accuracy in metres, or 0 for the best accuracy available.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for a transformation which is a datum shift without BursaWolfParameters.
    protected final org.opengis.referencing.operation.CoordinateOperationFactory
    The factory to use for creating coordinate operations not found in the registry.
    (package private) final DefaultCoordinateOperationFactory
    Used only when we need a SIS-specific method.
    private Predicate<org.opengis.referencing.operation.CoordinateOperation>
    A filter that can be used for applying additional restrictions on the coordinate operation, or null if none.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for a geocentric conversion.
    (package private) static final org.opengis.metadata.Identifier
    The identifier for an identity operation.
    private static final org.opengis.metadata.Identifier
    The identifier for an inverse operation.
    protected final org.opengis.referencing.operation.CoordinateOperationAuthorityFactory
    The factory to use for creating operations as defined by authority, or null if none.
    (package private) boolean
    true if search(…) should stop after the first coordinate operation found.
  • Constructor Summary

    Constructors
    Constructor
    Description
    CoordinateOperationRegistry(org.opengis.referencing.operation.CoordinateOperationAuthorityFactory registry, org.opengis.referencing.operation.CoordinateOperationFactory factory, CoordinateOperationContext context)
    Creates a new instance for the given factory and context.
  • Method Summary

    Modifier and Type
    Method
    Description
    private org.opengis.referencing.operation.CoordinateOperation
    complete(org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS)
    Completes (if necessary) the given coordinate operation for making sure that the source CRS is the given one and the target CRS is the given one.
    (package private) final org.opengis.referencing.operation.CoordinateOperation
    createFromMathTransform(Map<String,Object> properties, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.OperationMethod method, org.opengis.parameter.ParameterValueGroup parameters, Class<? extends org.opengis.referencing.operation.CoordinateOperation> type)
    Creates a coordinate operation from a math transform.
    private static org.opengis.metadata.Identifier
    createIdentifier(short key)
    Creates an identifier in the Apache SIS namespace for the given vocabulary key.
    List<org.opengis.referencing.operation.CoordinateOperation>
    createOperations(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS)
    Finds or infers operations for conversions or transformations between two coordinate reference systems.
    private static Map<String,?>
    derivedFrom(org.opengis.referencing.IdentifiedObject object)
    Returns the properties of the given object, excluding the identifiers.
    private List<String>
    findCode(org.opengis.referencing.crs.CoordinateReferenceSystem crs)
    Finds the authority codes for the given coordinate reference system.
    private org.opengis.referencing.operation.CoordinateOperation
    fromDefiningConversion(org.opengis.referencing.operation.SingleOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS)
    Creates a complete coordinate operation from a defining conversion.
    private org.opengis.referencing.operation.CoordinateOperation
    inverse(org.opengis.referencing.operation.CoordinateOperation operation)
    Creates the inverse of the given operation, which may be single or compound.
    (package private) final org.opengis.referencing.operation.CoordinateOperation
    inverse(org.opengis.referencing.operation.SingleOperation op)
    Creates the inverse of the given single operation.
    private static boolean
    isEasySearch(org.opengis.referencing.crs.CoordinateReferenceSystem crs)
    Returns whether it is presumed easy for IdentifiedObjectFinder to perform a full search (ignoring axis order) for the given CRS.
    private static void
    log(LogRecord record, Exception exception)
    Logs an unexpected but ignorable exception.
    private boolean
    propagateVertical(org.opengis.referencing.crs.CoordinateReferenceSystem source3D, org.opengis.referencing.crs.CoordinateReferenceSystem target3D, ListIterator<org.opengis.referencing.operation.CoordinateOperation> operations, boolean forward)
    Appends a vertical axis in the source CRS of the first step forward = true or in the target CRS of the last step forward = false of the given operations chain.
    private org.opengis.referencing.operation.CoordinateOperation
    propagateVertical(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.CoordinateOperation operation, CoordinateOperationRegistry.Decomposition decompose)
    Returns a new coordinate operation with the ellipsoidal height added either in the source coordinates, in the target coordinates or both.
    (package private) static Map<String,Object>
    properties(org.opengis.metadata.Identifier name)
    Returns the specified identifier in a map to be given to coordinate operation constructors.
    (package private) static void
    Logs an ignorable exception.
    private org.opengis.referencing.operation.CoordinateOperation
    recreate(org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.OperationMethod method)
    Creates a new coordinate operation with the same method than the given operation, but different CRS.
    private List<org.opengis.referencing.operation.CoordinateOperation>
    search(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS)
    Returns operations for conversions or transformations between two coordinate reference systems.
    private static org.opengis.referencing.operation.MathTransform
    swapAndScaleAxes(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransformFactory mtFactory)
    Returns an affine transform between two coordinate systems.
    (package private) final <T extends org.opengis.referencing.IdentifiedObject>
    T
    toAuthorityDefinition(Class<T> type, T object)
    If the authority defines an object equal, ignoring metadata, to the given object, returns that authority object.
    private org.opengis.referencing.crs.CoordinateReferenceSystem
    toGeodetic3D(org.opengis.referencing.crs.CoordinateReferenceSystem crs, org.opengis.referencing.crs.CoordinateReferenceSystem candidate)
    If the given CRS is two-dimensional, append an ellipsoidal height to it.
    private org.opengis.referencing.operation.CoordinateOperation
    transform(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.operation.MathTransform prepend, org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.operation.MathTransform append, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransformFactory mtFactory)
    Appends or prepends the specified math transforms to the transform of the given operation.

    Methods inherited from class java.lang.Object

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

    • IDENTITY

      static final org.opengis.metadata.Identifier IDENTITY
      The identifier for an identity operation.
    • CONSTANTS

      static final org.opengis.metadata.Identifier CONSTANTS
      The identifier for an operation setting some coordinates to constant values.
    • AXIS_CHANGES

      static final org.opengis.metadata.Identifier AXIS_CHANGES
      The identifier for conversion using an affine transform for axis swapping and/or unit conversions.
    • ELLIPSOID_CHANGE

      static final org.opengis.metadata.Identifier ELLIPSOID_CHANGE
      The identifier for a transformation which is a datum shift without BursaWolfParameters. Only the changes in ellipsoid axis-length are taken in account. Such ellipsoid shifts are approximations and may have 1 kilometre error.
      See Also:
    • DATUM_SHIFT

      static final org.opengis.metadata.Identifier DATUM_SHIFT
      The identifier for a transformation which is a datum shift.
      See Also:
    • GEOCENTRIC_CONVERSION

      static final org.opengis.metadata.Identifier GEOCENTRIC_CONVERSION
      The identifier for a geocentric conversion.
    • INVERSE_OPERATION

      private static final org.opengis.metadata.Identifier INVERSE_OPERATION
      The identifier for an inverse operation.
    • codeFinder

      private final IdentifiedObjectFinder codeFinder
      The object to use for finding authority codes, or null if none. An instance is fetched at construction time from the registry if possible.
      Design note: using a finder defined by the registry instead of MultiAuthoritiesFactory may cause the finder to perform extensive searches because it does not recognize the authority code of a given CRS. For example if registry is for EPSG and a given CRS is "CRS:84", then codeFinder would not recognize the given CRS and would search for a match in the EPSG database. This is desired because we need to have the two CRSs defined by the same authority (if possible) in order to find a predefined operation, even if an equivalent definition was provided by another authority.
      See Also:
    • registry

      protected final org.opengis.referencing.operation.CoordinateOperationAuthorityFactory registry
      The factory to use for creating operations as defined by authority, or null if none. This is the factory used by the late-binding approach.
    • factory

      protected final org.opengis.referencing.operation.CoordinateOperationFactory factory
      The factory to use for creating coordinate operations not found in the registry. This is the factory used by the early-binding approach.
    • factorySIS

      Used only when we need a SIS-specific method.
    • areaOfInterest

      protected org.opengis.metadata.extent.Extent areaOfInterest
      The spatiotemporal area of interest, or null if none. When a new CoordinateOperationFinder instance is created with a non-null CoordinateOperationContext, the context is used for initializing this value. After initialization, this field may be updated as CoordinateOperationFinder progresses in its search for a coordinate operation.
      See Also:
    • desiredAccuracy

      protected double desiredAccuracy
      The desired accuracy in metres, or 0 for the best accuracy available.
      See Also:
    • stopAtFirst

      boolean stopAtFirst
      true if search(…) should stop after the first coordinate operation found. This field is set to true when the caller is interested only in the "best" operation instead of all of possibilities.
      See Also:
    • filter

      private Predicate<org.opengis.referencing.operation.CoordinateOperation> filter
      A filter that can be used for applying additional restrictions on the coordinate operation, or null if none. If non-null, only operations passing this filter will be considered.
      See Also:
    • authorityCodes

      private final Map<org.opengis.referencing.crs.CoordinateReferenceSystem,List<String>> authorityCodes
      Authority codes found for CRS. This is a cache for findCode(CoordinateReferenceSystem). This map may be non-empty only if codeFinder is non-null.
      Design note: a cache is used because codes for the same CRS can be requested many times while iterating over the strategies enumerated by CoordinateOperationRegistry.Decomposition. This cache partially duplicates the cache provided by IdentifiedObjectFinder implementations, but we have no guarantees that those implementations provide such cache, and the values cached here are the result of a little bit more work.
      See Also:
  • Constructor Details

    • CoordinateOperationRegistry

      CoordinateOperationRegistry(org.opengis.referencing.operation.CoordinateOperationAuthorityFactory registry, org.opengis.referencing.operation.CoordinateOperationFactory factory, CoordinateOperationContext context) throws org.opengis.util.FactoryException
      Creates a new instance for the given factory and context.
      Parameters:
      registry - the factory to use for creating operations as defined by authority.
      factory - the factory to use for creating operations not found in the registry.
      context - the area of interest and desired accuracy, or null if none.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while initializing this CoordinateOperationRegistry.
  • Method Details

    • createIdentifier

      private static org.opengis.metadata.Identifier createIdentifier(short key)
      Creates an identifier in the Apache SIS namespace for the given vocabulary key.
    • toAuthorityDefinition

      final <T extends org.opengis.referencing.IdentifiedObject> T toAuthorityDefinition(Class<T> type, T object) throws org.opengis.util.FactoryException
      If the authority defines an object equal, ignoring metadata, to the given object, returns that authority object. Otherwise returns the given object unchanged. We do not invoke this method for user supplied CRS, but only for CRS or other objects created by CoordinateOperationRegistry as intermediate step.
      Throws:
      org.opengis.util.FactoryException
    • findCode

      private List<String> findCode(org.opengis.referencing.crs.CoordinateReferenceSystem crs) throws org.opengis.util.FactoryException
      Finds the authority codes for the given coordinate reference system. This method does not trust the code given by the user in its CRS - we verify it. This method may return codes even if the axis order does not match; it will be caller's responsibility to make necessary adjustments.
      Parameters:
      crs - the CRS for which to search authority codes.
      Returns:
      authority codes for the given CRS, or an empty list if none. Do not modify since this list may be cached.
      Throws:
      org.opengis.util.FactoryException
    • isEasySearch

      private static boolean isEasySearch(org.opengis.referencing.crs.CoordinateReferenceSystem crs)
      Returns whether it is presumed easy for IdentifiedObjectFinder to perform a full search (ignoring axis order) for the given CRS. An important criterion is to avoid all CRS containing a coordinate operation (in particular projected CRS), because they are difficult to search.

      We allow extensive search of geographic CRS because the EPSG database has some geographic CRS defined with both (longitude, latitude) and (latitude, longitude) axis order. But operations may be defined for only one axis order. So if the user specified the CRS with (longitude, latitude) axis order, we want to check also the coordinate operations using (latitude, longitude) axis order because they may be the only ones available.

    • createOperations

      public List<org.opengis.referencing.operation.CoordinateOperation> createOperations(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS) throws org.opengis.util.FactoryException
      Finds or infers operations for conversions or transformations between two coordinate reference systems. CoordinateOperationRegistry implements the late-binding approach (see definition of terms in class javadoc) by extracting the authority codes from the supplied sourceCRS and targetCRS, then by submitting those codes to the createFromCoordinateReferenceSystemCodes(sourceCode, targetCode) method.

      Operations in the returned list are ordered in preference order (preferred operation first). If no operation is found for those codes, then this method returns an empty list. Note that it does not mean that no path exist; it only means that it was not defined explicitly in the registry.

      Parameters:
      sourceCRS - input coordinate reference system.
      targetCRS - output coordinate reference system.
      Returns:
      coordinate operations from sourceCRS to targetCRS, or an empty list if no such operation is explicitly defined in the underlying database.
      Throws:
      org.opengis.util.FactoryException - if the operation creation failed.
    • search

      private List<org.opengis.referencing.operation.CoordinateOperation> search(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS) throws IllegalArgumentException, javax.measure.IncommensurableException, org.opengis.util.FactoryException
      Returns operations for conversions or transformations between two coordinate reference systems. This method extracts the authority code from the supplied sourceCRS and targetCRS, and submits them to the registry. If no operation is found for those codes, then this method returns null.
      Parameters:
      sourceCRS - source coordinate reference system.
      targetCRS - target coordinate reference system.
      Returns:
      a coordinate operation from sourceCRS to targetCRS, or null if no such operation is explicitly defined in the underlying database.
      Throws:
      IllegalArgumentException - if the coordinate systems are not of the same type or axes do not match.
      javax.measure.IncommensurableException - if the units are not compatible or a unit conversion is non-linear.
      org.opengis.util.FactoryException - if an error occurred while creating the operation.
    • inverse

      final org.opengis.referencing.operation.CoordinateOperation inverse(org.opengis.referencing.operation.SingleOperation op) throws org.opengis.referencing.operation.NoninvertibleTransformException, org.opengis.util.FactoryException
      Creates the inverse of the given single operation. If this operation succeed, then the returned coordinate operations has the following properties:
      • Its sourceCRS is the targetCRS of the given operation.
      • Its targetCRS is the sourceCRS of the given operation.
      • Its interpolationCRS is null.
      • Its MathTransform is the inverse of the MathTransform of this operation.
      • Its domain of validity and accuracy is the same.
      Note: in many cases, the inverse operation is numerically less accurate than the direct operation because it uses approximations like series expansions or iterative methods. However, the numerical errors caused by those approximations are not of interest here, because they are usually much smaller than the inaccuracy due to the stochastic nature of coordinate transformations (not to be confused with coordinate conversions; see ISO 19111 for more information).
      Throws:
      org.opengis.referencing.operation.NoninvertibleTransformException
      org.opengis.util.FactoryException
    • inverse

      private org.opengis.referencing.operation.CoordinateOperation inverse(org.opengis.referencing.operation.CoordinateOperation operation) throws org.opengis.referencing.operation.NoninvertibleTransformException, org.opengis.util.FactoryException
      Creates the inverse of the given operation, which may be single or compound.

      Design note

      We do not provide a AbstractCoordinateOperation.inverse() method. If the user wants an inverse method, he should invoke CRS.findOperation(targetCRS, sourceCRS, null) or something equivalent. This is because a new query of EPSG database may be necessary, and if no explicit definition is found there is too many arbitrary values to set in a default inverse operation for making that API public.
      Parameters:
      operation - the operation to invert, or null.
      Returns:
      the inverse of operation, or null if none.
      Throws:
      org.opengis.referencing.operation.NoninvertibleTransformException - if the operation is not invertible.
      org.opengis.util.FactoryException - if the operation creation failed for another reason.
    • complete

      private org.opengis.referencing.operation.CoordinateOperation complete(org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS) throws IllegalArgumentException, javax.measure.IncommensurableException, org.opengis.util.FactoryException
      Completes (if necessary) the given coordinate operation for making sure that the source CRS is the given one and the target CRS is the given one. In principle, the given CRS shall be equivalent to the operation source/target CRS. However, discrepancies happen if the user CRS have flipped axis order, or if we looked for 2D operation while the user provided 3D CRS.
      Parameters:
      operation - the coordinate operation to complete.
      sourceCRS - the source CRS requested by the user.
      targetCRS - the target CRS requested by the user.
      Returns:
      a coordinate operation for the given source and target CRS.
      Throws:
      IllegalArgumentException - if the coordinate systems are not of the same type or axes do not match.
      javax.measure.IncommensurableException - if the units are not compatible or a unit conversion is non-linear.
      org.opengis.util.FactoryException - if the operation cannot be constructed.
    • swapAndScaleAxes

      private static org.opengis.referencing.operation.MathTransform swapAndScaleAxes(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransformFactory mtFactory) throws IllegalArgumentException, javax.measure.IncommensurableException, org.opengis.util.FactoryException
      Returns an affine transform between two coordinate systems. Only units and axes order are taken in account by this method.
      Parameters:
      sourceCRS - the source coordinate reference system.
      targetCRS - the target coordinate reference system.
      mtFactory - the math transform factory to use.
      Returns:
      the transform from the given source to the given target CRS, or null if none is needed.
      Throws:
      IllegalArgumentException - if the coordinate systems are not of the same type or axes do not match.
      javax.measure.IncommensurableException - if the units are not compatible or a unit conversion is non-linear.
      org.opengis.util.FactoryException - if an error occurred while creating a math transform.
    • transform

      private org.opengis.referencing.operation.CoordinateOperation transform(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.operation.MathTransform prepend, org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.operation.MathTransform append, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransformFactory mtFactory) throws IllegalArgumentException, org.opengis.util.FactoryException
      Appends or prepends the specified math transforms to the transform of the given operation. The new coordinate operation (if any) will share the same metadata than the original operation, except the authority code.

      This method is used in order to change axis order when the user-specified CRS disagree with the authority-supplied CRS.

      Parameters:
      sourceCRS - the source CRS to give to the new operation.
      prepend - the transform to prepend to the operation math transform, or null if none.
      operation - the operation in which to prepend the math transforms.
      append - the transform to append to the operation math transform, or null if none.
      targetCRS - the target CRS to give to the new operation.
      mtFactory - the math transform factory to use.
      Returns:
      a new operation, or operation if prepend and append were nulls or identity transforms.
      Throws:
      IllegalArgumentException - if the operation method cannot have the desired number of dimensions.
      org.opengis.util.FactoryException - if the operation cannot be constructed.
    • recreate

      private org.opengis.referencing.operation.CoordinateOperation recreate(org.opengis.referencing.operation.CoordinateOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.OperationMethod method) throws IllegalArgumentException, org.opengis.util.FactoryException
      Creates a new coordinate operation with the same method than the given operation, but different CRS. The CRS may differ either in the number of dimensions (i.e. let the vertical coordinate pass through), or in axis order (i.e. axis order in user CRS were not compliant with authority definition).
      Parameters:
      operation - the operation specified by the authority.
      sourceCRS - the source CRS specified by the user.
      targetCRS - the target CRS specified by the user
      transform - the math transform to use in replacement to the one in operation.
      method - the operation method, or null for attempting an automatic detection.
      Returns:
      a new operation from the given source CRS to target CRS using the given transform.
      Throws:
      IllegalArgumentException - if the operation method cannot have the desired number of dimensions.
      org.opengis.util.FactoryException - if an error occurred while creating the new operation.
    • fromDefiningConversion

      private org.opengis.referencing.operation.CoordinateOperation fromDefiningConversion(org.opengis.referencing.operation.SingleOperation operation, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS) throws org.opengis.util.FactoryException
      Creates a complete coordinate operation from a defining conversion. Defining conversions usually have null source and target CRS, but this method nevertheless checks that, in order to reuse the operation CRS if it happens to have some.
      Parameters:
      operation - the operation specified by the authority.
      sourceCRS - the source CRS specified by the user.
      targetCRS - the target CRS specified by the user
      Returns:
      a new operation from the given source CRS to target CRS.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while creating the new operation.
    • propagateVertical

      private org.opengis.referencing.operation.CoordinateOperation propagateVertical(org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.CoordinateOperation operation, CoordinateOperationRegistry.Decomposition decompose) throws IllegalArgumentException, org.opengis.util.FactoryException
      Returns a new coordinate operation with the ellipsoidal height added either in the source coordinates, in the target coordinates or both. If there is an ellipsoidal transform, then this method updates the transforms in order to use the ellipsoidal height (it has an impact on the transformed values).

      This method requires that the EPSG factory insert explicit "Geographic3D to 2D conversion" operations (EPSG:9659) in the operations chain, or an equivalent operation (recognized by its matrix shape). This method tries to locate and remove EPSG:9659 or equivalent operation from the operation chain in order to get three-dimensional domains.

      This method is not guaranteed to succeed in adding the ellipsoidal height. It works on a best effort basis. In any cases, the complete(org.opengis.referencing.operation.CoordinateOperation, org.opengis.referencing.crs.CoordinateReferenceSystem, org.opengis.referencing.crs.CoordinateReferenceSystem) method should be invoked after this one in order to ensure that the source and target CRS are the expected ones.

      Parameters:
      sourceCRS - the potentially three-dimensional source CRS
      targetCRS - the potentially three-dimensional target CRS
      operation - the original (typically two-dimensional) coordinate operation.
      decompose - the decomposition which has been applied. If decompose.source is true, ellipsoidal height will be added to source coordinates. If decompose.target is true, ellipsoidal height will be added to target coordinates.
      Returns:
      a coordinate operation with the source and/or target coordinates made 3D, or null if this method does not know how to create the operation.
      Throws:
      IllegalArgumentException - if the operation method cannot have the desired number of dimensions.
      org.opengis.util.FactoryException - if an error occurred while creating the coordinate operation.
    • propagateVertical

      private boolean propagateVertical(org.opengis.referencing.crs.CoordinateReferenceSystem source3D, org.opengis.referencing.crs.CoordinateReferenceSystem target3D, ListIterator<org.opengis.referencing.operation.CoordinateOperation> operations, boolean forward) throws IllegalArgumentException, org.opengis.util.FactoryException
      Appends a vertical axis in the source CRS of the first step forward = true or in the target CRS of the last step forward = false of the given operations chain.
      Parameters:
      source3D - the potentially three-dimensional source CRS
      target3D - the potentially three-dimensional target CRS
      operations - the chain of operations in which to add a vertical axis.
      forward - true for adding the vertical axis at the beginning, or false for adding the vertical axis at the end.
      Returns:
      true on success.
      Throws:
      IllegalArgumentException - if the operation method cannot have the desired number of dimensions.
      org.opengis.util.FactoryException
    • toGeodetic3D

      private org.opengis.referencing.crs.CoordinateReferenceSystem toGeodetic3D(org.opengis.referencing.crs.CoordinateReferenceSystem crs, org.opengis.referencing.crs.CoordinateReferenceSystem candidate) throws org.opengis.util.FactoryException
      If the given CRS is two-dimensional, append an ellipsoidal height to it. It is caller's responsibility to ensure that the given CRS is geographic.
      Throws:
      org.opengis.util.FactoryException
    • derivedFrom

      private static Map<String,?> derivedFrom(org.opengis.referencing.IdentifiedObject object)
      Returns the properties of the given object, excluding the identifiers. This is used for new objects derived from an object specified by the authority. Since the new object is not strictly as defined by the authority, we cannot keep its identifier code.
    • properties

      static Map<String,Object> properties(org.opengis.metadata.Identifier name)
      Returns the specified identifier in a map to be given to coordinate operation constructors. In the special case where the name identifier is DATUM_SHIFT or ELLIPSOID_CHANGE, the map will contain extra information like positional accuracy.
      Note: in the datum shift case, an operation version is mandatory but unknown at this time. However, we noticed that the EPSG database do not always defines a version neither. Consequently, the Apache SIS implementation relaxes the rule requiring an operation version and we do not try to provide this information here for now.
      Parameters:
      name - the name to put in a map.
      Returns:
      a modifiable map containing the given name. Callers can put other entries in this map.
    • createFromMathTransform

      final org.opengis.referencing.operation.CoordinateOperation createFromMathTransform(Map<String,Object> properties, org.opengis.referencing.crs.CoordinateReferenceSystem sourceCRS, org.opengis.referencing.crs.CoordinateReferenceSystem targetCRS, org.opengis.referencing.operation.MathTransform transform, org.opengis.referencing.operation.OperationMethod method, org.opengis.parameter.ParameterValueGroup parameters, Class<? extends org.opengis.referencing.operation.CoordinateOperation> type) throws org.opengis.util.FactoryException
      Creates a coordinate operation from a math transform. The method performs the following steps:
      • If the given transform is already an instance of CoordinateOperation and if its properties (operation method, source and target CRS) are compatible with the arguments values, then that operation is returned as-is.
        Note: we do not have many objects that are both a CoordinateOperation and a MathTransform, but that combination is not forbidden. Since such practice is sometimes convenient for the implementer, Apache SIS allows that.
      • If the given type is null, then this method infers the type from whether the given properties specify and accuracy or not. If those properties were created by the properties(Identifier) method, then the operation will be a Transformation instance instead of Conversion if the name identifier was DATUM_SHIFT or ELLIPSOID_CHANGE.
      • If the given method is null, then infer an operation method by inspecting the given transform. The transform needs to implement the Parameterized interface in order to allow operation method discovery.
      • Delegate to DefaultCoordinateOperationFactory.createSingleOperation(…).
      Parameters:
      properties - the properties to give to the operation, as a modifiable map.
      sourceCRS - the source coordinate reference system.
      targetCRS - the destination coordinate reference system.
      transform - the math transform.
      method - the operation method, or null if unknown.
      parameters - the operations parameters, or null for automatic detection (not always reliable).
      type - Conversion.class, Transformation.class, or null if unknown.
      Returns:
      a coordinate operation using the specified math transform.
      Throws:
      org.opengis.util.FactoryException - if the operation cannot be created.
    • log

      private static void log(LogRecord record, Exception exception)
      Logs an unexpected but ignorable exception. This method pretends that the logging come from CoordinateOperationFinder since this is the public API which use this CoordinateOperationRegistry class.
      Parameters:
      record - the record to log, or null for creating from the exception.
      exception - the exception which occurred, or null if a record is specified instead.
    • recoverableException

      static void recoverableException(String method, Exception exception)
      Logs an ignorable exception. This method pretends that the logging come from CoordinateOperationFinder since this is the public API which use this CoordinateOperationRegistry class.
      Parameters:
      method - the method name where the error occurred.
      exception - the exception which occurred, or null if a record is specified instead.