Search in sources :

Example 1 with PassThroughTransform

use of org.apache.sis.referencing.operation.transform.PassThroughTransform in project sis by apache.

the class AbstractSingleOperation method checkDimensions.

/**
 * Checks if an operation method and a math transform have a compatible number of source and target dimensions.
 * In the particular case of a {@linkplain PassThroughTransform pass through transform} with more dimensions
 * than what we would expect from the given method, the check will rather be performed against the
 * {@linkplain PassThroughTransform#getSubTransform() sub transform}.
 * The intent is to allow creation of a three-dimensional {@code ProjectedCRS} with a two-dimensional
 * {@code OperationMethod}, where the third-dimension just pass through.
 *
 * <p>This method tries to locates what seems to be the "core" of the given math transform. The definition
 * of "core" is imprecise and may be adjusted in future SIS versions. The current algorithm is as below:</p>
 *
 * <ul>
 *   <li>If the given transform can be decomposed in {@linkplain MathTransforms#getSteps(MathTransform) steps},
 *       then the steps for {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes axis
 *       swapping and scaling} are ignored.</li>
 *   <li>If the given transform or its non-ignorable step is a {@link PassThroughTransform}, then its sub-transform
 *       is taken. Only one non-ignorable step may exist, otherwise we do not try to select any of them.</li>
 * </ul>
 *
 * @param  method      the operation method to compare to the math transform.
 * @param  interpDim   the number of interpolation dimension, or 0 if none.
 * @param  transform   the math transform to compare to the operation method.
 * @param  properties  properties of the caller object being constructed, used only for formatting error message.
 * @throws IllegalArgumentException if the number of dimensions are incompatible.
 */
static void checkDimensions(final OperationMethod method, final int interpDim, MathTransform transform, final Map<String, ?> properties) throws IllegalArgumentException {
    int actual = transform.getSourceDimensions();
    Integer expected = method.getSourceDimensions();
    if (expected != null && actual > expected + interpDim) {
        /*
             * The given MathTransform uses more dimensions than the OperationMethod.
             * Try to locate one and only one sub-transform, ignoring axis swapping and scaling.
             */
        MathTransform subTransform = null;
        for (final MathTransform step : MathTransforms.getSteps(transform)) {
            if (!isIgnorable(step)) {
                if (subTransform == null && step instanceof PassThroughTransform) {
                    subTransform = ((PassThroughTransform) step).getSubTransform();
                } else {
                    subTransform = null;
                    break;
                }
            }
        }
        if (subTransform != null) {
            transform = subTransform;
            actual = transform.getSourceDimensions();
        }
    }
    /*
         * Now verify if the MathTransform dimensions are equal to the OperationMethod ones,
         * ignoring null java.lang.Integer instances.  We do not specify whether the method
         * dimensions should include the interpolation dimensions or not, so we accept both.
         */
    // 0 == false: the wrong dimension is the source one.
    int isTarget = 0;
    if (expected == null || (actual == expected) || (actual == expected + interpDim)) {
        actual = transform.getTargetDimensions();
        expected = method.getTargetDimensions();
        if (expected == null || (actual == expected) || (actual == expected + interpDim)) {
            return;
        }
        // 1 == true: the wrong dimension is the target one.
        isTarget = 1;
    }
    /*
         * At least one dimension does not match.  In principle this is an error, but we make an exception for the
         * "Affine parametric transformation" (EPSG:9624). The reason is that while OGC define that transformation
         * as two-dimensional, it can easily be extended to any number of dimensions. Note that Apache SIS already
         * has special handling for this operation (a TensorParameters dedicated class, etc.)
         */
    if (!IdentifiedObjects.isHeuristicMatchForName(method, Constants.AFFINE)) {
        throw new IllegalArgumentException(Resources.forProperties(properties).getString(Resources.Keys.MismatchedTransformDimension_3, isTarget, expected, actual));
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) PassThroughTransform(org.apache.sis.referencing.operation.transform.PassThroughTransform)

Example 2 with PassThroughTransform

use of org.apache.sis.referencing.operation.transform.PassThroughTransform in project sis by apache.

the class DefaultPassThroughOperation method getModifiedCoordinates.

/**
 * Returns the ordered sequence of indices in a source coordinate tuple of the coordinates
 * affected by this pass-through operation.
 *
 * @return zero-based indices of the modified source coordinates.
 *
 * @see PassThroughTransform#getModifiedCoordinates()
 */
@Override
public int[] getModifiedCoordinates() {
    final MathTransform transform = super.getMathTransform();
    if (transform instanceof PassThroughTransform) {
        return ((PassThroughTransform) transform).getModifiedCoordinates();
    } else {
        /*
             * Should not happen with objects created by public methods since the constructor created the transform
             * itself. However may happen with operations parsed from GML. As a fallback, search in the components
             * of CompoundCRS. This is not a universal fallback, but work for the most straightforward cases.
             */
        final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
        if (sourceCRS instanceof CompoundCRS) {
            int firstAffectedOrdinate = 0;
            final CoordinateReferenceSystem search = operation.getSourceCRS();
            for (final CoordinateReferenceSystem c : ((CompoundCRS) sourceCRS).getComponents()) {
                final int dim = ReferencingUtilities.getDimension(c);
                if (c == search) {
                    final int[] indices = new int[dim];
                    for (int i = 0; i < dim; i++) {
                        indices[i] = firstAffectedOrdinate + i;
                    }
                    return indices;
                }
                firstAffectedOrdinate += dim;
            }
        }
        throw new UnsupportedImplementationException(transform.getClass());
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) PassThroughTransform(org.apache.sis.referencing.operation.transform.PassThroughTransform) UnsupportedImplementationException(org.apache.sis.util.UnsupportedImplementationException)

Aggregations

PassThroughTransform (org.apache.sis.referencing.operation.transform.PassThroughTransform)2 MathTransform (org.opengis.referencing.operation.MathTransform)2 UnsupportedImplementationException (org.apache.sis.util.UnsupportedImplementationException)1 CompoundCRS (org.opengis.referencing.crs.CompoundCRS)1 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)1