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