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));
}
Aggregations