Search in sources :

Example 1 with SpecializedOperationFactory

use of org.apache.sis.internal.referencing.SpecializedOperationFactory in project sis by apache.

the class CoordinateOperationFinder method createOperations.

/**
 * Infers operations for conversions or transformations between two coordinate reference systems.
 * If a non-null authority factory – the <cite>registry</cite> – has been specified at construction time,
 * then this method will first query that factory (<cite>late-binding</cite> approach – see class javadoc).
 * If no operation has been found in the registry or if no registry has been specified to the constructor,
 * this method inspects the given CRS and delegates the work to one or many {@code createOperationStep(…)}
 * methods (<cite>early-binding</cite> approach).
 *
 * <p>At first, this method is invoked with the {@code sourceCRS} and {@code targetCRS} arguments given to the
 * {@link DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem,
 * CoordinateOperationContext) CoordinateOperationFactory.createOperation(…)} method. But then, this method may
 * be invoked recursively by some {@code createOperationStep(…)} methods with different source or target CRS,
 * for example in order to process the {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS#getBaseCRS()
 * base geographic CRS} of a projected CRS.</p>
 *
 * <p>Coordinate operations are returned in preference order: best operations for the area of interest should be first.
 * The returned list is modifiable: callers can add, remove or set elements without impact on this
 * {@code CoordinateOperationFinder} instance.</p>
 *
 * @param  sourceCRS  input coordinate reference system.
 * @param  targetCRS  output coordinate reference system.
 * @return coordinate operations from {@code sourceCRS} to {@code targetCRS}.
 * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
 * @throws FactoryException if the operation creation failed for some other reason.
 *
 * @since 1.0
 */
@Override
public List<CoordinateOperation> createOperations(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS) throws FactoryException {
    ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
    ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
    if (equalsIgnoreMetadata(sourceCRS, targetCRS))
        try {
            return asList(createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(), targetCRS.getCoordinateSystem())));
        } catch (IllegalArgumentException | IncommensurableException e) {
            throw new FactoryException(Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, new CRSPair(sourceCRS, targetCRS)), e);
        }
    /*
         * If this method is invoked recursively, verify if the requested operation is already in the cache.
         * We do not perform this verification on the first invocation because it was already verified by
         * DefaultCoordinateOperationFactory.createOperation(…). We do not block if the operation is in
         * process of being computed in another thread because of the risk of deadlock. If the operation
         * is not in the cache, store the key in our internal map for preventing infinite recursivity.
         */
    final CRSPair key = new CRSPair(sourceCRS, targetCRS);
    if (useCache && stopAtFirst && !previousSearches.isEmpty()) {
        final CoordinateOperation op = factorySIS.cache.peek(key);
        // Must be a modifiable list as per this method contract.
        if (op != null)
            return asList(op);
    }
    if (previousSearches.put(key, Boolean.TRUE) != null) {
        throw new FactoryException(Resources.format(Resources.Keys.RecursiveCreateCallForCode_2, CoordinateOperation.class, key));
    }
    /*
         * If the user did not specified an area of interest, use the domain of validity of the CRS.
         */
    GeographicBoundingBox bbox = Extents.getGeographicBoundingBox(areaOfInterest);
    if (bbox == null) {
        bbox = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS), CRS.getGeographicBoundingBox(targetCRS));
        areaOfInterest = CoordinateOperationContext.setGeographicBoundingBox(areaOfInterest, bbox);
    }
    /*
         * Verify if some extension module handles this pair of CRS in a special way. For example it may
         * be the "sis-gdal" module checking if the given CRS are wrappers around Proj.4 data structure.
         */
    {
        // For keeping 'operations' list locale.
        final List<CoordinateOperation> operations = new ArrayList<>();
        for (final SpecializedOperationFactory sp : factorySIS.getSpecializedFactories()) {
            for (final CoordinateOperation op : sp.findOperations(sourceCRS, targetCRS)) {
                if (filter(op)) {
                    operations.add(op);
                }
            }
        }
        if (!operations.isEmpty()) {
            CoordinateOperationSorter.sort(operations, bbox);
            return operations;
        }
    }
    /*
         * Verify in the EPSG dataset if the operation is explicitely defined by an authority.
         */
    if (registry != null) {
        final List<CoordinateOperation> authoritatives = super.createOperations(sourceCRS, targetCRS);
        if (!authoritatives.isEmpty())
            return authoritatives;
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof GeneralDerivedCRS) {
        final GeneralDerivedCRS source = (GeneralDerivedCRS) sourceCRS;
        if (targetCRS instanceof GeneralDerivedCRS) {
            return createOperationStep(source, (GeneralDerivedCRS) targetCRS);
        }
        if (targetCRS instanceof SingleCRS) {
            return createOperationStep(source, (SingleCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (targetCRS instanceof GeneralDerivedCRS) {
        final GeneralDerivedCRS target = (GeneralDerivedCRS) targetCRS;
        if (sourceCRS instanceof SingleCRS) {
            return createOperationStep((SingleCRS) sourceCRS, target);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof GeodeticCRS) {
        final GeodeticCRS source = (GeodeticCRS) sourceCRS;
        if (targetCRS instanceof GeodeticCRS) {
            return createOperationStep(source, (GeodeticCRS) targetCRS);
        }
        if (targetCRS instanceof VerticalCRS) {
            return createOperationStep(source, (VerticalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof VerticalCRS) {
        final VerticalCRS source = (VerticalCRS) sourceCRS;
        if (targetCRS instanceof VerticalCRS) {
            return createOperationStep(source, (VerticalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof TemporalCRS) {
        final TemporalCRS source = (TemporalCRS) sourceCRS;
        if (targetCRS instanceof TemporalCRS) {
            return createOperationStep(source, (TemporalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof CompoundCRS || targetCRS instanceof CompoundCRS) {
        return createOperationStep(sourceCRS, CRS.getSingleComponents(sourceCRS), targetCRS, CRS.getSingleComponents(targetCRS));
    }
    throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
}
Also used : FactoryException(org.opengis.util.FactoryException) SpecializedOperationFactory(org.apache.sis.internal.referencing.SpecializedOperationFactory) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

ArrayList (java.util.ArrayList)1 List (java.util.List)1 SpecializedOperationFactory (org.apache.sis.internal.referencing.SpecializedOperationFactory)1 GeographicBoundingBox (org.opengis.metadata.extent.GeographicBoundingBox)1 FactoryException (org.opengis.util.FactoryException)1