Search in sources :

Example 1 with VerticalOffset

use of org.apache.sis.internal.referencing.provider.VerticalOffset in project sis by apache.

the class DefaultMathTransformFactory method swapAndScaleAxes.

/**
 * Given a transform between normalized spaces,
 * creates a transform taking in account axis directions, units of measurement and longitude rotation.
 * This method {@linkplain #createConcatenatedTransform concatenates} the given parameterized transform
 * with any other transform required for performing units changes and ordinates swapping.
 *
 * <p>The given {@code parameterized} transform shall expect
 * {@linkplain org.apache.sis.referencing.cs.AxesConvention#NORMALIZED normalized} input coordinates and
 * produce normalized output coordinates. See {@link org.apache.sis.referencing.cs.AxesConvention} for more
 * information about what Apache SIS means by "normalized".</p>
 *
 * <div class="note"><b>Example:</b>
 * The most typical examples of transforms with normalized inputs/outputs are normalized
 * map projections expecting (<cite>longitude</cite>, <cite>latitude</cite>) inputs in degrees
 * and calculating (<cite>x</cite>, <cite>y</cite>) coordinates in metres,
 * both of them with ({@linkplain org.opengis.referencing.cs.AxisDirection#EAST East},
 * {@linkplain org.opengis.referencing.cs.AxisDirection#NORTH North}) axis orientations.</div>
 *
 * <div class="section">Controlling the normalization process</div>
 * Users who need a different normalized space than the default one way find more convenient to
 * override the {@link Context#getMatrix Context.getMatrix(ContextualParameters.MatrixRole)} method.
 *
 * @param  parameterized  a transform for normalized input and output coordinates.
 * @param  context        source and target coordinate systems in which the transform is going to be used.
 * @return a transform taking in account unit conversions and axis swapping.
 * @throws FactoryException if the object creation failed.
 *
 * @see org.apache.sis.referencing.cs.AxesConvention#NORMALIZED
 * @see org.apache.sis.referencing.operation.DefaultConversion#DefaultConversion(Map, OperationMethod, MathTransform, ParameterValueGroup)
 *
 * @since 0.7
 */
public MathTransform swapAndScaleAxes(final MathTransform parameterized, final Context context) throws FactoryException {
    ArgumentChecks.ensureNonNull("parameterized", parameterized);
    ArgumentChecks.ensureNonNull("context", context);
    /*
         * Computes matrix for swapping axis and performing units conversion.
         * There is one matrix to apply before projection on (longitude,latitude)
         * coordinates, and one matrix to apply after projection on (easting,northing)
         * coordinates.
         */
    final Matrix swap1 = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
    final Matrix swap3 = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
    /*
         * Prepares the concatenation of the matrices computed above and the projection.
         * Note that at this stage, the dimensions between each step may not be compatible.
         * For example the projection (step2) is usually two-dimensional while the source
         * coordinate system (step1) may be three-dimensional if it has a height.
         */
    MathTransform step1 = (swap1 != null) ? createAffineTransform(swap1) : MathTransforms.identity(parameterized.getSourceDimensions());
    MathTransform step3 = (swap3 != null) ? createAffineTransform(swap3) : MathTransforms.identity(parameterized.getTargetDimensions());
    MathTransform step2 = parameterized;
    /*
         * Special case for the way EPSG handles reversal of axis direction. For now the "Vertical Offset" (EPSG:9616)
         * method is the only one for which we found a need for special case. But if more special cases are added in a
         * future SIS version, then we should replace the static method by a non-static one defined in AbstractProvider.
         */
    if (context.provider instanceof VerticalOffset) {
        step2 = VerticalOffset.postCreate(step2, swap3);
    }
    /*
         * If the target coordinate system has a height, instructs the projection to pass
         * the height unchanged from the base CRS to the target CRS. After this block, the
         * dimensions of 'step2' and 'step3' should match.
         */
    final int numTrailingOrdinates = step3.getSourceDimensions() - step2.getTargetDimensions();
    if (numTrailingOrdinates > 0) {
        step2 = createPassThroughTransform(0, step2, numTrailingOrdinates);
    }
    /*
         * If the source CS has a height but the target CS doesn't, drops the extra coordinates.
         * After this block, the dimensions of 'step1' and 'step2' should match.
         */
    final int sourceDim = step1.getTargetDimensions();
    final int targetDim = step2.getSourceDimensions();
    if (sourceDim > targetDim) {
        final Matrix drop = Matrices.createDiagonal(targetDim + 1, sourceDim + 1);
        // Element in the lower-right corner.
        drop.setElement(targetDim, sourceDim, 1);
        step1 = createConcatenatedTransform(createAffineTransform(drop), step1);
    }
    MathTransform mt = createConcatenatedTransform(createConcatenatedTransform(step1, step2), step3);
    /*
         * At this point we finished to create the transform.  But before to return it, verify if the
         * parameterized transform given in argument had some custom parameters. This happen with the
         * Equirectangular projection, which can be simplified as an AffineTransform while we want to
         * continue to describe it with the "semi_major", "semi_minor", etc. parameters  instead than
         * "elt_0_0", "elt_0_1", etc.  The following code just forwards those parameters to the newly
         * created transform; it does not change the operation.
         */
    if (parameterized instanceof ParameterizedAffine && !(mt instanceof ParameterizedAffine)) {
        mt = ((ParameterizedAffine) parameterized).newTransform(mt);
    }
    return mt;
}
Also used : Matrix(org.opengis.referencing.operation.Matrix) MathTransform(org.opengis.referencing.operation.MathTransform) ParameterizedAffine(org.apache.sis.internal.referencing.j2d.ParameterizedAffine) VerticalOffset(org.apache.sis.internal.referencing.provider.VerticalOffset)

Aggregations

ParameterizedAffine (org.apache.sis.internal.referencing.j2d.ParameterizedAffine)1 VerticalOffset (org.apache.sis.internal.referencing.provider.VerticalOffset)1 MathTransform (org.opengis.referencing.operation.MathTransform)1 Matrix (org.opengis.referencing.operation.Matrix)1