This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit bc27996b5e9991ea35c58b10591224f2d3ab1daa Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri May 29 20:35:35 2020 +0200 Better determination of the inverse of an OperationMethod. --- .../internal/referencing/SignReversalComment.java | 2 +- .../referencing/provider/AbstractProvider.java | 15 ++++-- .../sis/internal/referencing/provider/Affine.java | 8 +-- .../provider/FranceGeocentricInterpolation.java | 6 +-- .../provider/GeocentricToGeographic.java | 8 +-- .../referencing/provider/GeodeticOperation.java | 8 +-- .../referencing/provider/Geographic2Dto3D.java | 8 +++ .../referencing/provider/Geographic3Dto2D.java | 22 ++++++++ .../provider/GeographicToGeocentric.java | 8 +-- .../org/apache/sis/referencing/Properties.java | 37 ++++++++----- .../operation/CoordinateOperationRegistry.java | 20 ++++++-- .../operation/InverseOperationMethod.java | 60 ++++++++++++---------- .../referencing/operation/SubOperationInfo.java | 5 +- 13 files changed, 133 insertions(+), 74 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java index 8f68a91..750b7be 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java @@ -32,7 +32,7 @@ import org.apache.sis.util.iso.AbstractInternationalString; * @author Martin Desruisseaux (Geomatys) * @version 0.7 * - * @see org.apache.sis.internal.referencing.provider.AbstractProvider#isInvertible() + * @see org.apache.sis.internal.referencing.provider.AbstractProvider#inverse() * * @since 0.7 * @module diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java index 6678ee3..86a3889 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java @@ -239,8 +239,13 @@ public abstract class AbstractProvider extends DefaultOperationMethod implements } /** - * Returns {@code true} if the inverse of this operation method is the same operation method with some parameter - * values changed (typically with sign inverted). The default implementation returns {@code false}. + * Returns the operation method which is the inverse of this method. + * <ul> + * <li>If {@code null}, no inverse method is easily available. This is the default.</li> + * <li>If {@code this}, the inverse of this operation method is the same operation method + * with some parameter values changed (typically with sign inverted).</li> + * <li>If another method, it should take the same parameter values.</li> + * </ul> * * <p>This is a SIS-specific information which may be changed in any future SIS version. * Current implementation provides this information in a "all or nothing" way: either all parameter values @@ -257,12 +262,12 @@ public abstract class AbstractProvider extends DefaultOperationMethod implements * does not differentiate the map projection methods from <em>inverse</em> map projection methods.</li> * </ul> * - * @return {@code true} if the inverse of this operation method can be described by the same operation method. + * @return the inverse of this operation method (possibly {@code this}), or {@code null} if none. * * @see org.apache.sis.internal.referencing.SignReversalComment */ - public boolean isInvertible() { - return false; + public AbstractProvider inverse() { + return null; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java index 6bd499a..348b637 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java @@ -57,7 +57,7 @@ import org.apache.sis.referencing.operation.transform.MathTransforms; * </table> * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.1 * @since 0.5 * @module */ @@ -180,11 +180,11 @@ public final class Affine extends AbstractProvider { /** * The inverse of this operation can be described by the same operation with different parameter values. * - * @return {@code true} for all {@code Affine}. + * @return {@code this} for all {@code Affine}. */ @Override - public final boolean isInvertible() { - return true; + public AbstractProvider inverse() { + return this; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java index 6596f2e..862570b 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java @@ -219,11 +219,11 @@ public class FranceGeocentricInterpolation extends GeodeticOperation { /** * The inverse of {@code FranceGeocentricInterpolation} is a different operation. * - * @return {@code false}. + * @return {@code null}. */ @Override - public final boolean isInvertible() { - return false; + public AbstractProvider inverse() { + return null; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java index 37cf1d2..dcb90c1 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java @@ -32,7 +32,7 @@ import org.apache.sis.parameter.Parameters; * This provider creates transforms from geocentric to geographic coordinate reference systems. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.1 * * @see GeographicToGeocentric * @@ -104,11 +104,11 @@ public final class GeocentricToGeographic extends GeodeticOperation { /** * Specifies that the inverse of this operation is a different kind of operation. * - * @return {@code false}. + * @return {@code null}. */ @Override - public boolean isInvertible() { - return false; + public AbstractProvider inverse() { + return null; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java index a6641d3..9367b3f 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java @@ -31,7 +31,7 @@ import org.opengis.referencing.operation.Transformation; * variants are specific to Apache SIS and can be fetched only by a call to {@link #redimension(int, int)}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.1 * @since 0.7 * @module */ @@ -127,10 +127,10 @@ abstract class GeodeticOperation extends AbstractProvider { /** * The inverse of {@code GeodeticOperation} is usually the same operation with parameter signs inverted. * - * @return {@code true} for most {@code GeodeticOperation} instances. + * @return {@code this} for most {@code GeodeticOperation} instances. */ @Override - public boolean isInvertible() { - return true; + public AbstractProvider inverse() { + return this; } } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java index 9083d76..0d01f25 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java @@ -100,6 +100,14 @@ public final class Geographic2Dto3D extends GeographicRedimension { } /** + * Returns the inverse of this operation. + */ + @Override + public AbstractProvider inverse() { + return Geographic3Dto2D.getMethod(Geographic3Dto2D.PARAMETERS); + } + + /** * Returns the transform. * * @param factory the factory for creating affine transforms. diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java index 880641f..71e8afc 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java @@ -83,6 +83,28 @@ public final class Geographic3Dto2D extends GeographicRedimension { } /** + * Returns the inverse of this operation. + */ + @Override + public AbstractProvider inverse() { + return getMethod(Geographic2Dto3D.PARAMETERS); + } + + /** + * Workaround while waiting for JDK 9. After migration to Jigsaw, {@link #inverse()} + * should return directly the unique provider instance. + */ + static AbstractProvider getMethod(final ParameterDescriptorGroup desc) { + try { + return (AbstractProvider) org.apache.sis.internal.system.DefaultFactories.forBuildin(MathTransformFactory.class, + org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.class) + .getOperationMethod(desc.getName().getCode()); + } catch (FactoryException e) { + throw new org.apache.sis.util.collection.BackingStoreException(e); + } + } + + /** * Returns the transform. * * <div class="note"><b>Implementation note:</b> diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java index 97c283e..c9b9bcc 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java @@ -41,7 +41,7 @@ import org.apache.sis.internal.util.Constants; * This provider creates transforms from geographic to geocentric coordinate reference systems. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.1 * * @see GeocentricToGeographic * @@ -165,11 +165,11 @@ public final class GeographicToGeocentric extends GeodeticOperation { /** * Specifies that the inverse of this operation is a different kind of operation. * - * @return {@code false}. + * @return {@code null}. */ @Override - public boolean isInvertible() { - return false; + public AbstractProvider inverse() { + return null; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java index 8a4b0af..6ad7f91 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java @@ -27,8 +27,10 @@ import org.opengis.referencing.ReferenceSystem; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.OperationMethod; +import org.opengis.referencing.operation.SingleOperation; import org.opengis.metadata.quality.PositionalAccuracy; import org.apache.sis.internal.util.AbstractMap; +import org.apache.sis.internal.referencing.CoordinateOperations; import org.apache.sis.util.Deprecable; @@ -40,8 +42,8 @@ import org.apache.sis.util.Deprecable; * <p>This map is read-only. Whether it is serializable, immutable or thread-safe depends if the * underlying {@code IdentifiedObject} instance is itself serializable, immutable or thread-safe.</p> * - * @author Martin Desruisseaux (IRD) - * @version 0.7 + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 1.1 * @since 0.4 * @module */ @@ -49,23 +51,24 @@ final class Properties extends AbstractMap<String,Object> implements Serializabl /** * For cross-version compatibility. */ - private static final long serialVersionUID = 6391635771714311314L; + private static final long serialVersionUID = 836068852472172370L; /** * The keys to search for. The index of each element in this array must matches the index searched by * {@link #getAt(int)}. In other words, this array performs the reverse mapping of {@link #INDICES}. */ private static final String[] KEYS = { - /*[0]*/ IdentifiedObject .NAME_KEY, - /*[1]*/ IdentifiedObject .IDENTIFIERS_KEY, - /*[2]*/ IdentifiedObject .ALIAS_KEY, - /*[3]*/ IdentifiedObject .REMARKS_KEY, - /*[4]*/ CoordinateOperation .SCOPE_KEY, // same in Datum and ReferenceSystem - /*[5]*/ CoordinateOperation .DOMAIN_OF_VALIDITY_KEY, // same in Datum and ReferenceSystem - /*[6]*/ CoordinateOperation .OPERATION_VERSION_KEY, - /*[7]*/ CoordinateOperation .COORDINATE_OPERATION_ACCURACY_KEY, - /*[8]*/ OperationMethod .FORMULA_KEY, - /*[9]*/ AbstractIdentifiedObject.DEPRECATED_KEY + /*[ 0]*/ IdentifiedObject .NAME_KEY, + /*[ 1]*/ IdentifiedObject .IDENTIFIERS_KEY, + /*[ 2]*/ IdentifiedObject .ALIAS_KEY, + /*[ 3]*/ IdentifiedObject .REMARKS_KEY, + /*[ 4]*/ CoordinateOperation .SCOPE_KEY, // same in Datum and ReferenceSystem + /*[ 5]*/ CoordinateOperation .DOMAIN_OF_VALIDITY_KEY, // same in Datum and ReferenceSystem + /*[ 6]*/ CoordinateOperation .OPERATION_VERSION_KEY, + /*[ 7]*/ CoordinateOperation .COORDINATE_OPERATION_ACCURACY_KEY, + /*[ 8]*/ OperationMethod .FORMULA_KEY, + /*[ 9]*/ CoordinateOperations .PARAMETERS_KEY, + /*[10]*/ AbstractIdentifiedObject.DEPRECATED_KEY /* * The current implementation does not look for minimum and maximum values in ParameterDescriptor @@ -191,7 +194,13 @@ final class Properties extends AbstractMap<String,Object> implements Serializabl } break; } - case 9: { // DEPRECATED_KEY + case 9: { // PARAMETERS_KEY + if (object instanceof SingleOperation) { + return ((SingleOperation) object).getParameterValues(); + } + break; + } + case 10: { // DEPRECATED_KEY if (object instanceof Deprecable) { return ((Deprecable) object).isDeprecated(); } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java index 7827710..5a0aadd 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java @@ -234,8 +234,7 @@ class CoordinateOperationRegistry { } else try { codeFinder = IdentifiedObjects.newFinder(Citations.toCodeSpace(registry.getAuthority())); } catch (NoSuchAuthorityFactoryException e) { - Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION), - CoordinateOperationRegistry.class, "<init>", e); + recoverableException("<init>", e); } if (codeFinder != null) { codeFinder.setIgnoringAxes(true); @@ -315,7 +314,7 @@ class CoordinateOperationRegistry { { CoordinateReferenceSystem source = sourceCRS; CoordinateReferenceSystem target = targetCRS; - for (int combine=0; ;combine++) { + for (int combine=0; ; combine++) { /* * First, try directly the provided (sourceCRS, targetCRS) pair. If that pair does not work, * try to use different combinations of user-provided CRS and two-dimensional components of @@ -575,7 +574,7 @@ class CoordinateOperationRegistry { final CoordinateReferenceSystem sourceCRS = op.getSourceCRS(); final CoordinateReferenceSystem targetCRS = op.getTargetCRS(); final MathTransform transform = op.getMathTransform().inverse(); - final OperationMethod method = InverseOperationMethod.create(op.getMethod()); + final OperationMethod method = InverseOperationMethod.create(op.getMethod(), factorySIS); final Map<String,Object> properties = properties(INVERSE_OPERATION); InverseOperationMethod.properties(op, properties); /* @@ -1195,4 +1194,17 @@ class CoordinateOperationRegistry { } Logging.log(CoordinateOperationFinder.class, "createOperations", record); } + + /** + * Logs an ignorable exception. This method pretends that the logging come from + * {@link CoordinateOperationFinder} since this is the public API which use this + * {@code CoordinateOperationRegistry} class. + * + * @param method the method name where the error occurred. + * @param exception the exception which occurred, or {@code null} if a {@code record} is specified instead. + */ + static void recoverableException(final String method, final Exception exception) { + Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION), + CoordinateOperationFinder.class, method, exception); + } } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java index fe59da1..8f937b6 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java @@ -24,6 +24,8 @@ import javax.measure.Unit; import org.opengis.metadata.Identifier; import org.opengis.metadata.quality.PositionalAccuracy; import org.opengis.util.InternationalString; +import org.opengis.util.FactoryException; +import org.opengis.util.NoSuchIdentifierException; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptor; @@ -44,7 +46,7 @@ import org.apache.sis.util.Deprecable; * for the inverse, or when the inverse operation can not be represented by inverting the sign of parameters. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.1 * @since 0.7 * @module */ @@ -69,41 +71,45 @@ final class InverseOperationMethod extends DefaultOperationMethod { } /** - * Returns {@code true} if the given method flags itself as invertible. - */ - private static boolean isInvertible(final OperationMethod method) { - return method instanceof AbstractProvider && ((AbstractProvider) method).isInvertible(); - } - - /** * Returns or create the inverse of the given operation method. If the same operation method can be used * for the inverse operation either with the exact same parameter values or with the sign of some values * reversed, then the given method is returned as-is. Otherwise a synthetic method is created. */ - static OperationMethod create(final OperationMethod method) { + static OperationMethod create(OperationMethod method, final DefaultCoordinateOperationFactory factorySIS) + throws FactoryException + { if (method instanceof InverseOperationMethod) { return ((InverseOperationMethod) method).inverse; } - if (!isInvertible(method)) { - boolean useSameParameters = false; - for (final GeneralParameterDescriptor descriptor : method.getParameters().descriptors()) { - useSameParameters = (descriptor.getRemarks() instanceof SignReversalComment); - if (!useSameParameters) break; - } - if (!useSameParameters) { - Identifier name = method.getName(); - name = new ImmutableIdentifier(null, null, "Inverse of " + name.getCode()); - final Map<String,Object> properties = new HashMap<>(6); - properties.put(NAME_KEY, name); - properties.put(FORMULA_KEY, method.getFormula()); - properties.put(REMARKS_KEY, method.getRemarks()); - if (method instanceof Deprecable) { - properties.put(DEPRECATED_KEY, ((Deprecable) method).isDeprecated()); - } - return new InverseOperationMethod(properties, method); + if (!(method instanceof AbstractProvider)) try { + method = factorySIS.getOperationMethod(method.getName().getCode()); + } catch (NoSuchIdentifierException e) { + CoordinateOperationRegistry.recoverableException("inverse", e); + } + if (method instanceof AbstractProvider) { + final AbstractProvider inverse = ((AbstractProvider) method).inverse(); + if (inverse != null) { + return inverse; } } - return method; + boolean useSameParameters = false; + for (final GeneralParameterDescriptor descriptor : method.getParameters().descriptors()) { + useSameParameters = (descriptor.getRemarks() instanceof SignReversalComment); + if (!useSameParameters) break; + } + if (useSameParameters) { + return method; + } + Identifier name = method.getName(); + name = new ImmutableIdentifier(null, null, "Inverse of " + name.getCode()); + final Map<String,Object> properties = new HashMap<>(6); + properties.put(NAME_KEY, name); + properties.put(FORMULA_KEY, method.getFormula()); + properties.put(REMARKS_KEY, method.getRemarks()); + if (method instanceof Deprecable) { + properties.put(DEPRECATED_KEY, ((Deprecable) method).isDeprecated()); + } + return new InverseOperationMethod(properties, method); } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java index 0b80fd8..8318030 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java @@ -22,8 +22,6 @@ import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.OperationNotFoundException; import org.opengis.referencing.operation.TransformException; import org.opengis.util.FactoryException; -import org.apache.sis.util.logging.Logging; -import org.apache.sis.internal.system.Loggers; import org.apache.sis.referencing.operation.matrix.Matrices; import org.apache.sis.referencing.operation.matrix.MatrixSIS; @@ -215,8 +213,7 @@ next: for (int targetComponentIndex = 0; targetComponentIndex < infos.length; operation, null, sourceStartAtDimension, sourceEndAtDimension); if (failure != null) { - Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION), - CoordinateOperationFinder.class, "decompose", failure); + CoordinateOperationRegistry.recoverableException("decompose", failure); } continue next; }
