Search in sources :

Example 6 with DefaultOperationMethod

use of org.apache.sis.referencing.operation.DefaultOperationMethod in project sis by apache.

the class CC_OperationMethod method group.

/**
 * Wraps the given descriptors in a descriptor group of the given name. If the given name can be matched
 * to the name of one of the predefined operation method, then the predefined parameters will be used.
 *
 * <p>We try to use predefined parameters if possible because they contain information, especially the
 * {@link org.opengis.parameter.ParameterDescriptor#getValueClass()} property, which are not available
 * in the GML document.</p>
 *
 * <div class="note"><b>Note:</b>
 * this code is defined in this {@code CC_OperationMethod} class instead than in the
 * {@link DefaultOperationMethod} class in the hope to reduce the amount of code processed
 * by the JVM in the common case where JAXB (un)marshalling is not needed.</div>
 *
 * @param  name         the operation method name, to be also given to the descriptor group.
 * @param  descriptors  the parameter descriptors to wrap in a group. This array will be modified in-place.
 * @return a parameter group containing at least the given descriptors, or equivalent descriptors.
 */
public static ParameterDescriptorGroup group(final Identifier name, final GeneralParameterDescriptor[] descriptors) {
    OperationMethod method;
    try {
        method = CoordinateOperations.factory().getOperationMethod(name.getCode());
    } catch (FactoryException e) {
        // Use DefaultOperationMethod as the source class because it is the first public class in callers.
        Context.warningOccured(Context.current(), DefaultOperationMethod.class, "setDescriptors", e, true);
        method = null;
    }
    final Map<String, ?> properties = Collections.singletonMap(ParameterDescriptorGroup.NAME_KEY, name);
    if (method != null) {
        /*
             * Verify that the pre-defined operation method contains at least all the parameters specified by
             * the 'descriptors' array. If this is the case, then the pre-defined parameters will be used in
             * replacement of the given ones.
             */
        final ParameterDescriptorGroup parameters = method.getParameters();
        return CC_GeneralOperationParameter.merge(DefaultOperationMethod.class, properties, IdentifiedObjects.getProperties(parameters), 1, 1, descriptors, parameters, true);
    }
    return new DefaultParameterDescriptorGroup(properties, 1, 1, descriptors);
}
Also used : DefaultParameterDescriptorGroup(org.apache.sis.parameter.DefaultParameterDescriptorGroup) FactoryException(org.opengis.util.FactoryException) ParameterDescriptorGroup(org.opengis.parameter.ParameterDescriptorGroup) DefaultParameterDescriptorGroup(org.apache.sis.parameter.DefaultParameterDescriptorGroup) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Example 7 with DefaultOperationMethod

use of org.apache.sis.referencing.operation.DefaultOperationMethod in project sis by apache.

the class ProvidersTest method testRedimension.

/**
 * Tests {@link AbstractProvider#redimension(int, int)} on all providers managed by {@link Providers}.
 */
@Test
public void testRedimension() {
    final Map<Class<?>, Boolean> redimensionables = new HashMap<>(100);
    for (final Class<?> type : methods()) {
        assertNull(type.getName(), redimensionables.put(type, Boolean.FALSE));
    }
    for (final Class<?> type : redimensionables()) {
        assertEquals(type.getName(), Boolean.FALSE, redimensionables.put(type, Boolean.TRUE));
    }
    final Providers providers = new Providers();
    for (final OperationMethod method : providers) {
        if (method instanceof ProviderMock) {
            // Skip the methods that were defined only for test purpose.
            continue;
        }
        final int sourceDimensions = method.getSourceDimensions();
        final int targetDimensions = method.getTargetDimensions();
        final Boolean isRedimensionable = redimensionables.get(method.getClass());
        assertNotNull(method.getClass().getName(), isRedimensionable);
        if (isRedimensionable) {
            for (int newSource = 2; newSource <= 3; newSource++) {
                for (int newTarget = 2; newTarget <= 3; newTarget++) {
                    final OperationMethod redim = ((DefaultOperationMethod) method).redimension(newSource, newTarget);
                    assertEquals("sourceDimensions", newSource, redim.getSourceDimensions().intValue());
                    assertEquals("targetDimensions", newTarget, redim.getTargetDimensions().intValue());
                    if (!(method instanceof Affine)) {
                        if (newSource == sourceDimensions && newTarget == targetDimensions) {
                            assertSame("When asking the original number of dimensions, expected the original instance.", method, redim);
                        } else {
                            assertNotSame("When asking a different number of dimensions, expected a different instance.", method, redim);
                        }
                        assertSame("When asking the original number of dimensions, expected the original instance.", method, ((DefaultOperationMethod) redim).redimension(sourceDimensions, targetDimensions));
                    }
                }
            }
        } else if (method instanceof MapProjection) {
            final OperationMethod proj3D = ((MapProjection) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1);
            assertNotSame("redimension(3,3) should return a new method.", method, proj3D);
            assertSame("redimension(2,2) should give back the original method.", method, ((DefaultOperationMethod) proj3D).redimension(sourceDimensions, targetDimensions));
            assertSame("Value of redimension(3,3) should have been cached.", proj3D, ((MapProjection) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1));
        } else
            try {
                ((DefaultOperationMethod) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1);
                fail("Type " + method.getClass().getName() + " is not in our list of redimensionable methods.");
            } catch (IllegalArgumentException e) {
                final String message = e.getMessage();
                assertTrue(message, message.contains(method.getName().getCode()));
            }
    }
}
Also used : IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) Test(org.junit.Test)

Example 8 with DefaultOperationMethod

use of org.apache.sis.referencing.operation.DefaultOperationMethod in project sis by apache.

the class DefaultMathTransformFactory method createParameterizedTransform.

/**
 * Creates a transform from a group of parameters.
 * The set of expected parameters varies for each operation.
 * The easiest way to provide parameter values is to get an initially empty group for the desired
 * operation by calling {@link #getDefaultParameters(String)}, then to fill the parameter values.
 * Example:
 *
 * {@preformat java
 *     ParameterValueGroup group = factory.getDefaultParameters("Transverse_Mercator");
 *     group.parameter("semi_major").setValue(6378137.000);
 *     group.parameter("semi_minor").setValue(6356752.314);
 *     MathTransform mt = factory.createParameterizedTransform(group, null);
 * }
 *
 * Sometime the {@code "semi_major"} and {@code "semi_minor"} parameter values are not explicitly provided,
 * but rather inferred from the {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic
 * datum} of the source Coordinate Reference System. If the given {@code context} argument is non-null,
 * then this method will use those contextual information for:
 *
 * <ol>
 *   <li>Inferring the {@code "semi_major"}, {@code "semi_minor"}, {@code "src_semi_major"},
 *       {@code "src_semi_minor"}, {@code "tgt_semi_major"} or {@code "tgt_semi_minor"} parameters values
 *       from the {@linkplain org.apache.sis.referencing.datum.DefaultEllipsoid ellipsoids} associated to
 *       the source or target CRS, if those parameters are not explicitly given and if they are relevant
 *       for the coordinate operation method.</li>
 *   <li>{@linkplain #createConcatenatedTransform Concatenating} the parameterized transform
 *       with any other transforms required for performing units changes and ordinates swapping.</li>
 * </ol>
 *
 * The complete group of parameters, including {@code "semi_major"}, {@code "semi_minor"} or other calculated values,
 * can be obtained by a call to {@link Context#getCompletedParameters()} after {@code createParameterizedTransform(…)}
 * returned. Note that the completed parameters may only have additional parameters compared to the given parameter
 * group; existing parameter values should not be modified.
 *
 * <p>The {@code OperationMethod} instance used by this constructor can be obtained by a call to
 * {@link #getLastMethodUsed()}.</p>
 *
 * @param  parameters  the parameter values. The {@linkplain ParameterDescriptorGroup#getName() parameter group name}
 *                     shall be the name of the desired {@linkplain DefaultOperationMethod operation method}.
 * @param  context     information about the context (for example source and target coordinate systems)
 *                     in which the new transform is going to be used, or {@code null} if none.
 * @return the transform created from the given parameters.
 * @throws NoSuchIdentifierException if there is no method for the given parameter group name.
 * @throws FactoryException if the object creation failed. This exception is thrown
 *         if some required parameter has not been supplied, or has illegal value.
 *
 * @see #getDefaultParameters(String)
 * @see #getAvailableMethods(Class)
 * @see #getLastMethodUsed()
 * @see org.apache.sis.parameter.ParameterBuilder#createGroupForMapProjection(ParameterDescriptor...)
 */
public MathTransform createParameterizedTransform(ParameterValueGroup parameters, final Context context) throws NoSuchIdentifierException, FactoryException {
    OperationMethod method = null;
    RuntimeException failure = null;
    MathTransform transform;
    try {
        ArgumentChecks.ensureNonNull("parameters", parameters);
        final ParameterDescriptorGroup descriptor = parameters.getDescriptor();
        final String methodName = descriptor.getName().getCode();
        String methodIdentifier = IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(descriptor, Citations.EPSG));
        if (methodIdentifier == null) {
            methodIdentifier = methodName;
        }
        /*
             * Get the MathTransformProvider of the same name or identifier than the given parameter group.
             * We give precedence to EPSG identifier because operation method names are sometime ambiguous
             * (e.g. "Lambert Azimuthal Equal Area (Spherical)"). If we fail to find the method by its EPSG code,
             * we will try searching by method name. As a side effect, this second attempt will produce a better
             * error message if the method is really not found.
             */
        try {
            method = getOperationMethod(methodIdentifier);
        } catch (NoSuchIdentifierException exception) {
            if (methodIdentifier.equals(methodName)) {
                throw exception;
            }
            method = getOperationMethod(methodName);
            Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION), DefaultMathTransformFactory.class, "createParameterizedTransform", exception);
        }
        if (!(method instanceof MathTransformProvider)) {
            throw new NoSuchIdentifierException(// For now, handle like an unknown operation.
            Errors.format(Errors.Keys.UnsupportedImplementation_1, Classes.getClass(method)), methodName);
        }
        /*
             * Will catch only exceptions that may be the result of improper parameter usage (e.g. a value out
             * of range). Do not catch exceptions caused by programming errors (e.g. null pointer exception).
             */
        try {
            /*
                 * If the user's parameters do not contain semi-major and semi-minor axis lengths, infer
                 * them from the ellipsoid. We have to do that because those parameters are often omitted,
                 * since the standard place where to provide this information is in the ellipsoid object.
                 */
            if (context != null) {
                failure = context.completeParameters(this, method, parameters);
                parameters = context.parameters;
                method = context.provider;
            }
            transform = ((MathTransformProvider) method).createMathTransform(this, parameters);
        } catch (IllegalArgumentException | IllegalStateException exception) {
            throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception);
        }
        /*
             * Cache the transform that we just created and make sure that the number of dimensions
             * is compatible with the OperationMethod instance. Then make final adjustment for axis
             * directions and units of measurement.
             */
        transform = unique(transform);
        method = DefaultOperationMethod.redimension(method, transform.getSourceDimensions(), transform.getTargetDimensions());
        if (context != null) {
            transform = swapAndScaleAxes(transform, context);
        }
    } catch (FactoryException e) {
        if (failure != null) {
            e.addSuppressed(failure);
        }
        throw e;
    } finally {
        // May be null in case of failure, which is intended.
        lastMethod.set(method);
        if (context != null) {
            context.provider = null;
        /*
                 * For now we conservatively reset the provider information to null. But if we choose to
                 * make that information public in a future SIS version, then we would remove this code.
                 */
        }
    }
    return transform;
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) FactoryException(org.opengis.util.FactoryException) ParameterDescriptorGroup(org.opengis.parameter.ParameterDescriptorGroup) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod) InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException) NoSuchIdentifierException(org.opengis.util.NoSuchIdentifierException)

Aggregations

DefaultOperationMethod (org.apache.sis.referencing.operation.DefaultOperationMethod)8 OperationMethod (org.opengis.referencing.operation.OperationMethod)5 DefaultParameterDescriptorGroup (org.apache.sis.parameter.DefaultParameterDescriptorGroup)3 ParameterDescriptorGroup (org.opengis.parameter.ParameterDescriptorGroup)3 ResultSet (java.sql.ResultSet)2 SQLException (java.sql.SQLException)2 AbstractIdentifiedObject (org.apache.sis.referencing.AbstractIdentifiedObject)2 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)2 Test (org.junit.Test)2 IdentifiedObject (org.opengis.referencing.IdentifiedObject)2 FactoryException (org.opengis.util.FactoryException)2 InternationalString (org.opengis.util.InternationalString)2 NoSuchIdentifierException (org.opengis.util.NoSuchIdentifierException)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 ReferencingServices (org.apache.sis.internal.metadata.ReferencingServices)1 DeferredCoordinateOperation (org.apache.sis.internal.referencing.DeferredCoordinateOperation)1 DefaultParameterDescriptor (org.apache.sis.parameter.DefaultParameterDescriptor)1 InvalidGeodeticParameterException (org.apache.sis.referencing.factory.InvalidGeodeticParameterException)1